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:
parent
7f740cbb04
commit
1499a845ff
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
|
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 */
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue