Start source tree (final, I hope!) restructuration. Part 1/X
[reactos.git] / reactos / subsystems / mvdm / ntvdm / emulator.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: emulator.c
5 * PURPOSE: Minimal x86 machine emulator for the VDM
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #define NDEBUG
12
13 #include "emulator.h"
14
15 #include "cpu/callback.h"
16 #include "cpu/cpu.h"
17 #include "cpu/bop.h"
18 #include <isvbop.h>
19
20 #include "int32.h"
21
22 #include "clock.h"
23 #include "bios/rom.h"
24 #include "hardware/cmos.h"
25 #include "hardware/dma.h"
26 #include "hardware/keyboard.h"
27 #include "hardware/mouse.h"
28 #include "hardware/pic.h"
29 #include "hardware/ps2.h"
30 #include "hardware/sound/speaker.h"
31 #include "hardware/pit.h"
32 #include "hardware/video/vga.h"
33
34 #include "vddsup.h"
35 #include "io.h"
36
37 /* Extra PSDK/NDK Headers */
38 #include <ndk/psfuncs.h>
39 #include <ndk/mmfuncs.h>
40
41 /* PRIVATE VARIABLES **********************************************************/
42
43 LPVOID BaseAddress = NULL;
44 BOOLEAN VdmRunning = TRUE;
45
46 static BOOLEAN A20Line = FALSE;
47 static BYTE Port61hState = 0x00;
48
49 static HANDLE InputThread = NULL;
50
51 LPCWSTR ExceptionName[] =
52 {
53 L"Division By Zero",
54 L"Debug",
55 L"Unexpected Error",
56 L"Breakpoint",
57 L"Integer Overflow",
58 L"Bound Range Exceeded",
59 L"Invalid Opcode",
60 L"FPU Not Available"
61 };
62
63 /* BOP Identifiers */
64 #define BOP_DEBUGGER 0x56 // Break into the debugger from a 16-bit app
65
66 /* PRIVATE FUNCTIONS **********************************************************/
67
68 static inline VOID
69 EmulatorMoveMemory(OUT VOID UNALIGNED *Destination,
70 IN const VOID UNALIGNED *Source,
71 IN SIZE_T Length)
72 {
73 #if 1
74 /*
75 * We use a switch here to detect small moves of memory, as these
76 * constitute the bulk of our moves.
77 * Using RtlMoveMemory for all these small moves would be slow otherwise.
78 */
79 switch (Length)
80 {
81 case 0:
82 return;
83
84 case sizeof(UCHAR):
85 *(PUCHAR)Destination = *(PUCHAR)Source;
86 return;
87
88 case sizeof(USHORT):
89 *(PUSHORT)Destination = *(PUSHORT)Source;
90 return;
91
92 case sizeof(ULONG):
93 *(PULONG)Destination = *(PULONG)Source;
94 return;
95
96 case sizeof(ULONGLONG):
97 *(PULONGLONG)Destination = *(PULONGLONG)Source;
98 return;
99
100 default:
101 #if defined(__GNUC__)
102 __builtin_memmove(Destination, Source, Length);
103 #else
104 RtlMoveMemory(Destination, Source, Length);
105 #endif
106 }
107
108 #else // defined(_MSC_VER)
109
110 PUCHAR Dest = (PUCHAR)Destination;
111 PUCHAR Src = (PUCHAR)Source;
112
113 SIZE_T Count, NewSize = Length;
114
115 /* Move dword */
116 Count = NewSize >> 2; // NewSize / sizeof(ULONG);
117 NewSize = NewSize & 3; // NewSize % sizeof(ULONG);
118 __movsd(Dest, Src, Count);
119 Dest += Count << 2; // Count * sizeof(ULONG);
120 Src += Count << 2;
121
122 /* Move word */
123 Count = NewSize >> 1; // NewSize / sizeof(USHORT);
124 NewSize = NewSize & 1; // NewSize % sizeof(USHORT);
125 __movsw(Dest, Src, Count);
126 Dest += Count << 1; // Count * sizeof(USHORT);
127 Src += Count << 1;
128
129 /* Move byte */
130 Count = NewSize; // NewSize / sizeof(UCHAR);
131 // NewSize = NewSize; // NewSize % sizeof(UCHAR);
132 __movsb(Dest, Src, Count);
133
134 #endif
135 }
136
137 VOID WINAPI EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
138 {
139 UNREFERENCED_PARAMETER(State);
140
141 // BIG HACK!!!! To make BIOS images working correctly,
142 // until Aleksander rewrites memory management!!
143 if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
144
145 /* If the A20 line is disabled, mask bit 20 */
146 if (!A20Line) Address &= ~(1 << 20);
147
148 /* Make sure the requested address is valid */
149 if ((Address + Size) >= MAX_ADDRESS) return;
150
151 /*
152 * Check if we are going to read the VGA memory and
153 * copy it into the virtual address space if needed.
154 */
155 if (((Address + Size) >= VgaGetVideoBaseAddress())
156 && (Address < VgaGetVideoLimitAddress()))
157 {
158 DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
159 DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
160 - VgaAddress + 1;
161 LPBYTE DestBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
162
163 /* Read from the VGA memory */
164 VgaReadMemory(VgaAddress, DestBuffer, ActualSize);
165 }
166
167 /* Read the data from the virtual address space and store it in the buffer */
168 EmulatorMoveMemory(Buffer, REAL_TO_PHYS(Address), Size);
169 }
170
171 VOID WINAPI EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size)
172 {
173 UNREFERENCED_PARAMETER(State);
174
175 // BIG HACK!!!! To make BIOS images working correctly,
176 // until Aleksander rewrites memory management!!
177 if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
178
179 /* If the A20 line is disabled, mask bit 20 */
180 if (!A20Line) Address &= ~(1 << 20);
181
182 /* Make sure the requested address is valid */
183 if ((Address + Size) >= MAX_ADDRESS) return;
184
185 /* Make sure we don't write to the ROM area */
186 if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return;
187
188 /* Read the data from the buffer and store it in the virtual address space */
189 EmulatorMoveMemory(REAL_TO_PHYS(Address), Buffer, Size);
190
191 /*
192 * Check if we modified the VGA memory.
193 */
194 if (((Address + Size) >= VgaGetVideoBaseAddress())
195 && (Address < VgaGetVideoLimitAddress()))
196 {
197 DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
198 DWORD ActualSize = min(Address + Size - 1, VgaGetVideoLimitAddress())
199 - VgaAddress + 1;
200 LPBYTE SrcBuffer = (LPBYTE)REAL_TO_PHYS(VgaAddress);
201
202 /* Write to the VGA memory */
203 VgaWriteMemory(VgaAddress, SrcBuffer, ActualSize);
204 }
205 }
206
207 UCHAR WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
208 {
209 UNREFERENCED_PARAMETER(State);
210
211 /* Get the interrupt number from the PIC */
212 return PicGetInterrupt();
213 }
214
215 VOID WINAPI EmulatorFpu(PFAST486_STATE State)
216 {
217 /* The FPU is wired to IRQ 13 */
218 PicInterruptRequest(13);
219 }
220
221 VOID EmulatorException(BYTE ExceptionNumber, LPWORD Stack)
222 {
223 WORD CodeSegment, InstructionPointer;
224 PBYTE Opcode;
225
226 ASSERT(ExceptionNumber < 8);
227
228 /* Get the CS:IP */
229 InstructionPointer = Stack[STACK_IP];
230 CodeSegment = Stack[STACK_CS];
231 Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
232
233 /* Display a message to the user */
234 DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
235 L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
236 ExceptionName[ExceptionNumber],
237 CodeSegment,
238 InstructionPointer,
239 Opcode[0],
240 Opcode[1],
241 Opcode[2],
242 Opcode[3],
243 Opcode[4],
244 Opcode[5],
245 Opcode[6],
246 Opcode[7],
247 Opcode[8],
248 Opcode[9]);
249
250 Fast486DumpState(&EmulatorContext);
251
252 /* Stop the VDM */
253 EmulatorTerminate();
254 return;
255 }
256
257 VOID EmulatorTerminate(VOID)
258 {
259 /* Stop the VDM */
260 CpuUnsimulate(); // Halt the CPU
261 VdmRunning = FALSE;
262 }
263
264 VOID EmulatorInterruptSignal(VOID)
265 {
266 /* Call the Fast486 API */
267 Fast486InterruptSignal(&EmulatorContext);
268 }
269
270 VOID EmulatorSetA20(BOOLEAN Enabled)
271 {
272 A20Line = Enabled;
273 }
274
275 static VOID WINAPI EmulatorDebugBreakBop(LPWORD Stack)
276 {
277 DPRINT1("NTVDM: BOP_DEBUGGER\n");
278 DebugBreak();
279 }
280
281 static BYTE WINAPI Port61hRead(USHORT Port)
282 {
283 return Port61hState;
284 }
285
286 static VOID WINAPI Port61hWrite(USHORT Port, BYTE Data)
287 {
288 // BOOLEAN SpeakerStateChange = FALSE;
289 BYTE OldPort61hState = Port61hState;
290
291 /* Only the four lowest bytes can be written */
292 Port61hState = (Port61hState & 0xF0) | (Data & 0x0F);
293
294 if ((OldPort61hState ^ Port61hState) & 0x01)
295 {
296 DPRINT("PIT 2 Gate %s\n", Port61hState & 0x01 ? "on" : "off");
297 PitSetGate(2, !!(Port61hState & 0x01));
298 // SpeakerStateChange = TRUE;
299 }
300
301 if ((OldPort61hState ^ Port61hState) & 0x02)
302 {
303 /* There were some change for the speaker... */
304 DPRINT("Speaker %s\n", Port61hState & 0x02 ? "on" : "off");
305 // SpeakerStateChange = TRUE;
306 }
307 // if (SpeakerStateChange) SpeakerChange(Port61hState);
308 SpeakerChange(Port61hState);
309 }
310
311 static VOID WINAPI PitChan0Out(LPVOID Param, BOOLEAN State)
312 {
313 if (State)
314 {
315 DPRINT("PicInterruptRequest\n");
316 PicInterruptRequest(0); // Raise IRQ 0
317 }
318 // else < Lower IRQ 0 >
319 }
320
321 static VOID WINAPI PitChan1Out(LPVOID Param, BOOLEAN State)
322 {
323 #if 0
324 if (State)
325 {
326 /* Set bit 4 of Port 61h */
327 Port61hState |= 1 << 4;
328 }
329 else
330 {
331 /* Clear bit 4 of Port 61h */
332 Port61hState &= ~(1 << 4);
333 }
334 #else
335 Port61hState = (Port61hState & 0xEF) | (State << 4);
336 #endif
337 }
338
339 static VOID WINAPI PitChan2Out(LPVOID Param, BOOLEAN State)
340 {
341 BYTE OldPort61hState = Port61hState;
342
343 #if 0
344 if (State)
345 {
346 /* Set bit 5 of Port 61h */
347 Port61hState |= 1 << 5;
348 }
349 else
350 {
351 /* Clear bit 5 of Port 61h */
352 Port61hState &= ~(1 << 5);
353 }
354 #else
355 Port61hState = (Port61hState & 0xDF) | (State << 5);
356 #endif
357
358 if ((OldPort61hState ^ Port61hState) & 0x20)
359 {
360 DPRINT("PitChan2Out -- Port61hState changed\n");
361 SpeakerChange(Port61hState);
362 }
363 }
364
365
366 static DWORD
367 WINAPI
368 PumpConsoleInput(LPVOID Parameter)
369 {
370 HANDLE ConsoleInput = (HANDLE)Parameter;
371 INPUT_RECORD InputRecord;
372 DWORD Count;
373
374 while (VdmRunning)
375 {
376 /* Make sure the task event is signaled */
377 WaitForSingleObject(VdmTaskEvent, INFINITE);
378
379 /* Wait for an input record */
380 if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count))
381 {
382 DWORD LastError = GetLastError();
383 DPRINT1("Error reading console input (0x%p, %lu) - Error %lu\n", ConsoleInput, Count, LastError);
384 return LastError;
385 }
386
387 ASSERT(Count != 0);
388
389 /* Check the event type */
390 switch (InputRecord.EventType)
391 {
392 /*
393 * Hardware events
394 */
395 case KEY_EVENT:
396 KeyboardEventHandler(&InputRecord.Event.KeyEvent);
397 break;
398
399 case MOUSE_EVENT:
400 MouseEventHandler(&InputRecord.Event.MouseEvent);
401 break;
402
403 case WINDOW_BUFFER_SIZE_EVENT:
404 ScreenEventHandler(&InputRecord.Event.WindowBufferSizeEvent);
405 break;
406
407 /*
408 * Interface events
409 */
410 case MENU_EVENT:
411 MenuEventHandler(&InputRecord.Event.MenuEvent);
412 break;
413
414 case FOCUS_EVENT:
415 FocusEventHandler(&InputRecord.Event.FocusEvent);
416 break;
417
418 default:
419 break;
420 }
421 }
422
423 return 0;
424 }
425
426 static VOID EnableExtraHardware(HANDLE ConsoleInput)
427 {
428 DWORD ConInMode;
429
430 if (GetConsoleMode(ConsoleInput, &ConInMode))
431 {
432 #if 0
433 // GetNumberOfConsoleMouseButtons();
434 // GetSystemMetrics(SM_CMOUSEBUTTONS);
435 // GetSystemMetrics(SM_MOUSEPRESENT);
436 if (MousePresent)
437 {
438 #endif
439 /* Support mouse input events if there is a mouse on the system */
440 ConInMode |= ENABLE_MOUSE_INPUT;
441 #if 0
442 }
443 else
444 {
445 /* Do not support mouse input events if there is no mouse on the system */
446 ConInMode &= ~ENABLE_MOUSE_INPUT;
447 }
448 #endif
449
450 SetConsoleMode(ConsoleInput, ConInMode);
451 }
452 }
453
454 /* PUBLIC FUNCTIONS ***********************************************************/
455
456 static VOID
457 DumpMemoryRaw(HANDLE hFile)
458 {
459 PVOID Buffer;
460 SIZE_T Size;
461
462 /* Dump the VM memory */
463 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
464 Buffer = REAL_TO_PHYS(NULL);
465 Size = MAX_ADDRESS - (ULONG_PTR)(NULL);
466 WriteFile(hFile, Buffer, Size, &Size, NULL);
467 }
468
469 static VOID
470 DumpMemoryTxt(HANDLE hFile)
471 {
472 #define LINE_SIZE 75 + 2
473 ULONG i;
474 PBYTE Ptr1, Ptr2;
475 CHAR LineBuffer[LINE_SIZE];
476 PCHAR Line;
477 SIZE_T LineSize;
478
479 /* Dump the VM memory */
480 SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
481 Ptr1 = Ptr2 = REAL_TO_PHYS(NULL);
482 while (MAX_ADDRESS - (ULONG_PTR)PHYS_TO_REAL(Ptr1) > 0)
483 {
484 Ptr1 = Ptr2;
485 Line = LineBuffer;
486
487 /* Print the address */
488 Line += snprintf(Line, LINE_SIZE + LineBuffer - Line, "%08x ", PHYS_TO_REAL(Ptr1));
489
490 /* Print up to 16 bytes... */
491
492 /* ... in hexadecimal form first... */
493 i = 0;
494 while (i++ <= 0x0F && (MAX_ADDRESS - (ULONG_PTR)PHYS_TO_REAL(Ptr1) > 0))
495 {
496 Line += snprintf(Line, LINE_SIZE + LineBuffer - Line, " %02x", *Ptr1);
497 ++Ptr1;
498 }
499
500 /* ... align with spaces if needed... */
501 RtlFillMemory(Line, 0x0F + 4 - i, ' ');
502 Line += 0x0F + 4 - i;
503
504 /* ... then in character form. */
505 i = 0;
506 while (i++ <= 0x0F && (MAX_ADDRESS - (ULONG_PTR)PHYS_TO_REAL(Ptr2) > 0))
507 {
508 *Line++ = ((*Ptr2 >= 0x20 && *Ptr2 <= 0x7E) || (*Ptr2 >= 0x80 && *Ptr2 < 0xFF) ? *Ptr2 : '.');
509 ++Ptr2;
510 }
511
512 /* Newline */
513 *Line++ = '\r';
514 *Line++ = '\n';
515
516 /* Finally write the line to the file */
517 LineSize = Line - LineBuffer;
518 WriteFile(hFile, LineBuffer, LineSize, &LineSize, NULL);
519 }
520 }
521
522 VOID DumpMemory(BOOLEAN TextFormat)
523 {
524 static ULONG DumpNumber = 0;
525
526 HANDLE hFile;
527 WCHAR FileName[MAX_PATH];
528
529 /* Build a suitable file name */
530 _snwprintf(FileName, MAX_PATH,
531 L"memdump%lu.%s",
532 DumpNumber,
533 TextFormat ? L"txt" : L"dat");
534 ++DumpNumber;
535
536 DPRINT1("Creating memory dump file '%S'...\n", FileName);
537
538 /* Always create the dump file */
539 hFile = CreateFileW(FileName,
540 GENERIC_WRITE,
541 0,
542 NULL,
543 CREATE_ALWAYS,
544 FILE_ATTRIBUTE_NORMAL,
545 NULL);
546
547 if (hFile == INVALID_HANDLE_VALUE)
548 {
549 DPRINT1("Error when creating '%S' for memory dumping, GetLastError() = %u\n",
550 FileName, GetLastError());
551 return;
552 }
553
554 /* Dump the VM memory in the chosen format */
555 if (TextFormat)
556 DumpMemoryTxt(hFile);
557 else
558 DumpMemoryRaw(hFile);
559
560 /* Close the file */
561 CloseHandle(hFile);
562
563 DPRINT1("Memory dump done\n");
564 }
565
566 BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
567 {
568 #ifdef STANDALONE
569
570 /* Allocate 16 MB memory for the 16-bit address space */
571 BaseAddress = HeapAlloc(GetProcessHeap(), /*HEAP_ZERO_MEMORY*/ 0, MAX_ADDRESS);
572 if (BaseAddress == NULL)
573 {
574 wprintf(L"FATAL: Failed to allocate VDM memory.\n");
575 return FALSE;
576 }
577
578 #else
579
580 NTSTATUS Status;
581 SIZE_T MemorySize = MAX_ADDRESS; // See: kernel32/client/vdm.c!BaseGetVdmConfigInfo
582
583 /*
584 * The reserved region starts from the very first page.
585 * We need to commit the reserved first 16 MB virtual address.
586 */
587 BaseAddress = (PVOID)1; // NULL has another signification for NtAllocateVirtualMemory
588
589 /*
590 * Since to get NULL, we allocated from 0x1, account for this.
591 * See also: kernel32/client/proc.c!CreateProcessInternalW
592 */
593 MemorySize -= 1;
594
595 /* Commit the reserved memory */
596 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
597 &BaseAddress,
598 0,
599 &MemorySize,
600 MEM_COMMIT,
601 PAGE_EXECUTE_READWRITE);
602 if (!NT_SUCCESS(Status))
603 {
604 wprintf(L"FATAL: Failed to commit VDM memory, Status 0x%08lx\n", Status);
605 return FALSE;
606 }
607
608 ASSERT(BaseAddress == NULL);
609
610 #endif
611
612 /*
613 * For diagnostics purposes, we fill the memory with INT 0x03 codes
614 * so that if a program wants to execute random code in memory, we can
615 * retrieve the exact CS:IP where the problem happens.
616 */
617 RtlFillMemory(BaseAddress, MAX_ADDRESS, 0xCC);
618
619 /* Initialize I/O ports */
620 /* Initialize RAM */
621
622 /* Initialize the CPU */
623
624 /* Initialize the internal clock */
625 if (!ClockInitialize())
626 {
627 wprintf(L"FATAL: Failed to initialize the clock\n");
628 EmulatorCleanup();
629 return FALSE;
630 }
631
632 /* Initialize the CPU */
633 CpuInitialize();
634
635 /* Initialize DMA */
636 DmaInitialize();
637
638 /* Initialize the PIC, the PIT, the CMOS and the PC Speaker */
639 PicInitialize();
640 PitInitialize();
641 CmosInitialize();
642 SpeakerInitialize();
643
644 /* Set output functions */
645 PitSetOutFunction(0, NULL, PitChan0Out);
646 PitSetOutFunction(1, NULL, PitChan1Out);
647 PitSetOutFunction(2, NULL, PitChan2Out);
648
649 /* Register the I/O Ports */
650 RegisterIoPort(CONTROL_SYSTEM_PORT61H, Port61hRead, Port61hWrite);
651
652 /* Set the console input mode */
653 // FIXME: Activate ENABLE_WINDOW_INPUT when we will want to perform actions
654 // upon console window events (screen buffer resize, ...).
655 SetConsoleMode(ConsoleInput, ENABLE_PROCESSED_INPUT /* | ENABLE_WINDOW_INPUT */);
656 // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
657
658 /**/EnableExtraHardware(ConsoleInput);/**/
659
660 /* Initialize the PS/2 port */
661 PS2Initialize();
662
663 /* Initialize the keyboard and mouse and connect them to their PS/2 ports */
664 KeyboardInit(0);
665 MouseInit(1);
666
667 /**************** ATTACH INPUT WITH CONSOLE *****************/
668 /* Start the input thread */
669 InputThread = CreateThread(NULL, 0, &PumpConsoleInput, ConsoleInput, 0, NULL);
670 if (InputThread == NULL)
671 {
672 DisplayMessage(L"Failed to create the console input thread.");
673 EmulatorCleanup();
674 return FALSE;
675 }
676 /************************************************************/
677
678 /* Initialize the VGA */
679 if (!VgaInitialize(ConsoleOutput))
680 {
681 DisplayMessage(L"Failed to initialize VGA support.");
682 EmulatorCleanup();
683 return FALSE;
684 }
685
686 /* Initialize the software callback system and register the emulator BOPs */
687 InitializeInt32();
688 RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop);
689 // RegisterBop(BOP_UNSIMULATE, CpuUnsimulateBop);
690
691 /* Initialize VDD support */
692 VDDSupInitialize();
693
694 return TRUE;
695 }
696
697 VOID EmulatorCleanup(VOID)
698 {
699 #ifndef STANDALONE
700 NTSTATUS Status;
701 SIZE_T MemorySize = MAX_ADDRESS;
702 #endif
703
704 VgaCleanup();
705
706 /* Close the input thread handle */
707 if (InputThread != NULL) CloseHandle(InputThread);
708 InputThread = NULL;
709
710 PS2Cleanup();
711
712 SpeakerCleanup();
713 CmosCleanup();
714 // PitCleanup();
715 // PicCleanup();
716
717 // DmaCleanup();
718
719 CpuCleanup();
720
721 #ifdef STANDALONE
722
723 /* Free the memory allocated for the 16-bit address space */
724 if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
725
726 #else
727
728 /* The reserved region starts from the very first page */
729 // BaseAddress = (PVOID)1;
730
731 /* Since to get NULL, we allocated from 0x1, account for this */
732 MemorySize -= 1;
733
734 Status = NtFreeVirtualMemory(NtCurrentProcess(),
735 &BaseAddress,
736 &MemorySize,
737 MEM_DECOMMIT);
738 if (!NT_SUCCESS(Status))
739 {
740 DPRINT1("NTVDM: Failed to decommit VDM memory, Status 0x%08lx\n", Status);
741 }
742 #endif
743 }
744
745
746
747 VOID
748 WINAPI
749 VDDSimulate16(VOID)
750 {
751 CpuSimulate();
752 }
753
754 VOID
755 WINAPI
756 VDDTerminateVDM(VOID)
757 {
758 /* Stop the VDM */
759 EmulatorTerminate();
760 }
761
762 PBYTE
763 WINAPI
764 Sim32pGetVDMPointer(IN ULONG Address,
765 IN BOOLEAN ProtectedMode)
766 {
767 // FIXME
768 UNREFERENCED_PARAMETER(ProtectedMode);
769
770 /*
771 * HIWORD(Address) == Segment (if ProtectedMode == FALSE)
772 * or Selector (if ProtectedMode == TRUE )
773 * LOWORD(Address) == Offset
774 */
775 return (PBYTE)FAR_POINTER(Address);
776 }
777
778 PBYTE
779 WINAPI
780 MGetVdmPointer(IN ULONG Address,
781 IN ULONG Size,
782 IN BOOLEAN ProtectedMode)
783 {
784 UNREFERENCED_PARAMETER(Size);
785 return Sim32pGetVDMPointer(Address, ProtectedMode);
786 }
787
788 PVOID
789 WINAPI
790 VdmMapFlat(IN USHORT Segment,
791 IN ULONG Offset,
792 IN VDM_MODE Mode)
793 {
794 // FIXME
795 UNREFERENCED_PARAMETER(Mode);
796
797 return SEG_OFF_TO_PTR(Segment, Offset);
798 }
799
800 BOOL
801 WINAPI
802 VdmFlushCache(IN USHORT Segment,
803 IN ULONG Offset,
804 IN ULONG Size,
805 IN VDM_MODE Mode)
806 {
807 // FIXME
808 UNIMPLEMENTED;
809 return TRUE;
810 }
811
812 BOOL
813 WINAPI
814 VdmUnmapFlat(IN USHORT Segment,
815 IN ULONG Offset,
816 IN PVOID Buffer,
817 IN VDM_MODE Mode)
818 {
819 // FIXME
820 UNIMPLEMENTED;
821 return TRUE;
822 }
823
824 /* EOF */