/* DEFINES ********************************************************************/
/* BOP Identifiers */
-#define BOP_BIOSINIT 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
+#define BOP_RESET 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
// to let the virtual machine initialize itself
// the IVT and its hardware.
#define BOP_EQUIPLIST 0x11
static BOOLEAN Bios32Loaded = FALSE;
-static CALLBACK16 __BiosContext;
PBIOS_DATA_AREA Bda;
PBIOS_CONFIG_TABLE Bct;
/* PRIVATE FUNCTIONS **********************************************************/
-static VOID WINAPI BiosInitBop(LPWORD Stack)
-{
- BOOLEAN Success;
-
- /* Load the second part of the Windows NTVDM BIOS image */
- LPCSTR BiosFileName = "bios1.rom";
- PVOID BiosLocation = (PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000);
- DWORD BiosSize = 0;
-
- /* Disable interrupts */
- setIF(0);
-
- DisplayMessage(L"You are loading Windows NTVDM BIOS!\n");
-
- /* Initialize a private callback context */
- InitializeContext(&__BiosContext, BIOS_SEGMENT, 0x0000);
-
- Success = LoadRom(BiosFileName, BiosLocation, &BiosSize);
- DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
-
- if (Success == FALSE)
- {
- /* Stop the VDM */
- EmulatorTerminate();
- return;
- }
-
- // DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
- // L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
- // BiosLocation,
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
-
- // (PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
- // *(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
-
- /* Initialize IVT and hardware */
-
- /* Initialize the Keyboard and Video BIOS */
- if (!KbdBiosInitialize() || !VidBiosInitialize())
- {
- /* Stop the VDM */
- EmulatorTerminate();
- return;
- }
-
- /* Load VGA BIOS */
- // Success = LoadRom("v7vga.rom", (PVOID)0xC0000, &BiosSize);
- // DPRINT1("VGA BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
-
- /* Enable interrupts */
- setIF(1);
-
- ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
-
- /* Load some ROMs */
- // Success = LoadRom("boot.bin", (PVOID)0xE0000, &BiosSize);
- // DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
-
- SearchAndInitRoms(&__BiosContext);
-}
-
/* PUBLIC FUNCTIONS ***********************************************************/
VOID WINAPI BiosEquipmentService(LPWORD Stack)
// The BCT is found at F000:E6F5 for 100% compatible BIOSes.
Bct = (PBIOS_CONFIG_TABLE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5);
- /* Register the BIOS support BOPs */
- RegisterBop(BOP_BIOSINIT , BiosInitBop);
- RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
- RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
+ /**** HACK! HACK! for Windows NTVDM BIOS ****/
+ // WinNtVdmBiosSupportInitialize();
+
+ // /* Register the BIOS support BOPs */
+ // RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
+ // RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
- if (BiosFileName)
+ if (BiosFileName && BiosFileName[0] != '\0')
{
PVOID BiosLocation = NULL;
DWORD BiosSize = 0;
Success = Bios32Loaded = Bios32Initialize();
}
- /* Enable interrupts */
- setIF(1);
+ // /* Enable interrupts */
+ // setIF(1);
return Success;
}
/* DEFINES ********************************************************************/
+/* BOP Identifiers */
+#define BOP_RESET 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
+ // to let the virtual machine initialize itself
+ // the IVT and its hardware.
+#define BOP_EQUIPLIST 0x11
+#define BOP_GETMEMSIZE 0x12
+
+
+
+
#define BDA_SEGMENT 0x40
#define BIOS_SEGMENT 0xF000
#include "emulator.h"
#include "cpu/cpu.h" // for EMULATOR_FLAG_CF
+#include "cpu/bop.h"
#include "int32.h"
-// #include "bop.h"
#include "../bios.h"
#include "../rom.h"
*/
static BYTE PostCode[] =
{
- 0xCD, 0x19, // int 0x19, the bootstrap loader interrupt
+ LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_RESET, // Call BIOS POST
+ 0xCD, 0x19, // INT 0x19, the bootstrap loader interrupt
// LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_UNSIMULATE
};
return;
}
+
+VOID DosBootsectorInitialize(VOID);
+
static VOID WINAPI BiosBootstrapLoader(LPWORD Stack)
{
/*
- * In real bioses one loads the bootsector read from a diskette
- * or from a disk, to 0000:7C00 and then one runs it.
+ * In real BIOSes one loads the bootsector read from a diskette
+ * or from a disk, copy it to 0000:7C00 and then boot it.
* Since we are 32-bit VM and we hardcode our DOS at the moment,
* just call the DOS 32-bit initialization code.
*/
DPRINT1("BiosBootstrapLoader -->\n");
+ /* Load DOS */
+ DosBootsectorInitialize();
+ /* Position CPU to 0000:7C00 to boot the OS */
+ setCS(0x0000);
+ setIP(0x7C00);
+
DPRINT1("<-- BiosBootstrapLoader\n");
}
((PULONG)BaseAddress)[0x49] = (ULONG)NULL;
}
-static VOID InitializeBiosInfo(VOID)
-{
- RtlZeroMemory(Bct, sizeof(*Bct));
-
- Bct->Length = sizeof(*Bct);
- Bct->Model = BIOS_MODEL;
- Bct->SubModel = BIOS_SUBMODEL;
- Bct->Revision = BIOS_REVISION;
- Bct->Feature[0] = 0x70; // At the moment we don't support "wait for external event (INT 15/AH=41h)", we also don't have any "extended BIOS area allocated (usually at top of RAM)"; see http://www.ctyme.com/intr/rb-1594.htm#Table510
- Bct->Feature[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
- Bct->Feature[2] = 0x00;
- Bct->Feature[3] = 0x00;
- Bct->Feature[4] = 0x00;
-}
-
static VOID InitializeBiosData(VOID)
{
UCHAR Low, High;
- /* System BIOS Copyright */
- RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
-
- /* System BIOS Version */
- RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1); // FIXME: or E061, or E100 ??
-
- /* System BIOS Date */
- RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
-
- /* System BIOS Model (same as Bct->Model) */
- *(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
-
/* Initialize the BDA contents */
RtlZeroMemory(Bda, sizeof(*Bda));
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
Bda->MemorySize = MAKEWORD(Low, High);
}
-/* PUBLIC FUNCTIONS ***********************************************************/
+static VOID InitializeBiosInfo(VOID)
+{
+ RtlZeroMemory(Bct, sizeof(*Bct));
+
+ Bct->Length = sizeof(*Bct);
+ Bct->Model = BIOS_MODEL;
+ Bct->SubModel = BIOS_SUBMODEL;
+ Bct->Revision = BIOS_REVISION;
+ Bct->Feature[0] = 0x70; // At the moment we don't support "wait for external event (INT 15/AH=41h)", we also don't have any "extended BIOS area allocated (usually at top of RAM)"; see http://www.ctyme.com/intr/rb-1594.htm#Table510
+ Bct->Feature[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
+ Bct->Feature[2] = 0x00;
+ Bct->Feature[3] = 0x00;
+ Bct->Feature[4] = 0x00;
+}
+
+
/*
* The BIOS POST (Power On-Self Test)
*/
-BOOLEAN Bios32Initialize(VOID)
+VOID
+Bios32Post(VOID)
{
BOOLEAN Success;
+ DPRINT1("Bios32Post\n");
+
/* Initialize the stack */
// That's what says IBM... (stack at 30:00FF going downwards)
// setSS(0x0000);
/* Initialize the Keyboard, Video and Mouse BIOS */
if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
- return FALSE;
+ {
+ // return FALSE;
+
+ /* Stop the VDM */
+ EmulatorTerminate();
+ return;
+ }
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
SearchAndInitRoms(&BiosContext);
+ /*
+ * End of the 32-bit POST portion. We then fall back into 16-bit where
+ * the rest of the POST code is executed, typically calling INT 19h
+ * to boot up the OS.
+ */
+}
+
+static VOID WINAPI Bios32ResetBop(LPWORD Stack)
+{
+ DPRINT1("Bios32ResetBop\n");
+
+ /* Disable interrupts */
+ setIF(0);
+
+ // FIXME: Check the word at 0040h:0072h and do one of the following actions:
+ // - if the word is 1234h, perform a warm reboot (aka. Ctrl-Alt-Del);
+ // - if the word is 0000h, perform a cold reboot (aka. Reset).
+
+ /* Initialize IVT and hardware */
+
+ /* Initialize the Keyboard and Video BIOS */
+ if (!KbdBiosInitialize() || !VidBiosInitialize())
+ {
+ /* Stop the VDM */
+ EmulatorTerminate();
+ return;
+ }
+
+ /* Do the POST */
+ Bios32Post();
+
+ /* Enable interrupts */
+ setIF(1);
+}
+
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN Bios32Initialize(VOID)
+{
+ /*
+ * Initialize BIOS32 static data
+ */
+
/* Bootstrap code */
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE05B), PostCode , sizeof(PostCode ));
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF0), Bootstrap, sizeof(Bootstrap));
+ /* System BIOS Copyright */
+ RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
+
+ /* System BIOS Version */
+ RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1);
+ // FIXME: or E061, or E100 ??
+
+ /* System BIOS Date */
+ RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
+
+ /* System BIOS Model (same as Bct->Model) */
+ *(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
+
+ /* Redefine our POST function */
+ RegisterBop(BOP_RESET, Bios32ResetBop);
+
/* We are done */
return TRUE;
}
/* DEFINES ********************************************************************/
/* BOP Identifiers */
-#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
-#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
+#define BOP_LOAD_DOS 0x2B // DOS Loading and Initializing BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file.
+#define BOP_START_DOS 0x2C // DOS Starting BOP. In parameter (following bytes) we take a NULL-terminated string indicating the name of the DOS kernel file.
+#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
+#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
/* PRIVATE FUNCTIONS **********************************************************/
}
}
+#ifndef STANDALONE
+static DWORD
+WINAPI
+CommandThreadProc(LPVOID Parameter)
+{
+ BOOLEAN First = TRUE;
+ DWORD Result;
+ VDM_COMMAND_INFO CommandInfo;
+ CHAR CmdLine[MAX_PATH];
+ CHAR AppName[MAX_PATH];
+ CHAR PifFile[MAX_PATH];
+ CHAR Desktop[MAX_PATH];
+ CHAR Title[MAX_PATH];
+ ULONG EnvSize = 256;
+ PVOID Env = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
+
+ UNREFERENCED_PARAMETER(Parameter);
+ ASSERT(Env != NULL);
+
+ do
+ {
+ /* Clear the structure */
+ ZeroMemory(&CommandInfo, sizeof(CommandInfo));
+
+ /* Initialize the structure members */
+ CommandInfo.TaskId = SessionId;
+ CommandInfo.VDMState = VDM_FLAG_DOS;
+ CommandInfo.CmdLine = CmdLine;
+ CommandInfo.CmdLen = sizeof(CmdLine);
+ CommandInfo.AppName = AppName;
+ CommandInfo.AppLen = sizeof(AppName);
+ CommandInfo.PifFile = PifFile;
+ CommandInfo.PifLen = sizeof(PifFile);
+ CommandInfo.Desktop = Desktop;
+ CommandInfo.DesktopLen = sizeof(Desktop);
+ CommandInfo.Title = Title;
+ CommandInfo.TitleLen = sizeof(Title);
+ CommandInfo.Env = Env;
+ CommandInfo.EnvLen = EnvSize;
+
+ if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
+
+Command:
+ if (!GetNextVDMCommand(&CommandInfo))
+ {
+ if (CommandInfo.EnvLen > EnvSize)
+ {
+ /* Expand the environment size */
+ EnvSize = CommandInfo.EnvLen;
+ Env = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
+
+ /* Repeat the request */
+ goto Command;
+ }
+
+ break;
+ }
+
+ /* Start the process from the command line */
+ DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
+ Result = DosStartProcess(AppName, CmdLine, Env);
+ if (Result != ERROR_SUCCESS)
+ {
+ DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result);
+ // break;
+ continue;
+ }
+
+ First = FALSE;
+ }
+ while (AcceptCommands);
+
+ HeapFree(GetProcessHeap(), 0, Env);
+ return 0;
+}
+#endif
+
/* PUBLIC FUNCTIONS ***********************************************************/
-BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
+//
+// This function (equivalent of the DOS bootsector) is called by the bootstrap
+// loader *BEFORE* jumping at 0000:7C00. What we should do is to write at 0000:7C00
+// a BOP call that calls DosInitialize back. Then the bootstrap loader jumps at
+// 0000:7C00, our BOP gets called and then we can initialize the 32-bit part of the DOS.
+//
+
+/* 16-bit bootstrap code at 0000:7C00 */
+/* Of course, this is not in real bootsector format, because we don't care */
+static BYTE Bootsector1[] =
+{
+ LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_LOAD_DOS, // Call DOS Loading
+};
+/* This portion of code is run if we failed to load the DOS */
+static BYTE Bootsector2[] =
+{
+ 0xEA, // jmp far ptr
+ 0x5B, 0xE0, 0x00, 0xF0, // F000:E05B /** HACK! What to do instead?? **/
+};
+
+static VOID WINAPI DosInitialize(LPWORD Stack);
+
+VOID DosBootsectorInitialize(VOID)
{
+ /* We write the bootsector at 0000:7C00 */
+ ULONG_PTR Address = (ULONG_PTR)SEG_OFF_TO_PTR(0x0000, 0x7C00);
+ CHAR DosKernelFileName[] = ""; // No DOS file name, therefore we'll load DOS32
+
+ DPRINT1("DosBootsectorInitialize\n");
+
+ /* Write the "bootsector" */
+ RtlCopyMemory((PVOID)Address, Bootsector1, sizeof(Bootsector1));
+ Address += sizeof(Bootsector1);
+ RtlCopyMemory((PVOID)Address, DosKernelFileName, sizeof(DosKernelFileName));
+ Address += sizeof(DosKernelFileName);
+ RtlCopyMemory((PVOID)Address, Bootsector2, sizeof(Bootsector2));
+
+ /* Register the DOS Loading BOP */
+ RegisterBop(BOP_LOAD_DOS, DosInitialize);
+}
+
+
+//
+// This function is called by the DOS bootsector. We finish to load
+// the DOS, then we jump to 0070:0000.
+//
+
+/* 16-bit startup code at 0070:0000 */
+static BYTE Startup[] =
+{
+ LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_START_DOS, // Call DOS Start
+};
+
+static VOID WINAPI DosStart(LPWORD Stack);
+
+static VOID WINAPI DosInitialize(LPWORD Stack)
+{
+ BOOLEAN Success = FALSE;
+
+ /* Get the DOS kernel file name (NULL-terminated) */
+ // FIXME: Isn't it possible to use some DS:SI instead??
+ LPCSTR DosKernelFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
+ setIP(getIP() + strlen(DosKernelFileName) + 1); // Skip it
+
+ DPRINT1("DosInitialize('%s')\n", DosKernelFileName);
+
/* Register the DOS BOPs */
RegisterBop(BOP_DOS, DosSystemBop );
RegisterBop(BOP_CMD, DosCmdInterpreterBop);
- if (DosKernelFileName)
+ if (DosKernelFileName && DosKernelFileName[0] != '\0')
{
- BOOLEAN Success;
HANDLE hDosBios;
ULONG ulDosBiosSize = 0;
hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);
/* If we failed, bail out */
- if (hDosBios == NULL) return FALSE;
+ if (hDosBios == NULL) goto QuitCustom;
/* Attempt to load the DOS BIOS into memory */
Success = FileLoadByHandle(hDosBios,
/* Close the DOS BIOS file */
FileClose(hDosBios);
- if (Success)
- {
- /* Position execution pointers and return */
- setCS(0x0070);
- setIP(0x0000);
- }
+ if (!Success) goto QuitCustom;
- return Success;
+ /* Position execution pointers and return */
+ setCS(0x0070);
+ setIP(0x0000);
+
+ /* Return control */
+QuitCustom:
+ if (!Success)
+ DisplayMessage(L"Custom DOS '%S' loading failed, what to do??", DosKernelFileName);
}
else
{
- BOOLEAN Result;
+ Success = DosBIOSInitialize();
+ // Success &= DosKRNLInitialize();
+
+ if (!Success) goto Quit32;
+
+ /* Write the "bootsector" */
+ RtlCopyMemory(SEG_OFF_TO_PTR(0x0070, 0x0000), Startup, sizeof(Startup));
+
+ /* Register the DOS Starting BOP */
+ RegisterBop(BOP_START_DOS, DosStart);
+
+ /* Position execution pointers and return */
+ setCS(0x0070);
+ setIP(0x0000);
+
+ /* Return control */
+Quit32:
+ if (!Success)
+ DisplayMessage(L"DOS32 loading failed, what to do??");
+ }
+
+ if (Success)
+ {
+ /*
+ * We succeeded, deregister the DOS Loading BOP
+ * so that no app will be able to call us back.
+ */
+ RegisterBop(BOP_LOAD_DOS, NULL);
+ }
+}
+
+static VOID WINAPI DosStart(LPWORD Stack)
+{
+#ifdef STANDALONE
+ DWORD Result;
+ CHAR ApplicationName[MAX_PATH];
+ CHAR CommandLine[DOS_CMDLINE_LENGTH];
+#endif
+
+ DPRINT1("DosStart\n");
+
+ /*
+ * We succeeded, deregister the DOS Starting BOP
+ * so that no app will be able to call us back.
+ */
+ RegisterBop(BOP_START_DOS, NULL);
+
+ /* Load the mouse driver */
+ DosMouseInitialize();
+
+#ifndef STANDALONE
+
+ /* Create the GetNextVDMCommand thread */
+ CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL);
+ if (CommandThread == NULL)
+ {
+ wprintf(L"FATAL: Failed to create the command processing thread: %d\n", GetLastError());
+ goto Quit;
+ }
+
+ /* Wait for the command thread to exit */
+ WaitForSingleObject(CommandThread, INFINITE);
- Result = DosBIOSInitialize();
- DosMouseInitialize(); // FIXME: Should be done by the DOS BIOS
- // Result &= DosKRNLInitialize();
+ /* Close the thread handle */
+ CloseHandle(CommandThread);
- return Result;
+#else
+
+ if (NtVdmArgc >= 2)
+ {
+ WideCharToMultiByte(CP_ACP, 0, NtVdmArgv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
+
+ if (NtVdmArgc >= 3)
+ WideCharToMultiByte(CP_ACP, 0, NtVdmArgv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
+ else
+ strcpy(CommandLine, "");
}
+ else
+ {
+ DisplayMessage(L"Invalid DOS command line\n");
+ goto Quit;
+ }
+
+ /* Start the process from the command line */
+ DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
+ Result = DosStartProcess(ApplicationName,
+ CommandLine,
+ GetEnvironmentStrings());
+ if (Result != ERROR_SUCCESS)
+ {
+ DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result);
+ goto Quit;
+ }
+
+#endif
+
+Quit:
+ /* Stop the VDM */
+ EmulatorTerminate();
}
+
+
/* PUBLIC EXPORTED APIS *******************************************************/
// demLFNCleanup
/* FUNCTIONS ******************************************************************/
-BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames);
-
DWORD
WINAPI
demClientErrorEx
#include "ntvdm.h"
#include "emulator.h"
+#include "cpu/cpu.h"
#include "clock.h"
#include "hardware/ps2.h"
static HANDLE ConsoleInput = INVALID_HANDLE_VALUE;
static HANDLE ConsoleOutput = INVALID_HANDLE_VALUE;
static DWORD OrgConsoleInputMode, OrgConsoleOutputMode;
-static BOOLEAN AcceptCommands = TRUE;
-static HANDLE CommandThread = NULL;
-
-static HMENU hConsoleMenu = NULL;
-static INT VdmMenuPos = -1;
-static BOOLEAN ShowPointer = FALSE;
+// For DOS
#ifndef STANDALONE
+BOOLEAN AcceptCommands = TRUE;
+HANDLE CommandThread = NULL;
ULONG SessionId = 0;
#endif
HANDLE VdmTaskEvent = NULL;
+// Command line of NTVDM
+INT NtVdmArgc;
+WCHAR** NtVdmArgv;
+
+
+static HMENU hConsoleMenu = NULL;
+static INT VdmMenuPos = -1;
+static BOOLEAN ShowPointer = FALSE;
+
/*
* Those menu helpers were taken from the GUI frontend in winsrv.dll
*/
case CTRL_BREAK_EVENT:
{
/* Call INT 23h */
+ DPRINT1("Ctrl-C/Break: Call INT 23h\n");
EmulatorInterrupt(0x23);
break;
}
if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT)
{
/* Exit immediately */
+#ifndef STANDALONE
if (CommandThread) TerminateThread(CommandThread, 0);
+#endif
EmulatorTerminate();
}
+#ifndef STANDALONE
else
{
/* Stop accepting new commands */
AcceptCommands = FALSE;
}
+#endif
break;
}
DPRINT1("Focus events not handled\n");
}
-#ifndef STANDALONE
-static DWORD
-WINAPI
-CommandThreadProc(LPVOID Parameter)
-{
- BOOLEAN First = TRUE;
- DWORD Result;
- VDM_COMMAND_INFO CommandInfo;
- CHAR CmdLine[MAX_PATH];
- CHAR AppName[MAX_PATH];
- CHAR PifFile[MAX_PATH];
- CHAR Desktop[MAX_PATH];
- CHAR Title[MAX_PATH];
- ULONG EnvSize = 256;
- PVOID Env = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
-
- UNREFERENCED_PARAMETER(Parameter);
- ASSERT(Env != NULL);
-
- do
- {
- /* Clear the structure */
- ZeroMemory(&CommandInfo, sizeof(CommandInfo));
-
- /* Initialize the structure members */
- CommandInfo.TaskId = SessionId;
- CommandInfo.VDMState = VDM_FLAG_DOS;
- CommandInfo.CmdLine = CmdLine;
- CommandInfo.CmdLen = sizeof(CmdLine);
- CommandInfo.AppName = AppName;
- CommandInfo.AppLen = sizeof(AppName);
- CommandInfo.PifFile = PifFile;
- CommandInfo.PifLen = sizeof(PifFile);
- CommandInfo.Desktop = Desktop;
- CommandInfo.DesktopLen = sizeof(Desktop);
- CommandInfo.Title = Title;
- CommandInfo.TitleLen = sizeof(Title);
- CommandInfo.Env = Env;
- CommandInfo.EnvLen = EnvSize;
-
- if (First) CommandInfo.VDMState |= VDM_FLAG_FIRST_TASK;
-
-Command:
- if (!GetNextVDMCommand(&CommandInfo))
- {
- if (CommandInfo.EnvLen > EnvSize)
- {
- /* Expand the environment size */
- EnvSize = CommandInfo.EnvLen;
- Env = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Env, EnvSize);
-
- /* Repeat the request */
- goto Command;
- }
-
- break;
- }
-
- /* Start the process from the command line */
- DPRINT1("Starting '%s' ('%s')...\n", AppName, CmdLine);
- Result = DosStartProcess(AppName, CmdLine, Env);
- if (Result != ERROR_SUCCESS)
- {
- DisplayMessage(L"Could not start '%S'. Error: %u", AppName, Result);
- // break;
- continue;
- }
-
- First = FALSE;
- }
- while (AcceptCommands);
-
- HeapFree(GetProcessHeap(), 0, Env);
- return 0;
-}
-#endif
-
INT
wmain(INT argc, WCHAR *argv[])
{
#ifdef STANDALONE
- DWORD Result;
- CHAR ApplicationName[MAX_PATH];
- CHAR CommandLine[DOS_CMDLINE_LENGTH];
-
- if (argc >= 2)
- {
- WideCharToMultiByte(CP_ACP, 0, argv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
-
- if (argc >= 3) WideCharToMultiByte(CP_ACP, 0, argv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
- else strcpy(CommandLine, "");
- }
- else
+ if (argc < 2)
{
wprintf(L"\nReactOS Virtual DOS Machine\n\n"
L"Usage: NTVDM <executable> [<parameters>]\n");
#endif
+ NtVdmArgc = argc;
+ NtVdmArgv = argv;
+
DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
/* Create the task event */
goto Cleanup;
}
- /* Initialize the VDM DOS kernel */
- if (!DosInitialize(NULL))
- {
- wprintf(L"FATAL: Failed to initialize the VDM DOS kernel.\n");
- goto Cleanup;
- }
-
-#ifndef STANDALONE
-
- /* Create the GetNextVDMCommand thread */
- CommandThread = CreateThread(NULL, 0, &CommandThreadProc, NULL, 0, NULL);
- if (CommandThread == NULL)
- {
- wprintf(L"FATAL: Failed to create the command processing thread: %d\n", GetLastError());
- goto Cleanup;
- }
-
- /* Wait for the command thread to exit */
- WaitForSingleObject(CommandThread, INFINITE);
-
- /* Close the thread handle */
- CloseHandle(CommandThread);
-
-#else
-
- /* Start the process from the command line */
- DPRINT1("Starting '%s' ('%s')...\n", ApplicationName, CommandLine);
- Result = DosStartProcess(ApplicationName,
- CommandLine,
- GetEnvironmentStrings());
- if (Result != ERROR_SUCCESS)
- {
- DisplayMessage(L"Could not start '%S'. Error: %u", ApplicationName, Result);
- goto Cleanup;
- }
-
-#endif
+ /* Let's go! Start simulation */
+ CpuSimulate();
Cleanup:
BiosCleanup();
/* FUNCTIONS ******************************************************************/
#ifndef STANDALONE
+extern BOOLEAN AcceptCommands;
+extern HANDLE CommandThread;
extern ULONG SessionId;
#endif
extern HANDLE VdmTaskEvent;
+// Command line of NTVDM
+extern INT NtVdmArgc;
+extern WCHAR** NtVdmArgv;
+
+
/*
* Interface functions
*/