Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. //
  21. // vid_ext.c: extended video modes
  22. // in this implementation, VESA-specific DOS video stuff
  23. //
  24.  
  25. // TODO: make dependencies on vid_vga.c explicit or eliminate them
  26.  
  27. #include <stdlib.h>
  28. #include <dos.h>
  29.  
  30. #include "quakedef.h"
  31. #include "d_local.h"
  32. #include "dosisms.h"
  33. #include "vid_dos.h"
  34. #include <dpmi.h>
  35.  
  36. #define MODE_SUPPORTED_IN_HW    0x0001
  37. #define COLOR_MODE                              0x0008
  38. #define GRAPHICS_MODE                   0x0010
  39. #define VGA_INCOMPATIBLE                0x0020
  40. #define LINEAR_FRAME_BUFFER             0x0080
  41.  
  42. #define LINEAR_MODE                             0x4000
  43.  
  44. #define VESA_DONT_WAIT_VSYNC    0               // when page flipping
  45. #define VESA_WAIT_VSYNC                 0x80
  46.  
  47. #define MAX_VESA_MODES                  30      // we'll just take the first 30 if there
  48.                                                                         //  are more
  49. typedef struct {
  50.         int                     pages[3];                       // either 2 or 3 is valid
  51.         int                     vesamode;                       // LINEAR_MODE set if linear mode
  52.         void            *plinearmem;            // linear address of start of frame buffer
  53.         qboolean        vga_incompatible;
  54. } vesa_extra_t;
  55.  
  56. static vmode_t          vesa_modes[MAX_VESA_MODES] =
  57.         {{NULL, NULL, "    ********* VESA modes *********    "}};
  58. static vesa_extra_t     vesa_extra[MAX_VESA_MODES];
  59. static char                     names[MAX_VESA_MODES][10];
  60.  
  61. extern regs_t regs;
  62.  
  63. static int              VID_currentpage;
  64. static int              VID_displayedpage;
  65. static int              *VID_pagelist;
  66. static byte             *VID_membase;
  67. static int              VID_banked;
  68.  
  69. typedef struct
  70. {
  71.         int modenum;
  72.         int mode_attributes;
  73.         int     winasegment;
  74.         int     winbsegment;
  75.         int     bytes_per_scanline; // bytes per logical scanline (+16)
  76.         int win; // window number (A=0, B=1)
  77.         int win_size; // window size (+6)
  78.         int granularity; // how finely i can set the window in vid mem (+4)
  79.         int width, height; // displayed width and height (+18, +20)
  80.         int bits_per_pixel; // er, better be 8, 15, 16, 24, or 32 (+25)
  81.         int bytes_per_pixel; // er, better be 1, 2, or 4
  82.         int memory_model; // and better be 4 or 6, packed or direct color (+27)
  83.         int num_pages; // number of complete frame buffer pages (+29)
  84.         int red_width; // the # of bits in the red component (+31)
  85.         int red_pos; // the bit position of the red component (+32)
  86.         int green_width; // etc.. (+33)
  87.         int green_pos; // (+34)
  88.         int blue_width; // (+35)
  89.         int blue_pos; // (+36)
  90.         int pptr;
  91.         int     pagesize;
  92.         int     numpages;
  93. } modeinfo_t;
  94.  
  95. static modeinfo_t modeinfo;
  96.  
  97. // all bytes to avoid problems with compiler field packing
  98. typedef struct vbeinfoblock_s {
  99.      byte                       VbeSignature[4];
  100.      byte                       VbeVersion[2];
  101.      byte                       OemStringPtr[4];
  102.      byte                       Capabilities[4];
  103.      byte                       VideoModePtr[4];
  104.      byte                       TotalMemory[2];
  105.      byte                       OemSoftwareRev[2];
  106.      byte                       OemVendorNamePtr[4];
  107.      byte                       OemProductNamePtr[4];
  108.      byte                       OemProductRevPtr[4];
  109.      byte                       Reserved[222];
  110.      byte                       OemData[256];
  111. } vbeinfoblock_t;
  112.  
  113. static int      totalvidmem;
  114. static byte     *ppal;
  115. qboolean        vsync_exists, de_exists;
  116.  
  117. qboolean VID_ExtraGetModeInfo(int modenum);
  118. int VID_ExtraInitMode (viddef_t *vid, vmode_t *pcurrentmode);
  119. void VID_ExtraSwapBuffers (viddef_t *vid, vmode_t *pcurrentmode,
  120.         vrect_t *rects);
  121.  
  122.  
  123. /*
  124. ================
  125. VGA_BankedBeginDirectRect
  126. ================
  127. */
  128. void VGA_BankedBeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode,
  129.         int x, int y, byte *pbitmap, int width, int height)
  130. {
  131.  
  132.         if (!lvid->direct)
  133.                 return;
  134.  
  135.         regs.x.ax = 0x4f05;
  136.         regs.x.bx = 0;
  137.         regs.x.dx = VID_displayedpage;
  138.         dos_int86(0x10);
  139.  
  140.         VGA_BeginDirectRect (lvid, pcurrentmode, x, y, pbitmap, width, height);
  141.  
  142.         regs.x.ax = 0x4f05;
  143.         regs.x.bx = 0;
  144.         regs.x.dx = VID_currentpage;
  145.         dos_int86(0x10);
  146. }
  147.  
  148.  
  149. /*
  150. ================
  151. VGA_BankedEndDirectRect
  152. ================
  153. */
  154. void VGA_BankedEndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode,
  155.         int x, int y, int width, int height)
  156. {
  157.  
  158.         if (!lvid->direct)
  159.                 return;
  160.  
  161.         regs.x.ax = 0x4f05;
  162.         regs.x.bx = 0;
  163.         regs.x.dx = VID_displayedpage;
  164.         dos_int86(0x10);
  165.  
  166.         VGA_EndDirectRect (lvid, pcurrentmode, x, y, width, height);
  167.  
  168.         regs.x.ax = 0x4f05;
  169.         regs.x.bx = 0;
  170.         regs.x.dx = VID_currentpage;
  171.         dos_int86(0x10);
  172. }
  173.  
  174.  
  175. /*
  176. ================
  177. VID_SetVESAPalette
  178. ================
  179. */
  180. void VID_SetVESAPalette (viddef_t *lvid, vmode_t *pcurrentmode,
  181.         unsigned char *pal)
  182. {
  183.         int             i;
  184.         byte    *pp;
  185.  
  186.         UNUSED(lvid);
  187.         UNUSED(pcurrentmode);
  188.  
  189.         pp = ppal;
  190.  
  191.         for (i=0 ; i<256 ; i++)
  192.         {
  193.                 pp[2] = pal[0] >> 2;
  194.                 pp[1] = pal[1] >> 2;
  195.                 pp[0] = pal[2] >> 2;
  196.                 pp += 4;
  197.                 pal += 3;
  198.         }
  199.  
  200.         regs.x.ax = 0x4F09;
  201.         regs.x.bx = 0;
  202.         regs.x.cx = 256;
  203.         regs.x.dx = 0;
  204.         regs.x.es = ptr2real(ppal) >> 4;
  205.         regs.x.di = ptr2real(ppal) & 0xf;
  206.         dos_int86(0x10);
  207.  
  208.         if (regs.x.ax != 0x4f)
  209.                 Sys_Error ("Unable to load VESA palette\n");
  210. }
  211.  
  212.  
  213.  
  214.  
  215. /*
  216. ================
  217. VID_ExtraFarToLinear
  218. ================
  219. */
  220. void *VID_ExtraFarToLinear (void *ptr)
  221. {
  222.         int             temp;
  223.  
  224.         temp = (int)ptr;
  225.         return real2ptr(((temp & 0xFFFF0000) >> 12) + (temp & 0xFFFF));
  226. }
  227.  
  228.  
  229. /*
  230. ================
  231. VID_ExtraWaitDisplayEnable
  232. ================
  233. */
  234. void VID_ExtraWaitDisplayEnable ()
  235. {
  236.         while ((inportb (0x3DA) & 0x01) == 1)
  237.                 ;
  238. }
  239.  
  240.  
  241. /*
  242. ================
  243. VID_ExtraVidLookForState
  244. ================
  245. */
  246. qboolean VID_ExtraVidLookForState (unsigned state, unsigned mask)
  247. {
  248.         int             i;
  249.         double  starttime, time;
  250.  
  251.         starttime = Sys_FloatTime ();
  252.  
  253.         do
  254.         {
  255.                 for (i=0 ; i<100000 ; i++)
  256.                 {
  257.                         if ((inportb (0x3DA) & mask) == state)
  258.                                 return true;
  259.                 }
  260.  
  261.                 time = Sys_FloatTime ();
  262.         } while ((time - starttime) < 0.1);
  263.  
  264.         return false;
  265. }
  266.  
  267.  
  268. /*
  269. ================
  270. VID_ExtraStateFound
  271. ================
  272. */
  273. qboolean VID_ExtraStateFound (unsigned state)
  274. {
  275.         int             i, workingstate;
  276.  
  277.         workingstate = 0;
  278.  
  279.         for (i=0 ; i<10 ; i++)
  280.         {
  281.                 if (!VID_ExtraVidLookForState(workingstate, state))
  282.                 {
  283.                         return false;
  284.                 }
  285.  
  286.                 workingstate ^= state;
  287.         }
  288.  
  289.         return true;
  290. }
  291.  
  292.  
  293. /*
  294. ================
  295. VID_InitExtra
  296. ================
  297. */
  298. void VID_InitExtra (void)
  299. {
  300.         int                             nummodes;
  301.         short                   *pmodenums;
  302.         vbeinfoblock_t  *pinfoblock;
  303.         __dpmi_meminfo  phys_mem_info;
  304.  
  305.         pinfoblock = dos_getmemory(sizeof(vbeinfoblock_t));
  306.  
  307.         *(long *)pinfoblock->VbeSignature = 'V' + ('B'<<8) + ('E'<<16) + ('2'<<24);
  308.  
  309. // see if VESA support is available
  310.         regs.x.ax = 0x4f00;
  311.         regs.x.es = ptr2real(pinfoblock) >> 4;
  312.         regs.x.di = ptr2real(pinfoblock) & 0xf;
  313.         dos_int86(0x10);
  314.  
  315.         if (regs.x.ax != 0x4f)
  316.                 return;         // no VESA support
  317.  
  318.         if (pinfoblock->VbeVersion[1] < 0x02)
  319.                 return;         // not VESA 2.0 or greater
  320.  
  321.         Con_Printf ("VESA 2.0 compliant adapter:\n%s\n",
  322.                                 VID_ExtraFarToLinear (*(byte **)&pinfoblock->OemStringPtr[0]));
  323.  
  324.         totalvidmem = *(unsigned short *)&pinfoblock->TotalMemory[0] << 16;
  325.  
  326.         pmodenums = (short *)
  327.                         VID_ExtraFarToLinear (*(byte **)&pinfoblock->VideoModePtr[0]);
  328.  
  329. // find 8 bit modes until we either run out of space or run out of modes
  330.         nummodes = 0;
  331.  
  332.         while ((*pmodenums != -1) && (nummodes < MAX_VESA_MODES))
  333.         {
  334.                 if (VID_ExtraGetModeInfo (*pmodenums))
  335.                 {
  336.                         vesa_modes[nummodes].pnext = &vesa_modes[nummodes+1];
  337.                         if (modeinfo.width > 999)
  338.                         {
  339.                                 if (modeinfo.height > 999)
  340.                                 {
  341.                                         sprintf (&names[nummodes][0], "%4dx%4d", modeinfo.width,
  342.                                                          modeinfo.height);
  343.                                         names[nummodes][9] = 0;
  344.                                 }
  345.                                 else
  346.                                 {
  347.                                         sprintf (&names[nummodes][0], "%4dx%3d", modeinfo.width,
  348.                                                          modeinfo.height);
  349.                                         names[nummodes][8] = 0;
  350.                                 }
  351.                         }
  352.                         else
  353.                         {
  354.                                 if (modeinfo.height > 999)
  355.                                 {
  356.                                         sprintf (&names[nummodes][0], "%3dx%4d", modeinfo.width,
  357.                                                          modeinfo.height);
  358.                                         names[nummodes][8] = 0;
  359.                                 }
  360.                                 else
  361.                                 {
  362.                                         sprintf (&names[nummodes][0], "%3dx%3d", modeinfo.width,
  363.                                                          modeinfo.height);
  364.                                         names[nummodes][7] = 0;
  365.                                 }
  366.                         }
  367.  
  368.                         vesa_modes[nummodes].name = &names[nummodes][0];
  369.                         vesa_modes[nummodes].width = modeinfo.width;
  370.                         vesa_modes[nummodes].height = modeinfo.height;
  371.                         vesa_modes[nummodes].aspect =
  372.                                         ((float)modeinfo.height / (float)modeinfo.width) *
  373.                                         (320.0 / 240.0);
  374.                         vesa_modes[nummodes].rowbytes = modeinfo.bytes_per_scanline;
  375.                         vesa_modes[nummodes].planar = 0;
  376.                         vesa_modes[nummodes].pextradata = &vesa_extra[nummodes];
  377.                         vesa_modes[nummodes].setmode = VID_ExtraInitMode;
  378.                         vesa_modes[nummodes].swapbuffers = VID_ExtraSwapBuffers;
  379.                         vesa_modes[nummodes].setpalette = VID_SetVESAPalette;
  380.  
  381.                         if (modeinfo.mode_attributes & LINEAR_FRAME_BUFFER)
  382.                         {
  383.                         // add linear bit to mode for linear modes
  384.                                 vesa_extra[nummodes].vesamode = modeinfo.modenum | LINEAR_MODE;
  385.                                 vesa_extra[nummodes].pages[0] = 0;
  386.                                 vesa_extra[nummodes].pages[1] = modeinfo.pagesize;
  387.                                 vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2;
  388.                                 vesa_modes[nummodes].numpages = modeinfo.numpages;
  389.  
  390.                                 vesa_modes[nummodes].begindirectrect = VGA_BeginDirectRect;
  391.                                 vesa_modes[nummodes].enddirectrect = VGA_EndDirectRect;
  392.  
  393.                                 phys_mem_info.address = (int)modeinfo.pptr;
  394.                                 phys_mem_info.size = 0x400000;
  395.  
  396.                                 if (__dpmi_physical_address_mapping(&phys_mem_info))
  397.                                         goto NextMode;
  398.  
  399.                                 vesa_extra[nummodes].plinearmem =
  400.                                                  real2ptr (phys_mem_info.address);
  401.                         }
  402.                         else
  403.                         {
  404.                         // banked at 0xA0000
  405.                                 vesa_extra[nummodes].vesamode = modeinfo.modenum;
  406.                                 vesa_extra[nummodes].pages[0] = 0;
  407.                                 vesa_extra[nummodes].plinearmem =
  408.                                                 real2ptr(modeinfo.winasegment<<4);
  409.  
  410.                                 vesa_modes[nummodes].begindirectrect =
  411.                                                 VGA_BankedBeginDirectRect;
  412.                                 vesa_modes[nummodes].enddirectrect = VGA_BankedEndDirectRect;
  413.                                 vesa_extra[nummodes].pages[1] = modeinfo.pagesize;
  414.                                 vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2;
  415.                                 vesa_modes[nummodes].numpages = modeinfo.numpages;
  416.                         }
  417.  
  418.                         vesa_extra[nummodes].vga_incompatible =
  419.                                         modeinfo.mode_attributes & VGA_INCOMPATIBLE;
  420.  
  421.                         nummodes++;
  422.                 }
  423. NextMode:
  424.                 pmodenums++;
  425.         }
  426.  
  427. // add the VESA modes at the start of the mode list (if there are any)
  428.         if (nummodes)
  429.         {
  430.                 vesa_modes[nummodes-1].pnext = pvidmodes;
  431.                 pvidmodes = &vesa_modes[0];
  432.                 numvidmodes += nummodes;
  433.                 ppal = dos_getmemory(256*4);
  434.         }
  435.  
  436.         dos_freememory(pinfoblock);
  437. }
  438.  
  439.  
  440. /*
  441. ================
  442. VID_ExtraGetModeInfo
  443. ================
  444. */
  445. qboolean VID_ExtraGetModeInfo(int modenum)
  446. {
  447.         char    *infobuf;
  448.         int             numimagepages;
  449.  
  450.         infobuf = dos_getmemory(256);
  451.  
  452.         regs.x.ax = 0x4f01;
  453.         regs.x.cx = modenum;
  454.         regs.x.es = ptr2real(infobuf) >> 4;
  455.         regs.x.di = ptr2real(infobuf) & 0xf;
  456.         dos_int86(0x10);
  457.         if (regs.x.ax != 0x4f)
  458.         {
  459.                 return false;
  460.         }
  461.         else
  462.         {
  463.                 modeinfo.modenum = modenum;
  464.                 modeinfo.bits_per_pixel = *(char*)(infobuf+25);
  465.                 modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8;
  466.                 modeinfo.width = *(short*)(infobuf+18);
  467.                 modeinfo.height = *(short*)(infobuf+20);
  468.  
  469.         // we do only 8-bpp in software
  470.                 if ((modeinfo.bits_per_pixel != 8) ||
  471.                         (modeinfo.bytes_per_pixel != 1) ||
  472.                         (modeinfo.width > MAXWIDTH) ||
  473.                         (modeinfo.height > MAXHEIGHT))
  474.                 {
  475.                         return false;
  476.                 }
  477.  
  478.                 modeinfo.mode_attributes = *(short*)infobuf;
  479.  
  480.         // we only want color graphics modes that are supported by the hardware
  481.                 if ((modeinfo.mode_attributes &
  482.                          (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) !=
  483.                         (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE))
  484.                 {
  485.                         return false;
  486.                 }
  487.  
  488.         // we only work with linear frame buffers, except for 320x200, which can
  489.         // effectively be linear when banked at 0xA000
  490.                 if (!(modeinfo.mode_attributes & LINEAR_FRAME_BUFFER))
  491.                 {
  492.                         if ((modeinfo.width != 320) || (modeinfo.height != 200))
  493.                                 return false;
  494.                 }
  495.  
  496.                 modeinfo.bytes_per_scanline = *(short*)(infobuf+16);
  497.  
  498.                 modeinfo.pagesize = modeinfo.bytes_per_scanline * modeinfo.height;
  499.  
  500.                 if (modeinfo.pagesize > totalvidmem)
  501.                         return false;
  502.  
  503.         // force to one page if the adapter reports it doesn't support more pages
  504.         // than that, no matter how much memory it has--it may not have hardware
  505.         // support for page flipping
  506.                 numimagepages = *(unsigned char *)(infobuf+29);
  507.  
  508.                 if (numimagepages <= 0)
  509.                 {
  510.                 // wrong, but there seems to be an ATI VESA driver that reports 0
  511.                         modeinfo.numpages = 1;
  512.                 }
  513.                 else if (numimagepages < 3)
  514.                 {
  515.                         modeinfo.numpages = numimagepages;
  516.                 }
  517.                 else
  518.                 {
  519.                         modeinfo.numpages = 3;
  520.                 }
  521.  
  522.                 if (*(char*)(infobuf+2) & 5)
  523.                 {
  524.                         modeinfo.winasegment = *(unsigned short*)(infobuf+8);
  525.                         modeinfo.win = 0;
  526.                 }
  527.                 else if (*(char*)(infobuf+3) & 5)
  528.                 {
  529.                         modeinfo.winbsegment = *(unsigned short*)(infobuf+8);
  530.                         modeinfo.win = 1;
  531.                 }
  532.                 modeinfo.granularity = *(short*)(infobuf+4) * 1024;
  533.                 modeinfo.win_size = *(short*)(infobuf+6) * 1024;
  534.                 modeinfo.bits_per_pixel = *(char*)(infobuf+25);
  535.                 modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8;
  536.                 modeinfo.memory_model = *(unsigned char*)(infobuf+27);
  537.                 modeinfo.num_pages = *(char*)(infobuf+29) + 1;
  538.  
  539.                 modeinfo.red_width = *(char*)(infobuf+31);
  540.                 modeinfo.red_pos = *(char*)(infobuf+32);
  541.                 modeinfo.green_width = *(char*)(infobuf+33);
  542.                 modeinfo.green_pos = *(char*)(infobuf+34);
  543.                 modeinfo.blue_width = *(char*)(infobuf+35);
  544.                 modeinfo.blue_pos = *(char*)(infobuf+36);
  545.  
  546.                 modeinfo.pptr = *(long *)(infobuf+40);
  547.  
  548. #if 0
  549.                 printf("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum);
  550.                 printf("  mode attrib = 0x%0x\n", modeinfo.mode_attributes);
  551.                 printf("  win a attrib = 0x%0x\n", *(unsigned char*)(infobuf+2));
  552.                 printf("  win b attrib = 0x%0x\n", *(unsigned char*)(infobuf+3));
  553.                 printf("  win a seg 0x%0x\n", (int) modeinfo.winasegment);
  554.                 printf("  win b seg 0x%0x\n", (int) modeinfo.winbsegment);
  555.                 printf("  bytes per scanline = %d\n",
  556.                                 modeinfo.bytes_per_scanline);
  557.                 printf("  width = %d, height = %d\n", modeinfo.width,
  558.                                 modeinfo.height);
  559.                 printf("  win = %c\n", 'A' + modeinfo.win);
  560.                 printf("  win granularity = %d\n", modeinfo.granularity);
  561.                 printf("  win size = %d\n", modeinfo.win_size);
  562.                 printf("  bits per pixel = %d\n", modeinfo.bits_per_pixel);
  563.                 printf("  bytes per pixel = %d\n", modeinfo.bytes_per_pixel);
  564.                 printf("  memory model = 0x%x\n", modeinfo.memory_model);
  565.                 printf("  num pages = %d\n", modeinfo.num_pages);
  566.                 printf("  red width = %d\n", modeinfo.red_width);
  567.                 printf("  red pos = %d\n", modeinfo.red_pos);
  568.                 printf("  green width = %d\n", modeinfo.green_width);
  569.                 printf("  green pos = %d\n", modeinfo.green_pos);
  570.                 printf("  blue width = %d\n", modeinfo.blue_width);
  571.                 printf("  blue pos = %d\n", modeinfo.blue_pos);
  572.                 printf("  phys mem = %x\n", modeinfo.pptr);
  573. #endif
  574.         }
  575.  
  576.         dos_freememory(infobuf);
  577.  
  578.         return true;
  579. }
  580.  
  581.  
  582. /*
  583. ================
  584. VID_ExtraInitMode
  585. ================
  586. */
  587. int VID_ExtraInitMode (viddef_t *lvid, vmode_t *pcurrentmode)
  588. {
  589.         vesa_extra_t    *pextra;
  590.         int                             pageoffset;
  591.  
  592.         pextra = pcurrentmode->pextradata;
  593.  
  594.         if (vid_nopageflip.value)
  595.                 lvid->numpages = 1;
  596.         else
  597.                 lvid->numpages = pcurrentmode->numpages;
  598.  
  599. // clean up any old vid buffer lying around, alloc new if needed
  600.         if (!VGA_FreeAndAllocVidbuffer (lvid, lvid->numpages == 1))
  601.                 return -1;      // memory alloc failed
  602.  
  603. // clear the screen and wait for the next frame. VGA_pcurmode, which
  604. // VGA_ClearVideoMem relies on, is guaranteed to be set because mode 0 is
  605. // always the first mode set in a session
  606.         if (VGA_pcurmode)
  607.                 VGA_ClearVideoMem (VGA_pcurmode->planar);
  608.  
  609. // set the mode
  610.         regs.x.ax = 0x4f02;
  611.         regs.x.bx = pextra->vesamode;
  612.         dos_int86(0x10);
  613.  
  614.         if (regs.x.ax != 0x4f)
  615.                 return 0;
  616.  
  617.         VID_banked = !(pextra->vesamode & LINEAR_MODE);
  618.         VID_membase = pextra->plinearmem;
  619.         VGA_width = lvid->width;
  620.         VGA_height = lvid->height;
  621.         VGA_rowbytes = lvid->rowbytes;
  622.  
  623.         lvid->colormap = host_colormap;
  624.  
  625.         VID_pagelist = &pextra->pages[0];
  626.  
  627. // wait for display enable by default only when triple-buffering on a VGA-
  628. // compatible machine that actually has a functioning display enable status
  629.         vsync_exists = VID_ExtraStateFound (0x08);
  630.         de_exists = VID_ExtraStateFound (0x01);
  631.  
  632.         if (!pextra->vga_incompatible  &&
  633.                 (lvid->numpages == 3)      &&
  634.                 de_exists                  &&
  635.                 (_vid_wait_override.value == 0.0))
  636.         {
  637.                 Cvar_SetValue ("vid_wait", (float)VID_WAIT_DISPLAY_ENABLE);
  638.  
  639.                 VID_displayedpage = 0;
  640.                 VID_currentpage = 1;
  641.         }
  642.         else
  643.         {
  644.                 if ((lvid->numpages == 1) && (_vid_wait_override.value == 0.0))
  645.                 {
  646.                         Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE);
  647.                         VID_displayedpage = VID_currentpage = 0;
  648.                 }
  649.                 else
  650.                 {
  651.                         Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC);
  652.  
  653.                         VID_displayedpage = 0;
  654.  
  655.                         if (lvid->numpages > 1)
  656.                                 VID_currentpage = 1;
  657.                         else
  658.                                 VID_currentpage = 0;
  659.                 }
  660.         }
  661.  
  662. // TODO: really should be a call to a function
  663.         pageoffset = VID_pagelist[VID_displayedpage];
  664.  
  665.         regs.x.ax = 0x4f07;
  666.         regs.x.bx = 0x80;       // wait for vsync so we know page 0 is visible
  667.         regs.x.cx = pageoffset % VGA_rowbytes;
  668.         regs.x.dx = pageoffset / VGA_rowbytes;
  669.         dos_int86(0x10);
  670.  
  671.         if (VID_banked)
  672.         {
  673.                 regs.x.ax = 0x4f05;
  674.                 regs.x.bx = 0;
  675.                 regs.x.dx = VID_currentpage;
  676.                 dos_int86(0x10);
  677.  
  678.                 VGA_pagebase = VID_membase;
  679.         }
  680.         else
  681.         {
  682.                 VGA_pagebase = VID_membase + VID_pagelist[VID_currentpage];
  683.         }
  684.  
  685.         if (lvid->numpages > 1)
  686.         {
  687.                 lvid->buffer = VGA_pagebase;
  688.                 lvid->conbuffer = lvid->buffer;
  689.         }
  690.         else
  691.         {
  692.                 lvid->rowbytes = lvid->width;
  693.         }
  694.  
  695.         lvid->direct = VGA_pagebase;
  696.         lvid->conrowbytes = lvid->rowbytes;
  697.         lvid->conwidth = lvid->width;
  698.         lvid->conheight = lvid->height;
  699.  
  700.         lvid->maxwarpwidth = WARP_WIDTH;
  701.         lvid->maxwarpheight = WARP_HEIGHT;
  702.  
  703.         VGA_pcurmode = pcurrentmode;
  704.  
  705.         D_InitCaches (vid_surfcache, vid_surfcachesize);
  706.  
  707.         return 1;
  708. }
  709.  
  710.  
  711. /*
  712. ================
  713. VID_ExtraSwapBuffers
  714. ================
  715. */
  716. void VID_ExtraSwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode,
  717.         vrect_t *rects)
  718. {
  719.         int     pageoffset;
  720.  
  721.         UNUSED(rects);
  722.         UNUSED(pcurrentmode);
  723.  
  724.         pageoffset = VID_pagelist[VID_currentpage];
  725.  
  726. // display the newly finished page
  727.         if (lvid->numpages > 1)
  728.         {
  729.         // page flipped
  730.                 regs.x.ax = 0x4f07;
  731.        
  732.                 if (vid_wait.value != VID_WAIT_VSYNC)
  733.                 {
  734.                         if ((vid_wait.value == VID_WAIT_DISPLAY_ENABLE) && de_exists)
  735.                                 VID_ExtraWaitDisplayEnable ();
  736.        
  737.                         regs.x.bx = VESA_DONT_WAIT_VSYNC;
  738.                 }
  739.                 else
  740.                 {
  741.                         regs.x.bx = VESA_WAIT_VSYNC;    // double buffered has to wait
  742.                 }
  743.  
  744.                 regs.x.cx = pageoffset % VGA_rowbytes;
  745.                 regs.x.dx = pageoffset / VGA_rowbytes;
  746.                 dos_int86(0x10);
  747.        
  748.                 VID_displayedpage = VID_currentpage;
  749.                 if (++VID_currentpage >= lvid->numpages)
  750.                         VID_currentpage = 0;
  751.        
  752.         //
  753.         // set the new write window if this is a banked mode; otherwise, set the
  754.         // new address to which to write
  755.         //
  756.                 if (VID_banked)
  757.                 {
  758.                         regs.x.ax = 0x4f05;
  759.                         regs.x.bx = 0;
  760.                         regs.x.dx = VID_currentpage;
  761.                         dos_int86(0x10);
  762.                 }
  763.                 else
  764.                 {
  765.                         lvid->direct = lvid->buffer;    // direct drawing goes to the
  766.                                                                                         //  currently displayed page
  767.                         lvid->buffer = VID_membase + VID_pagelist[VID_currentpage];
  768.                         lvid->conbuffer = lvid->buffer;
  769.                 }
  770.        
  771.                 VGA_pagebase = lvid->buffer;
  772.         }
  773.         else
  774.         {
  775.         // non-page-flipped
  776.                 if (vsync_exists && (vid_wait.value == VID_WAIT_VSYNC))
  777.                 {
  778.                         VGA_WaitVsync ();
  779.                 }
  780.  
  781.                 while (rects)
  782.                 {
  783.                         VGA_UpdateLinearScreen (
  784.                                         lvid->buffer + rects->x + (rects->y * lvid->rowbytes),
  785.                                         VGA_pagebase + rects->x + (rects->y * VGA_rowbytes),
  786.                                         rects->width,
  787.                                         rects->height,
  788.                                         lvid->rowbytes,
  789.                                         VGA_rowbytes);
  790.  
  791.                         rects = rects->pnext;
  792.                 }
  793.         }
  794. }
  795.  
  796.