Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 1 | /* |
| 2 | * VGA hardware emulation |
| 3 | * |
| 4 | * Copyright 1998 Ove Kåven (with some help from Marcus Meissner) |
| 5 | * |
| 6 | */ |
| 7 | |
| 8 | #include <string.h> |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 9 | #include "winbase.h" |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 10 | #include "wincon.h" |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 11 | #include "miscemu.h" |
| 12 | #include "vga.h" |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 13 | #include "ddraw.h" |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 14 | #include "services.h" |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 15 | #include "debugtools.h" |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 16 | |
Dimitrie O. Paun | 529da54 | 2000-11-27 23:54:25 +0000 | [diff] [blame] | 17 | DEFAULT_DEBUG_CHANNEL(ddraw); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 18 | |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 19 | static IDirectDraw *lpddraw = NULL; |
| 20 | static IDirectDrawSurface *lpddsurf; |
| 21 | static IDirectDrawPalette *lpddpal; |
| 22 | static DDSURFACEDESC sdesc; |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 23 | static LONG vga_polling,vga_refresh; |
| 24 | static HANDLE poll_timer; |
| 25 | |
François Gouget | c583b68 | 2001-01-05 03:44:40 +0000 | [diff] [blame] | 26 | typedef HRESULT WINAPI (*DirectDrawCreateProc)(LPGUID,LPDIRECTDRAW *,LPUNKNOWN); |
| 27 | static DirectDrawCreateProc pDirectDrawCreate; |
Alexandre Julliard | ddce652 | 2000-03-17 16:58:10 +0000 | [diff] [blame] | 28 | |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 29 | static void VGA_DeinstallTimer(void) |
| 30 | { |
| 31 | if (poll_timer) { |
| 32 | SERVICE_Delete( poll_timer ); |
| 33 | poll_timer = 0; |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | static void VGA_InstallTimer(unsigned Rate) |
| 38 | { |
| 39 | VGA_DeinstallTimer(); |
| 40 | if (!poll_timer) |
| 41 | poll_timer = SERVICE_AddTimer( Rate, VGA_Poll, 0 ); |
| 42 | } |
| 43 | |
| 44 | HANDLE VGA_AlphaConsole(void) |
| 45 | { |
| 46 | /* this assumes that no Win32 redirection has taken place, but then again, |
| 47 | * only 16-bit apps are likely to use this part of Wine... */ |
| 48 | return GetStdHandle(STD_OUTPUT_HANDLE); |
| 49 | } |
| 50 | |
Ove Kaaven | 3be104e | 2000-05-23 21:14:11 +0000 | [diff] [blame] | 51 | char*VGA_AlphaBuffer(void) |
| 52 | { |
| 53 | return DOSMEM_MapDosToLinear(0xb8000); |
| 54 | } |
| 55 | |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 56 | /*** GRAPHICS MODE ***/ |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 57 | |
| 58 | int VGA_SetMode(unsigned Xres,unsigned Yres,unsigned Depth) |
| 59 | { |
| 60 | if (lpddraw) VGA_Exit(); |
| 61 | if (!lpddraw) { |
Alexandre Julliard | ddce652 | 2000-03-17 16:58:10 +0000 | [diff] [blame] | 62 | if (!pDirectDrawCreate) |
| 63 | { |
| 64 | HMODULE hmod = LoadLibraryA( "ddraw.dll" ); |
François Gouget | c583b68 | 2001-01-05 03:44:40 +0000 | [diff] [blame] | 65 | if (hmod) pDirectDrawCreate = (DirectDrawCreateProc)GetProcAddress( hmod, "DirectDrawCreate" ); |
Alexandre Julliard | ddce652 | 2000-03-17 16:58:10 +0000 | [diff] [blame] | 66 | } |
| 67 | if (pDirectDrawCreate) pDirectDrawCreate(NULL,&lpddraw,NULL); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 68 | if (!lpddraw) { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 69 | ERR("DirectDraw is not available\n"); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 70 | return 1; |
| 71 | } |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 72 | if (IDirectDraw_SetDisplayMode(lpddraw,Xres,Yres,Depth)) { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 73 | ERR("DirectDraw does not support requested display mode\n"); |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 74 | IDirectDraw_Release(lpddraw); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 75 | lpddraw=NULL; |
| 76 | return 1; |
| 77 | } |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 78 | IDirectDraw_CreatePalette(lpddraw,DDPCAPS_8BIT,NULL,&lpddpal,NULL); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 79 | memset(&sdesc,0,sizeof(sdesc)); |
| 80 | sdesc.dwSize=sizeof(sdesc); |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 81 | sdesc.dwFlags = DDSD_CAPS; |
| 82 | sdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 83 | if (IDirectDraw_CreateSurface(lpddraw,&sdesc,&lpddsurf,NULL)||(!lpddsurf)) { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 84 | ERR("DirectDraw surface is not available\n"); |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 85 | IDirectDraw_Release(lpddraw); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 86 | lpddraw=NULL; |
| 87 | return 1; |
| 88 | } |
Ove Kaaven | 3be104e | 2000-05-23 21:14:11 +0000 | [diff] [blame] | 89 | FIXME("no default palette entries\n"); |
| 90 | IDirectDrawSurface_SetPalette(lpddsurf,lpddpal); |
Ove Kaaven | 194cfed | 1998-11-08 15:06:31 +0000 | [diff] [blame] | 91 | vga_refresh=0; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 92 | /* poll every 20ms (50fps should provide adequate responsiveness) */ |
Alexandre Julliard | 8c8237b | 2000-05-10 04:43:32 +0000 | [diff] [blame] | 93 | VGA_InstallTimer(20); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 94 | } |
| 95 | return 0; |
| 96 | } |
| 97 | |
| 98 | int VGA_GetMode(unsigned*Height,unsigned*Width,unsigned*Depth) |
| 99 | { |
| 100 | if (!lpddraw) return 1; |
| 101 | if (!lpddsurf) return 1; |
| 102 | if (Height) *Height=sdesc.dwHeight; |
| 103 | if (Width) *Width=sdesc.dwWidth; |
Alexandre Julliard | d6c0f9f | 2001-01-04 22:44:55 +0000 | [diff] [blame] | 104 | if (Depth) *Depth=sdesc.ddpfPixelFormat.u1.dwRGBBitCount; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 105 | return 0; |
| 106 | } |
| 107 | |
| 108 | void VGA_Exit(void) |
| 109 | { |
| 110 | if (lpddraw) { |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 111 | VGA_DeinstallTimer(); |
Ove Kaaven | 3be104e | 2000-05-23 21:14:11 +0000 | [diff] [blame] | 112 | IDirectDrawSurface_SetPalette(lpddsurf,NULL); |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 113 | IDirectDrawSurface_Release(lpddsurf); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 114 | lpddsurf=NULL; |
Ove Kaaven | 3be104e | 2000-05-23 21:14:11 +0000 | [diff] [blame] | 115 | IDirectDrawPalette_Release(lpddpal); |
| 116 | lpddpal=NULL; |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 117 | IDirectDraw_Release(lpddraw); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 118 | lpddraw=NULL; |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | void VGA_SetPalette(PALETTEENTRY*pal,int start,int len) |
| 123 | { |
| 124 | if (!lpddraw) return; |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 125 | IDirectDrawPalette_SetEntries(lpddpal,0,start,len,pal); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | void VGA_SetQuadPalette(RGBQUAD*color,int start,int len) |
| 129 | { |
| 130 | PALETTEENTRY pal[256]; |
| 131 | int c; |
| 132 | |
| 133 | if (!lpddraw) return; |
| 134 | for (c=0; c<len; c++) { |
| 135 | pal[c].peRed =color[c].rgbRed; |
| 136 | pal[c].peGreen=color[c].rgbGreen; |
| 137 | pal[c].peBlue =color[c].rgbBlue; |
| 138 | pal[c].peFlags=0; |
| 139 | } |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 140 | IDirectDrawPalette_SetEntries(lpddpal,0,start,len,pal); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | LPSTR VGA_Lock(unsigned*Pitch,unsigned*Height,unsigned*Width,unsigned*Depth) |
| 144 | { |
| 145 | if (!lpddraw) return NULL; |
| 146 | if (!lpddsurf) return NULL; |
Francois Gouget | f44e3e9 | 1999-03-27 16:49:55 +0000 | [diff] [blame] | 147 | if (IDirectDrawSurface_Lock(lpddsurf,NULL,&sdesc,0,0)) { |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 148 | ERR("could not lock surface!\n"); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 149 | return NULL; |
| 150 | } |
Alexandre Julliard | d6c0f9f | 2001-01-04 22:44:55 +0000 | [diff] [blame] | 151 | if (Pitch) *Pitch=sdesc.u1.lPitch; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 152 | if (Height) *Height=sdesc.dwHeight; |
| 153 | if (Width) *Width=sdesc.dwWidth; |
Alexandre Julliard | d6c0f9f | 2001-01-04 22:44:55 +0000 | [diff] [blame] | 154 | if (Depth) *Depth=sdesc.ddpfPixelFormat.u1.dwRGBBitCount; |
| 155 | return sdesc.lpSurface; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | void VGA_Unlock(void) |
| 159 | { |
Alexandre Julliard | d6c0f9f | 2001-01-04 22:44:55 +0000 | [diff] [blame] | 160 | IDirectDrawSurface_Unlock(lpddsurf,sdesc.lpSurface); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 161 | } |
| 162 | |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 163 | /*** TEXT MODE ***/ |
| 164 | |
| 165 | int VGA_SetAlphaMode(unsigned Xres,unsigned Yres) |
| 166 | { |
| 167 | COORD siz; |
| 168 | |
| 169 | if (lpddraw) VGA_Exit(); |
| 170 | |
| 171 | /* the xterm is slow, so refresh only every 200ms (5fps) */ |
Alexandre Julliard | 8c8237b | 2000-05-10 04:43:32 +0000 | [diff] [blame] | 172 | VGA_InstallTimer(200); |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 173 | |
Alexandre Julliard | f818d42 | 2000-05-03 17:48:21 +0000 | [diff] [blame] | 174 | siz.X = Xres; |
| 175 | siz.Y = Yres; |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 176 | SetConsoleScreenBufferSize(VGA_AlphaConsole(),siz); |
| 177 | return 0; |
| 178 | } |
| 179 | |
| 180 | void VGA_GetAlphaMode(unsigned*Xres,unsigned*Yres) |
| 181 | { |
| 182 | CONSOLE_SCREEN_BUFFER_INFO info; |
| 183 | GetConsoleScreenBufferInfo(VGA_AlphaConsole(),&info); |
Alexandre Julliard | f818d42 | 2000-05-03 17:48:21 +0000 | [diff] [blame] | 184 | if (Xres) *Xres=info.dwSize.X; |
| 185 | if (Yres) *Yres=info.dwSize.Y; |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | void VGA_SetCursorPos(unsigned X,unsigned Y) |
| 189 | { |
| 190 | COORD pos; |
| 191 | |
Alexandre Julliard | f818d42 | 2000-05-03 17:48:21 +0000 | [diff] [blame] | 192 | pos.X = X; |
| 193 | pos.Y = Y; |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 194 | SetConsoleCursorPosition(VGA_AlphaConsole(),pos); |
| 195 | } |
| 196 | |
| 197 | void VGA_GetCursorPos(unsigned*X,unsigned*Y) |
| 198 | { |
| 199 | CONSOLE_SCREEN_BUFFER_INFO info; |
| 200 | GetConsoleScreenBufferInfo(VGA_AlphaConsole(),&info); |
Alexandre Julliard | f818d42 | 2000-05-03 17:48:21 +0000 | [diff] [blame] | 201 | if (X) *X=info.dwCursorPosition.X; |
| 202 | if (Y) *Y=info.dwCursorPosition.Y; |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 203 | } |
| 204 | |
Ove Kaaven | 3be104e | 2000-05-23 21:14:11 +0000 | [diff] [blame] | 205 | void VGA_WriteChars(unsigned X,unsigned Y,unsigned ch,int attr,int count) |
| 206 | { |
| 207 | unsigned XR, YR; |
| 208 | char*dat; |
| 209 | |
| 210 | VGA_GetAlphaMode(&XR, &YR); |
| 211 | dat = VGA_AlphaBuffer() + ((XR*Y + X) * 2); |
| 212 | /* FIXME: also call WriteConsoleOutputA, for better responsiveness */ |
| 213 | while (count--) { |
| 214 | *dat++ = ch; |
| 215 | if (attr>=0) *dat = attr; |
| 216 | dat++; |
| 217 | } |
| 218 | } |
| 219 | |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 220 | /*** CONTROL ***/ |
| 221 | |
| 222 | void CALLBACK VGA_Poll( ULONG_PTR arg ) |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 223 | { |
| 224 | char *dat; |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 225 | unsigned int Pitch,Height,Width,Y,X; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 226 | char *surf; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 227 | |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 228 | if (!InterlockedExchangeAdd(&vga_polling, 1)) { |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 229 | /* FIXME: optimize by doing this only if the data has actually changed |
| 230 | * (in a way similar to DIBSection, perhaps) */ |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 231 | if (lpddraw) { |
| 232 | /* graphics mode */ |
| 233 | surf = VGA_Lock(&Pitch,&Height,&Width,NULL); |
| 234 | if (!surf) return; |
| 235 | dat = DOSMEM_MapDosToLinear(0xa0000); |
| 236 | /* copy from virtual VGA frame buffer to DirectDraw surface */ |
| 237 | for (Y=0; Y<Height; Y++,surf+=Pitch,dat+=Width) { |
| 238 | memcpy(surf,dat,Width); |
| 239 | /*for (X=0; X<Width; X++) if (dat[X]) TRACE(ddraw,"data(%d) at (%d,%d)\n",dat[X],X,Y);*/ |
| 240 | } |
| 241 | VGA_Unlock(); |
| 242 | } else { |
| 243 | /* text mode */ |
| 244 | CHAR_INFO ch[80]; |
| 245 | COORD siz, off; |
| 246 | SMALL_RECT dest; |
| 247 | HANDLE con = VGA_AlphaConsole(); |
| 248 | |
| 249 | VGA_GetAlphaMode(&Width,&Height); |
Ove Kaaven | 3be104e | 2000-05-23 21:14:11 +0000 | [diff] [blame] | 250 | dat = VGA_AlphaBuffer(); |
Alexandre Julliard | f818d42 | 2000-05-03 17:48:21 +0000 | [diff] [blame] | 251 | siz.X = 80; siz.Y = 1; |
| 252 | off.X = 0; off.Y = 0; |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 253 | /* copy from virtual VGA frame buffer to console */ |
| 254 | for (Y=0; Y<Height; Y++) { |
| 255 | dest.Top=Y; dest.Bottom=Y; |
| 256 | for (X=0; X<Width; X++) { |
| 257 | ch[X].Char.AsciiChar = *dat++; |
Andreas Mohr | 744134e | 2000-10-12 20:41:29 +0000 | [diff] [blame] | 258 | /* WriteConsoleOutputA doesn't like "dead" chars */ |
| 259 | if (ch[X].Char.AsciiChar == '\0') |
| 260 | ch[X].Char.AsciiChar = ' '; |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 261 | ch[X].Attributes = *dat++; |
| 262 | } |
| 263 | dest.Left=0; dest.Right=Width+1; |
| 264 | WriteConsoleOutputA(con, ch, siz, off, &dest); |
| 265 | } |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 266 | } |
Ove Kaaven | 194cfed | 1998-11-08 15:06:31 +0000 | [diff] [blame] | 267 | vga_refresh=1; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 268 | } |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 269 | InterlockedDecrement(&vga_polling); |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | static BYTE palreg,palcnt; |
| 273 | static PALETTEENTRY paldat; |
| 274 | |
| 275 | void VGA_ioport_out( WORD port, BYTE val ) |
| 276 | { |
| 277 | switch (port) { |
| 278 | case 0x3c8: |
| 279 | palreg=val; palcnt=0; break; |
| 280 | case 0x3c9: |
| 281 | ((BYTE*)&paldat)[palcnt++]=val << 2; |
| 282 | if (palcnt==3) { |
Ove Kaaven | e1848e5 | 1999-03-14 12:23:17 +0000 | [diff] [blame] | 283 | VGA_SetPalette(&paldat,palreg++,1); |
| 284 | palcnt=0; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 285 | } |
Ove Kaaven | 194cfed | 1998-11-08 15:06:31 +0000 | [diff] [blame] | 286 | break; |
Ove Kaaven | 1499a84 | 1998-11-01 12:51:47 +0000 | [diff] [blame] | 287 | } |
| 288 | } |
Ove Kaaven | 194cfed | 1998-11-08 15:06:31 +0000 | [diff] [blame] | 289 | |
| 290 | BYTE VGA_ioport_in( WORD port ) |
| 291 | { |
| 292 | BYTE ret; |
| 293 | |
| 294 | switch (port) { |
| 295 | case 0x3da: |
| 296 | /* since we don't (yet?) serve DOS VM requests while VGA_Poll is running, |
| 297 | we need to fake the occurrence of the vertical refresh */ |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 298 | ret=vga_refresh?0x00:0x08; |
| 299 | vga_refresh=0; |
Ove Kaaven | 194cfed | 1998-11-08 15:06:31 +0000 | [diff] [blame] | 300 | break; |
| 301 | default: |
| 302 | ret=0xff; |
| 303 | } |
| 304 | return ret; |
| 305 | } |
Ove Kaaven | c9307ed | 2000-02-03 00:46:29 +0000 | [diff] [blame] | 306 | |
| 307 | void VGA_Clean(void) |
| 308 | { |
| 309 | VGA_Exit(); |
| 310 | VGA_DeinstallTimer(); |
| 311 | } |