#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;
/* 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)
A20Line = Enabled;
}
+BOOLEAN EmulatorGetA20(VOID)
+{
+ return A20Line;
+}
+
static VOID WINAPI EmulatorDebugBreakBop(LPWORD Stack)
{
DPRINT1("NTVDM: BOP_DEBUGGER\n");
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
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 */
/* 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();
VOID EmulatorCleanup(VOID)
{
-#ifndef STANDALONE
- NTSTATUS Status;
- SIZE_T MemorySize = MAX_ADDRESS;
-#endif
-
VgaCleanup();
/* Close the input thread handle */
// 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();
}
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 */