diff --git a/include/reactos/libs/fast486/fast486.h b/include/reactos/libs/fast486/fast486.h index 61d176eea6a..6076e666b48 100644 --- a/include/reactos/libs/fast486/fast486.h +++ b/include/reactos/libs/fast486/fast486.h @@ -210,7 +210,7 @@ VOID (NTAPI *FAST486_BOP_PROC) ( PFAST486_STATE State, - USHORT BopCode + UCHAR BopCode ); typedef diff --git a/lib/fast486/opcodes.c b/lib/fast486/opcodes.c index 7eb974f868c..81848a9b245 100644 --- a/lib/fast486/opcodes.c +++ b/lib/fast486/opcodes.c @@ -4331,10 +4331,10 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLdsLes) && (ModRegRm.SecondRegister == FAST486_REG_ESP) && (State->BopCallback != NULL)) { - USHORT BopCode; + UCHAR BopCode; /* Fetch the BOP code */ - if (!Fast486FetchWord(State, &BopCode)) + if (!Fast486FetchByte(State, &BopCode)) { /* Exception occurred */ return FALSE; diff --git a/subsystems/ntvdm/CMakeLists.txt b/subsystems/ntvdm/CMakeLists.txt index accf3f74344..eff132bc2ec 100644 --- a/subsystems/ntvdm/CMakeLists.txt +++ b/subsystems/ntvdm/CMakeLists.txt @@ -5,6 +5,7 @@ spec2def(ntvdm.exe ntvdm.spec) list(APPEND SOURCE bios.c + bop.c dos.c emulator.c pic.c diff --git a/subsystems/ntvdm/bios.c b/subsystems/ntvdm/bios.c index f040147bf76..13343c6aa98 100644 --- a/subsystems/ntvdm/bios.c +++ b/subsystems/ntvdm/bios.c @@ -453,7 +453,7 @@ BOOLEAN BiosSetVideoPage(BYTE PageNumber) BOOLEAN BiosInitialize(VOID) { - INT i; + USHORT i; WORD Offset = 0; LPWORD IntVecTable = (LPWORD)BaseAddress; LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0); @@ -465,7 +465,7 @@ BOOLEAN BiosInitialize(VOID) Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD); /* Generate ISR stubs and fill the IVT */ - for (i = 0; i < 256; i++) + for (i = 0x00; i <= 0xFF; i++) { IntVecTable[i * 2] = Offset; IntVecTable[i * 2 + 1] = BIOS_SEGMENT; @@ -473,27 +473,28 @@ BOOLEAN BiosInitialize(VOID) BiosCode[Offset++] = 0xFB; // sti BiosCode[Offset++] = 0x6A; // push i - BiosCode[Offset++] = (BYTE)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++] = LOBYTE(EMULATOR_INT_BOP); - BiosCode[Offset++] = HIBYTE(EMULATOR_INT_BOP); + BiosCode[Offset++] = EMULATOR_INT_BOP; - BiosCode[Offset++] = 0x73; // jnc +3 + 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 -10 - BiosCode[Offset++] = 0xF6; + BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -9) + BiosCode[Offset++] = 0xF7; +// EXIT: BiosCode[Offset++] = 0x83; // add sp, 4 BiosCode[Offset++] = 0xC4; BiosCode[Offset++] = 0x04; diff --git a/subsystems/ntvdm/bios.h b/subsystems/ntvdm/bios.h index 27e2578b8f6..e661c2ee0f0 100644 --- a/subsystems/ntvdm/bios.h +++ b/subsystems/ntvdm/bios.h @@ -18,8 +18,10 @@ #define ROM_AREA_START 0xE0000 #define ROM_AREA_END 0xFFFFF #define BDA_SEGMENT 0x40 + #define BIOS_PIC_MASTER_INT 0x08 -#define BIOS_PIC_SLAVE_INT 0x70 +#define BIOS_PIC_SLAVE_INT 0x70 + #define BIOS_SEGMENT 0xF000 #define BIOS_VIDEO_INTERRUPT 0x10 diff --git a/subsystems/ntvdm/bop.c b/subsystems/ntvdm/bop.c new file mode 100644 index 00000000000..41d95102943 --- /dev/null +++ b/subsystems/ntvdm/bop.c @@ -0,0 +1,165 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bop.c + * PURPOSE: BIOS Operation Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "bios.h" +#include "dos.h" +#include "vga.h" +#include "pic.h" +#include "ps2.h" +#include "timer.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" +}; + +VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack) +{ + WORD CodeSegment, InstructionPointer; + + ASSERT(ExceptionNumber < 8); + + /* Get the CS:IP */ + InstructionPointer = Stack[STACK_IP]; + CodeSegment = Stack[STACK_CS]; + + /* Display a message to the user */ + DisplayMessage(L"Exception: %s occured at %04X:%04X", + ExceptionName[ExceptionNumber], + CodeSegment, + InstructionPointer); + + /* 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 BiosInt(BYTE IntNumber, LPWORD Stack) +// { +// } + +VOID WINAPI IntDispatch(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; + } + + 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_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; + } + default: + { + DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum); + break; + } + } +} + +VOID WINAPI ControlBop(LPWORD Stack) +{ + IntDispatch(Stack); +} + +/* EOF */ diff --git a/subsystems/ntvdm/bop.h b/subsystems/ntvdm/bop.h new file mode 100644 index 00000000000..38a39e7eeed --- /dev/null +++ b/subsystems/ntvdm/bop.h @@ -0,0 +1,10 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bop.h + * PURPOSE: BIOS Operation Handlers + * PROGRAMMERS: Aleksandar Andrejevic + * Hermes Belusca-Maito (hermes.belusca@sfr.fr) + */ + +/* EOF */ diff --git a/subsystems/ntvdm/emulator.c b/subsystems/ntvdm/emulator.c index 601da014723..1b5f4dfb5ab 100644 --- a/subsystems/ntvdm/emulator.c +++ b/subsystems/ntvdm/emulator.c @@ -225,10 +225,10 @@ static VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffe } } -static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, USHORT BopCode) +VOID WINAPI ControlBop(LPWORD Stack); +static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode) { - WORD StackSegment, StackPointer, CodeSegment, InstructionPointer; - BYTE IntNum; + WORD StackSegment, StackPointer; LPWORD Stack; /* Get the SS:SP */ @@ -238,99 +238,22 @@ static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, USHORT BopCode) /* Get the stack */ Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer); - if (BopCode == EMULATOR_INT_BOP) + switch (BopCode) { - /* Get the interrupt number */ - IntNum = LOBYTE(Stack[STACK_INT_NUM]); + case EMULATOR_INT_BOP: + ControlBop(Stack); + break; - /* Get the CS:IP */ - InstructionPointer = Stack[STACK_IP]; - CodeSegment = Stack[STACK_CS]; - - /* Check if this was an exception */ - if (IntNum < 8) - { - /* Display a message to the user */ - DisplayMessage(L"Exception: %s occured at %04X:%04X", - ExceptionName[IntNum], - CodeSegment, - InstructionPointer); - - /* Stop the VDM */ - VdmRunning = FALSE; - 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; - } - - 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_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; - } - default: - { - DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum); - break; - } - } + default: + DPRINT1("Invalid BOP code %u\n", BopCode); + break; } } +static VOID WINAPI EmulatorIdle(PFAST486_STATE State) +{ +} + static UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State) { UNREFERENCED_PARAMETER(State); @@ -350,8 +273,9 @@ BOOLEAN EmulatorInitialize() /* Set the callbacks */ EmulatorContext.MemReadCallback = EmulatorReadMemory; EmulatorContext.MemWriteCallback = EmulatorWriteMemory; - EmulatorContext.IoReadCallback = EmulatorReadIo; - EmulatorContext.IoWriteCallback = EmulatorWriteIo; + EmulatorContext.IoReadCallback = EmulatorReadIo; // Must be != NULL + EmulatorContext.IoWriteCallback = EmulatorWriteIo; // Must be != NULL + EmulatorContext.IdleCallback = EmulatorIdle; // Must be != NULL EmulatorContext.BopCallback = EmulatorBiosOperation; EmulatorContext.IntAckCallback = EmulatorIntAcknowledge; diff --git a/subsystems/ntvdm/emulator.h b/subsystems/ntvdm/emulator.h index fcfb0712e96..b0d8a28347b 100644 --- a/subsystems/ntvdm/emulator.h +++ b/subsystems/ntvdm/emulator.h @@ -35,13 +35,14 @@ #define EMULATOR_FLAG_ID (1 << 21) /* Common definitions */ -#define EMULATOR_BOP 0xC4C4 -#define EMULATOR_INT_BOP 0xBEEF -#define STACK_COUNTER 0 -#define STACK_INT_NUM 1 -#define STACK_IP 2 -#define STACK_CS 3 -#define STACK_FLAGS 4 +#define EMULATOR_BOP 0xC4C4 +#define EMULATOR_INT_BOP 0xFF + +#define STACK_COUNTER 0 +#define STACK_INT_NUM 1 +#define STACK_IP 2 +#define STACK_CS 3 +#define STACK_FLAGS 4 enum { diff --git a/subsystems/ntvdm/ntvdm.c b/subsystems/ntvdm/ntvdm.c index b919c814695..c1efd21231b 100644 --- a/subsystems/ntvdm/ntvdm.c +++ b/subsystems/ntvdm/ntvdm.c @@ -29,17 +29,6 @@ BOOLEAN VdmRunning = TRUE; LPVOID BaseAddress = NULL; -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" -}; /* PUBLIC FUNCTIONS ***********************************************************/