diff options
Diffstat (limited to 'WinQuake/vid_ext.c')
| -rw-r--r-- | WinQuake/vid_ext.c | 1590 |
1 files changed, 795 insertions, 795 deletions
diff --git a/WinQuake/vid_ext.c b/WinQuake/vid_ext.c index 4188e2b..c12374c 100644 --- a/WinQuake/vid_ext.c +++ b/WinQuake/vid_ext.c @@ -1,795 +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; - } - } -} - +/*
+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;
+ }
+ }
+}
+
|
