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/vidbi... ============================================================================== --- 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/vidbi... ============================================================================== --- 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 ******************************************************************/