diff --git a/subsystems/ntvdm/bios.c b/subsystems/ntvdm/bios.c index 44803f19a59..b105465e5a4 100644 --- a/subsystems/ntvdm/bios.c +++ b/subsystems/ntvdm/bios.c @@ -10,8 +10,10 @@ #define NDEBUG -#include "bios.h" #include "emulator.h" +#include "bop.h" + +#include "bios.h" #include "vga.h" #include "pic.h" #include "ps2.h" @@ -461,7 +463,7 @@ BOOLEAN BiosInitialize(VOID) { USHORT i; WORD Offset = 0; - LPWORD IntVecTable = (LPWORD)BaseAddress; + LPDWORD IntVecTable = (LPDWORD)BaseAddress; LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0); /* Initialize the BDA */ @@ -480,8 +482,7 @@ BOOLEAN BiosInitialize(VOID) /* Generate ISR stubs and fill the IVT */ for (i = 0x00; i <= 0xFF; i++) { - IntVecTable[i * 2] = Offset; - IntVecTable[i * 2 + 1] = BIOS_SEGMENT; + IntVecTable[i] = MAKELONG(Offset, BIOS_SEGMENT); BiosCode[Offset++] = 0xFB; // sti @@ -494,9 +495,10 @@ BOOLEAN BiosInitialize(VOID) // BOP_SEQ: BiosCode[Offset++] = 0xF8; // clc - BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence + BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence BiosCode[Offset++] = HIBYTE(EMULATOR_BOP); - BiosCode[Offset++] = EMULATOR_INT_BOP; + BiosCode[Offset++] = EMULATOR_CTRL_BOP; // Control BOP + BiosCode[Offset++] = CTRL_BOP_INT32; // 32-bit Interrupt dispatcher BiosCode[Offset++] = 0x73; // jnc EXIT (offset +3) BiosCode[Offset++] = 0x03; @@ -504,8 +506,8 @@ BOOLEAN BiosInitialize(VOID) // HACK: The following instruction should be HLT! BiosCode[Offset++] = 0x90; // nop - BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -9) - BiosCode[Offset++] = 0xF7; + BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -10) + BiosCode[Offset++] = 0xF6; // EXIT: BiosCode[Offset++] = 0x83; // add sp, 4 @@ -514,6 +516,12 @@ BOOLEAN BiosInitialize(VOID) BiosCode[Offset++] = 0xCF; // iret } + RegisterInt32(BIOS_VIDEO_INTERRUPT , BiosVideoService ); + RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService ); + RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize ); + RegisterInt32(BIOS_KBD_INTERRUPT , BiosKeyboardService ); + RegisterInt32(BIOS_TIME_INTERRUPT , BiosTimeService ); + RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt); /* Get the input handle to the real console, and check for success */ BiosConsoleInput = CreateFileW(L"CONIN$", @@ -818,7 +826,7 @@ VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page) BiosSetCursorPosition(Row, Column, Page); } -VOID BiosVideoService(LPWORD Stack) +VOID WINAPI BiosVideoService(LPWORD Stack) { switch (getAH()) { @@ -1194,19 +1202,19 @@ VOID BiosVideoService(LPWORD Stack) } } -VOID BiosEquipmentService(LPWORD Stack) +VOID WINAPI BiosEquipmentService(LPWORD Stack) { /* Return the equipment list */ setAX(Bda->EquipmentList); } -VOID BiosGetMemorySize(LPWORD Stack) +VOID WINAPI BiosGetMemorySize(LPWORD Stack) { /* Return the conventional memory size in kB, typically 640 kB */ setAX(Bda->MemorySize); } -VOID BiosKeyboardService(LPWORD Stack) +VOID WINAPI BiosKeyboardService(LPWORD Stack) { switch (getAH()) { @@ -1288,7 +1296,7 @@ VOID BiosKeyboardService(LPWORD Stack) } } -VOID BiosTimeService(LPWORD Stack) +VOID WINAPI BiosTimeService(LPWORD Stack) { switch (getAH()) { @@ -1326,7 +1334,7 @@ VOID BiosTimeService(LPWORD Stack) } } -VOID BiosSystemTimerInterrupt(LPWORD Stack) +VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack) { /* Increase the system tick count */ Bda->TickCounter++; diff --git a/subsystems/ntvdm/bios.h b/subsystems/ntvdm/bios.h index 7fb2c1636ee..e89292d0c2f 100644 --- a/subsystems/ntvdm/bios.h +++ b/subsystems/ntvdm/bios.h @@ -159,13 +159,6 @@ WORD BiosPeekCharacter(VOID); WORD BiosGetCharacter(VOID); VOID BiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page); VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page); -VOID BiosVideoService(LPWORD Stack); -VOID BiosEquipmentService(LPWORD Stack); -VOID BiosGetMemorySize(LPWORD Stack); -VOID BiosKeyboardService(LPWORD Stack); -VOID BiosTimeService(LPWORD Stack); -VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack); -VOID BiosSystemTimerInterrupt(LPWORD Stack); VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page); BOOLEAN BiosScrollWindow( INT Direction, @@ -175,6 +168,15 @@ BOOLEAN BiosScrollWindow( BYTE FillAttribute ); +VOID WINAPI BiosVideoService(LPWORD Stack); +VOID WINAPI BiosEquipmentService(LPWORD Stack); +VOID WINAPI BiosGetMemorySize(LPWORD Stack); +VOID WINAPI BiosKeyboardService(LPWORD Stack); +VOID WINAPI BiosTimeService(LPWORD Stack); +VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack); + +VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack); + #endif // _BIOS_H_ /* EOF */ diff --git a/subsystems/ntvdm/bop.c b/subsystems/ntvdm/bop.c index f12ffd12430..a96d3d892b6 100644 --- a/subsystems/ntvdm/bop.c +++ b/subsystems/ntvdm/bop.c @@ -12,13 +12,10 @@ #define NDEBUG #include "emulator.h" -#include "bios.h" #include "bop.h" + +#include "bios.h" #include "dos.h" -//#include "vga.h" -//#include "pic.h" -//#include "ps2.h" -//#include "timer.h" #include "registers.h" LPCWSTR ExceptionName[] = @@ -33,6 +30,9 @@ LPCWSTR ExceptionName[] = L"FPU Not Available" }; +/* + * This is the list of registered BOP handlers. + */ EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] = { NULL, @@ -293,6 +293,271 @@ EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM] = ControlBop }; +/* + * This is the list of registered 32-bit Interrupt handlers. + */ +EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT_NUM] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + + VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack) { WORD CodeSegment, InstructionPointer; @@ -344,11 +609,7 @@ VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack) // return; // } -// VOID WINAPI BiosInt(BYTE IntNumber, LPWORD Stack) -// { -// } - -VOID WINAPI IntDispatch(LPWORD Stack) +VOID WINAPI Int32Dispatch(LPWORD Stack) { BYTE IntNum; @@ -376,77 +637,48 @@ VOID WINAPI IntDispatch(LPWORD Stack) return; } - switch (IntNum) - { - case BIOS_VIDEO_INTERRUPT: - { - /* This is the video BIOS interrupt, call the BIOS */ - BiosVideoService(Stack); - break; - } - case BIOS_EQUIPMENT_INTERRUPT: - { - /* This is the BIOS "get equipment" command, call the BIOS */ - BiosEquipmentService(Stack); - break; - } - case BIOS_MEMORY_SIZE: - { - /* This is the BIOS "get memory size" command, call the BIOS */ - BiosGetMemorySize(Stack); - break; - } - case BIOS_KBD_INTERRUPT: - { - /* This is the keyboard BIOS interrupt, call the BIOS */ - BiosKeyboardService(Stack); - break; - } - case BIOS_TIME_INTERRUPT: - { - /* This is the time BIOS interrupt, call the BIOS */ - BiosTimeService(Stack); - break; - } - case BIOS_SYS_TIMER_INTERRUPT: - { - /* BIOS timer update */ - BiosSystemTimerInterrupt(Stack); - break; - } - case 0x20: - { - DosInt20h(Stack); - break; - } - case 0x21: - { - DosInt21h(Stack); - break; - } - case 0x23: - { - DosBreakInterrupt(Stack); - break; - } - case 0x2F: - { - DPRINT1("DOS System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n", - getAH(), getAL()); - Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; - break; - } - default: - { - DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum); - break; - } - } + /* Call the 32-bit Interrupt handler */ + if (Int32Proc[IntNum] != NULL) + Int32Proc[IntNum](Stack); + else + DPRINT1("Unhandled 32-bit interrupt: 0x%02X\n", IntNum); } VOID WINAPI ControlBop(LPWORD Stack) { - IntDispatch(Stack); + /* Get the Function Number and skip it */ + BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP()); + setIP(getIP() + 1); + + if (FuncNum == CTRL_BOP_INT32) + Int32Dispatch(Stack); + else + DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum); +} + + +VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler) +{ + Int32Proc[IntNumber] = IntHandler; +} + +VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode) +{ + WORD StackSegment, StackPointer; + LPWORD Stack; + + /* Get the SS:SP */ + StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector; + StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord; + + /* Get the stack */ + Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer); + + /* Call the BOP handler */ + if (BopProc[BopCode] != NULL) + BopProc[BopCode](Stack); + else + DPRINT1("Invalid BOP code: 0x%02X\n", BopCode); } /* EOF */ diff --git a/subsystems/ntvdm/bop.h b/subsystems/ntvdm/bop.h index 61a45eb3ba3..12ebf275ff2 100644 --- a/subsystems/ntvdm/bop.h +++ b/subsystems/ntvdm/bop.h @@ -7,10 +7,33 @@ * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ -typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack); +#ifndef _BOP_H_ +#define _BOP_H_ -extern EMULATOR_BOP_PROC BopProc[EMULATOR_MAX_BOP_NUM]; +/* DEFINES ********************************************************************/ + +/* BOP Identifiers */ +#define EMULATOR_BOP 0xC4C4 + +#define EMULATOR_CTRL_BOP 0xFF // Control BOP Handler + #define CTRL_BOP_DEFLT 0x00 // Default Control BOP Function + #define CTRL_BOP_INT32 0xFF // 32-bit Interrupt dispatcher + +#define EMULATOR_MAX_BOP_NUM 0xFF + 1 + +/* 32-bit Interrupt Identifiers */ +#define EMULATOR_MAX_INT_NUM 0xFF + 1 + +/* FUNCTIONS ******************************************************************/ + +typedef VOID (WINAPI *EMULATOR_BOP_PROC)(LPWORD Stack); +typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack); VOID WINAPI ControlBop(LPWORD Stack); +VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler); +VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode); + +#endif // _BOP_H_ + /* EOF */ diff --git a/subsystems/ntvdm/dos.c b/subsystems/ntvdm/dos.c index f56ed764d98..027ea3e5474 100644 --- a/subsystems/ntvdm/dos.c +++ b/subsystems/ntvdm/dos.c @@ -10,9 +10,11 @@ #define NDEBUG +#include "emulator.h" +#include "bop.h" + #include "dos.h" #include "bios.h" -#include "emulator.h" #include "registers.h" @@ -1393,13 +1395,13 @@ BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle) } } -VOID DosInt20h(LPWORD Stack) +VOID WINAPI DosInt20h(LPWORD Stack) { /* This is the exit interrupt */ DosTerminateProcess(Stack[STACK_CS], 0); } -VOID DosInt21h(LPWORD Stack) +VOID WINAPI DosInt21h(LPWORD Stack) { BYTE Character; SYSTEMTIME SystemTime; @@ -2415,13 +2417,20 @@ VOID DosInt21h(LPWORD Stack) } } -VOID DosBreakInterrupt(LPWORD Stack) +VOID WINAPI DosBreakInterrupt(LPWORD Stack) { UNREFERENCED_PARAMETER(Stack); VdmRunning = FALSE; } +VOID WINAPI DosInt2Fh(LPWORD Stack) +{ + DPRINT1("DOS System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n", + getAH(), getAL()); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; +} + BOOLEAN DosInitialize(VOID) { BYTE i; @@ -2561,6 +2570,12 @@ BOOLEAN DosInitialize(VOID) DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE); DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE); + /* Register the DOS-32 Interrupts */ + RegisterInt32(0x20, DosInt20h ); + RegisterInt32(0x21, DosInt21h ); + RegisterInt32(0x23, DosBreakInterrupt); + RegisterInt32(0x2F, DosInt2Fh ); + return TRUE; } diff --git a/subsystems/ntvdm/dos.h b/subsystems/ntvdm/dos.h index 880ac6629e0..0ec0d83275b 100644 --- a/subsystems/ntvdm/dos.h +++ b/subsystems/ntvdm/dos.h @@ -136,9 +136,12 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode); CHAR DosReadCharacter(VOID); VOID DosPrintCharacter(CHAR Character); BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle); -VOID DosInt20h(LPWORD Stack); -VOID DosInt21h(LPWORD Stack); -VOID DosBreakInterrupt(LPWORD Stack); + +VOID WINAPI DosInt20h(LPWORD Stack); +VOID WINAPI DosInt21h(LPWORD Stack); +VOID WINAPI DosBreakInterrupt(LPWORD Stack); +VOID WINAPI DosInt2Fh(LPWORD Stack); + BOOLEAN DosInitialize(VOID); #endif // _DOS_H_ diff --git a/subsystems/ntvdm/emulator.c b/subsystems/ntvdm/emulator.c index 42dc841f752..742112c4cbe 100644 --- a/subsystems/ntvdm/emulator.c +++ b/subsystems/ntvdm/emulator.c @@ -272,24 +272,6 @@ VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULON } } -VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode) -{ - WORD StackSegment, StackPointer; - LPWORD Stack; - - /* Get the SS:SP */ - StackSegment = State->SegmentRegs[FAST486_REG_SS].Selector; - StackPointer = State->GeneralRegs[FAST486_REG_ESP].LowWord; - - /* Get the stack */ - Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer); - - if (BopProc[BopCode] != NULL) - BopProc[BopCode](Stack); - else - DPRINT1("Invalid BOP code %u\n", BopCode); -} - UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State) { UNREFERENCED_PARAMETER(State); diff --git a/subsystems/ntvdm/emulator.h b/subsystems/ntvdm/emulator.h index 877f01e7ab4..742079ed6e3 100644 --- a/subsystems/ntvdm/emulator.h +++ b/subsystems/ntvdm/emulator.h @@ -120,12 +120,6 @@ VOID WINAPI EmulatorWriteIo UCHAR DataSize ); -VOID WINAPI EmulatorBiosOperation -( - PFAST486_STATE State, - UCHAR BopCode -); - UCHAR WINAPI EmulatorIntAcknowledge ( PFAST486_STATE State