reactos/subsystems/ntvdm/bios/vidbios.c
Hermès Bélusca-Maïto 6ddfa7d2b8 [NTVDM]
- Move all the hardware initialization to EmulatorInitialize (since emulator.c can be viewed as support functions for emulating a PC motherboard) --> PS2 and VGA go there.
- Break bios.c into bios.c and kbdbios.c (the keyboard bios module) (according to the IBM documentation as well as other emulator sources or SeaBIOS or...).
- Move Exception handling from int32.c to emulator.c, because it's something tight to the emulator, not to the interrupt system by itself (yet it happens that INT 00h to 07h are commonly set to some exception handlers). In the bios.c, initialize those vectors with the default exception handler.
- Handling IRQs is done fully in bios.c now: introduce PicSetIRQMask and EnableHwIRQ helper functions (adapted from their equivalents from SeaBIOS) that allows the bios to set (and activate in the PIC) a given IRQ with its corresponding handler. Also introduce PicIRQComplete that serves as a PIC IRQ completer (i.e. sends the EOI to the right PIC(s)).
- Continuing on that, at the moment I set dumb default PIC IRQ handlers for IRQ 08h - 0Fh and IRQ 70h - 77h).
- By default I disable all the IRQs; there are then set on-demand with EnableHwIRQ.
- Rework the POST (aka. BiosInitialize function):
  * the memory size is now get from the CMOS (as well as the extended memory size via INT 12h, AH=88h),
  * then we initialize the interrupts,
  * then platform hardware (ie. the chips) are initialized,
  * and finally the keyboard and video bioses.
- As said before, move memory sizes into the CMOS.
- Simplify video bios initialization.

svn path=/branches/ntvdm/; revision=61796
2014-01-25 00:21:51 +00:00

1574 lines
62 KiB
C

