2 * VGA hardware emulation
4 * Copyright 1998 Ove Kåven (with some help from Marcus Meissner)
14 #include "interfaces.h"
18 static IDirectDraw
*lpddraw
= NULL
;
19 static IDirectDrawSurface
*lpddsurf
;
20 static IDirectDrawPalette
*lpddpal
;
21 static DDSURFACEDESC sdesc
;
22 static WORD poll_timer
;
23 static CRITICAL_SECTION vga_crit
;
24 static int vga_polling
;
26 int VGA_SetMode(unsigned Xres
,unsigned Yres
,unsigned Depth
)
28 if (lpddraw
) VGA_Exit();
30 DirectDrawCreate(NULL
,&lpddraw
,NULL
);
32 ERR(ddraw
,"DirectDraw is not available\n");
35 if (lpddraw
->lpvtbl
->fnSetDisplayMode(lpddraw
,Xres
,Yres
,Depth
)) {
36 ERR(ddraw
,"DirectDraw does not support requested display mode\n");
37 lpddraw
->lpvtbl
->fnRelease(lpddraw
);
41 lpddraw
->lpvtbl
->fnCreatePalette(lpddraw
,0,NULL
,&lpddpal
,NULL
);
42 memset(&sdesc
,0,sizeof(sdesc
));
43 sdesc
.dwSize
=sizeof(sdesc
);
44 if (lpddraw
->lpvtbl
->fnCreateSurface(lpddraw
,&sdesc
,&lpddsurf
,NULL
)||(!lpddsurf
)) {
45 ERR(ddraw
,"DirectDraw surface is not available\n");
46 lpddraw
->lpvtbl
->fnRelease(lpddraw
);
50 InitializeCriticalSection(&vga_crit
);
51 /* poll every 20ms (50fps should provide adequate responsiveness) */
52 poll_timer
= CreateSystemTimer( 20, (FARPROC16
)VGA_Poll
);
57 int VGA_GetMode(unsigned*Height
,unsigned*Width
,unsigned*Depth
)
59 if (!lpddraw
) return 1;
60 if (!lpddsurf
) return 1;
61 if (Height
) *Height
=sdesc
.dwHeight
;
62 if (Width
) *Width
=sdesc
.dwWidth
;
63 if (Depth
) *Depth
=sdesc
.ddpfPixelFormat
.x
.dwRGBBitCount
;
70 SYSTEM_KillSystemTimer(poll_timer
);
71 DeleteCriticalSection(&vga_crit
);
72 lpddsurf
->lpvtbl
->fnRelease(lpddsurf
);
74 lpddraw
->lpvtbl
->fnRelease(lpddraw
);
79 void VGA_SetPalette(PALETTEENTRY
*pal
,int start
,int len
)
82 lpddpal
->lpvtbl
->fnSetEntries(lpddpal
,0,start
,len
,pal
);
83 lpddsurf
->lpvtbl
->fnSetPalette(lpddsurf
,lpddpal
);
86 void VGA_SetQuadPalette(RGBQUAD
*color
,int start
,int len
)
88 PALETTEENTRY pal
[256];
92 for (c
=0; c
<len
; c
++) {
93 pal
[c
].peRed
=color
[c
].rgbRed
;
94 pal
[c
].peGreen
=color
[c
].rgbGreen
;
95 pal
[c
].peBlue
=color
[c
].rgbBlue
;
98 lpddpal
->lpvtbl
->fnSetEntries(lpddpal
,0,start
,len
,pal
);
99 lpddsurf
->lpvtbl
->fnSetPalette(lpddsurf
,lpddpal
);
102 LPSTR
VGA_Lock(unsigned*Pitch
,unsigned*Height
,unsigned*Width
,unsigned*Depth
)
104 if (!lpddraw
) return NULL
;
105 if (!lpddsurf
) return NULL
;
106 if (lpddsurf
->lpvtbl
->fnLock(lpddsurf
,NULL
,&sdesc
,0,0)) {
107 ERR(ddraw
,"could not lock surface!\n");
110 if (Pitch
) *Pitch
=sdesc
.lPitch
;
111 if (Height
) *Height
=sdesc
.dwHeight
;
112 if (Width
) *Width
=sdesc
.dwWidth
;
113 if (Depth
) *Depth
=sdesc
.ddpfPixelFormat
.x
.dwRGBBitCount
;
114 return sdesc
.y
.lpSurface
;
117 void VGA_Unlock(void)
119 lpddsurf
->lpvtbl
->fnUnlock(lpddsurf
,sdesc
.y
.lpSurface
);
125 unsigned Pitch
,Height
,Width
;
129 EnterCriticalSection(&vga_crit
);
132 LeaveCriticalSection(&vga_crit
);
133 /* FIXME: optimize by doing this only if the data has actually changed
134 * (in a way similar to DIBSection, perhaps) */
135 surf
= VGA_Lock(&Pitch
,&Height
,&Width
,NULL
);
137 dat
= DOSMEM_MapDosToLinear(0xa0000);
138 /* copy from virtual VGA frame buffer to DirectDraw surface */
139 for (Y
=0; Y
<Height
; Y
++,surf
+=Pitch
,dat
+=Width
) {
140 memcpy(surf
,dat
,Width
);
141 for (X
=0; X
<Width
; X
++) if (dat
[X
]) TRACE(ddraw
,"data(%d) at (%d,%d)\n",dat
[X
],X
,Y
);
144 EnterCriticalSection(&vga_crit
);
147 LeaveCriticalSection(&vga_crit
);
150 static BYTE palreg
,palcnt
;
151 static PALETTEENTRY paldat
;
153 void VGA_ioport_out( WORD port
, BYTE val
)
157 palreg
=val
; palcnt
=0; break;
159 ((BYTE
*)&paldat
)[palcnt
++]=val
<< 2;
161 VGA_SetPalette(&paldat
,palreg
,1);