home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / vid_amiga.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  17KB  |  717 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. /*
  22. ** vid_amiga.c
  23. **
  24. ** Amiga Video Drivers
  25. **
  26. ** AGA, CGX and ChunkyPPC
  27. **
  28. ** Written by Frank Wille <frank@phoenix.owl.de>
  29. **     and Steffen Häuser <magicsn@birdland.es.bawue.de>
  30. **
  31. ** FIXME: Support for DirectRect is missing
  32. **
  33. */
  34.  
  35. #define  CALC_SURFCACHE
  36.  
  37. #pragma amiga-align
  38. #include <exec/libraries.h>
  39. #include <exec/memory.h>
  40. #include <intuition/screens.h>
  41. #include <proto/exec.h>
  42. #ifdef __PPC__
  43. #ifdef WOS
  44. #include <clib/powerpc_protos.h>
  45. #else
  46. #include <powerup/gcclib/powerup_protos.h>
  47. #endif
  48. #endif
  49. #pragma default-align
  50.  
  51. #include "quakedef.h"
  52. #include "d_local.h"
  53. #include "vid_amiga.h"
  54.  
  55.  
  56. extern byte *r_warpbuffer;
  57.  
  58. #define AGAC2P 0
  59. #define CYBERGFX 1
  60. #define CHUNKYPPC 2
  61. static int gfxmode = CYBERGFX;  /* one of the constants above */
  62.  
  63. /* Library bases used by the video drivers */
  64. struct Library *GfxBase=NULL;
  65. struct Library *CyberGfxBase=NULL;
  66. struct Library *P96Base=NULL;
  67. struct Library *RtgBase=NULL;
  68. struct Library *ChunkyPPCBase=NULL;
  69. struct Library *IntuitionBase=NULL;
  70. struct Library *AslBase=NULL;
  71.  
  72. viddef_t vid;                    /* global video state */
  73. byte *vid_buffer = NULL;
  74. short *zbuffer = NULL;
  75. static int vid_buf_offs = 0;
  76. int config_notify=0;
  77. int shutdown_keyboard=0;
  78. struct Screen *QuakeScreen = NULL;  /* will be assigned by the video driver */
  79.  
  80. #ifndef CALC_SURFCACHE
  81. #define SURFCACHESIZE_SMALL     256*1024
  82. #define SURFCACHESIZE_MEDIUM    512*1024
  83. #define SURFCACHESIZE_LARGE     1024*1024
  84. static byte surfcache[SURFCACHESIZE_LARGE];
  85. #else
  86. static byte* surfcache;
  87. static int surfcachesize;
  88. #endif
  89.  
  90. unsigned short d_8to16table[256];
  91. unsigned d_8to24table[256];
  92.  
  93. unsigned char rawkeyconv[] = {
  94.   '`','1','2','3','4','5','6','7','8','9','0','-','=','\\',0,'0',
  95.   'q','w','e','r','t','y','u','i','o','p','[',']',0,K_END,K_DOWNARROW,K_PGDN,
  96.   'a','s','d','f','g','h','j','k','l',';','\'',K_F12,0,K_LEFTARROW,0,K_RIGHTARROW,
  97.   K_F11,'z','x','c','v','b','n','m',',','.','/',0,0,K_HOME,K_UPARROW,K_PGUP,
  98.   K_SPACE,K_BACKSPACE,K_TAB,K_ENTER,K_ENTER,K_ESCAPE,K_DEL,0,
  99.   0,0,'-',0,K_UPARROW,K_DOWNARROW,K_RIGHTARROW,K_LEFTARROW,
  100.   K_F1,K_F2,K_F3,K_F4,K_F5,K_F6,K_F7,K_F8,K_F9,K_F10,'(',')','/','*','+',K_PAUSE,
  101.   K_SHIFT,K_SHIFT,0,K_CTRL,K_ALT,K_ALT,0,0,
  102.   K_MOUSE1,K_MOUSE2,K_MOUSE3
  103. };
  104.  
  105.  
  106. void VID_MenuDraw (void);
  107. void VID_MenuKey (int);
  108. void M_Menu_Options_f(void);
  109.  
  110. byte vid_current_palette[768];
  111.  
  112.  
  113.  
  114. void VID_SetPalette (unsigned char *palette)
  115. {
  116.   if (palette!=vid_current_palette) Q_memcpy(vid_current_palette,palette,768);
  117.  
  118.   switch (gfxmode) {
  119.     case AGAC2P:
  120.       VID_SetPalette_AGA(palette);
  121.       break;
  122.     case CYBERGFX:
  123.       VID_SetPalette_CGFX(palette);
  124.       break;
  125.     case CHUNKYPPC:
  126.       VID_SetPalette_ChunkyPPC(palette);
  127.       break;
  128.   }
  129. }
  130.  
  131.  
  132. void VID_ShiftPalette (unsigned char *palette)
  133. {
  134.   VID_SetPalette(palette);
  135. }
  136.  
  137. int vid_modenum;
  138. int modearray_x[11]={320,320,320,400,480,512,640,640,800,1024,1280};
  139. int modearray_y[11]={200,240,400,300,384,384,400,480,600,768,1024};
  140.  
  141. void VID_MenuDraw(void);
  142. void VID_MenuKey(int key);
  143.  
  144. cvar_t vid_mode={"vid_mode","1",false};
  145. cvar_t _vid_default_mode={"_vid_default_mode","1",true};
  146.  
  147. int firstopen=1;
  148.  
  149. void VID_Init (unsigned char *palette)
  150. {
  151.   char *module = "VID_Init: ";
  152.   int i;
  153.  
  154.     if (!(IntuitionBase = OpenLibrary("intuition.library",36)))
  155.         Sys_Error("%sCan't open intuition.library V36",module);
  156.  
  157.   if (firstopen)
  158.   {
  159.    vid_modenum=_vid_default_mode.value;
  160.    Cvar_SetValue("vid_mode",vid_modenum);
  161.    firstopen=0;
  162.    vid_mode.value=_vid_default_mode.value;
  163.   }
  164.  
  165.   gfxmode=-1;
  166.  
  167.   if (i = COM_CheckParm("-cppc"))
  168.     gfxmode = CHUNKYPPC;
  169.   if (i = COM_CheckParm("-cgfx"))
  170.     gfxmode = CYBERGFX;
  171.   if (i = COM_CheckParm("-aga"))
  172.     gfxmode = AGAC2P;
  173.  
  174.   if (gfxmode==-1)
  175.   {
  176.     char strMode[255];
  177.     if (0<GetVar("env:Quake1/gfxmode",strMode,255,0))
  178.     {
  179.       if (!stricmp(strMode,"chunkyppc")) gfxmode=CHUNKYPPC;
  180.       else if (!stricmp(strMode,"cybergfx")) gfxmode=CYBERGFX;
  181.       else if (!stricmp(strMode,"agac2p")) gfxmode=AGAC2P;
  182.       else gfxmode=CHUNKYPPC;
  183.     }
  184.     else 
  185.     {
  186. #ifdef WOS
  187.       struct Library *LibBase=OpenLibrary("chunkyppc.library",13);
  188.       if (LibBase)
  189.       {
  190.         gfxmode=CHUNKYPPC;
  191.         CloseLibrary(LibBase);
  192.         LibBase=0;
  193.       }
  194.       else gfxmode=CYBERGFX;  
  195. #else
  196.       gfxmode=CHUNKYPPC;
  197. #endif
  198.     }
  199.   }
  200.  
  201.   switch (gfxmode) {
  202.     case AGAC2P:
  203.       VID_Init_AGA(palette);
  204.       break;
  205.     case CYBERGFX:
  206.       VID_Init_CGFX(palette);
  207.       break;
  208.     case CHUNKYPPC:
  209.       VID_Init_ChunkyPPC(palette);
  210.       break;
  211.   }
  212.  
  213.   vid.colormap = host_colormap;
  214.   vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
  215.  
  216. #ifdef __PPC__
  217. #ifdef WOS
  218.   if (!(vid_buffer = (byte *)AllocVecPPC(vid.width * vid.height,
  219.                                          MEMF_FAST|MEMF_PUBLIC,0)))
  220.     Sys_Error("%sNot enough memory for video buffer",module);
  221.   if (!(zbuffer = (short *)AllocVecPPC(vid.width * vid.height * 2,
  222.                                        MEMF_FAST|MEMF_PUBLIC,0)))
  223.     Sys_Error("%sNot enough memory for z-buffer",module);
  224.   if (!(r_warpbuffer = (byte *)AllocVecPPC(vid.width * vid.height,
  225.                                            MEMF_FAST|MEMF_PUBLIC,0)))
  226.     Sys_Error("%sNot enough memory for warp buffer",module);
  227.  
  228. #else /* PowerUp */
  229.   if (!(vid_buffer = (byte *)PPCAllocVec(vid.width * vid.height,
  230.                                          MEMF_FAST|MEMF_PUBLIC)))
  231.     Sys_Error("%sNot enough memory for video buffer",module);
  232.   if (!(zbuffer = (short *)PPCAllocVec(vid.width * vid.height * 2,
  233.                                        MEMF_FAST|MEMF_PUBLIC)))
  234.     Sys_Error("%sNot enough memory for z-buffer",module);
  235.   if (!(r_warpbuffer = (byte *)PPCAllocVec(vid.width * vid.height,
  236.                                            MEMF_FAST|MEMF_PUBLIC)))
  237.     Sys_Error("%sNot enough memory for warp buffer",module);
  238. #endif
  239.  
  240. #else /* M68k */
  241.   if (!(vid_buffer = (byte *)AllocMem(vid.width * vid.height + 8,
  242.                                       MEMF_FAST|MEMF_PUBLIC)))
  243.     Sys_Error("%sNot enough memory for video buffer",module);
  244.   if ((ULONG)vid_buffer & 8) {   /* 16-byte aligment */
  245.     vid_buffer += 8;
  246.     vid_buf_offs = 8;
  247.   }
  248.   if (!(zbuffer = (short *)AllocMem(vid.width * vid.height * 2,
  249.                                     MEMF_FAST|MEMF_PUBLIC)))
  250.     Sys_Error("%sNot enough memory for z-buffer",module);
  251.   if (!(r_warpbuffer = (byte *)AllocMem(vid.width * vid.height,
  252.                                         MEMF_FAST|MEMF_PUBLIC)))
  253.     Sys_Error("%sNot enough memory for warp buffer",module);
  254. #endif
  255.  
  256.   vid.conbuffer = vid.buffer = vid_buffer;
  257.   d_pzbuffer = zbuffer;
  258.   vid.maxwarpwidth = vid.rowbytes;
  259.   vid.maxwarpheight = vid.height;
  260.  
  261. #ifndef CALC_SURFCACHE
  262.   if ((vid.width*vid.height) < 65000)
  263.     D_InitCaches (surfcache, SURFCACHESIZE_SMALL);
  264.   else if ((vid.width*vid.height) < 200000)
  265.     D_InitCaches (surfcache, SURFCACHESIZE_MEDIUM);
  266.   else
  267.     D_InitCaches (surfcache, SURFCACHESIZE_LARGE);
  268.  
  269. #else
  270.   surfcachesize = D_SurfaceCacheForRes(vid.width,vid.height);
  271.  
  272. #ifdef __PPC__
  273. #ifdef WOS
  274.   if (!(surfcache = (byte *)AllocVecPPC(surfcachesize,MEMF_FAST,0)))
  275.     Sys_Error("%sNot enough memory for surface cache",module);
  276. #else /* PowerUp */
  277.   if (!(surfcache = (byte *)PPCAllocVec(surfcachesize,MEMF_FAST)))
  278.     Sys_Error("%sNot enough memory for surface cache",module);
  279. #endif
  280. #else /* M68k */
  281.   if (!(surfcache = (byte *)AllocMem(surfcachesize,MEMF_FAST)))
  282.     Sys_Error("%sNot enough memory for surface cache",module);
  283. #endif
  284.   D_InitCaches (surfcache, surfcachesize);
  285. #endif
  286.   if (gfxmode!=AGAC2P)
  287.   {
  288.     vid_menudrawfn=VID_MenuDraw;
  289.     vid_menukeyfn=VID_MenuKey;
  290.   }
  291.   else
  292.   {
  293.     vid_menudrawfn=0;
  294.     vid_menukeyfn=0;
  295.   }
  296. }
  297.  
  298.  
  299. void VID_Shutdown (void)
  300. {
  301.   D_FlushCaches();
  302. #ifdef __PPC__
  303. #ifdef WOS
  304. #ifdef CALC_SURFCACHE
  305.   if (surfcache)
  306.     FreeVecPPC(surfcache);
  307. #endif
  308.   if (r_warpbuffer)
  309.     FreeVecPPC(r_warpbuffer);
  310.   if (zbuffer)
  311.     FreeVecPPC(zbuffer);
  312.   if (vid_buffer)
  313.     FreeVecPPC(vid_buffer);
  314.  
  315. #else /* PowerUp */
  316. #ifdef CALC_SURFCACHE
  317.   if (surfcache)
  318.     PPCFreeVec(surfcache);
  319. #endif
  320.   if (r_warpbuffer)
  321.     PPCFreeVec(r_warpbuffer);
  322.   if (zbuffer)
  323.     PPCFreeVec(zbuffer);
  324.   if (vid_buffer)
  325.     PPCFreeVec(vid_buffer);
  326. #endif
  327.  
  328. #else /* M68k */
  329. #ifndef CALC_SURFCACHE
  330.   if (surfcache)
  331.     FreeMem(surfcache,surfcachesize);
  332. #endif
  333.   if (r_warpbuffer)
  334.     FreeMem(r_warpbuffer,vid.width * vid.height);
  335.   if (zbuffer)
  336.     FreeMem(zbuffer,vid.width * vid.height * 2);
  337.   if (vid_buffer)
  338.     FreeMem(vid_buffer-vid_buf_offs,vid.width*vid.height + 8);
  339. #endif
  340.  
  341.   switch (gfxmode) {
  342.     case AGAC2P:
  343.       VID_Shutdown_AGA();
  344.       break;
  345.     case CYBERGFX:
  346.       VID_Shutdown_CGFX();
  347.       break;
  348.     case CHUNKYPPC:
  349.       VID_Shutdown_ChunkyPPC();
  350.       break;
  351.   }
  352.  
  353.   if (IntuitionBase)
  354.     CloseLibrary(IntuitionBase);
  355. }
  356.  
  357. void VID_Update (vrect_t *rects)
  358. {
  359.   if (config_notify)
  360.   {
  361.     D_FlushCaches();
  362.     vid.recalc_refdef=1;
  363. #ifdef WOS
  364.     if (vid_buffer) FreeVecPPC(vid_buffer);
  365.     vid_buffer=0;
  366.     if (zbuffer) FreeVecPPC(zbuffer);
  367.     zbuffer=0;
  368.     if (r_warpbuffer) FreeVecPPC(r_warpbuffer);
  369.     d_viewbuffer=r_warpbuffer;
  370.     r_warpbuffer=0;
  371. #ifdef CALC_SURFCACHE
  372.     if (surfcache) FreeVecPPC(surfcache);
  373.     surfcache=0;
  374. #endif
  375. #else
  376. #ifdef __PPC__
  377.     if (vid_buffer) PPCFreeVec(vid_buffer);
  378.     vid_buffer=0;
  379.     if (zbuffer) PPCFreeVec(zbuffer);
  380.     zbuffer=0;
  381.     if (r_warpbuffer) PPCFreeVec(r_warpbuffer);
  382.     d_viewbuffer=r_warpbuffer;
  383.     r_warpbuffer=0;
  384. #ifdef CALC_SURFCACHE
  385.     if (surfcache) PPCFreeVec(surfcache);
  386.     surfcache=0;
  387. #endif
  388. #else
  389.     if (vid_buffer) FreeMem(vid_buffer-vid_buf_offs,vid.width*vid.height + 8);
  390.     vid_buffer=0;
  391.     if (zbuffer) FreeMem(zbuffer,vid.width * vid.height * 2);
  392.     zbuffer=0;
  393.     if (r_warpbuffer) FreeMem(r_warpbuffer,vid.width * vid.height);
  394.     d_viewbuffer=r_warpbuffer;
  395.     r_warpbuffer=0;
  396. #ifdef CALC_SURFCACHE
  397.     if (surfcache) FreeMem(surfcache,surfcachesize);
  398.     surfcache=0;
  399. #endif
  400. #endif
  401. #endif
  402.     if (gfxmode==CYBERGFX) VID_Shutdown_CGFX();
  403.     VID_Init(vid_current_palette);
  404.     shutdown_keyboard=1;
  405.     config_notify=0;
  406.     Con_CheckResize();
  407.     Con_Clear_f();
  408.     return;
  409.   }
  410.  
  411.   switch (gfxmode) {
  412.     case AGAC2P:
  413.       VID_Update_AGA(rects);
  414.       break;
  415.     case CYBERGFX:
  416.       VID_Update_CGFX(rects);
  417.       break;
  418.     case CHUNKYPPC:
  419.       VID_Update_ChunkyPPC(rects);
  420.       break;
  421.   }
  422. }
  423.  
  424.  
  425. void Sys_SendKeyEvents (void)
  426. {
  427.   switch (gfxmode) {
  428.     case AGAC2P:
  429.       Sys_SendKeyEvents_AGA();
  430.       break;
  431.     case CYBERGFX:
  432.       Sys_SendKeyEvents_CGFX();
  433.       break;
  434.     case CHUNKYPPC:
  435.       Sys_SendKeyEvents_ChunkyPPC();
  436.       break;
  437.   }
  438. }
  439.  
  440.  
  441. /*
  442. ================
  443. D_BeginDirectRect
  444. ================
  445. */
  446. void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
  447. {
  448. }
  449.  
  450.  
  451. /*
  452. ================
  453. D_EndDirectRect
  454. ================
  455. */
  456. void D_EndDirectRect (int x, int y, int width, int height)
  457. {
  458. }
  459.  
  460.  
  461. int numvidmodes=11;
  462. static int vid_wmodes,vid_line;
  463. int vid_column_size;
  464.  
  465. typedef struct
  466. {
  467.   int     modenum;
  468.   char    *desc;
  469.   int     iscur;
  470. } modedesc_t;
  471.  
  472. #define MAX_COLUMN_SIZE 11
  473. #define MAX_MODEDESCS   33
  474. static modedesc_t   modedescs[33];
  475.  
  476. typedef struct vmode_s {
  477.   struct vmode_s *pnext;
  478.   char           *name;
  479.   char           *header;
  480.   unsigned       width;
  481.   unsigned       height;
  482. } vmode_t;
  483.  
  484.  
  485. vmode_t vmode10={0,"1280*1024","HiRes V",1280,1024};
  486. vmode_t vmode9={&vmode10,"1024*768","HiRes IV",1024,768};
  487. vmode_t vmode8={&vmode9,"800*600","HiRes III",800,600};
  488. vmode_t vmode7={&vmode8,"640*480","HiRes II",640,480};
  489. vmode_t vmode6={&vmode7,"640*400","HiRes I",640,400};
  490. vmode_t vmode5={&vmode6,"512*384","MedRes III",512,384};
  491. vmode_t vmode4={&vmode5,"480*384","MedRes II",480,384};
  492. vmode_t vmode3={&vmode4,"400*300","MedRes I",400,300};
  493. vmode_t vmode2={&vmode3,"320*400","LowRes III",320,400};
  494. vmode_t vmode1={&vmode2,"320*240","LowRes II",320,240};
  495. vmode_t vmode0={&vmode1,"320*200","LowRes I",320,200};
  496. vmode_t *pvidmodes=&vmode0;
  497.  
  498. int VID_NumModes ()
  499. {
  500.   return (numvidmodes);
  501. }
  502.  
  503. vmode_t *VID_GetModePtr (int modenum)
  504. {
  505.   vmode_t *pv;
  506.   pv = pvidmodes;
  507.   if (!pv) Sys_Error ("VID_GetModePtr: empty vid mode list");
  508.   while (modenum--)
  509.   {
  510.     pv = pv->pnext;     
  511.     if (!pv) Sys_Error ("VID_GetModePtr: corrupt vid mode list");
  512.   }
  513.   return pv;
  514. }
  515.  
  516. char *VID_ModeInfo (int modenum, char **ppheader)
  517. {
  518.   static char *badmodestr = "Bad mode number";
  519.   vmode_t     *pv;
  520.   pv = VID_GetModePtr (modenum);
  521.   if (!pv)
  522.   {
  523.      if (ppheader) *ppheader = NULL;
  524.      return badmodestr;
  525.   }
  526.   else
  527.   {
  528.       if (ppheader) *ppheader = pv->header;
  529.       return pv->name;
  530.   }
  531. }
  532.  
  533. char *VID_GetModeDescription (int mode)
  534. {
  535.   char        *pinfo, *pheader;
  536.   vmode_t     *pv;
  537.   pv = VID_GetModePtr (mode);
  538.   pinfo = VID_ModeInfo (mode, &pheader);
  539.   return pinfo;
  540. }
  541.  
  542. /*
  543. ================
  544. VID_MenuDraw
  545. ================
  546. */
  547.  
  548. void VID_MenuDraw (void)
  549. {
  550.   qpic_t      *p;
  551.   char        *ptr;
  552.   int         nummodes, i, j, column, row, dup;
  553.   char        temp[100];
  554.  
  555.   vid_wmodes = 0;
  556.   nummodes = VID_NumModes ();
  557.   
  558.   p = Draw_CachePic ("gfx/vidmodes.lmp");
  559.   M_DrawPic ( (320-p->width)/2, 4, p);
  560.  
  561.   for (i=0 ; i<nummodes ; i++)
  562.   {
  563.     if (vid_wmodes < MAX_MODEDESCS)
  564.     {
  565.       ptr = VID_GetModeDescription (i);
  566.       if (ptr)
  567.       {
  568.         dup = 0;
  569.  
  570.         for (j=0 ; j<vid_wmodes ; j++)
  571.         {
  572.           if (!strcmp (modedescs[j].desc, ptr))
  573.           {
  574.             if (modedescs[j].modenum != 0)
  575.             {
  576.               modedescs[j].modenum = i;
  577.               dup = 1;
  578.  
  579.               if (i == vid_modenum) modedescs[j].iscur = 1;
  580.             }
  581.             else
  582.             {
  583.               dup = 1;
  584.             }
  585.             break;
  586.           }
  587.         }
  588.  
  589.         if (!dup)
  590.         {
  591.           modedescs[vid_wmodes].modenum = i;
  592.           modedescs[vid_wmodes].desc = ptr;
  593.           modedescs[vid_wmodes].iscur = 0;
  594.  
  595.           if (i == vid_modenum) modedescs[vid_wmodes].iscur = 1;
  596.  
  597.           vid_wmodes++;
  598.         }
  599.       }
  600.     }
  601.   }
  602.  
  603.   vid_column_size = (vid_wmodes + 2) / 3;
  604.  
  605.   column = 16;
  606.   row = 36;
  607.  
  608.   for (i=0 ; i<vid_wmodes ; i++)
  609.   {
  610.     if (modedescs[i].iscur) M_PrintWhite (column, row, modedescs[i].desc);
  611.     else M_Print (column, row, modedescs[i].desc);
  612.  
  613.     row += 8;
  614.  
  615.     if ((i % vid_column_size) == (vid_column_size - 1))
  616.     {
  617.       column += 13*8;
  618.       row = 36;
  619.     }
  620.   }
  621.  
  622.   M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8*3, "Press Enter to set mode");
  623.   ptr = VID_GetModeDescription (vid_modenum);
  624.   sprintf (temp, "D to make %s the default", ptr);
  625.   M_Print (6*8, 36 + MAX_COLUMN_SIZE * 8 + 8*5, temp);
  626.   ptr = VID_GetModeDescription ((int)_vid_default_mode.value);
  627.  
  628.   if (ptr)
  629.   {
  630.     sprintf (temp, "Current default is %s", ptr);
  631.     M_Print (7*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6, temp);
  632.   }
  633.  
  634.   M_Print (15*8, 36 + MAX_COLUMN_SIZE * 8 + 8*8, "Esc to exit");
  635.  
  636.   row = 36 + (vid_line % vid_column_size) * 8;
  637.   column = 8 + (vid_line / vid_column_size) * 13*8;
  638.  
  639.   M_DrawCharacter (column, row, 12+((int)(realtime*4)&1));
  640. }
  641.  
  642. /*
  643. ================
  644. VID_MenuKey
  645. ================
  646. */
  647. void VID_MenuKey (int key)
  648. {
  649.   switch (key)
  650.   {
  651.     case K_ESCAPE:
  652.       S_LocalSound ("misc/menu1.wav");
  653.       M_Menu_Options_f ();
  654.       break;
  655.   
  656.     case K_UPARROW:
  657.       S_LocalSound ("misc/menu1.wav");
  658.       vid_line--;
  659.   
  660.       if (vid_line < 0) vid_line = vid_wmodes - 1;
  661.       break;
  662.   
  663.     case K_DOWNARROW:
  664.       S_LocalSound ("misc/menu1.wav");
  665.       vid_line++;
  666.  
  667.       if (vid_line >= vid_wmodes)
  668.       vid_line = 0;
  669.       break;
  670.   
  671.     case K_LEFTARROW:
  672.       S_LocalSound ("misc/menu1.wav");
  673.       vid_line -= vid_column_size;
  674.   
  675.       if (vid_line < 0)
  676.       {
  677.         vid_line += ((vid_wmodes + (vid_column_size - 1)) /
  678.                      vid_column_size) * vid_column_size;
  679.   
  680.         while (vid_line >= vid_wmodes)
  681.                vid_line -= vid_column_size;
  682.       }
  683.       break;
  684.   
  685.     case K_RIGHTARROW:
  686.       S_LocalSound ("misc/menu1.wav");
  687.       vid_line += vid_column_size;
  688.   
  689.       if (vid_line >= vid_wmodes)
  690.       {
  691.         vid_line -= ((vid_wmodes + (vid_column_size - 1)) /
  692.                      vid_column_size) * vid_column_size;
  693.   
  694.         while (vid_line < 0)
  695.           vid_line += vid_column_size;
  696.       }
  697.       break;
  698.   
  699.     case K_ENTER:
  700.       S_LocalSound ("misc/menu1.wav");
  701.       Cvar_SetValue("vid_mode",modedescs[vid_line].modenum);
  702.       vid_modenum=modedescs[vid_line].modenum;
  703.       config_notify=1;
  704.       break;
  705.  
  706.     case 'D':
  707.     case 'd':
  708.       S_LocalSound ("misc/menu1.wav");
  709.       Cvar_SetValue ("_vid_default_mode", modedescs[vid_line].modenum);
  710.       vid_modenum=modedescs[vid_line].modenum;
  711.       break;
  712.  
  713.     default:
  714.       break;
  715.   }
  716. }
  717.