0,0 → 1,795 |
/* |
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; |
} |
} |
} |
|