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>
9 /* INCLUDES *******************************************************************/
20 * Activate this line if you want to be able to test NTVDM with:
25 /* PUBLIC VARIABLES ***********************************************************/
27 BOOLEAN VdmRunning
= TRUE
;
28 LPVOID BaseAddress
= NULL
;
29 LPCWSTR ExceptionName
[] =
36 L
"Bound Range Exceeded",
41 /* PUBLIC FUNCTIONS ***********************************************************/
43 VOID
DisplayMessage(LPCWSTR Format
, ...)
48 va_start(Parameters
, Format
);
49 _vsnwprintf(Buffer
, 256, Format
, Parameters
);
50 MessageBox(NULL
, Buffer
, L
"NTVDM Subsystem", MB_OK
);
54 BOOL WINAPI
ConsoleCtrlHandler(DWORD ControlType
)
59 case CTRL_BREAK_EVENT
:
61 /* Perform interrupt 0x23 */
62 EmulatorInterrupt(0x23);
67 /* Stop the VDM if the user logs out or closes the console */
74 INT
wmain(INT argc
, WCHAR
*argv
[])
77 CHAR CommandLine
[128];
78 DWORD CurrentTickCount
;
79 DWORD LastTickCount
= GetTickCount();
81 DWORD LastCyclePrintout
= GetTickCount();
82 DWORD LastVerticalRefresh
= GetTickCount();
83 LARGE_INTEGER Frequency
, LastTimerTick
, Counter
;
86 /* Set the handler routine */
87 SetConsoleCtrlHandler(ConsoleCtrlHandler
, TRUE
);
90 /* The DOS command line must be ASCII */
91 WideCharToMultiByte(CP_ACP
, 0, GetCommandLine(), -1, CommandLine
, 128, NULL
, NULL
);
93 if (argc
== 2 && argv
[1] != NULL
)
95 WideCharToMultiByte(CP_ACP
, 0, argv
[1], -1, CommandLine
, 128, NULL
, NULL
);
99 wprintf(L
"\nReactOS Virtual DOS Machine\n\n"
100 L
"Usage: NTVDM <executable>\n");
105 if (!EmulatorInitialize())
107 wprintf(L
"FATAL: Failed to initialize the CPU emulator\n");
111 /* Initialize the performance counter (needed for hardware timers) */
112 if (!QueryPerformanceFrequency(&Frequency
))
114 wprintf(L
"FATAL: Performance counter not available\n");
118 /* Initialize the system BIOS */
119 if (!BiosInitialize())
121 wprintf(L
"FATAL: Failed to initialize the VDM BIOS.\n");
125 /* Initialize the VDM DOS kernel */
126 if (!DosInitialize())
128 wprintf(L
"FATAL: Failed to initialize the VDM DOS kernel.\n");
132 /* Start the process from the command line */
133 if (!DosCreateProcess(CommandLine
, 0))
135 DisplayMessage(L
"Could not start program: %S", CommandLine
);
139 /* Set the last timer tick to the current time */
140 QueryPerformanceCounter(&LastTimerTick
);
145 /* Get the current number of ticks */
146 CurrentTickCount
= GetTickCount();
148 /* Get the current performance counter value */
149 QueryPerformanceCounter(&Counter
);
151 /* Get the number of PIT ticks that have passed */
152 TimerTicks
= ((Counter
.QuadPart
- LastTimerTick
.QuadPart
)
153 * PIT_BASE_FREQUENCY
) / Frequency
.QuadPart
;
156 for (i
= 0; i
< TimerTicks
; i
++) PitDecrementCount();
157 LastTimerTick
= Counter
;
159 /* Check for console input events every millisecond */
160 if (CurrentTickCount
!= LastTickCount
)
162 CheckForInputEvents();
163 LastTickCount
= CurrentTickCount
;
166 /* Check for vertical refresh */
167 if ((CurrentTickCount
- LastVerticalRefresh
) >= 16)
169 BiosVerticalRefresh();
170 LastVerticalRefresh
= CurrentTickCount
;
173 /* Continue CPU emulation */
174 for (i
= 0; (i
< STEPS_PER_CYCLE
) && VdmRunning
; i
++)
180 if ((CurrentTickCount
- LastCyclePrintout
) >= 1000)
182 DPRINT1("NTVDM: %d Instructions Per Second\n", Cycles
);
183 LastCyclePrintout
= CurrentTickCount
;