aboutsummaryrefslogtreecommitdiffstats
path: root/WinQuake/vid_ext.c
diff options
context:
space:
mode:
authorwyatt8740 <wyatt8740@yahoo.com>2014-01-06 12:02:16 -0500
committerwyatt8740 <wyatt8740@yahoo.com>2014-01-06 12:02:16 -0500
commita8f828a066773a59fdf646299359d35ae0e845af (patch)
tree86123409fc6f231cf4136e81159b63cb1e9ec102 /WinQuake/vid_ext.c
parentb2951690415054ae8705c07f8df7a4ba7cde382a (diff)
downloadquake-pum-a8f828a066773a59fdf646299359d35ae0e845af.tar.gz
Removed accidental upload of copyrighted map files
Diffstat (limited to 'WinQuake/vid_ext.c')
-rw-r--r--WinQuake/vid_ext.c1590
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;
+ }
+ }
+}
+