Moved VGA-emulating DirectX code from dispdib.c to a separate

file. Made it use a system timer and trap I/O accesses to the VGA
DAC registers to accommodate DisplayDib-using programs that try to
access the VGA hardware directly.
This commit is contained in:
Ove Kaaven 1998-11-01 12:51:47 +00:00 committed by Alexandre Julliard
parent 7f740cbb04
commit 1499a845ff
5 changed files with 212 additions and 51 deletions

View File

@ -17,6 +17,7 @@ C_SRCS = \
mapping.c \ mapping.c \
painting.c \ painting.c \
path.c \ path.c \
vga.c \
wing.c wing.c
all: $(MODULE).o all: $(MODULE).o

View File

@ -7,17 +7,12 @@
#include <string.h> #include <string.h>
#include "windows.h" #include "windows.h"
#include "miscemu.h"
#include "dispdib.h" #include "dispdib.h"
#include "compobj.h" #include "vga.h"
#include "interfaces.h"
#include "ddraw.h"
#include "debug.h" #include "debug.h"
static int dispdib_multi = 0; static int dispdib_multi = 0;
static IDirectDraw *lpddraw = NULL;
static IDirectDrawSurface *lpddsurf;
static IDirectDrawPalette *lpddpal;
static DDSURFACEDESC sdesc;
static WORD DISPDIB_Begin(WORD wFlags) static WORD DISPDIB_Begin(WORD wFlags)
{ {
@ -33,60 +28,28 @@ static WORD DISPDIB_Begin(WORD wFlags)
default: default:
return DISPLAYDIB_NOTSUPPORTED; return DISPLAYDIB_NOTSUPPORTED;
} }
if (!lpddraw) { if (VGA_SetMode(Xres,Yres,Depth)) return DISPLAYDIB_NOTSUPPORTED;
DirectDrawCreate(NULL,&lpddraw,NULL);
if (!lpddraw) {
ERR(ddraw,"DirectDraw is not available\n");
return DISPLAYDIB_NOTSUPPORTED;
}
if (lpddraw->lpvtbl->fnSetDisplayMode(lpddraw,Xres,Yres,Depth)) {
ERR(ddraw,"DirectDraw does not support requested display mode\n");
lpddraw->lpvtbl->fnRelease(lpddraw);
return DISPLAYDIB_NOTSUPPORTED;
}
lpddraw->lpvtbl->fnCreatePalette(lpddraw,0,NULL,&lpddpal,NULL);
memset(&sdesc,0,sizeof(sdesc));
sdesc.dwSize=sizeof(sdesc);
lpddraw->lpvtbl->fnCreateSurface(lpddraw,&sdesc,&lpddsurf,NULL);
}
return DISPLAYDIB_NOERROR; return DISPLAYDIB_NOERROR;
} }
static void DISPDIB_End(void) static void DISPDIB_End(void)
{ {
if (lpddraw) { VGA_Exit();
lpddsurf->lpvtbl->fnRelease(lpddsurf);
lpddraw->lpvtbl->fnRelease(lpddraw);
lpddraw=NULL;
}
} }
static void DISPDIB_Palette(LPBITMAPINFO lpbi) static void DISPDIB_Palette(LPBITMAPINFO lpbi)
{ {
PALETTEENTRY pal[256]; VGA_SetQuadPalette(lpbi->bmiColors,0,256);
int c;
for (c=0; c<256; c++) {
pal[c].peRed =lpbi->bmiColors[c].rgbRed;
pal[c].peGreen=lpbi->bmiColors[c].rgbGreen;
pal[c].peBlue =lpbi->bmiColors[c].rgbBlue;
pal[c].peFlags=0;
}
lpddpal->lpvtbl->fnSetEntries(lpddpal,0,0,256,pal);
lpddsurf->lpvtbl->fnSetPalette(lpddsurf,lpddpal);
} }
static void DISPDIB_Show(LPBITMAPINFOHEADER lpbi,LPSTR lpBits,WORD uFlags) static void DISPDIB_Show(LPBITMAPINFOHEADER lpbi,LPSTR lpBits,WORD uFlags)
{ {
int Xofs,Yofs,Width=lpbi->biWidth,Height=lpbi->biHeight,Delta; int Xofs,Yofs,Width=lpbi->biWidth,Height=lpbi->biHeight,Delta;
unsigned Pitch=(Width+3)&~3; unsigned Pitch=(Width+3)&~3,sPitch,sWidth,sHeight;
LPSTR surf; LPSTR surf = DOSMEM_MapDosToLinear(0xa0000);
if (lpddsurf->lpvtbl->fnLock(lpddsurf,NULL,&sdesc,0,0)) { if (VGA_GetMode(&sHeight,&sWidth,NULL)) return;
ERR(ddraw,"could not lock surface!\n"); sPitch=320;
return;
}
/* size in sdesc.dwHeight, sdesc.dwWidth, pitch in sdesc.lPitch, ptr in sdesc.y.lpSurface */
Delta=(Height<0)*2-1; Delta=(Height<0)*2-1;
Height*=-Delta; Pitch*=Delta; Height*=-Delta; Pitch*=Delta;
@ -94,16 +57,16 @@ static void DISPDIB_Show(LPBITMAPINFOHEADER lpbi,LPSTR lpBits,WORD uFlags)
if (uFlags&DISPLAYDIB_NOCENTER) { if (uFlags&DISPLAYDIB_NOCENTER) {
Xofs=0; Yofs=0; Xofs=0; Yofs=0;
} else { } else {
Xofs=(sdesc.dwWidth-Width)/2; Xofs=(sWidth-Width)/2;
Yofs=(sdesc.dwHeight-Height)/2; Yofs=(sHeight-Height)/2;
} }
surf=(LPSTR)sdesc.y.lpSurface + (Yofs*sdesc.lPitch)+Xofs; surf += (Yofs*sPitch)+Xofs;
if (Pitch<0) lpBits-=Pitch*(Height-1); if (Pitch<0) lpBits-=Pitch*(Height-1);
for (; Height; Height--,lpBits+=Pitch,surf+=sdesc.lPitch) { for (; Height; Height--,lpBits+=Pitch,surf+=sPitch) {
memcpy(surf,lpBits,Width); memcpy(surf,lpBits,Width);
} }
lpddsurf->lpvtbl->fnUnlock(lpddsurf,sdesc.y.lpSurface); VGA_Poll();
} }
/********************************************************************* /*********************************************************************

165
graphics/vga.c Normal file
View File

@ -0,0 +1,165 @@
/*
* VGA hardware emulation
*
* Copyright 1998 Ove Kåven (with some help from Marcus Meissner)
*
*/
#include <string.h>
#include "windows.h"
#include "winbase.h"
#include "miscemu.h"
#include "vga.h"
#include "compobj.h"
#include "interfaces.h"
#include "ddraw.h"
#include "debug.h"
static IDirectDraw *lpddraw = NULL;
static IDirectDrawSurface *lpddsurf;
static IDirectDrawPalette *lpddpal;
static DDSURFACEDESC sdesc;
static WORD poll_timer;
static CRITICAL_SECTION vga_crit;
static int vga_polling;
int VGA_SetMode(unsigned Xres,unsigned Yres,unsigned Depth)
{
if (lpddraw) VGA_Exit();
if (!lpddraw) {
DirectDrawCreate(NULL,&lpddraw,NULL);
if (!lpddraw) {
ERR(ddraw,"DirectDraw is not available\n");
return 1;
}
if (lpddraw->lpvtbl->fnSetDisplayMode(lpddraw,Xres,Yres,Depth)) {
ERR(ddraw,"DirectDraw does not support requested display mode\n");
lpddraw->lpvtbl->fnRelease(lpddraw);
lpddraw=NULL;
return 1;
}
lpddraw->lpvtbl->fnCreatePalette(lpddraw,0,NULL,&lpddpal,NULL);
memset(&sdesc,0,sizeof(sdesc));
sdesc.dwSize=sizeof(sdesc);
if (lpddraw->lpvtbl->fnCreateSurface(lpddraw,&sdesc,&lpddsurf,NULL)||(!lpddsurf)) {
ERR(ddraw,"DirectDraw surface is not available\n");
lpddraw->lpvtbl->fnRelease(lpddraw);
lpddraw=NULL;
return 1;
}
InitializeCriticalSection(&vga_crit);
/* poll every 20ms (50fps should provide adequate responsiveness) */
poll_timer = CreateSystemTimer( 20, (FARPROC16)VGA_Poll );
}
return 0;
}
int VGA_GetMode(unsigned*Height,unsigned*Width,unsigned*Depth)
{
if (!lpddraw) return 1;
if (!lpddsurf) return 1;
if (Height) *Height=sdesc.dwHeight;
if (Width) *Width=sdesc.dwWidth;
if (Depth) *Depth=sdesc.ddpfPixelFormat.x.dwRGBBitCount;
return 0;
}
void VGA_Exit(void)
{
if (lpddraw) {
SYSTEM_KillSystemTimer(poll_timer);
DeleteCriticalSection(&vga_crit);
lpddsurf->lpvtbl->fnRelease(lpddsurf);
lpddsurf=NULL;
lpddraw->lpvtbl->fnRelease(lpddraw);
lpddraw=NULL;
}
}
void VGA_SetPalette(PALETTEENTRY*pal,int start,int len)
{
if (!lpddraw) return;
lpddpal->lpvtbl->fnSetEntries(lpddpal,0,start,len,pal);
lpddsurf->lpvtbl->fnSetPalette(lpddsurf,lpddpal);
}
void VGA_SetQuadPalette(RGBQUAD*color,int start,int len)
{
PALETTEENTRY pal[256];
int c;
if (!lpddraw) return;
for (c=0; c<len; c++) {
pal[c].peRed =color[c].rgbRed;
pal[c].peGreen=color[c].rgbGreen;
pal[c].peBlue =color[c].rgbBlue;
pal[c].peFlags=0;
}
lpddpal->lpvtbl->fnSetEntries(lpddpal,0,start,len,pal);
lpddsurf->lpvtbl->fnSetPalette(lpddsurf,lpddpal);
}
LPSTR VGA_Lock(unsigned*Pitch,unsigned*Height,unsigned*Width,unsigned*Depth)
{
if (!lpddraw) return NULL;
if (!lpddsurf) return NULL;
if (lpddsurf->lpvtbl->fnLock(lpddsurf,NULL,&sdesc,0,0)) {
ERR(ddraw,"could not lock surface!\n");
return NULL;
}
if (Pitch) *Pitch=sdesc.lPitch;
if (Height) *Height=sdesc.dwHeight;
if (Width) *Width=sdesc.dwWidth;
if (Depth) *Depth=sdesc.ddpfPixelFormat.x.dwRGBBitCount;
return sdesc.y.lpSurface;
}
void VGA_Unlock(void)
{
lpddsurf->lpvtbl->fnUnlock(lpddsurf,sdesc.y.lpSurface);
}
void VGA_Poll(void)
{
char *dat;
unsigned Pitch,Height,Width;
char *surf;
int Y,X;
EnterCriticalSection(&vga_crit);
if (!vga_polling) {
vga_polling++;
LeaveCriticalSection(&vga_crit);
/* FIXME: optimize by doing this only if the data has actually changed
* (in a way similar to DIBSection, perhaps) */
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();
EnterCriticalSection(&vga_crit);
vga_polling--;
}
LeaveCriticalSection(&vga_crit);
}
static BYTE palreg,palcnt;
static PALETTEENTRY paldat;
void VGA_ioport_out( WORD port, BYTE val )
{
switch (port) {
case 0x3c8:
palreg=val; palcnt=0; break;
case 0x3c9:
((BYTE*)&paldat)[palcnt++]=val << 2;
if (palcnt==3) {
VGA_SetPalette(&paldat,palreg,1);
palreg++;
}
}
}

