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
Determining best CVS host... Using CVSROOT :pserver:cvs@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 {