https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e901489574e085811ecdff2097d1343d89d4f6b7

commit e901489574e085811ecdff2097d1343d89d4f6b7
Author:     Dmitry Borisov <[email protected]>
AuthorDate: Thu May 14 16:36:55 2020 +0600
Commit:     Stanislav Motylkov <[email protected]>
CommitDate: Fri May 15 22:28:34 2020 +0300

    [BOOTVID] Add boot video driver for NEC PC-98 series (#2787)
---
 drivers/base/bootvid/CMakeLists.txt      |  13 +-
 drivers/base/bootvid/bootvid.rc          |   6 +
 drivers/base/bootvid/i386/pc98/bootvid.c | 469 +++++++++++++++++++++++++++++++
 drivers/base/bootvid/i386/pc98/pc98.h    |  65 +++++
 drivers/base/bootvid/precomp.h           |   4 +
 sdk/include/reactos/drivers/pc98/video.h | 273 ++++++++++++++----
 6 files changed, 767 insertions(+), 63 deletions(-)

diff --git a/drivers/base/bootvid/CMakeLists.txt 
b/drivers/base/bootvid/CMakeLists.txt
index 10052eb2128..033a37c53ef 100644
--- a/drivers/base/bootvid/CMakeLists.txt
+++ b/drivers/base/bootvid/CMakeLists.txt
@@ -2,10 +2,15 @@
 spec2def(bootvid.dll bootvid.spec ADD_IMPORTLIB)
 
 if((ARCH STREQUAL "i386") OR (ARCH STREQUAL "amd64"))
-    list(APPEND SOURCE
-        i386/pc/bootvid.c
-        i386/pc/bootdata.c
-        i386/pc/vga.c)
+    if(SARCH STREQUAL "pc98")
+        list(APPEND SOURCE
+            i386/pc98/bootvid.c)
+    else()
+        list(APPEND SOURCE
+            i386/pc/bootvid.c
+            i386/pc/bootdata.c
+            i386/pc/vga.c)
+    endif()
 elseif(ARCH STREQUAL "arm")
     list(APPEND SOURCE
         arm/bootvid.c)
diff --git a/drivers/base/bootvid/bootvid.rc b/drivers/base/bootvid/bootvid.rc
index 34ea5309796..18d91d14650 100644
--- a/drivers/base/bootvid/bootvid.rc
+++ b/drivers/base/bootvid/bootvid.rc
@@ -1,5 +1,11 @@
 #define REACTOS_VERSION_DLL
+
+#if defined(SARCH_PC98)
+#define REACTOS_STR_FILE_DESCRIPTION  "NEC PC-98 Boot Video Driver"
+#else
 #define REACTOS_STR_FILE_DESCRIPTION  "VGA Boot Driver"
+#endif
+
 #define REACTOS_STR_INTERNAL_NAME     "bootvid.dll"
 #define REACTOS_STR_ORIGINAL_FILENAME "bootvid.dll"
 #include <reactos/version.rc>
diff --git a/drivers/base/bootvid/i386/pc98/bootvid.c 
b/drivers/base/bootvid/i386/pc98/bootvid.c
new file mode 100644
index 00000000000..e4b8b1b834b
--- /dev/null
+++ b/drivers/base/bootvid/i386/pc98/bootvid.c
@@ -0,0 +1,469 @@
+/*
+ * PROJECT:     ReactOS Boot Video Driver for NEC PC-98 series
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Main file
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov ([email protected])
+ */
+
+/* INCLUDES 
*******************************************************************/
+
+#include "precomp.h"
+
+/* GLOBALS 
********************************************************************/
+
+static ULONG_PTR VideoMemoryI;
+ULONG_PTR FrameBuffer;
+
+#define PEGC_MAX_COLORS    256
+
+/* PRIVATE FUNCTIONS 
**********************************************************/
+
+static BOOLEAN
+GraphGetStatus(
+    _In_ UCHAR Status)
+{
+    UCHAR Result;
+
+    WRITE_PORT_UCHAR((PUCHAR)GRAPH_IO_o_STATUS_SELECT, Status);
+    KeStallExecutionProcessor(1);
+    Result = READ_PORT_UCHAR((PUCHAR)GRAPH_IO_i_STATUS);
+
+    return (Result & GRAPH_STATUS_SET) && (Result != 0xFF);
+}
+
+static BOOLEAN
+HasPegcController(VOID)
+{
+    BOOLEAN Success;
+
+    if (GraphGetStatus(GRAPH_STATUS_PEGC))
+        return TRUE;
+
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_UNPROTECT);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_ENABLE);
+    Success = GraphGetStatus(GRAPH_STATUS_PEGC);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_DISABLE);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_PROTECT);
+
+    return Success;
+}
+
+static VOID
+TextSync(VOID)
+{
+    while (READ_PORT_UCHAR((PUCHAR)GDC1_IO_i_STATUS) & GDC_STATUS_VSYNC)
+        NOTHING;
+
+    while (!(READ_PORT_UCHAR((PUCHAR)GDC1_IO_i_STATUS) & GDC_STATUS_VSYNC))
+        NOTHING;
+}
+
+static VOID
+InitializeDisplay(VOID)
+{
+    SYNCPARAM SyncParameters;
+    CSRFORMPARAM CursorParameters;
+    CSRWPARAM CursorPosition;
+    PITCHPARAM PitchParameters;
+    PRAMPARAM RamParameters;
+    ZOOMPARAM ZoomParameters;
+    UCHAR RelayState;
+
+    /* RESET, without FIFO check */
+    WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_COMMAND, GDC_COMMAND_RESET1);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_COMMAND, GDC_COMMAND_RESET1);
+
+    /* Configure chipset */
+    WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, GRAPH_MODE_COLORED);
+    WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, 
GDC2_MODE_ODD_RLINE_SHOW);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_COLORS_16);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_GRCG);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_LCD);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_LINES_400);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_CLOCK1_5MHZ);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_CLOCK2_5MHZ);
+    WRITE_PORT_UCHAR((PUCHAR)GRAPH_IO_o_HORIZONTAL_SCAN_RATE, GRAPH_HF_31KHZ);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_VIDEO_PAGE, 0);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_VIDEO_PAGE_ACCESS, 0);
+
+    /* =========================== MASTER ============================ */
+
+    /* MASTER */
+    WRITE_GDC1_COMMAND(GDC_COMMAND_MASTER);
+
+    /* SYNC */
+    SyncParameters.Flags = SYNC_DISPLAY_MODE_GRAPHICS_AND_CHARACTERS | 
SYNC_VIDEO_FRAMING_NONINTERLACED |
+                           SYNC_DRAW_ONLY_DURING_RETRACE_BLANKING | 
SYNC_STATIC_RAM_NO_REFRESH;
+    SyncParameters.ScreenWidthChars = 80;
+    SyncParameters.HorizontalSyncWidth = 12;
+    SyncParameters.VerticalSyncWidth = 2;
+    SyncParameters.HorizontalFrontPorchWidth = 4;
+    SyncParameters.HorizontalBackPorchWidth = 4;
+    SyncParameters.VerticalFrontPorchWidth = 6;
+    SyncParameters.ScreenWidthLines = 480;
+    SyncParameters.VerticalBackPorchWidth = 37;
+    WRITE_GDC1_COMMAND(GDC_COMMAND_SYNC_ON);
+    WRITE_GDC_SYNC((PUCHAR)GDC1_IO_o_PARAM, &SyncParameters);
+
+    /* CSRFORM */
+    CursorParameters.Show = FALSE;
+    CursorParameters.Blink = FALSE;
+    CursorParameters.BlinkRate = 12;
+    CursorParameters.LinesPerRow = 16;
+    CursorParameters.StartScanLine = 0;
+    CursorParameters.EndScanLine = 15;
+    WRITE_GDC1_COMMAND(GDC_COMMAND_CSRFORM);
+    WRITE_GDC_CSRFORM((PUCHAR)GDC1_IO_o_PARAM, &CursorParameters);
+
+    /* PITCH */
+    PitchParameters.WordsPerScanline = BYTES_PER_SCANLINE;
+    WRITE_GDC1_COMMAND(GDC_COMMAND_PITCH);
+    WRITE_GDC_PITCH((PUCHAR)GDC1_IO_o_PARAM, &PitchParameters);
+
+    /* PRAM */
+    RamParameters.StartingAddress = 0;
+    RamParameters.Length = 1023;
+    RamParameters.ImageBit = FALSE;
+    RamParameters.WideDisplay = FALSE;
+    WRITE_GDC1_COMMAND(GDC_COMMAND_PRAM);
+    WRITE_GDC_PRAM((PUCHAR)GDC1_IO_o_PARAM, &RamParameters);
+
+    /* ZOOM */
+    ZoomParameters.DisplayZoomFactor = 0;
+    ZoomParameters.WritingZoomFactor = 0;
+    WRITE_GDC1_COMMAND(GDC_COMMAND_ZOOM);
+    WRITE_GDC_ZOOM((PUCHAR)GDC1_IO_o_PARAM, &ZoomParameters);
+
+    /* CSRW */
+    CursorPosition.CursorAddress = 0;
+    CursorPosition.DotAddress = 0;
+    WRITE_GDC1_COMMAND(GDC_COMMAND_CSRW);
+    WRITE_GDC_CSRW((PUCHAR)GDC1_IO_o_PARAM, &CursorPosition);
+
+    /* START */
+    WRITE_GDC1_COMMAND(GDC_COMMAND_BCTRL_START);
+
+    /* ============================ SLAVE ============================ */
+
+    /* SLAVE */
+    WRITE_GDC2_COMMAND(GDC_COMMAND_SLAVE);
+
+    /* SYNC */
+    SyncParameters.Flags = SYNC_DISPLAY_MODE_GRAPHICS | 
SYNC_VIDEO_FRAMING_NONINTERLACED |
+                           
SYNC_DRAW_DURING_ACTIVE_DISPLAY_TIME_AND_RETRACE_BLANKING |
+                           SYNC_STATIC_RAM_NO_REFRESH;
+    SyncParameters.ScreenWidthChars = 80;
+    SyncParameters.HorizontalSyncWidth = 12;
+    SyncParameters.VerticalSyncWidth = 2;
+    SyncParameters.HorizontalFrontPorchWidth = 4;
+    SyncParameters.HorizontalBackPorchWidth = 132;
+    SyncParameters.VerticalFrontPorchWidth = 6;
+    SyncParameters.ScreenWidthLines = 480;
+    SyncParameters.VerticalBackPorchWidth = 37;
+    WRITE_GDC2_COMMAND(GDC_COMMAND_SYNC_ON);
+    WRITE_GDC_SYNC((PUCHAR)GDC2_IO_o_PARAM, &SyncParameters);
+
+    /* CSRFORM */
+    CursorParameters.Show = FALSE;
+    CursorParameters.Blink = FALSE;
+    CursorParameters.BlinkRate = 0;
+    CursorParameters.LinesPerRow = 1;
+    CursorParameters.StartScanLine = 0;
+    CursorParameters.EndScanLine = 0;
+    WRITE_GDC2_COMMAND(GDC_COMMAND_CSRFORM);
+    WRITE_GDC_CSRFORM((PUCHAR)GDC2_IO_o_PARAM, &CursorParameters);
+
+    /* PITCH */
+    PitchParameters.WordsPerScanline = BYTES_PER_SCANLINE;
+    WRITE_GDC2_COMMAND(GDC_COMMAND_PITCH);
+    WRITE_GDC_PITCH((PUCHAR)GDC2_IO_o_PARAM, &PitchParameters);
+
+    /* PRAM */
+    RamParameters.StartingAddress = 0;
+    RamParameters.Length = 1023;
+    RamParameters.ImageBit = TRUE;
+    RamParameters.WideDisplay = FALSE;
+    WRITE_GDC2_COMMAND(GDC_COMMAND_PRAM);
+    WRITE_GDC_PRAM((PUCHAR)GDC2_IO_o_PARAM, &RamParameters);
+
+    /* ZOOM */
+    ZoomParameters.DisplayZoomFactor = 0;
+    ZoomParameters.WritingZoomFactor = 0;
+    WRITE_GDC2_COMMAND(GDC_COMMAND_ZOOM);
+    WRITE_GDC_ZOOM((PUCHAR)GDC2_IO_o_PARAM, &ZoomParameters);
+
+    /* CSRW */
+    CursorPosition.CursorAddress = 0;
+    CursorPosition.DotAddress = 0;
+    WRITE_GDC2_COMMAND(GDC_COMMAND_CSRW);
+    WRITE_GDC_CSRW((PUCHAR)GDC2_IO_o_PARAM, &CursorPosition);
+
+    /* Synchronize the master sync source */
+    TextSync();
+    TextSync();
+    TextSync();
+    TextSync();
+
+    /* START */
+    WRITE_GDC2_COMMAND(GDC_COMMAND_BCTRL_START);
+
+    /* 256 colors */
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_UNPROTECT);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_PEGC_ENABLE);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_MODE_LINES_800);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_MODE_FLIPFLOP2, GDC2_EGC_FF_PROTECT);
+    WRITE_REGISTER_USHORT((PUSHORT)(VideoMemoryI + PEGC_MMIO_MODE), 
PEGC_MODE_PACKED);
+    WRITE_REGISTER_USHORT((PUSHORT)(VideoMemoryI + PEGC_MMIO_FRAMEBUFFER), 
PEGC_FB_MAP);
+
+    /* Select the video source */
+    RelayState = READ_PORT_UCHAR((PUCHAR)GRAPH_IO_i_RELAY) & ~(GRAPH_RELAY_0 | 
GRAPH_RELAY_1);
+    RelayState |= GRAPH_VID_SRC_INTERNAL | GRAPH_SRC_GDC;
+    WRITE_PORT_UCHAR((PUCHAR)GRAPH_IO_o_RELAY, RelayState);
+}
+
+static VOID
+SetPaletteEntryRGB(
+    _In_ ULONG Id,
+    _In_ RGBQUAD Rgb)
+{
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_PALETTE_INDEX, Id);
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_RED, GetRValue(Rgb));
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_GREEN, GetGValue(Rgb));
+    WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_BLUE, GetBValue(Rgb));
+}
+
+VOID
+NTAPI
+InitPaletteWithTable(
+    _In_ PULONG Table,
+    _In_ ULONG Count)
+{
+    ULONG i;
+    PULONG Entry = Table;
+
+    for (i = 0; i < Count; i++)
+        SetPaletteEntryRGB(i, *Entry++);
+
+    for (i = Count; i < PEGC_MAX_COLORS; i++)
+        SetPaletteEntryRGB(i, VidpDefaultPalette[BV_COLOR_BLACK]);
+}
+
+VOID
+NTAPI
+DisplayCharacter(
+    _In_ CHAR Character,
+    _In_ ULONG Left,
+    _In_ ULONG Top,
+    _In_ ULONG TextColor,
+    _In_ ULONG BackColor)
+{
+    ULONG X, Y, PixelMask;
+    PUCHAR FontChar = GetFontPtr(Character);
+
+    for (Y = Top;
+         Y < Top + BOOTCHAR_HEIGHT;
+         ++Y, FontChar += FONT_PTR_DELTA)
+    {
+        for (X = Left, PixelMask = 1 << (BOOTCHAR_WIDTH - 1);
+             X < Left + BOOTCHAR_WIDTH;
+             ++X, PixelMask >>= 1)
+        {
+            if (*FontChar & PixelMask)
+                SetPixel(X, Y, (UCHAR)TextColor);
+            else if (BackColor < BV_COLOR_NONE)
+                SetPixel(X, Y, (UCHAR)BackColor);
+        }
+    }
+}
+
+VOID
+NTAPI
+PreserveRow(
+    _In_ ULONG CurrentTop,
+    _In_ ULONG TopDelta,
+    _In_ BOOLEAN Restore)
+{
+    PUCHAR OldPosition, NewPosition;
+    ULONG PixelCount = TopDelta * SCREEN_WIDTH;
+
+    if (Restore)
+    {
+        /* Restore the row by copying back the contents saved off-screen */
+        OldPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(0, SCREEN_HEIGHT));
+        NewPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(0, CurrentTop));
+    }
+    else
+    {
+        /* Preserve the row by saving its contents off-screen */
+        OldPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(0, CurrentTop));
+        NewPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(0, SCREEN_HEIGHT));
+    }
+
+    while (PixelCount--)
+        WRITE_REGISTER_UCHAR(NewPosition++, 
READ_REGISTER_UCHAR(OldPosition++));
+}
+
+VOID
+PrepareForSetPixel(VOID)
+{
+    NOTHING;
+}
+
+VOID
+NTAPI
+DoScroll(
+    _In_ ULONG Scroll)
+{
+    USHORT i, Line;
+    PUCHAR Src, Dst;
+    PULONG SrcWide, DstWide;
+    USHORT PixelCount = (VidpScrollRegion[2] - VidpScrollRegion[0]) + 1;
+    ULONG_PTR SourceOffset = FrameBuffer + FB_OFFSET(VidpScrollRegion[0], 
VidpScrollRegion[1] + Scroll);
+    ULONG_PTR DestinationOffset = FrameBuffer + FB_OFFSET(VidpScrollRegion[0], 
VidpScrollRegion[1]);
+
+    for (Line = VidpScrollRegion[1]; Line <= VidpScrollRegion[3]; Line++)
+    {
+        SrcWide = (PULONG)SourceOffset;
+        DstWide = (PULONG)DestinationOffset;
+        for (i = 0; i < PixelCount / sizeof(ULONG); i++)
+            WRITE_REGISTER_ULONG(DstWide++, READ_REGISTER_ULONG(SrcWide++));
+
+        Src = (PUCHAR)SrcWide;
+        Dst = (PUCHAR)DstWide;
+        for (i = 0; i < PixelCount % sizeof(ULONG); i++)
+            WRITE_REGISTER_UCHAR(Dst++, READ_REGISTER_UCHAR(Src++));
+
+        SourceOffset += SCREEN_WIDTH;
+        DestinationOffset += SCREEN_WIDTH;
+    }
+}
+
+/* PUBLIC FUNCTIONS 
***********************************************************/
+
+BOOLEAN
+NTAPI
+VidInitialize(
+    _In_ BOOLEAN SetMode)
+{
+    PHYSICAL_ADDRESS BaseAddress;
+
+    BaseAddress.QuadPart = VRAM_NORMAL_PLANE_I;
+    VideoMemoryI = (ULONG_PTR)MmMapIoSpace(BaseAddress, VRAM_PLANE_SIZE, 
MmNonCached);
+    if (!VideoMemoryI)
+        goto Failure;
+
+    if (!HasPegcController())
+        goto Failure;
+
+    BaseAddress.QuadPart = PEGC_FRAMEBUFFER_PACKED;
+    FrameBuffer = (ULONG_PTR)MmMapIoSpace(BaseAddress, PEGC_FRAMEBUFFER_SIZE, 
MmNonCached);
+    if (!FrameBuffer)
+        goto Failure;
+
+    if (SetMode)
+        VidResetDisplay(TRUE);
+
+    return TRUE;
+
+Failure:
+    if (!VideoMemoryI) MmUnmapIoSpace((PVOID)VideoMemoryI, VRAM_PLANE_SIZE);
+    if (!FrameBuffer) MmUnmapIoSpace((PVOID)FrameBuffer, 
PEGC_FRAMEBUFFER_SIZE);
+
+    return FALSE;
+}
+
+VOID
+NTAPI
+VidCleanUp(VOID)
+{
+    WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, 
GRAPH_MODE_DISPLAY_DISABLE);
+}
+
+VOID
+NTAPI
+VidResetDisplay(
+    _In_ BOOLEAN HalReset)
+{
+    PULONG PixelsPosition = (PULONG)(FrameBuffer + FB_OFFSET(0, 0));
+    ULONG PixelCount = ((SCREEN_WIDTH * SCREEN_HEIGHT) / sizeof(ULONG)) + 1;
+
+    /* Clear the current position */
+    VidpCurrentX = 0;
+    VidpCurrentY = 0;
+
+    /* Clear the screen with HAL if we were asked to */
+    if (HalReset)
+        HalResetDisplay();
+
+    WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, 
GRAPH_MODE_DISPLAY_DISABLE);
+
+    /* 640x480 256-color 31 kHz mode */
+    InitializeDisplay();
+
+    /* Re-initialize the palette and fill the screen black */
+    InitializePalette();
+    while (PixelCount--)
+        WRITE_REGISTER_ULONG(PixelsPosition++, 0);
+
+    WRITE_PORT_UCHAR((PUCHAR)GDC1_IO_o_MODE_FLIPFLOP1, 
GRAPH_MODE_DISPLAY_ENABLE);
+}
+
+VOID
+NTAPI
+VidScreenToBufferBlt(
+    _Out_ PUCHAR Buffer,
+    _In_ ULONG Left,
+    _In_ ULONG Top,
+    _In_ ULONG Width,
+    _In_ ULONG Height,
+    _In_ ULONG Delta)
+{
+    ULONG X, Y;
+    PUCHAR OutputBuffer;
+    USHORT Px;
+    PUSHORT PixelsPosition = (PUSHORT)(FrameBuffer + FB_OFFSET(Left, Top));
+
+    /* Clear the destination buffer */
+    RtlZeroMemory(Buffer, Delta * Height);
+
+    for (Y = 0; Y < Height; Y++)
+    {
+        OutputBuffer = Buffer + Y * Delta;
+
+        for (X = 0; X < Width; X += 2)
+        {
+            Px = READ_REGISTER_USHORT(PixelsPosition++);
+            *OutputBuffer++ = (FIRSTBYTE(Px) << 4) | (SECONDBYTE(Px) & 0x0F);
+        }
+    }
+}
+
+VOID
+NTAPI
+VidSolidColorFill(
+    _In_ ULONG Left,
+    _In_ ULONG Top,
+    _In_ ULONG Right,
+    _In_ ULONG Bottom,
+    _In_ UCHAR Color)
+{
+    USHORT i, Line;
+    PUCHAR PixelPtr;
+    PULONG PixelsPtr;
+    ULONG WideColor = (Color << 24) | (Color << 16) | (Color << 8) | Color;
+    USHORT PixelCount = (Right - Left) + 1;
+    ULONG_PTR StartOffset = FrameBuffer + FB_OFFSET(Left, Top);
+
+    for (Line = Top; Line <= Bottom; Line++)
+    {
+        PixelsPtr = (PULONG)StartOffset;
+        for (i = 0; i < PixelCount / sizeof(ULONG); i++)
+            WRITE_REGISTER_ULONG(PixelsPtr++, WideColor);
+
+        PixelPtr = (PUCHAR)PixelsPtr;
+        for (i = 0; i < PixelCount % sizeof(ULONG); i++)
+            WRITE_REGISTER_UCHAR(PixelPtr++, Color);
+
+        StartOffset += SCREEN_WIDTH;
+    }
+}
diff --git a/drivers/base/bootvid/i386/pc98/pc98.h 
b/drivers/base/bootvid/i386/pc98/pc98.h
new file mode 100644
index 00000000000..2e84211e192
--- /dev/null
+++ b/drivers/base/bootvid/i386/pc98/pc98.h
@@ -0,0 +1,65 @@
+/*
+ * PROJECT:     ReactOS Boot Video Driver for NEC PC-98 series
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Arch-specific header file
+ * COPYRIGHT:   Copyright 2020 Dmitry Borisov ([email protected])
+ */
+
+#pragma once
+
+/* INCLUDES 
*******************************************************************/
+
+#include <drivers/pc98/video.h>
+
+/* GLOBALS 
********************************************************************/
+
+#define BYTES_PER_SCANLINE (SCREEN_WIDTH / 8)
+#define FB_OFFSET(x, y)    ((y) * SCREEN_WIDTH + (x))
+
+extern ULONG_PTR FrameBuffer;
+
+/* PROTOTYPES 
*****************************************************************/
+
+VOID
+NTAPI
+DisplayCharacter(
+    _In_ CHAR Character,
+    _In_ ULONG Left,
+    _In_ ULONG Top,
+    _In_ ULONG TextColor,
+    _In_ ULONG BackColor);
+
+VOID
+NTAPI
+DoScroll(
+    _In_ ULONG Scroll);
+
+VOID
+NTAPI
+InitPaletteWithTable(
+    _In_ PULONG Table,
+    _In_ ULONG Count);
+
+VOID
+NTAPI
+PreserveRow(
+    _In_ ULONG CurrentTop,
+    _In_ ULONG TopDelta,
+    _In_ BOOLEAN Restore);
+
+VOID
+PrepareForSetPixel(VOID);
+
+/* FUNCTIONS 
******************************************************************/
+
+FORCEINLINE
+VOID
+SetPixel(
+    _In_ ULONG Left,
+    _In_ ULONG Top,
+    _In_ UCHAR Color)
+{
+    PUCHAR PixelPosition = (PUCHAR)(FrameBuffer + FB_OFFSET(Left, Top));
+
+    WRITE_REGISTER_UCHAR(PixelPosition, Color);
+}
diff --git a/drivers/base/bootvid/precomp.h b/drivers/base/bootvid/precomp.h
index da64ef71c86..a5a27f3ead2 100644
--- a/drivers/base/bootvid/precomp.h
+++ b/drivers/base/bootvid/precomp.h
@@ -7,8 +7,12 @@
 
 /* Arch specific includes */
 #if defined(_M_IX86) || defined(_M_AMD64)
