/* PRIVATE VARIABLES **********************************************************/
+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];
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;
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 };
static inline DWORD VgaTranslateReadAddress(DWORD Address)
{
- CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
- DWORD Offset = Address - MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
+ DWORD Offset = Address - VgaGetVideoBaseAddress();
BYTE Plane;
/* Check for chain-4 and odd-even mode */
static inline DWORD VgaTranslateWriteAddress(DWORD Address)
{
- CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
- DWORD Offset = Address - MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
+ DWORD Offset = Address - VgaGetVideoBaseAddress();
/* Check for chain-4 and odd-even mode */
if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
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);
/* Check if this is the first time the rectangle is updated */
if (!NeedsUpdate)
{
- UpdateRectangle.Left = UpdateRectangle.Top = (SHORT)0x7FFF;
- UpdateRectangle.Right = UpdateRectangle.Bottom = (SHORT)0x8000;
+ UpdateRectangle.Left = UpdateRectangle.Top = SHRT_MAX;
+ UpdateRectangle.Right = UpdateRectangle.Bottom = SHRT_MIN;
}
/* Expand the rectangle to include the point */
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)
VgaAcRegisters[VgaAcIndex] = Data;
}
-static VOID VgaEnterGraphicsMode(UINT Width, UINT Height, UINT BitDepth)
+static BOOL VgaEnterGraphicsMode(PCOORD Resolution)
{
- INT i;
+ DWORD i;
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));
BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- BitmapInfo->bmiHeader.biWidth = Width;
- BitmapInfo->bmiHeader.biHeight = Height;
+ BitmapInfo->bmiHeader.biWidth = Resolution->X;
+ BitmapInfo->bmiHeader.biHeight = Resolution->Y;
BitmapInfo->bmiHeader.biBitCount = 8;
BitmapInfo->bmiHeader.biPlanes = 1;
BitmapInfo->bmiHeader.biCompression = BI_RGB;
- BitmapInfo->bmiHeader.biSizeImage = Width * Height * (BitDepth / 8);
+ BitmapInfo->bmiHeader.biSizeImage = Resolution->X * Resolution->Y /* * 1 == biBitCount / 8 */;
/* Fill the palette data */
- for (i = 0; i < BitDepth; i++) PaletteIndex[i] = i;
+ for (i = 0; i < (VGA_PALETTE_SIZE / 3); i++) PaletteIndex[i] = (WORD)i;
/* Fill the console graphics buffer info */
GraphicsBufferInfo.dwBitMapInfoLength = VGA_BITMAP_INFO_SIZE;
NULL,
CONSOLE_GRAPHICS_BUFFER,
&GraphicsBufferInfo);
+ if (GraphicsConsoleBuffer == INVALID_HANDLE_VALUE) return FALSE;
/* Save the framebuffer address and mutex */
ConsoleFramebuffer = GraphicsBufferInfo.lpBitMap;
ConsoleMutex = GraphicsBufferInfo.hMutex;
+ /* Clear the framebuffer */
+ ZeroMemory(ConsoleFramebuffer, BitmapInfo->bmiHeader.biSizeImage);
+
/* 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;
}
-static VOID VgaLeaveGraphicsMode()
-{
+static VOID VgaLeaveGraphicsMode(VOID)
+{
+ /* Release the console framebuffer mutex if needed */
+ ReleaseMutex(ConsoleMutex);
+
/* Switch back to the text buffer */
SetConsoleActiveScreenBuffer(TextConsoleBuffer);
/* Cleanup the video data */
CloseHandle(ConsoleMutex);
+ ConsoleMutex = NULL;
CloseHandle(GraphicsConsoleBuffer);
GraphicsConsoleBuffer = NULL;
}
-static VOID VgaUpdateMode(VOID)
+static BOOL VgaEnterTextMode(PCOORD Resolution)
+{
+ /* Resize the console */
+ SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution);
+
+ /* Allocate a framebuffer */
+ ConsoleFramebuffer = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ Resolution->X * Resolution->Y
+ * sizeof(CHAR_INFO));
+ if (ConsoleFramebuffer == NULL)
+ {
+ DisplayMessage(L"An unexpected error occurred!\n");
+ VdmRunning = FALSE;
+ return FALSE;
+ }
+
+ /* Set the text mode flag */
+ TextMode = TRUE;
+
+ return TRUE;
+}
+
+static VOID VgaLeaveTextMode(VOID)
+{
+ /* Free the old framebuffer */
+ HeapFree(GetProcessHeap(), 0, ConsoleFramebuffer);
+ ConsoleFramebuffer = NULL;
+}
+
+static VOID VgaChangeMode(VOID)
{
COORD Resolution = VgaGetDisplayResolution();
+ /* Reset the mode change flag */
+ // ModeChanged = FALSE;
+
if (!TextMode)
{
- /* Switching from graphics mode to text mode */
+ /* Leave the current graphics mode */
VgaLeaveGraphicsMode();
}
else
{
- /* Free the old framebuffer */
- HeapFree(GetProcessHeap(), 0, ConsoleFramebuffer);
- ConsoleFramebuffer = NULL;
+ /* Leave the current text mode */
+ VgaLeaveTextMode();
}
/* Check if the new mode is alphanumeric */
if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA))
{
- /* Resize the console */
- SetConsoleScreenBufferSize(TextConsoleBuffer, Resolution);
-
- /* Allocate a framebuffer */
- ConsoleFramebuffer = HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof(CHAR_INFO)
- * Resolution.X
- * Resolution.Y);
- if (ConsoleFramebuffer == NULL)
+ /* Enter new text mode */
+ if (!VgaEnterTextMode(&Resolution))
{
- DisplayMessage(L"An unexpected error occurred!\n");
+ DisplayMessage(L"An unexpected VGA error occurred while switching into text mode.");
VdmRunning = FALSE;
return;
}
-
- /* Set the text mode flag */
- TextMode = TRUE;
}
else
{
/* Enter 8-bit graphics mode */
- VgaEnterGraphicsMode(Resolution.X, Resolution.Y, 8);
-
- /* 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)
DWORD Address = (VgaCrtcRegisters[VGA_CRTC_START_ADDR_HIGH_REG] << 8)
+ VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG];
DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
- PCHAR_INFO CharBuffer = (PCHAR_INFO)ConsoleFramebuffer;
- PBYTE GraphicsBuffer = (PBYTE)ConsoleFramebuffer;
- /* Loop through the scanlines */
- for (i = 0; i < Resolution.Y; i++)
+ /*
+ * 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)
{
- /* Check if this is text mode or graphics mode */
- if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
- {
- /* Graphics mode */
+ /* Graphics mode */
+ PBYTE GraphicsBuffer = (PBYTE)ConsoleFramebuffer;
+
+ /*
+ * Synchronize access to the graphics framebuffer
+ * with the console framebuffer mutex.
+ */
+ WaitForSingleObject(ConsoleMutex, INFINITE);
+ /* Loop through the scanlines */
+ for (i = 0; i < Resolution.Y; i++)
+ {
/* Loop through the pixels */
for (j = 0; j < Resolution.X; j++)
{
}
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];
- // TODO: NOT IMPLEMENTED!
- DPRINT1("Interleaved shift mode is not implemented!\n");
+ /* Extract the two bits from each plane */
+ LowPlaneData = (LowPlaneData >> (6 - ((j % 4) * 2))) & 3;
+ HighPlaneData = (HighPlaneData >> (6 - ((j % 4) * 2))) & 3;
+
+ /* Combine them into the pixel */
+ PixelData = LowPlaneData | (HighPlaneData << 2);
+ }
}
else
{
{
BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE
+ (Address + (j / 8)) * AddressSize];
-
+
/* If the bit on that plane is set, set it */
if (PlaneData & (1 << (7 - (j % 8)))) PixelData |= 1 << k;
}
}
}
+ 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)
{
VgaMarkForUpdate(i, j);
}
}
+
+ /* Move to the next scanline */
+ Address += ScanlineSize;
}
- else
- {
- /* Text mode */
+ /*
+ * Release the console framebuffer mutex
+ * so that we allow for repainting.
+ */
+ ReleaseMutex(ConsoleMutex);
+ }
+ else
+ {
+ /* Text mode */
+ PCHAR_INFO CharBuffer = (PCHAR_INFO)ConsoleFramebuffer;
+
+ /* Loop through the scanlines */
+ for (i = 0; i < Resolution.Y; i++)
+ {
/* Loop through the characters */
for (j = 0; j < Resolution.X; j++)
{
/* 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);
}
}
- }
- /* Move to the next scanline */
- Address += ScanlineSize;
+ /* Move to the next scanline */
+ Address += ScanlineSize;
+ }
}
}
BYTE CursorStart = VgaCrtcRegisters[VGA_CRTC_CURSOR_START_REG] & 0x3F;
BYTE CursorEnd = VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] & 0x1F;
DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
+ BYTE TextSize = 1 + (VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F);
WORD Location = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG],
VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG]);
{
/* Visible cursor */
CursorInfo.bVisible = TRUE;
- CursorInfo.dwSize = (100 * (CursorEnd - CursorStart)) >> 5;
+ CursorInfo.dwSize = (100 * (CursorEnd - CursorStart)) / TextSize;
}
else
{
Location += (VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] >> 5) & 3;
/* Find the coordinates of the new position */
- Position.X = Location % ScanlineSize;
- Position.Y = Location / ScanlineSize;
+ Position.X = (WORD)(Location % ScanlineSize);
+ Position.Y = (WORD)(Location / ScanlineSize);
/* Update the physical cursor */
SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo);
SetConsoleCursorPosition(TextConsoleBuffer, Position);
+
+ /* Reset the cursor move flag */
+ CursorMoved = FALSE;
}
/* PUBLIC FUNCTIONS ***********************************************************/
DWORD VgaGetVideoBaseAddress(VOID)
{
- CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
}
DWORD VgaGetVideoLimitAddress(VOID)
{
- CONST DWORD MemoryLimit[] = { 0xA7FFF, 0xA7FFF, 0xB7FFF, 0xBFFFF };
return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03];
}
COORD VgaGetDisplayResolution(VOID)
{
COORD Resolution;
+ 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];
/* 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 /= 16;
}
+ /* Divide the vertical resolution by the maximum scan line (== font size in text mode) */
+ Resolution.Y /= MaximumScanLine;
+
/* Return the resolution */
return Resolution;
}
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 */
VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
{
- INT i;
+ DWORD i;
+ DWORD VideoAddress;
DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n",
Address,
/* Loop through each byte */
for (i = 0; i < Size; i++)
{
- DWORD VideoAddress = VgaTranslateReadAddress(Address + i);
+ 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];
VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
{
- INT i, j;
+ DWORD i, j;
+ DWORD VideoAddress;
DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n",
Address,
/* Loop through each byte */
for (i = 0; i < Size; i++)
{
- DWORD VideoAddress = VgaTranslateWriteAddress(Address + i);
+ VideoAddress = VgaTranslateWriteAddress(Address + i);
for (j = 0; j < VGA_NUM_BANKS; j++)
{
}
/* 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);
}
}
}
case VGA_DAC_WRITE_INDEX:
{
- return VgaDacIndex;
+ return VgaDacIndex / 3;
}
case VGA_DAC_DATA:
case VGA_DAC_READ_INDEX:
{
VgaDacReadWrite = FALSE;
- VgaDacIndex = Data % VGA_PALETTE_SIZE;
+ VgaDacIndex = Data * 3;
break;
}
case VGA_DAC_WRITE_INDEX:
{
VgaDacReadWrite = TRUE;
- VgaDacIndex = Data % VGA_PALETTE_SIZE;
+ VgaDacIndex = Data * 3;
break;
}
}
}
-VOID VgaInitialize(HANDLE TextHandle)
+VOID VgaClearMemory(VOID)
+{
+ ZeroMemory(VgaMemory, sizeof(VgaMemory));
+}
+
+BOOLEAN VgaInitialize(HANDLE TextHandle)
{
INT i, j;
COORD Resolution;
SMALL_RECT ScreenRect;
PCHAR_INFO CharBuffer;
DWORD Address = 0;
+ DWORD CurrentAddr;
+ LPLOGPALETTE Palette;
/* Set the global handle */
TextConsoleBuffer = TextHandle;
+ /* Clear the VGA memory */
+ VgaClearMemory();
+
/* Set the default video mode */
BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
- VgaUpdateMode();
- ModeChanged = FALSE;
+ VgaChangeMode();
/* Get the data */
Resolution = VgaGetDisplayResolution();
/* Read the data from the console into the framebuffer */
ReadConsoleOutputA(TextConsoleBuffer,
- ConsoleFramebuffer,
+ CharBuffer,
Resolution,
Origin,
&ScreenRect);
-
/* Loop through the scanlines */
for (i = 0; i < Resolution.Y; i++)
{
/* Loop through the characters */
for (j = 0; j < Resolution.X; j++)
{
- DWORD CurrentAddr = LOWORD((Address + j) * AddressSize);
+ CurrentAddr = LOWORD((Address + j) * AddressSize);
/* Store the character in plane 0 */
VgaMemory[CurrentAddr] = CharBuffer[i * Resolution.X + j].Char.AsciiChar;
/* Store the attribute in plane 1 */
- VgaMemory[CurrentAddr + VGA_BANK_SIZE] = CharBuffer[i * Resolution.X + j].Attributes;
+ VgaMemory[CurrentAddr + VGA_BANK_SIZE] = (BYTE)CharBuffer[i * Resolution.X + j].Attributes;
}
/* 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 */
-