23
include/vga.h Normal file
View File

@ -0,0 +1,23 @@
/*
* VGA emulation
*
* Copyright 1998 Ove KÅven
*
*/
#ifndef __WINE_VGA_H
#define __WINE_VGA_H
#include "wintypes.h"
int VGA_SetMode(unsigned Xres,unsigned Yres,unsigned Depth);
int VGA_GetMode(unsigned*Height,unsigned*Width,unsigned*Depth);
void VGA_Exit(void);
void VGA_SetPalette(PALETTEENTRY*pal,int start,int len);
void VGA_SetQuadPalette(RGBQUAD*color,int start,int len);
LPSTR VGA_Lock(unsigned*Pitch,unsigned*Height,unsigned*Width,unsigned*Depth);
void VGA_Unlock(void);
void VGA_Poll(void);
void VGA_ioport_out(WORD port, BYTE val);
#endif /* __WINE_VGA_H */

View File

@ -16,6 +16,7 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "windows.h" #include "windows.h"
#include "vga.h"
#include "options.h" #include "options.h"
#include "debug.h" #include "debug.h"
@ -234,6 +235,10 @@ DWORD IO_inport( int port, int count )
case 0x71: case 0x71:
b = cmosimage[cmosaddress & 0x3f]; b = cmosimage[cmosaddress & 0x3f];
break; break;
case 0x200:
case 0x201:
b = 0xff; /* no joystick */
break;
default: default:
WARN( int, "Direct I/O read attempted from port %x\n", port); WARN( int, "Direct I/O read attempted from port %x\n", port);
b = 0xff; b = 0xff;
@ -293,6 +298,10 @@ void IO_outport( int port, int count, DWORD value )
case 0x71: case 0x71:
cmosimage[cmosaddress & 0x3f] = b; cmosimage[cmosaddress & 0x3f] = b;
break; break;
case 0x3c8:
case 0x3c9:
VGA_ioport_out( port, b );
break;
default: default:
WARN(int, "Direct I/O write attempted to port %x\n", port ); WARN(int, "Direct I/O write attempted to port %x\n", port );
break; break;