/*
* COPYRIGHT: GPL - See COPYING in the top level directory
* PROJECT: ReactOS Virtual DOS Machine
* FILE: vidbios.c
* PURPOSE: VDM Video BIOS
* PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
// #include "vidbios.h"
#include "bios.h"
#include "io.h"
#include "hardware/vga.h"
#include "int32.h"
/* MACROS *********************************************************************/
//
// These macros are defined for ease-of-use of some VGA I/O ports
// whose addresses depend whether we are in Monochrome or Colour mode.
//
#define VGA_INSTAT1_READ Bda->CrtBasePort + 6 // VGA_INSTAT1_READ_MONO or VGA_INSTAT1_READ_COLOR
#define VGA_CRTC_INDEX Bda->CrtBasePort // VGA_CRTC_INDEX_MONO or VGA_CRTC_INDEX_COLOR
#define VGA_CRTC_DATA Bda->CrtBasePort + 1 // VGA_CRTC_DATA_MONO or VGA_CRTC_DATA_COLOR
/* PRIVATE VARIABLES **********************************************************/
/*
* VGA Register Configurations for BIOS Video Modes
* The configurations come from DOSBox.
*/
static VGA_REGISTERS VideoMode_40x25_text =
{
/* Miscellaneous Register */
0x67,
/* Sequencer Registers */
{0x00, 0x08, 0x03, 0x00, 0x07},
/* CRTC Registers */
{0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
/* AC Registers */
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
};
static VGA_REGISTERS VideoMode_80x25_text =
{
/* Miscellaneous Register */
0x67,
/* Sequencer Registers */
{0x00, 0x00, 0x03, 0x00, 0x07},
/* CRTC Registers */
{0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
/* AC Registers */
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
};
static VGA_REGISTERS VideoMode_320x200_4color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
{0x00, 0x09, 0x03, 0x00, 0x02},
/* 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},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x0F, 0xFF},
/* AC Registers */
{0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
static VGA_REGISTERS VideoMode_640x200_2color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
{0x00, 0x09, 0x0F, 0x00, 0x02},
/* CRTC Registers */
{0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xC2,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0xFF},
/* AC Registers */
{0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
0x17, 0x17, 0x17, 0x17, 0x01, 0x00, 0x01, 0x00, 0x00}
};
static VGA_REGISTERS VideoMode_320x200_16color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
{0x00, 0x09, 0x0F, 0x00, 0x02},
/* CRTC Registers */
{0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
/* AC Registers */
// {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
// 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
static VGA_REGISTERS VideoMode_640x200_16color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
{0x00, 0x01, 0x0F, 0x00, 0x02},
/* CRTC Registers */
{0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
/* AC Registers */
// {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
// 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
static VGA_REGISTERS VideoMode_640x350_16color =
{
/* Miscellaneous Register */
0xA3,
/* Sequencer Registers */
{0x00, 0x01, 0x0F, 0x00, 0x02},
/* CRTC Registers */
{0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 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 VGA_REGISTERS VideoMode_640x480_2color =
{
/* Miscellaneous Register */
0xE3,
/* Sequencer Registers */
{0x00, 0x01, 0x0F, 0x00, 0x02},
/* CRTC Registers */
{0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
/* AC Registers */
{0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
0x3F, 0x3F, 0x3F, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
static VGA_REGISTERS VideoMode_640x480_16color =
{
/* Miscellaneous Register */
0xE3,
/* Sequencer Registers */
{0x00, 0x01, 0x0F, 0x00, 0x02},
/* CRTC Registers */
{0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 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 VGA_REGISTERS VideoMode_320x200_256color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
{0x00, 0x01, 0x0F, 0x00, 0x0E},
/* CRTC Registers */
{0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
0xFF},
/* GC Registers */
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF},
/* AC Registers */
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00}
};
/* See http://wiki.osdev.org/Drawing_In_Protected_Mode#Locating_Video_Memory */
static PVGA_REGISTERS VideoModes[BIOS_MAX_VIDEO_MODE + 1] =
{
&VideoMode_40x25_text, /* Mode 00h */ // 16 color (mono)
&VideoMode_40x25_text, /* Mode 01h */ // 16 color
&VideoMode_80x25_text, /* Mode 02h */ // 16 color (mono)
&VideoMode_80x25_text, /* Mode 03h */ // 16 color
&VideoMode_320x200_4color, /* Mode 04h */ // CGA 4 color
&VideoMode_320x200_4color, /* Mode 05h */ // CGA same (m)
&VideoMode_640x200_2color, /* Mode 06h */ // CGA 640*200 2 color
NULL, /* Mode 07h */ // MDA monochrome text 80*25
NULL, /* Mode 08h */ // PCjr
NULL, /* Mode 09h */ // PCjr
NULL, /* Mode 0Ah */ // PCjr
NULL, /* Mode 0Bh */ // Reserved
NULL, /* Mode 0Ch */ // Reserved
&VideoMode_320x200_16color, /* Mode 0Dh */ // EGA 320*200 16 color
&VideoMode_640x200_16color, /* Mode 0Eh */ // EGA 640*200 16 color
NULL, /* Mode 0Fh */ // EGA 640*350 mono
&VideoMode_640x350_16color, /* Mode 10h */ // EGA 640*350 HiRes 16 color
&VideoMode_640x480_2color, /* Mode 11h */ // VGA 640*480 mono
&VideoMode_640x480_16color, /* Mode 12h */ // VGA
&VideoMode_320x200_256color, /* Mode 13h */ // VGA
};
// FIXME: Are they computable with the previous data ??
// Values taken from DOSBox.
static WORD VideoModePageSize[BIOS_MAX_VIDEO_MODE + 1] =
{
0x0800, 0x0800, 0x1000, 0x1000,
0x4000, 0x4000, 0x4000, 0x1000,
0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2000, 0x4000, 0x8000,
0x8000, 0xA000, 0xA000, 0x2000
};
/*
* BIOS Mode Palettes
*
* Many people have different versions of those palettes
* (e.g. DOSBox, http://www.brokenthorn.com/Resources/OSDevVid2.html ,
* etc...) A choice should be made at some point.
*/
// This is the same as EgaPalette__HiRes
static CONST COLORREF TextPalette[VGA_MAX_COLORS / 4] =
{
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, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 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)
};
// Unused at the moment
static CONST COLORREF mtext_palette[64] =
{
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),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
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),
RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
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),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
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),
RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
};
// Unused at the moment
static CONST COLORREF mtext_s3_palette[64] =
{
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),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
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),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
};
// Unused at the moment
static CONST COLORREF CgaPalette[16] =
{
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)
};
// Unused at the moment
static CONST COLORREF CgaPalette2[VGA_MAX_COLORS / 4] =
{
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(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(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(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(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(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)
};
static CONST COLORREF EgaPalette___16ColorFixed_DOSBox[VGA_MAX_COLORS / 4] =
{
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(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(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(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(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(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)
};
// This is the same as TextPalette
static CONST COLORREF EgaPalette__HiRes[VGA_MAX_COLORS / 4] =
{
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, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),
RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),
RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),
RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 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)
};
#define USE_REACTOS_COLORS
// #define USE_DOSBOX_COLORS
/*
* Same palette as the default one 'VgaDefaultPalette' in vga.c
*/
#if defined(USE_REACTOS_COLORS)
// ReactOS colors
static CONST COLORREF VgaPalette[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)
};
#elif defined(USE_DOSBOX_COLORS)
// DOSBox colors
static CONST COLORREF VgaPalette[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(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),
RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),
RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 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(0x30, 0x00, 0x41),
RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
RGB(0x41, 0x41, 0x00), RGB(0x30, 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, 0x30),
RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 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)
};
#endif
/* PRIVATE FUNCTIONS **********************************************************/
static VOID VidBiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
{
INT i, j;
INT Counter = 0;
WORD Character;
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++)
{
/* Read from video memory */
EmulatorReadMemory(&EmulatorContext,
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 VidBiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
{
INT i, j;
INT Counter = 0;
WORD Character;
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++)
{
Character = Buffer[Counter++];
/* Write to video memory */
EmulatorWriteMemory(&EmulatorContext,
VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
(LPVOID)&Character,
sizeof(WORD));
}
}
}
static BOOLEAN VidBiosScrollWindow(INT Direction,
DWORD Amount,
SMALL_RECT Rectangle,
BYTE Page,
BYTE FillAttribute)
{
DWORD i;
LPWORD WindowData;
WORD WindowWidth = Rectangle.Right - Rectangle.Left + 1;
WORD WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
DWORD WindowSize = WindowWidth * WindowHeight;
/* 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 */
VidBiosReadWindow(WindowData, Rectangle, Page);
if ((Amount == 0)
|| (((Direction == SCROLL_DIRECTION_UP)
|| (Direction == SCROLL_DIRECTION_DOWN))
&& (Amount >= WindowHeight))
|| (((Direction == SCROLL_DIRECTION_LEFT)
|| (Direction == SCROLL_DIRECTION_RIGHT))
&& (Amount >= WindowWidth)))
{
/* Fill the window */
for (i = 0; i < WindowSize; i++)
{
WindowData[i] = MAKEWORD(' ', FillAttribute);
}
goto Done;
}
switch (Direction)
{
case SCROLL_DIRECTION_UP:
{
RtlMoveMemory(WindowData,
&WindowData[WindowWidth * Amount],
(WindowSize - WindowWidth * Amount) * sizeof(WORD));
for (i = 0; i < Amount * WindowWidth; i++)
{
WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
}
break;
}
case SCROLL_DIRECTION_DOWN:
{
RtlMoveMemory(&WindowData[WindowWidth * Amount],
WindowData,
(WindowSize - WindowWidth * Amount) * sizeof(WORD));
for (i = 0; i < Amount * WindowWidth; i++)
{
WindowData[i] = MAKEWORD(' ', FillAttribute);
}
break;
}
default:
{
// TODO: NOT IMPLEMENTED!
UNIMPLEMENTED;
}
}
Done:
/* Write back the window data */
VidBiosWriteWindow(WindowData, Rectangle, Page);
/* Free the window buffer */
HeapFree(GetProcessHeap(), 0, WindowData);
return TRUE;
}
static VOID VidBiosCopyTextConsoleToVgaMemory(HANDLE ConsoleOutput, PCOORD ConsoleSize)
{
PCHAR_INFO CharBuffer;
COORD BufferSize = {Bda->ScreenColumns, Bda->ScreenRows + 1};
COORD Origin = { 0, 0 };
SMALL_RECT ConRect;
INT i, j;
INT Counter = 0;
WORD Character;
DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize);
/* Allocate a temporary buffer for ReadConsoleOutput */
CharBuffer = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
BufferSize.X * BufferSize.Y
* sizeof(CHAR_INFO));
if (CharBuffer == NULL) return;
ConRect.Left = 0;
ConRect.Top = ConsoleSize->Y - BufferSize.Y;
ConRect.Right = ConRect.Left + BufferSize.X - 1;
ConRect.Bottom = ConRect.Top + BufferSize.Y - 1;
/* Read the data from the console into the temporary buffer... */
ReadConsoleOutputA(ConsoleOutput,
CharBuffer,
BufferSize,
Origin,
&ConRect);
/* ... and copy the temporary buffer into the VGA memory */
for (i = 0; i < BufferSize.Y; i++)
{
for (j = 0; j < BufferSize.X; j++)
{
Character = MAKEWORD(CharBuffer[Counter].Char.AsciiChar,
(BYTE)CharBuffer[Counter].Attributes);
++Counter;
/* Write to video memory */
EmulatorWriteMemory(&EmulatorContext,
VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
(LPVOID)&Character,
sizeof(WORD));
}
}
/* Free the temporary buffer */
HeapFree(GetProcessHeap(), 0, CharBuffer);
}
static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers)
{
INT i;
if (Registers == NULL) return FALSE;
/* Disable interrupts */
setIF(0);
/*
* Set the CRT base address according to the selected mode,
* monochrome or color. The following macros:
* VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then
* used to access the correct VGA I/O ports.
*/
Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR
: VGA_CRTC_INDEX_MONO;
/* Write the misc register */
IOWriteB(VGA_MISC_WRITE, Registers->Misc);
/* Synchronous reset on */
IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_AR);
/* Write the sequencer registers */
for (i = 1; i < VGA_SEQ_MAX_REG; i++)
{
IOWriteB(VGA_SEQ_INDEX, i);
IOWriteB(VGA_SEQ_DATA, Registers->Sequencer[i]);
}
/* Synchronous reset off */
IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR);
/* Unlock CRTC registers 0-7 */
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) | 0x80);
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
IOWriteB(VGA_CRTC_DATA, IOReadB(VGA_CRTC_DATA) & ~0x80);
// Make sure they remain unlocked
Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
/* Write the CRTC registers */
for (i = 0; i < VGA_CRTC_MAX_REG; i++)
{
IOWriteB(VGA_CRTC_INDEX, i);
IOWriteB(VGA_CRTC_DATA, Registers->CRT[i]);
}
/* Write the GC registers */
for (i = 0; i < VGA_GC_MAX_REG; i++)
{
IOWriteB(VGA_GC_INDEX, i);
IOWriteB(VGA_GC_DATA, Registers->Graphics[i]);
}
/* Write the AC registers */
// DbgPrint("\n");
for (i = 0; i < VGA_AC_MAX_REG; i++)
{
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, i);
IOWriteB(VGA_AC_WRITE, Registers->Attribute[i]);
// DbgPrint("Registers->Attribute[%d] = %d\n", i, Registers->Attribute[i]);
}
// DbgPrint("\n");
/* Set the PEL mask */
IOWriteB(VGA_DAC_MASK, 0xFF);
/* Enable screen and disable palette access */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, 0x20);
/* Enable interrupts */
setIF(1);
return TRUE;
}
static VOID VgaSetPalette(const COLORREF* Palette, ULONG Size)
{
ULONG i;
// /* Disable screen and enable palette access */
// IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
// IOWriteB(VGA_AC_INDEX, 0x00);
for (i = 0; i < Size; i++)
{
IOWriteB(VGA_DAC_WRITE_INDEX, i);
IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetRValue(Palette[i])));
IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetGValue(Palette[i])));
IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetBValue(Palette[i])));
}
/* The following step might be optional */
for (i = Size; i < VGA_MAX_COLORS; i++)
{
IOWriteB(VGA_DAC_WRITE_INDEX, i);
IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
}
/* Enable screen and disable palette access */
// IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
// IOWriteB(VGA_AC_INDEX, 0x20);
}
static VOID VgaChangePalette(BYTE ModeNumber)
{
const COLORREF* Palette;
ULONG Size;
if (ModeNumber >= 0x13)
{
/* VGA modes */
Palette = VgaPalette;
Size = sizeof(VgaPalette)/sizeof(VgaPalette[0]);
}
else if (ModeNumber == 0x10)
{
/* EGA HiRes mode */
Palette = EgaPalette__HiRes;
Size = sizeof(EgaPalette__HiRes)/sizeof(EgaPalette__HiRes[0]);
}
else // if ((ModeNumber == 0x0D) || (ModeNumber == 0x0E))
{
/* EGA modes */
Palette = EgaPalette___16ColorFixed_DOSBox;
Size = sizeof(EgaPalette___16ColorFixed_DOSBox)/sizeof(EgaPalette___16ColorFixed_DOSBox[0]);
}
VgaSetPalette(Palette, Size);
}
static VOID VidBiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
{
/* Make sure the selected video page is valid */
if (Page >= BIOS_MAX_PAGES) return;
/* Get the cursor location */
*Row = HIBYTE(Bda->CursorPosition[Page]);
*Column = LOBYTE(Bda->CursorPosition[Page]);
}
static VOID VidBiosSetCursorPosition(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] = MAKEWORD(Column, Row);
/* Check if this is the current video page */
if (Page == Bda->VideoPage)
{
WORD Offset = Row * Bda->ScreenColumns + Column;
/* Modify the CRTC registers */
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
IOWriteB(VGA_CRTC_DATA , LOBYTE(Offset));
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
IOWriteB(VGA_CRTC_DATA , HIBYTE(Offset));
}
}
BYTE VidBiosGetVideoMode(VOID)
{
return Bda->VideoMode;
}
static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber)
{
BYTE Page;
COORD Resolution;
PVGA_REGISTERS VgaMode = VideoModes[ModeNumber];
DPRINT1("Switching to mode %Xh; VgaMode = 0x%p\n", ModeNumber, VgaMode);
if (!VgaSetRegisters(VgaMode)) return FALSE;
VgaChangePalette(ModeNumber);
/*
* IBM standard modes do not clear the screen if the
* high bit of AL is set (EGA or higher only).
* See Ralf Brown: http://www.ctyme.com/intr/rb-0069.htm
* for more information.
*/
if ((ModeNumber & 0x08) == 0) VgaClearMemory();
// Bda->CrtModeControl;
// Bda->CrtColorPaletteMask;
// Bda->EGAFlags;
// Bda->VGAFlags;
/* Update the values in the BDA */
Bda->VideoMode = ModeNumber;
Bda->VideoPageSize = VideoModePageSize[ModeNumber];
Bda->VideoPage = 0;
Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
/* Set the start address in the CRTC */
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
/* Get the character height */
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_MAX_SCAN_LINE_REG);
Bda->CharacterHeight = 1 + (IOReadB(VGA_CRTC_DATA) & 0x1F);
Resolution = VgaGetDisplayResolution();
Bda->ScreenColumns = Resolution.X;
Bda->ScreenRows = Resolution.Y - 1;
/* Set the cursor position for each page */
for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
VidBiosSetCursorPosition(0, 0, Page);
return TRUE;
}
static BOOLEAN VidBiosSetVideoPage(BYTE PageNumber)
{
BYTE Row, Column;
/* Check if the page exists */
if (PageNumber >= BIOS_MAX_PAGES) return FALSE;
/* Check if this is the same page */
if (PageNumber == Bda->VideoPage) return TRUE;
/* Update the values in the BDA */
Bda->VideoPage = PageNumber;
Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
/* Set the start address in the CRTC */
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
/*
* Get the cursor location (we don't update anything on the BIOS side
* but we update the cursor location on the VGA side).
*/
VidBiosGetCursorPosition(&Row, &Column, PageNumber);
VidBiosSetCursorPosition(Row, Column, PageNumber);
return TRUE;
}
VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
{
WORD CharData = MAKEWORD(Character, Attribute);
BYTE Row, Column;
/* Make sure the page exists */
if (Page >= BIOS_MAX_PAGES) return;
/* Get the cursor location */
VidBiosGetCursorPosition(&Row, &Column, Page);
if (Character == '\a')
{
/* Bell control character */
// NOTE: We may use what the terminal emulator offers to us...
Beep(800, 200);
return;
}
else if (Character == '\b')
{
/* Backspace control character */
if (Column > 0)
{
Column--;
}
else if (Row > 0)
{
Column = Bda->ScreenColumns - 1;
Row--;
}
/* Erase the existing character */
CharData = MAKEWORD(' ', Attribute);
EmulatorWriteMemory(&EmulatorContext,
TO_LINEAR(TEXT_VIDEO_SEG,
Page * Bda->VideoPageSize +
(Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
(LPVOID)&CharData,
sizeof(WORD));
}
else if (Character == '\t')
{
/* Horizontal Tabulation control character */
do
{
// Taken from DOSBox
VidBiosPrintCharacter(' ', Attribute, Page);
VidBiosGetCursorPosition(&Row, &Column, Page);
} while (Column % 8);
}
else if (Character == '\n')
{
/* Line Feed control character */
Row++;
}
else if (Character == '\r')
{
/* Carriage Return control character */
Column = 0;
}
else
{
/* Default character */
/* Write the character */
EmulatorWriteMemory(&EmulatorContext,
TO_LINEAR(TEXT_VIDEO_SEG,
Page * Bda->VideoPageSize +
(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 and go to the next line */
Column = 0;
Row++;
}
/* Scroll the screen up if needed */
if (Row > Bda->ScreenRows)
{
/* The screen must be scrolled up */
SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
VidBiosScrollWindow(SCROLL_DIRECTION_UP,
1,
Rectangle,
Page,
DEFAULT_ATTRIBUTE);
Row--;
}
/* Set the cursor position */
VidBiosSetCursorPosition(Row, Column, Page);
}
static VOID WINAPI VidBiosVideoService(LPWORD Stack)
{
switch (getAH())
{
/* Set Video Mode */
case 0x00:
{
VidBiosSetVideoMode(getAL());
break;
}
/* Set Text-Mode Cursor Shape */
case 0x01:
{
/* Update the BDA */
Bda->CursorStartLine = getCH();
Bda->CursorEndLine = getCL();
/* Modify the CRTC registers */
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
IOWriteB(VGA_CRTC_DATA , Bda->CursorStartLine);
IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
IOWriteB(VGA_CRTC_DATA , Bda->CursorEndLine);
break;
}
/* Set Cursor Position */
case 0x02:
{
VidBiosSetCursorPosition(getDH(), getDL(), getBH());
break;
}
/* Get Cursor Position */
case 0x03:
{
/* Make sure the selected video page exists */
if (getBH() >= BIOS_MAX_PAGES) break;
/* Return the result */
setAX(0);
setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine));
setDX(Bda->CursorPosition[getBH()]);
break;
}
/* Query Light Pen */
case 0x04:
{
/*
* On modern BIOSes, this function returns 0
* so that we can ignore the other registers.
*/
setAX(0);
break;
}
/* Select Active Display Page */
case 0x05:
{
VidBiosSetVideoPage(getAL());
break;
}
/* Scroll Window Up/Down */
case 0x06:
case 0x07:
{
SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
/* Call the internal function */
VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_DIRECTION_UP
: SCROLL_DIRECTION_DOWN,
getAL(),
Rectangle,
Bda->VideoPage,
getBH());
break;
}
/* Read/Write Character From Cursor Position */
case 0x08:
case 0x09:
case 0x0A:
{
WORD CharacterData = MAKEWORD(getAL(), getBL());
BYTE Page = getBH();
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 (getAH() == 0x08)
{
/* Read from the video memory */
EmulatorReadMemory(&EmulatorContext,
TO_LINEAR(TEXT_VIDEO_SEG, Offset),
(LPVOID)&CharacterData,
sizeof(WORD));
/* Return the character in AX */
setAX(CharacterData);
}
else
{
/* Write to video memory */
EmulatorWriteMemory(&EmulatorContext,
TO_LINEAR(TEXT_VIDEO_SEG, Offset),
(LPVOID)&CharacterData,
(getBH() == 0x09) ? sizeof(WORD) : sizeof(BYTE));
}
break;
}
/* Teletype Output */
case 0x0E:
{
VidBiosPrintCharacter(getAL(), getBL(), getBH());
break;
}
/* Get Current Video Mode */
case 0x0F:
{
setAX(MAKEWORD(Bda->VideoMode, Bda->ScreenColumns));
setBX(MAKEWORD(getBL(), Bda->VideoPage));
break;
}
/* Palette Control */
case 0x10:
{
switch (getAL())
{
/* Set Single Palette Register */
case 0x00:
{
/* Write the index */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, getBL());
/* Write the data */
IOWriteB(VGA_AC_WRITE, getBH());
/* Enable screen and disable palette access */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, 0x20);
break;
}
/* Set Overscan Color */
case 0x01:
{
/* Write the index */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
/* Write the data */
IOWriteB(VGA_AC_WRITE, getBH());
/* Enable screen and disable palette access */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, 0x20);
break;
}
/* Set All Palette Registers */
case 0x02:
{
INT i;
LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
/* Set the palette registers */
for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
{
/* Write the index */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, i);
/* Write the data */
IOWriteB(VGA_AC_WRITE, Buffer[i]);
}
/* Set the overscan register */
IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
IOWriteB(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
/* Enable screen and disable palette access */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, 0x20);
break;
}
/* Get Single Palette Register */
case 0x07:
{
/* Write the index */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, getBL());
/* Read the data */
setBH(IOReadB(VGA_AC_READ));
/* Enable screen and disable palette access */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, 0x20);
break;
}
/* Get Overscan Color */
case 0x08:
{
/* Write the index */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
/* Read the data */
setBH(IOReadB(VGA_AC_READ));
/* Enable screen and disable palette access */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, 0x20);
break;
}
/* Get All Palette Registers */
case 0x09:
{
INT i;
LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
/* Get the palette registers */
for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
{
/* Write the index */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, i);
/* Read the data */
Buffer[i] = IOReadB(VGA_AC_READ);
}
/* Get the overscan register */
IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
Buffer[VGA_AC_PAL_F_REG + 1] = IOReadB(VGA_AC_READ);
/* Enable screen and disable palette access */
IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
IOWriteB(VGA_AC_INDEX, 0x20);
break;
}
/* Set Individual DAC Register */
case 0x10:
{
/* Write the index */
// Certainly in BL and not in BX as said by Ralf Brown...
IOWriteB(VGA_DAC_WRITE_INDEX, getBL());
/* Write the data in this order: Red, Green, Blue */
IOWriteB(VGA_DAC_DATA, getDH());
IOWriteB(VGA_DAC_DATA, getCH());
IOWriteB(VGA_DAC_DATA, getCL());
break;
}
/* Set Block of DAC Registers */
case 0x12:
{
INT i;
LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
/* Write the index */
// Certainly in BL and not in BX as said by Ralf Brown...
IOWriteB(VGA_DAC_WRITE_INDEX, getBL());
for (i = 0; i < getCX(); i++)
{
/* Write the data in this order: Red, Green, Blue */
IOWriteB(VGA_DAC_DATA, *Buffer++);
IOWriteB(VGA_DAC_DATA, *Buffer++);
IOWriteB(VGA_DAC_DATA, *Buffer++);
}
break;
}
/* Get Individual DAC Register */
case 0x15:
{
/* Write the index */
IOWriteB(VGA_DAC_READ_INDEX, getBL());
/* Read the data in this order: Red, Green, Blue */
setDH(IOReadB(VGA_DAC_DATA));
setCH(IOReadB(VGA_DAC_DATA));
setCL(IOReadB(VGA_DAC_DATA));
break;
}
/* Get Block of DAC Registers */
case 0x17:
{
INT i;
LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
/* Write the index */
// Certainly in BL and not in BX as said by Ralf Brown...
IOWriteB(VGA_DAC_READ_INDEX, getBL());
for (i = 0; i < getCX(); i++)
{
/* Write the data in this order: Red, Green, Blue */
*Buffer++ = IOReadB(VGA_DAC_DATA);
*Buffer++ = IOReadB(VGA_DAC_DATA);
*Buffer++ = IOReadB(VGA_DAC_DATA);
}
break;
}
default:
{
DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n",
getAL());
break;
}
}
break;
}
/* Scroll Window */
case 0x12:
{
SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };
/* Call the internal function */
VidBiosScrollWindow(getBL(),
getAL(),
Rectangle,
Bda->VideoPage,
DEFAULT_ATTRIBUTE);
break;
}
/* Display combination code */
case 0x1A:
{
switch(getAL())
{
case 0x00: /* Get Display combiantion code */
setAX(MAKEWORD(0x1A, 0x1A));
setBX(MAKEWORD(0x08, 0x00)); /* VGA w/ color analog display */
break;
case 0x01: /* Set Display combination code */
DPRINT1("Set Display combination code - Unsupported\n");
break;
default:
break;
}
break;
}
default:
{
DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n",
getAH());
}
}
}
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN VidBiosInitialize(HANDLE ConsoleOutput)
{
/* Some interrupts are in fact addresses to tables */
((PDWORD)BaseAddress)[0x1D] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x1F] = (DWORD)NULL;
// ((PDWORD)BaseAddress)[0x42] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x43] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x44] = (DWORD)NULL;
/* Set the default video mode */
VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
/* Set some screen properties if the console output handle is valid */
if (ConsoleOutput != INVALID_HANDLE_VALUE)
{
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
GetConsoleScreenBufferInfo(ConsoleOutput, &ConsoleInfo);
/* Copy console data into VGA memory */
VidBiosCopyTextConsoleToVgaMemory(ConsoleOutput, &ConsoleInfo.dwSize);
/* Update the cursor position for the current page */
VidBiosSetCursorPosition(ConsoleInfo.dwCursorPosition.Y,
ConsoleInfo.dwCursorPosition.X,
Bda->VideoPage);
}
/* Register the BIOS 32-bit Interrupts */
RegisterInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
return TRUE;
}
VOID VidBiosCleanup(VOID)
{
}
/* EOF */