[NTVDM]
[reactos.git] / subsystems / ntvdm / emulator.c
index 4a7ed72..42dc841 100644 (file)
 #include "bios.h"
 #include "bop.h"
 #include "dos.h"
+#include "speaker.h"
 #include "vga.h"
 #include "pic.h"
 #include "ps2.h"
 #include "timer.h"
+#include "cmos.h"
 
 /* PRIVATE VARIABLES **********************************************************/
 
@@ -27,7 +29,7 @@ static BOOLEAN A20Line = FALSE;
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
-static VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
+VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
 {
     UNREFERENCED_PARAMETER(State);
 
@@ -45,14 +47,16 @@ static VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID
         && (Address < VgaGetVideoLimitAddress()))
     {
         DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
+        DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
+                           - VgaAddress + 1;
         LPBYTE VgaBuffer = (LPBYTE)((ULONG_PTR)Buffer + VgaAddress - Address);
 
         /* Read from the VGA memory */
-        VgaReadMemory(VgaAddress, VgaBuffer, Size);
+        VgaReadMemory(VgaAddress, VgaBuffer, ActualSize);
     }
 }
 
-static VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
+VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
 {
     UNREFERENCED_PARAMETER(State);
 
@@ -73,160 +77,202 @@ static VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOI
         && (Address < VgaGetVideoLimitAddress()))
     {
         DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
+        DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
+                           - VgaAddress + 1;
         LPBYTE VgaBuffer = (LPBYTE)((ULONG_PTR)Buffer + VgaAddress - Address);
 
         /* Write to the VGA memory */
-        VgaWriteMemory(VgaAddress, VgaBuffer, Size);
+        VgaWriteMemory(VgaAddress, VgaBuffer, ActualSize);
     }
 }
 
-static VOID WINAPI EmulatorReadIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG Size)
+VOID WINAPI EmulatorReadIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
 {
+    INT i, j;
     LPBYTE Address = (LPBYTE)Buffer;
 
     UNREFERENCED_PARAMETER(State);
-    UNREFERENCED_PARAMETER(Size);
 
-    switch (Port)
+    for (i = 0; i < DataCount; i++) for (j = 0; j < DataSize; j++)
     {
-        case PIC_MASTER_CMD:
-        case PIC_SLAVE_CMD:
-        {
-            *Address = PicReadCommand(Port);
-            break;
-        }
-
-        case PIC_MASTER_DATA:
-        case PIC_SLAVE_DATA:
-        {
-            *Address = PicReadData(Port);
-            break;
-        }
+        ULONG CurrentPort = Port + j;
 
-        case PIT_DATA_PORT(0):
-        case PIT_DATA_PORT(1):
-        case PIT_DATA_PORT(2):
+        switch (CurrentPort)
         {
-            *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(CurrentPort);
+                break;
+            }
+
+            case PIC_MASTER_DATA:
+            case PIC_SLAVE_DATA:
+            {
+                *(Address++) = PicReadData(CurrentPort);
+                break;
+            }
+
+            case PIT_DATA_PORT(0):
+            case PIT_DATA_PORT(1):
+            case PIT_DATA_PORT(2):
+            {
+                *(Address++) = PitReadData(CurrentPort - PIT_DATA_PORT(0));
+                break;
+            }
+
+            case PS2_CONTROL_PORT:
+            {
+                *(Address++) = KeyboardReadStatus();
+                break;
+            }
+
+            case PS2_DATA_PORT:
+            {
+                *(Address++) = KeyboardReadData();
+                break;
+            }
+
+            case CMOS_DATA_PORT:
+            {
+                *(Address++) = CmosReadData();
+                break;
+            }
+
+            case SPEAKER_CONTROL_PORT:
+            {
+                *(Address++) = SpeakerReadStatus();
+                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(CurrentPort);
+                break;
+            }
+
+            default:
+            {
+                DPRINT1("Read from unknown port: 0x%X\n", CurrentPort);
+            }
         }
     }
 }
 
-static VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG Size)
+VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize)
 {
-    BYTE Byte = *(LPBYTE)Buffer;
+    INT i, j;
+    LPBYTE Address = (LPBYTE)Buffer;
 
     UNREFERENCED_PARAMETER(State);
-    UNREFERENCED_PARAMETER(Size);
 
-    switch (Port)
+    for (i = 0; i < DataCount; i++) for (j = 0; j < DataSize; j++)
     {
-        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:
-        {
-            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;
-        }
+        ULONG CurrentPort = Port + j;
 
-        default:
+        switch (CurrentPort)
         {
-            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(CurrentPort - PIT_DATA_PORT(0), *(Address++));
+                break;
+            }
+
+            case PIC_MASTER_CMD:
+            case PIC_SLAVE_CMD:
+            {
+                PicWriteCommand(CurrentPort, *(Address++));
+                break;
+            }
+
+            case PIC_MASTER_DATA:
+            case PIC_SLAVE_DATA:
+            {
+                PicWriteData(CurrentPort, *(Address++));
+                break;
+            }
+
+            case PS2_CONTROL_PORT:
+            {
+                KeyboardWriteCommand(*(Address++));
+                break;
+            }
+
+            case PS2_DATA_PORT:
+            {
+                KeyboardWriteData(*(Address++));
+                break;
+            }
+
+            case CMOS_ADDRESS_PORT:
+            {
+                CmosWriteAddress(*(Address++));
+                break;
+            }
+
+            case CMOS_DATA_PORT:
+            {
+                CmosWriteData(*(Address++));
+                break;
+            }
+
+            case SPEAKER_CONTROL_PORT:
+            {
+                SpeakerWriteCommand(*(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(CurrentPort, *(Address++));
+                break;
+            }
+
+            default:
+            {
+                DPRINT1("Write to unknown port: 0x%X\n", CurrentPort);
+            }
         }
     }
 }
 
-static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
+VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
 {
     WORD StackSegment, StackPointer;
     LPWORD Stack;
@@ -244,7 +290,7 @@ static VOID WINAPI EmulatorBiosOperation(PFAST486_STATE State, UCHAR BopCode)
         DPRINT1("Invalid BOP code %u\n", BopCode);
 }
 
-static UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
+UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
 {
     UNREFERENCED_PARAMETER(State);