Author: aandrejevic
Date: Tue Jun 9 04:03:27 2015
New Revision: 68086
URL:
http://svn.reactos.org/svn/reactos?rev=68086&view=rev
Log:
[NTVDM]
Implement drawing characters for all supported video modes.
Modified:
trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c
trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c [iso-8859-1] Tue Jun 9 04:03:27
2015
@@ -2561,8 +2561,245 @@
return TRUE;
}
+static VOID VidBiosDrawGlyph(WORD CharData, BYTE Page, BYTE Row, BYTE Column)
+{
+ switch (Bda->VideoMode)
+ {
+ /* Alphanumeric mode */
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(TEXT_VIDEO_SEG,
+ Page * Bda->VideoPageSize +
+ (Row * Bda->ScreenColumns + Column) *
sizeof(WORD)),
+ (LPVOID)&CharData,
+ sizeof(WORD));
+
+ break;
+ }
+
+ /* 4-color CGA */
+ case 0x04:
+ case 0x05:
+ {
+ WORD i;
+ WORD CgaSegment[] = { CGA_EVEN_VIDEO_SEG, CGA_ODD_VIDEO_SEG };
+ PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]);
+ PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight];
+ BOOLEAN Xor = (HIBYTE(CharData) & 0x80) ? TRUE : FALSE;
+ BYTE OldRotate;
+ BYTE DoubledBits[] =
+ {
+ 0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
+ 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF
+ };
+
+ if (Xor)
+ {
+ /* Set the logical operation to XOR */
+ IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
+ OldRotate = IOReadB(VGA_GC_DATA);
+ IOWriteB(VGA_GC_DATA, OldRotate | 0x18);
+ }
+
+ for (i = 0; i < Bda->CharacterHeight; i++)
+ {
+ WORD Pixel = MAKEWORD(DoubledBits[Glyph[i] >> 4],
+ DoubledBits[Glyph[i] & 0x0F]);
+ if (Xor)
+ {
+ USHORT Dummy;
+
+ /* Read from VGA memory to load the latch register */
+ EmulatorReadMemory(&EmulatorContext,
+ TO_LINEAR(CgaSegment[(Row + i) & 1],
+ ((((Row + i) >> 1) *
Bda->ScreenColumns) >> 2) + Column * 2),
+ (LPVOID)&Dummy,
+ sizeof(USHORT));
+ }
+
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(CgaSegment[(Row + i) & 1],
+ ((((Row + i) >> 1) *
Bda->ScreenColumns) >> 2) + Column * 2),
+ (LPVOID)&Pixel,
+ sizeof(USHORT));
+ }
+
+ if (Xor)
+ {
+ IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
+ IOWriteB(VGA_GC_DATA, OldRotate);
+ }
+
+ break;
+ }
+
+ /* 2-color CGA */
+ case 0x06:
+ {
+ WORD i;
+ WORD CgaSegment[] = { CGA_EVEN_VIDEO_SEG, CGA_ODD_VIDEO_SEG };
+ PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]);
+ PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight];
+ BOOLEAN Xor = (HIBYTE(CharData) & 0x80) ? TRUE : FALSE;
+ BYTE OldRotate;
+
+ if (Xor)
+ {
+ /* Set the logical operation to XOR */
+ IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
+ OldRotate = IOReadB(VGA_GC_DATA);
+ IOWriteB(VGA_GC_DATA, OldRotate | 0x18);
+ }
+
+ for (i = 0; i < Bda->CharacterHeight; i++)
+ {
+ if (Xor)
+ {
+ UCHAR Dummy;
+
+ /* Read from VGA memory to load the latch register */
+ EmulatorReadMemory(&EmulatorContext,
+ TO_LINEAR(CgaSegment[(Row + i) & 1],
+ ((((Row + i) >> 1) *
Bda->ScreenColumns) >> 3) + Column),
+ (LPVOID)&Dummy,
+ sizeof(UCHAR));
+ }
+
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(CgaSegment[(Row + i) & 1],
+ ((((Row + i) >> 1) *
Bda->ScreenColumns) >> 3) + Column),
+ (LPVOID)&Glyph[i],
+ sizeof(UCHAR));
+ }
+
+ if (Xor)
+ {
+ IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
+ IOWriteB(VGA_GC_DATA, OldRotate);
+ }
+
+ break;
+ }
+
+ /* 16-color modes */
+ case 0x0D:
+ case 0x0E:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ {
+ WORD i;
+ PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]);
+ PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight];
+ BOOLEAN Xor = (HIBYTE(CharData) & 0x80) ? TRUE : FALSE;
+ BYTE OldPlaneWrite, OldReset, OldEnableReset, OldRotate, OldMode;
+
+ /* Write to all planes */
+ IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG);
+ OldPlaneWrite = IOReadB(VGA_SEQ_DATA);
+ IOWriteB(VGA_SEQ_DATA, 0x0F);
+
+ /* Zero the planes whose bits are set in the enable set/reset register */
+ IOWriteB(VGA_GC_INDEX, VGA_GC_RESET_REG);
+ OldReset = IOReadB(VGA_GC_DATA);
+ IOWriteB(VGA_GC_DATA, 0x00);
+
+ /* Set the enable set/reset register to the inverse of the color */
+ IOWriteB(VGA_GC_INDEX, VGA_GC_ENABLE_RESET_REG);
+ OldEnableReset = IOReadB(VGA_GC_DATA);
+ IOWriteB(VGA_GC_DATA, (~HIBYTE(CharData)) & 0x0F);
+
+ /* Make sure we're in write mode 0 */
+ IOWriteB(VGA_GC_INDEX, VGA_GC_MODE_REG);
+ OldMode = IOReadB(VGA_GC_DATA);
+ IOWriteB(VGA_GC_DATA, 0x00);
+
+ if (Xor)
+ {
+ /* Set the logical operation to XOR */
+ IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
+ OldRotate = IOReadB(VGA_GC_DATA);
+ IOWriteB(VGA_GC_DATA, OldRotate | 0x18);
+ }
+
+ for (i = 0; i < Bda->CharacterHeight; i++)
+ {
+ if (Xor)
+ {
+ UCHAR Dummy;
+
+ /* Read from VGA memory to load the latch register */
+ EmulatorReadMemory(&EmulatorContext,
+ TO_LINEAR(GRAPHICS_VIDEO_SEG,
+ (((Row + i) * Bda->ScreenColumns)
>> 3) + Column),
+ (LPVOID)&Dummy,
+ sizeof(UCHAR));
+ }
+
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(GRAPHICS_VIDEO_SEG,
+ (((Row + i) * Bda->ScreenColumns)
>> 3) + Column),
+ (LPVOID)&Glyph[i],
+ sizeof(UCHAR));
+ }
+
+ /* Restore the registers */
+ IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG);
+ IOWriteB(VGA_SEQ_DATA, OldPlaneWrite);
+ IOWriteB(VGA_GC_INDEX, VGA_GC_RESET_REG);
+ IOWriteB(VGA_GC_DATA, OldReset);
+ IOWriteB(VGA_GC_INDEX, VGA_GC_ENABLE_RESET_REG);
+ IOWriteB(VGA_GC_DATA, OldEnableReset);
+ IOWriteB(VGA_GC_INDEX, VGA_GC_MODE_REG);
+ IOWriteB(VGA_GC_DATA, OldMode);
+
+ if (Xor)
+ {
+ IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
+ IOWriteB(VGA_GC_DATA, OldRotate);
+ }
+
+ break;
+ }
+
+ /* 256-color mode */
+ case 0x13:
+ {
+ WORD i, j;
+ PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]);
+ PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight];
+ BYTE PixelBuffer[8];
+
+ for (i = 0; i < Bda->CharacterHeight; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ PixelBuffer[j] = (Glyph[i] & (1 << (7 - j))) ?
HIBYTE(CharData) : 0;
+ }
+
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(GRAPHICS_VIDEO_SEG,
+ (Row + i) * Bda->ScreenColumns + Column
* 8),
+ (LPVOID)PixelBuffer,
+ sizeof(PixelBuffer));
+ }
+
+ break;
+ }
+
+ default:
+ {
+ DPRINT1("Drawing glyphs in mode %02Xh is not supported.\n",
Bda->VideoMode);
+ }
+ }
+}
+
static VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
-{
+ {
WORD CharData = MAKEWORD(Character, Attribute);
BYTE Row, Column;
@@ -2594,12 +2831,7 @@
/* 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));
+ VidBiosDrawGlyph(CharData, Page, Row, Column);
}
else if (Character == '\t')
{
@@ -2626,12 +2858,7 @@
/* 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));
+ VidBiosDrawGlyph(CharData, Page, Row, Column);
/* Advance the cursor */
Column++;
@@ -2761,24 +2988,18 @@
{
WORD CharacterData = MAKEWORD(getAL(), getBL());
BYTE Page = getBH();
- DWORD Offset, Counter = getCX();
+ DWORD Counter = getCX();
/* 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;
/* Write to video memory a certain number of times */
while (Counter > 0)
{
- EmulatorWriteMemory(&EmulatorContext,
- TO_LINEAR(TEXT_VIDEO_SEG, Offset),
- (LPVOID)&CharacterData,
- (getAH() == 0x09) ? sizeof(WORD) : sizeof(BYTE));
- Offset += 2;
+ VidBiosDrawGlyph(CharacterData,
+ CharacterData,
+ HIBYTE(Bda->CursorPosition[Page]),
+ LOBYTE(Bda->CursorPosition[Page]));
Counter--;
}
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/bios…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h [iso-8859-1] Tue Jun 9 04:03:27
2015
@@ -22,6 +22,8 @@
#define GRAPHICS_VIDEO_SEG 0xA000
#define TEXT_VIDEO_SEG 0xB800
+#define CGA_EVEN_VIDEO_SEG 0xB800
+#define CGA_ODD_VIDEO_SEG 0xBA00
#define VIDEO_BIOS_DATA_SEG 0xC000
#define FONT_8x8_OFFSET 0x0000