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 *******************************************************************/
19 /* PUBLIC VARIABLES ***********************************************************/
21 BOOLEAN VdmRunning
= TRUE
;
22 LPVOID BaseAddress
= NULL
;
23 LPCWSTR ExceptionName
[] =
30 L
"Bound Range Exceeded",
35 /* PUBLIC FUNCTIONS ***********************************************************/
37 VOID
DisplayMessage(LPCWSTR Format
, ...)
42 va_start(Parameters
, Format
);
43 _vsnwprintf(Buffer
, 256, Format
, Parameters
);
44 MessageBox(NULL
, Buffer
, L
"NTVDM Subsystem", MB_OK
);
48 BOOL WINAPI
ConsoleCtrlHandler(DWORD ControlType
)
53 case CTRL_BREAK_EVENT
:
55 /* Perform interrupt 0x23 */
56 EmulatorInterrupt(0x23);
61 /* Stop the VDM if the user logs out or closes the console */
68 INT
wmain(INT argc
, WCHAR
*argv
[])
71 CHAR CommandLine
[128];
72 DWORD CurrentTickCount
;
73 DWORD LastTickCount
= GetTickCount();
75 DWORD LastCyclePrintout
= GetTickCount();
76 DWORD LastVerticalRefresh
= GetTickCount();
77 LARGE_INTEGER Frequency
, LastTimerTick
, Counter
;
79 HANDLE ConsoleInput
= INVALID_HANDLE_VALUE
;
80 HANDLE ConsoleOutput
= INVALID_HANDLE_VALUE
;
81 CONSOLE_SCREEN_BUFFER_INFO SavedBufferInfo
;
83 /* Set the handler routine */
84 SetConsoleCtrlHandler(ConsoleCtrlHandler
, TRUE
);
86 /* Get the input and output handles to the real console */
87 ConsoleInput
= CreateFile(TEXT("CONIN$"),
88 GENERIC_READ
| GENERIC_WRITE
,
89 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
95 ConsoleOutput
= CreateFile(TEXT("CONOUT$"),
96 GENERIC_READ
| GENERIC_WRITE
,
97 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
103 if ((ConsoleInput
== INVALID_HANDLE_VALUE
)
104 || (ConsoleOutput
== INVALID_HANDLE_VALUE
))
106 wprintf(L
"FATAL: Could not get handles to the console\n");
110 /* Save the console screen buffer information */
111 if (!GetConsoleScreenBufferInfo(ConsoleOutput
, &SavedBufferInfo
))
113 wprintf(L
"FATAL: Could not save the console screen buffer information\n");
117 /* The DOS command line must be ASCII */
118 WideCharToMultiByte(CP_ACP
, 0, GetCommandLine(), -1, CommandLine
, 128, NULL
, NULL
);
120 if (!EmulatorInitialize())
122 wprintf(L
"FATAL: Failed to initialize the CPU emulator\n");
126 /* Initialize the performance counter (needed for hardware timers) */
127 if (!QueryPerformanceFrequency(&Frequency
))
129 wprintf(L
"FATAL: Performance counter not available\n");
133 /* Initialize the system BIOS */
134 if (!BiosInitialize(ConsoleInput
, ConsoleOutput
))
136 wprintf(L
"FATAL: Failed to initialize the VDM BIOS.\n");
140 /* Initialize the VDM DOS kernel */
141 if (!DosInitialize())
143 wprintf(L
"FATAL: Failed to initialize the VDM DOS kernel.\n");
147 /* Start the process from the command line */
148 if (!DosCreateProcess(CommandLine
, 0))
150 DisplayMessage(L
"Could not start program: %S", CommandLine
);
154 /* Set the last timer tick to the current time */
155 QueryPerformanceCounter(&LastTimerTick
);
160 /* Get the current number of ticks */
161 CurrentTickCount
= GetTickCount();
163 /* Get the current performance counter value */
164 QueryPerformanceCounter(&Counter
);
166 /* Get the number of PIT ticks that have passed */
167 TimerTicks
= ((Counter
.QuadPart
- LastTimerTick
.QuadPart
)
168 * PIT_BASE_FREQUENCY
) / Frequency
.QuadPart
;
171 for (i
= 0; i
< TimerTicks
; i
++) PitDecrementCount();
172 LastTimerTick
= Counter
;
174 /* Check for console input events every millisecond */
175 if (CurrentTickCount
!= LastTickCount
)
177 CheckForInputEvents();
178 LastTickCount
= CurrentTickCount
;
181 /* Check for vertical refresh */
182 if ((CurrentTickCount
- LastVerticalRefresh
) >= 16)
184 BiosVerticalRefresh();
185 LastVerticalRefresh
= CurrentTickCount
;
188 /* Continue CPU emulation */
189 for (i
= 0; (i
< STEPS_PER_CYCLE
) && VdmRunning
; i
++)
195 if ((CurrentTickCount
- LastCyclePrintout
) >= 1000)
197 DPRINT1("NTVDM: %d Instructions Per Second\n", Cycles
);
198 LastCyclePrintout
= CurrentTickCount
;
204 /* Restore the old screen buffer */
205 SetConsoleActiveScreenBuffer(ConsoleOutput
);
207 /* Restore the screen buffer size */
208 SetConsoleScreenBufferSize(ConsoleOutput
, SavedBufferInfo
.dwSize
);
212 /* Close the console handles */
213 if (ConsoleInput
!= INVALID_HANDLE_VALUE
) CloseHandle(ConsoleInput
);
214 if (ConsoleOutput
!= INVALID_HANDLE_VALUE
) CloseHandle(ConsoleOutput
);