home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / vid_dos.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  16KB  |  779 lines

  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_dos.c: DOS-specific video routines
  22. //
  23.  
  24. #include <unistd.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <dos.h>
  29. #include <dpmi.h>
  30. #include <go32.h>
  31.  
  32. #include "quakedef.h"
  33. #include "d_local.h"
  34. #include "dosisms.h"
  35. #include "vid_dos.h"
  36.  
  37. int     vid_modenum;
  38. vmode_t   *pcurrentmode = NULL;
  39. int     vid_testingmode, vid_realmode;
  40. double    vid_testendtime;
  41.  
  42. cvar_t    vid_mode = {"vid_mode","0", false};
  43. cvar_t    vid_wait = {"vid_wait","0"};
  44. cvar_t    vid_nopageflip = {"vid_nopageflip","0", true};
  45. cvar_t    _vid_wait_override = {"_vid_wait_override", "0", true};
  46. cvar_t    _vid_default_mode = {"_vid_default_mode","0", true};
  47. cvar_t    _vid_default_mode_win = {"_vid_default_mode_win","1", true};
  48. cvar_t    vid_config_x = {"vid_config_x","800", true};
  49. cvar_t    vid_config_y = {"vid_config_y","600", true};
  50. cvar_t    vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
  51. cvar_t    _windowed_mouse = {"_windowed_mouse","0", true};
  52. cvar_t    vid_fullscreen_mode = {"vid_fullscreen_mode","3", true};
  53. cvar_t    vid_windowed_mode = {"vid_windowed_mode","0", true};
  54. cvar_t    block_switch = {"block_switch","0", true};
  55. cvar_t    vid_window_x = {"vid_window_x", "0", true};
  56. cvar_t    vid_window_y = {"vid_window_y", "0", true};
  57.  
  58. int d_con_indirect = 0;
  59.  
  60. int   numvidmodes;
  61. vmode_t *pvidmodes;
  62.  
  63. static int  firstupdate = 1;
  64.  
  65. extern regs_t regs;
  66.  
  67. void VID_TestMode_f (void);
  68. void VID_NumModes_f (void);
  69. void VID_DescribeCurrentMode_f (void);
  70. void VID_DescribeMode_f (void);
  71. void VID_DescribeModes_f (void);
  72.  
  73. byte  vid_current_palette[768]; // save for mode changes
  74.  
  75.  
  76. static qboolean nomodecheck = false;
  77.  
  78. unsigned short  d_8to16table[256];  // not used in 8 bpp mode
  79. unsigned    d_8to24table[256];  // not used in 8 bpp mode
  80.  
  81. void VID_MenuDraw (void);
  82. void VID_MenuKey (int key);
  83.  
  84.  
  85. /*
  86. ================
  87. VID_Init
  88. ================
  89. */
  90. void    VID_Init (unsigned char *palette)
  91. {
  92.   Cvar_RegisterVariable (&vid_mode);
  93.   Cvar_RegisterVariable (&vid_wait);
  94.   Cvar_RegisterVariable (&vid_nopageflip);
  95.   Cvar_RegisterVariable (&_vid_wait_override);
  96.   Cvar_RegisterVariable (&_vid_default_mode);
  97.   Cvar_RegisterVariable (&_vid_default_mode_win);
  98.   Cvar_RegisterVariable (&vid_config_x);
  99.   Cvar_RegisterVariable (&vid_config_y);
  100.   Cvar_RegisterVariable (&vid_stretch_by_2);
  101.   Cvar_RegisterVariable (&_windowed_mouse);
  102.   Cvar_RegisterVariable (&vid_fullscreen_mode);
  103.   Cvar_RegisterVariable (&vid_windowed_mode);
  104.   Cvar_RegisterVariable (&block_switch);
  105.  
  106.   Cmd_AddCommand ("vid_testmode", VID_TestMode_f);
  107.   Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
  108.   Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
  109.   Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
  110.   Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
  111.  
  112. // set up the mode list; note that later inits link in their modes ahead of
  113. // earlier ones, so the standard VGA modes are always first in the list. This
  114. // is important because mode 0 must always be VGA mode 0x13
  115.   if (!COM_CheckParm ("-stdvid"))
  116.     VID_InitExtra ();
  117.   VGA_Init ();
  118.  
  119.   vid_testingmode = 0;
  120.  
  121.   vid_modenum = vid_mode.value;
  122.  
  123.   VID_SetMode (vid_modenum, palette);
  124.  
  125.   vid_realmode = vid_modenum;
  126.   
  127.   vid_menudrawfn = VID_MenuDraw;
  128.   vid_menukeyfn = VID_MenuKey;
  129. }
  130.  
  131.  
  132. /*
  133. =================
  134. VID_GetModePtr
  135. =================
  136. */
  137. vmode_t *VID_GetModePtr (int modenum)
  138. {
  139.   vmode_t *pv;
  140.  
  141.   pv = pvidmodes;
  142.   if (!pv)
  143.     Sys_Error ("VID_GetModePtr: empty vid mode list");
  144.  
  145.   while (modenum--)
  146.   {
  147.     pv = pv->pnext;
  148.     if (!pv)
  149.       Sys_Error ("VID_GetModePtr: corrupt vid mode list");
  150.   }
  151.  
  152.   return pv;
  153. }
  154.  
  155. /*
  156. ================
  157. VID_NumModes
  158. ================
  159. */
  160. int VID_NumModes ()
  161. {
  162.   return (numvidmodes);
  163. }
  164.  
  165.  
  166. /*
  167. ================
  168. VID_ModeInfo
  169. ================
  170. */
  171. char *VID_ModeInfo (int modenum, char **ppheader)
  172. {
  173.   static char *badmodestr = "Bad mode number";
  174.   vmode_t   *pv;
  175.  
  176.   pv = VID_GetModePtr (modenum);
  177.  
  178.   if (!pv)
  179.   {
  180.     if (ppheader)
  181.       *ppheader = NULL;
  182.     return badmodestr;
  183.   }
  184.   else
  185.   {
  186.     if (ppheader)
  187.       *ppheader = pv->header;
  188.     return pv->name;
  189.   }
  190. }
  191.  
  192.  
  193. /*
  194. ================
  195. VID_SetMode 
  196. ================
  197. */
  198. int VID_SetMode (int modenum, unsigned char *palette)
  199. {
  200.   int   stat;
  201.   vmode_t *pnewmode, *poldmode;
  202.  
  203.   if ((modenum >= numvidmodes) || (modenum < 0))
  204.   {
  205.     Cvar_SetValue ("vid_mode", (float)vid_modenum);
  206.  
  207.     nomodecheck = true;
  208.     Con_Printf ("No such video mode: %d\n", modenum);
  209.     nomodecheck = false;
  210.  
  211.     if (pcurrentmode == NULL)
  212.     {
  213.       modenum = 0;  // mode hasn't been set yet, so initialize to base
  214.               //  mode since they gave us an invalid initial mode
  215.     }
  216.     else
  217.     {
  218.       return 0;
  219.     }
  220.   }
  221.  
  222.   pnewmode = VID_GetModePtr (modenum);
  223.  
  224.   if (pnewmode == pcurrentmode)
  225.     return 1; // already in the desired mode
  226.  
  227. // initialize the new mode
  228.   poldmode = pcurrentmode;
  229.   pcurrentmode = pnewmode;
  230.  
  231.   vid.width = pcurrentmode->width;
  232.   vid.height = pcurrentmode->height;
  233.   vid.aspect = pcurrentmode->aspect;
  234.   vid.rowbytes = pcurrentmode->rowbytes;
  235.  
  236.   stat = (*pcurrentmode->setmode) (&vid, pcurrentmode);
  237.  
  238.   if (stat < 1)
  239.   {
  240.     if (stat == 0)
  241.     {
  242.     // real, hard failure that requires resetting the mode
  243.       if (!VID_SetMode (vid_modenum, palette))  // restore prior mode
  244.         Sys_Error ("VID_SetMode: Unable to set any mode, probably "
  245.                "because there's not enough memory available");
  246.       Con_Printf ("Failed to set mode %d\n", modenum);
  247.       return 0;
  248.     }
  249.     else if (stat == -1)
  250.     {
  251.     // not enough memory; just put things back the way they were
  252.       pcurrentmode = poldmode;
  253.       vid.width = pcurrentmode->width;
  254.       vid.height = pcurrentmode->height;
  255.       vid.aspect = pcurrentmode->aspect;
  256.       vid.rowbytes = pcurrentmode->rowbytes;
  257.       return 0;
  258.     }
  259.     else
  260.     {
  261.       Sys_Error ("VID_SetMode: invalid setmode return code %d");
  262.     }
  263.   }
  264.  
  265.   (*pcurrentmode->setpalette) (&vid, pcurrentmode, palette);
  266.  
  267.   vid_modenum = modenum;
  268.   Cvar_SetValue ("vid_mode", (float)vid_modenum);
  269.  
  270.   nomodecheck = true;
  271.   Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL));
  272.   nomodecheck = false;
  273.  
  274.   vid.recalc_refdef = 1;
  275.  
  276.   return 1;
  277. }
  278.  
  279.  
  280. /*
  281. ================
  282. VID_SetPalette
  283. ================
  284. */
  285. void    VID_SetPalette (unsigned char *palette)
  286. {
  287.   if (palette != vid_current_palette)
  288.     Q_memcpy(vid_current_palette, palette, 768);
  289.   (*pcurrentmode->setpalette)(&vid, pcurrentmode, vid_current_palette);
  290. }
  291.  
  292.  
  293. /*
  294. ================
  295. VID_ShiftPalette
  296. ================
  297. */
  298. void    VID_ShiftPalette (unsigned char *palette)
  299. {
  300.  
  301.   VID_SetPalette (palette);
  302. }
  303.  
  304.  
  305. /*
  306. ================
  307. VID_Shutdown
  308. ================
  309. */
  310. void VID_Shutdown (void)
  311. {
  312.  
  313.   regs.h.ah = 0;
  314.   regs.h.al = 0x3;
  315.   dos_int86(0x10);
  316.  
  317.   vid_testingmode = 0;
  318. }
  319.  
  320.  
  321. /*
  322. ================
  323. VID_Update
  324. ================
  325. */
  326. void    VID_Update (vrect_t *rects)
  327. {
  328.   if (firstupdate && _vid_default_mode.value)
  329.   {
  330.     if(_vid_default_mode.value >= numvidmodes)
  331.       Cvar_SetValue ("_vid_default_mode", 0);
  332.  
  333.     firstupdate = 0;
  334.     Cvar_SetValue ("vid_mode", _vid_default_mode.value);
  335.   }
  336.  
  337.   (*pcurrentmode->swapbuffers)(&vid, pcurrentmode, rects);
  338.  
  339.   if (!nomodecheck)
  340.   {
  341.     if (vid_testingmode)
  342.     {
  343.       if (realtime >= vid_testendtime)
  344.       {
  345.         VID_SetMode (vid_realmode, vid_current_palette);
  346.         vid_testingmode = 0;
  347.       }
  348.     }
  349.     else
  350.     {
  351.       if (vid_mode.value != vid_realmode)
  352.       {
  353.         VID_SetMode ((int)vid_mode.value, vid_current_palette);
  354.         Cvar_SetValue ("vid_mode", (float)vid_modenum);
  355.                   // so if mode set fails, we don't keep on
  356.                   //  trying to set that mode
  357.         vid_realmode = vid_modenum;
  358.       }
  359.     }
  360.   }
  361. }
  362.  
  363.  
  364. /*
  365. =================
  366. VID_NumModes_f
  367. =================
  368. */
  369. void VID_NumModes_f (void)
  370. {
  371.   int   nummodes;
  372.  
  373.   nummodes = VID_NumModes ();
  374.   if (nummodes == 1)
  375.     Con_Printf ("%d video mode is available\n", VID_NumModes ());
  376.   else
  377.     Con_Printf ("%d video modes are available\n", VID_NumModes ());
  378. }
  379.  
  380.  
  381. /*
  382. =================
  383. VID_DescribeCurrentMode_f
  384. =================
  385. */
  386. void VID_DescribeCurrentMode_f (void)
  387. {
  388.   Con_Printf ("%s\n", VID_ModeInfo (vid_modenum, NULL));
  389. }
  390.  
  391.  
  392. /*
  393. =================
  394. VID_DescribeMode_f
  395. =================
  396. */
  397. void VID_DescribeMode_f (void)
  398. {
  399.   int   modenum;
  400.   
  401.   modenum = Q_atoi (Cmd_Argv(1));
  402.  
  403.   Con_Printf ("%s\n", VID_ModeInfo (modenum, NULL));
  404. }
  405.  
  406.  
  407. /*
  408. =================
  409. VID_DescribeModes_f
  410. =================
  411. */
  412. void VID_DescribeModes_f (void)
  413. {
  414.   int     i, nummodes;
  415.   char    *pinfo, *pheader;
  416.   vmode_t   *pv;
  417.   qboolean  na;
  418.  
  419.   na = false;
  420.  
  421.   nummodes = VID_NumModes ();
  422.   for (i=0 ; i<nummodes ; i++)
  423.   {
  424.     pv = VID_GetModePtr (i);
  425.     pinfo = VID_ModeInfo (i, &pheader);
  426.     if (pheader)
  427.       Con_Printf ("\n%s\n", pheader);
  428.  
  429.     if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes,
  430.       (pv->numpages == 1) || vid_nopageflip.value))
  431.     {
  432.       Con_Printf ("%2d: %s\n", i, pinfo);
  433.     }
  434.     else
  435.     {
  436.       Con_Printf ("**: %s\n", pinfo);
  437.       na = true;
  438.     }
  439.   }
  440.  
  441.   if (na)
  442.   {
  443.     Con_Printf ("\n[**: not enough system RAM for mode]\n");
  444.   }
  445. }
  446.  
  447.  
  448. /*
  449. =================
  450. VID_GetModeDescription
  451. =================
  452. */
  453. char *VID_GetModeDescription (int mode)
  454. {
  455.   char    *pinfo, *pheader;
  456.   vmode_t   *pv;
  457.  
  458.   pv = VID_GetModePtr (mode);
  459.   pinfo = VID_ModeInfo (mode, &pheader);
  460.  
  461.   if (VGA_CheckAdequateMem (pv->width, pv->height, pv->rowbytes,
  462.     (pv->numpages == 1) || vid_nopageflip.value))
  463.   {
  464.     return pinfo;
  465.   }
  466.   else
  467.   {
  468.     return NULL;
  469.   }
  470. }
  471.  
  472.  
  473. /*
  474. =================
  475. VID_TestMode_f
  476. =================
  477. */
  478. void VID_TestMode_f (void)
  479. {
  480.   int   modenum;
  481.   double  testduration;
  482.  
  483.   if (!vid_testingmode)
  484.   {
  485.     modenum = Q_atoi (Cmd_Argv(1));
  486.  
  487.     if (VID_SetMode (modenum, vid_current_palette))
  488.     {
  489.       vid_testingmode = 1;
  490.       testduration = Q_atof (Cmd_Argv(2));
  491.       if (testduration == 0)
  492.         testduration = 5.0;
  493.       vid_testendtime = realtime + testduration;
  494.     }
  495.   }
  496. }
  497.  
  498.  
  499. /*
  500. ================
  501. D_BeginDirectRect
  502. ================
  503. */
  504. void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
  505. {
  506.  
  507.   if (!vid.direct || !pcurrentmode)
  508.     return;
  509.  
  510.   if ((width > 24) || (height > 24) || (width < 1) || (height < 1))
  511.     return;
  512.  
  513.   if (width & 0x03)
  514.     return;
  515.  
  516.   (*pcurrentmode->begindirectrect) (&vid, pcurrentmode, x, y, pbitmap, width,
  517.                     height);
  518. }
  519.  
  520.  
  521. /*
  522. ================
  523. D_EndDirectRect
  524. ================
  525. */
  526. void D_EndDirectRect (int x, int y, int width, int height)
  527. {
  528.  
  529.   if (!vid.direct || !pcurrentmode)
  530.     return;
  531.  
  532.   if ((width > 24) || (height > 24) || (width < 1) || (height < 1))
  533.     return;
  534.  
  535.   if ((width & 0x03) || (height & 0x03))
  536.     return;
  537.  
  538.   (*pcurrentmode->enddirectrect) (&vid, pcurrentmode, x, y, width, height);
  539. }
  540.  
  541.  
  542. //===========================================================================
  543.  
  544. extern void M_Menu_Options_f (void);
  545. extern void M_Print (int cx, int cy, char *str);
  546. extern void M_PrintWhite (int cx, int cy, char *str);
  547. extern void M_DrawCharacter (int cx, int line, int num);
  548. extern void M_DrawTransPic (int x, int y, qpic_t *pic);
  549. extern void M_DrawPic (int x, int y, qpic_t *pic);
  550.  
  551. static int  vid_line, vid_wmodes, vid_column_size;
  552.  
  553. typedef struct
  554. {
  555.   int   modenum;
  556.   char  *desc;
  557.   int   iscur;
  558. } modedesc_t;
  559.  
  560. #define MAX_COLUMN_SIZE 11
  561.  
  562. #define MAX_MODEDESCS (MAX_COLUMN_SIZE*3)
  563.  
  564. static modedesc_t modedescs[MAX_MODEDESCS];
  565.  
  566. /*
  567. ================
  568. VID_MenuDraw
  569. ================
  570. */
  571. void VID_MenuDraw (void)
  572. {
  573.   qpic_t    *p;
  574.   char    *ptr;
  575.   int     nummodes, i, j, column, row, dup;
  576.   char    temp[100];
  577.  
  578.   vid_wmodes = 0;
  579.   nummodes = VID_NumModes ();
  580.   
  581.   p = Draw_CachePic ("gfx/vidmodes.lmp");
  582.   M_DrawPic ( (320-p->width)/2, 4, p);
  583.  
  584.   for (i=0 ; i<nummodes ; i++)
  585.   {
  586.     if (vid_wmodes < MAX_MODEDESCS)
  587.     {
  588.       if (i != 1)
  589.       {
  590.         ptr = VID_GetModeDescription (i);
  591.  
  592.         if (ptr)
  593.         {
  594.           dup = 0;
  595.  
  596.           for (j=0 ; j<vid_wmodes ; j++)
  597.           {
  598.             if (!strcmp (modedescs[j].desc, ptr))
  599.             {
  600.               if (modedescs[j].modenum != 0)
  601.               {
  602.                 modedescs[j].modenum = i;
  603.                 dup = 1;
  604.  
  605.                 if (i == vid_modenum)
  606.                   modedescs[j].iscur = 1;
  607.               }
  608.               else
  609.               {
  610.                 dup = 1;
  611.               }
  612.  
  613.               break;
  614.             }
  615.           }
  616.  
  617.           if (!dup)
  618.           {
  619.             modedescs[vid_wmodes].modenum = i;
  620.             modedescs[vid_wmodes].desc = ptr;
  621.             modedescs[vid_wmodes].iscur = 0;
  622.  
  623.             if (i == vid_modenum)
  624.               modedescs[vid_wmodes].iscur = 1;
  625.  
  626.             vid_wmodes++;
  627.           }
  628.         }
  629.       }
  630.     }
  631.   }
  632.  
  633.   vid_column_size = (vid_wmodes + 2) / 3;
  634.  
  635.   column = 16;
  636.   row = 36;
  637.  
  638.   for (i=0 ; i<vid_wmodes ; i++)
  639.   {
  640.     if (modedescs[i].iscur)
  641.       M_PrintWhite (column, row, modedescs[i].desc);
  642.     else
  643.       M_Print (column, row, modedescs[i].desc);
  644.  
  645.     row += 8;
  646.  
  647.     if ((i % vid_column_size) == (vid_column_size - 1))
  648.     {
  649.       column += 13*8;
  650.       row = 36;
  651.     }
  652.   }
  653.  
  654. // line cursor
  655.   if (vid_testingmode)
  656.   {
  657.     sprintf (temp, "TESTING %s",
  658.         modedescs[vid_line].desc);
  659.     M_Print (13*8, 36 + MAX_COLUMN_SIZE * 8 + 8*4, temp);
  660.     M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6,
  661.         "Please wait 5 seconds...");
  662.   }
  663.   else
  664.   {
  665.     M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8,
  666.         "Press Enter to set mode");
  667.     M_Print (6*8, 36 + MAX_COLUMN_SIZE * 8 + 8*3,
  668.         "T to test mode for 5 seconds");
  669.     ptr = VID_GetModeDescription (vid_modenum);
  670.     sprintf (temp, "D to make %s the default", ptr);
  671.     M_Print (6*8, 36 + MAX_COLUMN_SIZE * 8 + 8*5, temp);
  672.     ptr = VID_GetModeDescription ((int)_vid_default_mode.value);
  673.  
  674.     if (ptr)
  675.     {
  676.       sprintf (temp, "Current default is %s", ptr);
  677.       M_Print (7*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6, temp);
  678.     }
  679.  
  680.     M_Print (15*8, 36 + MAX_COLUMN_SIZE * 8 + 8*8,
  681.         "Esc to exit");
  682.  
  683.     row = 36 + (vid_line % vid_column_size) * 8;
  684.     column = 8 + (vid_line / vid_column_size) * 13*8;
  685.  
  686.     M_DrawCharacter (column, row, 12+((int)(realtime*4)&1));
  687.   }
  688. }
  689.  
  690.  
  691. /*
  692. ================
  693. VID_MenuKey
  694. ================
  695. */
  696. void VID_MenuKey (int key)
  697. {
  698.   if (vid_testingmode)
  699.     return;
  700.  
  701.   switch (key)
  702.   {
  703.   case K_ESCAPE:
  704.     S_LocalSound ("misc/menu1.wav");
  705.     M_Menu_Options_f ();
  706.     break;
  707.  
  708.   case K_UPARROW:
  709.     S_LocalSound ("misc/menu1.wav");
  710.     vid_line--;
  711.  
  712.     if (vid_line < 0)
  713.       vid_line = vid_wmodes - 1;
  714.     break;
  715.  
  716.   case K_DOWNARROW:
  717.     S_LocalSound ("misc/menu1.wav");
  718.     vid_line++;
  719.  
  720.     if (vid_line >= vid_wmodes)
  721.       vid_line = 0;
  722.     break;
  723.  
  724.   case K_LEFTARROW:
  725.     S_LocalSound ("misc/menu1.wav");
  726.     vid_line -= vid_column_size;
  727.  
  728.     if (vid_line < 0)
  729.     {
  730.       vid_line += ((vid_wmodes + (vid_column_size - 1)) /
  731.           vid_column_size) * vid_column_size;
  732.  
  733.       while (vid_line >= vid_wmodes)
  734.         vid_line -= vid_column_size;
  735.     }
  736.     break;
  737.  
  738.   case K_RIGHTARROW:
  739.     S_LocalSound ("misc/menu1.wav");
  740.     vid_line += vid_column_size;
  741.  
  742.     if (vid_line >= vid_wmodes)
  743.     {
  744.       vid_line -= ((vid_wmodes + (vid_column_size - 1)) /
  745.           vid_column_size) * vid_column_size;
  746.  
  747.       while (vid_line < 0)
  748.         vid_line += vid_column_size;
  749.     }
  750.     break;
  751.  
  752.   case K_ENTER:
  753.     S_LocalSound ("misc/menu1.wav");
  754.     VID_SetMode (modedescs[vid_line].modenum, vid_current_palette);
  755.     break;
  756.  
  757.   case 'T':
  758.   case 't':
  759.     S_LocalSound ("misc/menu1.wav");
  760.     if (VID_SetMode (modedescs[vid_line].modenum, vid_current_palette))
  761.     {
  762.       vid_testingmode = 1;
  763.       vid_testendtime = realtime + 5.0;
  764.     }
  765.     break;
  766.  
  767.   case 'D':
  768.   case 'd':
  769.     S_LocalSound ("misc/menu1.wav");
  770.     firstupdate = 0;
  771.     Cvar_SetValue ("_vid_default_mode", vid_modenum);
  772.     break;
  773.  
  774.   default:
  775.     break;
  776.   }
  777. }
  778.  
  779.