diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/vid_vga.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/vid_vga.c | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/vid_vga.c b/apps/plugins/sdl/progs/quake/vid_vga.c new file mode 100644 index 0000000000..6fbec9de5c --- /dev/null +++ b/apps/plugins/sdl/progs/quake/vid_vga.c | |||
@@ -0,0 +1,478 @@ | |||
1 | /* | ||
2 | Copyright (C) 1996-1997 Id Software, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License | ||
6 | as published by the Free Software Foundation; either version 2 | ||
7 | of the License, or (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | |||
13 | See the GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | |||
19 | */ | ||
20 | // | ||
21 | // vid_vga.c: VGA-specific DOS video stuff | ||
22 | // | ||
23 | |||
24 | // TODO: proper handling of page-swap failure | ||
25 | |||
26 | #include <dos.h> | ||
27 | |||
28 | #include "quakedef.h" | ||
29 | #include "d_local.h" | ||
30 | #include "dosisms.h" | ||
31 | #include "vid_dos.h" | ||
32 | #include <dpmi.h> | ||
33 | |||
34 | extern regs_t regs; | ||
35 | |||
36 | int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes; | ||
37 | byte *VGA_pagebase; | ||
38 | vmode_t *VGA_pcurmode; | ||
39 | |||
40 | static int VGA_planar; | ||
41 | static int VGA_numpages; | ||
42 | static int VGA_buffersize; | ||
43 | |||
44 | void *vid_surfcache; | ||
45 | int vid_surfcachesize; | ||
46 | |||
47 | int VGA_highhunkmark; | ||
48 | |||
49 | #include "vgamodes.h" | ||
50 | |||
51 | #define NUMVIDMODES (sizeof(vgavidmodes) / sizeof(vgavidmodes[0])) | ||
52 | |||
53 | void VGA_UpdatePlanarScreen (void *srcbuffer); | ||
54 | |||
55 | static byte backingbuf[48*24]; | ||
56 | |||
57 | /* | ||
58 | ================ | ||
59 | VGA_BeginDirectRect | ||
60 | ================ | ||
61 | */ | ||
62 | void VGA_BeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, | ||
63 | int y, byte *pbitmap, int width, int height) | ||
64 | { | ||
65 | int i, j, k, plane, reps, repshift; | ||
66 | |||
67 | if (!lvid->direct) | ||
68 | return; | ||
69 | |||
70 | if (lvid->aspect > 1.5) | ||
71 | { | ||
72 | reps = 2; | ||
73 | repshift = 1; | ||
74 | } | ||
75 | else | ||
76 | { | ||
77 | reps = 1; | ||
78 | repshift = 0; | ||
79 | } | ||
80 | |||
81 | if (pcurrentmode->planar) | ||
82 | { | ||
83 | for (plane=0 ; plane<4 ; plane++) | ||
84 | { | ||
85 | // select the correct plane for reading and writing | ||
86 | outportb (SC_INDEX, MAP_MASK); | ||
87 | outportb (SC_DATA, 1 << plane); | ||
88 | outportb (GC_INDEX, READ_MAP); | ||
89 | outportb (GC_DATA, plane); | ||
90 | |||
91 | for (i=0 ; i<(height << repshift) ; i += reps) | ||
92 | { | ||
93 | for (k=0 ; k<reps ; k++) | ||
94 | { | ||
95 | for (j=0 ; j<(width >> 2) ; j++) | ||
96 | { | ||
97 | backingbuf[(i + k) * 24 + (j << 2) + plane] = | ||
98 | lvid->direct[(y + i + k) * VGA_rowbytes + | ||
99 | (x >> 2) + j]; | ||
100 | lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] = | ||
101 | pbitmap[(i >> repshift) * 24 + | ||
102 | (j << 2) + plane]; | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | for (i=0 ; i<(height << repshift) ; i += reps) | ||
111 | { | ||
112 | for (j=0 ; j<reps ; j++) | ||
113 | { | ||
114 | memcpy (&backingbuf[(i + j) * 24], | ||
115 | lvid->direct + x + ((y << repshift) + i + j) * | ||
116 | VGA_rowbytes, | ||
117 | width); | ||
118 | memcpy (lvid->direct + x + ((y << repshift) + i + j) * | ||
119 | VGA_rowbytes, | ||
120 | &pbitmap[(i >> repshift) * width], | ||
121 | width); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | |||
127 | |||
128 | /* | ||
129 | ================ | ||
130 | VGA_EndDirectRect | ||
131 | ================ | ||
132 | */ | ||
133 | void VGA_EndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, | ||
134 | int y, int width, int height) | ||
135 | { | ||
136 | int i, j, k, plane, reps, repshift; | ||
137 | |||
138 | if (!lvid->direct) | ||
139 | return; | ||
140 | |||
141 | if (lvid->aspect > 1.5) | ||
142 | { | ||
143 | reps = 2; | ||
144 | repshift = 1; | ||
145 | } | ||
146 | else | ||
147 | { | ||
148 | reps = 1; | ||
149 | repshift = 0; | ||
150 | } | ||
151 | |||
152 | if (pcurrentmode->planar) | ||
153 | { | ||
154 | for (plane=0 ; plane<4 ; plane++) | ||
155 | { | ||
156 | // select the correct plane for writing | ||
157 | outportb (SC_INDEX, MAP_MASK); | ||
158 | outportb (SC_DATA, 1 << plane); | ||
159 | |||
160 | for (i=0 ; i<(height << repshift) ; i += reps) | ||
161 | { | ||
162 | for (k=0 ; k<reps ; k++) | ||
163 | { | ||
164 | for (j=0 ; j<(width >> 2) ; j++) | ||
165 | { | ||
166 | lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] = | ||
167 | backingbuf[(i + k) * 24 + (j << 2) + plane]; | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | for (i=0 ; i<(height << repshift) ; i += reps) | ||
176 | { | ||
177 | for (j=0 ; j<reps ; j++) | ||
178 | { | ||
179 | memcpy (lvid->direct + x + ((y << repshift) + i + j) * | ||
180 | VGA_rowbytes, | ||
181 | &backingbuf[(i + j) * 24], | ||
182 | width); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | |||
188 | |||
189 | /* | ||
190 | ================ | ||
191 | VGA_Init | ||
192 | ================ | ||
193 | */ | ||
194 | void VGA_Init (void) | ||
195 | { | ||
196 | int i; | ||
197 | |||
198 | // link together all the VGA modes | ||
199 | for (i=0 ; i<(NUMVIDMODES - 1) ; i++) | ||
200 | { | ||
201 | vgavidmodes[i].pnext = &vgavidmodes[i+1]; | ||
202 | } | ||
203 | |||
204 | // add the VGA modes at the start of the mode list | ||
205 | vgavidmodes[NUMVIDMODES-1].pnext = pvidmodes; | ||
206 | pvidmodes = &vgavidmodes[0]; | ||
207 | |||
208 | numvidmodes += NUMVIDMODES; | ||
209 | } | ||
210 | |||
211 | |||
212 | /* | ||
213 | ================ | ||
214 | VGA_WaitVsync | ||
215 | ================ | ||
216 | */ | ||
217 | void VGA_WaitVsync (void) | ||
218 | { | ||
219 | while ((inportb (0x3DA) & 0x08) == 0) | ||
220 | ; | ||
221 | } | ||
222 | |||
223 | |||
224 | /* | ||
225 | ================ | ||
226 | VGA_ClearVideoMem | ||
227 | ================ | ||
228 | */ | ||
229 | void VGA_ClearVideoMem (int planar) | ||
230 | { | ||
231 | |||
232 | if (planar) | ||
233 | { | ||
234 | // enable all planes for writing | ||
235 | outportb (SC_INDEX, MAP_MASK); | ||
236 | outportb (SC_DATA, 0x0F); | ||
237 | } | ||
238 | |||
239 | Q_memset (VGA_pagebase, 0, VGA_rowbytes * VGA_height); | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | ================ | ||
244 | VGA_FreeAndAllocVidbuffer | ||
245 | ================ | ||
246 | */ | ||
247 | qboolean VGA_FreeAndAllocVidbuffer (viddef_t *lvid, int allocnewbuffer) | ||
248 | { | ||
249 | int tsize, tbuffersize; | ||
250 | |||
251 | if (allocnewbuffer) | ||
252 | { | ||
253 | // alloc an extra line in case we want to wrap, and allocate the z-buffer | ||
254 | tbuffersize = (lvid->rowbytes * (lvid->height + 1)) + | ||
255 | (lvid->width * lvid->height * sizeof (*d_pzbuffer)); | ||
256 | } | ||
257 | else | ||
258 | { | ||
259 | // just allocate the z-buffer | ||
260 | tbuffersize = lvid->width * lvid->height * sizeof (*d_pzbuffer); | ||
261 | } | ||
262 | |||
263 | tsize = D_SurfaceCacheForRes (lvid->width, lvid->height); | ||
264 | |||
265 | tbuffersize += tsize; | ||
266 | |||
267 | // see if there's enough memory, allowing for the normal mode 0x13 pixel, | ||
268 | // z, and surface buffers | ||
269 | if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + | ||
270 | 0x10000 * 3) < minimum_memory) | ||
271 | { | ||
272 | Con_Printf ("Not enough memory for video mode\n"); | ||
273 | VGA_pcurmode = NULL; // so no further accesses to the buffer are | ||
274 | // attempted, particularly when clearing | ||
275 | return false; // not enough memory for mode | ||
276 | } | ||
277 | |||
278 | VGA_buffersize = tbuffersize; | ||
279 | vid_surfcachesize = tsize; | ||
280 | |||
281 | if (d_pzbuffer) | ||
282 | { | ||
283 | D_FlushCaches (); | ||
284 | Hunk_FreeToHighMark (VGA_highhunkmark); | ||
285 | d_pzbuffer = NULL; | ||
286 | } | ||
287 | |||
288 | VGA_highhunkmark = Hunk_HighMark (); | ||
289 | |||
290 | d_pzbuffer = Hunk_HighAllocName (VGA_buffersize, "video"); | ||
291 | |||
292 | vid_surfcache = (byte *)d_pzbuffer | ||
293 | + lvid->width * lvid->height * sizeof (*d_pzbuffer); | ||
294 | |||
295 | if (allocnewbuffer) | ||
296 | { | ||
297 | lvid->buffer = (void *)( (byte *)vid_surfcache + vid_surfcachesize); | ||
298 | lvid->conbuffer = lvid->buffer; | ||
299 | } | ||
300 | |||
301 | return true; | ||
302 | } | ||
303 | |||
304 | |||
305 | /* | ||
306 | ================ | ||
307 | VGA_CheckAdequateMem | ||
308 | ================ | ||
309 | */ | ||
310 | qboolean VGA_CheckAdequateMem (int width, int height, int rowbytes, | ||
311 | int allocnewbuffer) | ||
312 | { | ||
313 | int tbuffersize; | ||
314 | |||
315 | tbuffersize = width * height * sizeof (*d_pzbuffer); | ||
316 | |||
317 | if (allocnewbuffer) | ||
318 | { | ||
319 | // alloc an extra line in case we want to wrap, and allocate the z-buffer | ||
320 | tbuffersize += (rowbytes * (height + 1)); | ||
321 | } | ||
322 | |||
323 | tbuffersize += D_SurfaceCacheForRes (width, height); | ||
324 | |||
325 | // see if there's enough memory, allowing for the normal mode 0x13 pixel, | ||
326 | // z, and surface buffers | ||
327 | if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + | ||
328 | 0x10000 * 3) < minimum_memory) | ||
329 | { | ||
330 | return false; // not enough memory for mode | ||
331 | } | ||
332 | |||
333 | return true; | ||
334 | } | ||
335 | |||
336 | |||
337 | /* | ||
338 | ================ | ||
339 | VGA_InitMode | ||
340 | ================ | ||
341 | */ | ||
342 | int VGA_InitMode (viddef_t *lvid, vmode_t *pcurrentmode) | ||
343 | { | ||
344 | vextra_t *pextra; | ||
345 | |||
346 | pextra = pcurrentmode->pextradata; | ||
347 | |||
348 | if (!VGA_FreeAndAllocVidbuffer (lvid, pextra->vidbuffer)) | ||
349 | return -1; // memory alloc failed | ||
350 | |||
351 | if (VGA_pcurmode) | ||
352 | VGA_ClearVideoMem (VGA_pcurmode->planar); | ||
353 | |||
354 | // mode 0x13 is the base for all the Mode X-class mode sets | ||
355 | regs.h.ah = 0; | ||
356 | regs.h.al = 0x13; | ||
357 | dos_int86(0x10); | ||
358 | |||
359 | VGA_pagebase = (void *)real2ptr(0xa0000); | ||
360 | lvid->direct = (pixel_t *)VGA_pagebase; | ||
361 | |||
362 | // set additional registers as needed | ||
363 | VideoRegisterSet (pextra->pregset); | ||
364 | |||
365 | VGA_numpages = 1; | ||
366 | lvid->numpages = VGA_numpages; | ||
367 | |||
368 | VGA_width = (lvid->width + 0x1F) & ~0x1F; | ||
369 | VGA_height = lvid->height; | ||
370 | VGA_planar = pcurrentmode->planar; | ||
371 | if (VGA_planar) | ||
372 | VGA_rowbytes = lvid->rowbytes / 4; | ||
373 | else | ||
374 | VGA_rowbytes = lvid->rowbytes; | ||
375 | VGA_bufferrowbytes = lvid->rowbytes; | ||
376 | lvid->colormap = host_colormap; | ||
377 | lvid->fullbright = 256 - LittleLong (*((int *)lvid->colormap + 2048)); | ||
378 | |||
379 | lvid->maxwarpwidth = WARP_WIDTH; | ||
380 | lvid->maxwarpheight = WARP_HEIGHT; | ||
381 | |||
382 | lvid->conbuffer = lvid->buffer; | ||
383 | lvid->conrowbytes = lvid->rowbytes; | ||
384 | lvid->conwidth = lvid->width; | ||
385 | lvid->conheight = lvid->height; | ||
386 | |||
387 | VGA_pcurmode = pcurrentmode; | ||
388 | |||
389 | VGA_ClearVideoMem (pcurrentmode->planar); | ||
390 | |||
391 | if (_vid_wait_override.value) | ||
392 | { | ||
393 | Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC); | ||
394 | } | ||
395 | else | ||
396 | { | ||
397 | Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE); | ||
398 | } | ||
399 | |||
400 | D_InitCaches (vid_surfcache, vid_surfcachesize); | ||
401 | |||
402 | return 1; | ||
403 | } | ||
404 | |||
405 | |||
406 | /* | ||
407 | ================ | ||
408 | VGA_SetPalette | ||
409 | ================ | ||
410 | */ | ||
411 | void VGA_SetPalette(viddef_t *lvid, vmode_t *pcurrentmode, unsigned char *pal) | ||
412 | { | ||
413 | int shiftcomponents=2; | ||
414 | int i; | ||
415 | |||
416 | UNUSED(lvid); | ||
417 | UNUSED(pcurrentmode); | ||
418 | |||
419 | dos_outportb(0x3c8, 0); | ||
420 | for (i=0 ; i<768 ; i++) | ||
421 | outportb(0x3c9, pal[i]>>shiftcomponents); | ||
422 | } | ||
423 | |||
424 | |||
425 | /* | ||
426 | ================ | ||
427 | VGA_SwapBuffersCopy | ||
428 | ================ | ||
429 | */ | ||
430 | void VGA_SwapBuffersCopy (viddef_t *lvid, vmode_t *pcurrentmode, | ||
431 | vrect_t *rects) | ||
432 | { | ||
433 | |||
434 | UNUSED(pcurrentmode); | ||
435 | |||
436 | // TODO: can write a dword at a time | ||
437 | // TODO: put in ASM | ||
438 | // TODO: copy only specified rectangles | ||
439 | if (VGA_planar) | ||
440 | { | ||
441 | |||
442 | // TODO: copy only specified rectangles | ||
443 | |||
444 | VGA_UpdatePlanarScreen (lvid->buffer); | ||
445 | } | ||
446 | else | ||
447 | { | ||
448 | while (rects) | ||
449 | { | ||
450 | VGA_UpdateLinearScreen ( | ||
451 | lvid->buffer + rects->x + (rects->y * lvid->rowbytes), | ||
452 | VGA_pagebase + rects->x + (rects->y * VGA_rowbytes), | ||
453 | rects->width, | ||
454 | rects->height, | ||
455 | lvid->rowbytes, | ||
456 | VGA_rowbytes); | ||
457 | |||
458 | rects = rects->pnext; | ||
459 | } | ||
460 | } | ||
461 | } | ||
462 | |||
463 | |||
464 | /* | ||
465 | ================ | ||
466 | VGA_SwapBuffers | ||
467 | ================ | ||
468 | */ | ||
469 | void VGA_SwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode, vrect_t *rects) | ||
470 | { | ||
471 | UNUSED(lvid); | ||
472 | |||
473 | if (vid_wait.value == VID_WAIT_VSYNC) | ||
474 | VGA_WaitVsync (); | ||
475 | |||
476 | VGA_SwapBuffersCopy (lvid, pcurrentmode, rects); | ||
477 | } | ||
478 | |||