[NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 4 Aug 2015 20:17:05 +0000 (20:17 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 4 Aug 2015 20:17:05 +0000 (20:17 +0000)
- Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed).
- Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode).
- Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon...

- Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434).
- Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools.
- During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside).
- Store statically the BIOS configuration table.

- Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys.
- Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard.
- Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported.
- Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS.
- Implement CMOS century register support.

svn path=/trunk/; revision=68598

17 files changed:
reactos/subsystems/mvdm/ntvdm/bios/bios.c
reactos/subsystems/mvdm/ntvdm/bios/bios.h
reactos/subsystems/mvdm/ntvdm/bios/bios32/bios32.c
reactos/subsystems/mvdm/ntvdm/bios/bios32/kbdbios32.c
reactos/subsystems/mvdm/ntvdm/bios/bios32/kbdbios32.h
reactos/subsystems/mvdm/ntvdm/bios/bios32/moubios32.c
reactos/subsystems/mvdm/ntvdm/bios/bios32/moubios32.h
reactos/subsystems/mvdm/ntvdm/bios/bios32/vidbios32.c
reactos/subsystems/mvdm/ntvdm/bios/kbdbios.c
reactos/subsystems/mvdm/ntvdm/bios/rom.c
reactos/subsystems/mvdm/ntvdm/bios/rom.h
reactos/subsystems/mvdm/ntvdm/bios/vidbios.c
reactos/subsystems/mvdm/ntvdm/bios/vidbios.h
reactos/subsystems/mvdm/ntvdm/hardware/cmos.c
reactos/subsystems/mvdm/ntvdm/hardware/cmos.h
reactos/subsystems/mvdm/ntvdm/ntvdm.c
reactos/subsystems/mvdm/ntvdm/ntvdm.h

index 3043e09..e2cf18a 100644 (file)
 #include "io.h"
 #include "hardware/cmos.h"
 
+#include <stdlib.h>
+
 /* 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.
+                                // to let the virtual machine perform the POST.
 #define BOP_EQUIPLIST   0x11
 #define BOP_GETMEMSIZE  0x12
 
@@ -43,95 +44,96 @@ PBIOS_CONFIG_TABLE Bct;
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-VOID WINAPI BiosEquipmentService(LPWORD Stack)
+VOID WINAPI
+WinNtVdmBiosReset(LPWORD Stack)
 {
-    /* Return the equipment list */
-    setAX(Bda->EquipmentList);
-}
+    DisplayMessage(L"You are loading Windows NTVDM BIOS!\n");
+    // Bios32Post(Stack);
 
-VOID WINAPI BiosGetMemorySize(LPWORD Stack)
-{
-    /* Return the conventional memory size in kB, typically 640 kB */
-    setAX(Bda->MemorySize);
+    DisplayMessage(L"ReactOS NTVDM doesn't support Windows NTVDM BIOS at the moment. The VDM will shut down.");
+    EmulatorTerminate();
 }
 
 BOOLEAN
-BiosInitialize(IN LPCSTR BiosFileName)
+BiosInitialize(IN LPCSTR BiosFileName,
+               IN LPCSTR RomFiles OPTIONAL)
 {
     BOOLEAN Success = FALSE;
+    BOOLEAN Success2 = FALSE;
+    LPCSTR RomFile;
+    LPSTR ptr;
+    ULONG RomAddress;
+    CHAR RomFileName[MAX_PATH + 10 + 1];
 
     /* Disable interrupts */
     setIF(0);
 
     /* Initialize the BDA and the BCT pointers */
-    Bda =    (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0x0000);
+    Bda =    (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT , 0x0000);
     // The BCT is found at F000:E6F5 for 100% compatible BIOSes.
     Bct = (PBIOS_CONFIG_TABLE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5);
 
-    /**** HACK! HACK! for Windows NTVDM BIOS ****/
-    // WinNtVdmBiosSupportInitialize();
-
-    // /* Register the BIOS support BOPs */
-    // RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
-    // RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
+    /* Register the BIOS support BOPs */
+    RegisterBop(BOP_RESET, WinNtVdmBiosReset);          // Needed for Windows NTVDM (SoftPC) BIOS.
+    RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);  // Needed by Windows NTVDM (SoftPC) BIOS
+    RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);     // and also NTDOS!!
 
-    if (BiosFileName && BiosFileName[0] != '\0')
+    if (BiosFileName == NULL)
+    {
+        Success = Bios32Loaded = Bios32Initialize();
+    }
+    else if (BiosFileName[0] != '\0')
     {
         PVOID BiosLocation = NULL;
-        DWORD BiosSize = 0;
-
-        Success = LoadBios(BiosFileName, &BiosLocation, &BiosSize);
-        DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
-
-        if (!Success) return FALSE;
-
-        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));
-
-        DisplayMessage(L"POST at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
-                       TO_LINEAR(getCS(), getIP()),
-                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 0),
-                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 1),
-                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 2),
-                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 3),
-                       *(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 4));
-
-        /* Boot it up */
-
-        /*
-         * The CPU is already in reset-mode so that
-         * CS:IP points to F000:FFF0 as required.
-         */
-        DisplayMessage(L"CS=0x%p ; IP=0x%p", getCS(), getIP());
-        // setCS(0xF000);
-        // setIP(0xFFF0);
 
-        Success = TRUE;
+        Success = LoadBios(BiosFileName, &BiosLocation, NULL);
+        DPRINT1("BIOS file '%s' loading %s at address 0x%08x; GetLastError() = %u\n",
+                BiosFileName, Success ? "succeeded" : "failed", BiosLocation, GetLastError());
     }
-    else
+    else // if (BiosFileName[0] == '\0')
     {
-        WriteProtectRom((PVOID)ROM_AREA_START,
-                        ROM_AREA_END - ROM_AREA_START + 1);
+        /* Do nothing */
+        Success = TRUE;
+    }
 
-        Success = Bios32Loaded = Bios32Initialize();
+    /* Bail out now if we failed to load any BIOS file */
+    if (!Success) return FALSE;
+
+    /* Load optional ROMs */
+    if (RomFiles)
+    {
+        RomFile = RomFiles;
+        while (*RomFile)
+        {
+            strncpy(RomFileName, RomFile, ARRAYSIZE(RomFileName));
+            RomFileName[ARRAYSIZE(RomFileName)-1] = '\0';
+
+            ptr = strchr(RomFileName, '|'); // Since '|' is forbidden as a valid file name, we use it as a separator for the ROM address.
+            if (!ptr) goto Skip;
+            *ptr++ = '\0';
+
+            RomAddress = strtoul(ptr, NULL, 0); // ROM segment
+            RomAddress <<= 4; // Convert to real address
+            if (RomAddress == 0) goto Skip;
+
+            Success2 = LoadRom(RomFileName, (PVOID)RomAddress, NULL);
+            DPRINT1("ROM file '%s' loading %s at address 0x%08x; GetLastError() = %u\n",
+                    RomFileName, Success2 ? "succeeded" : "failed", RomAddress, GetLastError());
+
+Skip:
+            RomFile += strlen(RomFile) + 1;
+        }
     }
 
