Author: aandrejevic
Date: Mon Aug 5 23:20:25 2013
New Revision: 59648
URL:
http://svn.reactos.org/svn/reactos?rev=59648&view=rev
Log:
[NTVDM]
Implement Video Graphics Array (VGA) support.
Replace the old BIOS video code with new code that uses the VGA.
Added:
branches/ntvdm/subsystems/ntvdm/vga.c (with props)
branches/ntvdm/subsystems/ntvdm/vga.h (with props)
Modified:
branches/ntvdm/subsystems/ntvdm/CMakeLists.txt
branches/ntvdm/subsystems/ntvdm/bios.c
branches/ntvdm/subsystems/ntvdm/bios.h
branches/ntvdm/subsystems/ntvdm/dos.h
branches/ntvdm/subsystems/ntvdm/emulator.c
branches/ntvdm/subsystems/ntvdm/ntvdm.c
Modified: branches/ntvdm/subsystems/ntvdm/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/CMakeLis…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/CMakeLists.txt [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/CMakeLists.txt [iso-8859-1] Mon Aug 5 23:20:25 2013
@@ -8,6 +8,7 @@
pic.c
timer.c
ps2.c
+ vga.c
ntvdm.c
ntvdm.rc)
Modified: branches/ntvdm/subsystems/ntvdm/bios.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.c?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] Mon Aug 5 23:20:25 2013
@@ -12,6 +12,7 @@
#include "bios.h"
#include "emulator.h"
+#include "vga.h"
#include "pic.h"
#include "ps2.h"
#include "timer.h"
@@ -22,81 +23,138 @@
static BYTE BiosKeyboardMap[256];
static HANDLE BiosConsoleInput = INVALID_HANDLE_VALUE;
static HANDLE BiosConsoleOutput = INVALID_HANDLE_VALUE;
-static HANDLE BiosGraphicsOutput = NULL;
-static LPVOID ConsoleFramebuffer = NULL;
-static HANDLE ConsoleMutex = NULL;
-static BYTE CurrentVideoMode, CurrentVideoPage;
-static BOOLEAN VideoNeedsUpdate = TRUE;
-static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 };
static CONSOLE_SCREEN_BUFFER_INFO BiosSavedBufferInfo;
-static VIDEO_MODE VideoModes[] =
-{
- /* Width | Height | Text | Bpp | Gray | Pages | Segment */
- { 40, 25, TRUE, 16, TRUE, 8, 0xB800}, /* Mode 00h */
- { 40, 25, TRUE, 16, FALSE, 8, 0xB800}, /* Mode 01h */
- { 80, 25, TRUE, 16, TRUE, 8, 0xB800}, /* Mode 02h */
- { 80, 25, TRUE, 16, FALSE, 8, 0xB800}, /* Mode 03h */
- { 320, 200, FALSE, 2, FALSE, 1, 0xB800}, /* Mode 04h */
- { 320, 200, FALSE, 2, TRUE, 1, 0xB800}, /* Mode 05h */
- { 640, 200, FALSE, 1, FALSE, 1, 0xB800}, /* Mode 06h */
- { 80, 25, TRUE, 8, FALSE, 1, 0xB000}, /* Mode 07h */
- { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 08h - not used
*/
- { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 09h - not used
*/
- { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 0Ah - not used
*/
- { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 0Bh - not used
*/
- { 0, 0, FALSE, 0, FALSE, 0, 0x0000}, /* Mode 0Ch - not used
*/
- { 320, 200, FALSE, 4, FALSE, 1, 0xA000}, /* Mode 0Dh */
- { 640, 200, FALSE, 4, FALSE, 1, 0xA000}, /* Mode 0Eh */
- { 640, 350, FALSE, 1, FALSE, 1, 0xA000}, /* Mode 0Fh */
- { 640, 350, FALSE, 4, FALSE, 1, 0xA000}, /* Mode 10h */
- { 640, 480, FALSE, 1, FALSE, 1, 0xA000}, /* Mode 11h */
- { 640, 480, FALSE, 4, FALSE, 1, 0xA000}, /* Mode 12h */
- { 320, 200, FALSE, 8, FALSE, 1, 0xA000} /* Mode 13h */
+static BYTE VideoMode_40x25_text[] =
+{
+ /* Miscellaneous Register */
+ 0x67,
+
+ /* Sequencer Registers */
+ 0x03, 0x08, 0x03, 0x00, 0x02,
+
+ /* GC Registers */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF,
+
+ /* CRTC Registers */
+ 0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0E, 0x0F,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3,
+ 0xFF,
+
+ /* AC Registers */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x01, 0x0F, 0x13, 0x00
};
+static BYTE VideoMode_80x25_text[] =
+{
+ /* Miscellaneous Register */
+ 0x67,
+
+ /* Sequencer Registers */
+ 0x03, 0x00, 0x03, 0x00, 0x02,
+
+ /* GC Registers */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF,
+
+ /* CRTC Registers */
+ 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0E, 0x0F,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
+ 0xFF,
+
+ /* AC Registers */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x01, 0x0F, 0x13, 0x00
+};
+
+static BYTE VideoMode_320x200_4color[] =
+{
+ /* Miscellaneous Register */
+ 0x63,
+
+ /* Sequencer Registers */
+ 0x03, 0x09, 0x03, 0x00, 0x02,
+
+ /* GC Registers */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x0F, 0xFF,
+
+ /* CRTC Registers */
+ 0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2,
+ 0xFF,
+
+ /* AC Registers */
+ 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x03, 0x00, 0x00
+};
+
+static BYTE VideoMode_640x480_16color[] =
+{
+ /* Miscellaneous Register */
+ 0xE3,
+
+ /* Sequencer Registers */
+ 0x03, 0x01, 0x08, 0x00, 0x06,
+
+ /* GC Registers */
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F, 0xFF,
+
+ /* CRTC Registers */
+ 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF,
+
+ /* AC Registers */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00
+};
+
+static BYTE VideoMode_320x200_256color[] =
+{
+ /* Miscellaneous Register */
+ 0x63,
+
+ /* Sequencer Registers */
+ 0x03, 0x01, 0x0F, 0x00, 0x0E,
+
+ /* GC Registers */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF,
+
+ /* CRTC Registers */
+ 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
+ 0xFF,
+
+ /* AC Registers */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00
+};
+
+static LPBYTE VideoModes[] =
+{
+ VideoMode_40x25_text, /* Mode 00h */
+ VideoMode_40x25_text, /* Mode 01h */
+ VideoMode_80x25_text, /* Mode 02h */
+ VideoMode_80x25_text, /* Mode 03h */
+ VideoMode_320x200_4color, /* Mode 04h */
+ VideoMode_320x200_4color, /* Mode 05h */
+ NULL, /* Mode 06h */
+ NULL, /* Mode 07h */
+ NULL, /* Mode 08h */
+ NULL, /* Mode 09h */
+ NULL, /* Mode 0Ah */
+ NULL, /* Mode 0Bh */
+ NULL, /* Mode 0Ch */
+ NULL, /* Mode 0Dh */
+ NULL, /* Mode 0Eh */
+ NULL, /* Mode 0Fh */
+ NULL, /* Mode 10h */
+ NULL, /* Mode 11h */
+ VideoMode_640x480_16color, /* Mode 12h */
+ VideoMode_320x200_256color, /* Mode 13h */
+};
+
/* PRIVATE FUNCTIONS **********************************************************/
-
-static DWORD BiosGetVideoPageSize(VOID)
-{
- INT i;
- DWORD BufferSize = VideoModes[CurrentVideoMode].Width
- * VideoModes[CurrentVideoMode].Height
- * VideoModes[CurrentVideoMode].Bpp
- / 8;
-
- for (i = 0; i < 32; i++) if ((1 << i) >= BufferSize) break;
-
- return 1 << i;
-}
-
-static BYTE BiosVideoAddressToPage(ULONG Address)
-{
- return (Address - BiosGetVideoMemoryStart())
- / BiosGetVideoPageSize();
-}
-
-static COORD BiosVideoAddressToCoord(ULONG Address)
-{
- COORD Result = {0, 0};
- DWORD PageStart = BiosVideoAddressToPage(Address) * BiosGetVideoPageSize();
- DWORD Offset = Address - BiosGetVideoMemoryStart() - PageStart;
-
- if (VideoModes[CurrentVideoMode].Text)
- {
- Result.X = (Offset / sizeof(WORD)) % VideoModes[CurrentVideoMode].Width;
- Result.Y = (Offset / sizeof(WORD)) / VideoModes[CurrentVideoMode].Width;
- }
- else
- {
- Result.X = ((Offset * 8) / VideoModes[CurrentVideoMode].Bpp)
- % VideoModes[CurrentVideoMode].Width;
- Result.Y = ((Offset * 8) / VideoModes[CurrentVideoMode].Bpp)
- / VideoModes[CurrentVideoMode].Width;
- }
-
- return Result;
-}
static BOOLEAN BiosKbdBufferPush(WORD Data)
{
@@ -154,205 +212,125 @@
return TRUE;
}
-static BOOLEAN BiosCreateGraphicsBuffer(BYTE ModeNumber)
+static VOID BiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
+{
+ INT i, j;
+ INT Counter = 0;
+ DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+ {
+ for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+ {
+ WORD Character;
+
+ /* Read from video memory */
+ VgaReadMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
+ (LPVOID)&Character,
+ sizeof(WORD));
+
+ /* Write the data to the buffer in row order */
+ Buffer[Counter++] = Character;
+ }
+ }
+}
+
+static VOID BiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
+{
+ INT i, j;
+ INT Counter = 0;
+ DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+ {
+ for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+ {
+ WORD Character = Buffer[Counter++];
+
+ /* Read from video memory */
+ VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) *
sizeof(WORD),
+ (LPVOID)&Character,
+ sizeof(WORD));
+ }
+ }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BYTE BiosGetVideoMode(VOID)
+{
+ return Bda->VideoMode;
+}
+
+BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
{
INT i;
- CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo;
- LPBITMAPINFO BitmapInfo;
- LPWORD PaletteIndex;
-
- /* Allocate a bitmap info structure */
- BitmapInfo = (LPBITMAPINFO)HeapAlloc(GetProcessHeap(),
- HEAP_ZERO_MEMORY,
- sizeof(BITMAPINFOHEADER)
- + (1 << VideoModes[ModeNumber].Bpp)
- * sizeof(WORD));
- if (BitmapInfo == NULL) return FALSE;
-
- /* Fill the bitmap info header */
- ZeroMemory(&BitmapInfo->bmiHeader, sizeof(BITMAPINFOHEADER));
- BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- BitmapInfo->bmiHeader.biWidth = VideoModes[ModeNumber].Width;
- BitmapInfo->bmiHeader.biHeight = VideoModes[ModeNumber].Height;
- BitmapInfo->bmiHeader.biPlanes = 1;
- BitmapInfo->bmiHeader.biCompression = BI_RGB;
- BitmapInfo->bmiHeader.biBitCount = VideoModes[ModeNumber].Bpp;
-
- /* Calculate the image size */
- BitmapInfo->bmiHeader.biSizeImage = BitmapInfo->bmiHeader.biWidth
- * BitmapInfo->bmiHeader.biHeight
- * (BitmapInfo->bmiHeader.biBitCount >>
3);
-
- /* Fill the palette data */
- PaletteIndex = (LPWORD)((ULONG_PTR)BitmapInfo + sizeof(BITMAPINFOHEADER));
- for (i = 0; i < (1 << VideoModes[ModeNumber].Bpp); i++)
- {
- PaletteIndex[i] = i;
- }
-
- /* Fill the console graphics buffer info */
- GraphicsBufferInfo.dwBitMapInfoLength = sizeof(BITMAPINFOHEADER)
- + (1 << VideoModes[ModeNumber].Bpp)
- * sizeof(WORD);
- GraphicsBufferInfo.lpBitMapInfo = BitmapInfo;
- GraphicsBufferInfo.dwUsage = DIB_PAL_COLORS;
-
- /* Create the buffer */
- BiosGraphicsOutput = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- CONSOLE_GRAPHICS_BUFFER,
- &GraphicsBufferInfo);
-
- /* Save the framebuffer address and mutex */
- ConsoleFramebuffer = GraphicsBufferInfo.lpBitMap;
- ConsoleMutex = GraphicsBufferInfo.hMutex;
-
- /* Free the bitmap information */
- HeapFree(GetProcessHeap(), 0, BitmapInfo);
+ COORD Resolution;
+ LPBYTE Values = VideoModes[ModeNumber];
+
+ if (Values == NULL) return FALSE;
+
+ /* Write the misc register */
+ VgaWritePort(VGA_MISC_WRITE, *(Values++));
+
+ /* Write the sequencer registers */
+ for (i = 0; i < VGA_SEQ_MAX_REG; i++)
+ {
+ VgaWritePort(VGA_SEQ_INDEX, i);
+ VgaWritePort(VGA_SEQ_DATA, *(Values++));
+ }
+
+ /* Write the GC registers */
+ for (i = 0; i < VGA_GC_MAX_REG; i++)
+ {
+ VgaWritePort(VGA_GC_INDEX, i);
+ VgaWritePort(VGA_GC_DATA, *(Values++));
+ }
+
+ /* Write the CRTC registers */
+ for (i = 0; i < VGA_CRTC_MAX_REG; i++)
+ {
+ VgaWritePort(VGA_CRTC_INDEX, i);
+ VgaWritePort(VGA_CRTC_DATA, *(Values++));
+ }
+
+ /* Write the AC registers */
+ for (i = 0; i < VGA_AC_MAX_REG; i++)
+ {
+ VgaWritePort(VGA_AC_INDEX, i);
+ VgaWritePort(VGA_AC_WRITE, *(Values++));
+ }
+
+ /* Update the values in the BDA */
+ Bda->VideoMode = ModeNumber;
+ Bda->VideoPage = 0;
+ Bda->VideoPageSize = BIOS_PAGE_SIZE;
+ Bda->VideoPageOffset = 0;
+ Bda->CharacterHeight = 16;
+
+ Resolution = VgaGetDisplayResolution();
+ Bda->ScreenColumns = Resolution.X;
+ Bda->ScreenRows = Resolution.Y - 1;
return TRUE;
}
-static VOID BiosDestroyGraphicsBuffer(VOID)
-{
- CloseHandle(ConsoleMutex);
- CloseHandle(BiosGraphicsOutput);
-}
-
-/* PUBLIC FUNCTIONS ***********************************************************/
-
-BYTE BiosGetVideoMode(VOID)
-{
- return CurrentVideoMode;
-}
-
-BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
-{
- COORD Coord;
-
- /* Make sure this is a valid video mode */
- if (ModeNumber > BIOS_MAX_VIDEO_MODE) return FALSE;
- if (VideoModes[ModeNumber].Pages == 0) return FALSE;
-
- /* Set the new video mode size */
- Coord.X = VideoModes[ModeNumber].Width;
- Coord.Y = VideoModes[ModeNumber].Height;
-
- if (VideoModes[ModeNumber].Text && VideoModes[CurrentVideoMode].Text)
- {
- /* Switching from text mode to another text mode */
-
- /* Resize the text buffer */
- SetConsoleScreenBufferSize(BiosConsoleOutput, Coord);
- }
- else if (VideoModes[ModeNumber].Text && !VideoModes[CurrentVideoMode].Text)
- {
- /* Switching from graphics mode to text mode */
-
- /* Resize the text buffer */
- SetConsoleScreenBufferSize(BiosConsoleOutput, Coord);
-
- /* Change the active screen buffer to the text buffer */
- SetConsoleActiveScreenBuffer(BiosConsoleOutput);
-
- /* Cleanup the graphics buffer */
- BiosDestroyGraphicsBuffer();
- }
- else if (!VideoModes[ModeNumber].Text && VideoModes[CurrentVideoMode].Text)
- {
- /* Switching from text mode to graphics mode */
- if (!BiosCreateGraphicsBuffer(ModeNumber)) return FALSE;
-
- SetConsoleActiveScreenBuffer(BiosGraphicsOutput);
- }
- else if (!VideoModes[ModeNumber].Text && !VideoModes[CurrentVideoMode].Text)
- {
- /* Switching from graphics mode to another graphics mode */
-
- /* Temporarily switch to the text mode buffer */
- SetConsoleActiveScreenBuffer(BiosConsoleOutput);
-
- /* Cleanup the current graphics mode buffer */
- BiosDestroyGraphicsBuffer();
-
- /* Create a new graphics mode buffer */
- if (!BiosCreateGraphicsBuffer(ModeNumber)) return FALSE;
-
- /* Switch to it */
- SetConsoleActiveScreenBuffer(BiosGraphicsOutput);
- }
-
- /* Change the mode number */
- CurrentVideoMode = ModeNumber;
- CurrentVideoPage = 0;
-
- /* Update the BDA */
- Bda->VideoMode = CurrentVideoMode;
- Bda->VideoPage = CurrentVideoPage;
- Bda->VideoPageSize = BiosGetVideoPageSize();
- Bda->VideoPageOffset = 0;
- Bda->ScreenColumns = VideoModes[ModeNumber].Width;
+BOOLEAN BiosSetVideoPage(BYTE PageNumber)
+{
+ if (PageNumber >= BIOS_MAX_PAGES) return FALSE;
+
+ /* Set the values in the BDA */
+ Bda->VideoPage = PageNumber;
+ Bda->VideoPageSize = BIOS_PAGE_SIZE;
+ Bda->VideoPageOffset = PageNumber * BIOS_PAGE_SIZE;
+
+ /* Set the start address in the CRTC */
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
+ VgaWritePort(VGA_CRTC_DATA, LOBYTE(Bda->VideoPageOffset));
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
+ VgaWritePort(VGA_CRTC_DATA, HIBYTE(Bda->VideoPageOffset));
return TRUE;
-}
-
-BOOLEAN BiosSetVideoPage(BYTE PageNumber)
-{
- ULONG PageStart;
- COORD Coordinates;
- CONSOLE_SCREEN_BUFFER_INFO BufferInfo;
-
- /* Make sure this is a valid page number */
- if (PageNumber >= VideoModes[CurrentVideoMode].Pages) return FALSE;
-
- /* Save the current console buffer in the video memory */
- PageStart = BiosGetVideoMemoryStart() + CurrentVideoPage * BiosGetVideoPageSize();
- BiosUpdateVideoMemory(PageStart, PageStart + BiosGetVideoPageSize());
-
- /* Save the cursor */
- if (!GetConsoleScreenBufferInfo(BiosConsoleOutput, &BufferInfo)) return FALSE;
- Bda->CursorPosition[CurrentVideoPage] = MAKEWORD(BufferInfo.dwCursorPosition.X,
- BufferInfo.dwCursorPosition.Y);
-
- /* Set the page */
- CurrentVideoPage = PageNumber;
-
- /* Update the BDA */
- Bda->VideoPage = CurrentVideoPage;
- Bda->VideoPageSize = BiosGetVideoPageSize();
- Bda->VideoPageOffset = CurrentVideoPage * Bda->VideoPageSize;
-
- /* Update the console */
- PageStart = BiosGetVideoMemoryStart() + Bda->VideoPage * BiosGetVideoPageSize();
- BiosUpdateConsole(PageStart, PageStart + BiosGetVideoPageSize());
-
- /* Set the cursor */
- Coordinates.X = LOBYTE(Bda->CursorPosition[Bda->VideoPage]);
- Coordinates.Y = HIBYTE(Bda->CursorPosition[Bda->VideoPage]);
- SetConsoleCursorPosition(BiosConsoleOutput, Coordinates);
-
- return TRUE;
-}
-
-inline DWORD BiosGetVideoMemoryStart(VOID)
-{
- return (VideoModes[CurrentVideoMode].Segment << 4);
-}
-
-inline VOID BiosVerticalRefresh(VOID)
-{
- /* Ignore if we're in text mode */
- if (VideoModes[CurrentVideoMode].Text) return;
-
- /* Ignore if there's nothing to update */
- if (!VideoNeedsUpdate) return;
-
- /* Redraw the screen */
- InvalidateConsoleDIBits(BiosGraphicsOutput, &UpdateRectangle);
-
- /* Clear the update flag */
- VideoNeedsUpdate = FALSE;
}
BOOLEAN BiosInitialize(VOID)
@@ -425,8 +403,7 @@
Bda->CursorPosition[0] = MAKEWORD(BiosSavedBufferInfo.dwCursorPosition.X,
BiosSavedBufferInfo.dwCursorPosition.Y);
- /* Set the default video mode */
- BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
+ VgaInitialize(BiosConsoleOutput);
/* Set the console input mode */
SetConsoleMode(BiosConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
@@ -466,149 +443,9 @@
/* Restore the screen buffer size */
SetConsoleScreenBufferSize(BiosConsoleOutput, BiosSavedBufferInfo.dwSize);
- /* Free the graphics buffer */
- if (!VideoModes[CurrentVideoMode].Text) BiosDestroyGraphicsBuffer();
-
/* Close the console handles */
if (BiosConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleInput);
if (BiosConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleOutput);
-}
-
-VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress)
-{
- ULONG i;
- COORD Coordinates;
- COORD Origin = { 0, 0 };
- COORD UnitSize = { 1, 1 };
- CHAR_INFO Character;
- SMALL_RECT Rect;
-
- /* Start from the character address */
- StartAddress &= ~1;
-
- if (VideoModes[CurrentVideoMode].Text)
- {
- /* Loop through all the addresses */
- for (i = StartAddress; i < EndAddress; i += 2)
- {
- /* Get the coordinates */
- Coordinates = BiosVideoAddressToCoord(i);
-
- /* Make sure this is the current page */
- if (BiosVideoAddressToPage(i) != CurrentVideoPage) continue;
-
- /* Fill the rectangle structure */
- Rect.Left = Coordinates.X;
- Rect.Top = Coordinates.Y;
- Rect.Right = Rect.Left;
- Rect.Bottom = Rect.Top;
-
- /* Fill the character data */
- Character.Char.AsciiChar = *((PCHAR)((ULONG_PTR)BaseAddress + i));
- Character.Attributes = *((PBYTE)((ULONG_PTR)BaseAddress + i + 1));
-
- /* Write the character */
- WriteConsoleOutputA(BiosConsoleOutput,
- &Character,
- UnitSize,
- Origin,
- &Rect);
- }
- }
- else
- {
- /* Wait for the mutex object */
- WaitForSingleObject(ConsoleMutex, INFINITE);
-
- /* Copy the data to the framebuffer */
- RtlCopyMemory((LPVOID)((ULONG_PTR)ConsoleFramebuffer
- + StartAddress - BiosGetVideoMemoryStart()),
- (LPVOID)((ULONG_PTR)BaseAddress + StartAddress),
- EndAddress - StartAddress);
-
- /* Release the mutex */
- ReleaseMutex(ConsoleMutex);
-
- /* Check if this is the first time the rectangle is updated */
- if (!VideoNeedsUpdate)
- {
- UpdateRectangle.Left = UpdateRectangle.Top = (SHORT)0x7FFF;
- UpdateRectangle.Right = UpdateRectangle.Bottom = (SHORT)0x8000;
- }
-
- /* Expand the update rectangle */
- for (i = StartAddress; i < EndAddress; i++)
- {
- /* Get the coordinates */
- Coordinates = BiosVideoAddressToCoord(i);
-
- /* Expand the rectangle to include the point */
- UpdateRectangle.Left = min(UpdateRectangle.Left, Coordinates.X);
- UpdateRectangle.Right = max(UpdateRectangle.Right, Coordinates.X);
- UpdateRectangle.Top = min(UpdateRectangle.Top, Coordinates.Y);
- UpdateRectangle.Bottom = max(UpdateRectangle.Bottom, Coordinates.Y);
- }
-
- /* Set the update flag */
- VideoNeedsUpdate = TRUE;
- }
-}
-
-VOID BiosUpdateVideoMemory(ULONG StartAddress, ULONG EndAddress)
-{
- ULONG i;
- COORD Coordinates;
- WORD Attribute;
- DWORD CharsWritten;
-
- if (VideoModes[CurrentVideoMode].Text)
- {
- /* Loop through all the addresses */
- for (i = StartAddress; i < EndAddress; i++)
- {
- /* Get the coordinates */
- Coordinates = BiosVideoAddressToCoord(i);
-
- /* Make sure this is the current page */
- if (BiosVideoAddressToPage(i) != CurrentVideoPage) continue;
-
- /* Check if this is a character byte or an attribute byte */
- if ((i - BiosGetVideoMemoryStart()) % 2 == 0)
- {
- /* This is a regular character */
- ReadConsoleOutputCharacterA(BiosConsoleOutput,
- (LPSTR)((ULONG_PTR)BaseAddress + i),
- sizeof(CHAR),
- Coordinates,
- &CharsWritten);
- }
- else
- {
- /* This is an attribute */
- ReadConsoleOutputAttribute(BiosConsoleOutput,
- &Attribute,
- sizeof(CHAR),
- Coordinates,
- &CharsWritten);
-
- *(PCHAR)((ULONG_PTR)BaseAddress + i) = LOBYTE(Attribute);
- }
- }
- }
- else
- {
- /* Wait for the mutex object */
- WaitForSingleObject(ConsoleMutex, INFINITE);
-
- /* Copy the data to the emulator memory */
- RtlCopyMemory((LPVOID)((ULONG_PTR)BaseAddress + StartAddress),
- (LPVOID)((ULONG_PTR)ConsoleFramebuffer
- + StartAddress - BiosGetVideoMemoryStart()),
- EndAddress - StartAddress);
-
- /* Release the mutex */
- ReleaseMutex(ConsoleMutex);
- }
}
WORD BiosPeekCharacter(VOID)
@@ -660,19 +497,124 @@
return CharacterData;
}
+VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
+{
+ /* Make sure the selected video page is valid */
+ if (Page >= BIOS_MAX_PAGES) return;
+
+ /* Update the position in the BDA */
+ Bda->CursorPosition[Page] = (Row << 8) | Column;
+
+ /* Check if this is the current video page */
+ if (Page == Bda->VideoPage)
+ {
+ WORD Offset = Row * Bda->ScreenColumns + Column;
+
+ /* Modify the CRTC registers */
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
+ VgaWritePort(VGA_CRTC_DATA, LOBYTE(Offset));
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
+ VgaWritePort(VGA_CRTC_DATA, HIBYTE(Offset));
+ }
+}
+
+BOOLEAN BiosScrollWindow(INT Direction,
+ DWORD Amount,
+ SMALL_RECT Rectangle,
+ BYTE Page,
+ BYTE FillAttribute)
+{
+ INT i;
+ LPWORD WindowData;
+ DWORD WindowSize = (Rectangle.Bottom - Rectangle.Top + 1)
+ * (Rectangle.Right - Rectangle.Left + 1);
+
+ /* Allocate a buffer for the window */
+ WindowData = (LPWORD)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ WindowSize * sizeof(WORD));
+ if (WindowData == NULL) return FALSE;
+
+ /* Read the window data */
+ BiosReadWindow(WindowData, Rectangle, Page);
+
+ if (Amount == 0)
+ {
+ /* Fill the window */
+ for (i = 0; i < WindowSize; i++)
+ {
+ WindowData[i] = ' ' | (FillAttribute << 8);
+ }
+
+ goto Done;
+ }
+
+ // TODO: Scroll the window!
+
+Done:
+ /* Write back the window data */
+ BiosWriteWindow(WindowData, Rectangle, Page);
+
+ /* Free the window buffer */
+ HeapFree(GetProcessHeap(), 0, WindowData);
+
+ return TRUE;
+}
+
+VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
+{
+ WORD CharData = (Attribute << 8) | Character;
+ BYTE Row, Column;
+
+ /* Make sure the page exists */
+ if (Page >= BIOS_MAX_PAGES) return;
+
+ /* Get the cursor location */
+ Row = HIBYTE(Bda->CursorPosition[Page]);
+ Column = LOBYTE(Bda->CursorPosition[Page]);
+
+ /* Write the character */
+ VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG,
+ (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
+ (LPVOID)&CharData,
+ sizeof(WORD));
+
+ /* Advance the cursor */
+ Column++;
+
+ /* Check if it passed the end of the row */
+ if (Column == Bda->ScreenColumns)
+ {
+ /* Return to the first column */
+ Column = 0;
+
+ if (Row == Bda->ScreenRows)
+ {
+ /* The screen must be scrolled */
+ SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows
};
+
+ BiosScrollWindow(SCROLL_DIRECTION_UP,
+ 1,
+ Rectangle,
+ Page,
+ DEFAULT_ATTRIBUTE);
+ }
+ else Row++;
+ }
+
+ /* Set the cursor position */
+ BiosSetCursorPosition(Row, Column, Page);
+}
+
VOID BiosVideoService(LPWORD Stack)
{
- INT i, CursorHeight;
- BOOLEAN Invisible = FALSE;
- COORD Position;
- CONSOLE_CURSOR_INFO CursorInfo;
- CHAR_INFO Character;
- SMALL_RECT Rect;
DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX);
DWORD Ecx = EmulatorGetRegister(EMULATOR_REG_CX);
DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX);
DWORD Ebx = EmulatorGetRegister(EMULATOR_REG_BX);
+ UNREFERENCED_PARAMETER(Ecx);
+
switch (HIBYTE(Eax))
{
/* Set Video Mode */
@@ -685,20 +627,15 @@
/* Set Text-Mode Cursor Shape */
case 0x01:
{
- /* Retrieve and validate the input */
- Invisible = ((HIBYTE(Ecx) >> 5) & 0x03) ? TRUE : FALSE;
- CursorHeight = (HIBYTE(Ecx) & 0x1F) - (LOBYTE(Ecx) & 0x1F);
- if (CursorHeight < 1) CursorHeight = 1;
- if (CursorHeight > 100) CursorHeight = 100;
-
/* Update the BDA */
Bda->CursorStartLine = HIBYTE(Ecx);
- Bda->CursorEndLine = LOBYTE(Ecx) & 0x1F;
-
- /* Set the cursor */
- CursorInfo.dwSize = (CursorHeight * 100) / CONSOLE_FONT_HEIGHT;
- CursorInfo.bVisible = !Invisible;
- SetConsoleCursorInfo(BiosConsoleOutput, &CursorInfo);
+ Bda->CursorEndLine = LOBYTE(Ecx);
+
+ /* Modify the CRTC registers */
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
+ VgaWritePort(VGA_CRTC_DATA, Bda->CursorStartLine);
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
+ VgaWritePort(VGA_CRTC_DATA, Bda->CursorEndLine);
break;
}
@@ -706,20 +643,7 @@
/* Set Cursor Position */
case 0x02:
{
- /* Make sure the selected video page exists */
- if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
-
- Bda->CursorPosition[HIBYTE(Ebx)] = LOWORD(Edx);
-
- /* Check if this is the current video page */
- if (HIBYTE(Ebx) == CurrentVideoPage)
- {
- /* Yes, change the actual cursor */
- Position.X = LOBYTE(Edx);
- Position.Y = HIBYTE(Edx);
- SetConsoleCursorPosition(BiosConsoleOutput, Position);
- }
-
+ BiosSetCursorPosition(HIBYTE(Edx), LOBYTE(Edx), HIBYTE(Ebx));
break;
}
@@ -727,7 +651,7 @@
case 0x03:
{
/* Make sure the selected video page exists */
- if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
+ if (HIBYTE(Ebx) >= BIOS_MAX_PAGES) break;
/* Return the result */
EmulatorSetRegister(EMULATOR_REG_AX, 0);
@@ -742,10 +666,10 @@
case 0x05:
{
/* Check if the page exists */
- if (LOBYTE(Eax) >= VideoModes[CurrentVideoMode].Pages) break;
+ if (LOBYTE(Eax) >= BIOS_MAX_PAGES) break;
/* Check if this is the same page */
- if (LOBYTE(Eax) == CurrentVideoPage) break;
+ if (LOBYTE(Eax) == Bda->VideoPage) break;
/* Change the video page */
BiosSetVideoPage(LOBYTE(Eax));
@@ -753,110 +677,63 @@
break;
}
- /* Scroll Up/Down Window */
- // TODO: Implement for different pages
+ /* Scroll Window Up/Down */
case 0x06:
case 0x07:
{
- BYTE Lines = LOBYTE(Eax);
-
- Rect.Top = HIBYTE(Ecx);
- Rect.Left = LOBYTE(Ecx);
- Rect.Bottom = HIBYTE(Edx);
- Rect.Right = LOBYTE(Edx);
- Character.Char.UnicodeChar = L' ';
- Character.Attributes = HIBYTE(Ebx);
- Position.X = Rect.Left;
-
- /* 0 means clear entire window */
- if (Lines == 0) Lines = Rect.Bottom - Rect.Top;
-
- if (HIBYTE(Eax) == 0x06) Position.Y = Rect.Top - Lines;
- else Position.Y = Rect.Top + Lines;
-
- ScrollConsoleScreenBuffer(BiosConsoleOutput,
- &Rect,
- &Rect,
- Position,
- &Character);
-
- break;
- }
-
- /* Read Character And Attribute At Cursor Position */
+ SMALL_RECT Rectangle =
+ {
+ LOBYTE(Ecx),
+ HIBYTE(Ecx),
+ LOBYTE(Edx),
+ HIBYTE(Edx)
+ };
+
+ /* Call the internal function */
+ BiosScrollWindow((HIBYTE(Eax)== 0x06)
+ ? SCROLL_DIRECTION_UP : SCROLL_DIRECTION_DOWN,
+ LOBYTE(Eax),
+ Rectangle,
+ Bda->VideoPage,
+ HIBYTE(Ebx));
+
+ break;
+ }
+
+ /* Read/Write Character From Cursor Position */
case 0x08:
- {
- DWORD Address;
-
- /* Make sure this is text mode */
- if (!VideoModes[CurrentVideoMode].Text) break;
-
- /* Make sure the selected video page exists */
- if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
-
- /* Find the address */
- Address = BiosGetVideoMemoryStart()
- + HIBYTE(Ebx) * BiosGetVideoPageSize()
- + (HIBYTE(Bda->CursorPosition[HIBYTE(Ebx)])
- * VideoModes[CurrentVideoMode].Height
- + LOBYTE(Bda->CursorPosition[HIBYTE(Ebx)]))
- * VideoModes[CurrentVideoMode].Bpp / 8;
-
- /* Update the video memory at that address */
- BiosUpdateVideoMemory(Address,
- Address + VideoModes[CurrentVideoMode].Bpp / 8);
-
- /* Return the result in AX */
- EmulatorSetRegister(EMULATOR_REG_AX,
- *((LPWORD)((ULONG_PTR)BaseAddress + Address)));
-
- break;
- } EmulatorSetFlag(EMULATOR_FLAG_ZF);
-
-
- /* Write Character And Attribute At Cursor Position */
case 0x09:
case 0x0A:
{
- BYTE PixelSize = VideoModes[CurrentVideoMode].Bpp / 8;
- WORD Data = (LOBYTE(Ebx) << 8) | LOBYTE(Eax);
- WORD Repeat = LOWORD(Ecx);
- DWORD Address = BiosGetVideoMemoryStart()
- + CurrentVideoPage * BiosGetVideoPageSize()
- + (HIBYTE(Bda->CursorPosition[CurrentVideoPage])
- * VideoModes[CurrentVideoMode].Height
- + LOBYTE(Bda->CursorPosition[CurrentVideoPage]))
- * PixelSize;
-
- /* Make sure this is text mode */
- if (!VideoModes[CurrentVideoMode].Text) break;
-
- /* Make sure the selected video page exists */
- if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
-
- /* Make sure we don't write over the end of video memory */
- Repeat = min(Repeat,
- (CONSOLE_VIDEO_MEM_END - Address)
- / PixelSize);
-
- /* Copy the values to the memory */
- for (i = 0; i < Repeat; i++)
+ WORD CharacterData = MAKEWORD(LOBYTE(Eax), LOBYTE(Ebx));
+ BYTE Page = HIBYTE(Ebx);
+ DWORD Offset;
+
+ /* Check if the page exists */
+ if (Page >= BIOS_MAX_PAGES) break;
+
+ /* Find the offset of the character */
+ Offset = Page * Bda->VideoPageSize
+ + (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns
+ + LOBYTE(Bda->CursorPosition[Page])) * 2;
+
+ if (HIBYTE(Eax) == 0x08)
{
- if (PixelSize == sizeof(BYTE) || HIBYTE(Eax) == 0x0A)
- {
- /* Just characters, no attributes */
- *((LPBYTE)((ULONG_PTR)BaseAddress + Address) + i * PixelSize) =
LOBYTE(Data);
- }
- else if (PixelSize == sizeof(WORD))
- {
- /* First byte for characters, second for attributes */
- *((LPWORD)((ULONG_PTR)BaseAddress + Address) + i) = Data;
- }
+ /* Read from the video memory */
+ VgaReadMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
+ (LPVOID)&CharacterData,
+ sizeof(WORD));
+
+ /* Return the character in AX */
+ EmulatorSetRegister(EMULATOR_REG_AX, CharacterData);
}
-
- /* Update the range */
- BiosUpdateConsole(Address,
- Address + Repeat * (VideoModes[CurrentVideoMode].Bpp /
8));
+ else
+ {
+ /* Write to video memory */
+ VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset),
+ (LPVOID)&CharacterData,
+ (HIBYTE(Ebx) == 0x09) ? sizeof(WORD) : sizeof(BYTE));
+ }
break;
}
@@ -864,22 +741,7 @@
/* Teletype Output */
case 0x0E:
{
- CHAR Character = LOBYTE(Eax);
- DWORD NumWritten;
-
- /* Make sure the page exists */
- if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
-
- /* Set the attribute */
- SetConsoleTextAttribute(BiosConsoleOutput, LOBYTE(Ebx));
-
- /* Write the character */
- WriteConsoleA(BiosConsoleOutput,
- &Character,
- sizeof(CHAR),
- &NumWritten,
- NULL);
-
+ BiosPrintCharacter(LOBYTE(Eax), LOBYTE(Ebx), HIBYTE(Ebx));
break;
}
@@ -897,25 +759,20 @@
/* Scroll Window */
case 0x12:
{
- Rect.Top = HIBYTE(Ecx);
- Rect.Left = LOBYTE(Ecx);
- Rect.Bottom = HIBYTE(Edx);
- Rect.Right = LOBYTE(Edx);
- Character.Char.UnicodeChar = L' ';
- Character.Attributes = 0x07;
- Position.X = Rect.Left;
- Position.Y = Rect.Top;
-
- if (LOBYTE(Ebx) == 0) Position.Y -= LOBYTE(Eax);
- else if (LOBYTE(Ebx) == 1) Position.Y += LOBYTE(Eax);
- else if (LOBYTE(Ebx) == 2) Position.X -= LOBYTE(Eax);
- else if (LOBYTE(Ebx) == 3) Position.X += LOBYTE(Eax);
-
- ScrollConsoleScreenBuffer(BiosConsoleOutput,
- &Rect,
- &Rect,
- Position,
- &Character);
+ SMALL_RECT Rectangle =
+ {
+ LOBYTE(Ecx),
+ HIBYTE(Ecx),
+ LOBYTE(Edx),
+ HIBYTE(Edx)
+ };
+
+ /* Call the internal function */
+ BiosScrollWindow(LOBYTE(Ebx),
+ LOBYTE(Eax),
+ Rectangle,
+ Bda->VideoPage,
+ DEFAULT_ATTRIBUTE);
break;
}
Modified: branches/ntvdm/subsystems/ntvdm/bios.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.h?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] Mon Aug 5 23:20:25 2013
@@ -15,7 +15,6 @@
/* DEFINES ********************************************************************/
-#define CONSOLE_VIDEO_MEM_END 0xBFFFF
#define ROM_AREA_START 0xE0000
#define ROM_AREA_END 0xFFFFF
#define BDA_SEGMENT 0x40
@@ -32,18 +31,19 @@
#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now
#define BIOS_DEFAULT_VIDEO_MODE 0x03
#define BIOS_MAX_PAGES 8
+#define BIOS_PAGE_SIZE 0x1000
#define BIOS_MAX_VIDEO_MODE 0x13
+#define DEFAULT_ATTRIBUTE 0x07
+#define GRAPHICS_VIDEO_SEG 0xA000
+#define TEXT_VIDEO_SEG 0xB800
-typedef struct
+enum
{
- DWORD Width;
- DWORD Height;
- BOOLEAN Text;
- BYTE Bpp;
- BOOLEAN Gray;
- BYTE Pages;
- WORD Segment;
-} VIDEO_MODE;
+ SCROLL_DIRECTION_UP,
+ SCROLL_DIRECTION_DOWN,
+ SCROLL_DIRECTION_LEFT,
+ SCROLL_DIRECTION_RIGHT
+};
#pragma pack(push, 1)
@@ -91,6 +91,8 @@
BYTE ComTimeOut[4];
WORD KeybdBufferStart;
WORD KeybdBufferEnd;
+ BYTE ScreenRows;
+ WORD CharacterHeight;
} BIOS_DATA_AREA, *PBIOS_DATA_AREA;
#pragma pack(pop)
@@ -99,10 +101,8 @@
BOOLEAN BiosInitialize(VOID);
VOID BiosCleanup(VOID);
-VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress);
-VOID BiosUpdateVideoMemory(ULONG StartAddress, ULONG EndAddress);
-inline DWORD BiosGetVideoMemoryStart(VOID);
-inline VOID BiosVerticalRefresh(VOID);
+BYTE BiosGetVideoMode(VOID);
+BOOLEAN BiosSetVideoMode(BYTE ModeNumber);
WORD BiosPeekCharacter(VOID);
WORD BiosGetCharacter(VOID);
VOID BiosVideoService(LPWORD Stack);
@@ -111,5 +111,12 @@
VOID BiosTimeService(LPWORD Stack);
VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack);
VOID BiosSystemTimerInterrupt(LPWORD Stack);
+BOOLEAN BiosScrollWindow(
+ INT Direction,
+ DWORD Amount,
+ SMALL_RECT Rectangle,
+ BYTE Page,
+ BYTE FillAttribute
+);
#endif
Modified: branches/ntvdm/subsystems/ntvdm/dos.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.h?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/dos.h [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/dos.h [iso-8859-1] Mon Aug 5 23:20:25 2013
@@ -98,6 +98,15 @@
CHAR Buffer[ANYSIZE_ARRAY];
} DOS_INPUT_BUFFER, *PDOS_INPUT_BUFFER;
+typedef struct _DOS_DRIVER_HEADER
+{
+ DWORD NextDriver;
+ WORD Attributes;
+ WORD StrategyEntry;
+ WORD InterruptEntry;
+ CHAR DeviceName[8];
+} DOS_DRIVER_HEADER, *PDOS_DRIVER_HEADER;
+
#pragma pack(pop)
/* FUNCTIONS ******************************************************************/
Modified: branches/ntvdm/subsystems/ntvdm/emulator.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] Mon Aug 5 23:20:25 2013
@@ -13,6 +13,7 @@
#include "emulator.h"
#include "bios.h"
#include "dos.h"
+#include "vga.h"
#include "pic.h"
#include "ps2.h"
#include "timer.h"
@@ -40,17 +41,19 @@
/* Make sure the requested address is valid */
if ((Address + Size) >= MAX_ADDRESS) return;
- /* Are we reading some of the console video memory? */
- if (((Address + Size) >= BiosGetVideoMemoryStart())
- && (Address < CONSOLE_VIDEO_MEM_END))
- {
- /* Call the VDM BIOS to update the video memory */
- BiosUpdateVideoMemory(max(Address, BiosGetVideoMemoryStart()),
- min(Address + Size, CONSOLE_VIDEO_MEM_END));
- }
-
/* Read the data from the virtual address space and store it in the buffer */
RtlCopyMemory(Buffer, (LPVOID)((ULONG_PTR)BaseAddress + Address), Size);
+
+ /* Check if we modified the console video memory */
+ if (((Address + Size) >= VgaGetVideoBaseAddress())
+ && (Address < VgaGetVideoLimitAddress()))
+ {
+ DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
+ LPBYTE VgaBuffer = &Buffer[VgaAddress - Address];
+
+ /* Read from the VGA memory */
+ VgaReadMemory(VgaAddress, VgaBuffer, Size);
+ }
}
static VOID EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
@@ -68,12 +71,14 @@
RtlCopyMemory((LPVOID)((ULONG_PTR)BaseAddress + Address), Buffer, Size);
/* Check if we modified the console video memory */
- if (((Address + Size) >= BiosGetVideoMemoryStart())
- && (Address < CONSOLE_VIDEO_MEM_END))
- {
- /* Call the VDM BIOS to update the screen */
- BiosUpdateConsole(max(Address, BiosGetVideoMemoryStart()),
- min(Address + Size, CONSOLE_VIDEO_MEM_END));
+ if (((Address + Size) >= VgaGetVideoBaseAddress())
+ && (Address < VgaGetVideoLimitAddress()))
+ {
+ DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress());
+ LPBYTE VgaBuffer = &Buffer[VgaAddress - Address];
+
+ /* Write to the VGA memory */
+ VgaWriteMemory(VgaAddress, VgaBuffer, Size);
}
}
@@ -115,6 +120,26 @@
break;
}
+ case VGA_AC_WRITE:
+ case VGA_AC_READ:
+ case VGA_SEQ_INDEX:
+ case VGA_SEQ_DATA:
+ case VGA_DAC_READ_INDEX:
+ case VGA_DAC_WRITE_INDEX:
+ case VGA_DAC_DATA:
+ case VGA_MISC_READ:
+ case VGA_MISC_WRITE:
+ case VGA_CRTC_INDEX:
+ case VGA_CRTC_DATA:
+ case VGA_GC_INDEX:
+ case VGA_GC_DATA:
+ case VGA_STAT_MONO:
+ case VGA_STAT_COLOR:
+ {
+ *Buffer = VgaReadPort(Address);
+ break;
+ }
+
default:
{
DPRINT1("Read from unknown port: 0x%X\n", Address);
@@ -165,6 +190,26 @@
case PS2_DATA_PORT:
{
KeyboardWriteData(Byte);
+ break;
+ }
+
+ case VGA_AC_WRITE:
+ case VGA_AC_READ:
+ case VGA_SEQ_INDEX:
+ case VGA_SEQ_DATA:
+ case VGA_DAC_READ_INDEX:
+ case VGA_DAC_WRITE_INDEX:
+ case VGA_DAC_DATA:
+ case VGA_MISC_READ:
+ case VGA_MISC_WRITE:
+ case VGA_CRTC_INDEX:
+ case VGA_CRTC_DATA:
+ case VGA_GC_INDEX:
+ case VGA_GC_DATA:
+ case VGA_STAT_MONO:
+ case VGA_STAT_COLOR:
+ {
+ VgaWritePort(Address, Byte);
break;
}
@@ -478,6 +523,9 @@
/* Skip the opcodes */
EmulatorContext.state->reg_ip += 4;
+ // HACK: Refresh the display because the called function may wait.
+ VgaRefreshDisplay();
+
/* Call the BOP handler */
EmulatorBop(Instruction[1]);
}
Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.c?…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] Mon Aug 5 23:20:25 2013
@@ -13,6 +13,7 @@
#include "ntvdm.h"
#include "emulator.h"
#include "bios.h"
+#include "vga.h"
#include "dos.h"
#include "timer.h"
#include "pic.h"
@@ -137,7 +138,7 @@
DisplayMessage(L"Could not start program: %S", CommandLine);
return -1;
}
-
+
/* Set the last timer tick to the current time */
QueryPerformanceCounter(&LastTimerTick);
@@ -146,18 +147,18 @@
{
/* Get the current number of ticks */
CurrentTickCount = GetTickCount();
-
+
/* Get the current performance counter value */
QueryPerformanceCounter(&Counter);
-
+
/* Get the number of PIT ticks that have passed */
TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart)
* PIT_BASE_FREQUENCY) / Frequency.QuadPart;
-
+
/* Update the PIT */
for (i = 0; i < TimerTicks; i++) PitDecrementCount();
LastTimerTick = Counter;
-
+
/* Check for console input events every millisecond */
if (CurrentTickCount != LastTickCount)
{
@@ -165,20 +166,23 @@
LastTickCount = CurrentTickCount;
}
- /* Check for vertical refresh */
+ /* Check for vertical retrace */
if ((CurrentTickCount - LastVerticalRefresh) >= 16)
{
- BiosVerticalRefresh();
+ VgaRefreshDisplay();
LastVerticalRefresh = CurrentTickCount;
}
-
+
+ /* Horizontal retrace occurs as fast as possible */
+ VgaHorizontalRetrace();
+
/* Continue CPU emulation */
for (i = 0; (i < STEPS_PER_CYCLE) && VdmRunning; i++)
{
EmulatorStep();
Cycles++;
}
-
+
if ((CurrentTickCount - LastCyclePrintout) >= 1000)
{
DPRINT1("NTVDM: %d Instructions Per Second\n", Cycles);
@@ -187,6 +191,9 @@
}
}
+ /* Perform another screen refresh */
+ VgaRefreshDisplay();
+
Cleanup:
BiosCleanup();
EmulatorCleanup();
Added: branches/ntvdm/subsystems/ntvdm/vga.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/vga.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/vga.c (added)
+++ branches/ntvdm/subsystems/ntvdm/vga.c [iso-8859-1] Mon Aug 5 23:20:25 2013
@@ -0,0 +1,974 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: vga.c
+ * PURPOSE: VGA hardware emulation
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+/* INCLUDES *******************************************************************/
+
+#define NDEBUG
+
+#include "vga.h"
+#include "bios.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static BYTE VgaMemory[VGA_NUM_BANKS * VGA_BANK_SIZE];
+static BYTE VgaMiscRegister;
+static BYTE VgaSeqIndex = VGA_SEQ_RESET_REG;
+static BYTE VgaSeqRegisters[VGA_SEQ_MAX_REG];
+static BYTE VgaGcIndex = VGA_GC_RESET_REG;
+static BYTE VgaGcRegisters[VGA_GC_MAX_REG];
+static BYTE VgaCrtcIndex = VGA_CRTC_HORZ_TOTAL_REG;
+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 BOOLEAN VgaDacReadWrite = FALSE;
+static BYTE VgaDacRegisters[VGA_PALETTE_SIZE];
+static BOOLEAN InVerticalRetrace = FALSE;
+static BOOLEAN InHorizontalRetrace = FALSE;
+static HANDLE TextConsoleBuffer = NULL;
+static HANDLE GraphicsConsoleBuffer = NULL;
+static LPVOID ConsoleFramebuffer = NULL;
+static HANDLE ConsoleMutex = NULL;
+static BOOLEAN NeedsUpdate = FALSE;
+static BOOLEAN ModeChanged = TRUE;
+static BOOLEAN CursorMoved = FALSE;
+static BOOLEAN TextMode = TRUE;
+static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 };
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static inline INT VgaGetAddressSize(VOID)
+{
+ if (VgaCrtcRegisters[VGA_CRTC_UNDERLINE_REG] & VGA_CRTC_UNDERLINE_DWORD)
+ {
+ /* Double-word addressing */
+ return 4;
+ }
+
+ if (VgaCrtcRegisters[VGA_CRTC_MODE_CONTROL_REG] & VGA_CRTC_MODE_CONTROL_BYTE)
+ {
+ /* Byte addressing */
+ return 1;
+ }
+
+ /* Word addressing */
+ return 2;
+}
+
+static inline DWORD VgaTranslateReadAddress(DWORD Address)
+{
+ CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
+ DWORD Offset = Address - MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2)
& 0x03];
+ BYTE Plane;
+
+ /* Check for chain-4 and odd-even mode */
+ if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
+ {
+ /* The lowest two bits are the plane number */
+ Plane = Offset & 3;
+ Offset >>= 2;
+ }
+ else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
+ {
+ /* The LSB is the plane number */
+ Plane = Offset & 1;
+ Offset >>= 1;
+ }
+ else
+ {
+ /* Use the read mode */
+ Plane = VgaGcRegisters[VGA_GC_READ_MAP_SEL_REG] & 0x03;
+ }
+
+ /* Multiply the offset by the address size */
+ Offset *= VgaGetAddressSize();
+
+ return Offset + Plane * VGA_BANK_SIZE;
+}
+
+static inline DWORD VgaTranslateWriteAddress(DWORD Address)
+{
+ CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
+ DWORD Offset = Address - MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2)
& 0x03];
+
+ /* Check for chain-4 and odd-even mode */
+ if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
+ {
+ /* Shift the offset to the right by 2 */
+ Offset >>= 2;
+ }
+ else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
+ {
+ /* Shift the offset to the right by 1 */
+ Offset >>= 1;
+ }
+
+ /* Multiply the offset by the address size */
+ Offset *= VgaGetAddressSize();
+
+ /* Return the offset on plane 0 */
+ return Offset;
+}
+
+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;
+ }
+
+ /* Expand the rectangle to include the point */
+ UpdateRectangle.Left = min(UpdateRectangle.Left, Column);
+ UpdateRectangle.Right = max(UpdateRectangle.Right, Column);
+ UpdateRectangle.Top = min(UpdateRectangle.Top, Row);
+ UpdateRectangle.Bottom = max(UpdateRectangle.Bottom, Row);
+
+ /* Set the update request flag */
+ NeedsUpdate = TRUE;
+}
+
+static VOID VgaWriteSequencer(BYTE Data)
+{
+ ASSERT(VgaSeqIndex < VGA_SEQ_MAX_REG);
+
+ /* Save the value */
+ VgaSeqRegisters[VgaSeqIndex] = Data;
+}
+
+static VOID VgaWriteGc(BYTE Data)
+{
+ ASSERT(VgaGcIndex < VGA_GC_MAX_REG);
+
+ /* Save the value */
+ VgaGcRegisters[VgaGcIndex] = Data;
+
+ /* Check the index */
+ switch (VgaGcIndex)
+ {
+ case VGA_GC_MISC_REG:
+ {
+ /* The GC misc register decides if it's text or graphics mode */
+ ModeChanged = TRUE;
+
+ break;
+ }
+ }
+}
+
+static VOID VgaWriteCrtc(BYTE Data)
+{
+ ASSERT(VgaGcIndex < VGA_CRTC_MAX_REG);
+
+ /* Save the value */
+ VgaCrtcRegisters[VgaCrtcIndex] = Data;
+
+ /* Check the index */
+ switch (VgaCrtcIndex)
+ {
+ case VGA_CRTC_END_HORZ_DISP_REG:
+ case VGA_CRTC_VERT_DISP_END_REG:
+ case VGA_CRTC_OVERFLOW_REG:
+ {
+ /* The video mode has changed */
+ ModeChanged = TRUE;
+
+ break;
+ }
+
+ case VGA_CRTC_CURSOR_LOC_LOW_REG:
+ case VGA_CRTC_CURSOR_LOC_HIGH_REG:
+ case VGA_CRTC_CURSOR_START_REG:
+ case VGA_CRTC_CURSOR_END_REG:
+ {
+ /* Set the cursor moved flag */
+ CursorMoved = TRUE;
+
+ break;
+ }
+ }
+}
+
+static VOID VgaWriteDac(BYTE Data)
+{
+ /* Set the value */
+ VgaDacRegisters[VgaDacIndex++] = Data;
+ VgaDacIndex %= VGA_PALETTE_SIZE;
+
+ // TODO: Change the palette!
+}
+
+static VOID VgaWriteAc(BYTE Data)
+{
+ ASSERT(VgaAcIndex < VGA_AC_MAX_REG);
+
+ /* Save the value */
+ VgaAcRegisters[VgaAcIndex] = Data;
+}
+
+static VOID VgaEnterGraphicsMode(UINT Width, UINT Height, UINT BitDepth)
+{
+ INT i;
+ CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo;
+ BYTE BitmapInfoBuffer[VGA_BITMAP_INFO_SIZE];
+ LPBITMAPINFO BitmapInfo = (LPBITMAPINFO)BitmapInfoBuffer;
+ LPWORD PaletteIndex = (LPWORD)(BitmapInfoBuffer + sizeof(BITMAPINFOHEADER));
+
+ /* 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.biBitCount = 8;
+ BitmapInfo->bmiHeader.biPlanes = 1;
+ BitmapInfo->bmiHeader.biCompression = BI_RGB;
+ BitmapInfo->bmiHeader.biSizeImage = Width * Height * (BitDepth / 8);
+
+ /* Fill the palette data */
+ for (i = 0; i < BitDepth; i++) PaletteIndex[i] = i;
+
+ /* Fill the console graphics buffer info */
+ GraphicsBufferInfo.dwBitMapInfoLength = VGA_BITMAP_INFO_SIZE;
+ GraphicsBufferInfo.lpBitMapInfo = BitmapInfo;
+ GraphicsBufferInfo.dwUsage = DIB_PAL_COLORS;
+
+ /* Create the buffer */
+ GraphicsConsoleBuffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ |
FILE_SHARE_WRITE,
+ NULL,
+ CONSOLE_GRAPHICS_BUFFER,
+ &GraphicsBufferInfo);
+
+ /* Save the framebuffer address and mutex */
+ ConsoleFramebuffer = GraphicsBufferInfo.lpBitMap;
+ ConsoleMutex = GraphicsBufferInfo.hMutex;
+
+ /* Set the active buffer */
+ SetConsoleActiveScreenBuffer(GraphicsConsoleBuffer);
+}
+
+static VOID VgaLeaveGraphicsMode()
+{
+ /* Switch back to the text buffer */
+ SetConsoleActiveScreenBuffer(TextConsoleBuffer);
+
+ /* Cleanup the video data */
+ CloseHandle(ConsoleMutex);
+ CloseHandle(GraphicsConsoleBuffer);
+ GraphicsConsoleBuffer = NULL;
+}
+
+static VOID VgaUpdateMode(VOID)
+{
+ COORD Resolution = VgaGetDisplayResolution();
+
+ if (!TextMode)
+ {
+ /* Switching from graphics mode to text mode */
+ VgaLeaveGraphicsMode();
+ }
+ else
+ {
+ /* Free the old framebuffer */
+ HeapFree(GetProcessHeap(), 0, ConsoleFramebuffer);
+ ConsoleFramebuffer = NULL;
+ }
+
+ /* 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)
+ {
+ DisplayMessage(L"An unexpected error occurred!\n");
+ 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;
+ }
+
+ /* Perform a full update */
+ NeedsUpdate = TRUE;
+ UpdateRectangle.Left = 0;
+ UpdateRectangle.Top = 0;
+ UpdateRectangle.Right = Resolution.X;
+ UpdateRectangle.Bottom = Resolution.Y;
+}
+
+static VOID VgaUpdateFramebuffer(VOID)
+{
+ INT i, j, k;
+ COORD Resolution = VgaGetDisplayResolution();
+ INT AddressSize = VgaGetAddressSize();
+ 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++)
+ {
+ /* Check if this is text mode or graphics mode */
+ if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
+ {
+ /* Graphics mode */
+
+ /* Loop through the pixels */
+ for (j = 0; j < Resolution.X; j++)
+ {
+ BYTE PixelData = 0;
+
+ /* Check the shifting mode */
+ if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFT256)
+ {
+ /* 4 bits shifted from each plane */
+
+ /* Check if this is 16 or 256 color mode */
+ if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
+ {
+ /* One byte per pixel */
+ PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE
+ + (Address + (j / VGA_NUM_BANKS))
+ * AddressSize];
+ }
+ else
+ {
+ /* 4-bits per pixel */
+
+ PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE
+ + (Address + (j / (VGA_NUM_BANKS * 2)))
+ * AddressSize];
+
+ /* Check if we should use the highest 4 bits or lowest 4 */
+ if (((j / VGA_NUM_BANKS) % 2) == 0)
+ {
+ /* Highest 4 */
+ PixelData >>= 4;
+ }
+ else
+ {
+ /* Lowest 4 */
+ PixelData &= 0x0F;
+ }
+ }
+ }
+ 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
+ */
+
+ // TODO: NOT IMPLEMENTED!
+ DPRINT1("Interleaved shift mode is not implemented!\n");
+ }
+ else
+ {
+ /* 1 bit shifted from each plane */
+
+ /* Check if this is 16 or 256 color mode */
+ if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
+ {
+ /* 8 bits per pixel, 2 on each plane */
+
+ for (k = 0; k < VGA_NUM_BANKS; k++)
+ {
+ /* The data is on plane k, 4 pixels per byte */
+ BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE
+ + (Address + (j / 4)) *
AddressSize];
+
+ /* The mask of the first bit in the pair */
+ BYTE BitMask = 1 << (((3 - (j % 4)) * 2) + 1);
+
+ /* Bits 0, 1, 2 and 3 come from the first bit of the pair */
+ if (PlaneData & BitMask) PixelData |= 1 << k;
+
+ /* Bits 4, 5, 6 and 7 come from the second bit of the pair
*/
+ if (PlaneData & (BitMask >> 1)) PixelData |= 1
<< (k + 4);
+ }
+ }
+ else
+ {
+ /* 4 bits per pixel, 1 on each plane */
+
+ for (k = 0; k < VGA_NUM_BANKS; k++)
+ {
+ 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;
+ }
+ }
+ }
+
+ /* Now check if the resulting pixel data has changed */
+ if (GraphicsBuffer[i * Resolution.X + j] != PixelData)
+ {
+ /* Yes, write the new value */
+ GraphicsBuffer[i * Resolution.X + j] = PixelData;
+
+ /* Mark the specified pixel as changed */
+ VgaMarkForUpdate(i, j);
+ }
+ }
+ }
+ else
+ {
+ /* Text mode */
+
+ /* Loop through the characters */
+ for (j = 0; j < Resolution.X; j++)
+ {
+ DWORD CurrentAddr = LOWORD((Address + j) * AddressSize);
+ CHAR_INFO CharInfo;
+
+ /* Plane 0 holds the character itself */
+ CharInfo.Char.AsciiChar = VgaMemory[CurrentAddr];
+
+ /* Plane 1 holds the attribute */
+ CharInfo.Attributes = VgaMemory[CurrentAddr + VGA_BANK_SIZE];
+
+ /* Now check if the resulting character data has changed */
+ if ((CharBuffer[i * Resolution.X + j].Char.AsciiChar !=
CharInfo.Char.AsciiChar)
+ || (CharBuffer[i * Resolution.X + j].Attributes !=
CharInfo.Attributes))
+ {
+ /* Yes, write the new value */
+ CharBuffer[i * Resolution.X + j] = CharInfo;
+
+ /* Mark the specified pixel as changed */
+ VgaMarkForUpdate(i, j);
+ }
+ }
+ }
+
+ /* Move to the next scanline */
+ Address += ScanlineSize;
+ }
+}
+
+static VOID VgaUpdateTextCursor(VOID)
+{
+ COORD Position;
+ CONSOLE_CURSOR_INFO CursorInfo;
+ 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;
+ WORD Location = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG],
+ VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG]);
+
+ if (CursorStart < CursorEnd)
+ {
+ /* Visible cursor */
+ CursorInfo.bVisible = TRUE;
+ CursorInfo.dwSize = (100 * (CursorEnd - CursorStart)) >> 5;
+ }
+ else
+ {
+ /* No cursor */
+ CursorInfo.bVisible = FALSE;
+ CursorInfo.dwSize = 0;
+ }
+
+ /* Add the cursor skew to the location */
+ Location += (VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] >> 5) & 3;
+
+ /* Find the coordinates of the new position */
+ Position.X = Location % ScanlineSize;
+ Position.Y = Location / ScanlineSize;
+
+ /* Update the physical cursor */
+ SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo);
+ SetConsoleCursorPosition(TextConsoleBuffer, Position);
+}
+
+/* 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;
+
+ /* The low 8 bits are in the display registers */
+ Resolution.X = VgaCrtcRegisters[VGA_CRTC_END_HORZ_DISP_REG];
+ Resolution.Y = VgaCrtcRegisters[VGA_CRTC_VERT_DISP_END_REG];
+
+ /* Set the top bits from the overflow register */
+ if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE8)
+ {
+ Resolution.Y |= 1 << 8;
+ }
+ if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE9)
+ {
+ Resolution.Y |= 1 << 9;
+ }
+
+ /* Increase the values by 1 */
+ Resolution.X++;
+ Resolution.Y++;
+
+ if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
+ {
+ /* Multiply the horizontal resolution by the 9/8 dot mode */
+ Resolution.X *= (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & VGA_SEQ_CLOCK_98DM)
+ ? 8 : 9;
+
+ /* 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;
+ }
+
+ /* Return the resolution */
+ return Resolution;
+}
+
+VOID VgaRefreshDisplay(VOID)
+{
+ COORD Resolution = VgaGetDisplayResolution();
+
+ DPRINT("VgaRefreshDisplay\n");
+
+ if (ModeChanged)
+ {
+ /* Change the display mode */
+ VgaUpdateMode();
+
+ /* Reset the mode change flag */
+ ModeChanged = FALSE;
+ }
+
+ if (CursorMoved)
+ {
+ /* Change the text cursor location */
+ VgaUpdateTextCursor();
+
+ /* Reset the cursor move flag */
+ CursorMoved = FALSE;
+ }
+
+ /* Update the contents of the framebuffer */
+ VgaUpdateFramebuffer();
+
+ /* Set the vertical retrace flag */
+ InVerticalRetrace = TRUE;
+
+ /* Ignore if there's nothing to update */
+ if (!NeedsUpdate) return;
+
+ DPRINT("Updating screen rectangle (%d, %d, %d, %d)\n",
+ UpdateRectangle.Left,
+ UpdateRectangle.Top,
+ UpdateRectangle.Right,
+ UpdateRectangle.Bottom);
+
+ /* Check if this is text mode or graphics mode */
+ if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)
+ {
+ /* Graphics mode */
+
+ /* Redraw the screen */
+ InvalidateConsoleDIBits(GraphicsConsoleBuffer, &UpdateRectangle);
+ }
+ else
+ {
+ /* Text mode */
+ COORD Origin = { UpdateRectangle.Left, UpdateRectangle.Top };
+
+ /* Write the data to the console */
+ WriteConsoleOutputA(TextConsoleBuffer,
+ (PCHAR_INFO)ConsoleFramebuffer,
+ Resolution,
+ Origin,
+ &UpdateRectangle);
+
+ }
+
+ /* Clear the update flag */
+ NeedsUpdate = FALSE;
+}
+
+VOID VgaHorizontalRetrace(VOID)
+{
+ /* Set the flag */
+ InHorizontalRetrace = TRUE;
+}
+
+VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
+{
+ INT i;
+
+ DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n",
+ Address,
+ Size);
+
+ /* Ignore if video RAM access is disabled */
+ if (!(VgaMiscRegister & VGA_MISC_RAM_ENABLED)) return;
+
+ /* Loop through each byte */
+ for (i = 0; i < Size; i++)
+ {
+ DWORD VideoAddress = VgaTranslateReadAddress(Address + i);
+
+ /* Copy the value to the buffer */
+ Buffer[i] = VgaMemory[VideoAddress];
+ }
+}
+
+VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size)
+{
+ INT i, j;
+
+ DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n",
+ Address,
+ Size);
+
+ /* Ignore if video RAM access is disabled */
+ if (!(VgaMiscRegister & VGA_MISC_RAM_ENABLED)) return;
+
+ /* Also ignore if write access to all planes is disabled */
+ if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return;
+
+ /* Loop through each byte */
+ for (i = 0; i < Size; i++)
+ {
+ DWORD VideoAddress = VgaTranslateWriteAddress(Address + i);
+
+ for (j = 0; j < VGA_NUM_BANKS; j++)
+ {
+ /* Make sure the page is writeable */
+ if (!(VgaSeqRegisters[VGA_SEQ_MASK_REG] & (1 << j))) continue;
+
+ /* Check if this is chain-4 mode */
+ if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
+ {
+ if (((Address + i) & 3) != j)
+ {
+ /* This plane will not be accessed */
+ continue;
+ }
+ }
+
+ /* Check if this is odd-even mode */
+ if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
+ {
+ if (((Address + i) & 1) != (j & 1))
+ {
+ /* This plane will not be accessed */
+ continue;
+ }
+ }
+
+ /* Copy the value to the VGA memory */
+ VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = Buffer[i];
+ }
+ }
+}
+
+BYTE VgaReadPort(WORD Port)
+{
+ DPRINT("VgaReadPort: Port 0x%04X\n", Port);
+
+ switch (Port)
+ {
+ case VGA_AC_INDEX:
+ {
+ return VgaAcIndex;
+ }
+
+ case VGA_AC_READ:
+ {
+ return VgaAcRegisters[VgaAcIndex];
+ }
+
+ case VGA_SEQ_INDEX:
+ {
+ return VgaSeqIndex;
+ }
+
+ case VGA_SEQ_DATA:
+ {
+ return VgaSeqRegisters[VgaSeqIndex];
+ }
+
+ case VGA_DAC_READ_INDEX:
+ {
+ /* This returns the read/write state */
+ return VgaDacReadWrite ? 0 : 3;
+ }
+
+ case VGA_DAC_WRITE_INDEX:
+ {
+ return VgaDacIndex;
+ }
+
+ case VGA_DAC_DATA:
+ {
+ /* Ignore reads in write mode */
+ if (!VgaDacReadWrite)
+ {
+ BYTE Data = VgaDacRegisters[VgaDacIndex++];
+ VgaDacIndex %= VGA_PALETTE_SIZE;
+ return Data;
+ }
+
+ break;
+ }
+
+ case VGA_MISC_READ:
+ {
+ return VgaMiscRegister;
+ }
+
+ case VGA_CRTC_INDEX:
+ {
+ return VgaCrtcIndex;
+ }
+
+ case VGA_CRTC_DATA:
+ {
+ return VgaCrtcRegisters[VgaCrtcIndex];
+ }
+
+ case VGA_GC_INDEX:
+ {
+ return VgaGcIndex;
+ }
+
+ case VGA_GC_DATA:
+ {
+ return VgaGcRegisters[VgaGcIndex];
+ }
+
+ case VGA_STAT_MONO:
+ case VGA_STAT_COLOR:
+ {
+ BYTE Result = 0;
+
+ /* Reset the AC latch */
+ VgaAcLatch = FALSE;
+
+ /* Set a flag if there is a vertical or horizontal retrace */
+ if (InVerticalRetrace || InHorizontalRetrace) Result |= VGA_STAT_DD;
+
+ /* Set an additional flag if there was a vertical retrace */
+ if (InVerticalRetrace) Result |= VGA_STAT_VRETRACE;
+
+ /* Clear the flags */
+ InHorizontalRetrace = InVerticalRetrace = FALSE;
+
+ return Result;
+ }
+ }
+
+ return 0;
+}
+
+VOID VgaWritePort(WORD Port, BYTE Data)
+{
+ DPRINT("VgaWritePort: Port 0x%04X, Data 0x%02X\n", Port, Data);
+
+ switch (Port)
+ {
+ case VGA_AC_INDEX:
+ {
+ if (!VgaAcLatch)
+ {
+ /* Change the index */
+ if (Data < VGA_AC_MAX_REG) VgaAcIndex = Data;
+ }
+ else
+ {
+ /* Write the data */
+ VgaWriteAc(Data);
+ }
+
+ /* Toggle the latch */
+ VgaAcLatch = !VgaAcLatch;
+
+ break;
+ }
+
+ case VGA_SEQ_INDEX:
+ {
+ /* Set the sequencer index register */
+ if (Data < VGA_SEQ_MAX_REG) VgaSeqIndex = Data;
+
+ break;
+ }
+
+ case VGA_SEQ_DATA:
+ {
+ /* Call the sequencer function */
+ VgaWriteSequencer(Data);
+
+ break;
+ }
+
+ case VGA_DAC_READ_INDEX:
+ {
+ VgaDacReadWrite = FALSE;
+ VgaDacIndex = Data % VGA_PALETTE_SIZE;
+
+ break;
+ }
+
+ case VGA_DAC_WRITE_INDEX:
+ {
+ VgaDacReadWrite = TRUE;
+ VgaDacIndex = Data % VGA_PALETTE_SIZE;
+
+ break;
+ }
+
+ case VGA_DAC_DATA:
+ {
+ /* Ignore writes in read mode */
+ if (VgaDacReadWrite) VgaWriteDac(Data & 0x3F);
+
+ break;
+ }
+
+ case VGA_MISC_WRITE:
+ {
+ VgaMiscRegister = Data;
+
+ break;
+ }
+
+ case VGA_CRTC_INDEX:
+ {
+ /* Set the CRTC index register */
+ if (Data < VGA_CRTC_MAX_REG) VgaCrtcIndex = Data;
+
+ break;
+ }
+
+ case VGA_CRTC_DATA:
+ {
+ /* Call the CRTC function */
+ VgaWriteCrtc(Data);
+
+ break;
+ }
+
+ case VGA_GC_INDEX:
+ {
+ /* Set the GC index register */
+ if (Data < VGA_GC_MAX_REG) VgaGcIndex = Data;
+ break;
+ }
+
+ case VGA_GC_DATA:
+ {
+ /* Call the GC function */
+ VgaWriteGc(Data);
+
+ break;
+ }
+ }
+}
+
+VOID VgaInitialize(HANDLE TextHandle)
+{
+ INT i, j;
+ COORD Resolution;
+ INT AddressSize;
+ DWORD ScanlineSize;
+ COORD Origin = { 0, 0 };
+ SMALL_RECT ScreenRect;
+ PCHAR_INFO CharBuffer;
+ DWORD Address = 0;
+
+ /* Set the global handle */
+ TextConsoleBuffer = TextHandle;
+
+ /* Set the default video mode */
+ BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
+ VgaUpdateMode();
+ ModeChanged = FALSE;
+
+ /* Get the data */
+ Resolution = VgaGetDisplayResolution();
+ CharBuffer = (PCHAR_INFO)ConsoleFramebuffer;
+ AddressSize = VgaGetAddressSize();
+ ScreenRect.Left = ScreenRect.Top = 0;
+ ScreenRect.Right = Resolution.X;
+ ScreenRect.Bottom = Resolution.Y;
+ ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
+
+ /* Read the data from the console into the framebuffer */
+ ReadConsoleOutputA(TextConsoleBuffer,
+ ConsoleFramebuffer,
+ 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);
+
+ /* 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;
+ }
+
+ /* Move to the next scanline */
+ Address += ScanlineSize;
+ }
+}
+
+/* EOF */
+
Propchange: branches/ntvdm/subsystems/ntvdm/vga.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: branches/ntvdm/subsystems/ntvdm/vga.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/vga.h?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/vga.h (added)
+++ branches/ntvdm/subsystems/ntvdm/vga.h [iso-8859-1] Mon Aug 5 23:20:25 2013
@@ -0,0 +1,200 @@
+/*
+ * COPYRIGHT: GPL - See COPYING in the top level directory
+ * PROJECT: ReactOS Virtual DOS Machine
+ * FILE: vga.h
+ * PURPOSE: VGA hardware emulation (header file)
+ * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ */
+
+#ifndef _VGA_H_
+#define _VGA_H_
+
+/* INCLUDES *******************************************************************/
+
+#include "ntvdm.h"
+
+/* DEFINES ********************************************************************/
+
+/* Register I/O ports */
+#define VGA_AC_INDEX 0x3C0
+#define VGA_AC_WRITE 0x3C0
+#define VGA_AC_READ 0x3C1
+#define VGA_SEQ_INDEX 0x3C4
+#define VGA_SEQ_DATA 0x3C5
+#define VGA_DAC_READ_INDEX 0x3C7
+#define VGA_DAC_WRITE_INDEX 0x3C8
+#define VGA_DAC_DATA 0x3C9
+#define VGA_MISC_READ 0x3CC
+#define VGA_MISC_WRITE 0x3C2
+#define VGA_CRTC_INDEX 0x3D4
+#define VGA_CRTC_DATA 0x3D5
+#define VGA_GC_INDEX 0x3CE
+#define VGA_GC_DATA 0x3CF
+#define VGA_STAT_MONO 0x3BA
+#define VGA_STAT_COLOR 0x3DA
+
+#define VGA_NUM_BANKS 4
+#define VGA_BANK_SIZE 0x10000
+#define VGA_PALETTE_SIZE 768
+#define VGA_BITMAP_INFO_SIZE (sizeof(BITMAPINFOHEADER) + 2 * (VGA_PALETTE_SIZE / 3))
+
+/* Sequencer reset register bits */
+#define VGA_SEQ_RESET_AR (1 << 0)
+#define VGA_SEQ_RESET_SR (1 << 1)
+
+/* Sequencer clock register bits */
+#define VGA_SEQ_CLOCK_98DM (1 << 0)
+#define VGA_SEQ_CLOCK_SLR (1 << 2)
+#define VGA_SEQ_CLOCK_DCR (1 << 3)
+#define VGA_SEQ_CLOCK_S4 (1 << 4)
+#define VGA_SEQ_CLOCK_SD (1 << 5)
+
+/* Sequencer memory register bits */
+#define VGA_SEQ_MEM_EXT (1 << 1)
+#define VGA_SEQ_MEM_OE (1 << 2)
+#define VGA_SEQ_MEM_C4 (1 << 3)
+
+/* Graphics controller mode register bits */
+#define VGA_GC_MODE_READ (1 << 3)
+#define VGA_GC_MODE_OE (1 << 4)
+#define VGA_GC_MODE_SHIFTREG (1 << 5)
+#define VGA_GC_MODE_SHIFT256 (1 << 6)
+
+/* Graphics controller miscellaneous register bits */
+#define VGA_GC_MISC_NOALPHA (1 << 0)
+#define VGA_GC_MISC_OE (1 << 1)
+
+/* CRTC overflow register bits */
+#define VGA_CRTC_OVERFLOW_VT8 (1 << 0)
+#define VGA_CRTC_OVERFLOW_VDE8 (1 << 1)
+#define VGA_CRTC_OVERFLOW_VRS8 (1 << 2)
+#define VGA_CRTC_OVERFLOW_SVB8 (1 << 3)
+#define VGA_CRTC_OVERFLOW_LC8 (1 << 4)
+#define VGA_CRTC_OVERFLOW_VT9 (1 << 5)
+#define VGA_CRTC_OVERFLOW_VDE9 (1 << 6)
+#define VGA_CRTC_OVERFLOW_VRS9 (1 << 7)
+
+/* CRTC underline register bits */
+#define VGA_CRTC_UNDERLINE_DWORD (1 << 6)
+
+/* CRTC mode control register bits */
+#define VGA_CRTC_MODE_CONTROL_WRAP (1 << 5)
+#define VGA_CRTC_MODE_CONTROL_BYTE (1 << 6)
+#define VGA_CRTC_MODE_CONTROL_SYNC (1 << 7)
+
+/* AC control register bits */
+#define VGA_AC_CONTROL_ATGE (1 << 0)
+#define VGA_AC_CONTROL_MONO (1 << 1)
+#define VGA_AC_CONTROL_LGE (1 << 2)
+#define VGA_AC_CONTROL_BLINK (1 << 3)
+#define VGA_AC_CONTROL_PPM (1 << 5)
+#define VGA_AC_CONTROL_8BIT (1 << 6)
+#define VGA_AC_CONTROL_P54S (1 << 7)
+
+/* Miscellaneous register bits */
+#define VGA_MISC_COLOR (1 << 0)
+#define VGA_MISC_RAM_ENABLED (1 << 1)
+#define VGA_MISC_OE_INVERT (1 << 5)
+#define VGA_MISC_HSYNCP (1 << 6)
+#define VGA_MISC_VSYNCP (1 << 7)
+
+/* Status register flags */
+#define VGA_STAT_DD (1 << 0)
+#define VGA_STAT_VRETRACE (1 << 3)
+
+enum
+{
+ VGA_SEQ_RESET_REG,
+ VGA_SEQ_CLOCK_REG,
+ VGA_SEQ_MASK_REG,
+ VGA_SEQ_CHAR_REG,
+ VGA_SEQ_MEM_REG,
+ VGA_SEQ_MAX_REG
+};
+
+enum
+{
+ VGA_GC_RESET_REG,
+ VGA_GC_ENABLE_RESET_REG,
+ VGA_GC_COLOR_COMPARE_REG,
+ VGA_GC_ROTATE_REG,
+ VGA_GC_READ_MAP_SEL_REG,
+ VGA_GC_MODE_REG,
+ VGA_GC_MISC_REG,
+ VGA_GC_COLOR_IGNORE_REG,
+ VGA_GC_BITMASK_REG,
+ VGA_GC_MAX_REG
+};
+
+enum
+{
+ VGA_CRTC_HORZ_TOTAL_REG,
+ VGA_CRTC_END_HORZ_DISP_REG,
+ VGA_CRTC_START_HORZ_BLANKING_REG,
+ VGA_CRTC_END_HORZ_BLANKING_REG,
+ VGA_CRTC_START_HORZ_RETRACE_REG,
+ VGA_CRTC_END_HORZ_RETRACE_REG,
+ VGA_CRTC_VERT_TOTAL_REG,
+ VGA_CRTC_OVERFLOW_REG,
+ VGA_CRTC_PRESET_ROW_SCAN_REG,
+ VGA_CRTC_MAX_SCAN_LINE_REG,
+ VGA_CRTC_CURSOR_START_REG,
+ VGA_CRTC_CURSOR_END_REG,
+ VGA_CRTC_START_ADDR_HIGH_REG,
+ VGA_CRTC_START_ADDR_LOW_REG,
+ VGA_CRTC_CURSOR_LOC_HIGH_REG,
+ VGA_CRTC_CURSOR_LOC_LOW_REG,
+ VGA_CRTC_VERT_RETRACE_START_REG,
+ VGA_CRTC_VERT_RETRACE_END_REG,
+ VGA_CRTC_VERT_DISP_END_REG,
+ VGA_CRTC_OFFSET_REG,
+ VGA_CRTC_UNDERLINE_REG,
+ VGA_CRTC_START_VERT_BLANKING_REG,
+ VGA_CRTC_END_VERT_BLANKING,
+ VGA_CRTC_MODE_CONTROL_REG,
+ VGA_CRTC_LINE_COMPARE_REG,
+ VGA_CRTC_MAX_REG
+};
+
+enum
+{
+ VGA_AC_PAL_0_REG,
+ VGA_AC_PAL_1_REG,
+ VGA_AC_PAL_2_REG,
+ VGA_AC_PAL_3_REG,
+ VGA_AC_PAL_4_REG,
+ VGA_AC_PAL_5_REG,
+ VGA_AC_PAL_6_REG,
+ VGA_AC_PAL_7_REG,
+ VGA_AC_PAL_8_REG,
+ VGA_AC_PAL_9_REG,
+ VGA_AC_PAL_A_REG,
+ VGA_AC_PAL_B_REG,
+ VGA_AC_PAL_C_REG,
+ VGA_AC_PAL_D_REG,
+ VGA_AC_PAL_E_REG,
+ VGA_AC_PAL_F_REG,
+ VGA_AC_CONTROL_REG,
+ VGA_AC_OVERSCAN_REG,
+ VGA_AC_COLOR_PLANE_REG,
+ VGA_AC_HORZ_PANNING_REG,
+ VGA_AC_COLOR_SEL_REG,
+ VGA_AC_MAX_REG
+};
+
+/* FUNCTIONS ******************************************************************/
+
+DWORD VgaGetVideoBaseAddress(VOID);
+DWORD VgaGetVideoLimitAddress(VOID);
+COORD VgaGetDisplayResolution(VOID);
+VOID VgaRefreshDisplay(VOID);
+VOID VgaHorizontalRetrace(VOID);
+VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size);
+VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size);
+BYTE VgaReadPort(WORD Port);
+VOID VgaWritePort(WORD Port, BYTE Data);
+VOID VgaInitialize(HANDLE TextHandle);
+
+#endif
+
+/* EOF */
Propchange: branches/ntvdm/subsystems/ntvdm/vga.h
------------------------------------------------------------------------------
svn:eol-style = native