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/vidbios.c?rev=65451&r1=65450&r2=65451&view=diff
==============================================================================
--- 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/vidbios.h?rev=65451&r1=65450&r2=65451&view=diff
==============================================================================
--- 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 
******************************************************************/
 


Reply via email to