+    /*
+     * Boot it up.
+     * The CPU is already in reset-mode so that
+     * CS:IP points to F000:FFF0 as required.
+     */
+    // DisplayMessage(L"CS:IP=%04X:%04X", getCS(), getIP());
+    // setCS(0xF000);
+    // setIP(0xFFF0);
+
     // /* Enable interrupts */
     // setIF(1);
 
index e8f30ba..1fe7b14 100644 (file)
@@ -18,8 +18,7 @@
 
 /* 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.
+                                // to let the virtual machine perform the POST.
 #define BOP_EQUIPLIST   0x11
 #define BOP_GETMEMSIZE  0x12
 
 #define BDA_SEGMENT     0x40
 #define BIOS_SEGMENT    0xF000
 
-// HACK: Disable FPU for now because it is not fully ready yet for being used
-// by all applications (e.g. QBasic runtime would use the native FPU if the bit
-// is set, but then subsequently fails, unless the FPU bit is unset in that case
-// QBasic uses its emulated FPU).
 #define BIOS_EQUIPMENT_LIST 0x2E    // Bit1: FPU, Bit 2: Mouse
 
 #pragma pack(push, 1)
@@ -104,7 +99,8 @@ typedef struct
     BYTE Reserved5[2];                          // 0x90
     BYTE Reserved6[2];                          // 0x92
     BYTE Reserved7[2];                          // 0x94
-    WORD KeybdStatusFlags;                      // 0x96
+    BYTE KeybdStatusFlags;                      // 0x96
+    BYTE KeybdLedFlags;                         // 0x97
     DWORD Reserved9;                            // 0x98
     DWORD Reserved10;                           // 0x9c
     DWORD Reserved11[2];                        // 0xa0
@@ -165,7 +161,8 @@ VOID WINAPI BiosEquipmentService(LPWORD Stack);
 VOID WINAPI BiosGetMemorySize(LPWORD Stack);
 
 BOOLEAN
-BiosInitialize(IN LPCSTR BiosFileName);
+BiosInitialize(IN LPCSTR BiosFileName,
+               IN LPCSTR RomFiles OPTIONAL);
 
 VOID
 BiosCleanup(VOID);
index a4df846..29a457c 100644 (file)
@@ -10,8 +10,9 @@
 
 #define NDEBUG
 
-/* For BIOS Version number */
+/* BIOS Version number and Copyright */
 #include <reactos/buildno.h>
+#include <reactos/version.h>
 
 #include "ntvdm.h"
 #include "emulator.h"
@@ -106,19 +107,39 @@ $fffe ; System Model ID
 #define BIOS_REVISION   0x00
 // FIXME: Find a nice PS/2 486 + 487 BIOS combination!
 
+static const BIOS_CONFIG_TABLE BiosConfigTable =
+{
+    sizeof(BIOS_CONFIG_TABLE),  // Length
+
+    BIOS_MODEL,     // BIOS Model
+    BIOS_SUBMODEL,  // BIOS Sub-Model
+    BIOS_REVISION,  // BIOS Revision
+
+    // Feature bytes
+    {
+        0x78,       // At the moment we don't have any Extended BIOS Area; see http://www.ctyme.com/intr/rb-1594.htm#Table510
+        0x00,       // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
+        0x10,       // Bit 4: POST supports ROM-to-RAM enable/disable
+        0x00,
+        0x00
+    }
+};
+
+
 /*
  * WARNING! For compatibility purposes the string "IBM" should be at F000:E00E .
- * Some programs alternatively look at "COPR. IBM" that is at F000:E008 .
+ * Some programs otherwise look for "COPR. IBM" at F000:E008 .
  */
-static const CHAR BiosCopyright[] = "0000000 NTVDM IBM Compatible 486 32-bit BIOS Copyright (C) ReactOS Team 1996-2014";
-static const CHAR BiosVersion[]   = "ReactOS NTVDM 32-bit BIOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")";
+static const CHAR BiosCopyright[] = "0000000 NTVDM IBM COMPATIBLE 486 BIOS COPYRIGHT (C) ReactOS Team 1996-"COPYRIGHT_YEAR;
+static const CHAR BiosVersion[]   = "ReactOS NTVDM 32-bit BIOS Version "KERNEL_VERSION_STR"\0"
+                                    "BIOS32 Version "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")";
 static const CHAR BiosDate[]      = "06/17/13";
 
 C_ASSERT(sizeof(BiosCopyright)-1 <= 0x5B); // Ensures that we won't overflow on the POST Code starting at F000:E05B
 C_ASSERT(sizeof(BiosDate)-1      == 0x08);
 
 /* 16-bit bootstrap code at F000:FFF0 */
-static BYTE Bootstrap[] =
+static const BYTE Bootstrap[] =
 {
     0xEA,                   // jmp far ptr
     0x5B, 0xE0, 0x00, 0xF0, // F000:E05B
@@ -128,7 +149,7 @@ static BYTE Bootstrap[] =
  * POST code at F000:E05B. All the POST is done in 32 bit
  * and only at the end it calls the bootstrap interrupt.
  */
-static BYTE PostCode[] =
+static const BYTE PostCode[] =
 {
     LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_RESET,  // Call BIOS POST
     0xCD, BIOS_BOOTSTRAP_LOADER,                            // INT 0x19
@@ -145,6 +166,18 @@ static VOID WINAPI BiosException(LPWORD Stack)
     EmulatorException(ExceptionNumber, Stack);
 }
 
+VOID WINAPI BiosEquipmentService(LPWORD Stack)
+{
+    /* Return the equipment list */
+    setAX(Bda->EquipmentList);
+}
+
+VOID WINAPI BiosGetMemorySize(LPWORD Stack)
+{
+    /* Return the conventional memory size in kB, typically 640 kB */
+    setAX(Bda->MemorySize);
+}
+
 static VOID WINAPI BiosMiscService(LPWORD Stack)
 {
     switch (getAH())
@@ -162,7 +195,7 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
             break;
         }
 
-        /* Wait On External Event */
+        /* Wait on External Event */
         case 0x41:
         {
             BYTE Value;
@@ -242,7 +275,6 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
 
             /* Repeat the BOP if we shouldn't return */
             setCF(!Return);
-
             break;
         }
 
@@ -272,7 +304,6 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
 
             /* Clear CF */
             Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
-
             break;
         }
 
@@ -325,7 +356,6 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
 
             /* Clear CF */
             Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
-
             break;
         }
 
@@ -335,7 +365,7 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
             DPRINT1("BIOS INT 15h, AH=89h \"Switch to Protected Mode\" is UNIMPLEMENTED");
 
             Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
-            break;
+            goto Default;
         }
 
         /* Get Configuration */
@@ -349,28 +379,44 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
             /* Call successful; clear CF */
             setAH(0x00);
             Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