+#if defined(SARCH_PC98)
+#include "i386/pc98/pc98.h"
+#else
 #include "i386/pc/vga.h"
 #include "i386/pc/pc.h"
+#endif
 #elif defined(_M_ARM)
 #include "arm/arm.h"
 #else
diff --git a/sdk/include/reactos/drivers/pc98/video.h 
b/sdk/include/reactos/drivers/pc98/video.h
index c55211d091b..35a5f704b75 100644
--- a/sdk/include/reactos/drivers/pc98/video.h
+++ b/sdk/include/reactos/drivers/pc98/video.h
@@ -9,16 +9,19 @@
 
 /* Video memory 
***************************************************************/
 
-#define VRAM_NORMAL_PLANE_B      0xA8000
-#define VRAM_NORMAL_PLANE_G      0xB0000
-#define VRAM_NORMAL_PLANE_R      0xB8000
-#define VRAM_NORMAL_PLANE_I      0xE0000
+#define VRAM_NORMAL_PLANE_B      0xA8000 /* Blue */
+#define VRAM_NORMAL_PLANE_G      0xB0000 /* Green */
+#define VRAM_NORMAL_PLANE_R      0xB8000 /* Red */
+#define VRAM_NORMAL_PLANE_I      0xE0000 /* Intensity */
 #define VRAM_PLANE_SIZE          0x08000
 #define VRAM_NORMAL_TEXT         0xA0000
 #define VRAM_TEXT_ATTR_OFFSET    0x02000
 #define VRAM_TEXT_SIZE           0x02000
 #define VRAM_ATTR_SIZE           0x02000
 
