[NTVDM]
[reactos.git] / subsystems / ntvdm / emulator.c
index 826ff39..0732ebb 100644 (file)
 /* PRIVATE VARIABLES **********************************************************/
 
 FAST486_STATE EmulatorContext;
+BOOLEAN CpuSimulate = FALSE;
+
+/* No more than 'MaxCpuCallLevel' recursive CPU calls are allowed */
+const static INT MaxCpuCallLevel = 32;
+static INT CpuCallLevel = 0;
+
 LPVOID  BaseAddress = NULL;
 BOOLEAN VdmRunning  = TRUE;
 
@@ -59,6 +65,10 @@ VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer
 {
     UNREFERENCED_PARAMETER(State);
 
+    // BIG HACK!!!! To make BIOS images working correctly,
+    // until Aleksander rewrites memory management!!
+    if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
+
     /* If the A20 line is disabled, mask bit 20 */
     if (!A20Line) Address &= ~(1 << 20);
 
@@ -75,20 +85,24 @@ VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer
         DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
         DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
                            - VgaAddress + 1;
-        LPBYTE DestBuffer = (LPBYTE)((ULONG_PTR)BaseAddress + VgaAddress);
+        LPBYTE DestBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
 
         /* Read from the VGA memory */
         VgaReadMemory(VgaAddress, DestBuffer, ActualSize);
     }
 
     /* Read the data from the virtual address space and store it in the buffer */
-    RtlCopyMemory(Buffer, (LPVOID)((ULONG_PTR)BaseAddress + Address), Size);
+    RtlCopyMemory(Buffer, REAL_TO_PHYS(Address), Size);
 }
 
 VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
 {
     UNREFERENCED_PARAMETER(State);
 
+    // BIG HACK!!!! To make BIOS images working correctly,
+    // until Aleksander rewrites memory management!!
+    if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
+
     /* If the A20 line is disabled, mask bit 20 */
     if (!A20Line) Address &= ~(1 << 20);
 
@@ -99,7 +113,7 @@ VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffe
     if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return;
 
     /* Read the data from the buffer and store it in the virtual address space */
-    RtlCopyMemory((LPVOID)((ULONG_PTR)BaseAddress + Address), Buffer, Size);
+    RtlCopyMemory(REAL_TO_PHYS(Address), Buffer, Size);
 
     /*
      * Check if we modified the VGA memory.
@@ -110,7 +124,7 @@ VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffe
         DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
         DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
                            - VgaAddress + 1;
-        LPBYTE SrcBuffer = (LPBYTE)((ULONG_PTR)BaseAddress + VgaAddress);
+        LPBYTE SrcBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
 
         /* Write to the VGA memory */
         VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize);
@@ -177,12 +191,31 @@ VOID EmulatorStep(VOID)
 
 VOID EmulatorSimulate(VOID)
 {
-    UNIMPLEMENTED;
+    if (CpuCallLevel > MaxCpuCallLevel)
+    {
+        DisplayMessage(L"Too many CPU levels of recursion (%d, expected maximum %d)",
+                       CpuCallLevel, MaxCpuCallLevel);
+
+        /* Stop the VDM */
+        VdmRunning = FALSE;
+        return;
+    }
+    CpuCallLevel++;
+
+    CpuSimulate = TRUE;
+    while (VdmRunning && CpuSimulate) ClockUpdate();
+
+    CpuCallLevel--;
+    if (CpuCallLevel < 0) CpuCallLevel = 0;
+
+    /* This takes into account for reentrance */
+    CpuSimulate = TRUE;
 }
 
 VOID EmulatorUnsimulate(VOID)
 {
-    UNIMPLEMENTED;
+    /* Stop simulation */
+    CpuSimulate = FALSE;
 }
 
 VOID EmulatorInterrupt(BYTE Number)
@@ -330,9 +363,6 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
                       EmulatorIntAcknowledge,
                       NULL /* TODO: Use a TLB */);
 
-    /* Enable interrupts */
-    setIF(1);
-
     /* Initialize DMA */
 
     /* Initialize the PIC, the PIT, the CMOS and the PC Speaker */
@@ -363,7 +393,8 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
     // if (!VgaInitialize(ConsoleOutput)) return FALSE;
     VgaInitialize(ConsoleOutput);
 
-    /* Register the emulator BOPs */
+    /* Initialize the software callback system and register the emulator BOPs */
+    InitializeCallbacks();
     RegisterBop(BOP_DEBUGGER  , EmulatorDebugBreakBop);
     RegisterBop(BOP_UNSIMULATE, EmulatorUnsimulateBop);