+BYTE BiosGetVideoMode()
+{
+ return CurrentVideoMode;
+}
+
+BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
+{
+ INT i;
+ COORD Coord;
+ CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo;
+ LPBITMAPINFO BitmapInfo;
+ LPWORD PaletteIndex;
+
+ /* Make sure this is a valid video mode */
+ if (ModeNumber > BIOS_MAX_VIDEO_MODE) return FALSE;
+ if (VideoModes[ModeNumber].Pages == 0) return FALSE;
+
+ /* Free the current buffers */
+ for (i = 0; i < VideoModes[CurrentVideoMode].Pages; i++)
+ {
+ if (ConsoleBuffers[i] != NULL) CloseHandle(ConsoleBuffers[i]);
+ }
+
+ if (VideoModes[ModeNumber].Text)
+ {
+ /* Page 0 is CONOUT$ */
+ ConsoleBuffers[0] = CreateFile(TEXT("CONOUT$"),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ /* Set the current page to page 0 */
+ CurrentVideoPage = 0;
+
+ /* Create console buffers for other pages */
+ for (i = 1; i < VideoModes[ModeNumber].Pages; i++)
+ {
+ ConsoleBuffers[i] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CONSOLE_TEXTMODE_BUFFER,
+ NULL);
+ }
+
+ /* Set the size for the buffers */
+ for (i = 0; i < VideoModes[ModeNumber].Pages; i++)
+ {
+ Coord.X = VideoModes[ModeNumber].Width;
+ Coord.Y = VideoModes[ModeNumber].Height;
+
+ SetConsoleScreenBufferSize(ConsoleBuffers[i], Coord);
+ }
+ }
+ else
+ {
+ /* Allocate a bitmap info structure */
+ BitmapInfo = (LPBITMAPINFO)HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ sizeof(BITMAPINFOHEADER)
+ + VideoModes[ModeNumber].Colors
+ * 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;
+
+ /* Calculate the number of color bits */
+ for (i = 31; i >= 0; i--)
+ {
+ if (VideoModes[ModeNumber].Colors & (1 << i)) break;
+ }
+ if (i == 0) i = 32;
+ BitmapInfo->bmiHeader.biBitCount = i;
+
+ /* 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 < VideoModes[ModeNumber].Colors; i++)
+ {
+ PaletteIndex[i] = i;
+ }
+
+ /* Create a console buffer for each page */
+ for (i = 0; i < VideoModes[ModeNumber].Pages; i++)
+ {
+ /* Fill the console graphics buffer info */
+ GraphicsBufferInfo.dwBitMapInfoLength = sizeof(BITMAPINFOHEADER)
+ + VideoModes[ModeNumber].Colors
+ * sizeof(WORD);
+ GraphicsBufferInfo.lpBitMapInfo = BitmapInfo;
+ GraphicsBufferInfo.dwUsage = DIB_PAL_COLORS;
+
+ /* Create the buffer */
+ ConsoleBuffers[i] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CONSOLE_GRAPHICS_BUFFER,
+ &GraphicsBufferInfo);
+
+ /* Save the framebuffer address */
+ ConsoleFramebuffers[i] = GraphicsBufferInfo.lpBitMap;
+ }
+
+ /* Free the bitmap information */
+ HeapFree(GetProcessHeap(), 0, BitmapInfo);
+ }
+
+ /* Set the active page console buffer */
+ SetConsoleActiveScreenBuffer(ConsoleBuffers[CurrentVideoPage]);
+
+ /* Update the mode number */
+ CurrentVideoMode = ModeNumber;
+
+ return TRUE;
+}
+
+inline DWORD BiosGetVideoMemoryStart()
+{
+ return (VideoModes[CurrentVideoMode].Segment << 4);
+}
+
+inline VOID BiosVerticalRefresh()
+{
+ SMALL_RECT Region;
+
+ /* Ignore if we're in text mode */
+ if (VideoModes[CurrentVideoMode].Text) return;
+
+ /* Fill the rectangle structure */
+ Region.Left = Region.Top = 0;
+ Region.Right = VideoModes[CurrentVideoMode].Width;
+ Region.Bottom = VideoModes[CurrentVideoMode].Height;
+
+ /* Redraw the screen */
+ InvalidateConsoleDIBits(ConsoleBuffers[CurrentVideoPage],
+ &Region);
+}
+
+BOOLEAN BiosInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)