bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr) { if (callback>=CB_MAX) return false; switch (type) { case CB_RETF: phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFE); //GRP 4 phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction phys_writew(CB_BASE+(callback<<4)+2,callback); //The immediate word phys_writeb(CB_BASE+(callback<<4)+4,(Bit8u)0xCB); //A RETF Instruction break; case CB_IRET: phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFE); //GRP 4 phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction phys_writew(CB_BASE+(callback<<4)+2,callback); //The immediate word phys_writeb(CB_BASE+(callback<<4)+4,(Bit8u)0xCF); //An IRET Instruction break; case CB_IRET_STI: phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFB); //STI phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0xFE); //GRP 4 phys_writeb(CB_BASE+(callback<<4)+2,(Bit8u)0x38); //Extra Callback instruction phys_writew(CB_BASE+(callback<<4)+3,callback); //The immediate word phys_writeb(CB_BASE+(callback<<4)+5,(Bit8u)0xCF); //An IRET Instruction break; default: E_Exit("CALLBACK:Setup:Illegal type %d",type); } CallBack_Handlers[callback]=handler; CALLBACK_SetDescription(callback,descr); return true; }
void updateDPT(void) { Bit32u tmpheads, tmpcyl, tmpsect, tmpsize; if(imageDiskList[2] != NULL) { PhysPt dp0physaddr=CALLBACK_PhysPointer(diskparm0); imageDiskList[2]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); phys_writew(dp0physaddr,(Bit16u)tmpcyl); phys_writeb(dp0physaddr+0x2,(Bit8u)tmpheads); phys_writew(dp0physaddr+0x3,0); phys_writew(dp0physaddr+0x5,(Bit16u)-1); phys_writeb(dp0physaddr+0x7,0); phys_writeb(dp0physaddr+0x8,(0xc0 | (((imageDiskList[2]->heads) > 8) << 3))); phys_writeb(dp0physaddr+0x9,0); phys_writeb(dp0physaddr+0xa,0); phys_writeb(dp0physaddr+0xb,0); phys_writew(dp0physaddr+0xc,(Bit16u)tmpcyl); phys_writeb(dp0physaddr+0xe,(Bit8u)tmpsect); } if(imageDiskList[3] != NULL) { PhysPt dp1physaddr=CALLBACK_PhysPointer(diskparm1); imageDiskList[3]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); phys_writew(dp1physaddr,(Bit16u)tmpcyl); phys_writeb(dp1physaddr+0x2,(Bit8u)tmpheads); phys_writeb(dp1physaddr+0xe,(Bit8u)tmpsect); } }
Bit16u INT10_SetupVideoParameterTable(PhysPt basepos) { if (IS_VGA_ARCH) { for (Bitu i=0;i<0x40*0x1d;i++) { phys_writeb(basepos+i,video_parameter_table_vga[i]); } return 0x40*0x1d; } else { for (Bitu i=0;i<0x40*0x17;i++) { phys_writeb(basepos+i,video_parameter_table_ega[i]); } return 0x40*0x17; } }
void CreateMouseCallback(void) { // Create callback call_int33=CALLBACK_Allocate(); CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET,"Mouse"); // Create a mouse vector with weird address // for strange mouse detection routines in Sim City & Wasteland Bit16u ofs = call_int33<<4; phys_writeb(CB_BASE+ofs+0,(Bit8u)0x90); //NOP phys_writeb(CB_BASE+ofs+1,(Bit8u)0xFE); //GRP 4 phys_writeb(CB_BASE+ofs+2,(Bit8u)0x38); //Extra Callback instruction phys_writew(CB_BASE+ofs+3,call_int33); //The immediate word phys_writeb(CB_BASE+ofs+5,(Bit8u)0xCF); //An IRET Instruction // Write weird vector WriteMouseIntVector(); };
void INT10_SetupVESA(void) { /* Put the mode list somewhere in memory */ Bitu i; i=0; int10.rom.vesa_modes=RealMake(0xc000,int10.rom.used); //TODO Maybe add normal vga modes too, but only seems to complicate things while (ModeList_VGA[i].mode!=0xffff) { bool canuse_mode=false; if (!svga.accepts_mode) canuse_mode=true; else { if (svga.accepts_mode(ModeList_VGA[i].mode)) canuse_mode=true; } if (ModeList_VGA[i].mode>=0x100 && canuse_mode) { if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) { phys_writew(PhysMake(0xc000,int10.rom.used),ModeList_VGA[i].mode); int10.rom.used+=2; } } i++; } phys_writew(PhysMake(0xc000,int10.rom.used),0xffff); int10.rom.used+=2; int10.rom.oemstring=RealMake(0xc000,int10.rom.used); Bitu len=(Bitu)(strlen(string_oem)+1); for (i=0;i<len;i++) { phys_writeb(0xc0000+int10.rom.used++,string_oem[i]); } switch (svgaCard) { case SVGA_S3Trio: break; } callback.setwindow=CALLBACK_Allocate(); callback.pmPalette=CALLBACK_Allocate(); callback.pmStart=CALLBACK_Allocate(); CALLBACK_Setup(callback.setwindow,VESA_SetWindow,CB_RETF, "VESA Real Set Window"); /* Prepare the pmode interface */ int10.rom.pmode_interface=RealMake(0xc000,int10.rom.used); int10.rom.used += 8; //Skip the byte later used for offsets /* PM Set Window call */ int10.rom.pmode_interface_window = int10.rom.used - RealOff( int10.rom.pmode_interface ); phys_writew( Real2Phys(int10.rom.pmode_interface) + 0, int10.rom.pmode_interface_window ); callback.pmWindow=CALLBACK_Allocate(); int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmWindow, VESA_PMSetWindow, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Window"); /* PM Set start call */ int10.rom.pmode_interface_start = int10.rom.used - RealOff( int10.rom.pmode_interface ); phys_writew( Real2Phys(int10.rom.pmode_interface) + 2, int10.rom.pmode_interface_start); callback.pmStart=CALLBACK_Allocate(); int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmStart, VESA_PMSetStart, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Start"); /* PM Set Palette call */ int10.rom.pmode_interface_palette = int10.rom.used - RealOff( int10.rom.pmode_interface ); phys_writew( Real2Phys(int10.rom.pmode_interface) + 4, int10.rom.pmode_interface_palette); callback.pmPalette=CALLBACK_Allocate(); int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmPalette, VESA_PMSetPalette, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Palette"); /* Finalize the size and clear the required ports pointer */ phys_writew( Real2Phys(int10.rom.pmode_interface) + 6, 0); int10.rom.pmode_interface_size=int10.rom.used - RealOff( int10.rom.pmode_interface ); }
/* write a block into physical memory */ static void DMA_BlockWrite(PhysPt pt,void * data,Bitu size) { Bit8u * read=(Bit8u *) data; for ( ; size ; size--, pt++) { Bitu page = pt >> 12; /* care for EMS pageframe etc. */ if (page < EMM_PAGEFRAME4K) page = paging.firstmb[page]; else if (page < EMM_PAGEFRAME4K+0x10) page = ems_board_mapping[page]; else if (page < LINK_START) page = paging.firstmb[page]; phys_writeb(page*4096 + (pt & 4095), *read++); } }
void INT10_SetupBasicVideoParameterTable(void) { /* video parameter table at F000:F0A4 */ RealSetVec(0x1d,RealMake(0xF000, 0xF0A4)); switch (machine) { case MCH_TANDY: for (Bit16u i = 0; i < sizeof(vparams_tandy); i++) { phys_writeb(0xFF0A4+i,vparams_tandy[i]); } break; case MCH_PCJR: for (Bit16u i = 0; i < sizeof(vparams_pcjr); i++) { phys_writeb(0xFF0A4+i,vparams_pcjr[i]); } break; default: for (Bit16u i = 0; i < sizeof(vparams); i++) { phys_writeb(0xFF0A4+i,vparams[i]); } break; } }
void SVGA_Setup_ParadisePVGA1A(void) { svga.write_p3cf = &write_p3cf_pvga1a; svga.read_p3cf = &read_p3cf_pvga1a; svga.set_video_mode = &FinishSetMode_PVGA1A; svga.determine_mode = &DetermineMode_PVGA1A; svga.set_clock = &SetClock_PVGA1A; svga.get_clock = &GetClock_PVGA1A; svga.accepts_mode = &AcceptsMode_PVGA1A; VGA_SetClock(0,CLK_25); VGA_SetClock(1,CLK_28); VGA_SetClock(2,32400); // could not find documentation VGA_SetClock(3,35900); // Adjust memory, default to 512K if (vga.vmemsize == 0) vga.vmemsize = 512*1024; if (vga.vmemsize < 512*1024) { vga.vmemsize = 256*1024; pvga1a.PR1 = 1<<6; } else if (vga.vmemsize > 512*1024) { vga.vmemsize = 1024*1024; pvga1a.PR1 = 3<<6; } else { pvga1a.PR1 = 2<<6; } // Paradise ROM signature PhysPt rom_base=PhysMake(0xc000,0); phys_writeb(rom_base+0x007d,'V'); phys_writeb(rom_base+0x007e,'G'); phys_writeb(rom_base+0x007f,'A'); phys_writeb(rom_base+0x0080,'='); IO_Write(0x3cf, 0x05); // Enable! }
void INT10_SetupBasicVideoParameterTable(void) { const unsigned char *copy = NULL; size_t copy_sz = 0; Bitu ofs; switch (machine) { case MCH_TANDY: copy = vparams_tandy; copy_sz = sizeof(vparams_tandy); break; case MCH_PCJR: copy = vparams_pcjr; copy_sz = sizeof(vparams_pcjr); break; default: copy = vparams; copy_sz = sizeof(vparams); break; } if (BIOS_VIDEO_TABLE_LOCATION == ~0 || BIOS_VIDEO_TABLE_SIZE != (Bitu)copy_sz) { if (rom_bios_vptable_enable) { /* TODO: Free previous block */ BIOS_VIDEO_TABLE_SIZE = copy_sz; if (mainline_compatible_bios_mapping) BIOS_VIDEO_TABLE_LOCATION = RealMake(0xf000,0xf0a4); else BIOS_VIDEO_TABLE_LOCATION = PhysToReal416(ROMBIOS_GetMemory(copy_sz,"BIOS video table (INT 1Dh)")); /* TODO: make option */ /* NTS: Failure to allocate means BIOS_VIDEO_TABLE_LOCATION == 0 */ } else { BIOS_VIDEO_TABLE_LOCATION = 0; } } RealSetVec(0x1d,BIOS_VIDEO_TABLE_LOCATION); ofs = RealToPhys(BIOS_VIDEO_TABLE_LOCATION); if (ofs != 0) { if (copy && copy_sz <= BIOS_VIDEO_TABLE_SIZE) { for (size_t i=0;i < copy_sz;i++) phys_writeb(ofs+i,copy[i]); } else { E_Exit("Somehow, INT 10 video param table too large"); } } }
void CALLBACK_Init(Section* /*sec*/) { Bitu i; for (i=0;i<CB_MAX;i++) { CallBack_Handlers[i]=&illegal_handler; } /* Setup the Stop Handler */ call_stop=CALLBACK_Allocate(); CallBack_Handlers[call_stop]=stop_handler; CALLBACK_SetDescription(call_stop,"stop"); phys_writeb(CALLBACK_PhysPointer(call_stop)+0,0xFE); phys_writeb(CALLBACK_PhysPointer(call_stop)+1,0x38); phys_writew(CALLBACK_PhysPointer(call_stop)+2,(Bit16u)call_stop); /* Setup the idle handler */ call_idle=CALLBACK_Allocate(); CallBack_Handlers[call_idle]=stop_handler; CALLBACK_SetDescription(call_idle,"idle"); for (i=0;i<=11;i++) phys_writeb(CALLBACK_PhysPointer(call_idle)+i,0x90); phys_writeb(CALLBACK_PhysPointer(call_idle)+12,0xFE); phys_writeb(CALLBACK_PhysPointer(call_idle)+13,0x38); phys_writew(CALLBACK_PhysPointer(call_idle)+14,(Bit16u)call_idle); /* Default handlers for unhandled interrupts that have to be non-null */ call_default=CALLBACK_Allocate(); CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default"); call_default2=CALLBACK_Allocate(); CALLBACK_Setup(call_default2,&default_handler,CB_IRET,"default"); /* Only setup default handler for first part of interrupt table */ for (Bit16u ct=0;ct<0x60;ct++) { real_writed(0,ct*4,CALLBACK_RealPointer(call_default)); } for (Bit16u ct=0x68;ct<0x70;ct++) { real_writed(0,ct*4,CALLBACK_RealPointer(call_default)); } /* Setup block of 0xCD 0xxx instructions */ PhysPt rint_base=CALLBACK_GetBase()+CB_MAX*CB_SIZE; for (i=0;i<=0xff;i++) { phys_writeb(rint_base,0xCD); phys_writeb(rint_base+1,(Bit8u)i); phys_writeb(rint_base+2,0xFE); phys_writeb(rint_base+3,0x38); phys_writew(rint_base+4,(Bit16u)call_stop); rint_base+=6; } // setup a few interrupt handlers that point to bios IRETs by default real_writed(0,0x0e*4,CALLBACK_RealPointer(call_default2)); //design your own railroad real_writed(0,0x66*4,CALLBACK_RealPointer(call_default)); //war2d real_writed(0,0x67*4,CALLBACK_RealPointer(call_default)); real_writed(0,0x68*4,CALLBACK_RealPointer(call_default)); real_writed(0,0x5c*4,CALLBACK_RealPointer(call_default)); //Network stuff //real_writed(0,0xf*4,0); some games don't like it call_priv_io=CALLBACK_Allocate(); // virtualizable in-out opcodes phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x00,(Bit8u)0xec); // in al, dx phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x01,(Bit8u)0xcb); // retf phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x02,(Bit8u)0xed); // in ax, dx phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x03,(Bit8u)0xcb); // retf phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x04,(Bit8u)0x66); // in eax, dx phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x05,(Bit8u)0xed); phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x06,(Bit8u)0xcb); // retf phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x08,(Bit8u)0xee); // out dx, al phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x09,(Bit8u)0xcb); // retf phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0a,(Bit8u)0xef); // out dx, ax phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0b,(Bit8u)0xcb); // retf phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0c,(Bit8u)0x66); // out dx, eax phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0d,(Bit8u)0xef); phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0e,(Bit8u)0xcb); // retf }
void CALLBACK_RemoveSetup(Bitu callback) { for (Bitu i = 0;i < CB_SIZE;i++) { phys_writeb(CALLBACK_PhysPointer(callback)+i ,(Bit8u) 0x00); } }
Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_cb=true) { if (callback>=CB_MAX) return 0; switch (type) { case CB_RETN: if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0xC3); //A RETN Instruction return (use_cb?5:1); case CB_RETF: if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0xCB); //A RETF Instruction return (use_cb?5:1); case CB_RETF8: if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0xCA); //A RETF 8 Instruction phys_writew(physAddress+0x01,(Bit16u)0x0008); return (use_cb?7:3); case CB_IRET: if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0xCF); //An IRET Instruction return (use_cb?5:1); case CB_IRETD: if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0x66); //An IRETD Instruction phys_writeb(physAddress+0x01,(Bit8u)0xCF); return (use_cb?6:2); case CB_IRET_STI: phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI if (use_cb) { phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction return (use_cb?6:2); case CB_IRET_EOI_PIC1: if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax phys_writeb(physAddress+0x01,(Bit8u)0xb0); // mov al, 0x20 phys_writeb(physAddress+0x02,(Bit8u)0x20); phys_writeb(physAddress+0x03,(Bit8u)0xe6); // out 0x20, al phys_writeb(physAddress+0x04,(Bit8u)0x20); phys_writeb(physAddress+0x05,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x06,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x0b:0x07); case CB_IRQ0: // timer int8 phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI if (use_cb) { phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x01,(Bit8u)0x1e); // push ds phys_writeb(physAddress+0x02,(Bit8u)0x50); // push ax phys_writeb(physAddress+0x03,(Bit8u)0x52); // push dx phys_writew(physAddress+0x04,(Bit16u)0x1ccd); // int 1c phys_writeb(physAddress+0x06,(Bit8u)0xfa); // cli phys_writew(physAddress+0x07,(Bit16u)0x20b0); // mov al, 0x20 phys_writew(physAddress+0x09,(Bit16u)0x20e6); // out 0x20, al phys_writeb(physAddress+0x0b,(Bit8u)0x5a); // pop dx phys_writeb(physAddress+0x0c,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x0d,(Bit8u)0x1f); // pop ds phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x13:0x0f); case CB_IRQ1: // keyboard int9 phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax phys_writew(physAddress+0x01,(Bit16u)0x60e4); // in al, 0x60 phys_writew(physAddress+0x03,(Bit16u)0x4fb4); // mov ah, 0x4f phys_writeb(physAddress+0x05,(Bit8u)0xf9); // stc phys_writew(physAddress+0x06,(Bit16u)0x15cd); // int 15 if (use_cb) { phys_writew(physAddress+0x08,(Bit16u)0x0473); // jc skip phys_writeb(physAddress+0x0a,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x0b,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x0c,(Bit16u)callback); //The immediate word // jump here to (skip): physAddress+=6; } phys_writeb(physAddress+0x08,(Bit8u)0xfa); // cli phys_writew(physAddress+0x09,(Bit16u)0x20b0); // mov al, 0x20 phys_writew(physAddress+0x0b,(Bit16u)0x20e6); // out 0x20, al phys_writeb(physAddress+0x0d,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x15:0x0f); case CB_IRQ9: // pic cascade interrupt if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax phys_writew(physAddress+0x01,(Bit16u)0x61b0); // mov al, 0x61 phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al phys_writew(physAddress+0x05,(Bit16u)0x0acd); // int a phys_writeb(physAddress+0x07,(Bit8u)0xfa); // cli phys_writeb(physAddress+0x08,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x09,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x0e:0x0a); case CB_IRQ12: // ps2 mouse int74 if (!use_cb) E_Exit("int74 callback must implement a callback handler!"); phys_writeb(physAddress+0x00,(Bit8u)0x1e); // push ds phys_writeb(physAddress+0x01,(Bit8u)0x06); // push es phys_writew(physAddress+0x02,(Bit16u)0x6066); // pushad phys_writeb(physAddress+0x04,(Bit8u)0xfc); // cld phys_writeb(physAddress+0x05,(Bit8u)0xfb); // sti phys_writeb(physAddress+0x06,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x07,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x08,(Bit16u)callback); //The immediate word return 0x0a; case CB_IRQ12_RET: // ps2 mouse int74 return if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0xfa); // cli phys_writew(physAddress+0x01,(Bit16u)0x20b0); // mov al, 0x20 phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al phys_writew(physAddress+0x05,(Bit16u)0x20e6); // out 0x20, al phys_writew(physAddress+0x07,(Bit16u)0x6166); // popad phys_writeb(physAddress+0x09,(Bit8u)0x07); // pop es phys_writeb(physAddress+0x0a,(Bit8u)0x1f); // pop ds phys_writeb(physAddress+0x0b,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x10:0x0c); case CB_IRQ6_PCJR: // pcjr keyboard interrupt phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax phys_writew(physAddress+0x01,(Bit16u)0x60e4); // in al, 0x60 phys_writew(physAddress+0x03,(Bit16u)0xe03c); // cmp al, 0xe0 if (use_cb) { phys_writew(physAddress+0x05,(Bit16u)0x0674); // je skip phys_writeb(physAddress+0x07,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x08,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x09,(Bit16u)callback); //The immediate word physAddress+=4; } else { phys_writew(physAddress+0x05,(Bit16u)0x0274); // je skip } phys_writew(physAddress+0x07,(Bit16u)0x09cd); // int 9 // jump here to (skip): phys_writeb(physAddress+0x09,(Bit8u)0xfa); // cli phys_writew(physAddress+0x0a,(Bit16u)0x20b0); // mov al, 0x20 phys_writew(physAddress+0x0c,(Bit16u)0x20e6); // out 0x20, al phys_writeb(physAddress+0x0e,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x0f,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x14:0x10); case CB_MOUSE: phys_writew(physAddress+0x00,(Bit16u)0x07eb); // jmp i33hd physAddress+=9; // jump here to (i33hd): if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0xCF); //An IRET Instruction return (use_cb?0x0e:0x0a); case CB_INT16: phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI if (use_cb) { phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction for (Bitu i=0;i<=0x0b;i++) phys_writeb(physAddress+0x02+i,0x90); phys_writew(physAddress+0x0e,(Bit16u)0xedeb); //jmp callback return (use_cb?0x10:0x0c); case CB_INT29: // fast console output if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax phys_writeb(physAddress+0x01,(Bit8u)0x53); // push bx phys_writew(physAddress+0x02,(Bit16u)0x0eb4); // mov ah, 0x0e phys_writeb(physAddress+0x04,(Bit8u)0xbb); // mov bx, phys_writew(physAddress+0x05,(Bit16u)0x0007); // 0x0007 phys_writew(physAddress+0x07,(Bit16u)0x10cd); // int 10 phys_writeb(physAddress+0x09,(Bit8u)0x5b); // pop bx phys_writeb(physAddress+0x0a,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x0b,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x10:0x0c); case CB_HOOKABLE: phys_writeb(physAddress+0x00,(Bit8u)0xEB); //jump near phys_writeb(physAddress+0x01,(Bit8u)0x03); //offset phys_writeb(physAddress+0x02,(Bit8u)0x90); //NOP phys_writeb(physAddress+0x03,(Bit8u)0x90); //NOP phys_writeb(physAddress+0x04,(Bit8u)0x90); //NOP if (use_cb) { phys_writeb(physAddress+0x05,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x06,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x07,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x05,(Bit8u)0xCB); //A RETF Instruction return (use_cb?0x0a:0x06); case CB_TDE_IRET: // TandyDAC end transfer if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax phys_writeb(physAddress+0x01,(Bit8u)0xb8); // mov ax, 0x91fb phys_writew(physAddress+0x02,(Bit16u)0x91fb); phys_writew(physAddress+0x04,(Bit16u)0x15cd); // int 15 phys_writeb(physAddress+0x06,(Bit8u)0xfa); // cli phys_writew(physAddress+0x07,(Bit16u)0x20b0); // mov al, 0x20 phys_writew(physAddress+0x09,(Bit16u)0x20e6); // out 0x20, al phys_writeb(physAddress+0x0b,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x0c,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x11:0x0d); /* case CB_IPXESR: // IPX ESR if (!use_cb) E_Exit("ipx esr must implement a callback handler!"); phys_writeb(physAddress+0x00,(Bit8u)0x1e); // push ds phys_writeb(physAddress+0x01,(Bit8u)0x06); // push es phys_writew(physAddress+0x02,(Bit16u)0xa00f); // push fs phys_writew(physAddress+0x04,(Bit16u)0xa80f); // push gs phys_writeb(physAddress+0x06,(Bit8u)0x60); // pusha phys_writeb(physAddress+0x07,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x08,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x09,(Bit16u)callback); //The immediate word phys_writeb(physAddress+0x0b,(Bit8u)0xCB); //A RETF Instruction return 0x0c; case CB_IPXESR_RET: // IPX ESR return if (use_cb) E_Exit("ipx esr return must not implement a callback handler!"); phys_writeb(physAddress+0x00,(Bit8u)0xfa); // cli phys_writew(physAddress+0x01,(Bit16u)0x20b0); // mov al, 0x20 phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al phys_writew(physAddress+0x05,(Bit16u)0x20e6); // out 0x20, al phys_writeb(physAddress+0x07,(Bit8u)0x61); // popa phys_writew(physAddress+0x08,(Bit16u)0xA90F); // pop gs phys_writew(physAddress+0x0a,(Bit16u)0xA10F); // pop fs phys_writeb(physAddress+0x0c,(Bit8u)0x07); // pop es phys_writeb(physAddress+0x0d,(Bit8u)0x1f); // pop ds phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction return 0x0f; */ case CB_INT21: phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI if (use_cb) { phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction phys_writeb(physAddress+0x02,(Bit8u)0xCB); //A RETF Instruction phys_writeb(physAddress+0x03,(Bit8u)0x51); // push cx phys_writeb(physAddress+0x04,(Bit8u)0xB9); // mov cx, phys_writew(physAddress+0x05,(Bit16u)0x0140); // 0x140 phys_writew(physAddress+0x07,(Bit16u)0xFEE2); // loop $-2 phys_writeb(physAddress+0x09,(Bit8u)0x59); // pop cx phys_writeb(physAddress+0x0A,(Bit8u)0xCF); //An IRET Instruction return (use_cb?15:11); case CB_INT13: phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI if (use_cb) { phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word physAddress+=4; } phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction phys_writew(physAddress+0x02,(Bit16u)0x0ECD); // int 0e phys_writeb(physAddress+0x04,(Bit8u)0xCF); //An IRET Instruction return (use_cb?9:5); default: E_Exit("CALLBACK:Setup:Illegal type %d",type); } return 0; }
void CALLBACK_Init(Section* sec) { Bitu i; for (i=0;i<CB_MAX;i++) { CallBack_Handlers[i]=&illegal_handler; } /* Setup the Stop Handler */ call_stop=CALLBACK_Allocate(); CallBack_Handlers[call_stop]=stop_handler; CALLBACK_SetDescription(call_stop,"stop"); phys_writeb(CB_BASE+(call_stop<<4)+0,0xFE); phys_writeb(CB_BASE+(call_stop<<4)+1,0x38); phys_writew(CB_BASE+(call_stop<<4)+2,call_stop); /* Setup the idle handler */ call_idle=CALLBACK_Allocate(); CallBack_Handlers[call_idle]=stop_handler; CALLBACK_SetDescription(call_idle,"idle"); for (i=0;i<=11;i++) phys_writeb(CB_BASE+(call_idle<<4)+i,0x90); phys_writeb(CB_BASE+(call_idle<<4)+12,0xFE); phys_writeb(CB_BASE+(call_idle<<4)+13,0x38); phys_writew(CB_BASE+(call_idle<<4)+14,call_idle); /* Setup all Interrupt to point to the default handler */ call_default=CALLBACK_Allocate(); CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default"); /* Only setup default handler for first half of interrupt table */ for (i=0;i<0x40;i++) { real_writed(0,i*4,CALLBACK_RealPointer(call_default)); } /* Setup block of 0xCD 0xxx instructions */ PhysPt rint_base=CB_BASE+CB_MAX*16; for (i=0;i<=0xff;i++) { phys_writeb(rint_base,0xCD); phys_writeb(rint_base+1,i); phys_writeb(rint_base+2,0xFE); phys_writeb(rint_base+3,0x38); phys_writew(rint_base+4,call_stop); rint_base+=6; } real_writed(0,0x67*4,CALLBACK_RealPointer(call_default)); real_writed(0,0x5c*4,CALLBACK_RealPointer(call_default)); //Network stuff //real_writed(0,0xf*4,0); some games don't like it call_priv_io=CALLBACK_Allocate(); phys_writeb(CB_BASE+(call_priv_io<<4)+0x00,(Bit8u)0xec); // in al, dx phys_writeb(CB_BASE+(call_priv_io<<4)+0x01,(Bit8u)0xcb); // retf phys_writeb(CB_BASE+(call_priv_io<<4)+0x02,(Bit8u)0xed); // in ax, dx phys_writeb(CB_BASE+(call_priv_io<<4)+0x03,(Bit8u)0xcb); // retf phys_writeb(CB_BASE+(call_priv_io<<4)+0x04,(Bit8u)0x66); // in eax, dx phys_writeb(CB_BASE+(call_priv_io<<4)+0x05,(Bit8u)0xed); phys_writeb(CB_BASE+(call_priv_io<<4)+0x06,(Bit8u)0xcb); // retf phys_writeb(CB_BASE+(call_priv_io<<4)+0x08,(Bit8u)0xee); // out dx, al phys_writeb(CB_BASE+(call_priv_io<<4)+0x09,(Bit8u)0xcb); // retf phys_writeb(CB_BASE+(call_priv_io<<4)+0x0a,(Bit8u)0xef); // out dx, ax phys_writeb(CB_BASE+(call_priv_io<<4)+0x0b,(Bit8u)0xcb); // retf phys_writeb(CB_BASE+(call_priv_io<<4)+0x0c,(Bit8u)0x66); // out dx, eax phys_writeb(CB_BASE+(call_priv_io<<4)+0x0d,(Bit8u)0xef); phys_writeb(CB_BASE+(call_priv_io<<4)+0x0e,(Bit8u)0xcb); // retf }
Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress) { if (callback>=CB_MAX) return 0; switch (type) { case CB_RETN: phys_writeb(physAddress+0,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+1,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+2, callback); //The immediate word phys_writeb(physAddress+4,(Bit8u)0xC3); //A RETN Instruction return 5; case CB_RETF: phys_writeb(physAddress+0,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+1,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+2, callback); //The immediate word phys_writeb(physAddress+4,(Bit8u)0xCB); //A RETF Instruction return 5; case CB_IRET: phys_writeb(physAddress+0,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+1,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+2,callback); //The immediate word phys_writeb(physAddress+4,(Bit8u)0xCF); //An IRET Instruction return 5; case CB_IRET_STI: phys_writeb(physAddress+0,(Bit8u)0xFB); //STI phys_writeb(physAddress+1,(Bit8u)0xFE); //GRP 4 phys_writeb(physAddress+2,(Bit8u)0x38); //Extra Callback instruction phys_writew(physAddress+3, callback); //The immediate word phys_writeb(physAddress+5,(Bit8u)0xCF); //An IRET Instruction return 6; default: E_Exit("CALLBACK:Setup:Illegal type %d",type); } return 0; }
void CALLBACK_RemoveSetup(Bitu callback) { for (Bitu i = 0;i < 16;i++) { phys_writeb(CB_BASE+(callback<<4)+i ,(Bit8u) 0x00); } }