DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 00020 #include <stdlib.h> 00021 #include <string.h> 00022 00023 #include "dosbox.h" 00024 #include "callback.h" 00025 #include "logging.h" 00026 #include "bios.h" 00027 #include "mem.h" 00028 #include "cpu.h" 00029 00030 #if C_EMSCRIPTEN 00031 # include <emscripten.h> 00032 #endif 00033 00034 Bit16u CB_SEG=0,CB_SOFFSET=0; 00035 extern Bitu vm86_fake_io_seg; 00036 extern Bitu vm86_fake_io_off; 00037 00038 unsigned int last_callback = 0; 00039 00040 /* CallBack are located at 0xF000:0x1000 (see CB_SEG and CB_SOFFSET in callback.h) 00041 And they are 16 bytes each and you can define them to behave in certain ways like a 00042 far return or and IRET 00043 */ 00044 00045 CallBack_Handler CallBack_Handlers[CB_MAX] = {NULL}; 00046 char* CallBack_Description[CB_MAX] = {NULL}; 00047 00048 Bitu call_stop,call_default; 00049 Bit8u call_idle; 00050 Bitu call_priv_io; 00051 00052 static Bitu illegal_handler(void) { 00053 E_Exit("Illegal CallBack #%u Called",last_callback); 00054 return 1; 00055 } 00056 00057 void DBG_CALLBACK_Dump(void) { 00058 LOG_MSG("Callbacks"); 00059 for (Bitu i=0;i < CB_MAX;i++) { 00060 if (CallBack_Handlers[i] == &illegal_handler) 00061 continue; 00062 00063 LOG_MSG(" [%u] func=%p desc='%s'", 00064 (unsigned int)i, 00065 (void*)((uintptr_t)CallBack_Handlers[i]), /* shut the compiler up by func -> uintptr_t -> void* conversion */ 00066 CallBack_Description[i] != NULL ? CallBack_Description[i] : ""); 00067 } 00068 LOG_MSG("--------------"); 00069 } 00070 00071 void CALLBACK_Dump(void) { 00072 LOG(LOG_CPU,LOG_DEBUG)("Callback dump"); 00073 for (Bitu i=0;i < CB_MAX;i++) { 00074 if (CallBack_Handlers[i] == &illegal_handler) 00075 continue; 00076 00077 LOG(LOG_CPU,LOG_DEBUG)(" [%u] func=%p desc='%s'", 00078 (unsigned int)i, 00079 (void*)((uintptr_t)CallBack_Handlers[i]), /* shut the compiler up by func -> uintptr_t -> void* conversion */ 00080 CallBack_Description[i] != NULL ? CallBack_Description[i] : ""); 00081 } 00082 LOG(LOG_CPU,LOG_DEBUG)("--------------"); 00083 } 00084 00085 void CALLBACK_Shutdown(void) { 00086 for (Bitu i=0;(i<CB_MAX);i++) { 00087 CallBack_Handlers[i] = &illegal_handler; 00088 CALLBACK_SetDescription(i,NULL); 00089 } 00090 } 00091 00092 Bit8u CALLBACK_Allocate(void) { 00093 for (Bit8u i=1;(i<CB_MAX);i++) { 00094 if (CallBack_Handlers[i]==&illegal_handler) { 00095 if (CallBack_Description[i] != NULL) LOG_MSG("CALLBACK_Allocate() warning: empty slot still has description string!\n"); 00096 CallBack_Handlers[i]=0; 00097 return i; 00098 } 00099 } 00100 E_Exit("CALLBACK:Can't allocate handler."); 00101 return 0; 00102 } 00103 00104 void CALLBACK_DeAllocate(Bitu in) { 00105 assert(in != 0); 00106 assert(in < CB_MAX); 00107 00108 CallBack_Handlers[in]=&illegal_handler; 00109 CALLBACK_SetDescription(in,NULL); 00110 } 00111 00112 00113 void CALLBACK_Idle(void) { 00114 #if C_EMSCRIPTEN 00115 void GFX_Events(); 00116 GFX_Events(); 00117 #endif 00118 00119 /* this makes the cpu execute instructions to handle irq's and then come back */ 00120 Bitu oldIF=GETFLAG(IF); 00121 SETFLAGBIT(IF,true); 00122 Bit16u oldcs=SegValue(cs); 00123 Bit32u oldeip=reg_eip; 00124 SegSet16(cs,CB_SEG); 00125 reg_eip=CB_SOFFSET+call_idle*CB_SIZE; 00126 DOSBOX_RunMachine(); 00127 reg_eip=oldeip; 00128 SegSet16(cs,oldcs); 00129 SETFLAGBIT(IF,oldIF); 00130 if (!CPU_CycleAutoAdjust && CPU_Cycles>0) 00131 CPU_Cycles=0; 00132 } 00133 00134 void CALLBACK_IdleNoInts(void) { 00135 #if C_EMSCRIPTEN 00136 void GFX_Events(); 00137 GFX_Events(); 00138 #endif 00139 00140 /* this makes the cpu execute instructions to handle irq's and then come back */ 00141 // Bitu oldIF=GETFLAG(IF); 00142 // SETFLAGBIT(IF,true); 00143 Bit16u oldcs=SegValue(cs); 00144 Bit32u oldeip=reg_eip; 00145 SegSet16(cs,CB_SEG); 00146 reg_eip=CB_SOFFSET+call_idle*CB_SIZE; 00147 DOSBOX_RunMachine(); 00148 reg_eip=oldeip; 00149 SegSet16(cs,oldcs); 00150 // SETFLAGBIT(IF,oldIF); 00151 if (!CPU_CycleAutoAdjust && CPU_Cycles>0) 00152 CPU_Cycles=0; 00153 } 00154 00155 static Bitu default_handler(void) { 00156 LOG(LOG_CPU,LOG_ERROR)("Illegal Unhandled Interrupt Called %X",lastint); 00157 return CBRET_NONE; 00158 } 00159 00160 static Bitu stop_handler(void) { 00161 return CBRET_STOP; 00162 } 00163 00164 Bitu FillFlags(void); 00165 00166 void CALLBACK_RunRealFarInt(Bit16u seg,Bit16u off) { 00167 FillFlags(); 00168 00169 reg_sp-=6; 00170 mem_writew(SegPhys(ss)+reg_sp,RealOff(CALLBACK_RealPointer(call_stop))); 00171 mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(CALLBACK_RealPointer(call_stop))); 00172 mem_writew(SegPhys(ss)+reg_sp+4,(Bit16u)reg_flags); 00173 Bit32u oldeip=reg_eip; 00174 Bit16u oldcs=SegValue(cs); 00175 reg_eip=off; 00176 SegSet16(cs,seg); 00177 DOSBOX_RunMachine(); 00178 reg_eip=oldeip; 00179 SegSet16(cs,oldcs); 00180 } 00181 00182 void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) { 00183 reg_sp-=4; 00184 mem_writew(SegPhys(ss)+reg_sp,RealOff(CALLBACK_RealPointer(call_stop))); 00185 mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(CALLBACK_RealPointer(call_stop))); 00186 Bit32u oldeip=reg_eip; 00187 Bit16u oldcs=SegValue(cs); 00188 reg_eip=off; 00189 SegSet16(cs,seg); 00190 DOSBOX_RunMachine(); 00191 reg_eip=oldeip; 00192 SegSet16(cs,oldcs); 00193 } 00194 00195 void CALLBACK_RunRealInt_retcsip(Bit8u intnum,Bitu &rcs,Bitu &rip) { 00196 Bit32u oldeip=reg_eip; 00197 Bit16u oldcs=SegValue(cs); 00198 reg_eip=CB_SOFFSET+(CB_MAX*CB_SIZE)+(intnum*6U); 00199 SegSet16(cs,CB_SEG); 00200 DOSBOX_RunMachine(); 00201 rcs = SegValue(cs); 00202 rip = reg_ip; 00203 reg_eip=oldeip; 00204 SegSet16(cs,oldcs); 00205 } 00206 00207 void CALLBACK_RunRealInt(Bit8u intnum) { 00208 Bit32u oldeip=reg_eip; 00209 Bit16u oldcs=SegValue(cs); 00210 reg_eip=CB_SOFFSET+(CB_MAX*CB_SIZE)+(intnum*6U); 00211 SegSet16(cs,CB_SEG); 00212 DOSBOX_RunMachine(); 00213 reg_eip=oldeip; 00214 SegSet16(cs,oldcs); 00215 } 00216 00217 void CALLBACK_SZF(bool val) { 00218 Bit32u tempf; 00219 00220 if (cpu.stack.big) 00221 tempf = mem_readd(SegPhys(ss)+reg_esp+8); // first word past FAR 32:32 00222 else 00223 tempf = mem_readw(SegPhys(ss)+reg_sp+4); // first word past FAR 16:16 00224 00225 if (val) tempf |= FLAG_ZF; 00226 else tempf &= ~FLAG_ZF; 00227 00228 if (cpu.stack.big) 00229 mem_writed(SegPhys(ss)+reg_esp+8,tempf); 00230 else 00231 mem_writew(SegPhys(ss)+reg_sp+4,(Bit16u)tempf); 00232 } 00233 00234 void CALLBACK_SCF(bool val) { 00235 Bit32u tempf; 00236 00237 if (cpu.stack.big) 00238 tempf = mem_readd(SegPhys(ss)+reg_esp+8); // first word past FAR 32:32 00239 else 00240 tempf = mem_readw(SegPhys(ss)+reg_sp+4); // first word past FAR 16:16 00241 00242 if (val) tempf |= FLAG_CF; 00243 else tempf &= ~FLAG_CF; 00244 00245 if (cpu.stack.big) 00246 mem_writed(SegPhys(ss)+reg_esp+8,tempf); 00247 else 00248 mem_writew(SegPhys(ss)+reg_sp+4,(Bit16u)tempf); 00249 } 00250 00251 void CALLBACK_SIF(bool val) { 00252 Bit32u tempf; 00253 00254 if (cpu.stack.big) 00255 tempf = mem_readd(SegPhys(ss)+reg_esp+8); // first word past FAR 32:32 00256 else 00257 tempf = mem_readw(SegPhys(ss)+reg_sp+4); // first word past FAR 16:16 00258 00259 if (val) tempf |= FLAG_IF; 00260 else tempf &= ~FLAG_IF; 00261 00262 if (cpu.stack.big) 00263 mem_writed(SegPhys(ss)+reg_esp+8,tempf); 00264 else 00265 mem_writew(SegPhys(ss)+reg_sp+4,(Bit16u)tempf); 00266 } 00267 00268 void CALLBACK_SetDescription(Bitu nr, const char* descr) { 00269 if (CallBack_Description[nr]) delete[] CallBack_Description[nr]; 00270 CallBack_Description[nr] = 0; 00271 00272 if (descr != NULL) { 00273 CallBack_Description[nr] = new char[strlen(descr)+1]; 00274 strcpy(CallBack_Description[nr],descr); 00275 } 00276 } 00277 00278 const char* CALLBACK_GetDescription(Bitu nr) { 00279 if (nr>=CB_MAX) return 0; 00280 return CallBack_Description[nr]; 00281 } 00282 00283 Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_cb=true) { 00284 if (callback>=CB_MAX) 00285 return 0; 00286 switch (type) { 00287 case CB_RETN: 00288 if (use_cb) { 00289 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00290 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00291 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00292 physAddress+=4; 00293 } 00294 phys_writeb(physAddress+0x00,(Bit8u)0xC3); //A RETN Instruction 00295 return (use_cb?5:1); 00296 case CB_RETF: 00297 if (use_cb) { 00298 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00299 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00300 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00301 physAddress+=4; 00302 } 00303 phys_writeb(physAddress+0x00,(Bit8u)0xCB); //A RETF Instruction 00304 return (use_cb?5:1); 00305 case CB_RETF8: 00306 if (use_cb) { 00307 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00308 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00309 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00310 physAddress+=4; 00311 } 00312 phys_writeb(physAddress+0x00,(Bit8u)0xCA); //A RETF 8 Instruction 00313 phys_writew(physAddress+0x01,(Bit16u)0x0008); 00314 return (use_cb?7:3); 00315 case CB_RETF_STI: 00316 phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI 00317 if (use_cb) { 00318 phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 00319 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction 00320 phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word 00321 physAddress+=4; 00322 } 00323 phys_writeb(physAddress+0x01,(Bit8u)0xCB); //A RETF Instruction 00324 return (use_cb?6:2); 00325 case CB_RETF_CLI: 00326 phys_writeb(physAddress+0x00,(Bit8u)0xFA); //CLI 00327 if (use_cb) { 00328 phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 00329 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction 00330 phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word 00331 physAddress+=4; 00332 } 00333 phys_writeb(physAddress+0x01,(Bit8u)0xCB); //A RETF Instruction 00334 return (use_cb?6:2); 00335 case CB_IRET: 00336 if (use_cb) { 00337 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00338 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00339 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00340 physAddress+=4; 00341 } 00342 phys_writeb(physAddress+0x00,(Bit8u)0xCF); //An IRET Instruction 00343 return (use_cb?5:1); 00344 case CB_IRETD: 00345 if (use_cb) { 00346 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00347 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00348 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00349 physAddress+=4; 00350 } 00351 phys_writeb(physAddress+0x00,(Bit8u)0x66); //An IRETD Instruction 00352 phys_writeb(physAddress+0x01,(Bit8u)0xCF); 00353 return (use_cb?6:2); 00354 case CB_IRET_STI: 00355 phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI 00356 if (use_cb) { 00357 phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 00358 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction 00359 phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word 00360 physAddress+=4; 00361 } 00362 phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction 00363 return (use_cb?6:2); 00364 case CB_IRET_EOI_PIC1: 00365 if (use_cb) { 00366 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00367 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00368 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00369 physAddress+=4; 00370 } 00371 phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax 00372 phys_writeb(physAddress+0x01,(Bit8u)0xb0); // mov al, 0x20 00373 phys_writeb(physAddress+0x02,(Bit8u)0x20); 00374 phys_writeb(physAddress+0x03,(Bit8u)0xe6); // out 0x20, al (IBM) / out 0x00, al (PC-98) 00375 phys_writeb(physAddress+0x04,(Bit8u)(IS_PC98_ARCH ? 0x00 : 0x20)); 00376 phys_writeb(physAddress+0x05,(Bit8u)0x58); // pop ax 00377 phys_writeb(physAddress+0x06,(Bit8u)0xcf); //An IRET Instruction 00378 return (use_cb?0x0b:0x07); 00379 case CB_IRQ0: // timer int8 00380 phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI 00381 if (use_cb) { 00382 phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 00383 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction 00384 phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word 00385 physAddress+=4; 00386 } 00387 phys_writeb(physAddress+0x01,(Bit8u)0x1e); // push ds 00388 phys_writeb(physAddress+0x02,(Bit8u)0x50); // push ax 00389 phys_writeb(physAddress+0x03,(Bit8u)0x52); // push dx 00390 phys_writew(physAddress+0x04,(Bit16u)0x1ccd); // int 1c 00391 phys_writeb(physAddress+0x06,(Bit8u)0xfa); // cli 00392 phys_writew(physAddress+0x07,(Bit16u)0x20b0); // mov al, 0x20 00393 phys_writew(physAddress+0x09,(Bit16u)(IS_PC98_ARCH ? 0x00e6 : 0x20e6)); // out 0x20, al / out 0x00, al (PC-98) (FIXME: PC-98 does not have INT 1Ch) 00394 phys_writeb(physAddress+0x0b,(Bit8u)0x5a); // pop dx 00395 phys_writeb(physAddress+0x0c,(Bit8u)0x58); // pop ax 00396 phys_writeb(physAddress+0x0d,(Bit8u)0x1f); // pop ds 00397 phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction 00398 return (use_cb?0x13:0x0f); 00399 case CB_IRQ1: // keyboard int9 00400 phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax 00401 if (machine == MCH_PCJR || IS_PC98_ARCH) { 00402 /* NTS: NEC PC-98 does not have keyboard input on port 60h, it's a 8251 UART elsewhere. 00403 * 00404 * IBM PCjr reads the infared input on NMI interrupt, which then calls INT 48h to 00405 * translate to IBM PC/XT scan codes before passing AL directly to IRQ1 (INT 9). 00406 * PCjr keyboard handlers, including games made for the PCjr, assume the scan code 00407 * is in AL and do not read the I/O port */ 00408 phys_writew(physAddress+0x01,(Bit16u)0x9090); // nop, nop 00409 } 00410 else { 00411 phys_writew(physAddress+0x01,(Bit16u)0x60e4); // in al, 0x60 00412 } 00413 if (IS_PC98_ARCH || IS_TANDY_ARCH) { 00414 phys_writew(physAddress+0x03,(Bit16u)0x9090); // nop, nop 00415 phys_writeb(physAddress+0x05,(Bit8u)0x90); // nop 00416 phys_writew(physAddress+0x06,(Bit16u)0x9090); // nop, nop (PC-98 does not have INT 15h keyboard hook) 00417 } 00418 else { 00419 phys_writew(physAddress+0x03,(Bit16u)0x4fb4); // mov ah, 0x4f 00420 phys_writeb(physAddress+0x05,(Bit8u)0xf9); // stc 00421 phys_writew(physAddress+0x06,(Bit16u)0x15cd); // int 15 00422 } 00423 00424 if (use_cb) { 00425 if (IS_PC98_ARCH || IS_TANDY_ARCH) 00426 phys_writew(physAddress+0x08,(Bit16u)0x9090); // nop nop 00427 else 00428 phys_writew(physAddress+0x08,(Bit16u)0x0473); // jc skip 00429 00430 phys_writeb(physAddress+0x0a,(Bit8u)0xFE); //GRP 4 00431 phys_writeb(physAddress+0x0b,(Bit8u)0x38); //Extra Callback instruction 00432 phys_writew(physAddress+0x0c,(Bit16u)callback); //The immediate word 00433 // jump here to (skip): 00434 physAddress+=6; 00435 } 00436 phys_writeb(physAddress+0x08,(Bit8u)0xfa); // cli 00437 phys_writew(physAddress+0x09,(Bit16u)0x20b0); // mov al, 0x20 00438 phys_writew(physAddress+0x0b,(Bit16u)(IS_PC98_ARCH ? 0x00e6 : 0x20e6)); // out 0x20, al 00439 phys_writeb(physAddress+0x0d,(Bit8u)0x58); // pop ax 00440 phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction 00441 phys_writeb(physAddress+0x0f,(Bit8u)0xfa); // cli 00442 phys_writew(physAddress+0x10,(Bit16u)0x20b0); // mov al, 0x20 00443 phys_writew(physAddress+0x12,(Bit16u)0x20e6); // out 0x20, al 00444 phys_writeb(physAddress+0x14,(Bit8u)0x55); // push bp 00445 phys_writew(physAddress+0x15,(Bit16u)0x05cd); // int 5 00446 phys_writeb(physAddress+0x17,(Bit8u)0x5d); // pop bp 00447 phys_writeb(physAddress+0x18,(Bit8u)0x58); // pop ax 00448 phys_writeb(physAddress+0x19,(Bit8u)0xcf); //An IRET Instruction 00449 return (use_cb ?0x20:0x1a); 00450 case CB_IRQ1_BREAK: // return from int9, when Ctrl-Break is detected; invokes int 1b 00451 phys_writew(physAddress+0x00,(Bit16u)0x1bcd); // int 1b 00452 phys_writeb(physAddress+0x02,(Bit8u)0xfa); // cli 00453 if (use_cb) { 00454 phys_writeb(physAddress+0x03,(Bit8u)0xFE); //GRP 4 00455 phys_writeb(physAddress+0x04,(Bit8u)0x38); //Extra Callback instruction 00456 phys_writew(physAddress+0x05,(Bit16u)callback); //The immediate word 00457 physAddress+=4; 00458 } 00459 phys_writew(physAddress+0x03,(Bit16u)0x20b0); // mov al, 0x20 00460 phys_writew(physAddress+0x05,(Bit16u)(IS_PC98_ARCH ? 0x00e6 : 0x20e6)); // out 0x20, al 00461 phys_writeb(physAddress+0x07,(Bit8u)0x58); // pop ax 00462 phys_writeb(physAddress+0x08,(Bit8u)0xcf); //An IRET Instruction 00463 return (use_cb?0x0d:0x09); 00464 case CB_IRQ9: // pic cascade interrupt 00465 if (use_cb) { 00466 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00467 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00468 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00469 physAddress+=4; 00470 } 00471 phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax 00472 phys_writew(physAddress+0x01,(Bit16u)0x61b0); // mov al, 0x61 00473 phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al 00474 phys_writew(physAddress+0x05,(Bit16u)0x0acd); // int a 00475 phys_writeb(physAddress+0x07,(Bit8u)0xfa); // cli 00476 phys_writeb(physAddress+0x08,(Bit8u)0x58); // pop ax 00477 phys_writeb(physAddress+0x09,(Bit8u)0xcf); //An IRET Instruction 00478 return (use_cb?0x0e:0x0a); 00479 case CB_IRQ12: // ps2 mouse int74 00480 if (!use_cb) E_Exit("int74 callback must implement a callback handler!"); 00481 phys_writeb(physAddress++,(Bit8u)0xfb); // sti 00482 phys_writeb(physAddress++,(Bit8u)0x1e); // push ds 00483 phys_writeb(physAddress++,(Bit8u)0x06); // push es 00484 if (CPU_ArchitectureType>=CPU_ARCHTYPE_386) { 00485 phys_writew(physAddress,(Bit16u)0x6066);// pushad 00486 physAddress += 2; 00487 } 00488 else if (CPU_ArchitectureType>=CPU_ARCHTYPE_80186) { 00489 phys_writeb(physAddress++,(Bit8u)0x60); // pusha 00490 } 00491 else { 00492 // 8086-level tedium, PUSHA not available 00493 phys_writeb(physAddress++,(Bit8u)0x50); // push ax 00494 phys_writeb(physAddress++,(Bit8u)0x51); // push cx 00495 phys_writeb(physAddress++,(Bit8u)0x52); // push dx 00496 phys_writeb(physAddress++,(Bit8u)0x53); // push bx 00497 phys_writeb(physAddress++,(Bit8u)0x55); // push bp 00498 phys_writeb(physAddress++,(Bit8u)0x56); // push si 00499 phys_writeb(physAddress++,(Bit8u)0x57); // push di 00500 } 00501 phys_writeb(physAddress++,(Bit8u)0xFE); //GRP 4 00502 phys_writeb(physAddress++,(Bit8u)0x38); //Extra Callback instruction 00503 phys_writew(physAddress,(Bit16u)callback); //The immediate word 00504 physAddress += 2; 00505 phys_writeb(physAddress++,(Bit8u)0x50); // push ax 00506 phys_writew(physAddress,(Bit16u)0x20b0); // mov al, 0x20 00507 physAddress += 2; 00508 phys_writew(physAddress,(Bit16u)0xa0e6); // out 0xa0, al 00509 physAddress += 2; 00510 phys_writew(physAddress,(Bit16u)0x20e6); // out 0x20, al 00511 physAddress += 2; 00512 phys_writeb(physAddress++,(Bit8u)0x58); // pop ax 00513 phys_writeb(physAddress++,(Bit8u)0xfc); // cld 00514 phys_writeb(physAddress++,(Bit8u)0xCB); //A RETF Instruction 00515 return 0x13; 00516 case CB_IRQ12_RET: // ps2 mouse int74 return 00517 phys_writeb(physAddress++,(Bit8u)0xfa); // cli 00518 phys_writew(physAddress,(Bit16u)0x20b0); // mov al, 0x20 00519 physAddress += 2; 00520 phys_writew(physAddress,(Bit16u)0xa0e6); // out 0xa0, al 00521 physAddress += 2; 00522 phys_writew(physAddress,(Bit16u)0x20e6); // out 0x20, al 00523 physAddress += 2; 00524 if (use_cb) { 00525 phys_writeb(physAddress++,(Bit8u)0xFE); //GRP 4 00526 phys_writeb(physAddress++,(Bit8u)0x38); //Extra Callback instruction 00527 phys_writew(physAddress,(Bit16u)callback); //The immediate word 00528 physAddress+=2; 00529 } 00530 if (CPU_ArchitectureType>=CPU_ARCHTYPE_386) { 00531 phys_writew(physAddress,(Bit16u)0x6166);// popad 00532 physAddress += 2; 00533 } 00534 else if (CPU_ArchitectureType>=CPU_ARCHTYPE_80186) { 00535 phys_writeb(physAddress++,(Bit8u)0x61); // popa 00536 } 00537 else { 00538 // 8086-level tedium, POPA not available 00539 phys_writeb(physAddress++,(Bit8u)0x5F); // pop di 00540 phys_writeb(physAddress++,(Bit8u)0x5E); // pop si 00541 phys_writeb(physAddress++,(Bit8u)0x5D); // pop bp 00542 phys_writeb(physAddress++,(Bit8u)0x5B); // pop bx 00543 phys_writeb(physAddress++,(Bit8u)0x5A); // pop dx 00544 phys_writeb(physAddress++,(Bit8u)0x59); // pop cx 00545 phys_writeb(physAddress++,(Bit8u)0x58); // pop ax 00546 } 00547 phys_writeb(physAddress++,(Bit8u)0x07); // pop es 00548 phys_writeb(physAddress++,(Bit8u)0x1f); // pop ds 00549 phys_writeb(physAddress++,(Bit8u)0xcf); //An IRET Instruction 00550 return (use_cb?0x10:0x0c); 00551 case CB_IRQ6_PCJR: // pcjr keyboard interrupt 00552 phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax 00553 phys_writew(physAddress+0x01,(Bit16u)0x60e4); // in al, 0x60 00554 phys_writew(physAddress+0x03,(Bit16u)0xe03c); // cmp al, 0xe0 00555 if (use_cb) { 00556 phys_writew(physAddress+0x05,(Bit16u)0x0b74); // je skip 00557 phys_writeb(physAddress+0x07,(Bit8u)0xFE); //GRP 4 00558 phys_writeb(physAddress+0x08,(Bit8u)0x38); //Extra Callback instruction 00559 phys_writew(physAddress+0x09,(Bit16u)callback); //The immediate word 00560 physAddress+=4; 00561 } else { 00562 phys_writew(physAddress+0x05,(Bit16u)0x0774); // je skip 00563 } 00564 phys_writeb(physAddress+0x07,(Bit8u)0x1e); // push ds 00565 phys_writew(physAddress+0x08,(Bit16u)0x406a); // push 0x0040 00566 phys_writeb(physAddress+0x0a,(Bit8u)0x1f); // pop ds 00567 phys_writew(physAddress+0x0b,(Bit16u)0x09cd); // int 9 00568 phys_writeb(physAddress+0x0d,(Bit8u)0x1f); // pop ds 00569 // jump here to (skip): 00570 phys_writeb(physAddress+0x0e,(Bit8u)0xfa); // cli 00571 phys_writew(physAddress+0x0f,(Bit16u)0x20b0); // mov al, 0x20 00572 phys_writew(physAddress+0x11,(Bit16u)0x20e6); // out 0x20, al 00573 phys_writeb(physAddress+0x13,(Bit8u)0x58); // pop ax 00574 phys_writeb(physAddress+0x14,(Bit8u)0xcf); //An IRET Instruction 00575 return (use_cb?0x19:0x15); 00576 case CB_MOUSE: 00577 phys_writew(physAddress+0x00,(Bit16u)0x07eb); // jmp i33hd 00578 physAddress+=9; 00579 // jump here to (i33hd): 00580 if (use_cb) { 00581 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00582 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00583 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00584 physAddress+=4; 00585 } 00586 phys_writeb(physAddress+0x00,(Bit8u)0xCF); //An IRET Instruction 00587 return (use_cb?0x0e:0x0a); 00588 case CB_INT16: 00589 phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI 00590 if (use_cb) { 00591 phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 00592 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction 00593 phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word 00594 physAddress+=4; 00595 } 00596 phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction 00597 for (Bit8u i=0;i<=0x0b;i++) phys_writeb(physAddress+0x02+i,0x90); 00598 phys_writew(physAddress+0x0e,(Bit16u)0xedeb); //jmp callback 00599 return (use_cb?0x10:0x0c); 00600 /*case CB_INT28: // DOS idle 00601 phys_writeb(physAddress+0x00,(Bit8u)0xFB); // STI 00602 phys_writeb(physAddress+0x01,(Bit8u)0xF4); // HLT 00603 phys_writeb(physAddress+0x02,(Bit8u)0xcf); // An IRET Instruction 00604 return (0x04);*/ 00605 case CB_INT29: // fast console output 00606 if (IS_PC98_ARCH) LOG_MSG("WARNING: CB_INT29 callback setup not appropriate for PC-98 mode (INT 10h no longer BIOS call)"); 00607 if (use_cb) { 00608 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00609 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00610 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00611 physAddress+=4; 00612 } 00613 phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax 00614 phys_writeb(physAddress+0x01,(Bit8u)0x53); // push bx 00615 phys_writew(physAddress+0x02,(Bit16u)0x0eb4); // mov ah, 0x0e 00616 phys_writeb(physAddress+0x04,(Bit8u)0xbb); // mov bx, 00617 phys_writew(physAddress+0x05,(Bit16u)0x0007); // 0x0007 00618 phys_writew(physAddress+0x07,(Bit16u)0x10cd); // int 10 00619 phys_writeb(physAddress+0x09,(Bit8u)0x5b); // pop bx 00620 phys_writeb(physAddress+0x0a,(Bit8u)0x58); // pop ax 00621 phys_writeb(physAddress+0x0b,(Bit8u)0xcf); //An IRET Instruction 00622 return (use_cb?0x10:0x0c); 00623 case CB_HOOKABLE: 00624 phys_writeb(physAddress+0x00,(Bit8u)0xEB); //jump near 00625 phys_writeb(physAddress+0x01,(Bit8u)0x03); //offset 00626 phys_writeb(physAddress+0x02,(Bit8u)0x90); //NOP 00627 phys_writeb(physAddress+0x03,(Bit8u)0x90); //NOP 00628 phys_writeb(physAddress+0x04,(Bit8u)0x90); //NOP 00629 if (use_cb) { 00630 phys_writeb(physAddress+0x05,(Bit8u)0xFE); //GRP 4 00631 phys_writeb(physAddress+0x06,(Bit8u)0x38); //Extra Callback instruction 00632 phys_writew(physAddress+0x07,(Bit16u)callback); //The immediate word 00633 physAddress+=4; 00634 } 00635 phys_writeb(physAddress+0x05,(Bit8u)0xCB); //A RETF Instruction 00636 return (use_cb?0x0a:0x06); 00637 case CB_TDE_IRET: // TandyDAC end transfer 00638 if (use_cb) { 00639 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00640 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00641 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00642 physAddress+=4; 00643 } 00644 phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax 00645 phys_writeb(physAddress+0x01,(Bit8u)0xb8); // mov ax, 0x91fb 00646 phys_writew(physAddress+0x02,(Bit16u)0x91fb); 00647 phys_writew(physAddress+0x04,(Bit16u)0x15cd); // int 15 00648 phys_writeb(physAddress+0x06,(Bit8u)0xfa); // cli 00649 phys_writew(physAddress+0x07,(Bit16u)0x20b0); // mov al, 0x20 00650 phys_writew(physAddress+0x09,(Bit16u)0x20e6); // out 0x20, al 00651 phys_writeb(physAddress+0x0b,(Bit8u)0x58); // pop ax 00652 phys_writeb(physAddress+0x0c,(Bit8u)0xcf); //An IRET Instruction 00653 return (use_cb?0x11:0x0d); 00654 /* case CB_IPXESR: // IPX ESR 00655 if (!use_cb) E_Exit("ipx esr must implement a callback handler!"); 00656 phys_writeb(physAddress+0x00,(Bit8u)0x1e); // push ds 00657 phys_writeb(physAddress+0x01,(Bit8u)0x06); // push es 00658 phys_writew(physAddress+0x02,(Bit16u)0xa00f); // push fs 00659 phys_writew(physAddress+0x04,(Bit16u)0xa80f); // push gs 00660 phys_writeb(physAddress+0x06,(Bit8u)0x60); // pusha 00661 phys_writeb(physAddress+0x07,(Bit8u)0xFE); //GRP 4 00662 phys_writeb(physAddress+0x08,(Bit8u)0x38); //Extra Callback instruction 00663 phys_writew(physAddress+0x09,(Bit16u)callback); //The immediate word 00664 phys_writeb(physAddress+0x0b,(Bit8u)0xCB); //A RETF Instruction 00665 return 0x0c; 00666 case CB_IPXESR_RET: // IPX ESR return 00667 if (use_cb) E_Exit("ipx esr return must not implement a callback handler!"); 00668 phys_writeb(physAddress+0x00,(Bit8u)0xfa); // cli 00669 phys_writew(physAddress+0x01,(Bit16u)0x20b0); // mov al, 0x20 00670 phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al 00671 phys_writew(physAddress+0x05,(Bit16u)0x20e6); // out 0x20, al 00672 phys_writeb(physAddress+0x07,(Bit8u)0x61); // popa 00673 phys_writew(physAddress+0x08,(Bit16u)0xA90F); // pop gs 00674 phys_writew(physAddress+0x0a,(Bit16u)0xA10F); // pop fs 00675 phys_writeb(physAddress+0x0c,(Bit8u)0x07); // pop es 00676 phys_writeb(physAddress+0x0d,(Bit8u)0x1f); // pop ds 00677 phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction 00678 return 0x0f; */ 00679 case CB_INT21: 00680 phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI 00681 if (use_cb) { 00682 phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 00683 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction 00684 phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word 00685 physAddress+=4; 00686 } 00687 phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction 00688 phys_writeb(physAddress+0x02,(Bit8u)0xCB); //A RETF Instruction 00689 phys_writeb(physAddress+0x03,(Bit8u)0x51); // push cx 00690 phys_writeb(physAddress+0x04,(Bit8u)0xB9); // mov cx, 00691 phys_writew(physAddress+0x05,(Bit16u)0x0140); // 0x140 00692 phys_writew(physAddress+0x07,(Bit16u)0xFEE2); // loop $-2 00693 phys_writeb(physAddress+0x09,(Bit8u)0x59); // pop cx 00694 phys_writeb(physAddress+0x0A,(Bit8u)0xCF); //An IRET Instruction 00695 return (use_cb?15:11); 00696 case CB_INT13: 00697 phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI 00698 if (use_cb) { 00699 phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 00700 phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction 00701 phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word 00702 physAddress+=4; 00703 } 00704 phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction 00705 phys_writew(physAddress+0x02,(Bit16u)0x0ECD); // int 0e 00706 phys_writeb(physAddress+0x04,(Bit8u)0xCF); //An IRET Instruction 00707 return (use_cb?9:5); 00708 case CB_VESA_WAIT: 00709 if (use_cb) E_Exit("VESA wait must not implement a callback handler!"); 00710 phys_writeb(physAddress+0x00,(Bit8u)0xFB); // sti 00711 phys_writeb(physAddress+0x01,(Bit8u)0x50); // push ax 00712 phys_writeb(physAddress+0x02,(Bit8u)0x52); // push dx 00713 phys_writeb(physAddress+0x03,(Bit8u)0xBA); // mov dx, 00714 phys_writew(physAddress+0x04,(Bit16u)0x03DA); // 0x3da 00715 phys_writeb(physAddress+0x06,(Bit8u)0xEC); // in al,dx 00716 phys_writew(physAddress+0x07,(Bit16u)0x08A8); // test al,8 00717 phys_writew(physAddress+0x09,(Bit16u)0xFB75); // jne $-5 00718 phys_writeb(physAddress+0x0B,(Bit8u)0xEC); // in al,dx 00719 phys_writew(physAddress+0x0C,(Bit16u)0x08A8); // test al,8 00720 phys_writew(physAddress+0x0E,(Bit16u)0xFB74); // je $-5 00721 phys_writeb(physAddress+0x10,(Bit8u)0x5A); // pop dx 00722 phys_writeb(physAddress+0x11,(Bit8u)0x58); // pop ax 00723 phys_writeb(physAddress+0x12,(Bit8u)0xCB); //A RETF Instruction 00724 return 19; 00725 case CB_VESA_PM: 00726 if (use_cb) { 00727 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00728 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00729 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00730 physAddress+=4; 00731 } 00732 phys_writew(physAddress+0x00,(Bit16u)0xC3F6); // test bl, 00733 phys_writeb(physAddress+0x02,(Bit8u)0x80); // 0x80 00734 phys_writew(physAddress+0x03,(Bit16u)0x1674); // je $+22 00735 phys_writew(physAddress+0x05,(Bit16u)0x5066); // push ax 00736 phys_writew(physAddress+0x07,(Bit16u)0x5266); // push dx 00737 phys_writew(physAddress+0x09,(Bit16u)0xBA66); // mov dx, 00738 phys_writew(physAddress+0x0B,(Bit16u)0x03DA); // 0x3da 00739 phys_writeb(physAddress+0x0D,(Bit8u)0xEC); // in al,dx 00740 phys_writew(physAddress+0x0E,(Bit16u)0x08A8); // test al,8 00741 phys_writew(physAddress+0x10,(Bit16u)0xFB75); // jne $-5 00742 phys_writeb(physAddress+0x12,(Bit8u)0xEC); // in al,dx 00743 phys_writew(physAddress+0x13,(Bit16u)0x08A8); // test al,8 00744 phys_writew(physAddress+0x15,(Bit16u)0xFB74); // je $-5 00745 phys_writew(physAddress+0x17,(Bit16u)0x5A66); // pop dx 00746 phys_writew(physAddress+0x19,(Bit16u)0x5866); // pop ax 00747 if (use_cb) 00748 phys_writeb(physAddress+0x1B,(Bit8u)0xC3); //A RETN Instruction 00749 return (use_cb?32:27); 00750 case CB_IRET_EOI_PIC2: 00751 if (use_cb) { 00752 phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 00753 phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction 00754 phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word 00755 physAddress+=4; 00756 } 00757 phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax 00758 phys_writeb(physAddress+0x01,(Bit8u)0xb0); // mov al, 0x20 00759 phys_writeb(physAddress+0x02,(Bit8u)0x20); 00760 phys_writeb(physAddress+0x03,(Bit8u)0xe6); // out 0xA0, al (IBM) / out 0x08, al (PC-98) 00761 phys_writeb(physAddress+0x04,(Bit8u)(IS_PC98_ARCH ? 0x08 : 0xA0)); 00762 phys_writeb(physAddress+0x05,(Bit8u)0xe6); // out 0x20, al (IBM) / out 0x00, al (PC-98) 00763 phys_writeb(physAddress+0x06,(Bit8u)(IS_PC98_ARCH ? 0x00 : 0x20)); 00764 phys_writeb(physAddress+0x07,(Bit8u)0x58); // pop ax 00765 phys_writeb(physAddress+0x08,(Bit8u)0xcf); //An IRET Instruction 00766 return (use_cb?0x0d:0x09); 00767 case CB_CPM: 00768 phys_writeb(physAddress+0x00,(Bit8u)0x9C); //PUSHF 00769 return CALLBACK_SetupExtra(callback,CB_INT21,physAddress+1,use_cb)+1; 00770 default: 00771 E_Exit("CALLBACK:Setup:Illegal type %u",(unsigned int)type); 00772 } 00773 return 0; 00774 } 00775 00776 bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr) { 00777 if (callback>=CB_MAX) return false; 00778 CALLBACK_SetupExtra(callback,type,CALLBACK_PhysPointer(callback)+0,(handler!=NULL)); 00779 CallBack_Handlers[callback]=handler; 00780 CALLBACK_SetDescription(callback,descr); 00781 return true; 00782 } 00783 00784 Bitu CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,PhysPt addr,const char* descr) { 00785 if (callback>=CB_MAX) return 0; 00786 Bitu csize=CALLBACK_SetupExtra(callback,type,addr,(handler!=NULL)); 00787 if (csize>0) { 00788 CallBack_Handlers[callback]=handler; 00789 CALLBACK_SetDescription(callback,descr); 00790 } 00791 return csize; 00792 } 00793 00794 void CALLBACK_RemoveSetup(Bitu callback) { 00795 if (MemBase == NULL) { 00796 /* avoid crash */ 00797 return; 00798 } 00799 00800 for (Bit8u i = 0;i < CB_SIZE;i++) { 00801 phys_writeb(CALLBACK_PhysPointer(callback)+i ,(Bit8u) 0x00); 00802 } 00803 } 00804 00805 void CALLBACK_HandlerObject::Uninstall(){ 00806 if(!installed) return; 00807 if(m_type == CALLBACK_HandlerObject::SETUP) { 00808 if(vectorhandler.installed && MemBase != NULL){ 00809 //See if we are the current handler. if so restore the old one 00810 if(RealGetVec(vectorhandler.interrupt) == Get_RealPointer()) { 00811 RealSetVec(vectorhandler.interrupt,vectorhandler.old_vector); 00812 } else 00813 LOG(LOG_MISC,LOG_WARN)("Interrupt vector changed on %X %s",vectorhandler.interrupt,CALLBACK_GetDescription(m_callback)); 00814 } 00815 CALLBACK_RemoveSetup(m_callback); 00816 } else if(m_type == CALLBACK_HandlerObject::SETUPAT){ 00817 E_Exit("Callback:SETUP at not handled yet."); 00818 } else if(m_type == CALLBACK_HandlerObject::NONE){ 00819 //Do nothing. Merely DeAllocate the callback 00820 } else E_Exit("what kind of callback is this!"); 00821 if(CallBack_Description[m_callback]) delete [] CallBack_Description[m_callback]; 00822 CallBack_Description[m_callback] = 0; 00823 CALLBACK_DeAllocate(m_callback); 00824 installed=false; 00825 } 00826 00827 CALLBACK_HandlerObject::~CALLBACK_HandlerObject(){ 00828 Uninstall(); 00829 } 00830 00831 void CALLBACK_HandlerObject::Install(CallBack_Handler handler,Bitu type,const char* description){ 00832 if(!installed) { 00833 installed=true; 00834 m_type=SETUP; 00835 m_callback=CALLBACK_Allocate(); 00836 CALLBACK_Setup(m_callback,handler,type,description); 00837 } else E_Exit("Callback handler object already installed"); 00838 } 00839 void CALLBACK_HandlerObject::Install(CallBack_Handler handler,Bitu type,PhysPt addr,const char* description){ 00840 if(!installed) { 00841 installed=true; 00842 m_type=SETUP; 00843 m_callback=CALLBACK_Allocate(); 00844 CALLBACK_Setup(m_callback,handler,type,addr,description); 00845 } else E_Exit("Callback handler object already installed"); 00846 } 00847 00848 void CALLBACK_HandlerObject::Allocate(CallBack_Handler handler,const char* description) { 00849 if(!installed) { 00850 installed=true; 00851 m_type=NONE; 00852 m_callback=CALLBACK_Allocate(); 00853 CALLBACK_SetDescription(m_callback,description); 00854 CallBack_Handlers[m_callback]=handler; 00855 } else E_Exit("Callback handler object already installed"); 00856 } 00857 00858 void CALLBACK_HandlerObject::Set_RealVec(Bit8u vec,bool reinstall){ 00859 if(!vectorhandler.installed || reinstall) { 00860 vectorhandler.installed=true; 00861 vectorhandler.interrupt=vec; 00862 RealSetVec(vec,Get_RealPointer(),vectorhandler.old_vector); 00863 } else E_Exit ("double usage of vector handler"); 00864 } 00865 00866 extern bool custom_bios; 00867 00868 void CALLBACK_Init() { 00869 { 00870 /* NTS: Layout of the callback area: 00871 * 00872 * CB_MAX entries CB_SIZE each, where executable x86 code is written per callback, 00873 * followed by 256 entries 6 bytes each corresponding to an interrupt call */ 00874 Bitu o; 00875 00876 LOG(LOG_MISC,LOG_DEBUG)("Initializing DOSBox callback instruction system"); 00877 00878 o = ROMBIOS_GetMemory((CB_MAX*CB_SIZE)+(256*6),"DOSBox callback area",/*align*/4); 00879 if (o == 0) E_Exit("Cannot allocate callback area"); 00880 CB_SOFFSET = o&0xFFFF; 00881 CB_SEG = (o>>4)&0xF000; 00882 if (((Bitu)CB_SOFFSET + (CB_MAX*CB_SIZE) + (256*6)) > 0x10000) E_Exit("Callback area spans 64KB segment"); 00883 00884 o = ROMBIOS_GetMemory(14/*2+2+3+2+2+3*/,"DOSBox vm86 hack",/*align*/4); 00885 if (o == 0) E_Exit("Cannot allocate vm86 hack"); 00886 vm86_fake_io_off = o&0xFFFF; 00887 vm86_fake_io_seg = (o>>4)&0xF000; 00888 if ((vm86_fake_io_off+14) > 0x1000000) E_Exit("vm86 area spans 64KB segment"); 00889 } 00890 00891 LOG(LOG_CPU,LOG_DEBUG)("Callback area starts at %04x:%04x",CB_SEG,CB_SOFFSET); 00892 00893 Bit16u i; 00894 for (i=0;i<CB_MAX;i++) { 00895 CallBack_Handlers[i]=&illegal_handler; 00896 CallBack_Description[i]=NULL; 00897 } 00898 00899 /* Setup the Stop Handler */ 00900 call_stop=CALLBACK_Allocate(); 00901 CallBack_Handlers[call_stop]=stop_handler; 00902 CALLBACK_SetDescription(call_stop,"stop"); 00903 phys_writeb(CALLBACK_PhysPointer(call_stop)+0,0xFE); 00904 phys_writeb(CALLBACK_PhysPointer(call_stop)+1,0x38); 00905 phys_writew(CALLBACK_PhysPointer(call_stop)+2,(Bit16u)call_stop); 00906 00907 /* Setup the idle handler */ 00908 call_idle=CALLBACK_Allocate(); 00909 CallBack_Handlers[call_idle]=stop_handler; 00910 CALLBACK_SetDescription(call_idle,"idle"); 00911 for (i=0;i<=11;i++) phys_writeb(CALLBACK_PhysPointer(call_idle)+i,0x90); 00912 phys_writeb(CALLBACK_PhysPointer(call_idle)+12,0xFE); 00913 phys_writeb(CALLBACK_PhysPointer(call_idle)+13,0x38); 00914 phys_writew(CALLBACK_PhysPointer(call_idle)+14,(Bit16u)call_idle); 00915 00916 /* Default handlers for unhandled interrupts that have to be non-null */ 00917 call_default=CALLBACK_Allocate(); 00918 CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default"); 00919 00920 /* Setup block of 0xCD 0xxx instructions */ 00921 PhysPt rint_base=CALLBACK_GetBase()+CB_MAX*CB_SIZE; 00922 for (i=0;i<=0xff;i++) { 00923 phys_writeb(rint_base,0xCD); 00924 phys_writeb(rint_base+1,(Bit8u)i); 00925 phys_writeb(rint_base+2,0xFE); 00926 phys_writeb(rint_base+3,0x38); 00927 phys_writew(rint_base+4,(Bit16u)call_stop); 00928 rint_base+=6; 00929 00930 } 00931 00932 call_priv_io=CALLBACK_Allocate(); 00933 00934 // virtualizable in-out opcodes 00935 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x00,(Bit8u)0xec); // in al, dx 00936 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x01,(Bit8u)0xcb); // retf 00937 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x02,(Bit8u)0xed); // in ax, dx 00938 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x03,(Bit8u)0xcb); // retf 00939 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x04,(Bit8u)0x66); // in eax, dx 00940 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x05,(Bit8u)0xed); 00941 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x06,(Bit8u)0xcb); // retf 00942 00943 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x08,(Bit8u)0xee); // out dx, al 00944 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x09,(Bit8u)0xcb); // retf 00945 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0a,(Bit8u)0xef); // out dx, ax 00946 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0b,(Bit8u)0xcb); // retf 00947 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0c,(Bit8u)0x66); // out dx, eax 00948 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0d,(Bit8u)0xef); 00949 phys_writeb(CALLBACK_PhysPointer(call_priv_io)+0x0e,(Bit8u)0xcb); // retf 00950 }