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_ext.c: extended video modes
22 // in this implementation, VESA-specific DOS video stuff
23 //
24
25 // TODO: make dependencies on vid_vga.c explicit or eliminate them
26
27 #include <stdlib.h>
28 #include <dos.h>
29
30 #include "quakedef.h"
31 #include "d_local.h"
32 #include "dosisms.h"
33 #include "vid_dos.h"
34 #include <dpmi.h>
35
36 #define MODE_SUPPORTED_IN_HW 0x0001
37 #define COLOR_MODE 0x0008
38 #define GRAPHICS_MODE 0x0010
39 #define VGA_INCOMPATIBLE 0x0020
40 #define LINEAR_FRAME_BUFFER 0x0080
41
42 #define LINEAR_MODE 0x4000
43
44 #define VESA_DONT_WAIT_VSYNC 0 // when page flipping
45 #define VESA_WAIT_VSYNC 0x80
46
47 #define MAX_VESA_MODES 30 // we'll just take the first 30 if there
48 // are more
49 typedef struct {
50 int pages[3]; // either 2 or 3 is valid
51 int vesamode; // LINEAR_MODE set if linear mode
52 void *plinearmem; // linear address of start of frame buffer
53 qboolean vga_incompatible;
54 } vesa_extra_t;
55
56 static vmode_t vesa_modes[MAX_VESA_MODES] =
57 {{NULL, NULL, " ********* VESA modes ********* "}};
58 static vesa_extra_t vesa_extra[MAX_VESA_MODES];
59 static char names[MAX_VESA_MODES][10];
60
61 extern regs_t regs;
62
63 static int VID_currentpage;
64 static int VID_displayedpage;
65 static int *VID_pagelist;
66 static byte *VID_membase;
67 static int VID_banked;
68
69 typedef struct
70 {
71 int modenum;
72 int mode_attributes;
73 int winasegment;
74 int winbsegment;
75 int bytes_per_scanline; // bytes per logical scanline (+16)
76 int win; // window number (A=0, B=1)
77 int win_size; // window size (+6)
78 int granularity; // how finely i can set the window in vid mem (+4)
79 int width, height; // displayed width and height (+18, +20)
80 int bits_per_pixel; // er, better be 8, 15, 16, 24, or 32 (+25)
81 int bytes_per_pixel; // er, better be 1, 2, or 4
82 int memory_model; // and better be 4 or 6, packed or direct color (+27)
83 int num_pages; // number of complete frame buffer pages (+29)
84 int red_width; // the # of bits in the red component (+31)
85 int red_pos; // the bit position of the red component (+32)
86 int green_width; // etc.. (+33)
87 int green_pos; // (+34)
88 int blue_width; // (+35)
89 int blue_pos; // (+36)
90 int pptr;
91 int pagesize;
92 int numpages;
93 } modeinfo_t;
94
95 static modeinfo_t modeinfo;
96
97 // all bytes to avoid problems with compiler field packing
98 typedef struct vbeinfoblock_s {
99 byte VbeSignature[4];
100 byte VbeVersion[2];
101 byte OemStringPtr[4];
102 byte Capabilities[4];
103 byte VideoModePtr[4];
104 byte TotalMemory[2];
105 byte OemSoftwareRev[2];
106 byte OemVendorNamePtr[4];
107 byte OemProductNamePtr[4];
108 byte OemProductRevPtr[4];
109 byte Reserved[222];
110 byte OemData[256];
111 } vbeinfoblock_t;
112
113 static int totalvidmem;
114 static byte *ppal;
115 qboolean vsync_exists, de_exists;
116
117 qboolean VID_ExtraGetModeInfo(int modenum);
118 int VID_ExtraInitMode (viddef_t *vid, vmode_t *pcurrentmode);
119 void VID_ExtraSwapBuffers (viddef_t *vid, vmode_t *pcurrentmode,
120 vrect_t *rects);
121
122
123 /*
124 ================
125 VGA_BankedBeginDirectRect
126 ================
127 */
VGA_BankedBeginDirectRect(viddef_t * lvid,struct vmode_s * pcurrentmode,int x,int y,byte * pbitmap,int width,int height)128 void VGA_BankedBeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode,
129 int x, int y, byte *pbitmap, int width, int height)
130 {
131
132 if (!lvid->direct)
133 return;
134
135 regs.x.ax = 0x4f05;
136 regs.x.bx = 0;
137 regs.x.dx = VID_displayedpage;
138 dos_int86(0x10);
139
140 VGA_BeginDirectRect (lvid, pcurrentmode, x, y, pbitmap, width, height);
141
142 regs.x.ax = 0x4f05;
143 regs.x.bx = 0;
144 regs.x.dx = VID_currentpage;
145 dos_int86(0x10);
146 }
147
148
149 /*
150 ================
151 VGA_BankedEndDirectRect
152 ================
153 */
VGA_BankedEndDirectRect(viddef_t * lvid,struct vmode_s * pcurrentmode,int x,int y,int width,int height)154 void VGA_BankedEndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode,
155 int x, int y, int width, int height)
156 {
157
158 if (!lvid->direct)
159 return;
160
161 regs.x.ax = 0x4f05;
162 regs.x.bx = 0;
163 regs.x.dx = VID_displayedpage;
164 dos_int86(0x10);
165
166 VGA_EndDirectRect (lvid, pcurrentmode, x, y, width, height);
167
168 regs.x.ax = 0x4f05;
169 regs.x.bx = 0;
170 regs.x.dx = VID_currentpage;
171 dos_int86(0x10);
172 }
173
174
175 /*
176 ================
177 VID_SetVESAPalette
178 ================
179 */
VID_SetVESAPalette(viddef_t * lvid,vmode_t * pcurrentmode,unsigned char * pal)180 void VID_SetVESAPalette (viddef_t *lvid, vmode_t *pcurrentmode,
181 unsigned char *pal)
182 {
183 int i;
184 byte *pp;
185
186 UNUSED(lvid);
187 UNUSED(pcurrentmode);
188
189 pp = ppal;
190
191 for (i=0 ; i<256 ; i++)
192 {
193 pp[2] = pal[0] >> 2;
194 pp[1] = pal[1] >> 2;
195 pp[0] = pal[2] >> 2;
196 pp += 4;
197 pal += 3;
198 }
199
200 regs.x.ax = 0x4F09;
201 regs.x.bx = 0;
202 regs.x.cx = 256;
203 regs.x.dx = 0;
204 regs.x.es = ptr2real(ppal) >> 4;
205 regs.x.di = ptr2real(ppal) & 0xf;
206 dos_int86(0x10);
207
208 if (regs.x.ax != 0x4f)
209 Sys_Error ("Unable to load VESA palette\n");
210 }
211
212
213
214
215 /*
216 ================
217 VID_ExtraFarToLinear
218 ================
219 */
VID_ExtraFarToLinear(void * ptr)220 void *VID_ExtraFarToLinear (void *ptr)
221 {
222 int temp;
223
224 temp = (int)ptr;
225 return real2ptr(((temp & 0xFFFF0000) >> 12) + (temp & 0xFFFF));
226 }
227
228
229 /*
230 ================
231 VID_ExtraWaitDisplayEnable
232 ================
233 */
VID_ExtraWaitDisplayEnable()234 void VID_ExtraWaitDisplayEnable ()
235 {
236 while ((inportb (0x3DA) & 0x01) == 1)
237 ;
238 }
239
240
241 /*
242 ================
243 VID_ExtraVidLookForState
244 ================
245 */
VID_ExtraVidLookForState(unsigned state,unsigned mask)246 qboolean VID_ExtraVidLookForState (unsigned state, unsigned mask)
247 {
248 int i;
249 double starttime, time;
250
251 starttime = Sys_FloatTime ();
252
253 do
254 {
255 for (i=0 ; i<100000 ; i++)
256 {
257 if ((inportb (0x3DA) & mask) == state)
258 return true;
259 }
260
261 time = Sys_FloatTime ();
262 } while ((time - starttime) < 0.1);
263
264 return false;
265 }
266
267
268 /*
269 ================
270 VID_ExtraStateFound
271 ================
272 */
VID_ExtraStateFound(unsigned state)273 qboolean VID_ExtraStateFound (unsigned state)
274 {
275 int i, workingstate;
276
277 workingstate = 0;
278
279 for (i=0 ; i<10 ; i++)
280 {
281 if (!VID_ExtraVidLookForState(workingstate, state))
282 {
283 return false;
284 }
285
286 workingstate ^= state;
287 }
288
289 return true;
290 }
291
292
293 /*
294 ================
295 VID_InitExtra
296 ================
297 */
VID_InitExtra(void)298 void VID_InitExtra (void)
299 {
300 int nummodes;
301 short *pmodenums;
302 vbeinfoblock_t *pinfoblock;
303 __dpmi_meminfo phys_mem_info;
304
305 pinfoblock = dos_getmemory(sizeof(vbeinfoblock_t));
306
307 *(long *)pinfoblock->VbeSignature = 'V' + ('B'<<8) + ('E'<<16) + ('2'<<24);
308
309 // see if VESA support is available
310 regs.x.ax = 0x4f00;
311 regs.x.es = ptr2real(pinfoblock) >> 4;
312 regs.x.di = ptr2real(pinfoblock) & 0xf;
313 dos_int86(0x10);
314
315 if (regs.x.ax != 0x4f)
316 return; // no VESA support
317
318 if (pinfoblock->VbeVersion[1] < 0x02)
319 return; // not VESA 2.0 or greater
320
321 Con_Printf ("VESA 2.0 compliant adapter:\n%s\n",
322 VID_ExtraFarToLinear (*(byte **)&pinfoblock->OemStringPtr[0]));
323
324 totalvidmem = *(unsigned short *)&pinfoblock->TotalMemory[0] << 16;
325
326 pmodenums = (short *)
327 VID_ExtraFarToLinear (*(byte **)&pinfoblock->VideoModePtr[0]);
328
329 // find 8 bit modes until we either run out of space or run out of modes
330 nummodes = 0;
331
332 while ((*pmodenums != -1) && (nummodes < MAX_VESA_MODES))
333 {
334 if (VID_ExtraGetModeInfo (*pmodenums))
335 {
336 vesa_modes[nummodes].pnext = &vesa_modes[nummodes+1];
337 if (modeinfo.width > 999)
338 {
339 if (modeinfo.height > 999)
340 {
341 sprintf (&names[nummodes][0], "%4dx%4d", modeinfo.width,
342 modeinfo.height);
343 names[nummodes][9] = 0;
344 }
345 else
346 {
347 sprintf (&names[nummodes][0], "%4dx%3d", modeinfo.width,
348 modeinfo.height);
349 names[nummodes][8] = 0;
350 }
351 }
352 else
353 {
354 if (modeinfo.height > 999)
355 {
356 sprintf (&names[nummodes][0], "%3dx%4d", modeinfo.width,
357 modeinfo.height);
358 names[nummodes][8] = 0;
359 }
360 else
361 {
362 sprintf (&names[nummodes][0], "%3dx%3d", modeinfo.width,
363 modeinfo.height);
364 names[nummodes][7] = 0;
365 }
366 }
367
368 vesa_modes[nummodes].name = &names[nummodes][0];
369 vesa_modes[nummodes].width = modeinfo.width;
370 vesa_modes[nummodes].height = modeinfo.height;
371 vesa_modes[nummodes].aspect =
372 ((float)modeinfo.height / (float)modeinfo.width) *
373 (320.0 / 240.0);
374 vesa_modes[nummodes].rowbytes = modeinfo.bytes_per_scanline;
375 vesa_modes[nummodes].planar = 0;
376 vesa_modes[nummodes].pextradata = &vesa_extra[nummodes];
377 vesa_modes[nummodes].setmode = VID_ExtraInitMode;
378 vesa_modes[nummodes].swapbuffers = VID_ExtraSwapBuffers;
379 vesa_modes[nummodes].setpalette = VID_SetVESAPalette;
380
381 if (modeinfo.mode_attributes & LINEAR_FRAME_BUFFER)
382 {
383 // add linear bit to mode for linear modes
384 vesa_extra[nummodes].vesamode = modeinfo.modenum | LINEAR_MODE;
385 vesa_extra[nummodes].pages[0] = 0;
386 vesa_extra[nummodes].pages[1] = modeinfo.pagesize;
387 vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2;
388 vesa_modes[nummodes].numpages = modeinfo.numpages;
389
390 vesa_modes[nummodes].begindirectrect = VGA_BeginDirectRect;
391 vesa_modes[nummodes].enddirectrect = VGA_EndDirectRect;
392
393 phys_mem_info.address = (int)modeinfo.pptr;
394 phys_mem_info.size = 0x400000;
395
396 if (__dpmi_physical_address_mapping(&phys_mem_info))
397 goto NextMode;
398
399 vesa_extra[nummodes].plinearmem =
400 real2ptr (phys_mem_info.address);
401 }
402 else
403 {
404 // banked at 0xA0000
405 vesa_extra[nummodes].vesamode = modeinfo.modenum;
406 vesa_extra[nummodes].pages[0] = 0;
407 vesa_extra[nummodes].plinearmem =
408 real2ptr(modeinfo.winasegment<<4);
409
410 vesa_modes[nummodes].begindirectrect =
411 VGA_BankedBeginDirectRect;
412 vesa_modes[nummodes].enddirectrect = VGA_BankedEndDirectRect;
413 vesa_extra[nummodes].pages[1] = modeinfo.pagesize;
414 vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2;
415 vesa_modes[nummodes].numpages = modeinfo.numpages;
416 }
417
418 vesa_extra[nummodes].vga_incompatible =
419 modeinfo.mode_attributes & VGA_INCOMPATIBLE;
420
421 nummodes++;
422 }
423 NextMode:
424 pmodenums++;
425 }
426
427 // add the VESA modes at the start of the mode list (if there are any)
428 if (nummodes)
429 {
430 vesa_modes[nummodes-1].pnext = pvidmodes;
431 pvidmodes = &vesa_modes[0];
432 numvidmodes += nummodes;
433 ppal = dos_getmemory(256*4);
434 }
435
436 dos_freememory(pinfoblock);
437 }
438
439
440 /*
441 ================
442 VID_ExtraGetModeInfo
443 ================
444 */
VID_ExtraGetModeInfo(int modenum)445 qboolean VID_ExtraGetModeInfo(int modenum)
446 {
447 char *infobuf;
448 int numimagepages;
449
450 infobuf = dos_getmemory(256);
451
452 regs.x.ax = 0x4f01;
453 regs.x.cx = modenum;
454 regs.x.es = ptr2real(infobuf) >> 4;
455 regs.x.di = ptr2real(infobuf) & 0xf;
456 dos_int86(0x10);
457 if (regs.x.ax != 0x4f)
458 {
459 return false;
460 }
461 else
462 {
463 modeinfo.modenum = modenum;
464 modeinfo.bits_per_pixel = *(char*)(infobuf+25);
465 modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8;
466 modeinfo.width = *(short*)(infobuf+18);
467 modeinfo.height = *(short*)(infobuf+20);
468
469 // we do only 8-bpp in software
470 if ((modeinfo.bits_per_pixel != 8) ||
471 (modeinfo.bytes_per_pixel != 1) ||
472 (modeinfo.width > MAXWIDTH) ||
473 (modeinfo.height > MAXHEIGHT))
474 {
475 return false;
476 }
477
478 modeinfo.mode_attributes = *(short*)infobuf;
479
480 // we only want color graphics modes that are supported by the hardware
481 if ((modeinfo.mode_attributes &
482 (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) !=
483 (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE))
484 {
485 return false;
486 }
487
488 // we only work with linear frame buffers, except for 320x200, which can
489 // effectively be linear when banked at 0xA000
490 if (!(modeinfo.mode_attributes & LINEAR_FRAME_BUFFER))
491 {
492 if ((modeinfo.width != 320) || (modeinfo.height != 200))
493 return false;
494 }
495
496 modeinfo.bytes_per_scanline = *(short*)(infobuf+16);
497
498 modeinfo.pagesize = modeinfo.bytes_per_scanline * modeinfo.height;
499
500 if (modeinfo.pagesize > totalvidmem)
501 return false;
502
503 // force to one page if the adapter reports it doesn't support more pages
504 // than that, no matter how much memory it has--it may not have hardware
505 // support for page flipping
506 numimagepages = *(unsigned char *)(infobuf+29);
507
508 if (numimagepages <= 0)
509 {
510 // wrong, but there seems to be an ATI VESA driver that reports 0
511 modeinfo.numpages = 1;
512 }
513 else if (numimagepages < 3)
514 {
515 modeinfo.numpages = numimagepages;
516 }
517 else
518 {
519 modeinfo.numpages = 3;
520 }
521
522 if (*(char*)(infobuf+2) & 5)
523 {
524 modeinfo.winasegment = *(unsigned short*)(infobuf+8);
525 modeinfo.win = 0;
526 }
527 else if (*(char*)(infobuf+3) & 5)
528 {
529 modeinfo.winbsegment = *(unsigned short*)(infobuf+8);
530 modeinfo.win = 1;
531 }
532 modeinfo.granularity = *(short*)(infobuf+4) * 1024;
533 modeinfo.win_size = *(short*)(infobuf+6) * 1024;
534 modeinfo.bits_per_pixel = *(char*)(infobuf+25);
535 modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8;
536 modeinfo.memory_model = *(unsigned char*)(infobuf+27);
537 modeinfo.num_pages = *(char*)(infobuf+29) + 1;
538
539 modeinfo.red_width = *(char*)(infobuf+31);
540 modeinfo.red_pos = *(char*)(infobuf+32);
541 modeinfo.green_width = *(char*)(infobuf+33);
542 modeinfo.green_pos = *(char*)(infobuf+34);
543 modeinfo.blue_width = *(char*)(infobuf+35);
544 modeinfo.blue_pos = *(char*)(infobuf+36);
545
546 modeinfo.pptr = *(long *)(infobuf+40);
547
548 #if 0
549 printf("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum);
550 printf(" mode attrib = 0x%0x\n", modeinfo.mode_attributes);
551 printf(" win a attrib = 0x%0x\n", *(unsigned char*)(infobuf+2));
552 printf(" win b attrib = 0x%0x\n", *(unsigned char*)(infobuf+3));
553 printf(" win a seg 0x%0x\n", (int) modeinfo.winasegment);
554 printf(" win b seg 0x%0x\n", (int) modeinfo.winbsegment);
555 printf(" bytes per scanline = %d\n",
556 modeinfo.bytes_per_scanline);
557 printf(" width = %d, height = %d\n", modeinfo.width,
558 modeinfo.height);
559 printf(" win = %c\n", 'A' + modeinfo.win);
560 printf(" win granularity = %d\n", modeinfo.granularity);
561 printf(" win size = %d\n", modeinfo.win_size);
562 printf(" bits per pixel = %d\n", modeinfo.bits_per_pixel);
563 printf(" bytes per pixel = %d\n", modeinfo.bytes_per_pixel);
564 printf(" memory model = 0x%x\n", modeinfo.memory_model);
565 printf(" num pages = %d\n", modeinfo.num_pages);
566 printf(" red width = %d\n", modeinfo.red_width);
567 printf(" red pos = %d\n", modeinfo.red_pos);
568 printf(" green width = %d\n", modeinfo.green_width);
569 printf(" green pos = %d\n", modeinfo.green_pos);
570 printf(" blue width = %d\n", modeinfo.blue_width);
571 printf(" blue pos = %d\n", modeinfo.blue_pos);
572 printf(" phys mem = %x\n", modeinfo.pptr);
573 #endif
574 }
575
576 dos_freememory(infobuf);
577
578 return true;
579 }
580
581
582 /*
583 ================
584 VID_ExtraInitMode
585 ================
586 */
VID_ExtraInitMode(viddef_t * lvid,vmode_t * pcurrentmode)587 int VID_ExtraInitMode (viddef_t *lvid, vmode_t *pcurrentmode)
588 {
589 vesa_extra_t *pextra;
590 int pageoffset;
591
592 pextra = pcurrentmode->pextradata;
593
594 if (vid_nopageflip.value)
595 lvid->numpages = 1;
596 else
597 lvid->numpages = pcurrentmode->numpages;
598
599 // clean up any old vid buffer lying around, alloc new if needed
600 if (!VGA_FreeAndAllocVidbuffer (lvid, lvid->numpages == 1))
601 return -1; // memory alloc failed
602
603 // clear the screen and wait for the next frame. VGA_pcurmode, which
604 // VGA_ClearVideoMem relies on, is guaranteed to be set because mode 0 is
605 // always the first mode set in a session
606 if (VGA_pcurmode)
607 VGA_ClearVideoMem (VGA_pcurmode->planar);
608
609 // set the mode
610 regs.x.ax = 0x4f02;
611 regs.x.bx = pextra->vesamode;
612 dos_int86(0x10);
613
614 if (regs.x.ax != 0x4f)
615 return 0;
616
617 VID_banked = !(pextra->vesamode & LINEAR_MODE);
618 VID_membase = pextra->plinearmem;
619 VGA_width = lvid->width;
620 VGA_height = lvid->height;
621 VGA_rowbytes = lvid->rowbytes;
622
623 lvid->colormap = host_colormap;
624
625 VID_pagelist = &pextra->pages[0];
626
627 // wait for display enable by default only when triple-buffering on a VGA-
628 // compatible machine that actually has a functioning display enable status
629 vsync_exists = VID_ExtraStateFound (0x08);
630 de_exists = VID_ExtraStateFound (0x01);
631
632 if (!pextra->vga_incompatible &&
633 (lvid->numpages == 3) &&
634 de_exists &&
635 (_vid_wait_override.value == 0.0))
636 {
637 Cvar_SetValue ("vid_wait", (float)VID_WAIT_DISPLAY_ENABLE);
638
639 VID_displayedpage = 0;
640 VID_currentpage = 1;
641 }
642 else
643 {
644 if ((lvid->numpages == 1) && (_vid_wait_override.value == 0.0))
645 {
646 Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE);
647 VID_displayedpage = VID_currentpage = 0;
648 }
649 else
650 {
651 Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC);
652
653 VID_displayedpage = 0;
654
655 if (lvid->numpages > 1)
656 VID_currentpage = 1;
657 else
658 VID_currentpage = 0;
659 }
660 }
661
662 // TODO: really should be a call to a function
663 pageoffset = VID_pagelist[VID_displayedpage];
664
665 regs.x.ax = 0x4f07;
666 regs.x.bx = 0x80; // wait for vsync so we know page 0 is visible
667 regs.x.cx = pageoffset % VGA_rowbytes;
668 regs.x.dx = pageoffset / VGA_rowbytes;
669 dos_int86(0x10);
670
671 if (VID_banked)
672 {
673 regs.x.ax = 0x4f05;
674 regs.x.bx = 0;
675 regs.x.dx = VID_currentpage;
676 dos_int86(0x10);
677
678 VGA_pagebase = VID_membase;
679 }
680 else
681 {
682 VGA_pagebase = VID_membase + VID_pagelist[VID_currentpage];
683 }
684
685 if (lvid->numpages > 1)
686 {
687 lvid->buffer = VGA_pagebase;
688 lvid->conbuffer = lvid->buffer;
689 }
690 else
691 {
692 lvid->rowbytes = lvid->width;
693 }
694
695 lvid->direct = VGA_pagebase;
696 lvid->conrowbytes = lvid->rowbytes;
697 lvid->conwidth = lvid->width;
698 lvid->conheight = lvid->height;
699
700 lvid->maxwarpwidth = WARP_WIDTH;
701 lvid->maxwarpheight = WARP_HEIGHT;
702
703 VGA_pcurmode = pcurrentmode;
704
705 D_InitCaches (vid_surfcache, vid_surfcachesize);
706
707 return 1;
708 }
709
710
711 /*
712 ================
713 VID_ExtraSwapBuffers
714 ================
715 */
VID_ExtraSwapBuffers(viddef_t * lvid,vmode_t * pcurrentmode,vrect_t * rects)716 void VID_ExtraSwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode,
717 vrect_t *rects)
718 {
719 int pageoffset;
720
721 UNUSED(rects);
722 UNUSED(pcurrentmode);
723
724 pageoffset = VID_pagelist[VID_currentpage];
725
726 // display the newly finished page
727 if (lvid->numpages > 1)
728 {
729 // page flipped
730 regs.x.ax = 0x4f07;
731
732 if (vid_wait.value != VID_WAIT_VSYNC)
733 {
734 if ((vid_wait.value == VID_WAIT_DISPLAY_ENABLE) && de_exists)
735 VID_ExtraWaitDisplayEnable ();
736
737 regs.x.bx = VESA_DONT_WAIT_VSYNC;
738 }
739 else
740 {
741 regs.x.bx = VESA_WAIT_VSYNC; // double buffered has to wait
742 }
743
744 regs.x.cx = pageoffset % VGA_rowbytes;
745 regs.x.dx = pageoffset / VGA_rowbytes;
746 dos_int86(0x10);
747
748 VID_displayedpage = VID_currentpage;
749 if (++VID_currentpage >= lvid->numpages)
750 VID_currentpage = 0;
751
752 //
753 // set the new write window if this is a banked mode; otherwise, set the
754 // new address to which to write
755 //
756 if (VID_banked)
757 {
758 regs.x.ax = 0x4f05;
759 regs.x.bx = 0;
760 regs.x.dx = VID_currentpage;
761 dos_int86(0x10);
762 }
763 else
764 {
765 lvid->direct = lvid->buffer; // direct drawing goes to the
766 // currently displayed page
767 lvid->buffer = VID_membase + VID_pagelist[VID_currentpage];
768 lvid->conbuffer = lvid->buffer;
769 }
770
771 VGA_pagebase = lvid->buffer;
772 }
773 else
774 {
775 // non-page-flipped
776 if (vsync_exists && (vid_wait.value == VID_WAIT_VSYNC))
777 {
778 VGA_WaitVsync ();
779 }
780
781 while (rects)
782 {
783 VGA_UpdateLinearScreen (
784 lvid->buffer + rects->x + (rects->y * lvid->rowbytes),
785 VGA_pagebase + rects->x + (rects->y * VGA_rowbytes),
786 rects->width,
787 rects->height,
788 lvid->rowbytes,
789 VGA_rowbytes);
790
791 rects = rects->pnext;
792 }
793 }
794 }
795
796