+#define PEGC_FRAMEBUFFER_PACKED  0xF00000
+#define PEGC_FRAMEBUFFER_SIZE    0x080000
+
 /* High-resolution machine */
 #define VRAM_HI_RESO_PLANE_B     0xC0000
 #define VRAM_HI_RESO_PLANE_G     0xC8000
@@ -52,39 +55,96 @@
 #define GDC_ATTR_YELLOW           0xC0
 #define GDC_ATTR_WHITE            0xE0
 
-#define GDC_COMMAND_RESET         0x00
+/* Operation type */
+#define GDC_MOD_REPLACE           0x00
+#define GDC_MOD_COMPLEMENT        0x01 /* XOR */
+#define GDC_MOD_CLEAR             0x02 /* AND */
+#define GDC_MOD_SET               0x03 /* OR */
+
+#define GDC_GRAPHICS_DRAWING      0x40
+
+#define GDC_COMMAND_RESET1        0x00
+#define GDC_COMMAND_RESET2        0x01
+#define GDC_COMMAND_STOP2         0x05
+#define GDC_COMMAND_RESET3        0x09
 #define GDC_COMMAND_BCTRL_STOP    0x0C
 #define GDC_COMMAND_BCTRL_START   0x0D
+
 #define GDC_COMMAND_SYNC_ON       0x0E
