summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/vid_vga.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/vid_vga.c')
-rw-r--r--apps/plugins/sdl/progs/quake/vid_vga.c478
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/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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
34extern regs_t regs;
35
36int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes;
37byte *VGA_pagebase;
38vmode_t *VGA_pcurmode;
39
40static int VGA_planar;
41static int VGA_numpages;
42static int VGA_buffersize;
43
44void *vid_surfcache;
45int vid_surfcachesize;
46
47int VGA_highhunkmark;
48
49#include "vgamodes.h"
50
51#define NUMVIDMODES (sizeof(vgavidmodes) / sizeof(vgavidmodes[0]))
52
53void VGA_UpdatePlanarScreen (void *srcbuffer);
54
55static byte backingbuf[48*24];
56
57/*
58================
59VGA_BeginDirectRect
60================
61*/
62void 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================
130VGA_EndDirectRect
131================
132*/
133void 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================
191VGA_Init
192================
193*/
194void 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================
214VGA_WaitVsync
215================
216*/
217void VGA_WaitVsync (void)
218{
219 while ((inportb (0x3DA) & 0x08) == 0)
220 ;
221}
222
223
224/*
225================
226VGA_ClearVideoMem
227================
228*/
229void 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================
244VGA_FreeAndAllocVidbuffer
245================
246*/
247qboolean 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================
307VGA_CheckAdequateMem
308================
309*/
310qboolean 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================
339VGA_InitMode
340================
341*/
342int 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================
408VGA_SetPalette
409================
410*/
411void 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================
427VGA_SwapBuffersCopy
428================
429*/
430void 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================
466VGA_SwapBuffers
467================
468*/
469void 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