/* | |
Copyright (C) 1996-1997 Id Software, Inc. | |
This program is free software; you can redistribute it and/or | |
modify it under the terms of the GNU General Public License | |
as published by the Free Software Foundation; either version 2 | |
of the License, or (at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
See the GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program; if not, write to the Free Software | |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
*/ | |
// | |
// vid_ext.c: extended video modes | |
// in this implementation, VESA-specific DOS video stuff | |
// | |
// TODO: make dependencies on vid_vga.c explicit or eliminate them | |
#include <stdlib.h> | |
#include <dos.h> | |
#include "quakedef.h" | |
#include "d_local.h" | |
#include "dosisms.h" | |
#include "vid_dos.h" | |
#include <dpmi.h> | |
#define MODE_SUPPORTED_IN_HW 0x0001 | |
#define COLOR_MODE 0x0008 | |
#define GRAPHICS_MODE 0x0010 | |
#define VGA_INCOMPATIBLE 0x0020 | |
#define LINEAR_FRAME_BUFFER 0x0080 | |
#define LINEAR_MODE 0x4000 | |
#define VESA_DONT_WAIT_VSYNC 0 // when page flipping | |
#define VESA_WAIT_VSYNC 0x80 | |
#define MAX_VESA_MODES 30 // we'll just take the first 30 if there | |
// are more | |
typedef struct { | |
int pages[3]; // either 2 or 3 is valid | |
int vesamode; // LINEAR_MODE set if linear mode | |
void *plinearmem; // linear address of start of frame buffer | |
qboolean vga_incompatible; | |
} vesa_extra_t; | |
static vmode_t vesa_modes[MAX_VESA_MODES] = | |
{{NULL, NULL, " ********* VESA modes ********* "}}; | |
static vesa_extra_t vesa_extra[MAX_VESA_MODES]; | |
static char names[MAX_VESA_MODES][10]; | |
extern regs_t regs; | |
static int VID_currentpage; | |
static int VID_displayedpage; | |
static int *VID_pagelist; | |
static byte *VID_membase; | |
static int VID_banked; | |
typedef struct | |
{ | |
int modenum; | |
int mode_attributes; | |
int winasegment; | |
int winbsegment; | |
int bytes_per_scanline; // bytes per logical scanline (+16) | |
int win; // window number (A=0, B=1) | |
int win_size; // window size (+6) | |
int granularity; // how finely i can set the window in vid mem (+4) | |
int width, height; // displayed width and height (+18, +20) | |
int bits_per_pixel; // er, better be 8, 15, 16, 24, or 32 (+25) | |
int bytes_per_pixel; // er, better be 1, 2, or 4 | |
int memory_model; // and better be 4 or 6, packed or direct color (+27) | |
int num_pages; // number of complete frame buffer pages (+29) | |
int red_width; // the # of bits in the red component (+31) | |
int red_pos; // the bit position of the red component (+32) | |
int green_width; // etc.. (+33) | |
int green_pos; // (+34) | |
int blue_width; // (+35) | |
int blue_pos; // (+36) | |
int pptr; | |
int pagesize; | |
int numpages; | |
} modeinfo_t; | |
static modeinfo_t modeinfo; | |
// all bytes to avoid problems with compiler field packing | |
typedef struct vbeinfoblock_s { | |
byte VbeSignature[4]; | |
byte VbeVersion[2]; | |
byte OemStringPtr[4]; | |
byte Capabilities[4]; | |
byte VideoModePtr[4]; | |
byte TotalMemory[2]; | |
byte OemSoftwareRev[2]; | |
byte OemVendorNamePtr[4]; | |
byte OemProductNamePtr[4]; | |
byte OemProductRevPtr[4]; | |
byte Reserved[222]; | |
byte OemData[256]; | |
} vbeinfoblock_t; | |
static int totalvidmem; | |
static byte *ppal; | |
qboolean vsync_exists, de_exists; | |
qboolean VID_ExtraGetModeInfo(int modenum); | |
int VID_ExtraInitMode (viddef_t *vid, vmode_t *pcurrentmode); | |
void VID_ExtraSwapBuffers (viddef_t *vid, vmode_t *pcurrentmode, | |
vrect_t *rects); | |
/* | |
================ | |
VGA_BankedBeginDirectRect | |
================ | |
*/ | |
void VGA_BankedBeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, | |
int x, int y, byte *pbitmap, int width, int height) | |
{ | |
if (!lvid->direct) | |
return; | |
regs.x.ax = 0x4f05; | |
regs.x.bx = 0; | |
regs.x.dx = VID_displayedpage; | |
dos_int86(0x10); | |
VGA_BeginDirectRect (lvid, pcurrentmode, x, y, pbitmap, width, height); | |
regs.x.ax = 0x4f05; | |
regs.x.bx = 0; | |
regs.x.dx = VID_currentpage; | |
dos_int86(0x10); | |
} | |
/* | |
================ | |
VGA_BankedEndDirectRect | |
================ | |
*/ | |
void VGA_BankedEndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, | |
int x, int y, int width, int height) | |
{ | |
if (!lvid->direct) | |
return; | |
regs.x.ax = 0x4f05; | |
regs.x.bx = 0; | |
regs.x.dx = VID_displayedpage; | |
dos_int86(0x10); | |
VGA_EndDirectRect (lvid, pcurrentmode, x, y, width, height); | |
regs.x.ax = 0x4f05; | |
regs.x.bx = 0; | |
regs.x.dx = VID_currentpage; | |
dos_int86(0x10); | |
} | |
/* | |
================ | |
VID_SetVESAPalette | |
================ | |
*/ | |
void VID_SetVESAPalette (viddef_t *lvid, vmode_t *pcurrentmode, | |
unsigned char *pal) | |
{ | |
int i; | |
byte *pp; | |
UNUSED(lvid); | |
UNUSED(pcurrentmode); | |
pp = ppal; | |
for (i=0 ; i<256 ; i++) | |
{ | |
pp[2] = pal[0] >> 2; | |
pp[1] = pal[1] >> 2; | |
pp[0] = pal[2] >> 2; | |
pp += 4; | |
pal += 3; | |
} | |
regs.x.ax = 0x4F09; | |
regs.x.bx = 0; | |
regs.x.cx = 256; | |
regs.x.dx = 0; | |
regs.x.es = ptr2real(ppal) >> 4; | |
regs.x.di = ptr2real(ppal) & 0xf; | |
dos_int86(0x10); | |
if (regs.x.ax != 0x4f) | |
Sys_Error ("Unable to load VESA palette\n"); | |
} | |
/* | |
================ | |
VID_ExtraFarToLinear | |
================ | |
*/ | |
void *VID_ExtraFarToLinear (void *ptr) | |
{ | |
int temp; | |
temp = (int)ptr; | |
return real2ptr(((temp & 0xFFFF0000) >> 12) + (temp & 0xFFFF)); | |
} | |
/* | |
================ | |
VID_ExtraWaitDisplayEnable | |
================ | |
*/ | |
void VID_ExtraWaitDisplayEnable () | |
{ | |
while ((inportb (0x3DA) & 0x01) == 1) | |
; | |
} | |
/* | |
================ | |
VID_ExtraVidLookForState | |
================ | |
*/ | |
qboolean VID_ExtraVidLookForState (unsigned state, unsigned mask) | |
{ | |
int i; | |
double starttime, time; | |
starttime = Sys_FloatTime (); | |
do | |
{ | |
for (i=0 ; i<100000 ; i++) | |
{ | |
if ((inportb (0x3DA) & mask) == state) | |
return true; | |
} | |
time = Sys_FloatTime (); | |
} while ((time - starttime) < 0.1); | |
return false; | |
} | |
/* | |
================ | |
VID_ExtraStateFound | |
================ | |
*/ | |
qboolean VID_ExtraStateFound (unsigned state) | |
{ | |
int i, workingstate; | |
workingstate = 0; | |
for (i=0 ; i<10 ; i++) | |
{ | |
if (!VID_ExtraVidLookForState(workingstate, state)) | |
{ | |
return false; | |
} | |
workingstate ^= state; | |
} | |
return true; | |
} | |
/* | |
================ | |
VID_InitExtra | |
================ | |
*/ | |
void VID_InitExtra (void) | |
{ | |
int nummodes; | |
short *pmodenums; | |
vbeinfoblock_t *pinfoblock; | |
__dpmi_meminfo phys_mem_info; | |
pinfoblock = dos_getmemory(sizeof(vbeinfoblock_t)); | |
*(long *)pinfoblock->VbeSignature = 'V' + ('B'<<8) + ('E'<<16) + ('2'<<24); | |
// see if VESA support is available | |
regs.x.ax = 0x4f00; | |
regs.x.es = ptr2real(pinfoblock) >> 4; | |
regs.x.di = ptr2real(pinfoblock) & 0xf; | |
dos_int86(0x10); | |
if (regs.x.ax != 0x4f) | |
return; // no VESA support | |
if (pinfoblock->VbeVersion[1] < 0x02) | |
return; // not VESA 2.0 or greater | |
Con_Printf ("VESA 2.0 compliant adapter:\n%s\n", | |
VID_ExtraFarToLinear (*(byte **)&pinfoblock->OemStringPtr[0])); | |
totalvidmem = *(unsigned short *)&pinfoblock->TotalMemory[0] << 16; | |
pmodenums = (short *) | |
VID_ExtraFarToLinear (*(byte **)&pinfoblock->VideoModePtr[0]); | |
// find 8 bit modes until we either run out of space or run out of modes | |
nummodes = 0; | |
while ((*pmodenums != -1) && (nummodes < MAX_VESA_MODES)) | |
{ | |
if (VID_ExtraGetModeInfo (*pmodenums)) | |
{ | |
vesa_modes[nummodes].pnext = &vesa_modes[nummodes+1]; | |
if (modeinfo.width > 999) | |
{ | |
if (modeinfo.height > 999) | |
{ | |
sprintf (&names[nummodes][0], "%4dx%4d", modeinfo.width, | |
modeinfo.height); | |
names[nummodes][9] = 0; | |
} | |
else | |
{ | |
sprintf (&names[nummodes][0], "%4dx%3d", modeinfo.width, | |
modeinfo.height); | |
names[nummodes][8] = 0; | |
} | |
} | |
else | |
{ | |
if (modeinfo.height > 999) | |
{ | |
sprintf (&names[nummodes][0], "%3dx%4d", modeinfo.width, | |
modeinfo.height); | |
names[nummodes][8] = 0; | |
} | |
else | |
{ | |
sprintf (&names[nummodes][0], "%3dx%3d", modeinfo.width, | |
modeinfo.height); | |
names[nummodes][7] = 0; | |
} | |
} | |
vesa_modes[nummodes].name = &names[nummodes][0]; | |
vesa_modes[nummodes].width = modeinfo.width; | |
vesa_modes[nummodes].height = modeinfo.height; | |
vesa_modes[nummodes].aspect = | |
((float)modeinfo.height / (float)modeinfo.width) * | |
(320.0 / 240.0); | |
vesa_modes[nummodes].rowbytes = modeinfo.bytes_per_scanline; | |
vesa_modes[nummodes].planar = 0; | |
vesa_modes[nummodes].pextradata = &vesa_extra[nummodes]; | |
vesa_modes[nummodes].setmode = VID_ExtraInitMode; | |
vesa_modes[nummodes].swapbuffers = VID_ExtraSwapBuffers; | |
vesa_modes[nummodes].setpalette = VID_SetVESAPalette; | |
if (modeinfo.mode_attributes & LINEAR_FRAME_BUFFER) | |
{ | |
// add linear bit to mode for linear modes | |
vesa_extra[nummodes].vesamode = modeinfo.modenum | LINEAR_MODE; | |
vesa_extra[nummodes].pages[0] = 0; | |
vesa_extra[nummodes].pages[1] = modeinfo.pagesize; | |
vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; | |
vesa_modes[nummodes].numpages = modeinfo.numpages; | |
vesa_modes[nummodes].begindirectrect = VGA_BeginDirectRect; | |
vesa_modes[nummodes].enddirectrect = VGA_EndDirectRect; | |
phys_mem_info.address = (int)modeinfo.pptr; | |
phys_mem_info.size = 0x400000; | |
if (__dpmi_physical_address_mapping(&phys_mem_info)) | |
goto NextMode; | |
vesa_extra[nummodes].plinearmem = | |
real2ptr (phys_mem_info.address); | |
} | |
else | |
{ | |
// banked at 0xA0000 | |
vesa_extra[nummodes].vesamode = modeinfo.modenum; | |
vesa_extra[nummodes].pages[0] = 0; | |
vesa_extra[nummodes].plinearmem = | |
real2ptr(modeinfo.winasegment<<4); | |
vesa_modes[nummodes].begindirectrect = | |
VGA_BankedBeginDirectRect; | |
vesa_modes[nummodes].enddirectrect = VGA_BankedEndDirectRect; | |
vesa_extra[nummodes].pages[1] = modeinfo.pagesize; | |
vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; | |
vesa_modes[nummodes].numpages = modeinfo.numpages; | |
} | |
vesa_extra[nummodes].vga_incompatible = | |
modeinfo.mode_attributes & VGA_INCOMPATIBLE; | |
nummodes++; | |
} | |
NextMode: | |
pmodenums++; | |
} | |
// add the VESA modes at the start of the mode list (if there are any) | |
if (nummodes) | |
{ | |
vesa_modes[nummodes-1].pnext = pvidmodes; | |
pvidmodes = &vesa_modes[0]; | |
numvidmodes += nummodes; | |
ppal = dos_getmemory(256*4); | |
} | |
dos_freememory(pinfoblock); | |
} | |
/* | |
================ | |
VID_ExtraGetModeInfo | |
================ | |
*/ | |
qboolean VID_ExtraGetModeInfo(int modenum) | |
{ | |
char *infobuf; | |
int numimagepages; | |
infobuf = dos_getmemory(256); | |
regs.x.ax = 0x4f01; | |
regs.x.cx = modenum; | |
regs.x.es = ptr2real(infobuf) >> 4; | |
regs.x.di = ptr2real(infobuf) & 0xf; | |
dos_int86(0x10); | |
if (regs.x.ax != 0x4f) | |
{ | |
return false; | |
} | |
else | |
{ | |
modeinfo.modenum = modenum; | |
modeinfo.bits_per_pixel = *(char*)(infobuf+25); | |
modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8; | |
modeinfo.width = *(short*)(infobuf+18); | |
modeinfo.height = *(short*)(infobuf+20); | |
// we do only 8-bpp in software | |
if ((modeinfo.bits_per_pixel != 8) || | |
(modeinfo.bytes_per_pixel != 1) || | |
(modeinfo.width > MAXWIDTH) || | |
(modeinfo.height > MAXHEIGHT)) | |
{ | |
return false; | |
} | |
modeinfo.mode_attributes = *(short*)infobuf; | |
// we only want color graphics modes that are supported by the hardware | |
if ((modeinfo.mode_attributes & | |
(MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) != | |
(MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) | |
{ | |
return false; | |
} | |
// we only work with linear frame buffers, except for 320x200, which can | |
// effectively be linear when banked at 0xA000 | |
if (!(modeinfo.mode_attributes & LINEAR_FRAME_BUFFER)) | |
{ | |
if ((modeinfo.width != 320) || (modeinfo.height != 200)) | |
return false; | |
} | |
modeinfo.bytes_per_scanline = *(short*)(infobuf+16); | |
modeinfo.pagesize = modeinfo.bytes_per_scanline * modeinfo.height; | |
if (modeinfo.pagesize > totalvidmem) | |
return false; | |
// force to one page if the adapter reports it doesn't support more pages | |
// than that, no matter how much memory it has--it may not have hardware | |
// support for page flipping | |
numimagepages = *(unsigned char *)(infobuf+29); | |
if (numimagepages <= 0) | |
{ | |
// wrong, but there seems to be an ATI VESA driver that reports 0 | |
modeinfo.numpages = 1; | |
} | |
else if (numimagepages < 3) | |
{ | |
modeinfo.numpages = numimagepages; | |
} | |
else | |
{ | |
modeinfo.numpages = 3; | |
} | |
if (*(char*)(infobuf+2) & 5) | |
{ | |
modeinfo.winasegment = *(unsigned short*)(infobuf+8); | |
modeinfo.win = 0; | |
} | |
else if (*(char*)(infobuf+3) & 5) | |
{ | |
modeinfo.winbsegment = *(unsigned short*)(infobuf+8); | |
modeinfo.win = 1; | |
} | |
modeinfo.granularity = *(short*)(infobuf+4) * 1024; | |
modeinfo.win_size = *(short*)(infobuf+6) * 1024; | |
modeinfo.bits_per_pixel = *(char*)(infobuf+25); | |
modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8; | |
modeinfo.memory_model = *(unsigned char*)(infobuf+27); | |
modeinfo.num_pages = *(char*)(infobuf+29) + 1; | |
modeinfo.red_width = *(char*)(infobuf+31); | |
modeinfo.red_pos = *(char*)(infobuf+32); | |
modeinfo.green_width = *(char*)(infobuf+33); | |
modeinfo.green_pos = *(char*)(infobuf+34); | |
modeinfo.blue_width = *(char*)(infobuf+35); | |
modeinfo.blue_pos = *(char*)(infobuf+36); | |
modeinfo.pptr = *(long *)(infobuf+40); | |
#if 0 | |
printf("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum); | |
printf(" mode attrib = 0x%0x\n", modeinfo.mode_attributes); | |
printf(" win a attrib = 0x%0x\n", *(unsigned char*)(infobuf+2)); | |
printf(" win b attrib = 0x%0x\n", *(unsigned char*)(infobuf+3)); | |
printf(" win a seg 0x%0x\n", (int) modeinfo.winasegment); | |
printf(" win b seg 0x%0x\n", (int) modeinfo.winbsegment); | |
printf(" bytes per scanline = %d\n", | |
modeinfo.bytes_per_scanline); | |
printf(" width = %d, height = %d\n", modeinfo.width, | |
modeinfo.height); | |
printf(" win = %c\n", 'A' + modeinfo.win); | |
printf(" win granularity = %d\n", modeinfo.granularity); | |
printf(" win size = %d\n", modeinfo.win_size); | |
printf(" bits per pixel = %d\n", modeinfo.bits_per_pixel); | |
printf(" bytes per pixel = %d\n", modeinfo.bytes_per_pixel); | |
printf(" memory model = 0x%x\n", modeinfo.memory_model); | |
printf(" num pages = %d\n", modeinfo.num_pages); | |
printf(" red width = %d\n", modeinfo.red_width); | |
printf(" red pos = %d\n", modeinfo.red_pos); | |
printf(" green width = %d\n", modeinfo.green_width); | |
printf(" green pos = %d\n", modeinfo.green_pos); | |
printf(" blue width = %d\n", modeinfo.blue_width); | |
printf(" blue pos = %d\n", modeinfo.blue_pos); | |
printf(" phys mem = %x\n", modeinfo.pptr); | |
#endif | |
} | |
dos_freememory(infobuf); | |
return true; | |
} | |
/* | |
================ | |
VID_ExtraInitMode | |
================ | |
*/ | |
int VID_ExtraInitMode (viddef_t *lvid, vmode_t *pcurrentmode) | |
{ | |
vesa_extra_t *pextra; | |
int pageoffset; | |
pextra = pcurrentmode->pextradata; | |
if (vid_nopageflip.value) | |
lvid->numpages = 1; | |
else | |
lvid->numpages = pcurrentmode->numpages; | |
// clean up any old vid buffer lying around, alloc new if needed | |
if (!VGA_FreeAndAllocVidbuffer (lvid, lvid->numpages == 1)) | |
return -1; // memory alloc failed | |
// clear the screen and wait for the next frame. VGA_pcurmode, which | |
// VGA_ClearVideoMem relies on, is guaranteed to be set because mode 0 is | |
// always the first mode set in a session | |
if (VGA_pcurmode) | |
VGA_ClearVideoMem (VGA_pcurmode->planar); | |
// set the mode | |
regs.x.ax = 0x4f02; | |
regs.x.bx = pextra->vesamode; | |
dos_int86(0x10); | |
if (regs.x.ax != 0x4f) | |
return 0; | |
VID_banked = !(pextra->vesamode & LINEAR_MODE); | |
VID_membase = pextra->plinearmem; | |
VGA_width = lvid->width; | |
VGA_height = lvid->height; | |
VGA_rowbytes = lvid->rowbytes; | |
lvid->colormap = host_colormap; | |
VID_pagelist = &pextra->pages[0]; | |
// wait for display enable by default only when triple-buffering on a VGA- | |
// compatible machine that actually has a functioning display enable status | |
vsync_exists = VID_ExtraStateFound (0x08); | |
de_exists = VID_ExtraStateFound (0x01); | |
if (!pextra->vga_incompatible && | |
(lvid->numpages == 3) && | |
de_exists && | |
(_vid_wait_override.value == 0.0)) | |
{ | |
Cvar_SetValue ("vid_wait", (float)VID_WAIT_DISPLAY_ENABLE); | |
VID_displayedpage = 0; | |
VID_currentpage = 1; | |
} | |
else | |
{ | |
if ((lvid->numpages == 1) && (_vid_wait_override.value == 0.0)) | |
{ | |
Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE); | |
VID_displayedpage = VID_currentpage = 0; | |
} | |
else | |
{ | |
Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC); | |
VID_displayedpage = 0; | |
if (lvid->numpages > 1) | |
VID_currentpage = 1; | |
else | |
VID_currentpage = 0; | |
} | |
} | |
// TODO: really should be a call to a function | |
pageoffset = VID_pagelist[VID_displayedpage]; | |
regs.x.ax = 0x4f07; | |
regs.x.bx = 0x80; // wait for vsync so we know page 0 is visible | |
regs.x.cx = pageoffset % VGA_rowbytes; | |
regs.x.dx = pageoffset / VGA_rowbytes; | |
dos_int86(0x10); | |
if (VID_banked) | |
{ | |
regs.x.ax = 0x4f05; | |
regs.x.bx = 0; | |
regs.x.dx = VID_currentpage; | |
dos_int86(0x10); | |
VGA_pagebase = VID_membase; | |
} | |
else | |
{ | |
VGA_pagebase = VID_membase + VID_pagelist[VID_currentpage]; | |
} | |
if (lvid->numpages > 1) | |
{ | |
lvid->buffer = VGA_pagebase; | |
lvid->conbuffer = lvid->buffer; | |
} | |
else | |
{ | |
lvid->rowbytes = lvid->width; | |
} | |
lvid->direct = VGA_pagebase; | |
lvid->conrowbytes = lvid->rowbytes; | |
lvid->conwidth = lvid->width; | |
lvid->conheight = lvid->height; | |
lvid->maxwarpwidth = WARP_WIDTH; | |
lvid->maxwarpheight = WARP_HEIGHT; | |
VGA_pcurmode = pcurrentmode; | |
D_InitCaches (vid_surfcache, vid_surfcachesize); | |
return 1; | |
} | |
/* | |
================ | |
VID_ExtraSwapBuffers | |
================ | |
*/ | |
void VID_ExtraSwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode, | |
vrect_t *rects) | |
{ | |
int pageoffset; | |
UNUSED(rects); | |
UNUSED(pcurrentmode); | |
pageoffset = VID_pagelist[VID_currentpage]; | |
// display the newly finished page | |
if (lvid->numpages > 1) | |
{ | |
// page flipped | |
regs.x.ax = 0x4f07; | |
if (vid_wait.value != VID_WAIT_VSYNC) | |
{ | |
if ((vid_wait.value == VID_WAIT_DISPLAY_ENABLE) && de_exists) | |
VID_ExtraWaitDisplayEnable (); | |
regs.x.bx = VESA_DONT_WAIT_VSYNC; | |
} | |
else | |
{ | |
regs.x.bx = VESA_WAIT_VSYNC; // double buffered has to wait | |
} | |
regs.x.cx = pageoffset % VGA_rowbytes; | |
regs.x.dx = pageoffset / VGA_rowbytes; | |
dos_int86(0x10); | |
VID_displayedpage = VID_currentpage; | |
if (++VID_currentpage >= lvid->numpages) | |
VID_currentpage = 0; | |
// | |
// set the new write window if this is a banked mode; otherwise, set the | |
// new address to which to write | |
// | |
if (VID_banked) | |
{ | |
regs.x.ax = 0x4f05; | |
regs.x.bx = 0; | |
regs.x.dx = VID_currentpage; | |
dos_int86(0x10); | |
} | |
else | |
{ | |
lvid->direct = lvid->buffer; // direct drawing goes to the | |
// currently displayed page | |
lvid->buffer = VID_membase + VID_pagelist[VID_currentpage]; | |
lvid->conbuffer = lvid->buffer; | |
} | |
VGA_pagebase = lvid->buffer; | |
} | |
else | |
{ | |
// non-page-flipped | |
if (vsync_exists && (vid_wait.value == VID_WAIT_VSYNC)) | |
{ | |
VGA_WaitVsync (); | |
} | |
while (rects) | |
{ | |
VGA_UpdateLinearScreen ( | |
lvid->buffer + rects->x + (rects->y * lvid->rowbytes), | |
VGA_pagebase + rects->x + (rects->y * VGA_rowbytes), | |
rects->width, | |
rects->height, | |
lvid->rowbytes, | |
VGA_rowbytes); | |
rects = rects->pnext; | |
} | |
} | |
} | |