diff --git a/subsystems/ntvdm/CMakeLists.txt b/subsystems/ntvdm/CMakeLists.txt index 9d1bc8b31ef..45bf971d23d 100644 --- a/subsystems/ntvdm/CMakeLists.txt +++ b/subsystems/ntvdm/CMakeLists.txt @@ -6,15 +6,16 @@ spec2def(ntvdm.exe ntvdm.spec) list(APPEND SOURCE bios.c bop.c + cmos.c dos.c emulator.c + int32.c pic.c - registers.c - timer.c ps2.c + registers.c speaker.c + timer.c vga.c - cmos.c ntvdm.c ntvdm.rc ${CMAKE_CURRENT_BINARY_DIR}/ntvdm.def) diff --git a/subsystems/ntvdm/bios.c b/subsystems/ntvdm/bios.c index b105465e5a4..6f026e61af1 100644 --- a/subsystems/ntvdm/bios.c +++ b/subsystems/ntvdm/bios.c @@ -11,14 +11,14 @@ #define NDEBUG #include "emulator.h" -#include "bop.h" - #include "bios.h" + #include "vga.h" #include "pic.h" #include "ps2.h" #include "timer.h" +#include "int32.h" #include "registers.h" /* PRIVATE VARIABLES **********************************************************/ @@ -461,11 +461,6 @@ BOOLEAN BiosSetVideoPage(BYTE PageNumber) BOOLEAN BiosInitialize(VOID) { - USHORT i; - WORD Offset = 0; - LPDWORD IntVecTable = (LPDWORD)BaseAddress; - LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0); - /* Initialize the BDA */ Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0); Bda->EquipmentList = BIOS_EQUIPMENT_LIST; @@ -479,43 +474,10 @@ BOOLEAN BiosInitialize(VOID) Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer); Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD); - /* Generate ISR stubs and fill the IVT */ - for (i = 0x00; i <= 0xFF; i++) - { - IntVecTable[i] = MAKELONG(Offset, BIOS_SEGMENT); + /* Initialize the 32-bit Interrupt system */ + InitializeInt32(BIOS_SEGMENT); - BiosCode[Offset++] = 0xFB; // sti - - BiosCode[Offset++] = 0x6A; // push i - BiosCode[Offset++] = (UCHAR)i; - - BiosCode[Offset++] = 0x6A; // push 0 - BiosCode[Offset++] = 0x00; - -// BOP_SEQ: - BiosCode[Offset++] = 0xF8; // clc - - BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence - BiosCode[Offset++] = HIBYTE(EMULATOR_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; - - // HACK: The following instruction should be HLT! - BiosCode[Offset++] = 0x90; // nop - - BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -10) - BiosCode[Offset++] = 0xF6; - -// EXIT: - BiosCode[Offset++] = 0x83; // add sp, 4 - BiosCode[Offset++] = 0xC4; - BiosCode[Offset++] = 0x04; - - BiosCode[Offset++] = 0xCF; // iret - } + /* Register the BIOS 32-bit Interrupts */ RegisterInt32(BIOS_VIDEO_INTERRUPT , BiosVideoService ); RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService ); RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize ); diff --git a/subsystems/ntvdm/bop.c b/subsystems/ntvdm/bop.c index a96d3d892b6..5904030de51 100644 --- a/subsystems/ntvdm/bop.c +++ b/subsystems/ntvdm/bop.c @@ -14,21 +14,10 @@ #include "emulator.h" #include "bop.h" -#include "bios.h" -#include "dos.h" +#include "int32.h" #include "registers.h" -LPCWSTR ExceptionName[] = -{ - L"Division By Zero", - L"Debug", - L"Unexpected Error", - L"Breakpoint", - L"Integer Overflow", - L"Bound Range Exceeded", - L"Invalid Opcode", - L"FPU Not Available" -}; +/* PRIVATE VARIABLES **********************************************************/ /* * This is the list of registered BOP handlers. @@ -293,356 +282,7 @@ 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; - PBYTE Opcode; - - ASSERT(ExceptionNumber < 8); - - /* Get the CS:IP */ - InstructionPointer = Stack[STACK_IP]; - CodeSegment = Stack[STACK_CS]; - Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer); - - /* Display a message to the user */ - DisplayMessage(L"Exception: %s occured at %04X:%04X\n" - L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", - ExceptionName[ExceptionNumber], - CodeSegment, - InstructionPointer, - Opcode[0], - Opcode[1], - Opcode[2], - Opcode[3], - Opcode[4], - Opcode[5], - Opcode[6], - Opcode[7], - Opcode[8], - Opcode[9]); - - /* Stop the VDM */ - VdmRunning = FALSE; - return; -} - -// VOID WINAPI IrqDispatch(BYTE IrqNumber, LPWORD Stack) -// { - // /* Check if this was an PIC IRQ */ - // if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8) - // { - // /* It was an IRQ from the master PIC */ - // BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack); - // } - // else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) - // { - // /* It was an IRQ from the slave PIC */ - // BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack); - // } - - // return; -// } - -VOID WINAPI Int32Dispatch(LPWORD Stack) -{ - BYTE IntNum; - - /* Get the interrupt number */ - IntNum = LOBYTE(Stack[STACK_INT_NUM]); - - /* Check if this was an exception */ - if (IntNum < 8) - { - Exception(IntNum, Stack); - return; - } - - /* Check if this was an PIC IRQ */ - if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8) - { - /* It was an IRQ from the master PIC */ - BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack); - return; - } - else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) - { - /* It was an IRQ from the slave PIC */ - BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack); - return; - } - - /* Call the 32-bit Interrupt handler */ - if (Int32Proc[IntNum] != NULL) - Int32Proc[IntNum](Stack); - else - DPRINT1("Unhandled 32-bit interrupt: 0x%02X\n", IntNum); -} +/* PUBLIC FUNCTIONS ***********************************************************/ VOID WINAPI ControlBop(LPWORD Stack) { @@ -656,12 +296,6 @@ VOID WINAPI ControlBop(LPWORD Stack) 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; diff --git a/subsystems/ntvdm/bop.h b/subsystems/ntvdm/bop.h index 12ebf275ff2..f176395c566 100644 --- a/subsystems/ntvdm/bop.h +++ b/subsystems/ntvdm/bop.h @@ -17,21 +17,14 @@ #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_ diff --git a/subsystems/ntvdm/dos.c b/subsystems/ntvdm/dos.c index 027ea3e5474..7b394849937 100644 --- a/subsystems/ntvdm/dos.c +++ b/subsystems/ntvdm/dos.c @@ -11,11 +11,10 @@ #define NDEBUG #include "emulator.h" -#include "bop.h" - #include "dos.h" -#include "bios.h" +#include "bios.h" +#include "int32.h" #include "registers.h" /* PRIVATE VARIABLES **********************************************************/ @@ -2570,7 +2569,7 @@ BOOLEAN DosInitialize(VOID) DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE); DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE); - /* Register the DOS-32 Interrupts */ + /* Register the DOS 32-bit Interrupts */ RegisterInt32(0x20, DosInt20h ); RegisterInt32(0x21, DosInt21h ); RegisterInt32(0x23, DosBreakInterrupt); diff --git a/subsystems/ntvdm/emulator.h b/subsystems/ntvdm/emulator.h index 742079ed6e3..aa5243b547f 100644 --- a/subsystems/ntvdm/emulator.h +++ b/subsystems/ntvdm/emulator.h @@ -34,11 +34,6 @@ #define EMULATOR_FLAG_VIP (1 << 20) #define EMULATOR_FLAG_ID (1 << 21) -/* Common definitions */ -#define EMULATOR_BOP 0xC4C4 -#define EMULATOR_INT_BOP 0xFF -#define EMULATOR_MAX_BOP_NUM 0xFF + 1 - #define STACK_COUNTER 0 #define STACK_INT_NUM 1 #define STACK_IP 2 diff --git a/subsystems/ntvdm/int32.c b/subsystems/ntvdm/int32.c new file mode 100644 index 00000000000..8e039333587 --- /dev/null +++ b/subsystems/ntvdm/int32.c @@ -0,0 +1,181 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: int32.c + * PURPOSE: 32-bit Interrupt Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "int32.h" + +#include "bop.h" +#include "bios.h" + +/* PRIVATE VARIABLES **********************************************************/ + +LPCWSTR ExceptionName[] = +{ + L"Division By Zero", + L"Debug", + L"Unexpected Error", + L"Breakpoint", + L"Integer Overflow", + L"Bound Range Exceeded", + L"Invalid Opcode", + L"FPU Not Available" +}; + +/* + * This is the list of registered 32-bit Interrupt handlers. + */ +EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL }; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack) +{ + WORD CodeSegment, InstructionPointer; + PBYTE Opcode; + + ASSERT(ExceptionNumber < 8); + + /* Get the CS:IP */ + InstructionPointer = Stack[STACK_IP]; + CodeSegment = Stack[STACK_CS]; + Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer); + + /* Display a message to the user */ + DisplayMessage(L"Exception: %s occured at %04X:%04X\n" + L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + ExceptionName[ExceptionNumber], + CodeSegment, + InstructionPointer, + Opcode[0], + Opcode[1], + Opcode[2], + Opcode[3], + Opcode[4], + Opcode[5], + Opcode[6], + Opcode[7], + Opcode[8], + Opcode[9]); + + /* Stop the VDM */ + VdmRunning = FALSE; + return; +} + +#if 0 +VOID WINAPI IrqDispatch(BYTE IrqNumber, LPWORD Stack) +{ + /* Check if this was an PIC IRQ */ + if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8) + { + /* It was an IRQ from the master PIC */ + BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack); + } + else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) + { + /* It was an IRQ from the slave PIC */ + BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack); + } + + return; +} +#endif + +VOID WINAPI Int32Dispatch(LPWORD Stack) +{ + BYTE IntNum; + + /* Get the interrupt number */ + IntNum = LOBYTE(Stack[STACK_INT_NUM]); + + /* Check if this was an exception */ + if (IntNum < 8) + { + Exception(IntNum, Stack); + return; + } + + /* Check if this was an PIC IRQ */ + if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8) + { + /* It was an IRQ from the master PIC */ + BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack); + return; + } + else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) + { + /* It was an IRQ from the slave PIC */ + BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack); + return; + } + + /* 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 InitializeInt32(WORD BiosSegment) +{ + USHORT i; + WORD Offset = 0; + + LPDWORD IntVecTable = (LPDWORD)BaseAddress; + LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0); + + /* Generate ISR stubs and fill the IVT */ + for (i = 0x00; i <= 0xFF; i++) + { + IntVecTable[i] = MAKELONG(Offset, BiosSegment); + + BiosCode[Offset++] = 0xFB; // sti + + BiosCode[Offset++] = 0x6A; // push i + BiosCode[Offset++] = (UCHAR)i; + + BiosCode[Offset++] = 0x6A; // push 0 + BiosCode[Offset++] = 0x00; + +// BOP_SEQ: + BiosCode[Offset++] = 0xF8; // clc + + BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence + BiosCode[Offset++] = HIBYTE(EMULATOR_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; + + // HACK: The following instruction should be HLT! + BiosCode[Offset++] = 0x90; // nop + + BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -10) + BiosCode[Offset++] = 0xF6; + +// EXIT: + BiosCode[Offset++] = 0x83; // add sp, 4 + BiosCode[Offset++] = 0xC4; + BiosCode[Offset++] = 0x04; + + BiosCode[Offset++] = 0xCF; // iret + } +} + +VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler) +{ + Int32Proc[IntNumber] = IntHandler; +} + +/* EOF */ diff --git a/subsystems/ntvdm/int32.h b/subsystems/ntvdm/int32.h new file mode 100644 index 00000000000..0738b0d8469 --- /dev/null +++ b/subsystems/ntvdm/int32.h @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: int32.h + * PURPOSE: 32-bit Interrupt Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +#ifndef _INT32_H_ +#define _INT32_H_ + +/* DEFINES ********************************************************************/ + +/* 32-bit Interrupt dispatcher function code for the Control BOP Handler */ +#define CTRL_BOP_INT32 0xFF + +/* 32-bit Interrupt Identifiers */ +#define EMULATOR_MAX_INT32_NUM 0xFF + 1 + +/* FUNCTIONS ******************************************************************/ + +typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack); + +VOID WINAPI Int32Dispatch(LPWORD Stack); +VOID WINAPI InitializeInt32(WORD BiosSegment); +VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler); + +#endif // _INT32_H_ + +/* EOF */ diff --git a/subsystems/ntvdm/ntvdm.h b/subsystems/ntvdm/ntvdm.h index 0ae0747d8b0..2c2b5e1a0b1 100644 --- a/subsystems/ntvdm/ntvdm.h +++ b/subsystems/ntvdm/ntvdm.h @@ -39,7 +39,6 @@ extern LPVOID BaseAddress; extern BOOLEAN VdmRunning; -extern LPCWSTR ExceptionName[]; VOID DisplayMessage(LPCWSTR Format, ...);