Remove INT 16h when entering PC-98 mode. DOS CONIO emulation calls INT

16h handler directly (well... somewhat indirectly due to how INT16h
expects to implement idle). INT 10h-17h are now zeroed out in PC-98
mode.
This commit is contained in:
Jonathan Campbell 2017-11-13 15:45:41 -08:00
parent e67e49ccd1
commit dce1c911d9
4 changed files with 65 additions and 7 deletions

View File

@ -65,6 +65,7 @@ void CALLBACK_Idle(void);
void CALLBACK_RunRealInt(Bit8u intnum); void CALLBACK_RunRealInt(Bit8u intnum);
void CALLBACK_RunRealFar(Bit16u seg,Bit16u off); void CALLBACK_RunRealFar(Bit16u seg,Bit16u off);
void CALLBACK_RunRealFarInt(Bit16u seg,Bit16u off);
bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr); bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr);
Bitu CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,PhysPt addr,const char* descr); Bitu CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,PhysPt addr,const char* descr);

View File

@ -114,7 +114,23 @@ static Bitu stop_handler(void) {
return CBRET_STOP; return CBRET_STOP;
} }
Bitu FillFlags(void);
void CALLBACK_RunRealFarInt(Bit16u seg,Bit16u off) {
FillFlags();
reg_sp-=6;
mem_writew(SegPhys(ss)+reg_sp,RealOff(CALLBACK_RealPointer(call_stop)));
mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(CALLBACK_RealPointer(call_stop)));
mem_writew(SegPhys(ss)+reg_sp+4,reg_flags);
Bit32u oldeip=reg_eip;
Bit16u oldcs=SegValue(cs);
reg_eip=off;
SegSet16(cs,seg);
DOSBOX_RunMachine();
reg_eip=oldeip;
SegSet16(cs,oldcs);
}
void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) { void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) {
reg_sp-=4; reg_sp-=4;

View File

@ -28,6 +28,7 @@
extern bool DOS_BreakFlag; extern bool DOS_BreakFlag;
Bitu INT10_Handler(void); Bitu INT10_Handler(void);
Bitu INT16_Handler_Wrap(void);
class device_CON : public DOS_Device { class device_CON : public DOS_Device {
public: public:
@ -223,7 +224,16 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
} }
while (*size>count) { while (*size>count) {
reg_ah=(IS_EGAVGA_ARCH)?0x10:0x0; reg_ah=(IS_EGAVGA_ARCH)?0x10:0x0;
CALLBACK_RunRealInt(0x16);
/* FIXME: PC-98 emulation should eventually use CONIO emulation that
* better emulates the actual platform. The purpose of this
* hack is to allow our code to call into INT 16h without
* setting up an INT 16h vector */
if (IS_PC98_ARCH)
INT16_Handler_Wrap();
else
CALLBACK_RunRealInt(0x16);
switch(reg_al) { switch(reg_al) {
case 13: case 13:
data[count++]=0x0D; data[count++]=0x0D;
@ -570,7 +580,16 @@ Bit16u device_CON::GetInformation(void) {
Bitu saved_ax = reg_ax; Bitu saved_ax = reg_ax;
reg_ah = (IS_EGAVGA_ARCH)?0x11:0x1; // check for keystroke reg_ah = (IS_EGAVGA_ARCH)?0x11:0x1; // check for keystroke
CALLBACK_RunRealInt(0x16);
/* FIXME: PC-98 emulation should eventually use CONIO emulation that
* better emulates the actual platform. The purpose of this
* hack is to allow our code to call into INT 16h without
* setting up an INT 16h vector */
if (IS_PC98_ARCH)
INT16_Handler_Wrap();
else
CALLBACK_RunRealInt(0x16);
if (!GETFLAG(ZF)) { /* key is present, waiting to be returned on AH=0x10 or AH=0x00 */ if (!GETFLAG(ZF)) { /* key is present, waiting to be returned on AH=0x10 or AH=0x00 */
ret = 0x8093; /* Key Available */ ret = 0x8093; /* Key Available */
} }

View File

@ -532,7 +532,7 @@ static bool IsEnhancedKey(Bit16u &key) {
bool int16_unmask_irq1_on_read = true; bool int16_unmask_irq1_on_read = true;
bool int16_ah_01_cf_undoc = true; bool int16_ah_01_cf_undoc = true;
static Bitu INT16_Handler(void) { Bitu INT16_Handler(void) {
Bit16u temp=0; Bit16u temp=0;
switch (reg_ah) { switch (reg_ah) {
case 0x00: /* GET KEYSTROKE */ case 0x00: /* GET KEYSTROKE */
@ -643,6 +643,18 @@ static Bitu INT16_Handler(void) {
return CBRET_NONE; return CBRET_NONE;
} }
/* The INT16h handler manipulates reg_ip and expects it to work
* based on the layout of the callback. So to allow calling
* directly we have to save/restore CS:IP and run the DOS
* machine. */
Bitu INT16_Handler_Wrap(void) {
Bitu proc;
proc = CALLBACK_RealPointer(call_int16);
CALLBACK_RunRealFarInt(proc >> 16/*seg*/,proc & 0xFFFFU/*off*/);
return 0;
}
//Keyboard initialisation. src/gui/sdlmain.cpp //Keyboard initialisation. src/gui/sdlmain.cpp
extern bool startup_state_numlock; extern bool startup_state_numlock;
extern bool startup_state_capslock; extern bool startup_state_capslock;
@ -675,6 +687,7 @@ void CALLBACK_DeAllocate(Bitu in);
void BIOS_UnsetupKeyboard(void) { void BIOS_UnsetupKeyboard(void) {
if (call_int16 != 0) { if (call_int16 != 0) {
CALLBACK_DeAllocate(call_int16); CALLBACK_DeAllocate(call_int16);
RealSetVec(0x16,0);
call_int16 = 0; call_int16 = 0;
} }
if (call_irq1 != 0) { if (call_irq1 != 0) {
@ -695,10 +708,19 @@ void BIOS_SetupKeyboard(void) {
/* Init the variables */ /* Init the variables */
InitBiosSegment(); InitBiosSegment();
/* Allocate/setup a callback for int 0x16 and for standard IRQ 1 handler */ if (IS_PC98_ARCH) {
call_int16=CALLBACK_Allocate(); /* HACK */
CALLBACK_Setup(call_int16,&INT16_Handler,CB_INT16,"Keyboard"); /* Allocate/setup a callback for int 0x16 and for standard IRQ 1 handler */
RealSetVec(0x16,CALLBACK_RealPointer(call_int16)); call_int16=CALLBACK_Allocate();
CALLBACK_Setup(call_int16,&INT16_Handler,CB_INT16,"Keyboard");
/* DO NOT set up an INT 16h vector. This exists only for the DOS CONIO emulation. */
}
else {
/* Allocate/setup a callback for int 0x16 and for standard IRQ 1 handler */
call_int16=CALLBACK_Allocate();
CALLBACK_Setup(call_int16,&INT16_Handler,CB_INT16,"Keyboard");
RealSetVec(0x16,CALLBACK_RealPointer(call_int16));
}
call_irq1=CALLBACK_Allocate(); call_irq1=CALLBACK_Allocate();
if (machine == MCH_PCJR) { /* PCjr keyboard interrupt connected to NMI */ if (machine == MCH_PCJR) { /* PCjr keyboard interrupt connected to NMI */