-
             break;
         }
 
         /* Return Extended-Bios Data-Area Segment Address (PS) */
         case 0xC1:
         {
-            // Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
-            // setES(???);
-
-            UNIMPLEMENTED;
-
             /* We do not support EBDA yet */
+            UNIMPLEMENTED;
             Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
-
-            break;
+            goto Default;
         }
 
         /* Pointing Device BIOS Interface (PS) */
         case 0xC2:
         {
             BiosMousePs2Interface(Stack);
+            UNIMPLEMENTED; // Remove it when BiosMousePs2Interface is implemented!
+            goto Default;
+        }
+
+        /* Get CPU Type and Mask Revision */
+        case 0xC9:
+        {
+            /*
+             * We can see this function as a CPUID replacement.
+             * See Ralf Brown: http://www.ctyme.com/intr/rb-1613.htm
+             * for more information.
+             */
+
+            /*
+             * Fast486 is a 486DX with FPU included,
+             * but old enough to not support CPUID.
+             */
+            setCX(0x0400);
+
+            /* Call successful; clear CF */
+            setAH(0x00);
+            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
             break;
         }
 
@@ -437,10 +483,19 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
             break;
         }
 
-        default:
+        default: Default:
         {
             DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
                     getAH());
+
+            /*
+             * The original signification of the error code 0x86 is that
+             * no PC Cassette is present. The CF is also set in this case.
+             * To keep backward compatibility, newer BIOSes use this value
+             * to indicate an unimplemented call in INT 15h.
+             */
+            setAH(0x86);
+            Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
         }
     }
 }
@@ -490,6 +545,7 @@ static VOID WINAPI BiosTimeService(LPWORD Stack)
 {
     switch (getAH())
     {
+        /* Get System Time */
         case 0x00:
         {
             /* Set AL to 1 if midnight had passed, 0 otherwise */
@@ -505,6 +561,7 @@ static VOID WINAPI BiosTimeService(LPWORD Stack)
             break;
         }
 
+        /* Set System Time */
         case 0x01:
         {
             /* Set the tick count to CX:DX */
@@ -516,6 +573,62 @@ static VOID WINAPI BiosTimeService(LPWORD Stack)
             break;
         }
 
+        /* Get Real-Time Clock Time */
+        case 0x02:
+        {
+            UCHAR StatusB;
+
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_HOURS);
+            setCH(IOReadB(CMOS_DATA_PORT));
+
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_MINUTES);
+            setCL(IOReadB(CMOS_DATA_PORT));
+
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_SECONDS);
+            setDH(IOReadB(CMOS_DATA_PORT));
+
+            /* Daylight Savings Time */
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_STATUS_B);
+            StatusB = IOReadB(CMOS_DATA_PORT);
+            setDL(StatusB & 0x01);
+
+            /* Clear CF */
+            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            break;
+        }
+
+        // /* Set Real-Time Clock Time */
+        // case 0x03:
+        // {
+        //     break;
+        // }
+
+        /* Get Real-Time Clock Date */
+        case 0x04:
+        {
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_CENTURY);
+            setCH(IOReadB(CMOS_DATA_PORT));
+
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_YEAR);
+            setCL(IOReadB(CMOS_DATA_PORT));
+
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_MONTH);
+            setDH(IOReadB(CMOS_DATA_PORT));
+
+            IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_DAY);
+            setDL(IOReadB(CMOS_DATA_PORT));
+
+            /* Clear CF */
+            Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+            break;
+        }
+
+        // /* Set Real-Time Clock Date */
+        // case 0x05:
+        // {
+        //     break;
+        // }
+
         default:
         {
             DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
@@ -675,7 +788,7 @@ static VOID InitializeBiosInt32(VOID)
     /* Zero out all of the IVT (0x00 -- 0xFF) */
     RtlZeroMemory(BaseAddress, 0x0100 * sizeof(ULONG));
 
-#ifdef ADVANCED_DEBUGGING
+#if defined(ADVANCED_DEBUGGING) && (ADVANCED_DEBUGGING_LEVEL >= 3)
     // Initialize all the interrupt vectors to the default one.
     for (i = 0x00; i <= 0xFF; i++)
         RegisterBiosInt32(i, NULL);
@@ -756,36 +869,21 @@ static VOID InitializeBiosData(VOID)
     Bda->MemorySize = MAKEWORD(Low, High);
 }
 
-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)
  */
-static VOID
+/*static*/ VOID
 WINAPI
 Bios32Post(LPWORD Stack)
 {
     static BOOLEAN FirstBoot = TRUE;
-#if 0
-    BOOLEAN Success;
-#endif
     BYTE ShutdownStatus;
 
+    /*
+     * Initialize BIOS/Keyboard/Video RAM dynamic data
+     */
+
     DPRINT("Bios32Post\n");
 
     /* Disable interrupts */
@@ -879,7 +977,6 @@ Bios32Post(LPWORD Stack)
      * - if the word is 0000h, perform a cold reboot (aka. Reset). Everything gets initialized.
      * - if the word is 1234h, perform a warm reboot (aka. Ctrl-Alt-Del). Some stuff is skipped.
      */
-
     switch (Bda->SoftReset)
     {
         case 0x0000:
@@ -906,17 +1003,22 @@ Bios32Post(LPWORD Stack)
 
     FirstBoot = FALSE;
 
-    /* Initialize the BDA and the BIOS ROM Information */
+    /* Initialize the BDA */
     InitializeBiosData();
-    InitializeBiosInfo();
 
     /* Initialize the User Data Area at 0050:XXXX */
     RtlZeroMemory(SEG_OFF_TO_PTR(0x50, 0x0000), sizeof(USER_DATA_AREA));
 
+
+
+    //////// NOTE: This is more or less bios-specific ////////
+
     /*
      * Initialize IVT and hardware
      */
 
+    // WriteUnProtectRom(...);
+
     /* Register the BIOS 32-bit Interrupts */
     InitializeBiosInt32();
 
@@ -924,30 +1026,15 @@ Bios32Post(LPWORD Stack)
     BiosHwSetup();
 
     /* Initialize the Keyboard, Video and Mouse BIOS */
-    if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
-    {
-        /* Stop the VDM */
-        EmulatorTerminate();
-        return;
-    }
+    KbdBios32Post();
+    VidBiosPost();
+    MouseBios32Post();
 
-#if 0
-    /* Initialize the Keyboard and Video BIOS */
-    if (!KbdBiosInitialize() || !VidBiosInitialize())
-    {
-        /* Stop the VDM */
-        EmulatorTerminate();
-        return;
-    }
-#endif
+    // WriteProtectRom(...);
+
+    //////// End of more or less bios-specific section ///////
 
-    ///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
 
-#if 0
-    /* Load some ROMs */
-    Success = LoadRom("boot.bin", (PVOID)0xE0000, NULL);
-    DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
-#endif
 
     SearchAndInitRoms(&BiosContext);
 
@@ -968,29 +1055,42 @@ Quit:
 BOOLEAN Bios32Initialize(VOID)
 {
     /*
-     * Initialize BIOS32 static data
+     * Initialize BIOS/Keyboard/Video ROM 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);
+    RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
 
     /* System BIOS Version */
-    RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1);
-    // FIXME: or E061, or E100 ??
+    RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE070), BiosVersion, sizeof(BiosVersion)-1);
 
     /* System BIOS Date */