+typedef struct _SYNCPARAM
+{
+    UCHAR Flags;
+#define SYNC_DISPLAY_MODE_GRAPHICS_AND_CHARACTERS                 0x00
+#define SYNC_DISPLAY_MODE_GRAPHICS                                0x02
+#define SYNC_DISPLAY_MODE_CHARACTERS                              0x20
+
+#define SYNC_VIDEO_FRAMING_NONINTERLACED                          0x00
+#define SYNC_VIDEO_FRAMING_INTERLACED_REPEAT_FOR_CHARACTERS       0x08
+#define SYNC_VIDEO_FRAMING_INTERLACED                             0x09
+
+#define SYNC_DRAW_DURING_ACTIVE_DISPLAY_TIME_AND_RETRACE_BLANKING 0x00
+#define SYNC_DRAW_ONLY_DURING_RETRACE_BLANKING                    0x10
+
+#define SYNC_STATIC_RAM_NO_REFRESH                                0x00
+#define SYNC_DYNAMIC_RAM_REFRESH                                  0x04
+
+    UCHAR ScreenWidthChars;
+    UCHAR HorizontalSyncWidth;
+    UCHAR VerticalSyncWidth;
+    UCHAR HorizontalFrontPorchWidth;
+    UCHAR HorizontalBackPorchWidth;
+    UCHAR VerticalFrontPorchWidth;
+    USHORT ScreenWidthLines;
+    UCHAR VerticalBackPorchWidth;
+} SYNCPARAM, *PSYNCPARAM;
+
+FORCEINLINE
+VOID
+WRITE_GDC_SYNC(PUCHAR Port, PSYNCPARAM SyncParameters)
+{
+    WRITE_PORT_UCHAR(Port, SyncParameters->Flags & 0x3F);
+    WRITE_PORT_UCHAR(Port, SyncParameters->ScreenWidthChars - 2);
+    WRITE_PORT_UCHAR(Port, (SyncParameters->VerticalSyncWidth & 0x07) << 5 |
+                     (SyncParameters->HorizontalSyncWidth - 1));
+    WRITE_PORT_UCHAR(Port, ((SyncParameters->HorizontalFrontPorchWidth - 1) << 
2) |
+                     ((SyncParameters->VerticalSyncWidth & 0x18) >> 3));
+    WRITE_PORT_UCHAR(Port, SyncParameters->HorizontalBackPorchWidth - 1);
+    WRITE_PORT_UCHAR(Port, SyncParameters->VerticalFrontPorchWidth);
+    WRITE_PORT_UCHAR(Port, SyncParameters->ScreenWidthLines & 0xFF);
+    WRITE_PORT_UCHAR(Port, (SyncParameters->VerticalBackPorchWidth << 2) |
+                     ((SyncParameters->ScreenWidthLines & 0x300) >> 8));
+}
+
 #define GDC_COMMAND_SYNC_OFF      0x0F
 #define GDC_COMMAND_WRITE         0x20
