Author: hbelusca Date: Wed Aug 26 01:26:33 2015 New Revision: 68827
URL: http://svn.reactos.org/svn/reactos?rev=68827&view=rev Log: [NTVDM] - Towards a complete fix of VGA console attach/detach: a lot of progress is made but few little things need to be checked/adjusted. - Fix text scroll (at least in text modes) by doing guest-to-guest moves, using the EmulatorCopyMemory function introduced in r68826. - Fix the computation of the screen rows/columns values stored in the BDA, in graphics modes (in addition to the change of r68090), by dividing the graphics resolution by the character heights & widths. Correct values are indeed needed by some programs, eg. QBasic (I also add a CharacterWidth; normally it should be computable using the CRTC registers, and is always == 8 or 9, but still...).
Modified: trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.c trunk/reactos/subsystems/mvdm/ntvdm/bios/vidbios.h trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.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] Wed Aug 26 01:26:33 2015 @@ -1937,32 +1937,33 @@ { PVGA_REGISTERS VgaRegisters; WORD PageSize; + WORD CharacterWidth; WORD CharacterHeight; // PCOLORREF Palette; } VGA_MODE, *PVGA_MODE;
static CONST VGA_MODE VideoModes[BIOS_MAX_VIDEO_MODE + 1] = { - {&VideoMode_40x25_text, 0x0800, 16}, /* Mode 00h - 16 color (mono) */ - {&VideoMode_40x25_text, 0x0800, 16}, /* Mode 01h - 16 color */ - {&VideoMode_80x25_text, 0x1000, 16}, /* Mode 02h - 16 color (mono) */ - {&VideoMode_80x25_text, 0x1000, 16}, /* Mode 03h - 16 color */ - {&VideoMode_320x200_4color, 0x4000, 8}, /* Mode 04h - CGA 4 color */ - {&VideoMode_320x200_4color, 0x4000, 8}, /* Mode 05h - CGA same (m) (uses 3rd CGA palette) */ - {&VideoMode_640x200_2color, 0x4000, 8}, /* Mode 06h - CGA 640*200 2 color */ - {NULL, 0x1000, 0}, /* Mode 07h - MDA monochrome text 80*25 */ - {NULL, 0x0000, 0}, /* Mode 08h - PCjr */ - {NULL, 0x0000, 0}, /* Mode 09h - PCjr */ - {NULL, 0x0000, 0}, /* Mode 0Ah - PCjr */ - {NULL, 0x0000, 0}, /* Mode 0Bh - Reserved */ - {NULL, 0x0000, 0}, /* Mode 0Ch - Reserved */ - {&VideoMode_320x200_16color, 0x2000, 8}, /* Mode 0Dh - EGA 320*200 16 color */ - {&VideoMode_640x200_16color, 0x4000, 8}, /* Mode 0Eh - EGA 640*200 16 color */ - {NULL, 0x8000, 0}, /* Mode 0Fh - EGA 640*350 mono */ - {&VideoMode_640x350_16color, 0x8000, 14}, /* Mode 10h - EGA 640*350 HiRes 16 color */ - {&VideoMode_640x480_2color, 0xA000, 16}, /* Mode 11h - VGA 640*480 mono */ - {&VideoMode_640x480_16color, 0xA000, 16}, /* Mode 12h - VGA */ - {&VideoMode_320x200_256color, 0x2000, 8}, /* Mode 13h - VGA */ + {&VideoMode_40x25_text, 0x0800, 9, 16}, /* Mode 00h - 16 color (mono) */ + {&VideoMode_40x25_text, 0x0800, 9, 16}, /* Mode 01h - 16 color */ + {&VideoMode_80x25_text, 0x1000, 9, 16}, /* Mode 02h - 16 color (mono) */ + {&VideoMode_80x25_text, 0x1000, 9, 16}, /* Mode 03h - 16 color */ + {&VideoMode_320x200_4color, 0x4000, 8, 8}, /* Mode 04h - CGA 4 color */ + {&VideoMode_320x200_4color, 0x4000, 8, 8}, /* Mode 05h - CGA same (m) (uses 3rd CGA palette) */ + {&VideoMode_640x200_2color, 0x4000, 8, 8}, /* Mode 06h - CGA 640*200 2 color */ + {NULL, 0x1000, 1, 1}, /* Mode 07h - MDA monochrome text 80*25 */ + {NULL, 0x0000, 1, 1}, /* Mode 08h - PCjr */ + {NULL, 0x0000, 1, 1}, /* Mode 09h - PCjr */ + {NULL, 0x0000, 1, 1}, /* Mode 0Ah - PCjr */ + {NULL, 0x0000, 1, 1}, /* Mode 0Bh - Reserved */ + {NULL, 0x0000, 1, 1}, /* Mode 0Ch - Reserved */ + {&VideoMode_320x200_16color, 0x2000, 8, 8}, /* Mode 0Dh - EGA 320*200 16 color */ + {&VideoMode_640x200_16color, 0x4000, 8, 8}, /* Mode 0Eh - EGA 640*200 16 color */ + {NULL, 0x8000, 1, 1}, /* Mode 0Fh - EGA 640*350 mono */ + {&VideoMode_640x350_16color, 0x8000, 8, 14}, /* Mode 10h - EGA 640*350 HiRes 16 color */ + {&VideoMode_640x480_2color, 0xA000, 8, 16}, /* Mode 11h - VGA 640*480 mono */ + {&VideoMode_640x480_16color, 0xA000, 8, 16}, /* Mode 12h - VGA */ + {&VideoMode_320x200_256color, 0x2000, 8, 8}, /* Mode 13h - VGA */ };
#define IS_TEXT_MODE(ModeNumber) \ @@ -2021,10 +2022,10 @@ /* Move text lines up */ for (i = Rectangle.Top + Amount; i <= Rectangle.Bottom; i++) { - EmulatorWriteMemory(&EmulatorContext, - VideoAddress + ((i - Amount) * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD), - REAL_TO_PHYS(VideoAddress + ( i * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD)), - (Rectangle.Right - Rectangle.Left + 1) * sizeof(WORD)); + EmulatorCopyMemory(&EmulatorContext, + VideoAddress + ((i - Amount) * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD), + VideoAddress + ( i * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD), + (Rectangle.Right - Rectangle.Left + 1) * sizeof(WORD)); }
/* Fill the bottom of the rectangle */ @@ -2049,10 +2050,10 @@ /* Move text lines down */ for (i = Rectangle.Bottom - Amount; i >= Rectangle.Top; i--) { - EmulatorWriteMemory(&EmulatorContext, - VideoAddress + ((i + Amount) * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD), - REAL_TO_PHYS(VideoAddress + ( i * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD)), - (Rectangle.Right - Rectangle.Left + 1) * sizeof(WORD)); + EmulatorCopyMemory(&EmulatorContext, + VideoAddress + ((i + Amount) * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD), + VideoAddress + ( i * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD), + (Rectangle.Right - Rectangle.Left + 1) * sizeof(WORD)); }
/* Fill the top of the rectangle */ @@ -2076,10 +2077,10 @@ /* Move text lines left */ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++) { - EmulatorWriteMemory(&EmulatorContext, - VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left ) * sizeof(WORD), - REAL_TO_PHYS(VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left + Amount) * sizeof(WORD)), - (Rectangle.Right - Rectangle.Left - Amount + 1) * sizeof(WORD)); + EmulatorCopyMemory(&EmulatorContext, + VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left ) * sizeof(WORD), + VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left + Amount) * sizeof(WORD), + (Rectangle.Right - Rectangle.Left - Amount + 1) * sizeof(WORD)); }
/* Fill the right of the rectangle */ @@ -2099,19 +2100,21 @@
case SCROLL_RIGHT: { + INT Right; + /* Move text lines right */ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++) { - EmulatorWriteMemory(&EmulatorContext, - VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left + Amount) * sizeof(WORD), - REAL_TO_PHYS(VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left ) * sizeof(WORD)), - (Rectangle.Right - Rectangle.Left - Amount + 1) * sizeof(WORD)); + EmulatorCopyMemory(&EmulatorContext, + VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left + Amount) * sizeof(WORD), + VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left ) * sizeof(WORD), + (Rectangle.Right - Rectangle.Left - Amount + 1) * sizeof(WORD)); }
/* Fill the left of the rectangle */ + Right = Rectangle.Left + Amount - 1; for (i = Rectangle.Top; i <= Rectangle.Bottom; i++) { - INT Right = Rectangle.Left + Amount - 1; for (j = Rectangle.Left; j <= Right; j++) { EmulatorWriteMemory(&EmulatorContext, @@ -2372,11 +2375,11 @@ IOWriteB(VGA_CRTC_DATA , LOBYTE(CursorStartEnd)); }
-VOID VidBiosSyncCursorPosition(VOID) +static VOID VidBiosSyncCursorPosition(VOID) { BYTE Row, Column; BYTE Low, High; - SHORT ScreenColumns = VgaGetDisplayResolution().X; + SHORT ScreenColumns = Bda->ScreenColumns; WORD Offset;
/* Get the cursor position */ @@ -2493,11 +2496,15 @@
/* Update the screen size */ Resolution = VgaGetDisplayResolution(); + // This could be simplified if the VGA helper always returned the resolution + // in number of pixels, instead of in number of cells for text-modes only... + if (!IS_TEXT_MODE(ModeNumber)) + { + Resolution.X /= VideoModes[ModeNumber].CharacterWidth ; + Resolution.Y /= VideoModes[ModeNumber].CharacterHeight; + } Bda->ScreenColumns = Resolution.X; Bda->ScreenRows = Resolution.Y - 1; - - /* Adjust the number of columns for graphics modes */ - if (!IS_TEXT_MODE(ModeNumber)) Bda->ScreenColumns >>= 3;
/* Update the current font */ Bda->CharacterHeight = VideoModes[ModeNumber].CharacterHeight; @@ -2592,7 +2599,7 @@ * but we update the cursor position on the VGA side). */ VidBiosGetCursorPosition(&Row, &Column, PageNumber); - VidBiosSetCursorPosition(Row, Column, PageNumber); + VidBiosSetCursorPosition( Row, Column, PageNumber);
return TRUE; } @@ -2814,11 +2821,11 @@ WORD i, j; PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]); PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight]; - BYTE PixelBuffer[8]; + BYTE PixelBuffer[8]; // 8 == CharacterWidth
for (i = 0; i < Bda->CharacterHeight; i++) { - for (j = 0; j < 8; j++) + for (j = 0; j < ARRAYSIZE(PixelBuffer); j++) { PixelBuffer[j] = (Glyph[i] & (1 << (7 - j))) ? HIBYTE(CharData) : 0; } @@ -2826,7 +2833,7 @@ EmulatorWriteMemory(&EmulatorContext, TO_LINEAR(GRAPHICS_VIDEO_SEG, ((Row * Bda->CharacterHeight + i) - * Bda->ScreenColumns + Column) << 3), + * Bda->ScreenColumns + Column) * 8), (LPVOID)PixelBuffer, sizeof(PixelBuffer)); }
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] Wed Aug 26 01:26:33 2015 @@ -104,8 +104,6 @@
/* FUNCTIONS ******************************************************************/
-VOID VidBiosSyncCursorPosition(VOID); - VOID WINAPI VidBiosVideoService(LPWORD Stack);
VOID VidBiosDetachFromConsole(VOID);
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c [iso-8859-1] Wed Aug 26 01:26:33 2015 @@ -455,7 +455,6 @@ VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG] = LOBYTE(Offset); VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG] = HIBYTE(Offset);
- // VidBiosSyncCursorPosition(); VgaUpdateTextCursor(); }
@@ -519,13 +518,14 @@ ASSERT(CharBuff); #endif
- /* - * Resize the console - */ + /* Retrieve the latest console information */ + GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo); + + /* Resize the console */ ConRect.Left = 0; - ConRect.Top = ConsoleInfo.srWindow.Top; ConRect.Right = ConRect.Left + Resolution->X - 1; - ConRect.Bottom = ConRect.Top + Resolution->Y - 1; + ConRect.Bottom = max(ConsoleInfo.dwCursorPosition.Y, Resolution->Y - 1); + ConRect.Top = ConRect.Bottom - Resolution->Y + 1; /* * Use this trick to effectively resize the console buffer and window, * because: @@ -534,9 +534,13 @@ * - SetConsoleWindowInfo fails if the new console window size is larger * than the current console screen buffer size. */ - SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution); - SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect); - SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution); + Success = SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution); + DPRINT1("(attach) SetConsoleScreenBufferSize(1) %s with error %d\n", Success ? "succeeded" : "failed", GetLastError()); + Success = SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect); + DPRINT1("(attach) SetConsoleWindowInfo %s with error %d\n", Success ? "succeeded" : "failed", GetLastError()); + Success = SetConsoleScreenBufferSize(TextConsoleBuffer, *Resolution); + DPRINT1("(attach) SetConsoleScreenBufferSize(2) %s with error %d\n", Success ? "succeeded" : "failed", GetLastError()); + /* Update the saved console information */ GetConsoleScreenBufferInfo(TextConsoleBuffer, &ConsoleInfo);
@@ -544,14 +548,11 @@ * Copy console data into VGA memory */
- /* Get the data */ - AddressSize = VgaGetAddressSize(); + /* Read the data from the console into the framebuffer... */ ConRect.Left = ConRect.Top = 0; ConRect.Right = TextResolution.X; ConRect.Bottom = TextResolution.Y; - ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2; - - /* Read the data from the console into the framebuffer... */ + ReadConsoleOutputA(TextConsoleBuffer, CharBuff, TextResolution, @@ -559,6 +560,8 @@ &ConRect);
/* ... and copy the framebuffer into the VGA memory */ + AddressSize = VgaGetAddressSize(); + ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2;
/* Loop through the scanlines */ for (i = 0; i < TextResolution.Y; i++) @@ -1058,6 +1061,7 @@ static BOOL VgaEnterTextMode(PCOORD Resolution) { /* Switch to the text buffer */ + // FIXME: Wouldn't it be preferrable to switch to it AFTER we reset everything?? VgaSetActiveScreenBuffer(TextConsoleBuffer);
/* Adjust the text framebuffer if we changed the resolution */ @@ -1067,8 +1071,8 @@ VgaDetachFromConsoleInternal();
/* - * VgaAttachToConsoleInternal sets TextResolution to the - * new resolution and updates ConsoleInfo. + * VgaAttachToConsoleInternal sets TextResolution + * to the new resolution and updates ConsoleInfo. */ if (!VgaAttachToConsoleInternal(Resolution)) { @@ -1126,6 +1130,9 @@ { goto Quit; } + + // FIXME: Wouldn't it be preferrable to switch to the new console SB + // *ONLY* if we succeeded in setting the new mode??
/* Leave the current video mode */ if (ScreenMode == GRAPHICS_MODE) @@ -1495,7 +1502,7 @@ { /* Hidden cursor */ CursorInfo.bVisible = FALSE; - CursorInfo.dwSize = 1; // The size needs to be non-null in order SetConsoleCursorInfo to succeed. + CursorInfo.dwSize = 1; // The size needs to be non-zero for SetConsoleCursorInfo to succeed. }
/* Add the cursor skew to the location */ @@ -2315,8 +2322,8 @@ // VgaDetachFromConsoleInternal();
/* - * VgaAttachToConsoleInternal sets TextResolution to the - * new resolution and updates ConsoleInfo. + * VgaAttachToConsoleInternal sets TextResolution + * to the new resolution and updates ConsoleInfo. */ if (!VgaAttachToConsoleInternal(&TextResolution)) { @@ -2347,6 +2354,8 @@
VOID VgaDetachFromConsole(VOID) { + BOOL Success; + SMALL_RECT ConRect;
VgaDetachFromConsoleInternal(); @@ -2361,23 +2370,33 @@ OldConsoleFramebuffer = ConsoleFramebuffer; ConsoleFramebuffer = NULL;
+ /* Restore the original console size */ + ConRect.Left = ConRect.Top = 0; + ConRect.Right = ConRect.Left + OrgConsoleBufferInfo.srWindow.Right - OrgConsoleBufferInfo.srWindow.Left; + ConRect.Bottom = ConRect.Top + OrgConsoleBufferInfo.srWindow.Bottom - OrgConsoleBufferInfo.srWindow.Top ; + /* See the following trick explanation in VgaAttachToConsoleInternal */ + Success = SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize); + DPRINT1("(detach) SetConsoleScreenBufferSize(1) %s with error %d\n", Success ? "succeeded" : "failed", GetLastError()); + Success = SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect); + DPRINT1("(detach) SetConsoleWindowInfo %s with error %d\n", Success ? "succeeded" : "failed", GetLastError()); + Success = SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize); + DPRINT1("(detach) SetConsoleScreenBufferSize(2) %s with error %d\n", Success ? "succeeded" : "failed", GetLastError()); + + /* Restore the original cursor shape */ + SetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo); + + // FIXME: Should we copy back the screen data to the screen buffer?? + // WriteConsoleOutputA(...); + + // FIXME: Should we change cursor POSITION?? + // VgaUpdateTextCursor(); + + ///* Update the physical cursor */ + //SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo); + //SetConsoleCursorPosition(TextConsoleBuffer, Position /*OrgConsoleBufferInfo.dwCursorPosition*/); + /* Restore the old text-mode screen buffer */ VgaSetActiveScreenBuffer(TextConsoleBuffer); - - /* Restore the original console size */ - ConRect.Left = 0; - ConRect.Top = 0; - ConRect.Right = ConRect.Left + OrgConsoleBufferInfo.srWindow.Right - OrgConsoleBufferInfo.srWindow.Left; - ConRect.Bottom = ConRect.Top + OrgConsoleBufferInfo.srWindow.Bottom - OrgConsoleBufferInfo.srWindow.Top ; - /* - * See the following trick explanation in VgaAttachToConsoleInternal. - */ - SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize); - SetConsoleWindowInfo(TextConsoleBuffer, TRUE, &ConRect); - SetConsoleScreenBufferSize(TextConsoleBuffer, OrgConsoleBufferInfo.dwSize); - - /* Restore the original cursor shape */ - SetConsoleCursorInfo(TextConsoleBuffer, &OrgConsoleCursorInfo); }
BOOLEAN VgaInitialize(HANDLE TextHandle) @@ -2395,10 +2414,10 @@ ConsoleInfo = OrgConsoleBufferInfo;
/* Clear the SEQ, GC, CRTC and AC registers */ - RtlZeroMemory(VgaSeqRegisters, sizeof(VgaSeqRegisters)); - RtlZeroMemory(VgaGcRegisters, sizeof(VgaGcRegisters)); + RtlZeroMemory(VgaSeqRegisters , sizeof(VgaSeqRegisters )); + RtlZeroMemory(VgaGcRegisters , sizeof(VgaGcRegisters )); RtlZeroMemory(VgaCrtcRegisters, sizeof(VgaCrtcRegisters)); - RtlZeroMemory(VgaAcRegisters, sizeof(VgaAcRegisters)); + RtlZeroMemory(VgaAcRegisters , sizeof(VgaAcRegisters ));
/* Initialize the VGA palette and fail if it isn't successfully created */ if (!VgaInitializePalette()) return FALSE;