#define NDEBUG
#include "emulator.h"
-#include "bios.h"
+
+#include "bios/bios.h"
+#include "hardware/cmos.h"
+#include "hardware/pic.h"
+#include "hardware/ps2.h"
+#include "hardware/speaker.h"
+#include "hardware/timer.h"
+#include "hardware/vga.h"
+
#include "bop.h"
#include "vddsup.h"
#include "io.h"
-#include "registers.h"
-#include "vga.h"
-#include "pic.h"
-
-// HACK
-typedef INT VDM_MODE;
/* PRIVATE VARIABLES **********************************************************/
FAST486_STATE EmulatorContext;
+LPVOID BaseAddress = NULL;
+BOOLEAN VdmRunning = TRUE;
static BOOLEAN A20Line = FALSE;
+static BYTE Port61hState = 0x00;
+
+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"
+};
/* BOP Identifiers */
#define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app
DebugBreak();
}
+
+static BYTE WINAPI Port61hRead(ULONG Port)
+{
+ return Port61hState;
+}
+
+static VOID WINAPI Port61hWrite(ULONG Port, BYTE Data)
+{
+ // BOOLEAN SpeakerChange = FALSE;
+ BYTE OldPort61hState = Port61hState;
+
+ /* Only the four lowest bytes can be written */
+ Port61hState = (Port61hState & 0xF0) | (Data & 0x0F);
+
+ if ((OldPort61hState ^ Port61hState) & 0x01)
+ {
+ DPRINT("PIT 2 Gate %s\n", Port61hState & 0x01 ? "on" : "off");
+ // SpeakerChange = TRUE;
+ }
+
+ PitSetGate(2, !!(Port61hState & 0x01));
+
+ if ((OldPort61hState ^ Port61hState) & 0x02)
+ {
+ /* There were some change for the speaker... */
+ DPRINT("Speaker %s\n", Port61hState & 0x02 ? "on" : "off");
+ // SpeakerChange = TRUE;
+ }
+ // if (SpeakerChange) SpeakerChange();
+ SpeakerChange();
+}
+
+static VOID WINAPI PitChan0Out(LPVOID Param, BOOLEAN State)
+{
+ if (State)
+ {
+ DPRINT("PicInterruptRequest\n");
+ PicInterruptRequest(0); // Raise IRQ 0
+ }
+ // else < Lower IRQ 0 >
+}
+
+static VOID WINAPI PitChan1Out(LPVOID Param, BOOLEAN State)
+{
+#if 0
+ if (State)
+ {
+ /* Set bit 4 of Port 61h */
+ Port61hState |= 1 << 4;
+ }
+ else
+ {
+ /* Clear bit 4 of Port 61h */
+ Port61hState &= ~(1 << 4);
+ }
+#else
+ Port61hState = (Port61hState & 0xEF) | (State << 4);
+#endif
+}
+
+static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State)
+{
+ // BYTE OldPort61hState = Port61hState;
+
+#if 0
+ if (State)
+ {
+ /* Set bit 5 of Port 61h */
+ Port61hState |= 1 << 5;
+ }
+ else
+ {
+ /* Clear bit 5 of Port 61h */
+ Port61hState &= ~(1 << 5);
+ }
+#else
+ Port61hState = (Port61hState & 0xDF) | (State << 5);
+#endif
+ DPRINT("Speaker PIT out\n");
+ // if ((OldPort61hState ^ Port61hState) & 0x20)
+ // SpeakerChange();
+}
+
/* PUBLIC FUNCTIONS ***********************************************************/
-BOOLEAN EmulatorInitialize(VOID)
+BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
{
/* Allocate memory for the 16-bit address space */
BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS);
- if (BaseAddress == NULL) return FALSE;
+ if (BaseAddress == NULL)
+ {
+ wprintf(L"FATAL: Failed to allocate VDM memory.\n");
+ return FALSE;
+ }
+
+ /* Initialize I/O ports */
+ /* Initialize RAM */
/* Initialize the CPU */
Fast486Initialize(&EmulatorContext,
/* Enable interrupts */
setIF(1);
- /* Initialize VDD support */
- VDDSupInitialize();
+ /* Initialize the PIC, the PIT, the CMOS and the PC Speaker */
+ PicInitialize();
+ PitInitialize();
+ CmosInitialize();
+ SpeakerInitialize();
+
+ /* Set output functions */
+ PitSetOutFunction(0, NULL, PitChan0Out);
+ PitSetOutFunction(1, NULL, PitChan1Out);
+ PitSetOutFunction(2, NULL, PitChan2Out);
+
+ /* Register the I/O Ports */
+ RegisterIoPort(CONTROL_SYSTEM_PORT61H, Port61hRead, Port61hWrite);
+
+ /* Initialize the PS2 port */
+ PS2Initialize(ConsoleInput);
+
+ /* Set the console input mode */
+ // SetConsoleMode(ConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
+
+ /* Initialize the VGA */
+ // if (!VgaInitialize(ConsoleOutput)) return FALSE;
+ VgaInitialize(ConsoleOutput);
/* Register the DebugBreak BOP */
RegisterBop(BOP_DEBUGGER, EmulatorDebugBreak);
+ /* Initialize VDD support */
+ VDDSupInitialize();
+
return TRUE;
}
VOID EmulatorCleanup(VOID)
{
+ // VgaCleanup();
+ PS2Cleanup();
+
+ SpeakerCleanup();
+ CmosCleanup();
+ // PitCleanup();
+ // PicCleanup();
+
+ // Fast486Cleanup();
+
/* Free the memory allocated for the 16-bit address space */
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
}
+VOID EmulatorException(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;
+}
+
// FIXME: This function assumes 16-bit mode!!!
VOID EmulatorExecute(WORD Segment, WORD Offset)
{
return SEG_OFF_TO_PTR(Segment, Offset);
}
-BOOL
+BOOL
WINAPI
VdmFlushCache(IN USHORT Segment,
IN ULONG Offset,