-#define GDC_COMMAND_SLAVE         0x6E
-#define GDC_COMMAND_MASTER        0x6F
+#define GDC_COMMAND_DMAW          0x24
 
-#define GDC_COMMAND_CSRFORM       0x4B
-typedef struct _CSRFORMPARAM
+#define GDC_COMMAND_ZOOM          0x46
+typedef struct _ZOOMPARAM
 {
-    BOOLEAN Show;
-    BOOLEAN Blink;
-    UCHAR BlinkRate;
-    UCHAR LinesPerRow;
-    UCHAR StartScanLine;
-    UCHAR EndScanLine;
-} CSRFORMPARAM, *PCSRFORMPARAM;
+    UCHAR DisplayZoomFactor;
+    UCHAR WritingZoomFactor;
+} ZOOMPARAM, *PZOOMPARAM;
 
 FORCEINLINE
 VOID
-WRITE_GDC_CSRFORM(PUCHAR Port, PCSRFORMPARAM CursorParameters)
+WRITE_GDC_ZOOM(PUCHAR Port, PZOOMPARAM ZoomParameters)
 {
-    WRITE_PORT_UCHAR(Port, ((CursorParameters->Show & 0x01) << 7) |
-                     (CursorParameters->LinesPerRow - 1));
-    WRITE_PORT_UCHAR(Port, ((CursorParameters->BlinkRate & 0x03) << 6) |
-                     ((!CursorParameters->Blink & 0x01) << 5) | 
CursorParameters->StartScanLine);
-    WRITE_PORT_UCHAR(Port, (CursorParameters->EndScanLine << 3) | 
((CursorParameters->BlinkRate & 0x1C) >> 2));
+    WRITE_PORT_UCHAR(Port, ZoomParameters->DisplayZoomFactor << 4 | 
ZoomParameters->WritingZoomFactor);
 }
 