-    RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
+    RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
+
+    /* Bootstrap code */
+    RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE05B), PostCode , sizeof(PostCode ));
+    RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xFFF0), Bootstrap, sizeof(Bootstrap));
+
+    /* BIOS ROM Information */
+    RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5), &BiosConfigTable, sizeof(BiosConfigTable));
 
     /* System BIOS Model (same as Bct->Model) */
-    *(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
+    *(PBYTE)(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xFFFE)) = BIOS_MODEL;
+
+    /* Initialize the Keyboard and Video BIOS */
+    if (!KbdBiosInitialize() || !VidBiosInitialize() || !MouseBiosInitialize())
+    {
+        /* Stop the VDM */
+        EmulatorTerminate();
+        return FALSE;
+    }
 
     /* Redefine our POST function */
     RegisterBop(BOP_RESET, Bios32Post);
 
+    WriteProtectRom((PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000),
+                    ROM_AREA_END - TO_LINEAR(BIOS_SEGMENT, 0x0000) + 1);
+
     /* We are done */
     return TRUE;
 }
@@ -999,7 +1099,7 @@ VOID Bios32Cleanup(VOID)
 {
     MouseBios32Cleanup();
     VidBios32Cleanup();
-    KbdBios32Cleanup();
+    KbdBiosCleanup();
 }
 
 /* EOF */
index 1eef4b8..6f12851 100644 (file)
@@ -80,7 +80,8 @@ static BOOLEAN BiosKbdBufferPop(VOID)
     return TRUE;
 }
 
