X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=subsystems%2Fntvdm%2Fvga.c;h=d4616a789b25dab55464c94a34ea5c0ee41d99be;hp=a535048a680dd06a6f7ceee197526242a2afb5e0;hb=0043c2f37785f45d909d5e64cc9a02fa1b6342ef;hpb=ed55d73cfd36620a0dc1531e3b0196e0cbdda0df diff --git a/subsystems/ntvdm/vga.c b/subsystems/ntvdm/vga.c index a535048a680..d4616a789b2 100644 --- a/subsystems/ntvdm/vga.c +++ b/subsystems/ntvdm/vga.c @@ -15,10 +15,79 @@ /* PRIVATE VARIABLES **********************************************************/ -static CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 }; +static CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 }; static CONST DWORD MemoryLimit[] = { 0xAFFFF, 0xAFFFF, 0xB7FFF, 0xBFFFF }; +static CONST COLORREF VgaDefaultPalette[VGA_MAX_COLORS] = +{ + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA), + RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA), + RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF), + RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35), + RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75), + RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA), + RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF), + RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF), + RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41), + RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00), + RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00), + RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE), + RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF), + RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF), + RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E), + RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82), + RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82), + RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF), + RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF), + RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF), + RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA), + RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA), + RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA), + RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF), + RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF), + RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71), + RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C), + RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00), + RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00), + RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55), + RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71), + RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71), + RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45), + RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39), + RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39), + RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61), + RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71), + RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71), + RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59), + RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51), + RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51), + RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69), + RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71), + RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41), + RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10), + RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00), + RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00), + RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31), + RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41), + RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41), + RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28), + RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20), + RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20), + RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39), + RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41), + RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41), + RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31), + RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D), + RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D), + RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D), + RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), + RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00) +}; + static BYTE VgaMemory[VGA_NUM_BANKS * VGA_BANK_SIZE]; +static BYTE VgaLatchRegisters[VGA_NUM_BANKS] = {0, 0, 0, 0}; static BYTE VgaMiscRegister; static BYTE VgaSeqIndex = VGA_SEQ_RESET_REG; static BYTE VgaSeqRegisters[VGA_SEQ_MAX_REG]; @@ -29,9 +98,10 @@ 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; static BOOLEAN InVerticalRetrace = FALSE; static BOOLEAN InHorizontalRetrace = FALSE; static HANDLE TextConsoleBuffer = NULL; @@ -41,6 +111,7 @@ static HANDLE ConsoleMutex = NULL; static BOOLEAN NeedsUpdate = FALSE; static BOOLEAN ModeChanged = TRUE; static BOOLEAN CursorMoved = FALSE; +static BOOLEAN PaletteChanged = FALSE; static BOOLEAN TextMode = TRUE; static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 }; @@ -117,6 +188,66 @@ static inline DWORD VgaTranslateWriteAddress(DWORD Address) return Offset; } +static inline BYTE VgaTranslateByteForWriting(BYTE Data, BYTE Plane) +{ + BYTE WriteMode = VgaGcRegisters[VGA_GC_MODE_REG] & 3; + BYTE LogicalOperation = (VgaGcRegisters[VGA_GC_ROTATE_REG] >> 3) & 3; + BYTE RotateCount = VgaGcRegisters[VGA_GC_ROTATE_REG] & 7; + BYTE BitMask = VgaGcRegisters[VGA_GC_BITMASK_REG]; + + if (WriteMode == 1) + { + /* In write mode 1 just return the latch register */ + return VgaLatchRegisters[Plane]; + } + + if (WriteMode != 2) + { + /* Write modes 0 and 3 rotate the data to the right first */ + Data = LOBYTE(((DWORD)Data >> RotateCount) | ((DWORD)Data << (8 - RotateCount))); + } + else + { + /* Write mode 2 expands the appropriate bit to all 8 bits */ + Data = (Data & (1 << Plane)) ? 0xFF : 0x00; + } + + if (WriteMode == 0) + { + /* + * In write mode 0, the enable set/reset register decides if the + * set/reset bit should be expanded to all 8 bits. + */ + if (VgaGcRegisters[VGA_GC_ENABLE_RESET_REG] & (1 << Plane)) + { + /* Copy the bit from the set/reset register to all 8 bits */ + Data = (VgaGcRegisters[VGA_GC_RESET_REG] & (1 << Plane)) ? 0xFF : 0x00; + } + } + + if (WriteMode != 3) + { + /* Write modes 0 and 2 then perform a logical operation on the data and latch */ + if (LogicalOperation == 1) Data &= VgaLatchRegisters[Plane]; + else if (LogicalOperation == 2) Data |= VgaLatchRegisters[Plane]; + else if (LogicalOperation == 3) Data ^= VgaLatchRegisters[Plane]; + } + else + { + /* For write mode 3, we AND the bitmask with the data, which is used as the new bitmask */ + BitMask &= Data; + + /* Then we expand the bit in the set/reset field */ + Data = (VgaGcRegisters[VGA_GC_RESET_REG] & (1 << Plane)) ? 0xFF : 0x00; + } + + /* Bits cleared in the bitmask are replaced with latch register bits */ + Data = (Data & BitMask) | (VgaLatchRegisters[Plane] & (~BitMask)); + + /* Return the byte */ + return Data; +} + static inline VOID VgaMarkForUpdate(SHORT Row, SHORT Column) { DPRINT("VgaMarkForUpdate: Row %d, Column %d\n", Row, Column); @@ -201,11 +332,30 @@ static VOID VgaWriteCrtc(BYTE Data) static VOID VgaWriteDac(BYTE Data) { + INT PaletteIndex; + PALETTEENTRY Entry; + /* Set the value */ - VgaDacRegisters[VgaDacIndex++] = Data; - VgaDacIndex %= VGA_PALETTE_SIZE; + VgaDacRegisters[VgaDacIndex] = Data; + + /* Find the palette index */ + PaletteIndex = VgaDacIndex / 3; - // TODO: Change the palette! + /* Fill the entry structure */ + Entry.peRed = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3]); + Entry.peGreen = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3 + 1]); + Entry.peBlue = VGA_DAC_TO_COLOR(VgaDacRegisters[PaletteIndex * 3 + 2]); + Entry.peFlags = 0; + + /* Update the palette entry */ + SetPaletteEntries(PaletteHandle, PaletteIndex, 1, &Entry); + + /* Set the palette change flag */ + PaletteChanged = TRUE; + + /* Update the index */ + VgaDacIndex++; + VgaDacIndex %= VGA_PALETTE_SIZE; } static VOID VgaWriteAc(BYTE Data) @@ -222,7 +372,7 @@ static BOOL VgaEnterGraphicsMode(PCOORD Resolution) CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo; BYTE BitmapInfoBuffer[VGA_BITMAP_INFO_SIZE]; LPBITMAPINFO BitmapInfo = (LPBITMAPINFO)BitmapInfoBuffer; - LPWORD PaletteIndex = (LPWORD)(BitmapInfoBuffer + sizeof(BITMAPINFOHEADER)); + LPWORD PaletteIndex = (LPWORD)(BitmapInfo->bmiColors); /* Fill the bitmap info header */ ZeroMemory(&BitmapInfo->bmiHeader, sizeof(BITMAPINFOHEADER)); @@ -232,7 +382,7 @@ static BOOL VgaEnterGraphicsMode(PCOORD Resolution) BitmapInfo->bmiHeader.biBitCount = 8; BitmapInfo->bmiHeader.biPlanes = 1; BitmapInfo->bmiHeader.biCompression = BI_RGB; - BitmapInfo->bmiHeader.biSizeImage = Resolution->X * Resolution->Y; + BitmapInfo->bmiHeader.biSizeImage = Resolution->X * Resolution->Y /* * 1 == biBitCount / 8 */; /* Fill the palette data */ for (i = 0; i < (VGA_PALETTE_SIZE / 3); i++) PaletteIndex[i] = (WORD)i; @@ -260,6 +410,14 @@ static BOOL VgaEnterGraphicsMode(PCOORD Resolution) /* Set the active buffer */ SetConsoleActiveScreenBuffer(GraphicsConsoleBuffer); + /* Set the graphics mode palette */ + SetConsolePalette(GraphicsConsoleBuffer, + PaletteHandle, + SYSPAL_NOSTATIC256); + + /* Clear the text mode flag */ + TextMode = FALSE; + return TRUE; } @@ -295,6 +453,9 @@ static BOOL VgaEnterTextMode(PCOORD Resolution) return FALSE; } + /* Set the text mode flag */ + TextMode = TRUE; + return TRUE; } @@ -305,10 +466,13 @@ static VOID VgaLeaveTextMode(VOID) ConsoleFramebuffer = NULL; } -static VOID VgaUpdateMode(VOID) +static VOID VgaChangeMode(VOID) { COORD Resolution = VgaGetDisplayResolution(); + /* Reset the mode change flag */ + // ModeChanged = FALSE; + if (!TextMode) { /* Leave the current graphics mode */ @@ -324,26 +488,33 @@ static VOID VgaUpdateMode(VOID) if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)) { /* Enter new text mode */ - if (!VgaEnterTextMode(&Resolution)) return; - - /* Set the text mode flag */ - TextMode = TRUE; + 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; - - /* Clear the text mode flag */ - TextMode = FALSE; + if (!VgaEnterGraphicsMode(&Resolution)) + { + DisplayMessage(L"An unexpected VGA error occurred while switching into graphics mode."); + VdmRunning = FALSE; + return; + } } - /* Perform a full update */ + /* Trigger a full update of the screen */ NeedsUpdate = TRUE; UpdateRectangle.Left = 0; UpdateRectangle.Top = 0; UpdateRectangle.Right = Resolution.X; UpdateRectangle.Bottom = Resolution.Y; + + /* Reset the mode change flag */ + ModeChanged = FALSE; } static VOID VgaUpdateFramebuffer(VOID) @@ -355,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) { @@ -411,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 { @@ -459,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) { @@ -507,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); } } @@ -552,6 +752,9 @@ static VOID VgaUpdateTextCursor(VOID) /* Update the physical cursor */ SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo); SetConsoleCursorPosition(TextConsoleBuffer, Position); + + /* Reset the cursor move flag */ + CursorMoved = FALSE; } /* PUBLIC FUNCTIONS ***********************************************************/ @@ -569,7 +772,7 @@ DWORD VgaGetVideoLimitAddress(VOID) COORD VgaGetDisplayResolution(VOID) { COORD Resolution; - BYTE TextSize = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F); + BYTE MaximumScanLine = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F); /* The low 8 bits are in the display registers */ Resolution.X = VgaCrtcRegisters[VGA_CRTC_END_HORZ_DISP_REG]; @@ -597,16 +800,11 @@ COORD VgaGetDisplayResolution(VOID) /* The horizontal resolution is halved in 8-bit mode */ if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) Resolution.X /= 2; - - /* Divide the vertical resolution by the maximum scan line */ - Resolution.Y /= ((DWORD)VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F) + 1; - } - else - { - /* Divide the number of scanlines by the font size */ - Resolution.Y /= TextSize; } + /* Divide the vertical resolution by the maximum scan line (== font size in text mode) */ + Resolution.Y /= MaximumScanLine; + /* Return the resolution */ return Resolution; } @@ -617,22 +815,25 @@ VOID VgaRefreshDisplay(VOID) DPRINT("VgaRefreshDisplay\n"); - if (ModeChanged) - { - /* Change the display mode */ - VgaUpdateMode(); + /* Change the display mode */ + if (ModeChanged) VgaChangeMode(); - /* Reset the mode change flag */ - ModeChanged = FALSE; - } + /* Change the text cursor location */ + if (CursorMoved) VgaUpdateTextCursor(); - if (CursorMoved) + if (PaletteChanged) { - /* Change the text cursor location */ - VgaUpdateTextCursor(); + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) + { + /* Trigger a full update of the screen */ + NeedsUpdate = TRUE; + UpdateRectangle.Left = 0; + UpdateRectangle.Top = 0; + UpdateRectangle.Right = Resolution.X; + UpdateRectangle.Bottom = Resolution.Y; + } - /* Reset the cursor move flag */ - CursorMoved = FALSE; + PaletteChanged = FALSE; } /* Update the contents of the framebuffer */ @@ -699,6 +900,12 @@ VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size) { VideoAddress = VgaTranslateReadAddress(Address + i); + /* Load the latch registers */ + VgaLatchRegisters[0] = VgaMemory[LOWORD(VideoAddress)]; + VgaLatchRegisters[1] = VgaMemory[VGA_BANK_SIZE + LOWORD(VideoAddress)]; + VgaLatchRegisters[2] = VgaMemory[(2 * VGA_BANK_SIZE) + LOWORD(VideoAddress)]; + VgaLatchRegisters[3] = VgaMemory[(3 * VGA_BANK_SIZE) + LOWORD(VideoAddress)]; + /* Copy the value to the buffer */ Buffer[i] = VgaMemory[VideoAddress]; } @@ -750,7 +957,7 @@ VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size) } /* Copy the value to the VGA memory */ - VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = Buffer[i]; + VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = VgaTranslateByteForWriting(Buffer[i], j); } } } @@ -789,7 +996,7 @@ BYTE VgaReadPort(WORD Port) case VGA_DAC_WRITE_INDEX: { - return VgaDacIndex; + return VgaDacIndex / 3; } case VGA_DAC_DATA: @@ -898,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; } @@ -906,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; } @@ -959,7 +1166,12 @@ VOID VgaWritePort(WORD Port, BYTE Data) } } -VOID VgaInitialize(HANDLE TextHandle) +VOID VgaClearMemory(VOID) +{ + ZeroMemory(VgaMemory, sizeof(VgaMemory)); +} + +BOOLEAN VgaInitialize(HANDLE TextHandle) { INT i, j; COORD Resolution; @@ -970,17 +1182,17 @@ VOID VgaInitialize(HANDLE TextHandle) PCHAR_INFO CharBuffer; DWORD Address = 0; DWORD CurrentAddr; + LPLOGPALETTE Palette; /* Set the global handle */ 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); - VgaUpdateMode(); - ModeChanged = FALSE; + VgaChangeMode(); /* Get the data */ Resolution = VgaGetDisplayResolution(); @@ -1016,6 +1228,41 @@ VOID VgaInitialize(HANDLE TextHandle) /* Move to the next scanline */ Address += ScanlineSize; } + + /* Allocate storage space for the palette */ + Palette = (LPLOGPALETTE)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(LOGPALETTE) + + VGA_MAX_COLORS * sizeof(PALETTEENTRY)); + if (Palette == NULL) return FALSE; + + /* Initialize the palette */ + Palette->palVersion = 0x0300; + Palette->palNumEntries = VGA_MAX_COLORS; + + /* Copy the colors of the default palette to the DAC and console palette */ + for (i = 0; i < VGA_MAX_COLORS; i++) + { + /* Set the palette entries */ + Palette->palPalEntry[i].peRed = GetRValue(VgaDefaultPalette[i]); + Palette->palPalEntry[i].peGreen = GetGValue(VgaDefaultPalette[i]); + Palette->palPalEntry[i].peBlue = GetBValue(VgaDefaultPalette[i]); + Palette->palPalEntry[i].peFlags = 0; + + /* Set the DAC registers */ + VgaDacRegisters[i * 3] = VGA_COLOR_TO_DAC(GetRValue(VgaDefaultPalette[i])); + VgaDacRegisters[i * 3 + 1] = VGA_COLOR_TO_DAC(GetGValue(VgaDefaultPalette[i])); + VgaDacRegisters[i * 3 + 2] = VGA_COLOR_TO_DAC(GetBValue(VgaDefaultPalette[i])); + } + + /* Create the palette */ + PaletteHandle = CreatePalette(Palette); + + /* Free the palette */ + HeapFree(GetProcessHeap(), 0, Palette); + + /* Return success if the palette was successfully created */ + return (PaletteHandle ? TRUE : FALSE); } /* EOF */