-#define GDC_COMMAND_START         0x6B
-#define GDC_COMMAND_ZOOM          0x46
+#define GDC_COMMAND_PITCH         0x47
+typedef struct _PITCHPARAM
+{
+    ULONG WordsPerScanline;
+} PITCHPARAM, *PPITCHPARAM;
+
+FORCEINLINE
+VOID
+WRITE_GDC_PITCH(PUCHAR Port, PPITCHPARAM PitchParameters)
+{
+    WRITE_PORT_UCHAR(Port, PitchParameters->WordsPerScanline);
+}
 
 #define GDC_COMMAND_CSRW          0x49
 typedef struct _CSRWPARAM
@@ -106,17 +166,62 @@ WRITE_GDC_CSRW(PUCHAR Port, PCSRWPARAM CursorParameters)
                      ((CursorParameters->CursorAddress >> 16) & 0x03));
 }
 
-#define GDC_COMMAND_PRAM          0x70
-#define GDC_COMMAND_PITCH         0x47
 #define GDC_COMMAND_MASK          0x4A
+
+#define GDC_COMMAND_CSRFORM       0x4B
+typedef struct _CSRFORMPARAM
+{
+    BOOLEAN Show;
+    BOOLEAN Blink;
+    UCHAR BlinkRate;
+    UCHAR LinesPerRow;
+    UCHAR StartScanLine;
+    UCHAR EndScanLine;
+} CSRFORMPARAM, *PCSRFORMPARAM;
+
+FORCEINLINE
+VOID
+WRITE_GDC_CSRFORM(PUCHAR Port, PCSRFORMPARAM CursorParameters)
+{
+    WRITE_PORT_UCHAR(Port, ((CursorParameters->Show & 0x01) << 7) |
+                     (CursorParameters->LinesPerRow - 1));
+    WRITE_PORT_UCHAR(Port, ((CursorParameters->BlinkRate & 0x03) << 6) |
+                     ((!CursorParameters->Blink & 0x01) << 5) | 
CursorParameters->StartScanLine);
+    WRITE_PORT_UCHAR(Port, (CursorParameters->EndScanLine << 3) | 
((CursorParameters->BlinkRate & 0x1C) >> 2));
+}
+
 #define GDC_COMMAND_FIGS          0x4C
