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