[NTVDM]
[reactos.git] / reactos / subsystems / mvdm / ntvdm / emulator.c
index bea6de8..dcd90c3 100644 (file)
@@ -10,7 +10,9 @@
 
 #define NDEBUG
 
+#include "ntvdm.h"
 #include "emulator.h"
+#include "memory.h"
 
 #include "cpu/callback.h"
 #include "cpu/cpu.h"
 #include "vddsup.h"
 #include "io.h"
 
-/* Extra PSDK/NDK Headers */
-#include <ndk/psfuncs.h>
-#include <ndk/mmfuncs.h>
-
 /* PRIVATE VARIABLES **********************************************************/
 
 LPVOID  BaseAddress = NULL;
@@ -65,143 +63,35 @@ LPCWSTR ExceptionName[] =
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
-static inline VOID
-EmulatorMoveMemory(OUT VOID UNALIGNED *Destination,
-                   IN const VOID UNALIGNED *Source,
-                   IN SIZE_T Length)
-{
-#if 1
-    /*
-     * We use a switch here to detect small moves of memory, as these
-     * constitute the bulk of our moves.
-     * Using RtlMoveMemory for all these small moves would be slow otherwise.
-     */
-    switch (Length)
-    {
-        case 0:
-            return;
-
-        case sizeof(UCHAR):
-            *(PUCHAR)Destination = *(PUCHAR)Source;
-            return;
-
-        case sizeof(USHORT):
-            *(PUSHORT)Destination = *(PUSHORT)Source;
-            return;
-
-        case sizeof(ULONG):
-            *(PULONG)Destination = *(PULONG)Source;
-            return;
-
-        case sizeof(ULONGLONG):
-            *(PULONGLONG)Destination = *(PULONGLONG)Source;
-            return;
-
-        default:
-#if defined(__GNUC__)
-            __builtin_memmove(Destination, Source, Length);
-#else
-            RtlMoveMemory(Destination, Source, Length);
-#endif
-    }
-
-#else // defined(_MSC_VER)
-
-    PUCHAR Dest = (PUCHAR)Destination;
-    PUCHAR Src  = (PUCHAR)Source;
-
-    SIZE_T Count, NewSize = Length;
-
-    /* Move dword */
-    Count   = NewSize >> 2; // NewSize / sizeof(ULONG);
-    NewSize = NewSize  & 3; // NewSize % sizeof(ULONG);
-    __movsd(Dest, Src, Count);
-    Dest += Count << 2; // Count * sizeof(ULONG);
-    Src  += Count << 2;
-
-    /* Move word */
-    Count   = NewSize >> 1; // NewSize / sizeof(USHORT);
-    NewSize = NewSize  & 1; // NewSize % sizeof(USHORT);
-    __movsw(Dest, Src, Count);
-    Dest += Count << 1; // Count * sizeof(USHORT);
-    Src  += Count << 1;
-
-    /* Move byte */
-    Count   = NewSize; // NewSize / sizeof(UCHAR);
-    // NewSize = NewSize; // NewSize % sizeof(UCHAR);
-    __movsb(Dest, Src, Count);
-
-#endif
-}
-
 VOID WINAPI EmulatorReadMemory(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!!
+    /* Mirror 0x000FFFF0 at 0xFFFFFFF0 */
     if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
 
     /* 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;
+    if (!A20Line) Address &= ~(1 << 20); 
 
-    /*
-     * Check if we are going to read the VGA memory and
-     * copy it into the virtual address space if needed.
-     */
-    if (((Address + Size) >= VgaGetVideoBaseAddress())
-        && (Address < VgaGetVideoLimitAddress()))
-    {
-        DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
-        DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
-                           - VgaAddress + 1;
-        LPBYTE DestBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
-
-        /* Read from the VGA memory */
-        VgaReadMemory(VgaAddress, DestBuffer, ActualSize);
-    }
+    if (Address >= MAX_ADDRESS) return;
+    Size = min(Size, MAX_ADDRESS - Address);
 
-    /* Read the data from the virtual address space and store it in the buffer */
-    EmulatorMoveMemory(Buffer, REAL_TO_PHYS(Address), Size);
+    /* Read while calling fast memory hooks */
+    MemRead(Address, Buffer, 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);
-
-    /* Make sure the requested address is valid */
-    if ((Address + Size) >= MAX_ADDRESS) return;
+    if (!A20Line) Address &= ~(1 << 20); 
 
-    /* Make sure we don't write to the ROM area */
-    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 */
-    EmulatorMoveMemory(REAL_TO_PHYS(Address), Buffer, Size);
-
-    /*
-     * Check if we modified the VGA memory.
-     */
-    if (((Address + Size) >= VgaGetVideoBaseAddress())
-        && (Address < VgaGetVideoLimitAddress()))
-    {
-        DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
-        DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
-                           - VgaAddress + 1;
-        LPBYTE SrcBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
+    if (Address >= MAX_ADDRESS) return;
+    Size = min(Size, MAX_ADDRESS - Address);
 
-        /* Write to the VGA memory */
-        VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize);
-    }
+    /* Write while calling fast memory hooks */
+    MemWrite(Address, Buffer, Size);
 }
 
 UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
