[NTVDM]
[reactos.git] / subsystems / ntvdm / vga.c
index 28a157f..d4616a7 100644 (file)
@@ -98,7 +98,7 @@ static BYTE VgaCrtcRegisters[VGA_CRTC_MAX_REG];
 static BYTE VgaAcIndex = VGA_AC_PAL_0_REG;
 static BOOLEAN VgaAcLatch = FALSE;
 static BYTE VgaAcRegisters[VGA_AC_MAX_REG];
-static BYTE VgaDacIndex = 0;
+static WORD VgaDacIndex = 0;
 static BOOLEAN VgaDacReadWrite = FALSE;
 static BYTE VgaDacRegisters[VGA_PALETTE_SIZE];
 static HPALETTE PaletteHandle = NULL;
@@ -488,12 +488,22 @@ static VOID VgaChangeMode(VOID)
     if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA))
     {
         /* Enter new text mode */
-        if (!VgaEnterTextMode(&Resolution)) return;
+        if (!VgaEnterTextMode(&Resolution))
+        {
+            DisplayMessage(L"An unexpected VGA error occurred while switching into text mode.");
+            VdmRunning = FALSE;
+            return;
+        }
     }
     else
     {
         /* Enter 8-bit graphics mode */
-        if (!VgaEnterGraphicsMode(&Resolution)) return;
+        if (!VgaEnterGraphicsMode(&Resolution))
+        {
+            DisplayMessage(L"An unexpected VGA error occurred while switching into graphics mode.");
+            VdmRunning = FALSE;
+            return;
+        }
     }
 
     /* Trigger a full update of the screen */
@@ -516,6 +526,12 @@ static VOID VgaUpdateFramebuffer(VOID)
                     + VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG];
     DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
 
+    /*
+     * If console framebuffer is NULL, that means something went wrong
+     * earlier and this is the final display refresh.
+     */
+    if (ConsoleFramebuffer == NULL) return;
+
     /* Check if this is text mode or graphics mode */
     if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
     {
@@ -572,13 +588,30 @@ static VOID VgaUpdateFramebuffer(VOID)
                 }
                 else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFTREG)
                 {
-                    /*
-                     * 2 bits shifted from plane 0 and 2 for the first 4 pixels,
-                     * then 2 bits shifted from plane 1 and 3 for the next 4
-                     */
+                    /* Check if this is 16 or 256 color mode */
+                    if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
+                    {
+                        // TODO: NOT IMPLEMENTED
+                        DPRINT1("8-bit interleaved mode is not implemented!\n");
+                    }
+                    else
+                    {
+                        /*
+                         * 2 bits shifted from plane 0 and 2 for the first 4 pixels,
+                         * then 2 bits shifted from plane 1 and 3 for the next 4
+                         */
+                        BYTE LowPlaneData = VgaMemory[((j / 4) % 2) * VGA_BANK_SIZE
+                                                      + (Address + (j / 4)) * AddressSize];
+                        BYTE HighPlaneData = VgaMemory[(((j / 4) % 2) + 2) * VGA_BANK_SIZE
+                                                       + (Address + (j / 4)) * AddressSize];
+
+                        /* Extract the two bits from each plane */
+                        LowPlaneData = (LowPlaneData >> (6 - ((j % 4) * 2))) & 3;
+                        HighPlaneData = (HighPlaneData >> (6 - ((j % 4) * 2))) & 3;
 
-                    // TODO: NOT IMPLEMENTED!
-                    DPRINT1("Interleaved shift mode is not implemented!\n");
+                        /* Combine them into the pixel */
+                        PixelData = LowPlaneData | (HighPlaneData << 2);
+                    }
                 }
                 else
                 {
@@ -620,6 +653,12 @@ static VOID VgaUpdateFramebuffer(VOID)
                     }
                 }
 
+                if (!(VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT))
+                {
+                    /* In 16 color mode, the value is an index to the AC registers */
+                    PixelData = VgaAcRegisters[PixelData];
+                }
+
                 /* Now check if the resulting pixel data has changed */
                 if (GraphicsBuffer[i * Resolution.X + j] != PixelData)
                 {
@@ -668,7 +707,7 @@ static VOID VgaUpdateFramebuffer(VOID)
                     /* Yes, write the new value */
                     CharBuffer[i * Resolution.X + j] = CharInfo;
 
-                    /* Mark the specified pixel as changed */
+                    /* Mark the specified cell as changed */
                     VgaMarkForUpdate(i, j);
                 }
             }
@@ -786,11 +825,6 @@ VOID VgaRefreshDisplay(VOID)
     {
         if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
         {
-            /* Set the graphics mode palette */
-            //SetConsolePalette(GraphicsConsoleBuffer,
-            //                  PaletteHandle,
-            //                  SYSPAL_NOSTATIC256);
-
             /* Trigger a full update of the screen */
             NeedsUpdate = TRUE;
             UpdateRectangle.Left = 0;
@@ -962,7 +996,7 @@ BYTE VgaReadPort(WORD Port)
 
         case VGA_DAC_WRITE_INDEX:
         {
-            return VgaDacIndex;
+            return VgaDacIndex / 3;
         }
 
         case VGA_DAC_DATA:
@@ -1071,7 +1105,7 @@ VOID VgaWritePort(WORD Port, BYTE Data)
         case VGA_DAC_READ_INDEX:
         {
             VgaDacReadWrite = FALSE;
-            VgaDacIndex = Data % VGA_PALETTE_SIZE;
+            VgaDacIndex = Data * 3;
 
             break;
         }
@@ -1079,7 +1113,7 @@ VOID VgaWritePort(WORD Port, BYTE Data)
         case VGA_DAC_WRITE_INDEX:
         {
             VgaDacReadWrite = TRUE;
-            VgaDacIndex = Data % VGA_PALETTE_SIZE;
+            VgaDacIndex = Data * 3;
 
             break;
         }
@@ -1154,7 +1188,7 @@ BOOLEAN VgaInitialize(HANDLE TextHandle)
     TextConsoleBuffer = TextHandle;
 
     /* Clear the VGA memory */
-    ZeroMemory(VgaMemory, VGA_NUM_BANKS * VGA_BANK_SIZE);
+    VgaClearMemory();
 
     /* Set the default video mode */
     BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);