Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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 
28
#include 
29
 
30
#include "quakedef.h"
31
#include "d_local.h"
32
#include "dosisms.h"
33
#include "vid_dos.h"
34
#include 
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
*/
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
*/
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
*/
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
*/
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
*/
234
void VID_ExtraWaitDisplayEnable ()
235
{
236
	while ((inportb (0x3DA) & 0x01) == 1)
237
		;
238
}
239
 
240
 
241
/*
242
================
243
VID_ExtraVidLookForState
244
================
245
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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