Author: hbelusca
Date: Sun Nov 23 12:03:55 2014
New Revision: 65451
URL:
http://svn.reactos.org/svn/reactos?rev=65451&view=rev
Log:
[NTVDM]: Rewrite video window scrolling code more efficiently (i.e. getting rid of
HeapAlloc/Free calls). As a bonus, implement scrolling horizontally.
Modified:
trunk/reactos/subsystems/ntvdm/bios/vidbios.c
trunk/reactos/subsystems/ntvdm/bios/vidbios.h
Modified: trunk/reactos/subsystems/ntvdm/bios/vidbios.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/vidb…
==============================================================================
--- trunk/reactos/subsystems/ntvdm/bios/vidbios.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/ntvdm/bios/vidbios.c [iso-8859-1] Sun Nov 23 12:03:55 2014
@@ -1943,132 +1943,153 @@
/* 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,
+static BOOLEAN VidBiosScrollWindow(SCROLL_DIRECTION 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)))
+ INT i, j;
+ DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+ WORD FillCharacter = MAKEWORD(' ', FillAttribute);
+
+ WORD WindowWidth, WindowHeight;
+
+ /* Fixup the rectangle if needed */
+ Rectangle.Left = min(max(Rectangle.Left , 0), Bda->ScreenColumns - 1);
+ Rectangle.Right = min(max(Rectangle.Right , 0), Bda->ScreenColumns - 1);
+ Rectangle.Top = min(max(Rectangle.Top , 0), Bda->ScreenRows);
+ Rectangle.Bottom = min(max(Rectangle.Bottom, 0), Bda->ScreenRows);
+
+ WindowWidth = Rectangle.Right - Rectangle.Left + 1;
+ WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
+
+ /* Amount == 0 means we clear all the rectangle */
+ if ((Amount == 0) ||
+ (((Direction == SCROLL_UP ) || (Direction == SCROLL_DOWN )) && (Amount
>= WindowHeight)) ||
+ (((Direction == SCROLL_LEFT) || (Direction == SCROLL_RIGHT)) && (Amount
>= WindowWidth )))
{
- /* Fill the window */
- for (i = 0; i < WindowSize; i++)
+ /* Fill the rectangle */
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
{
- WindowData[i] = MAKEWORD(' ', FillAttribute);
+ for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) *
sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
}
- goto Done;
+ return TRUE;
}
switch (Direction)
{
- case SCROLL_DIRECTION_UP:
+ case SCROLL_UP:
{
- RtlMoveMemory(WindowData,
- &WindowData[WindowWidth * Amount],
- (WindowSize - WindowWidth * Amount) * sizeof(WORD));
-
- for (i = 0; i < Amount * WindowWidth; i++)
+ /* Move text lines up */
+ for (i = Rectangle.Top + Amount; i <= Rectangle.Bottom; i++)
{
- WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
+ 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));
+ }
+
+ /* Fill the bottom of the rectangle */
+ for (i = Rectangle.Bottom - Amount + 1; i <= Rectangle.Bottom; i++)
+ {
+ for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) *
sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
}
break;
}
- case SCROLL_DIRECTION_DOWN:
+ case SCROLL_DOWN:
{
- RtlMoveMemory(&WindowData[WindowWidth * Amount],
- WindowData,
- (WindowSize - WindowWidth * Amount) * sizeof(WORD));
-
- for (i = 0; i < Amount * WindowWidth; i++)
+ /* Move text lines down */
+ for (i = Rectangle.Bottom - Amount; i >= Rectangle.Top; i--)
{
- WindowData[i] = MAKEWORD(' ', FillAttribute);
+ 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));
+ }
+
+ /* Fill the top of the rectangle */
+ for (i = Rectangle.Top; i <= Rectangle.Top + Amount - 1; i++)
+ {
+ for (j = Rectangle.Left; j <= Rectangle.Right; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) *
sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
}
break;
}
- default:
+ case SCROLL_LEFT:
{
- // TODO: NOT IMPLEMENTED!
- UNIMPLEMENTED;
+ /* 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));
+ }
+
+ /* Fill the right of the rectangle */
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+ {
+ for (j = Rectangle.Right - Amount + 1; j <= Rectangle.Right; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) *
sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
+ }
+
+ break;
+ }
+
+ case SCROLL_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));
+ }
+
+ /* Fill the left of the rectangle */
+ for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
+ {
+ for (j = Rectangle.Left; j <= Rectangle.Left + Amount - 1; j++)
+ {
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) *
sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
+ }
+
+ break;
}
}
-
-Done:
- /* Write back the window data */
- VidBiosWriteWindow(WindowData, Rectangle, Page);
-
- /* Free the window buffer */
- HeapFree(GetProcessHeap(), 0, WindowData);
return TRUE;
}
@@ -2426,6 +2447,31 @@
VidBiosSetCursorPosition(0, 0, Page);
// FIXME: We need to reset the fonts and the font vectors. (INT 1Fh and 43h).
+
+ // HACK: We clear here all the text memory. TODO: Do it better!
+ if (!DoNotClear && ((ModeNumber >= 0x00 && ModeNumber <= 0x03)
|| (ModeNumber == 0x07)))
+ {
+ INT i, j;
+ DWORD VideoAddress;
+ WORD FillCharacter = MAKEWORD(' ', DEFAULT_ATTRIBUTE);
+
+ for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
+ {
+ VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
+
+ for (i = 0; i <= Bda->ScreenRows; i++)
+ {
+ for (j = 0; j <= Bda->ScreenColumns - 1; j++)
+ {
+ /* Write to video memory */
+ EmulatorWriteMemory(&EmulatorContext,
+ VideoAddress + (i * Bda->ScreenColumns + j) *
sizeof(WORD),
+ (LPVOID)&FillCharacter,
+ sizeof(FillCharacter));
+ }
+ }
+ }
+ }
/* Refresh display */
VgaRefreshDisplay();
@@ -2552,13 +2598,7 @@
{
/* 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);
-
+ VidBiosScrollWindow(SCROLL_UP, 1, Rectangle, Page,
DEFAULT_ATTRIBUTE/*Attribute*/);
Row--;
}
@@ -2629,13 +2669,8 @@
{
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());
+ VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_UP : SCROLL_DOWN,
+ getAL(), Rectangle, Bda->VideoPage, getBH());
break;
}
Modified: trunk/reactos/subsystems/ntvdm/bios/vidbios.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/ntvdm/bios/vidb…
==============================================================================
--- trunk/reactos/subsystems/ntvdm/bios/vidbios.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/ntvdm/bios/vidbios.h [iso-8859-1] Sun Nov 23 12:03:55 2014
@@ -33,13 +33,13 @@
#define FONT_8x16_OFFSET 0x0800
#define FONT_8x14_OFFSET 0x1800
-enum
+typedef enum
{
- SCROLL_DIRECTION_UP,
- SCROLL_DIRECTION_DOWN,
- SCROLL_DIRECTION_LEFT,
- SCROLL_DIRECTION_RIGHT
-};
+ SCROLL_UP,
+ SCROLL_DOWN,
+ SCROLL_LEFT,
+ SCROLL_RIGHT
+} SCROLL_DIRECTION;
/* FUNCTIONS ******************************************************************/