-static VOID WINAPI BiosKeyboardService(LPWORD Stack)
+/* static */
+VOID WINAPI BiosKeyboardService(LPWORD Stack)
 {
     switch (getAH())
     {
@@ -168,11 +169,16 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
         case 0x12:
         {
             /*
-             * Be careful! The returned word is similar to Bda->KeybdShiftFlags
+             * Be careful! The returned word is similar to 'Bda->KeybdShiftFlags'
              * but the high byte is organized differently:
-             * the bytes 2 and 3 of the high byte are not the same...
+             * the bits 2 and 3 of the high byte are not the same:
+             * instead they correspond to the right CTRL and ALT keys as specified
+             * in bits 2 and 3 of LOBYTE(Bda->KeybdStatusFlags).
              */
-            WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
+            // Bda->KeybdShiftFlags & 0xF3FF;
+            WORD KeybdShiftFlags = MAKEWORD(LOBYTE(Bda->KeybdShiftFlags),
+                                               (HIBYTE(Bda->KeybdShiftFlags ) & 0xF3) |
+                                               (LOBYTE(Bda->KeybdStatusFlags) & 0x0C));
 
             /* Return the extended keyboard shift status word */
             setAX(KeybdShiftFlags);
@@ -188,7 +194,8 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
 }
 
 // Keyboard IRQ 1
-static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
+/* static */
+VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
 {
     static BOOLEAN Extended = FALSE;
     BOOLEAN SkipScanCode;
@@ -222,9 +229,14 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
     if (ScanCode == 0xE0)
     {
         Extended = TRUE;
+        Bda->KeybdStatusFlags |= 0x02;
         goto Quit;
     }
 
+    // FIXME: For diagnostic purposes. We should decide what to do then!!
+    if (ScanCode == 0xE1)
+        DPRINT1("BiosKeyboardIrq, ScanCode == 0xE1\n");
+
     /* Check whether CF is clear. If so, skip the scan code. */
     if (SkipScanCode) goto Quit;
 
@@ -249,10 +261,12 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
                 break;
             }
 
-            case VK_CONTROL:
             case VK_SHIFT:
             case VK_LSHIFT:
             case VK_RSHIFT:
+            case VK_CONTROL:
+            case VK_RCONTROL:
+            case VK_LCONTROL:
             case VK_MENU:
             case VK_LMENU:
             case VK_RMENU:
@@ -288,19 +302,27 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
 
     /* Clear the keyboard flags */
     Bda->KeybdShiftFlags = 0;
+    // Release right CTRL and ALT keys
+    Bda->KeybdStatusFlags &= ~(BDA_KBDFLAG_RCTRL | BDA_KBDFLAG_RALT);
 
     /* Set the appropriate flags based on the state */
-    if (BiosKeyboardMap[VK_SHIFT]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
+    // SHIFT
     if (BiosKeyboardMap[VK_RSHIFT]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RSHIFT;
     if (BiosKeyboardMap[VK_LSHIFT]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
+    if (BiosKeyboardMap[VK_SHIFT]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
+    // CTRL
+    if (BiosKeyboardMap[VK_RCONTROL] & (1 << 7)) Bda->KeybdStatusFlags |= BDA_KBDFLAG_RCTRL;
+    if (BiosKeyboardMap[VK_LCONTROL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LCTRL;
     if (BiosKeyboardMap[VK_CONTROL]  & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CTRL;
+    // ALT
+    if (BiosKeyboardMap[VK_RMENU]    & (1 << 7)) Bda->KeybdStatusFlags |= BDA_KBDFLAG_RALT;
+    if (BiosKeyboardMap[VK_LMENU]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
     if (BiosKeyboardMap[VK_MENU]     & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_ALT;
+    // Others
     if (BiosKeyboardMap[VK_SCROLL]   & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL_ON;
     if (BiosKeyboardMap[VK_NUMLOCK]  & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK_ON;
     if (BiosKeyboardMap[VK_CAPITAL]  & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK_ON;
     if (BiosKeyboardMap[VK_INSERT]   & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT_ON;
-    if (BiosKeyboardMap[VK_RMENU]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RALT;
-    if (BiosKeyboardMap[VK_LMENU]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
     if (BiosKeyboardMap[VK_SNAPSHOT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SYSRQ;
     if (BiosKeyboardMap[VK_PAUSE]    & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_PAUSE;
     if (BiosKeyboardMap[VK_SCROLL]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL;
@@ -310,6 +332,8 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
 
     /* Clear the extended key flag */
     Extended = FALSE;
+    Bda->KeybdStatusFlags &= ~0x02; // Remove the 0xE0 code flag
+    // Bda->KeybdStatusFlags &= ~0x01; // Remove the 0xE1 code flag
 
     DPRINT("BiosKeyboardIrq - Character = 0x%X, ScanCode = 0x%X, KeybdShiftFlags = 0x%X\n",
            Character, ScanCode, Bda->KeybdShiftFlags);
@@ -320,11 +344,8 @@ Quit:
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-BOOLEAN KbdBios32Initialize(VOID)
+VOID KbdBios32Post(VOID)
 {
-    /* Initialize the common Keyboard BIOS Support Library */
-    if (!KbdBiosInitialize()) return FALSE;
-
     /* Initialize the BDA */
     Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
     Bda->KeybdBufferEnd   = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
@@ -334,6 +355,10 @@ BOOLEAN KbdBios32Initialize(VOID)
     RtlFillMemory(((LPVOID)((ULONG_PTR)Bda + Bda->KeybdBufferStart)),
                   BIOS_KBD_BUFFER_SIZE * sizeof(WORD), 'A');
 
+    Bda->KeybdShiftFlags  = 0;
+    Bda->KeybdStatusFlags = (1 << 4); // 101/102 enhanced keyboard installed
+    Bda->KeybdLedFlags    = 0;
+
     /*
      * Register the BIOS 32-bit Interrupts:
      * - Software vector handler
@@ -341,14 +366,6 @@ BOOLEAN KbdBios32Initialize(VOID)
      */
     RegisterBiosInt32(BIOS_KBD_INTERRUPT, BiosKeyboardService);
     EnableHwIRQ(1, BiosKeyboardIrq);
-
-    return TRUE;
-}
-
-VOID KbdBios32Cleanup(VOID)
-{
-    /* Cleanup the common Keyboard BIOS Support Library */
-    KbdBiosCleanup();
 }
 
 /* EOF */
index 211033c..55d297b 100644 (file)
 #define BDA_KBDFLAG_RSHIFT      (1 << 0)
 #define BDA_KBDFLAG_LSHIFT      (1 << 1)
 #define BDA_KBDFLAG_CTRL        (1 << 2)
+#define BDA_KBDFLAG_RCTRL       (1 << 2)    // Used for KeybdStatusFlags
 #define BDA_KBDFLAG_ALT         (1 << 3)
+#define BDA_KBDFLAG_RALT        (1 << 3)    // Used for KeybdStatusFlags
 #define BDA_KBDFLAG_SCROLL_ON   (1 << 4)
 #define BDA_KBDFLAG_NUMLOCK_ON  (1 << 5)
 #define BDA_KBDFLAG_CAPSLOCK_ON (1 << 6)
 #define BDA_KBDFLAG_INSERT_ON   (1 << 7)
-#define BDA_KBDFLAG_RALT        (1 << 8)
+#define BDA_KBDFLAG_LCTRL       (1 << 8)
 #define BDA_KBDFLAG_LALT        (1 << 9)
 #define BDA_KBDFLAG_SYSRQ       (1 << 10)
 #define BDA_KBDFLAG_PAUSE       (1 << 11)
@@ -34,8 +36,7 @@
 
 /* FUNCTIONS ******************************************************************/
 
-BOOLEAN KbdBios32Initialize(VOID);
-VOID KbdBios32Cleanup(VOID);
+VOID KbdBios32Post(VOID);
 
 #endif /* _KBDBIOS32_H_ */
 
index a17c410..a044a21 100644 (file)
@@ -105,7 +105,7 @@ VOID BiosMousePs2Interface(LPWORD Stack)
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-BOOLEAN MouseBios32Initialize(VOID)
+VOID MouseBios32Post(VOID)
 {
     BYTE ControllerConfig;
 
@@ -127,7 +127,10 @@ BOOLEAN MouseBios32Initialize(VOID)
 
     /* Set up the HW vector interrupts */
     EnableHwIRQ(12, BiosMouseIrq);
+}
 
+BOOLEAN MouseBiosInitialize(VOID)
+{
     return TRUE;
 }
 
index 7339d7f..3e5aad9 100644 (file)
@@ -15,7 +15,8 @@
 
 VOID BiosMousePs2Interface(LPWORD Stack);
 
-BOOLEAN MouseBios32Initialize(VOID);
+VOID MouseBios32Post(VOID);
+BOOLEAN MouseBiosInitialize(VOID);
 VOID MouseBios32Cleanup(VOID);
 
 #endif /* _MOUBIOS32_H_ */
index 7a40da8..fd1a7a1 100644 (file)
 #define NDEBUG
 
 #include "ntvdm.h"
+#include "emulator.h"
+#include "cpu/bop.h"
 #include "int32.h"
 
 #include "vidbios32.h"
 #include <bios/vidbios.h>
 #include "bios32p.h"
 
+/* DEFINES ********************************************************************/
+
+/* BOP Identifiers */
+#define BOP_VIDEO_INT   0x10
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 
-BOOLEAN VidBios32Initialize(VOID)
+extern VOID WINAPI VidBiosVideoService(LPWORD Stack);
+static VOID WINAPI VidBiosINT(LPWORD Stack)
 {
-    /* Initialize the common Video BIOS Support Library */
-    if (!VidBiosInitialize()) return FALSE;
+    /*
+     * Set up a false stack to hardwire the BOP function (that can directly
+     * manipulate CPU registers) to the 32-bit interrupt function (which uses
+     * the stack to be able to modify the original CS:IP and FLAGS).
+     *
+     * See int32.h stack codes.
+     */
+    WORD EmuStack[4];
+    DWORD Flags = getEFLAGS();
+
+    DPRINT1("Calling BOP VidBiosINT\n");
 
-    /* Register the BIOS 32-bit Interrupts */
-    RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
+    EmuStack[STACK_FLAGS]   = LOWORD(Flags);
+    EmuStack[STACK_CS]      = getCS();
+    EmuStack[STACK_IP]      = getIP();
+    EmuStack[STACK_INT_NUM] = BOP_VIDEO_INT;
 
-    /* Vectors that should be implemented */
-    RegisterBiosInt32(0x42, NULL); // Relocated Default INT 10h Video Services
-    RegisterBiosInt32(0x6D, NULL); // Video BIOS Entry Point
+    VidBiosVideoService(EmuStack);
 
+    setIP(EmuStack[STACK_IP]);
+    setCS(EmuStack[STACK_CS]);
+    setEFLAGS(MAKELONG(EmuStack[STACK_FLAGS], HIWORD(Flags)));
+}
+
+BOOLEAN VidBios32Initialize(VOID)
+{
+    /* Register the BIOS support BOPs */
+    RegisterBop(BOP_VIDEO_INT, VidBiosINT);
     return TRUE;
 }
 
 VOID VidBios32Cleanup(VOID)
 {
-    /* Cleanup the common Video BIOS Support Library */
-    VidBiosCleanup();
+    /* Unregister the BIOS support BOPs */
+    RegisterBop(BOP_VIDEO_INT, NULL);
 }
 
 /* EOF */
index 27d2f0f..1913fb8 100644 (file)
@@ -13,6 +13,7 @@
 #include "ntvdm.h"
 #include "emulator.h"
 #include "cpu/bop.h"
+#include "int32.h"
 
 #include "bios.h"
 // #include "kbdbios.h"
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
+extern VOID WINAPI BiosKeyboardIrq(LPWORD Stack);
 static VOID WINAPI KbdBiosIRQ(LPWORD Stack)
 {
-    DPRINT1("KbdBiosIRQ is UNIMPLEMENTED\n");
+    /*
+     * Set up a false stack to hardwire the BOP function (that can directly
+     * manipulate CPU registers) to the 32-bit interrupt function (which uses
+     * the stack to be able to modify the original CS:IP and FLAGS).
+     *
+     * See int32.h stack codes.
+     */
+    WORD EmuStack[4];
+    DWORD Flags = getEFLAGS();
+
+    DPRINT1("Calling BOP KbdBiosIRQ\n");
+
+    EmuStack[STACK_FLAGS]   = LOWORD(Flags);
+    EmuStack[STACK_CS]      = getCS();
+    EmuStack[STACK_IP]      = getIP();
+    EmuStack[STACK_INT_NUM] = BOP_KBD_IRQ;
+
+    BiosKeyboardIrq(EmuStack);
+
+    setIP(EmuStack[STACK_IP]);
+    setCS(EmuStack[STACK_CS]);
+    setEFLAGS(MAKELONG(EmuStack[STACK_FLAGS], HIWORD(Flags)));
 }
 
+extern VOID WINAPI BiosKeyboardService(LPWORD Stack);
 static VOID WINAPI KbdBiosINT(LPWORD Stack)
 {
-    DPRINT1("KbdBiosINT is UNIMPLEMENTED\n");
+    /*
+     * Set up a false stack to hardwire the BOP function (that can directly
+     * manipulate CPU registers) to the 32-bit interrupt function (which uses
+     * the stack to be able to modify the original CS:IP and FLAGS).
+     *
+     * See int32.h stack codes.
+     */
+    WORD EmuStack[4];
+    DWORD Flags = getEFLAGS();
+
+    DPRINT1("Calling BOP KbdBiosINT\n");
+
+    EmuStack[STACK_FLAGS]   = LOWORD(Flags);
+    EmuStack[STACK_CS]      = getCS();
+    EmuStack[STACK_IP]      = getIP();
+    EmuStack[STACK_INT_NUM] = BOP_KBD_IRQ;
+
+    BiosKeyboardService(EmuStack);
+
+    setIP(EmuStack[STACK_IP]);
+    setCS(EmuStack[STACK_CS]);
+    setEFLAGS(MAKELONG(EmuStack[STACK_FLAGS], HIWORD(Flags)));
 }
 
 BOOLEAN KbdBiosInitialize(VOID)
 {
     /* Register the BIOS support BOPs */
-    RegisterBop(BOP_KBD_IRQ, KbdBiosIRQ);
-    RegisterBop(BOP_KBD_INT, KbdBiosINT);
-
+    RegisterBop(BOP_KBD_IRQ, KbdBiosIRQ);   // BiosKeyboardIrq in kbdbios32.c
+    RegisterBop(BOP_KBD_INT, KbdBiosINT);   // BiosKeyboardService in kbdbios32.c
     return TRUE;
 }
 
 VOID KbdBiosCleanup(VOID)
 {
+    /* Unregister the BIOS support BOPs */
+    RegisterBop(BOP_KBD_IRQ, NULL);
+    RegisterBop(BOP_KBD_INT, NULL);
 }
 
 /* EOF */
index f3ff579..3cba9b5 100644 (file)
@@ -81,22 +81,6 @@ LoadRomFileByHandle(IN  HANDLE RomFileHandle,
                             BytesRead);
 }
 
-static UCHAR
-ComputeChecksum(IN ULONG RomLocation,
-                IN ULONG RomSize)
-{
-    ULONG RomLastAddress = RomLocation + RomSize;
-    UCHAR Sum = 0x00;   // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
-
-    while (RomLocation < RomLastAddress)
-    {
-        Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation);
-        ++RomLocation;
-    }
-
-    return Sum;
-}
-
 static VOID
 InitRomRange(IN PCALLBACK16 Context,
              IN ULONG Start,
@@ -115,16 +99,16 @@ InitRomRange(IN PCALLBACK16 Context,
             /* Check the control sum of the ROM */
 
             /*
-             * If this is an adapter ROM (Start: C8000, End: E0000), its
-             * reported size is stored in byte 2 of the ROM.
+             * If this is an adapter ROM (Start: C8000, End: E0000),
+             * its reported size is stored in byte 2 of the ROM.
              *
              * If this is an expansion ROM (Start: E0000, End: F0000),
              * its real length is 64kB.
              */
-            RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512;
+            RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512; // Size in blocks of 512 bytes
             if (Address >= 0xE0000) RomSize = 0x10000;
 
-            Checksum = ComputeChecksum(Address, RomSize);
+            Checksum = CalcRomChecksum(Address, RomSize);
             if (Checksum == 0x00)
             {
                 EntryPoint = Address + 3;
@@ -156,6 +140,29 @@ WriteProtectRom(IN PVOID RomLocation,
                                     NULL, ShadowRomWrite);
 }
 
+BOOLEAN
+WriteUnProtectRom(IN PVOID RomLocation,
+                  IN ULONG RomSize)
+{
+    return MemRemoveFastMemoryHook(RomLocation, RomSize);
+}
+
+UCHAR
+CalcRomChecksum(IN ULONG RomLocation,
+                IN ULONG RomSize)
+{
+    ULONG RomLastAddress = RomLocation + RomSize;
+    UCHAR Sum = 0x00;   // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
+
+    while (RomLocation < RomLastAddress)
+    {
+        Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation);
+        ++RomLocation;
+    }
+
+    return Sum;
+}
+
 BOOLEAN
 LoadBios(IN  PCSTR  BiosFileName,
          OUT PVOID* BiosLocation OPTIONAL,
@@ -242,6 +249,9 @@ LoadRom(IN  PCSTR  RomFileName,
 VOID
 SearchAndInitRoms(IN PCALLBACK16 Context)
 {
+    /* Video ROMs -- Start: C0000, End: C8000, 2kB blocks */
+    InitRomRange(Context, 0xC0000, 0xC8000, 0x0800);
+
     /* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */
     InitRomRange(Context, 0xC8000, 0xE0000, 0x0800);
 
index 5c74b54..04f1724 100644 (file)
@@ -22,6 +22,14 @@ BOOLEAN
 WriteProtectRom(IN PVOID RomLocation,
                 IN ULONG RomSize);
 
+BOOLEAN
+WriteUnProtectRom(IN PVOID RomLocation,
+                  IN ULONG RomSize);
+
+UCHAR
+CalcRomChecksum(IN ULONG RomLocation,
+                IN ULONG RomSize);
+
 BOOLEAN
 LoadBios(IN  PCSTR  BiosFileName,
          OUT PVOID* BiosLocation OPTIONAL,
index bdce032..c544c0a 100644 (file)
 
 #define NDEBUG
 
+/* BIOS Version number and Copyright */
+#include <reactos/buildno.h>
+#include <reactos/version.h>
+
 #include "ntvdm.h"
 #include "emulator.h"
 #include "cpu/cpu.h"
 #include "memory.h"
 
 #include "bios.h"
+#include "bios32/bios32p.h"
+#include "rom.h"
 #include "bios32/vbe.h"
 // #include "vidbios.h"
+#include "bios32/vidbios32.h"
 
 #include "io.h"
 #include "hardware/video/svga.h"
 
-/* DEFINES ********************************************************************/
-
-/* BOP Identifiers */
-#define BOP_VIDEO_INT   0x10
-
 /* MACROS *********************************************************************/
 
 //
 
 /* PRIVATE VARIABLES **********************************************************/
 
+/*
+ * WARNING! For compatibility purposes the string "IBM" should be at C000:001E.
+ */
+static const CHAR BiosInfo[] =
+    "00000000000 Emulation of IBM VGA Compatible ROM\0"
+    "CL-GD5434 VGA BIOS Version 1.41  \r\n"
+    "Copyright (C) ReactOS Team 1996-"COPYRIGHT_YEAR"\r\n"
+    "The original CL-GD5434 card was created by Cirrus Logic, Inc.\r\n\0"
+    "BIOS Date: 06/17/13\0";
+
+C_ASSERT(sizeof(BiosInfo)-1 <= 0xFF-0x05); // Ensures that we won't overflow on the Video Code
+
+
 /*
  * VGA Register Configurations for BIOS Video Modes.
  * The configurations were checked against SeaBIOS VGA BIOS.
@@ -3862,8 +3877,12 @@ VOID VidBiosDetachFromConsole(VOID)
     Attached = FALSE;
 }
 
-BOOLEAN VidBiosInitialize(VOID)
+VOID VidBiosPost(VOID)
 {
+    /*
+     * Initialize VGA BIOS32 RAM dynamic data
+     */
+
     /* Some vectors are in fact addresses to tables */
     ((PULONG)BaseAddress)[0x1D] = (ULONG)NULL; // Video Parameter Tables
     // Far pointer to the 8x8 graphics font for the 8x8 characters 80h-FFh
@@ -3876,26 +3895,6 @@ BOOLEAN VidBiosInitialize(VOID)
     ((PULONG)BaseAddress)[0x42] = (ULONG)NULL; // Relocated Default INT 10h Video Services
     ((PULONG)BaseAddress)[0x6D] = (ULONG)NULL; // Video BIOS Entry Point
 
-    /* Initialize the VGA static function table */
-    VgaStaticFuncTable = SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_STATE_INFO_OFFSET);
-    RtlZeroMemory(VgaStaticFuncTable, sizeof(*VgaStaticFuncTable));
-    VgaStaticFuncTable->SupportedModes[0] = 0xFF; // Modes 0x00 to 0x07 supported
-    VgaStaticFuncTable->SupportedModes[1] = 0xFF; // Modes 0x08 to 0x0F supported
-    VgaStaticFuncTable->SupportedModes[2] = 0x0F; // Modes 0x10 to 0x13 supported
-    VgaStaticFuncTable->SupportedScanlines   = 0x07; // Scanlines 200, 350 and 400 supported
-    VgaStaticFuncTable->TextCharBlocksNumber = 0;
-    VgaStaticFuncTable->MaxActiveTextCharBlocksNumber = 0;
-    VgaStaticFuncTable->VGAFuncSupportFlags = 0x0CFD; // See: http://www.ctyme.com/intr/rb-0221.htm#Table46
-    VgaStaticFuncTable->VGASavePtrFuncFlags = 0x18;   // See: http://www.ctyme.com/intr/rb-0221.htm#Table47
-
-    /* Fill the font tables */
-    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x8_OFFSET),
-                  Font8x8, sizeof(Font8x8));
-    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x16_OFFSET),
-                  Font8x16, sizeof(Font8x16));
-    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x14_OFFSET),
-                  Font8x14, sizeof(Font8x14));
-
     //
     // FIXME: At the moment we always set a VGA mode. In the future,
     // we should set this mode **only** when:
@@ -3915,12 +3914,66 @@ BOOLEAN VidBiosInitialize(VOID)
     /* Synchronize our cursor position with VGA */
     VidBiosSyncCursorPosition();
 
-    /* Register the BIOS support BOPs */
-    RegisterBop(BOP_VIDEO_INT, VidBiosVideoService);
+    /* Register the BIOS 32-bit Interrupts */
+    RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
+
+    /* Vectors that should be implemented */
+    RegisterBiosInt32(0x42, NULL); // Relocated Default INT 10h Video Services
+    RegisterBiosInt32(0x6D, NULL); // Video BIOS Entry Point
 
     /* Initialize VBE */
     VbeInitialized = VbeInitialize();
     if (!VbeInitialized) DPRINT1("Couldn't initialize VBE!\n");
+}
+
+BOOLEAN VidBiosInitialize(VOID)
+{
+    UCHAR Checksum;
+
+    /*
+     * Initialize VGA BIOS32 static data
+     */
+
+    /* This is a ROM of size 'VIDEO_BIOS_ROM_SIZE' */
+    *(PWORD)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0000)) = 0xAA55;
+    *(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0002)) = VIDEO_BIOS_ROM_SIZE / 512; // Size in blocks of 512 bytes
+
+    /* Bootstrap code */
+    *(PWORD)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0003)) = 0x90CB; // retf, nop
+    // RtlCopyMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0xFFF0), Bootstrap, sizeof(Bootstrap));
+
+    /* Video BIOS Information */
+    RtlCopyMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0005), BiosInfo, sizeof(BiosInfo)-1);
+
+    /* Initialize the VGA static function table */
+    VgaStaticFuncTable = SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_STATE_INFO_OFFSET);
+    RtlZeroMemory(VgaStaticFuncTable, sizeof(*VgaStaticFuncTable));
+    VgaStaticFuncTable->SupportedModes[0] = 0xFF; // Modes 0x00 to 0x07 supported
+    VgaStaticFuncTable->SupportedModes[1] = 0xFF; // Modes 0x08 to 0x0F supported
+    VgaStaticFuncTable->SupportedModes[2] = 0x0F; // Modes 0x10 to 0x13 supported
+    VgaStaticFuncTable->SupportedScanlines   = 0x07; // Scanlines 200, 350 and 400 supported
+    VgaStaticFuncTable->TextCharBlocksNumber = 0;
+    VgaStaticFuncTable->MaxActiveTextCharBlocksNumber = 0;
+    VgaStaticFuncTable->VGAFuncSupportFlags = 0x0CFD; // See: http://www.ctyme.com/intr/rb-0221.htm#Table46
+    VgaStaticFuncTable->VGASavePtrFuncFlags = 0x18;   // See: http://www.ctyme.com/intr/rb-0221.htm#Table47
+
+    /* Fill the font tables */
+    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x8_OFFSET),
+                  Font8x8, sizeof(Font8x8));
+    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x16_OFFSET),
+                  Font8x16, sizeof(Font8x16));
+    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x14_OFFSET),
+                  Font8x14, sizeof(Font8x14));
+
+    VidBios32Initialize();
+
+    /* Compute the ROM checksum and store it */
+    *(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_BIOS_ROM_SIZE - 1)) = 0x00;
+    Checksum = CalcRomChecksum(TO_LINEAR(VIDEO_BIOS_DATA_SEG, 0x0000), VIDEO_BIOS_ROM_SIZE);
+    *(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_BIOS_ROM_SIZE - 1)) = (0xFF - Checksum + 1) & 0xFF;
+
+    WriteProtectRom((PVOID)TO_LINEAR(VIDEO_BIOS_DATA_SEG, 0x0000),
+                    VIDEO_BIOS_ROM_SIZE);
 
     return TRUE;
 }
