Author: hbelusca Date: Sun Jul 5 18:35:25 2015 New Revision: 68347
URL: http://svn.reactos.org/svn/reactos?rev=68347&view=rev Log: [NTVDM] - Implement INT 10h, AH=13h "Write String" function. - Fix VidBiosPrintCharacter to use the colour attribute only in graphics mode, or when explicitely needed. - Fix some special cases where specifying a BIOS mode page of 0xFF means "use current page". - Use a macro to check whether a given mode number specifies a text mode, and use it where needed.
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c
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] Sun Jul 5 18:35:25 2015 @@ -1949,6 +1949,8 @@ {&VideoMode_320x200_256color, 0x2000, 8}, /* Mode 13h - VGA */ };
+#define IS_TEXT_MODE(ModeNumber) \ + (((ModeNumber) >= 0x00 && (ModeNumber) <= 0x03) || ((ModeNumber) == 0x07))
static PVGA_STATIC_FUNC_TABLE VgaStaticFuncTable;
@@ -2282,21 +2284,14 @@ 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 */ +static __inline VOID VidBiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page) +{ *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);
@@ -2316,7 +2311,7 @@ static VOID VidBiosSetCursorShape(WORD CursorStartEnd) { /* Only valid in text-mode */ - if ((Bda->VideoMode > 0x03) && (Bda->VideoMode != 0x07)) return; + if (!IS_TEXT_MODE(Bda->VideoMode)) return;
/* Update the BDA */ Bda->CursorStartLine = HIBYTE(CursorStartEnd) & 0x1F; @@ -2367,7 +2362,7 @@ SHORT ScreenColumns = VgaGetDisplayResolution().X; WORD Offset;
- /* Get the cursor location */ + /* Get the cursor position */ IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG); Low = IOReadB(VGA_CRTC_DATA); IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG); @@ -2406,6 +2401,7 @@ VideoAddress = MemoryMaps[(Misc >> 2) & 3]; BufferSize = MemorySizes[(Misc >> 2) & 3];
+ // !IS_TEXT_MODE(Bda->VideoMode) if (Misc & 1) { /* Graphics mode */ @@ -2484,7 +2480,7 @@ Bda->ScreenRows = Resolution.Y - 1;
/* Adjust the number of columns for graphics modes */ - if (ModeNumber > 3) Bda->ScreenColumns >>= 3; + if (!IS_TEXT_MODE(ModeNumber)) Bda->ScreenColumns >>= 3;
/* Update the current font */ Bda->CharacterHeight = VideoModes[ModeNumber].CharacterHeight; @@ -2496,7 +2492,7 @@ */ case 8: { - if (ModeNumber <= 3) + if (IS_TEXT_MODE(ModeNumber)) VgaWriteTextModeFont(0, Font8x8, ARRAYSIZE(Font8x8) / VGA_FONT_CHARACTERS);
((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x8_OFFSET, VIDEO_BIOS_DATA_SEG); @@ -2504,7 +2500,7 @@ } case 14: { - if (ModeNumber <= 3) + if (IS_TEXT_MODE(ModeNumber)) VgaWriteTextModeFont(0, Font8x14, ARRAYSIZE(Font8x14) / VGA_FONT_CHARACTERS);
((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x14_OFFSET, VIDEO_BIOS_DATA_SEG); @@ -2512,7 +2508,7 @@ } case 16: { - if (ModeNumber <= 3) + if (IS_TEXT_MODE(ModeNumber)) VgaWriteTextModeFont(0, Font8x16, ARRAYSIZE(Font8x16) / VGA_FONT_CHARACTERS);
((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x16_OFFSET, VIDEO_BIOS_DATA_SEG); @@ -2538,7 +2534,7 @@ * Use the default CGA cursor scanline values, * see: http://vitaly_filatov.tripod.com/ng/asm/asm_023.2.html */ - if ((ModeNumber >= 0x00 && ModeNumber <= 0x03) || (ModeNumber == 0x07)) + if (IS_TEXT_MODE(ModeNumber)) // FIXME: we might read the CRT registers and do the adjustment? VidBiosSetCursorShape(MAKEWORD(0x07, 0x06));
@@ -2575,8 +2571,8 @@ 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). + * Get the cursor position (we don't update anything on the BIOS side + * but we update the cursor position on the VGA side). */ VidBiosGetCursorPosition(&Row, &Column, PageNumber); VidBiosSetCursorPosition(Row, Column, PageNumber); @@ -2593,6 +2589,7 @@ case 0x01: case 0x02: case 0x03: + case 0x07: { EmulatorWriteMemory(&EmulatorContext, TO_LINEAR(TEXT_VIDEO_SEG, @@ -2827,15 +2824,12 @@ } }
-static VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page) - { +static VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BOOLEAN UseAttr, 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 */ + /* Get the cursor position */ VidBiosGetCursorPosition(&Row, &Column, Page);
if (Character == '\a') @@ -2860,7 +2854,7 @@
/* Erase the existing character */ CharData = MAKEWORD(' ', Attribute); - VidBiosDrawGlyph(CharData, TRUE, Page, Row, Column); + VidBiosDrawGlyph(CharData, UseAttr, Page, Row, Column); } else if (Character == '\t') { @@ -2868,7 +2862,7 @@ do { // Taken from DOSBox - VidBiosPrintCharacter(' ', Attribute, Page); + VidBiosPrintCharacter(' ', Attribute, UseAttr, Page); VidBiosGetCursorPosition(&Row, &Column, Page); } while (Column % 8); } @@ -2887,7 +2881,7 @@ /* Default character */
/* Write the character and advance the cursor */ - VidBiosDrawGlyph(CharData, TRUE, Page, Row, Column); + VidBiosDrawGlyph(CharData, UseAttr, Page, Row, Column); Column++; }
@@ -2935,19 +2929,29 @@ /* Set Cursor Position */ case 0x02: { - VidBiosSetCursorPosition(getDH(), getDL(), getBH()); + BYTE Page = getBH(); + + /* Validate the selected video page */ + if (Page >= BIOS_MAX_PAGES) break; + + VidBiosSetCursorPosition(getDH(), getDL(), Page); break; }
/* Get Cursor Position and Shape */ case 0x03: { - /* Make sure the selected video page exists */ - if (getBH() >= BIOS_MAX_PAGES) break; + BYTE Page = getBH(); + + /* Validate the selected video page */ + if (Page == 0xFF) // Special case: use the current video page + Page = Bda->VideoPage; + else if (Page >= BIOS_MAX_PAGES) + break;
/* Return the result */ setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine)); - setDX(Bda->CursorPosition[getBH()]); + setDX(Bda->CursorPosition[Page]); break; }
@@ -2988,8 +2992,11 @@ BYTE Page = getBH(); DWORD Offset;
- /* Check if the page exists */ - if (Page >= BIOS_MAX_PAGES) break; + /* Validate the selected video page */ + if (Page == 0xFF) // Special case: use the current video page + Page = Bda->VideoPage; + else if (Page >= BIOS_MAX_PAGES) + break;
/* Find the offset of the character */ Offset = Page * Bda->VideoPageSize + @@ -3019,13 +3026,14 @@ BYTE Page = getBH(); BYTE Row, Column;
- /* Check if the page exists */ - if (Page >= BIOS_MAX_PAGES) break; - - /* Get the cursor location */ - // VidBiosGetCursorPosition(&Row, &Column, Page); - Row = HIBYTE(Bda->CursorPosition[Page]); - Column = LOBYTE(Bda->CursorPosition[Page]); + /* Validate the selected video page */ + if (Page == 0xFF) // Special case: use the current video page + Page = Bda->VideoPage; + else if (Page >= BIOS_MAX_PAGES) + break; + + /* Get the cursor position */ + VidBiosGetCursorPosition(&Row, &Column, Page);
/* Write to video memory a certain number of times */ while (Counter-- > 0) @@ -3137,7 +3145,15 @@ /* Teletype Output */ case 0x0E: { - VidBiosPrintCharacter(getAL(), getBL(), getBH()); + BYTE Page = getBH(); + + /* Validate the selected video page */ + if (Page == 0xFF) // Special case: use the current video page + Page = Bda->VideoPage; + else if (Page >= BIOS_MAX_PAGES) + break; + + VidBiosPrintCharacter(getAL(), getBL(), !IS_TEXT_MODE(Bda->VideoMode), Page); break; }
@@ -3686,7 +3702,44 @@ /* Write String */ case 0x13: { - DPRINT1("BIOS Function INT 13h (Write String) is UNIMPLEMENTED\n"); + PCHAR String = (PCHAR)SEG_OFF_TO_PTR(getES(), getBP()); + WORD Counter = getCX(); + BYTE Row, Column; + BYTE OldRow, OldColumn; + CHAR Character; + BYTE Attribute = getBL(); // Default attribute in case the string contains only characters. + BYTE Page = getBH(); + BYTE Flags = getAL(); + + /* Validate the selected video page */ + if (Page == 0xFF) // Special case: use the current video page + Page = Bda->VideoPage; + else if (Page >= BIOS_MAX_PAGES) + break; + + /* Get the original cursor position */ + VidBiosGetCursorPosition(&OldRow, &OldColumn, Page); + + /* Set the new cursor position */ + Row = getDH(); + Column = getDL(); + if (Row == 0xFF) // Special case: use the current cursor position + { + Row = OldRow; + Column = OldColumn; + } + VidBiosSetCursorPosition(Row, Column, Page); + + while (Counter-- > 0) + { + Character = *String++; + if (Flags & 0x02) Attribute = *String++; + VidBiosPrintCharacter(Character, Attribute, TRUE, Page); + } + + /* Reset the cursor position to its original value if we don't want to update it */ + if (!(Flags & 0x01)) VidBiosSetCursorPosition(OldRow, OldColumn, Page); + break; }