[NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 4 Oct 2014 13:36:17 +0000 (13:36 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 4 Oct 2014 13:36:17 +0000 (13:36 +0000)
- Move almost all the DOS command launch thread into dem.c,
- Rework the code so that now, when we want to either load our BIOS32 or a custom one, we start their execution at F000:FFF0 as it should be,
- For modularity purposes (ie. to be able one day to load real OSes in our ntvdm), implement INT 19h (bootstrap loader) so that it calls a (temporary) dos bootsector loader that writes some bootstrap code at 0000:7c00, then the INT 19h runs this code, that has as an effect to load our DOS32 (for a real OS, the MBR code goes to 0000:7c00 and is then run).

svn path=/trunk/; revision=64521

reactos/subsystems/ntvdm/bios/bios.c
reactos/subsystems/ntvdm/bios/bios.h
reactos/subsystems/ntvdm/bios/bios32/bios32.c
reactos/subsystems/ntvdm/dos/dem.c
reactos/subsystems/ntvdm/dos/dem.h
reactos/subsystems/ntvdm/ntvdm.c
reactos/subsystems/ntvdm/ntvdm.h

index ad04e48..7b6d038 100644 (file)
@@ -25,7 +25,7 @@
 /* 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)
@@ -140,12 +67,14 @@ BiosInitialize(IN LPCSTR BiosFileName)
     // 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;
@@ -199,8 +128,8 @@ BiosInitialize(IN LPCSTR BiosFileName)
         Success = Bios32Loaded = Bios32Initialize();
     }
 
-    /* Enable interrupts */
-    setIF(1);
+    // /* Enable interrupts */
+    // setIF(1);
 
     return Success;
 }
index 808e013..5799db5 100644 (file)
 
 /* 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
 
index 46d139f..c6fbc84 100644 (file)
@@ -15,8 +15,8 @@
 
 #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"
@@ -129,7 +129,8 @@ static BYTE Bootstrap[] =
  */
 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
 };
 
@@ -278,17 +279,26 @@ static VOID WINAPI BiosRomBasic(LPWORD Stack)
     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");
 }
 
@@ -510,37 +520,10 @@ static VOID InitializeBiosInt32(VOID)
     ((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;
@@ -556,15 +539,33 @@ static VOID InitializeBiosData(VOID)
     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);
@@ -587,7 +588,13 @@ BOOLEAN Bios32Initialize(VOID)
 
     /* 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 !! /////////////////////
 
@@ -597,10 +604,70 @@ BOOLEAN Bios32Initialize(VOID)
 
     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;
 }
index 13fde99..2e20a9c 100644 (file)
 /* 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 **********************************************************/
 
@@ -185,17 +187,157 @@ static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
     }
 }
 
+#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;
 
@@ -203,7 +345,7 @@ BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
         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,
@@ -220,27 +362,122 @@ BOOLEAN DosInitialize(IN LPCSTR DosKernelFileName)
         /* 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
index 1e5f2de..297ac26 100644 (file)
@@ -20,8 +20,6 @@
 
 /* FUNCTIONS ******************************************************************/
 
-BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames);
-
 DWORD
 WINAPI
 demClientErrorEx
index ecdaa7d..ab75aff 100644 (file)
@@ -12,6 +12,7 @@
 
 #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
  */
@@ -198,6 +205,7 @@ ConsoleCtrlHandler(DWORD ControlType)
         case CTRL_BREAK_EVENT:
         {
             /* Call INT 23h */
+            DPRINT1("Ctrl-C/Break: Call INT 23h\n");
             EmulatorInterrupt(0x23);
             break;
         }
@@ -206,14 +214,18 @@ ConsoleCtrlHandler(DWORD ControlType)
             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;
         }
@@ -361,100 +373,12 @@ VOID FocusEventHandler(PFOCUS_EVENT_RECORD FocusEvent)
     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");
@@ -481,6 +405,9 @@ wmain(INT argc, WCHAR *argv[])
 
 #endif
 
+    NtVdmArgc = argc;
+    NtVdmArgv = argv;
+
     DPRINT1("\n\n\nNTVDM - Starting...\n\n\n");
 
     /* Create the task event */
@@ -508,43 +435,8 @@ wmain(INT argc, WCHAR *argv[])
         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();
index 68ca34c..1bfe64f 100644 (file)
@@ -41,11 +41,18 @@ DWORD WINAPI SetLastConsoleEventActive(VOID);
 /* 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
  */