index 50dafce..c4970fe 100644 (file)
 #define CGA_ODD_VIDEO_SEG       0xBA00
 #define VIDEO_BIOS_DATA_SEG     0xC000
 
-#define FONT_8x8_OFFSET         0x0000
-#define FONT_8x8_HIGH_OFFSET    0x0400
-#define FONT_8x16_OFFSET        0x0800
-#define FONT_8x14_OFFSET        0x1800
+#define FONT_8x8_OFFSET         0x0100
+#define FONT_8x8_HIGH_OFFSET    0x0500
+#define FONT_8x16_OFFSET        0x0900
+#define FONT_8x14_OFFSET        0x1900
 
-#define VIDEO_STATE_INFO_OFFSET 0x3000 // == 0x1800 + (sizeof(Font8x14) == 0x0E00) + 0x0A00 for padding
+#define VIDEO_STATE_INFO_OFFSET 0x3000 // == 0x1900 + (sizeof(Font8x14) == 0x0E00) + 0x0900 for padding
+
+#define VIDEO_BIOS_ROM_SIZE     0x4000
 
 typedef enum
 {
@@ -109,6 +111,7 @@ VOID WINAPI VidBiosVideoService(LPWORD Stack);
 VOID VidBiosDetachFromConsole(VOID);
 VOID VidBiosAttachToConsole(VOID);
 
+VOID VidBiosPost(VOID);
 BOOLEAN VidBiosInitialize(VOID);
 VOID VidBiosCleanup(VOID);
 
index 390c1d2..87ba6ca 100644 (file)
@@ -222,6 +222,12 @@ static BYTE CmosReadData(VOID)
             break;
         }
 
