Improved DOS VGA mode support

Jukka Heinonen jhei at iki.fi
Fri Jan 25 23:51:37 CST 2002


Before this patch, only VGA mode 320x200x8 worked and
even that mode was displayed in a rather sad little window in 
one corner. After this patch, 320x200x8 mode is displayed using
mode 640x480x8, which works a lot better. Also, one bit plane
of 1-4 bit modes is shown correctly. This is enough to use
some programs that use these modes even though it looks quite
ugly. Proper support for these modes requires emulating VGA
registers and probably separately handling each read/write
into VGA buffer.

Another in the series of weird hacks you do when you feel bored.

Changelog:
	Low-resolution and low-color VGA modes are now mapped 
	into mode 640x480x8. Added preliminary support for
	four bit modes.


Index: wine/dlls/winedos/vga.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/vga.c,v
retrieving revision 1.1
diff -u -r1.1 vga.c
--- wine/dlls/winedos/vga.c     2001/12/04 19:54:45     1.1
+++ wine/dlls/winedos/vga.c     2002/01/26 03:47:22
@@ -26,6 +26,10 @@
 static LONG vga_polling,vga_refresh;
 static HANDLE poll_timer;
 
+static int vga_width;
+static int vga_height;
+static int vga_depth;
+
 typedef HRESULT WINAPI (*DirectDrawCreateProc)(LPGUID,LPDIRECTDRAW *,LPUNKNOWN);
 static DirectDrawCreateProc pDirectDrawCreate;
 
@@ -155,9 +159,21 @@
 int VGA_SetMode(unsigned Xres,unsigned Yres,unsigned Depth)
 {
     ModeSet par;
-    par.Xres = Xres;
-    par.Yres = Yres;
-    par.Depth = Depth;
+
+    vga_width = Xres;
+    vga_height = Yres;
+    vga_depth = Depth;
+
+    if(Xres >= 640 || Yres >= 480) {
+      par.Xres = Xres;
+      par.Yres = Yres;
+    } else {
+      par.Xres = 640;
+      par.Yres = 480;
+    }
+
+    par.Depth = (Depth < 8) ? 8 : Depth;
+
     MZ_RunInThread(VGA_DoSetMode, (ULONG_PTR)&par);
     return par.ret;
 }
@@ -290,6 +306,59 @@
 
 /*** CONTROL ***/
 
+static void VGA_Poll_Graphics(void)
+{
+  unsigned int Pitch, Height, Width, X, Y;
+  char *surf;
+  char *dat = DOSMEM_MapDosToLinear(0xa0000);
+
+  surf = VGA_Lock(&Pitch,&Height,&Width,NULL);
+  if (!surf) return;
+
+  if(vga_width == 320 && vga_depth <= 4)
+    for (Y=0; Y<vga_height; Y++,surf+=Pitch*2,dat+=vga_width/8) {
+      for(X=0; X<vga_width; X+=8) {
+       int offset = X/8;
+       int Z;
+       for(Z=0; Z<8; Z++) {
+         int b0 =  (dat[offset] >> Z) & 0x1;
+         int index = 7-Z;
+         surf[(X+index)*2] = b0;
+         surf[(X+index)*2+1] = b0;
+         surf[(X+index)*2+Pitch] = b0;
+         surf[(X+index)*2+Pitch+1] = b0;
+       }
+      }
+    }
+
+  if(vga_width == 320 && vga_depth == 8)
+    for (Y=0; Y<vga_height; Y++,surf+=Pitch*2,dat+=vga_width) {
+      for(X=0; X<vga_width; X++) {
+       int b0 = dat[X];
+       surf[X*2] = b0;
+       surf[X*2+1] = b0;
+       surf[X*2+Pitch] = b0;
+       surf[X*2+Pitch+1] = b0;
+      }
+    }
+
+  if(vga_depth <= 4)
+    for (Y=0; Y<vga_height; Y++,surf+=Pitch,dat+=vga_width/8) {
+      for(X=0; X<vga_width; X+=8) {
+       int offset = X/8;
+       int Z;
+       for(Z=0; Z<8; Z++) {
+         int b0 =  (dat[offset] >> Z) & 0x1;
+         int index = 7-Z;
+         surf[X+index] = b0;
+       }
+      }
+    }
+
+  VGA_Unlock();
+}
+
+
 void CALLBACK VGA_Poll( ULONG_PTR arg )
 {
     char *dat;
@@ -300,16 +369,7 @@
         /* FIXME: optimize by doing this only if the data has actually changed
          *        (in a way similar to DIBSection, perhaps) */
         if (lpddraw) {
-          /* graphics mode */
-          surf = VGA_Lock(&Pitch,&Height,&Width,NULL);
-          if (!surf) return;
-          dat = DOSMEM_MapDosToLinear(0xa0000);
-          /* copy from virtual VGA frame buffer to DirectDraw surface */
-          for (Y=0; Y<Height; Y++,surf+=Pitch,dat+=Width) {
-              memcpy(surf,dat,Width);
-              /*for (X=0; X<Width; X++) if (dat[X]) TRACE(ddraw,"data(%d) at (%d,%d)\n",dat[X],X,Y);*/
-          }
-          VGA_Unlock();
+         VGA_Poll_Graphics();
         } else {
           /* text mode */
           CHAR_INFO ch[80];



-- 
Jukka Heinonen <http://www.iki.fi/jhei/>




More information about the wine-patches mailing list