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/>