[BOOTVID]
[reactos.git] / reactos / drivers / base / bootvid / i386 / vga.c
index 28a43cc..71754c5 100644 (file)
@@ -63,7 +63,7 @@ ULONG lookup[16] =
     0x1111,
 };
 
-ULONG TextColor = 0xF;
+ULONG VidTextColor = 0xF;
 ULONG curr_x = 0;
 ULONG curr_y = 0;
 BOOLEAN CarriageReturn = FALSE;
@@ -95,8 +95,8 @@ ReadWriteMode(UCHAR Mode)
 }
 
 
-VOID
 FORCEINLINE
+VOID
 SetPixel(IN ULONG Left,
          IN ULONG Top,
          IN UCHAR Color)
@@ -114,19 +114,32 @@ SetPixel(IN ULONG Left,
                          READ_REGISTER_UCHAR(PixelPosition) & Color);
 }
 
+#ifdef CHAR_GEN_UPSIDE_DOWN
+# define GetFontPtr(_Char) &FontData[_Char * BOOTCHAR_HEIGHT] + BOOTCHAR_HEIGHT - 1;
+# define FONT_PTR_DELTA (-1)
+#else
+# define GetFontPtr(_Char) &FontData[_Char * BOOTCHAR_HEIGHT];
+# define FONT_PTR_DELTA (1)
+#endif
+
+#define SET_PIXELS(_PixelPtr, _PixelMask, _TextColor) \
+    /* Select the bitmask register and write the mask */ \
+    __outpw(0x3CE, (_PixelMask << 8) | 8); \
+\
+    /* Set the new color */ \
+    WRITE_REGISTER_UCHAR(_PixelPtr, (UCHAR)_TextColor);\
+
 VOID
 NTAPI
 DisplayCharacter(CHAR Character,
                  ULONG Left,
                  ULONG Top,
                  ULONG TextColor,
-                 ULONG BackTextColor)
+                 ULONG BackColor)
 {
-    PUCHAR FontChar;
-    ULONG i, j, XOffset;
-
-    /* Get the font line for this character */
-    FontChar = &FontData[Character * BOOTCHAR_HEIGHT];
+    PUCHAR FontChar, PixelPtr;
+    ULONG Height;
+    UCHAR Shift;
 
     /* Switch to mode 10 */
     ReadWriteMode(10);
@@ -137,40 +150,84 @@ DisplayCharacter(CHAR Character,
     /* Select the color don't care register */
     __outpw(0x3CE, 7);
 
-    /* Loop each pixel height */
-    i = BOOTCHAR_HEIGHT;
+    /* Calculate shift */
+    Shift = Left & 7;
+
+    /* Get the font and pixel pointer */
+    FontChar = GetFontPtr(Character);
+    PixelPtr = (PUCHAR)VgaBase + (Left >> 3) + (Top * 80);
+
+    /* Loop all pixel rows */
+    Height = BOOTCHAR_HEIGHT;
     do
     {
-        /* Loop each pixel width */
-        j = 128;
-        XOffset = Left;
+        SET_PIXELS(PixelPtr, *FontChar >> Shift, TextColor);
+        PixelPtr += 80;
+        FontChar += FONT_PTR_DELTA;
+    } while (--Height);
+
+    /* Check if we need to update neighbor bytes */
+    if (Shift)
+    {
+        /* Calculate shift for 2nd byte */
+        Shift = 8 - Shift;
+
+        /* Get the font and pixel pointer (2nd byte) */
+        FontChar = GetFontPtr(Character);
+        PixelPtr = (PUCHAR)VgaBase + (Left >> 3) + (Top * 80) + 1;
+
+        /* Loop all pixel rows */
+        Height = BOOTCHAR_HEIGHT;
         do
         {
-            /* Check if we should draw this pixel */
-#ifdef CHAR_GEN_UPSIDE_DOWN
-            if (FontChar[i] & (UCHAR)j)
-#else
-            /* Normal character generator (top of char is first element) */
-            if (FontChar[BOOTCHAR_HEIGHT - i] & (UCHAR)j)
-#endif
-            {
-                /* We do, use the given Text Color */
-                SetPixel(XOffset, Top, (UCHAR)TextColor);
-            }
-            else if (BackTextColor < 16)
-            {
-                /* This is a background pixel. */
-                /* We're drawing it unless it's transparent. */
-                SetPixel(XOffset, Top, (UCHAR)BackTextColor);
-            }
+            SET_PIXELS(PixelPtr, *FontChar << Shift, TextColor);
+            PixelPtr += 80;
+            FontChar += FONT_PTR_DELTA;
+        } while (--Height);
+    }
+
+    /* Check if the background color is transparent */
+    if (BackColor >= 16)
+    {
+        /* We are done */
+        return;
+    }
+
+    /* Calculate shift */
+    Shift = Left & 7;
+
+    /* Get the font and pixel pointer */
+    FontChar = GetFontPtr(Character);
+    PixelPtr = (PUCHAR)VgaBase + (Left >> 3) + (Top * 80);
 
-            /* Increase X Offset */
-            XOffset++;
-        } while (j >>= 1);
+    /* Loop all pixel rows */
+    Height = BOOTCHAR_HEIGHT;
+    do
+    {
+        SET_PIXELS(PixelPtr, ~*FontChar >> Shift, BackColor);
+        PixelPtr += 80;
+        FontChar += FONT_PTR_DELTA;
+    } while (--Height);
+
+    /* Check if we need to update neighbor bytes */
+    if (Shift)
+    {
+        /* Calculate shift for 2nd byte */
+        Shift = 8 - Shift;
+
+        /* Get the font and pixel pointer (2nd byte) */
+        FontChar = GetFontPtr(Character);
+        PixelPtr = (PUCHAR)VgaBase + (Left >> 3) + (Top * 80) + 1;
 
-        /* Move to the next Y ordinate */
-        Top++;
-    } while (--i);
+        /* Loop all pixel rows */
+        Height = BOOTCHAR_HEIGHT;
+        do
+        {
+            SET_PIXELS(PixelPtr, ~*FontChar << Shift, BackColor);
+            PixelPtr += 80;
+            FontChar += FONT_PTR_DELTA;
+        } while (--Height);
+    }
 }
 
 VOID
@@ -632,8 +689,8 @@ VidSetTextColor(ULONG Color)
     ULONG OldColor;
 
     /* Save the old color and set the new one */
-    OldColor = TextColor;
-    TextColor = Color;
+    OldColor = VidTextColor;
+    VidTextColor = Color;
     return OldColor;
 }
 
@@ -767,7 +824,7 @@ VidDisplayString(PUCHAR String)
             }
 
             /* Display this character */
-            DisplayCharacter(*String, curr_x, curr_y, TextColor, 16);
+            DisplayCharacter(*String, curr_x, curr_y, VidTextColor, 16);
             curr_x += 8;
 
             /* Check if we should scroll */
@@ -1095,4 +1152,3 @@ VidSolidColorFill(IN ULONG Left,
         }
     }
 }
-