@@ -272,6 +162,11 @@ VOID EmulatorSetA20(BOOLEAN Enabled)
     A20Line = Enabled;
 }
 
+BOOLEAN EmulatorGetA20(VOID)
+{
+    return A20Line;
+}
+
 static VOID WINAPI EmulatorDebugBreakBop(LPWORD Stack)
 {
     DPRINT1("NTVDM: BOP_DEBUGGER\n");
@@ -423,34 +318,6 @@ PumpConsoleInput(LPVOID Parameter)
     return 0;
 }
 
-static VOID EnableExtraHardware(HANDLE ConsoleInput)
-{
-    DWORD ConInMode;
-
-    if (GetConsoleMode(ConsoleInput, &ConInMode))
-    {
-#if 0
-        // GetNumberOfConsoleMouseButtons();
-        // GetSystemMetrics(SM_CMOUSEBUTTONS);
-        // GetSystemMetrics(SM_MOUSEPRESENT);
-        if (MousePresent)
-        {
-#endif
-            /* Support mouse input events if there is a mouse on the system */
-            ConInMode |= ENABLE_MOUSE_INPUT;
-#if 0
-        }
-        else
-        {
-            /* Do not support mouse input events if there is no mouse on the system */
-            ConInMode &= ~ENABLE_MOUSE_INPUT;
-        }
-#endif
-
-        SetConsoleMode(ConsoleInput, ConInMode);
-    }
-}
-
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 static VOID
@@ -565,57 +432,13 @@ VOID DumpMemory(BOOLEAN TextFormat)
 
 BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
 {
-#ifdef STANDALONE
-
-    /* Allocate 16 MB memory for the 16-bit address space */
-    BaseAddress = HeapAlloc(GetProcessHeap(), /*HEAP_ZERO_MEMORY*/ 0, MAX_ADDRESS);
-    if (BaseAddress == NULL)
+    /* Initialize memory */
+    if (!MemInitialize())
     {
-        wprintf(L"FATAL: Failed to allocate VDM memory.\n");
+        wprintf(L"Memory initialization failed.\n");
         return FALSE;
     }
 
-#else
-
-    NTSTATUS Status;
-    SIZE_T MemorySize = MAX_ADDRESS; // See: kernel32/client/vdm.c!BaseGetVdmConfigInfo
-
-    /*
-     * The reserved region starts from the very first page.
-     * We need to commit the reserved first 16 MB virtual address.
-     */
-    BaseAddress = (PVOID)1; // NULL has another signification for NtAllocateVirtualMemory
-
-    /*
-     * Since to get NULL, we allocated from 0x1, account for this.
-     * See also: kernel32/client/proc.c!CreateProcessInternalW
-     */
-    MemorySize -= 1;
-
-    /* Commit the reserved memory */
-    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
-                                     &BaseAddress,
-                                     0,
-                                     &MemorySize,
-                                     MEM_COMMIT,
-                                     PAGE_EXECUTE_READWRITE);
-    if (!NT_SUCCESS(Status))
-    {
-        wprintf(L"FATAL: Failed to commit VDM memory, Status 0x%08lx\n", Status);
-        return FALSE;
-    }
-
-    ASSERT(BaseAddress == NULL);
-
-#endif
-
-    /*
-     * For diagnostics purposes, we fill the memory with INT 0x03 codes
-     * so that if a program wants to execute random code in memory, we can
-     * retrieve the exact CS:IP where the problem happens.
-     */
-    RtlFillMemory(BaseAddress, MAX_ADDRESS, 0xCC);
-
     /* Initialize I/O ports */
     /* Initialize RAM */
 
