/* INCLUDES *******************************************************************/
-#include "ntvdm.h"
-#include <softx86/softx86.h>
-#include <softx86/softx87.h>
+#include "emulator.h"
+#include "bios.h"
+#include "dos.h"
+#include "pic.h"
+#include "ps2.h"
+#include "timer.h"
-softx86_ctx EmulatorContext;
-softx87_ctx FpuEmulatorContext;
+/* PRIVATE VARIABLES **********************************************************/
+
+static softx86_ctx EmulatorContext;
+static softx87_ctx FpuEmulatorContext;
+static BOOLEAN A20Line = FALSE;
+
+/* PRIVATE FUNCTIONS **********************************************************/
static VOID EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
{
+ /* If the A20 line is disabled, mask bit 20 */
+ if (!A20Line) Address &= ~(1 << 20);
+
/* Make sure the requested address is valid */
if ((Address + Size) >= MAX_ADDRESS) return;
static VOID EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
{
+ /* If the A20 line is disabled, mask bit 20 */
+ if (!A20Line) Address &= ~(1 << 20);
+
/* Make sure the requested address is valid */
if ((Address + Size) >= MAX_ADDRESS) return;
*Buffer = PicReadCommand(Address);
break;
}
-
+
case PIC_MASTER_DATA:
case PIC_SLAVE_DATA:
{
*Buffer = PicReadData(Address);
break;
}
+
+ case PIT_DATA_PORT(0):
+ case PIT_DATA_PORT(1):
+ case PIT_DATA_PORT(2):
+ {
+ *Buffer = PitReadData(Address - PIT_DATA_PORT(0));
+ break;
+ }
+
+ case PS2_CONTROL_PORT:
+ {
+ *Buffer = KeyboardReadStatus();
+ break;
+ }
+
+ case PS2_DATA_PORT:
+ {
+ *Buffer = KeyboardReadData();
+ break;
+ }
}
}
static VOID EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
{
BYTE Byte = *Buffer;
-
+
switch (Address)
{
case PIT_COMMAND_PORT:
PitWriteCommand(Byte);
break;
}
-
+
case PIT_DATA_PORT(0):
case PIT_DATA_PORT(1):
case PIT_DATA_PORT(2):
PitWriteData(Address - PIT_DATA_PORT(0), Byte);
break;
}
-
+
case PIC_MASTER_CMD:
case PIC_SLAVE_CMD:
{
PicWriteCommand(Address, Byte);
break;
}
-
+
case PIC_MASTER_DATA:
case PIC_SLAVE_DATA:
{
PicWriteData(Address, Byte);
break;
}
+
+ case PS2_CONTROL_PORT:
+ {
+ KeyboardWriteCommand(Byte);
+ break;
+ }
+
+ case PS2_DATA_PORT:
+ {
+ KeyboardWriteData(Byte);
+ break;
+ }
}
}
VdmRunning = FALSE;
return;
}
-
+
/* Check if this was an PIC IRQ */
if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
{
BiosVideoService();
break;
}
+ case VIDEO_KBD_INTERRUPT:
+ {
+ /* This is the keyboard BIOS interrupt, call the BIOS */
+ BiosKeyboardService();
+ break;
+ }
case 0x20:
{
DosInt20h(CodeSegment);
}
}
+static VOID EmulatorHardwareInt(PVOID Context, BYTE Number)
+{
+ /* Do nothing */
+}
+
+static VOID EmulatorHardwareIntAck(PVOID Context, BYTE Number)
+{
+ /* Do nothing */
+}
+
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN EmulatorInitialize()
if (BaseAddress == NULL) return FALSE;
/* Initialize the softx86 CPU emulator */
- if (!softx86_init(&EmulatorContext, SX86_CPULEVEL_80186))
+ if (!softx86_init(&EmulatorContext, SX86_CPULEVEL_80286))
{
HeapFree(GetProcessHeap(), 0, BaseAddress);
return FALSE;
/* Set interrupt callbacks */
EmulatorContext.callbacks->on_sw_int = EmulatorSoftwareInt;
+ EmulatorContext.callbacks->on_hw_int = EmulatorHardwareInt;
+ EmulatorContext.callbacks->on_hw_int_ack = EmulatorHardwareIntAck;
/* Connect the emulated FPU to the emulated CPU */
softx87_connect_to_CPU(&EmulatorContext, &FpuEmulatorContext);
+ /* Enable interrupts */
+ EmulatorSetFlag(EMULATOR_FLAG_IF);
+
return TRUE;
}
softx86_make_simple_interrupt_call(&EmulatorContext, &Segment, &Offset);
}
+VOID EmulatorExternalInterrupt(BYTE Number)
+{
+ /* Call the softx86 API */
+ softx86_ext_hw_signal(&EmulatorContext, Number);
+}
+
ULONG EmulatorGetRegister(ULONG Register)
{
- if (Register < EMULATOR_REG_CS)
+ if (Register < EMULATOR_REG_ES)
{
return EmulatorContext.state->general_reg[Register].val;
}
else
{
- return EmulatorContext.state->segment_reg[(Register >> 3) - 1].val;
+ return EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val;
}
}
}
else
{
- EmulatorContext.state->segment_reg[(Register >> 3) - 1].val = Value;
+ EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val = Value;
}
}
VOID EmulatorStep()
{
/* Call the softx86 API */
- softx86_step(&EmulatorContext);
+ if (!softx86_step(&EmulatorContext))
+ {
+ /* Invalid opcode */
+ EmulatorInterrupt(EMULATOR_EXCEPTION_INVALID_OPCODE);
+ }
}
VOID EmulatorCleanup()
softx87_free(&FpuEmulatorContext);
}
+VOID EmulatorSetA20(BOOLEAN Enabled)
+{
+ A20Line = Enabled;
+}
+
/* EOF */