[NTVDM]
[reactos.git] / subsystems / ntvdm / emulator.c
index 1b5f4df..df30150 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "emulator.h"
 #include "bios.h"
+#include "bop.h"
 #include "dos.h"
 #include "vga.h"
 #include "pic.h"
@@ -81,151 +82,156 @@ static VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOI
 
 static VOID WINAPI EmulatorReadIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG Size)
 {
+    INT i;
     LPBYTE Address = (LPBYTE)Buffer;
 
     UNREFERENCED_PARAMETER(State);
-    UNREFERENCED_PARAMETER(Size);
 
-    switch (Port)
+    for (i = 0; i < Size; i++)
     {
-        case PIC_MASTER_CMD:
-        case PIC_SLAVE_CMD:
+        switch (Port)
         {
-            *Address = PicReadCommand(Port);
-            break;
-        }
-
-        case PIC_MASTER_DATA:
-        case PIC_SLAVE_DATA:
-        {
-            *Address = PicReadData(Port);
-            break;
-        }
-
-        case PIT_DATA_PORT(0):
-        case PIT_DATA_PORT(1):
-        case PIT_DATA_PORT(2):
-        {
-            *Address = PitReadData(Port - PIT_DATA_PORT(0));
-            break;
-        }
-
-        case PS2_CONTROL_PORT:
-        {
-            *Address = KeyboardReadStatus();
-            break;
-        }
-
-        case PS2_DATA_PORT:
-        {
-            *Address = KeyboardReadData();
-            break;
-        }
-
-        case VGA_AC_WRITE:
-        case VGA_AC_READ:
-        case VGA_SEQ_INDEX:
-        case VGA_SEQ_DATA:
-        case VGA_DAC_READ_INDEX:
-        case VGA_DAC_WRITE_INDEX:
-        case VGA_DAC_DATA:
-        case VGA_MISC_READ:
-        case VGA_MISC_WRITE:
-        case VGA_CRTC_INDEX:
-        case VGA_CRTC_DATA:
-        case VGA_GC_INDEX:
-        case VGA_GC_DATA:
-        case VGA_STAT_MONO:
-        case VGA_STAT_COLOR:
-        {
-            *Address = VgaReadPort(Port);
-            break;
-        }
-
-        default:
-        {
-            DPRINT1("Read from unknown port: 0x%X\n", Port);
+            case PIC_MASTER_CMD:
+            case PIC_SLAVE_CMD:
+            {
+                *(Address++) = PicReadCommand(Port);
+                break;
+            }
+
+            case PIC_MASTER_DATA:
+            case PIC_SLAVE_DATA:
+            {
+                *(Address++) = PicReadData(Port);
+                break;
+            }
+
+            case PIT_DATA_PORT(0):
+            case PIT_DATA_PORT(1):
+            case PIT_DATA_PORT(2):
+            {
+                *(Address++) = PitReadData(Port - PIT_DATA_PORT(0));
+                break;
+            }
+
+            case PS2_CONTROL_PORT:
+            {
+                *(Address++) = KeyboardReadStatus();
+                break;
+            }
+
+            case PS2_DATA_PORT:
+            {
+                *(Address++) = KeyboardReadData();
+                break;
+            }
+
+            case VGA_AC_WRITE:
+            case VGA_AC_READ:
+            case VGA_SEQ_INDEX:
+            case VGA_SEQ_DATA:
+            case VGA_DAC_READ_INDEX:
+            case VGA_DAC_WRITE_INDEX:
+            case VGA_DAC_DATA:
+            case VGA_MISC_READ:
+            case VGA_MISC_WRITE:
+            case VGA_CRTC_INDEX:
+            case VGA_CRTC_DATA:
+            case VGA_GC_INDEX:
+            case VGA_GC_DATA:
+            case VGA_STAT_MONO:
+            case VGA_STAT_COLOR:
+            {
+                *(Address++) = VgaReadPort(Port);
+                break;
+            }
+
+            default:
+            {
+                DPRINT1("Read from unknown port: 0x%X\n", Port);
+            }
         }
     }
 }
 
 static VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG Size)
 {
-    BYTE Byte = *(LPBYTE)Buffer;
+    INT i;
+    LPBYTE Address = (LPBYTE)Buffer;
 
     UNREFERENCED_PARAMETER(State);
-    UNREFERENCED_PARAMETER(Size);
 
-    switch (Port)
+    for (i = 0; i < Size; i++)
     {
-        case PIT_COMMAND_PORT:
-        {
-            PitWriteCommand(Byte);
-            break;
-        }
-
-        case PIT_DATA_PORT(0):
-        case PIT_DATA_PORT(1):
-        case PIT_DATA_PORT(2):
-        {
-            PitWriteData(Port - PIT_DATA_PORT(0), Byte);
-            break;
-        }
-
-        case PIC_MASTER_CMD:
-        case PIC_SLAVE_CMD:
-        {
-            PicWriteCommand(Port, Byte);
-            break;
-        }
-
-        case PIC_MASTER_DATA:
-        case PIC_SLAVE_DATA:
-        {
-            PicWriteData(Port, Byte);
-            break;
-        }
-
-        case PS2_CONTROL_PORT:
-        {
-            KeyboardWriteCommand(Byte);
-            break;
-        }
-
-        case PS2_DATA_PORT:
+        switch (Port)
         {
-            KeyboardWriteData(Byte);
-            break;
-        }
-
-        case VGA_AC_WRITE:
-        case VGA_AC_READ:
-        case VGA_SEQ_INDEX:
-        case VGA_SEQ_DATA:
-        case VGA_DAC_READ_INDEX:
-        case VGA_DAC_WRITE_INDEX:
-        case VGA_DAC_DATA:
-        case VGA_MISC_READ:
-        case VGA_MISC_WRITE:
-        case VGA_CRTC_INDEX:
-        case VGA_CRTC_DATA:
-        case VGA_GC_INDEX:
-        case VGA_GC_DATA:
-        case VGA_STAT_MONO:
-        case VGA_STAT_COLOR:
-        {
-            VgaWritePort(Port, Byte);
-            break;
-        }
-
-        default:
-        {
-            DPRINT1("Write to unknown port: 0x%X\n", Port);
+            case PIT_COMMAND_PORT:
+            {
+                PitWriteCommand(*(Address++));
+                break;
+            }
+
+            case PIT_DATA_PORT(0):
+            case PIT_DATA_PORT(1):
+            case PIT_DATA_PORT(2):
+            {
+                PitWriteData(Port - PIT_DATA_PORT(0), *(Address++));
+                break;
+            }
+
+            case PIC_MASTER_CMD:
+            case PIC_SLAVE_CMD:
+            {
+                PicWriteCommand(Port, *(Address++));
+                break;
+            }
+
+            case PIC_MASTER_DATA:
+            case PIC_SLAVE_DATA:
+            {
+                PicWriteData(Port, *(Address++));
+                break;
+            }
+
+            case PS2_CONTROL_PORT:
+            {
+                KeyboardWriteCommand(*(Address++));
+                break;
+            }
+
+            case PS2_DATA_PORT:
+            {
+                KeyboardWriteData(*(Address++));
+                break;
+            }
+
+            case VGA_AC_WRITE:
+            case VGA_AC_READ:
+            case VGA_SEQ_INDEX:
+            case VGA_SEQ_DATA:
+            case VGA_DAC_READ_INDEX:
+            case VGA_DAC_WRITE_INDEX:
+            case VGA_DAC_DATA:
+            case VGA_MISC_READ:
+            case VGA_MISC_WRITE:
+            case VGA_CRTC_INDEX:
+            case VGA_CRTC_DATA:
+            case VGA_GC_INDEX:
+            case VGA_GC_DATA:
+            case VGA_STAT_MONO:
+            case VGA_STAT_COLOR:
+            {
+                VgaWritePort(Port, *(Address++));
+                break;
+            }
+
+            default:
+            {
+                DPRINT1("Write to unknown port: 0x%X\n", Port);
+            }
         }
     }
 }
 