+        case CMOS_REG_CENTURY:
+        {
+            Value = READ_CMOS_DATA(CmosMemory, CurrentTime.wYear / 100 + 19);
+            break;
+        }
+
         case CMOS_REG_STATUS_C:
         {
             /* Return the old value */
@@ -363,6 +369,12 @@ static VOID CmosWriteData(BYTE Value)
             break;
         }
 
+        case CMOS_REG_CENTURY:
+        {
+            UNIMPLEMENTED;
+            break;
+        }
+
         case CMOS_REG_STATUS_A:
         {
             CmosMemory.StatusRegA = Value & 0x7F; // Bit 7 is read-only
index ac243ad..23d486c 100644 (file)
 #define CMOS_BATTERY_OK     0x80
 
 /* Status Register B flags */
+#define CMOS_STB_DST            (1 << 0)
 #define CMOS_STB_24HOUR         (1 << 1)
 #define CMOS_STB_BINARY         (1 << 2)
 #define CMOS_STB_SQUARE_WAVE    (1 << 3)
 #define CMOS_STB_INT_ON_UPDATE  (1 << 4)
 #define CMOS_STB_INT_ON_ALARM   (1 << 5)
 #define CMOS_STB_INT_PERIODIC   (1 << 6)
+#define CMOS_STB_UPDATE_CYCLE   (1 << 7)
 
 /* Status Register C flags */
-#define CMOS_STC_UF     CMOS_STB_INT_ON_UPDATE
-#define CMOS_STC_AF     CMOS_STB_INT_ON_ALARM
-#define CMOS_STC_PF     CMOS_STB_INT_PERIODIC
+#define CMOS_STC_UF     (1 << 4)
+#define CMOS_STC_AF     (1 << 5)
+#define CMOS_STC_PF     (1 << 6)
 #define CMOS_STC_IRQF   (1 << 7)
 
 /* Default register values */
-#define CMOS_DEFAULT_STA 0x26
-#define CMOS_DEFAULT_STB CMOS_STB_24HOUR
+#define CMOS_DEFAULT_STA    0x26
+#define CMOS_DEFAULT_STB    CMOS_STB_24HOUR
 
 #define WRITE_CMOS_DATA(Cmos, Value)    \
     ((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BCD_TO_BINARY(Value)
@@ -65,6 +67,7 @@ typedef enum _CMOS_REGISTERS
     CMOS_REG_EXT_MEMORY_HIGH        = 0x18,
     CMOS_REG_ACTUAL_EXT_MEMORY_LOW  = 0x30,
     CMOS_REG_ACTUAL_EXT_MEMORY_HIGH = 0x31,
+    CMOS_REG_CENTURY                = 0x32,
     CMOS_REG_MAX                    = 0x40
 } CMOS_REGISTERS, *PCMOS_REGISTERS;
 
@@ -107,6 +110,8 @@ typedef struct
             BYTE StatusRegD;        // 0x0d
             BYTE Diagnostics;       // 0x0e
             BYTE ShutdownStatus;    // 0x0f
+            BYTE Padding[0x22];     // 0x10
+            BYTE Century;           // 0x32
         };
         BYTE Regs1[0x10];           // 0x00 - 0x0f
         BYTE Regs [0x40];           // 0x00 - 0x3f
index ac247db..84bf6fe 100644 (file)
@@ -526,6 +526,25 @@ wmain(INT argc, WCHAR *argv[])
 
 #endif
 
+#ifdef ADVANCED_DEBUGGING
+    {
+    INT i = 20;
+
+    printf("Waiting for debugger (10 secs)..");
+    while (i--)
+    {
+        printf(".");
+        if (IsDebuggerPresent())
+        {
+            DbgBreakPoint();
+            break;
+        }
+        Sleep(500);
+    }
+    printf("Continue\n");
+    }
+#endif
+
     /* Load global VDM settings */
     LoadGlobalSettings();
 
@@ -549,8 +568,8 @@ wmain(INT argc, WCHAR *argv[])
         goto Cleanup;
     }
 
-    /* Initialize the system BIOS */
-    if (!BiosInitialize(NULL))
+    /* Initialize the system BIOS and option ROMs */
+    if (!BiosInitialize(NULL, NULL))
     {
         wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n");
         goto Cleanup;
index 08044dd..825971e 100644 (file)
@@ -63,6 +63,10 @@ DWORD WINAPI SetLastConsoleEventActive(VOID);
  */
 // #define ADVANCED_DEBUGGING
 
+#ifdef ADVANCED_DEBUGGING
+#define ADVANCED_DEBUGGING_LEVEL    1
+#endif
+
 /* FUNCTIONS ******************************************************************/
 
 extern HANDLE VdmTaskEvent;