improve DOS text mode updating

Andreas Mohr andi at rhlx01.fht-esslingen.de
Mon Jul 1 16:47:36 CDT 2002


Hi all,

added a DOS text mode memory buffer copy in order to be able to tell which
lines of text changed and thus which ones to update.
In order words: only refresh the lines of the text console (wineconsole)
that really changed.
I also freed the console copying from a 80 chars/line limitation.

This is another patch to make IDA/DOS some real joy to use...
(it's working almost beautifully now !)

-- 
Andreas Mohr                        Stauferstr. 6, D-71272 Renningen, Germany
-------------- next part --------------
Determining best CVS host...
Using CVSROOT :pserver:cvs at rhlx01.fht-esslingen.de:/home/wine
Index: dlls/winedos/vga.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/vga.c,v
retrieving revision 1.15
diff -u -r1.15 vga.c
--- dlls/winedos/vga.c	1 Jul 2002 18:13:52 -0000	1.15
+++ dlls/winedos/vga.c	1 Jul 2002 21:47:56 -0000
@@ -42,6 +42,7 @@
 static int vga_height;
 static int vga_depth;
 static BYTE vga_text_attr;
+static char *textbuf_old = NULL;
 
 static BOOL vga_mode_initialized = FALSE;
 
@@ -447,6 +448,25 @@
 
 /*** TEXT MODE ***/
 
+/* prepare the text mode video memory copy that is used to only
+ * update the video memory line that did get updated. */
+void VGA_PrepareVideoMemCopy(unsigned Xres, unsigned Yres)
+{
+    char *p, *p2;
+    int i;
+    
+    textbuf_old = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textbuf_old, Xres * Yres * 2); /* char + attr */
+
+    p = VGA_AlphaBuffer();
+    p2 = textbuf_old;
+
+    /* make sure the video mem copy contains the exact opposite of our
+     * actual text mode memory area to make sure the screen
+     * does get updated fully initially */
+    for (i=0; i < Xres*Yres*2; i++)
+	*p2++ ^= *p++; /* XOR it */
+}
+	
 int VGA_SetAlphaMode(unsigned Xres,unsigned Yres)
 {
     COORD siz;
@@ -456,8 +476,10 @@
     /* FIXME: Where to initialize text attributes? */
     VGA_SetTextAttribute(0xf);
 
-    /* the xterm is slow, so refresh only every 200ms (5fps) */
-    VGA_InstallTimer(200);
+    VGA_PrepareVideoMemCopy(Xres, Yres);
+
+    /* poll every 30ms (33fps should provide adequate responsiveness) */
+    VGA_InstallTimer(30);
 
     siz.X = Xres;
     siz.Y = Yres;
@@ -671,6 +693,8 @@
 
 /*** CONTROL ***/
 
+/* FIXME: optimize by doing this only if the data has actually changed
+ *        (in a way similar to DIBSection, perhaps) */
 static void VGA_Poll_Graphics(void)
 {
   unsigned int Pitch, Height, Width, X, Y;
@@ -725,29 +749,41 @@
 
 static void VGA_Poll_Text(void)
 {
-    char *dat;
+    char *dat, *old, *p_line;
     unsigned int Height,Width,Y,X;
-    CHAR_INFO ch[80];
+    CHAR_INFO ch[256]; /* that should suffice for the largest text width */
     COORD siz, off;
     SMALL_RECT dest;
     HANDLE con = VGA_AlphaConsole();
+    BOOL linechanged = FALSE; /* video memory area differs from stored copy ? */
 
     VGA_GetAlphaMode(&Width,&Height);
     dat = VGA_AlphaBuffer();
-    siz.X = 80; siz.Y = 1;
+    old = textbuf_old; /* pointer to stored video mem copy */
+    siz.X = Width; siz.Y = 1;
     off.X = 0; off.Y = 0;
     /* copy from virtual VGA frame buffer to console */
     for (Y=0; Y<Height; Y++) {
-        dest.Top=Y; dest.Bottom=Y;
-       for (X=0; X<Width; X++) {
-           ch[X].Char.AsciiChar = *dat++;
-           /* WriteConsoleOutputA doesn't like "dead" chars */
-           if (ch[X].Char.AsciiChar == '\0')
-               ch[X].Char.AsciiChar = ' ';
-           ch[X].Attributes = *dat++;
-       }
-       dest.Left=0; dest.Right=Width+1;
-       WriteConsoleOutputA(con, ch, siz, off, &dest);
+	linechanged = memcmp(dat, old, Width*2);
+	if (linechanged)
+	{
+	    /*TRACE("line %d changed\n", Y);*/
+	    p_line = dat;
+            for (X=0; X<Width; X++) {
+                ch[X].Char.AsciiChar = *p_line++;
+                /* WriteConsoleOutputA doesn't like "dead" chars */
+                if (ch[X].Char.AsciiChar == '\0')
+                    ch[X].Char.AsciiChar = ' ';
+                ch[X].Attributes = *p_line++;
+            }
+            dest.Top=Y; dest.Bottom=Y;
+            dest.Left=0; dest.Right=Width+1;
+            WriteConsoleOutputA(con, ch, siz, off, &dest);
+	    memcpy(old, dat, Width*2);
+	}
+	/* advance to next text line */
+	dat += Width*2;
+	old += Width*2;
     }
 }
 
@@ -756,8 +792,6 @@
     if(!TryEnterCriticalSection(&vga_lock))
         return;
 
-    /* FIXME: optimize by doing this only if the data has actually changed
-     *        (in a way similar to DIBSection, perhaps) */
     if (lpddraw) {
         VGA_Poll_Graphics();
     } else {


More information about the wine-patches mailing list