@@ -649,14 +472,6 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
     /* Register the I/O Ports */
     RegisterIoPort(CONTROL_SYSTEM_PORT61H, Port61hRead, Port61hWrite);
 
-    /* Set the console input mode */
-    // FIXME: Activate ENABLE_WINDOW_INPUT when we will want to perform actions
-    // upon console window events (screen buffer resize, ...).
-    SetConsoleMode(ConsoleInput, ENABLE_PROCESSED_INPUT /* | ENABLE_WINDOW_INPUT */);
-    // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
-
-    /**/EnableExtraHardware(ConsoleInput);/**/
-
     /* Initialize the PS/2 port */
     PS2Initialize();
 
@@ -696,11 +511,6 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
 
 VOID EmulatorCleanup(VOID)
 {
-#ifndef STANDALONE
-    NTSTATUS Status;
-    SIZE_T MemorySize = MAX_ADDRESS;
-#endif
-
     VgaCleanup();
 
     /* Close the input thread handle */
@@ -717,29 +527,7 @@ VOID EmulatorCleanup(VOID)
     // DmaCleanup();
 
     CpuCleanup();
-
-#ifdef STANDALONE
-
-    /* Free the memory allocated for the 16-bit address space */
-    if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
-
-#else
-
-    /* The reserved region starts from the very first page */
-    // BaseAddress = (PVOID)1;
-
-    /* Since to get NULL, we allocated from 0x1, account for this */
-    MemorySize -= 1;
-
-    Status = NtFreeVirtualMemory(NtCurrentProcess(),
-                                 &BaseAddress,
-                                 &MemorySize,
-                                 MEM_DECOMMIT);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("NTVDM: Failed to decommit VDM memory, Status 0x%08lx\n", Status);
-    }
-#endif
+    MemCleanup();
 }
 
 
@@ -759,66 +547,4 @@ VDDTerminateVDM(VOID)
     EmulatorTerminate();
 }
 
-PBYTE
-WINAPI
-Sim32pGetVDMPointer(IN ULONG   Address,
-                    IN BOOLEAN ProtectedMode)
-{
-    // FIXME
-    UNREFERENCED_PARAMETER(ProtectedMode);
-
-    /*
-     * HIWORD(Address) == Segment  (if ProtectedMode == FALSE)
-     *                 or Selector (if ProtectedMode == TRUE )
-     * LOWORD(Address) == Offset
-     */
-    return (PBYTE)FAR_POINTER(Address);
-}
-
-PBYTE
-WINAPI
-MGetVdmPointer(IN ULONG   Address,
-               IN ULONG   Size,
-               IN BOOLEAN ProtectedMode)
-{
-    UNREFERENCED_PARAMETER(Size);
-    return Sim32pGetVDMPointer(Address, ProtectedMode);
-}
-
-PVOID
-WINAPI
-VdmMapFlat(IN USHORT   Segment,
-           IN ULONG    Offset,
-           IN VDM_MODE Mode)
-{
-    // FIXME
-    UNREFERENCED_PARAMETER(Mode);
-
-    return SEG_OFF_TO_PTR(Segment, Offset);
-}
-
-BOOL
-WINAPI
-VdmFlushCache(IN USHORT   Segment,
-              IN ULONG    Offset,
-              IN ULONG    Size,
-              IN VDM_MODE Mode)
-{
-    // FIXME
-    UNIMPLEMENTED;
-    return TRUE;
-}
-
-BOOL
-WINAPI
-VdmUnmapFlat(IN USHORT   Segment,
-             IN ULONG    Offset,
-             IN PVOID    Buffer,
-             IN VDM_MODE Mode)
-{
-    // FIXME
-    UNIMPLEMENTED;
-    return TRUE;
-}
-
 /* EOF */