2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: Minimal x86 machine emulator for the VDM
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
18 #include "registers.h"
25 /* PRIVATE VARIABLES **********************************************************/
27 FAST486_STATE EmulatorContext
;
29 static BOOLEAN A20Line
= FALSE
;
32 #define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app
34 /* PRIVATE FUNCTIONS **********************************************************/
36 VOID WINAPI
EmulatorReadMemory(PFAST486_STATE State
, ULONG Address
, PVOID Buffer
, ULONG Size
)
38 UNREFERENCED_PARAMETER(State
);
40 /* If the A20 line is disabled, mask bit 20 */
41 if (!A20Line
) Address
&= ~(1 << 20);
43 /* Make sure the requested address is valid */
44 if ((Address
+ Size
) >= MAX_ADDRESS
) return;
47 * Check if we are going to read the VGA memory and
48 * copy it into the virtual address space if needed.
50 if (((Address
+ Size
) >= VgaGetVideoBaseAddress())
51 && (Address
< VgaGetVideoLimitAddress()))
53 DWORD VgaAddress
= max(Address
, VgaGetVideoBaseAddress());
54 DWORD ActualSize
= min(Address
+ Size
- 1, VgaGetVideoLimitAddress())
56 LPBYTE DestBuffer
= (LPBYTE
)((ULONG_PTR
)BaseAddress
+ VgaAddress
);
58 /* Read from the VGA memory */
59 VgaReadMemory(VgaAddress
, DestBuffer
, ActualSize
);
62 /* Read the data from the virtual address space and store it in the buffer */
63 RtlCopyMemory(Buffer
, (LPVOID
)((ULONG_PTR
)BaseAddress
+ Address
), Size
);
66 VOID WINAPI
EmulatorWriteMemory(PFAST486_STATE State
, ULONG Address
, PVOID Buffer
, ULONG Size
)
68 UNREFERENCED_PARAMETER(State
);
70 /* If the A20 line is disabled, mask bit 20 */
71 if (!A20Line
) Address
&= ~(1 << 20);
73 /* Make sure the requested address is valid */
74 if ((Address
+ Size
) >= MAX_ADDRESS
) return;
76 /* Make sure we don't write to the ROM area */
77 if ((Address
+ Size
) >= ROM_AREA_START
&& (Address
< ROM_AREA_END
)) return;
79 /* Read the data from the buffer and store it in the virtual address space */
80 RtlCopyMemory((LPVOID
)((ULONG_PTR
)BaseAddress
+ Address
), Buffer
, Size
);
83 * Check if we modified the VGA memory.
85 if (((Address
+ Size
) >= VgaGetVideoBaseAddress())
86 && (Address
< VgaGetVideoLimitAddress()))
88 DWORD VgaAddress
= max(Address
, VgaGetVideoBaseAddress());
89 DWORD ActualSize
= min(Address
+ Size
- 1, VgaGetVideoLimitAddress())
91 LPBYTE SrcBuffer
= (LPBYTE
)((ULONG_PTR
)BaseAddress
+ VgaAddress
);
93 /* Write to the VGA memory */
94 VgaWriteMemory(VgaAddress
, SrcBuffer
, ActualSize
);
98 UCHAR WINAPI
EmulatorIntAcknowledge(PFAST486_STATE State
)
100 UNREFERENCED_PARAMETER(State
);
102 /* Get the interrupt number from the PIC */
103 return PicGetInterrupt();
106 VOID WINAPI
EmulatorDebugBreak(LPWORD Stack
)
108 DPRINT1("NTVDM: BOP_DEBUGGER\n");
112 /* PUBLIC FUNCTIONS ***********************************************************/
114 BOOLEAN
EmulatorInitialize(VOID
)
116 /* Allocate memory for the 16-bit address space */
117 BaseAddress
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, MAX_ADDRESS
);
118 if (BaseAddress
== NULL
) return FALSE
;
120 /* Initialize the CPU */
121 Fast486Initialize(&EmulatorContext
,
127 EmulatorBiosOperation
,
128 EmulatorIntAcknowledge
,
129 NULL
/* TODO: Use a TLB */);
131 /* Enable interrupts */
134 /* Initialize VDD support */
137 /* Register the DebugBreak BOP */
138 RegisterBop(BOP_DEBUGGER
, EmulatorDebugBreak
);
143 VOID
EmulatorCleanup(VOID
)
145 /* Free the memory allocated for the 16-bit address space */
146 if (BaseAddress
!= NULL
) HeapFree(GetProcessHeap(), 0, BaseAddress
);
149 // FIXME: This function assumes 16-bit mode!!!
150 VOID
EmulatorExecute(WORD Segment
, WORD Offset
)
152 /* Tell Fast486 to move the instruction pointer */
153 Fast486ExecuteAt(&EmulatorContext
, Segment
, Offset
);
156 VOID
EmulatorInterrupt(BYTE Number
)
158 /* Call the Fast486 API */
159 Fast486Interrupt(&EmulatorContext
, Number
);
162 VOID
EmulatorInterruptSignal(VOID
)
164 /* Call the Fast486 API */
165 Fast486InterruptSignal(&EmulatorContext
);
168 VOID
EmulatorStep(VOID
)
170 /* Dump the state for debugging purposes */
171 // Fast486DumpState(&EmulatorContext);
173 /* Execute the next instruction */
174 Fast486StepInto(&EmulatorContext
);
177 VOID
EmulatorSetA20(BOOLEAN Enabled
)
186 VDDTerminateVDM(VOID
)
194 Sim32pGetVDMPointer(IN ULONG Address
,
195 IN BOOLEAN ProtectedMode
)
198 UNREFERENCED_PARAMETER(ProtectedMode
);
201 * HIWORD(Address) == Segment (if ProtectedMode == FALSE)
202 * or Selector (if ProtectedMode == TRUE )
203 * LOWORD(Address) == Offset
205 return (PBYTE
)FAR_POINTER(Address
);
210 MGetVdmPointer(IN ULONG Address
,
212 IN BOOLEAN ProtectedMode
)
214 UNREFERENCED_PARAMETER(Size
);
215 return Sim32pGetVDMPointer(Address
, ProtectedMode
);
220 VdmMapFlat(IN USHORT Segment
,
225 UNREFERENCED_PARAMETER(Mode
);
227 return SEG_OFF_TO_PTR(Segment
, Offset
);
232 VdmFlushCache(IN USHORT Segment
,
244 VdmUnmapFlat(IN USHORT Segment
,