reactos/subsystems/ntvdm/emulator.c
Hermès Bélusca-Maïto 40f773b96b [DDK:NT_VDD]
Declare some VDM memory services.

[NTVDM]
- Almost all of the XXXInitialize functions just return TRUE always, so VOIDify them instead (since they always succeed).
- Move almost all of the hardware initialization inside EmulatorInitialize.
- Move pure console initialization/mode-saving/cleanup code into ConsoleInit/Cleanup functions in ntvdm.c instead of in bios.c.

svn path=/branches/ntvdm/; revision=61588
2014-01-11 20:59:27 +00:00

279 lines
6.9 KiB
C

/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: emulator.c
* PURPOSE: Minimal x86 machine emulator for the VDM
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "bios/bios.h"
#include "hardware/cmos.h"
#include "hardware/pic.h"
#include "hardware/speaker.h"
#include "hardware/timer.h"
#include "hardware/vga.h"
#include "bop.h"
#include "vddsup.h"
#include "io.h"
#include "registers.h"
/* PRIVATE VARIABLES **********************************************************/
FAST486_STATE EmulatorContext;
LPVOID BaseAddress = NULL;
BOOLEAN VdmRunning = TRUE;
static BOOLEAN A20Line = FALSE;
/* BOP Identifiers */
#define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app
/* PRIVATE FUNCTIONS **********************************************************/
VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
{
UNREFERENCED_PARAMETER(State);
/* 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;
/*
* 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)((ULONG_PTR)BaseAddress + 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);
}
VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
{
UNREFERENCED_PARAMETER(State);
/* 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;
/* 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 */
RtlCopyMemory((LPVOID)((ULONG_PTR)BaseAddress + 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)((ULONG_PTR)BaseAddress + VgaAddress);
/* Write to the VGA memory */
VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize);
}
}
UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
{
UNREFERENCED_PARAMETER(State);
/* Get the interrupt number from the PIC */
return PicGetInterrupt();
}
VOID WINAPI EmulatorDebugBreak(LPWORD Stack)
{
DPRINT1("NTVDM: BOP_DEBUGGER\n");
DebugBreak();
}
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN EmulatorInitialize(VOID)
{
/* Allocate memory for the 16-bit address space */
BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS);
if (BaseAddress == NULL)
{
wprintf(L"FATAL: Failed to allocate VDM memory.\n");
return FALSE;
}
/* Initialize I/O ports */
/* Initialize RAM */
/* Initialize the CPU */
Fast486Initialize(&EmulatorContext,
EmulatorReadMemory,
EmulatorWriteMemory,
EmulatorReadIo,
EmulatorWriteIo,
NULL,
EmulatorBiosOperation,
EmulatorIntAcknowledge,
NULL /* TODO: Use a TLB */);
/* Enable interrupts */
setIF(1);
/* Initialize the PIC, the PIT, the CMOS and the PC Speaker */
PicInitialize();
PitInitialize();
CmosInitialize();
SpeakerInitialize();
/* Register the DebugBreak BOP */
RegisterBop(BOP_DEBUGGER, EmulatorDebugBreak);
/* Initialize VDD support */
VDDSupInitialize();
return TRUE;
}
VOID EmulatorCleanup(VOID)
{
SpeakerCleanup();
CmosCleanup();
// PitCleanup();
// PicCleanup();
// Fast486Cleanup();
/* Free the memory allocated for the 16-bit address space */
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
}
// FIXME: This function assumes 16-bit mode!!!
VOID EmulatorExecute(WORD Segment, WORD Offset)
{
/* Tell Fast486 to move the instruction pointer */
Fast486ExecuteAt(&EmulatorContext, Segment, Offset);
}
VOID EmulatorInterrupt(BYTE Number)
{
/* Call the Fast486 API */
Fast486Interrupt(&EmulatorContext, Number);
}
VOID EmulatorInterruptSignal(VOID)
{
/* Call the Fast486 API */
Fast486InterruptSignal(&EmulatorContext);
}
VOID EmulatorStep(VOID)
{
/* Dump the state for debugging purposes */
// Fast486DumpState(&EmulatorContext);
/* Execute the next instruction */
Fast486StepInto(&EmulatorContext);
}
VOID EmulatorSetA20(BOOLEAN Enabled)
{
A20Line = Enabled;
}
VOID
WINAPI
VDDTerminateVDM(VOID)
{
/* Stop the VDM */
VdmRunning = FALSE;
}
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 */