-VOID WINAPI ControlBop(LPWORD Stack);
 static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
 {
     WORD StackSegment, StackPointer;
@@ -238,20 +244,10 @@ static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
     /* Get the stack */
     Stack = (LPWORD)SEG_OFF_TO_PTR(StackSegment, StackPointer);
 
-    switch (BopCode)
-    {
-        case EMULATOR_INT_BOP:
-            ControlBop(Stack);
-            break;
-
-        default:
-            DPRINT1("Invalid BOP code %u\n", BopCode);
-            break;
-    }
-}
-
-static VOID WINAPI EmulatorIdle(PFAST486_STATE State)
-{
+    if (BopProc[BopCode] != NULL)
+        BopProc[BopCode](Stack);
+    else
+        DPRINT1("Invalid BOP code %u\n", BopCode);
 }
 
 static UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
@@ -264,23 +260,21 @@ static UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-BOOLEAN EmulatorInitialize()
+BOOLEAN EmulatorInitialize(VOID)
 {
     /* Allocate memory for the 16-bit address space */
     BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS);
     if (BaseAddress == NULL) return FALSE;
 
-    /* Set the callbacks */
-    EmulatorContext.MemReadCallback  = EmulatorReadMemory;
-    EmulatorContext.MemWriteCallback = EmulatorWriteMemory;
-    EmulatorContext.IoReadCallback   = EmulatorReadIo;  // Must be != NULL
-    EmulatorContext.IoWriteCallback  = EmulatorWriteIo; // Must be != NULL
-    EmulatorContext.IdleCallback     = EmulatorIdle;    // Must be != NULL
-    EmulatorContext.BopCallback      = EmulatorBiosOperation;
-    EmulatorContext.IntAckCallback   = EmulatorIntAcknowledge;
-
-    /* Reset the CPU */
-    Fast486Reset(&EmulatorContext);
+    /* Initialize the CPU */
+    Fast486Initialize(&EmulatorContext,
+                      EmulatorReadMemory,
+                      EmulatorWriteMemory,
+                      EmulatorReadIo,
+                      EmulatorWriteIo,
+                      NULL,
+                      EmulatorBiosOperation,
+                      EmulatorIntAcknowledge);
 
     /* Enable interrupts */
     EmulatorSetFlag(EMULATOR_FLAG_IF);
@@ -288,6 +282,12 @@ BOOLEAN EmulatorInitialize()
     return TRUE;
 }
 
+VOID EmulatorCleanup(VOID)
+{
+    /* Free the memory allocated for the 16-bit address space */
+    if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
+}
+
 VOID EmulatorSetStack(WORD Segment, DWORD Offset)
 {
     Fast486SetStack(&EmulatorContext, Segment, Offset);
@@ -365,12 +365,6 @@ VOID EmulatorStep(VOID)
     Fast486StepInto(&EmulatorContext);
 }
 
-VOID EmulatorCleanup(VOID)
-{
-    /* Free the memory allocated for the 16-bit address space */
-    if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
-}
-
 VOID EmulatorSetA20(BOOLEAN Enabled)
 {
     A20Line = Enabled;