Stubs for EnumServiceStatus32, small changes.
[wine/multimedia.git] / graphics / vga.c
blobbe4730d6e20eb4360b8db0b31ca2e2fd617e8af6
1 /*
2 * VGA hardware emulation
3 *
4 * Copyright 1998 Ove Kåven (with some help from Marcus Meissner)
6 */
8 #include <string.h>
9 #include "windows.h"
10 #include "winbase.h"
11 #include "miscemu.h"
12 #include "vga.h"
13 #include "compobj.h"
14 #include "interfaces.h"
15 #include "ddraw.h"
16 #include "debug.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,vga_refresh;
26 int VGA_SetMode(unsigned Xres,unsigned Yres,unsigned Depth)
28 if (lpddraw) VGA_Exit();
29 if (!lpddraw) {
30 DirectDrawCreate(NULL,&lpddraw,NULL);
31 if (!lpddraw) {
32 ERR(ddraw,"DirectDraw is not available\n");
33 return 1;
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);
38 lpddraw=NULL;
39 return 1;
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);
47 lpddraw=NULL;
48 return 1;
50 vga_refresh=0;
51 InitializeCriticalSection(&vga_crit);
52 /* poll every 20ms (50fps should provide adequate responsiveness) */
53 poll_timer = CreateSystemTimer( 20, (FARPROC16)VGA_Poll );
55 return 0;
58 int VGA_GetMode(unsigned*Height,unsigned*Width,unsigned*Depth)
60 if (!lpddraw) return 1;
61 if (!lpddsurf) return 1;
62 if (Height) *Height=sdesc.dwHeight;
63 if (Width) *Width=sdesc.dwWidth;
64 if (Depth) *Depth=sdesc.ddpfPixelFormat.x.dwRGBBitCount;
65 return 0;
68 void VGA_Exit(void)
70 if (lpddraw) {
71 SYSTEM_KillSystemTimer(poll_timer);
72 DeleteCriticalSection(&vga_crit);
73 lpddsurf->lpvtbl->fnRelease(lpddsurf);
74 lpddsurf=NULL;
75 lpddraw->lpvtbl->fnRelease(lpddraw);
76 lpddraw=NULL;
80 void VGA_SetPalette(PALETTEENTRY*pal,int start,int len)
82 if (!lpddraw) return;
83 lpddpal->lpvtbl->fnSetEntries(lpddpal,0,start,len,pal);
84 lpddsurf->lpvtbl->fnSetPalette(lpddsurf,lpddpal);
87 void VGA_SetQuadPalette(RGBQUAD*color,int start,int len)
89 PALETTEENTRY pal[256];
90 int c;
92 if (!lpddraw) return;
93 for (c=0; c<len; c++) {
94 pal[c].peRed =color[c].rgbRed;
95 pal[c].peGreen=color[c].rgbGreen;
96 pal[c].peBlue =color[c].rgbBlue;
97 pal[c].peFlags=0;
99 lpddpal->lpvtbl->fnSetEntries(lpddpal,0,start,len,pal);
100 lpddsurf->lpvtbl->fnSetPalette(lpddsurf,lpddpal);
103 LPSTR VGA_Lock(unsigned*Pitch,unsigned*Height,unsigned*Width,unsigned*Depth)
105 if (!lpddraw) return NULL;
106 if (!lpddsurf) return NULL;
107 if (lpddsurf->lpvtbl->fnLock(lpddsurf,NULL,&sdesc,0,0)) {
108 ERR(ddraw,"could not lock surface!\n");
109 return NULL;
111 if (Pitch) *Pitch=sdesc.lPitch;
112 if (Height) *Height=sdesc.dwHeight;
113 if (Width) *Width=sdesc.dwWidth;
114 if (Depth) *Depth=sdesc.ddpfPixelFormat.x.dwRGBBitCount;
115 return sdesc.y.lpSurface;
118 void VGA_Unlock(void)
120 lpddsurf->lpvtbl->fnUnlock(lpddsurf,sdesc.y.lpSurface);
123 void VGA_Poll(void)
125 char *dat;
126 unsigned Pitch,Height,Width;
127 char *surf;
128 int Y,X;
130 EnterCriticalSection(&vga_crit);
131 if (!vga_polling) {
132 vga_polling++;
133 LeaveCriticalSection(&vga_crit);
134 /* FIXME: optimize by doing this only if the data has actually changed
135 * (in a way similar to DIBSection, perhaps) */
136 surf = VGA_Lock(&Pitch,&Height,&Width,NULL);
137 if (!surf) return;
138 dat = DOSMEM_MapDosToLinear(0xa0000);
139 /* copy from virtual VGA frame buffer to DirectDraw surface */
140 for (Y=0; Y<Height; Y++,surf+=Pitch,dat+=Width) {
141 memcpy(surf,dat,Width);
142 for (X=0; X<Width; X++) if (dat[X]) TRACE(ddraw,"data(%d) at (%d,%d)\n",dat[X],X,Y);
144 VGA_Unlock();
145 vga_refresh=1;
146 EnterCriticalSection(&vga_crit);
147 vga_polling--;
149 LeaveCriticalSection(&vga_crit);
152 static BYTE palreg,palcnt;
153 static PALETTEENTRY paldat;
155 void VGA_ioport_out( WORD port, BYTE val )
157 switch (port) {
158 case 0x3c8:
159 palreg=val; palcnt=0; break;
160 case 0x3c9:
161 ((BYTE*)&paldat)[palcnt++]=val << 2;
162 if (palcnt==3) {
163 VGA_SetPalette(&paldat,palreg,1);
164 palreg++;
166 break;
170 BYTE VGA_ioport_in( WORD port )
172 BYTE ret;
174 switch (port) {
175 case 0x3da:
176 /* since we don't (yet?) serve DOS VM requests while VGA_Poll is running,
177 we need to fake the occurrence of the vertical refresh */
178 if (lpddraw) {
179 ret=vga_refresh?0x00:0x08;
180 vga_refresh=0;
181 } else ret=0x08;
182 break;
183 default:
184 ret=0xff;
186 return ret;