2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: Virtual DOS Machine
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
13 BOOLEAN VdmRunning
= TRUE
;
14 LPVOID BaseAddress
= NULL
;
15 LPCWSTR ExceptionName
[] =
22 L
"Bound Range Exceeded",
27 VOID
DisplayMessage(LPCWSTR Format
, ...)
32 va_start(Parameters
, Format
);
33 _vsnwprintf(Buffer
, 256, Format
, Parameters
);
34 MessageBox(NULL
, Buffer
, L
"NTVDM Subsystem", MB_OK
);
38 BOOL WINAPI
ConsoleCtrlHandler(DWORD ControlType
)
43 case CTRL_BREAK_EVENT
:
45 /* Perform interrupt 0x23 */
46 EmulatorInterrupt(0x23);
50 /* Stop the VDM if the user logs out or closes the console */
57 INT
wmain(INT argc
, WCHAR
*argv
[])
60 BOOLEAN PrintUsage
= TRUE
;
61 CHAR CommandLine
[128];
62 DWORD CurrentTickCount
, LastTickCount
= 0, Cycles
= 0, LastCyclePrintout
= 0;
63 LARGE_INTEGER Frequency
, LastTimerTick
, Counter
;
66 /* Set the handler routine */
67 SetConsoleCtrlHandler(ConsoleCtrlHandler
, TRUE
);
69 /* Parse the command line arguments */
70 for (i
= 1; i
< argc
; i
++)
72 if (argv
[i
][0] != L
'-' && argv
[i
][0] != L
'/') continue;
79 if (argv
[i
+1] != NULL
)
81 /* The DOS command line must be ASCII */
82 WideCharToMultiByte(CP_ACP
, 0, argv
[i
+1], -1, CommandLine
, 128, NULL
, NULL
);
84 /* This is the only mandatory parameter */
91 wprintf(L
"Unknown option: %s", argv
[i
]);
98 wprintf(L
"ReactOS Virtual DOS Machine\n\n");
99 wprintf(L
"Usage: NTVDM /F <PROGRAM>\n");
103 if (!EmulatorInitialize()) return 1;
105 /* Initialize the performance counter (needed for hardware timers) */
106 if (!QueryPerformanceFrequency(&Frequency
))
108 wprintf(L
"FATAL: Performance counter not available\n");
112 /* Initialize the system BIOS */
113 if (!BiosInitialize())
115 wprintf(L
"FATAL: Failed to initialize the VDM BIOS.\n");
119 /* Initialize the VDM DOS kernel */
120 if (!DosInitialize())
122 wprintf(L
"FATAL: Failed to initialize the VDM DOS kernel.\n");
126 /* Start the process from the command line */
127 if (!DosCreateProcess(CommandLine
, 0))
129 DisplayMessage(L
"Could not start program: %S", CommandLine
);
133 /* Set the last timer tick to the current time */
134 QueryPerformanceCounter(&LastTimerTick
);
139 /* Get the current number of ticks */
140 CurrentTickCount
= GetTickCount();
142 /* Get the current performance counter value */
143 QueryPerformanceCounter(&Counter
);
145 /* Get the number of PIT ticks that have passed */
146 TimerTicks
= ((Counter
.QuadPart
- LastTimerTick
.QuadPart
)
147 * PIT_BASE_FREQUENCY
) / Frequency
.QuadPart
;
150 for (i
= 0; i
< TimerTicks
; i
++) PitDecrementCount();
151 LastTimerTick
= Counter
;
153 /* Check for console input events every millisecond */
154 if (CurrentTickCount
!= LastTickCount
)
156 CheckForInputEvents();
157 LastTickCount
= CurrentTickCount
;
160 /* Continue CPU emulation */
164 if ((CurrentTickCount
- LastCyclePrintout
) >= 1000)
166 DPRINT1("NTVDM: %d Instructions Per Second\n", Cycles
);
167 LastCyclePrintout
= CurrentTickCount
;