[FREELDR] Use BIOS font and accelerated text drawing on NEC PC-98
authorStanislav Motylkov <x86corez@gmail.com>
Fri, 16 Oct 2020 21:32:38 +0000 (00:32 +0300)
committerStanislav Motylkov <x86corez@gmail.com>
Sat, 17 Oct 2020 16:28:05 +0000 (19:28 +0300)
Both features are switchable via global variables.

boot/freeldr/freeldr/arch/i386/pc98/pc98video.c

index 7f038a0..0d9b3b3 100644 (file)
@@ -28,6 +28,13 @@ UCHAR TextLines;
 #define SCREEN_HEIGHT 400
 #define BYTES_PER_SCANLINE (SCREEN_WIDTH / 8)
 
+/* Use BIOS font; set to FALSE for built-in VGA font. */
+static BOOLEAN UseCGFont = TRUE;
+/* Hardware accelerated text drawing; set to FALSE for non-accelerated
+ * self-drawing, which will allow more than 8 colors for text though.
+ * This option is possible only with BIOS fonts enabled. */
+static BOOLEAN CGAccelDraw = TRUE;
+
 ULONG VramText;
 static ULONG VramPlaneB;
 static ULONG VramPlaneG;
@@ -232,6 +239,77 @@ Pc98VideoHideShowTextCursor(BOOLEAN Show)
     WRITE_GDC_CSRFORM((PUCHAR)GDC1_IO_o_PARAM, &CursorParameters);
 }
 
+static
+UCHAR
+Pc98VideoAttrToGdcAttr(UCHAR Attr)
+{
+    switch (Attr & 0xF)
+    {
+        case COLOR_BLACK:
+            return GDC_ATTR_BLACK;
+        case COLOR_BLUE:
+            return GDC_ATTR_BLUE;
+        case COLOR_GREEN:
+        case COLOR_LIGHTGREEN:
+            return GDC_ATTR_GREEN;
+        case COLOR_CYAN:
+        case COLOR_GRAY:
+        case COLOR_DARKGRAY:
+        case COLOR_WHITE:
+            return GDC_ATTR_WHITE;
+        case COLOR_RED:
+        case COLOR_LIGHTRED:
+            return GDC_ATTR_RED;
+        case COLOR_MAGENTA:
+        case COLOR_LIGHTMAGENTA:
+            return GDC_ATTR_PURPLE;
+        case COLOR_BROWN:
+        case COLOR_YELLOW:
+            return GDC_ATTR_YELLOW;
+        case COLOR_LIGHTBLUE:
+        case COLOR_LIGHTCYAN:
+            return GDC_ATTR_LIGHTBLUE;
+        default:
+            return GDC_ATTR_BLACK;
+    }
+}
+
+static
+USHORT
+Pc98AsciiToJisX(int Ch)
+{
+    switch (Ch)
+    {
+        /* Only characters required for pseudographic are handled here */
+        case 0x18: return 0x1E;
+        case 0x19: return 0x1F;
+        case 0xB3: return 0x260B;
+        case 0xB6: return 0x4C0B;
+        case 0xBA: return 0x270B;
+        case 0xBB: return 0x370B;
+        case 0xBC: return 0x3F0B;
+        case 0xBF: return 0x340B;
+        case 0xC0: return 0x380B;
+        case 0xC4: return 0x240B;
+        case 0xC7: return 0x440B;
+        case 0xC8: return 0x3B0B;
+        case 0xC9: return 0x330B;
+        case 0xCD: return 0x250B;
+        case 0xD9: return 0x3C0B;
+        case 0xDA: return 0x300B;
+        case 0xDB: return 0x87;
+        default: return Ch;
+    }
+}
+
+static
+VOID
+Pc98VideoTextRamPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
+{
+    *(PUSHORT)(VramText + (X + Y * TextCols) * TEXT_CHAR_SIZE) = Ch;
+    *(PUCHAR)(VramText + VRAM_TEXT_ATTR_OFFSET + (X + Y * TextCols) * TEXT_CHAR_SIZE) = Pc98VideoAttrToGdcAttr(Attr) | GDC_ATTR_VISIBLE;
+}
+
 VOID
 Pc98VideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
 {
@@ -242,9 +320,46 @@ Pc98VideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
     UCHAR I = (Attr & 0x80) ? 0xFF : 0;
     ULONG VramOffset = X + (Y * CHAR_HEIGHT) * BYTES_PER_SCANLINE;
     PUCHAR FontPtr = BitmapFont8x16 + Ch * 16;
+    BOOLEAN CGFont = UseCGFont && (Ch != LIGHT_FILL && Ch != MEDIUM_FILL && Ch != DARK_FILL);
+
+    if (CGFont)
+    {
+        Ch = Pc98AsciiToJisX(Ch);
+
+        if (CGAccelDraw)
+        {
+            Pc98VideoTextRamPutChar(Ch, Attr, X, Y);
+        }
+        else
+        {
+            /* Set needed character code to obtain glyph from CG Window */
+            WRITE_PORT_UCHAR((PUCHAR)KCG_IO_o_CHARCODE_LOW, Ch);
+            WRITE_PORT_UCHAR((PUCHAR)KCG_IO_o_CHARCODE_HIGH, Ch >> 8);
+        }
+    }
+    else if (UseCGFont && CGAccelDraw)
+    {
+        /* Clear character at this place in Text RAM */
+        Pc98VideoTextRamPutChar(' ', Attr, X, Y);
+    }
 
     for (Line = 0; Line < CHAR_HEIGHT; Line++)
     {
+        if (CGFont)
+        {
+            if (CGAccelDraw)
+            {
+                /* Character is already displayed by GDC (Text RAM),
+                 * so display only background for it. */
+                FontPtr[Line] = 0;
+            }
+            else
+            {
+                /* Obtain glyph data from CG Window */
+                WRITE_PORT_UCHAR((PUCHAR)KCG_IO_o_LINE, Line | 0x20);
+                FontPtr[Line] = READ_PORT_UCHAR((PUCHAR)KCG_IO_i_PATTERN);
+            }
+        }
         if (Attr & 0x0F)
         {
             *(PUCHAR)(VramPlaneB + VramOffset + Line * BYTES_PER_SCANLINE) = B | ((Attr & 0x01) ? FontPtr[Line] : 0);
@@ -336,4 +451,14 @@ Pc98VideoPrepareForReactOS(VOID)
     Int386(0x18, &Regs, &Regs);
 
     Pc98VideoHideShowTextCursor(FALSE);
+
+    if (UseCGFont && CGAccelDraw)
+    {
+        /* Clear the text screen, resetting to default attributes */
+        for (USHORT i = 0; i < VRAM_TEXT_SIZE; i += TEXT_CHAR_SIZE)
+        {
+            *(PUSHORT)(VramText + i) = ' ';
+            *(PUCHAR)(VramText + VRAM_TEXT_ATTR_OFFSET + i) = GDC_ATTR_WHITE | GDC_ATTR_VISIBLE;
+        }
+    }
 }