-#define GDC_COMMAND_FIGD          0x6C
 #define GDC_COMMAND_GCHRD         0x68
+#define GDC_COMMAND_START         0x6B
+#define GDC_COMMAND_FIGD          0x6C
+#define GDC_COMMAND_SLAVE         0x6E
+#define GDC_COMMAND_MASTER        0x6F
+
+#define GDC_COMMAND_PRAM          0x70
+typedef struct _PRAMPARAM
+{
+    ULONG StartingAddress;
+    USHORT Length;
+    BOOLEAN ImageBit;
+    BOOLEAN WideDisplay;
+} PRAMPARAM, *PPRAMPARAM;
+
+FORCEINLINE
+VOID
+WRITE_GDC_PRAM(PUCHAR Port, PPRAMPARAM RamParameters)
+{
+    WRITE_PORT_UCHAR(Port, RamParameters->StartingAddress & 0xFF);
+    WRITE_PORT_UCHAR(Port, (RamParameters->StartingAddress >> 8) & 0xFF);
+    WRITE_PORT_UCHAR(Port, ((RamParameters->Length & 0x0F) << 4) | 
((RamParameters->StartingAddress >> 16) & 0x03));
+    WRITE_PORT_UCHAR(Port, ((RamParameters->WideDisplay & 0x01) << 7) | 
((RamParameters->ImageBit & 0x01) << 6) |
+                            ((RamParameters->Length >> 4) & 0x3F));
+}
+
+#define GDC_COMMAND_TEXTW         0x78
 #define GDC_COMMAND_READ          0xA0
-#define GDC_COMMAND_CURD          0xE0
-#define GDC_COMMAND_LPRD          0xC0
 #define GDC_COMMAND_DMAR          0xA4
-#define GDC_COMMAND_DMAW          0x24
+#define GDC_COMMAND_LPRD          0xC0
+#define GDC_COMMAND_CURD          0xE0
 
 /* Master GDC 
*****************************************************************/
 
@@ -131,20 +236,20 @@ WRITE_GDC_CSRW(PUCHAR Port, PCSRWPARAM CursorParameters)
 #define GDC1_IO_o_MODE_FLIPFLOP1  0x68
     #define GDC1_MODE_VERTICAL_LINE    0x00 /* Character attribute */
     #define GDC1_MODE_SIMPLE_GRAPHICS  0x01
-    #define GDC1_MODE_COLORED          0x02
-    #define GDC1_MODE_MONOCHROME       0x03
+    #define GRAPH_MODE_COLORED         0x02
+    #define GRAPH_MODE_MONOCHROME      0x03
     #define GDC1_MODE_COLS_80          0x04
     #define GDC1_MODE_COLS_40          0x05
     #define GDC1_MODE_ANK_6_8          0x06
     #define GDC1_MODE_ANK_7_13         0x07
-    #define GDC1_MODE_LINES_400        0x08
-    #define GDC1_MODE_LINES_200        0x09 /* Hide odd raster line */
+    #define GDC2_MODE_ODD_RLINE_SHOW   0x08
+    #define GDC2_MODE_ODD_RLINE_HIDE   0x09
     #define GDC1_MODE_KCG_CODE         0x0A /* CG access during V-SYNC */
     #define GDC1_MODE_KCG_BITMAP       0x0B
-    #define GDC1_NVMW_PROTECT          0x0C
-    #define GDC1_NVMW_UNPROTECT        0x0D /* Memory at 
TextVramSegment:(3FE2-3FFEh) */
-    #define GDC1_MODE_DISPLAY_DISABLE  0x0E
-    #define GDC1_MODE_DISPLAY_ENABLE   0x0F
+    #define GDC1_NVRAM_PROTECT         0x0C
+    #define GDC1_NVRAM_UNPROTECT       0x0D /* Memory at 
TextVramSegment:(3FE2-3FFEh) */
+    #define GRAPH_MODE_DISPLAY_DISABLE 0x0E
+    #define GRAPH_MODE_DISPLAY_ENABLE  0x0F
 
 #define GDC1_IO_o_BORDER_COLOR    0x6C /* PC-H98 */
 
@@ -177,7 +282,7 @@ WRITE_GDC_CSRW(PUCHAR Port, PCSRWPARAM CursorParameters)
     #define GDC2_MODE_EGC              0x05
     #define GDC2_EGC_FF_PROTECT        0x06
     #define GDC2_EGC_FF_UNPROTECT      0x07 /* Unprotect the EGC F/F registers 
*/
-    #define GDC2_MODE_PEGS_DISABLE     0x20
+    #define GDC2_MODE_PEGC_DISABLE     0x20
     #define GDC2_MODE_PEGC_ENABLE      0x21
     // #define GDC2_MODE_              0x26
     // #define GDC2_MODE_              0x27
@@ -189,7 +294,7 @@ WRITE_GDC_CSRW(PUCHAR Port, PCSRWPARAM CursorParameters)
     // #define GDC2_MODE_              0x2D
     #define GDC2_MODE_CRT              0x40
     #define GDC2_MODE_LCD              0x41
