mirror of
https://github.com/reactos/reactos.git
synced 2024-10-21 00:18:26 +00:00
4fb7f6e1d7
- Move some PS/2 initialization from bios.c to ps2.c - NULLify interrupt entries which are in fact pointers to data tables. - Add a framework for adding I/O port handlers. svn path=/branches/ntvdm/; revision=61107
159 lines
4.7 KiB
C
159 lines
4.7 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.h"
|
|
#include "bop.h"
|
|
#include "io.h"
|
|
#include "registers.h"
|
|
#include "vga.h"
|
|
#include "pic.h"
|
|
|
|
/* PRIVATE VARIABLES **********************************************************/
|
|
|
|
FAST486_STATE EmulatorContext;
|
|
|
|
static BOOLEAN A20Line = FALSE;
|
|
|
|
/* 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;
|
|
|
|
/* Read the data from the virtual address space and store it in the buffer */
|
|
RtlCopyMemory(Buffer, (LPVOID)((ULONG_PTR)BaseAddress + Address), Size);
|
|
|
|
/* Check if we modified the console video memory */
|
|
if (((Address + Size) >= VgaGetVideoBaseAddress())
|
|
&& (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, ActualSize);
|
|
}
|
|
}
|
|
|
|
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 console video memory */
|
|
if (((Address + Size) >= VgaGetVideoBaseAddress())
|
|
&& (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, ActualSize);
|
|
}
|
|
}
|
|
|
|
UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
|
|
{
|
|
UNREFERENCED_PARAMETER(State);
|
|
|
|
/* Get the interrupt number from the PIC */
|
|
return PicGetInterrupt();
|
|
}
|
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
|
|
|
BOOLEAN EmulatorInitialize(VOID)
|
|
{
|
|
/* Allocate memory for the 16-bit address space */
|
|
BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS);
|
|
if (BaseAddress == NULL) return FALSE;
|
|
|
|
/* Initialize the CPU */
|
|
Fast486Initialize(&EmulatorContext,
|
|
EmulatorReadMemory,
|
|
EmulatorWriteMemory,
|
|
EmulatorReadIo,
|
|
EmulatorWriteIo,
|
|
NULL,
|
|
EmulatorBiosOperation,
|
|
EmulatorIntAcknowledge,
|
|
NULL /* TODO: Use a TLB */);
|
|
|
|
/* Enable interrupts */
|
|
EmulatorSetFlag(EMULATOR_FLAG_IF);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID EmulatorCleanup(VOID)
|
|
{
|
|
/* 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;
|
|
}
|
|
|
|
/* EOF */
|