-    // #define GDC2_MODE_VRAM_PLAIN    0x62 /* PC-H98 */
+    // #define GDC2_MODE_VRAM_PLANAR   0x62 /* PC-H98 */
     // #define GDC2_MODE_VRAM_PACKED   0x63
     #define GDC2_MODE_LINES_400        0x68 /* 128 kB VRAM boundary */
     #define GDC2_MODE_LINES_800        0x69 /* 256 kB VRAM boundary */
@@ -234,6 +339,36 @@ WRITE_GDC2_COMMAND(UCHAR Command)
     WRITE_PORT_UCHAR((PUCHAR)GDC2_IO_o_COMMAND, Command);
 }
 
+/* Miscellaneous 
**************************************************************/
+
+#define GRAPH_IO_i_STATUS                 0x9A0
+    #define GRAPH_STATUS_SET                   0x01
+    #define GRAPH_GDC_CLOCK2_5MHZ              0x02
+
+#define GRAPH_IO_o_STATUS_SELECT          0x9A0
+    #define GRAPH_STATUS_GDC_CLOCK1_5MHZ       0x09
+    #define GRAPH_STATUS_PEGC                  0x0A
+
+#define GRAPH_IO_i_DPMS                   0x9A2
+#define GRAPH_IO_o_DPMS                   0x9A2
+
+#define GRAPH_IO_i_HORIZONTAL_SCAN_RATE   0x9A8
+#define GRAPH_IO_o_HORIZONTAL_SCAN_RATE   0x9A8
+    #define GRAPH_HF_24KHZ                     0x00
+    #define GRAPH_HF_31KHZ                     0x01
+
+#define GRAPH_IO_i_RELAY                  0xFAC
+    #define GRAPH_RELAY_0                      0x01
+    #define GRAPH_RELAY_1                      0x02
+
+#define GRAPH_IO_o_RELAY                  0xFAC
+    /* Relay 0 */
+    #define GRAPH_VID_SRC_INTERNAL             0x00
+    #define GRAPH_VID_SRC_EXTERNAL             0x01
+    /* Relay 1 */
+    #define GRAPH_SRC_GDC                      0x00
+    #define GRAPH_SRC_WAB                      0x02
+
 /* CRT Controller 
*************************************************************/
 
 #define CRTC_IO_o_SCANLINE_START       0x70
@@ -247,25 +382,11 @@ WRITE_GDC2_COMMAND(UCHAR Command)
 
 #define GRCG_IO_i_MODE                 0x7C
 #define GRCG_IO_o_MODE                 0x7C
-typedef union _GRCG_MODE_REGISTER
-{
-    struct
-    {
-        UCHAR DisablePlaneB:1;
-        UCHAR DisablePlaneR:1;
-        UCHAR DisablePlaneG:1;
-        UCHAR DisablePlaneI:1;
-        UCHAR Unused:2;
-
-        UCHAR Mode:1;
-#define GRCG_MODE_TILE_DIRECT_WRITE 0
-#define GRCG_MODE_TILE_COMPARE_READ 0
-#define GRCG_MODE_READ_MODIFY_WRITE 1
-
-        UCHAR Enable:1;
-    };
-    UCHAR Bits;
-} GRCG_MODE_REGISTER, *PGRCG_MODE_REGISTER;
+    #define GRCG_DISABLE                   0x00
+    #define GRCG_ENABLE                    0x80
+    #define GRCG_MODE_TILE_DIRECT_WRITE    0x80
+    #define GRCG_MODE_TILE_COMPARE_READ    0x80
+    #define GRCG_MODE_READ_MODIFY_WRITE    0xC0
 
 #define GRCG_IO_o_TILE_PATTERN         0x7E
 
@@ -277,3 +398,37 @@ typedef union _GRCG_MODE_REGISTER
 #define KCG_IO_o_PATTERN            0xA9
 
 #define KCG_IO_i_PATTERN            0xA9
+
+/* EGC blitter 
****************************************************************/
+
+#define EGC_IO_o_PLANE_ACCESS            0x4A0
+#define EGC_IO_o_PATTERN_DATA_PLANE_READ 0x4A2
+#define EGC_IO_o_READ_WRITE_MODE         0x4A4
+#define EGC_IO_o_FG_COLOR                0x4A6
+#define EGC_IO_o_MASK                    0x4A8
+#define EGC_IO_o_BG_COLOR                0x4AA
+#define EGC_IO_o_BIT_ADDRESS             0x4AC
+#define EGC_IO_o_BIT_LENGTH              0x4AE
+
+#define PEGC_MMIO_BANK_0          0x004
+#define PEGC_MMIO_BANK_1          0x006
+
+#define PEGC_MMIO_MODE            0x100
+    #define PEGC_MODE_PACKED           0x00
+    #define PEGC_MODE_PLANAR           0x01
+
+#define PEGC_MMIO_FRAMEBUFFER     0x102
+    #define PEGC_FB_UNMAP              0x00
+    #define PEGC_FB_MAP                0x01
+    #define PEGC_FB_UNKNOWN1           0x02
+    #define PEGC_FB_UNKNOWN2           0x03
+
+#define PEGC_MMIO_PLANE_ACCESS    0x104
+#define PEGC_MMIO_ROP             0x108
+#define PEGC_MMIO_DATA_SELECT     0x10A
+#define PEGC_MMIO_MASK            0x10C
+#define PEGC_MMIO_BIT_LENGTH      0x110
+#define PEGC_MMIO_BIT_ADDRESS     0x112
+#define PEGC_MMIO_FG_COLOR        0x114
+#define PEGC_MMIO_BG_COLOR        0x118
+#define PEGC_MMIO_ROP_PATTERN     0x120

Reply via email to