Home | History | Annotate | Download | only in WinQuake
      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 // gl_vidnt.c -- NT GL vid component
     21 
     22 #include "quakedef.h"
     23 #include "winquake.h"
     24 #include "resource.h"
     25 #include <commctrl.h>
     26 
     27 #define MAX_MODE_LIST	30
     28 #define VID_ROW_SIZE	3
     29 #define WARP_WIDTH		320
     30 #define WARP_HEIGHT		200
     31 #define MAXWIDTH		10000
     32 #define MAXHEIGHT		10000
     33 #define BASEWIDTH		320
     34 #define BASEHEIGHT		200
     35 
     36 #define MODE_WINDOWED			0
     37 #define NO_MODE					(MODE_WINDOWED - 1)
     38 #define MODE_FULLSCREEN_DEFAULT	(MODE_WINDOWED + 1)
     39 
     40 typedef struct {
     41 	modestate_t	type;
     42 	int			width;
     43 	int			height;
     44 	int			modenum;
     45 	int			dib;
     46 	int			fullscreen;
     47 	int			bpp;
     48 	int			halfscreen;
     49 	char		modedesc[17];
     50 } vmode_t;
     51 
     52 typedef struct {
     53 	int			width;
     54 	int			height;
     55 } lmode_t;
     56 
     57 lmode_t	lowresmodes[] = {
     58 	{320, 200},
     59 	{320, 240},
     60 	{400, 300},
     61 	{512, 384},
     62 };
     63 
     64 const char *gl_vendor;
     65 const char *gl_renderer;
     66 const char *gl_version;
     67 const char *gl_extensions;
     68 
     69 qboolean		DDActive;
     70 qboolean		scr_skipupdate;
     71 
     72 static vmode_t	modelist[MAX_MODE_LIST];
     73 static int		nummodes;
     74 static vmode_t	*pcurrentmode;
     75 static vmode_t	badmode;
     76 
     77 static DEVMODE	gdevmode;
     78 static qboolean	vid_initialized = false;
     79 static qboolean	windowed, leavecurrentmode;
     80 static qboolean vid_canalttab = false;
     81 static qboolean vid_wassuspended = false;
     82 static int		windowed_mouse;
     83 extern qboolean	mouseactive;  // from in_win.c
     84 static HICON	hIcon;
     85 
     86 int			DIBWidth, DIBHeight;
     87 RECT		WindowRect;
     88 DWORD		WindowStyle, ExWindowStyle;
     89 
     90 HWND	mainwindow, dibwindow;
     91 
     92 int			vid_modenum = NO_MODE;
     93 int			vid_realmode;
     94 int			vid_default = MODE_WINDOWED;
     95 static int	windowed_default;
     96 unsigned char	vid_curpal[256*3];
     97 static qboolean fullsbardraw = false;
     98 
     99 static float vid_gamma = 1.0;
    100 
    101 HGLRC	baseRC;
    102 HDC		maindc;
    103 
    104 glvert_t glv;
    105 
    106 cvar_t	gl_ztrick = {"gl_ztrick","1"};
    107 
    108 HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
    109 
    110 viddef_t	vid;				// global video state
    111 
    112 unsigned short	d_8to16table[256];
    113 unsigned	d_8to24table[256];
    114 unsigned char d_15to8table[65536];
    115 
    116 float		gldepthmin, gldepthmax;
    117 
    118 modestate_t	modestate = MS_UNINIT;
    119 
    120 void VID_MenuDraw (void);
    121 void VID_MenuKey (int key);
    122 
    123 LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    124 void AppActivate(BOOL fActive, BOOL minimize);
    125 char *VID_GetModeDescription (int mode);
    126 void ClearAllStates (void);
    127 void VID_UpdateWindowStatus (void);
    128 void GL_Init (void);
    129 
    130 PROC glArrayElementEXT;
    131 PROC glColorPointerEXT;
    132 PROC glTexCoordPointerEXT;
    133 PROC glVertexPointerEXT;
    134 
    135 typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*);
    136 lp3DFXFUNC glColorTableEXT;
    137 qboolean is8bit = false;
    138 qboolean isPermedia = false;
    139 qboolean gl_mtexable = false;
    140 
    141 //====================================
    142 
    143 cvar_t		vid_mode = {"vid_mode","0", false};
    144 // Note that 0 is MODE_WINDOWED
    145 cvar_t		_vid_default_mode = {"_vid_default_mode","0", true};
    146 // Note that 3 is MODE_FULLSCREEN_DEFAULT
    147 cvar_t		_vid_default_mode_win = {"_vid_default_mode_win","3", true};
    148 cvar_t		vid_wait = {"vid_wait","0"};
    149 cvar_t		vid_nopageflip = {"vid_nopageflip","0", true};
    150 cvar_t		_vid_wait_override = {"_vid_wait_override", "0", true};
    151 cvar_t		vid_config_x = {"vid_config_x","800", true};
    152 cvar_t		vid_config_y = {"vid_config_y","600", true};
    153 cvar_t		vid_stretch_by_2 = {"vid_stretch_by_2","1", true};
    154 cvar_t		_windowed_mouse = {"_windowed_mouse","1", true};
    155 
    156 int			window_center_x, window_center_y, window_x, window_y, window_width, window_height;
    157 RECT		window_rect;
    158 
    159 // direct draw software compatability stuff
    160 
    161 void VID_HandlePause (qboolean pause)
    162 {
    163 }
    164 
    165 void VID_ForceLockState (int lk)
    166 {
    167 }
    168 
    169 void VID_LockBuffer (void)
    170 {
    171 }
    172 
    173 void VID_UnlockBuffer (void)
    174 {
    175 }
    176 
    177 int VID_ForceUnlockedAndReturnState (void)
    178 {
    179 	return 0;
    180 }
    181 
    182 void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
    183 {
    184 }
    185 
    186 void D_EndDirectRect (int x, int y, int width, int height)
    187 {
    188 }
    189 
    190 
    191 void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify)
    192 {
    193     RECT    rect;
    194     int     CenterX, CenterY;
    195 
    196 	CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
    197 	CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
    198 	if (CenterX > CenterY*2)
    199 		CenterX >>= 1;	// dual screens
    200 	CenterX = (CenterX < 0) ? 0: CenterX;
    201 	CenterY = (CenterY < 0) ? 0: CenterY;
    202 	SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
    203 			SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
    204 }
    205 
    206 qboolean VID_SetWindowedMode (int modenum)
    207 {
    208 	HDC				hdc;
    209 	int				lastmodestate, width, height;
    210 	RECT			rect;
    211 
    212 	lastmodestate = modestate;
    213 
    214 	WindowRect.top = WindowRect.left = 0;
    215 
    216 	WindowRect.right = modelist[modenum].width;
    217 	WindowRect.bottom = modelist[modenum].height;
    218 
    219 	DIBWidth = modelist[modenum].width;
    220 	DIBHeight = modelist[modenum].height;
    221 
    222 	WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
    223 				  WS_MINIMIZEBOX;
    224 	ExWindowStyle = 0;
    225 
    226 	rect = WindowRect;
    227 	AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
    228 
    229 	width = rect.right - rect.left;
    230 	height = rect.bottom - rect.top;
    231 
    232 	// Create the DIB window
    233 	dibwindow = CreateWindowEx (
    234 		 ExWindowStyle,
    235 		 "WinQuake",
    236 		 "GLQuake",
    237 		 WindowStyle,
    238 		 rect.left, rect.top,
    239 		 width,
    240 		 height,
    241 		 NULL,
    242 		 NULL,
    243 		 global_hInstance,
    244 		 NULL);
    245 
    246 	if (!dibwindow)
    247 		Sys_Error ("Couldn't create DIB window");
    248 
    249 	// Center and show the DIB window
    250 	CenterWindow(dibwindow, WindowRect.right - WindowRect.left,
    251 				 WindowRect.bottom - WindowRect.top, false);
    252 
    253 	ShowWindow (dibwindow, SW_SHOWDEFAULT);
    254 	UpdateWindow (dibwindow);
    255 
    256 	modestate = MS_WINDOWED;
    257 
    258 // because we have set the background brush for the window to NULL
    259 // (to avoid flickering when re-sizing the window on the desktop),
    260 // we clear the window to black when created, otherwise it will be
    261 // empty while Quake starts up.
    262 	hdc = GetDC(dibwindow);
    263 	PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
    264 	ReleaseDC(dibwindow, hdc);
    265 
    266 	if (vid.conheight > modelist[modenum].height)
    267 		vid.conheight = modelist[modenum].height;
    268 	if (vid.conwidth > modelist[modenum].width)
    269 		vid.conwidth = modelist[modenum].width;
    270 	vid.width = vid.conwidth;
    271 	vid.height = vid.conheight;
    272 
    273 	vid.numpages = 2;
    274 
    275 	mainwindow = dibwindow;
    276 
    277 	SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
    278 	SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
    279 
    280 	return true;
    281 }
    282 
    283 
    284 qboolean VID_SetFullDIBMode (int modenum)
    285 {
    286 	HDC				hdc;
    287 	int				lastmodestate, width, height;
    288 	RECT			rect;
    289 
    290 	if (!leavecurrentmode)
    291 	{
    292 		gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
    293 		gdevmode.dmBitsPerPel = modelist[modenum].bpp;
    294 		gdevmode.dmPelsWidth = modelist[modenum].width <<
    295 							   modelist[modenum].halfscreen;
    296 		gdevmode.dmPelsHeight = modelist[modenum].height;
    297 		gdevmode.dmSize = sizeof (gdevmode);
    298 
    299 		if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
    300 			Sys_Error ("Couldn't set fullscreen DIB mode");
    301 	}
    302 
    303 	lastmodestate = modestate;
    304 	modestate = MS_FULLDIB;
    305 
    306 	WindowRect.top = WindowRect.left = 0;
    307 
    308 	WindowRect.right = modelist[modenum].width;
    309 	WindowRect.bottom = modelist[modenum].height;
    310 
    311 	DIBWidth = modelist[modenum].width;
    312 	DIBHeight = modelist[modenum].height;
    313 
    314 	WindowStyle = WS_POPUP;
    315 	ExWindowStyle = 0;
    316 
    317 	rect = WindowRect;
    318 	AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
    319 
    320 	width = rect.right - rect.left;
    321 	height = rect.bottom - rect.top;
    322 
    323 	// Create the DIB window
    324 	dibwindow = CreateWindowEx (
    325 		 ExWindowStyle,
    326 		 "WinQuake",
    327 		 "GLQuake",
    328 		 WindowStyle,
    329 		 rect.left, rect.top,
    330 		 width,
    331 		 height,
    332 		 NULL,
    333 		 NULL,
    334 		 global_hInstance,
    335 		 NULL);
    336 
    337 	if (!dibwindow)
    338 		Sys_Error ("Couldn't create DIB window");
    339 
    340 	ShowWindow (dibwindow, SW_SHOWDEFAULT);
    341 	UpdateWindow (dibwindow);
    342 
    343 	// Because we have set the background brush for the window to NULL
    344 	// (to avoid flickering when re-sizing the window on the desktop), we
    345 	// clear the window to black when created, otherwise it will be
    346 	// empty while Quake starts up.
    347 	hdc = GetDC(dibwindow);
    348 	PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
    349 	ReleaseDC(dibwindow, hdc);
    350 
    351 	if (vid.conheight > modelist[modenum].height)
    352 		vid.conheight = modelist[modenum].height;
    353 	if (vid.conwidth > modelist[modenum].width)
    354 		vid.conwidth = modelist[modenum].width;
    355 	vid.width = vid.conwidth;
    356 	vid.height = vid.conheight;
    357 
    358 	vid.numpages = 2;
    359 
    360 // needed because we're not getting WM_MOVE messages fullscreen on NT
    361 	window_x = 0;
    362 	window_y = 0;
    363 
    364 	mainwindow = dibwindow;
    365 
    366 	SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
    367 	SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
    368 
    369 	return true;
    370 }
    371 
    372 
    373 int VID_SetMode (int modenum, unsigned char *palette)
    374 {
    375 	int				original_mode, temp;
    376 	qboolean		stat;
    377     MSG				msg;
    378 	HDC				hdc;
    379 
    380 	if ((windowed && (modenum != 0)) ||
    381 		(!windowed && (modenum < 1)) ||
    382 		(!windowed && (modenum >= nummodes)))
    383 	{
    384 		Sys_Error ("Bad video mode\n");
    385 	}
    386 
    387 // so Con_Printfs don't mess us up by forcing vid and snd updates
    388 	temp = scr_disabled_for_loading;
    389 	scr_disabled_for_loading = true;
    390 
    391 	CDAudio_Pause ();
    392 
    393 	if (vid_modenum == NO_MODE)
    394 		original_mode = windowed_default;
    395 	else
    396 		original_mode = vid_modenum;
    397 
    398 	// Set either the fullscreen or windowed mode
    399 	if (modelist[modenum].type == MS_WINDOWED)
    400 	{
    401 		if (_windowed_mouse.value && key_dest == key_game)
    402 		{
    403 			stat = VID_SetWindowedMode(modenum);
    404 			IN_ActivateMouse ();
    405 			IN_HideMouse ();
    406 		}
    407 		else
    408 		{
    409 			IN_DeactivateMouse ();
    410 			IN_ShowMouse ();
    411 			stat = VID_SetWindowedMode(modenum);
    412 		}
    413 	}
    414 	else if (modelist[modenum].type == MS_FULLDIB)
    415 	{
    416 		stat = VID_SetFullDIBMode(modenum);
    417 		IN_ActivateMouse ();
    418 		IN_HideMouse ();
    419 	}
    420 	else
    421 	{
    422 		Sys_Error ("VID_SetMode: Bad mode type in modelist");
    423 	}
    424 
    425 	window_width = DIBWidth;
    426 	window_height = DIBHeight;
    427 	VID_UpdateWindowStatus ();
    428 
    429 	CDAudio_Resume ();
    430 	scr_disabled_for_loading = temp;
    431 
    432 	if (!stat)
    433 	{
    434 		Sys_Error ("Couldn't set video mode");
    435 	}
    436 
    437 // now we try to make sure we get the focus on the mode switch, because
    438 // sometimes in some systems we don't.  We grab the foreground, then
    439 // finish setting up, pump all our messages, and sleep for a little while
    440 // to let messages finish bouncing around the system, then we put
    441 // ourselves at the top of the z order, then grab the foreground again,
    442 // Who knows if it helps, but it probably doesn't hurt
    443 	SetForegroundWindow (mainwindow);
    444 	VID_SetPalette (palette);
    445 	vid_modenum = modenum;
    446 	Cvar_SetValue ("vid_mode", (float)vid_modenum);
    447 
    448 	while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
    449 	{
    450       	TranslateMessage (&msg);
    451       	DispatchMessage (&msg);
    452 	}
    453 
    454 	Sleep (100);
    455 
    456 	SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
    457 				  SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
    458 				  SWP_NOCOPYBITS);
    459 
    460 	SetForegroundWindow (mainwindow);
    461 
    462 // fix the leftover Alt from any Alt-Tab or the like that switched us away
    463 	ClearAllStates ();
    464 
    465 	if (!msg_suppress_1)
    466 		Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum));
    467 
    468 	VID_SetPalette (palette);
    469 
    470 	vid.recalc_refdef = 1;
    471 
    472 	return true;
    473 }
    474 
    475 
    476 /*
    477 ================
    478 VID_UpdateWindowStatus
    479 ================
    480 */
    481 void VID_UpdateWindowStatus (void)
    482 {
    483 
    484 	window_rect.left = window_x;
    485 	window_rect.top = window_y;
    486 	window_rect.right = window_x + window_width;
    487 	window_rect.bottom = window_y + window_height;
    488 	window_center_x = (window_rect.left + window_rect.right) / 2;
    489 	window_center_y = (window_rect.top + window_rect.bottom) / 2;
    490 
    491 	IN_UpdateClipCursor ();
    492 }
    493 
    494 
    495 //====================================
    496 
    497 BINDTEXFUNCPTR bindTexFunc;
    498 
    499 #define TEXTURE_EXT_STRING "GL_EXT_texture_object"
    500 
    501 
    502 void CheckTextureExtensions (void)
    503 {
    504 	char		*tmp;
    505 	qboolean	texture_ext;
    506 	HINSTANCE	hInstGL;
    507 
    508 	texture_ext = FALSE;
    509 	/* check for texture extension */
    510 	tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
    511 	while (*tmp)
    512 	{
    513 		if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0)
    514 			texture_ext = TRUE;
    515 		tmp++;
    516 	}
    517 
    518 	if (!texture_ext || COM_CheckParm ("-gl11") )
    519 	{
    520 		hInstGL = LoadLibrary("opengl32.dll");
    521 
    522 		if (hInstGL == NULL)
    523 			Sys_Error ("Couldn't load opengl32.dll\n");
    524 
    525 		bindTexFunc = (void *)GetProcAddress(hInstGL,"glBindTexture");
    526 
    527 		if (!bindTexFunc)
    528 			Sys_Error ("No texture objects!");
    529 		return;
    530 	}
    531 
    532 /* load library and get procedure adresses for texture extension API */
    533 	if ((bindTexFunc = (BINDTEXFUNCPTR)
    534 		wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL)
    535 	{
    536 		Sys_Error ("GetProcAddress for BindTextureEXT failed");
    537 		return;
    538 	}
    539 }
    540 
    541 void CheckArrayExtensions (void)
    542 {
    543 	char		*tmp;
    544 
    545 	/* check for texture extension */
    546 	tmp = (unsigned char *)glGetString(GL_EXTENSIONS);
    547 	while (*tmp)
    548 	{
    549 		if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0)
    550 		{
    551 			if (
    552 ((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) ||
    553 ((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) ||
    554 ((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) ||
    555 ((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) )
    556 			{
    557 				Sys_Error ("GetProcAddress for vertex extension failed");
    558 				return;
    559 			}
    560 			return;
    561 		}
    562 		tmp++;
    563 	}
    564 
    565 	Sys_Error ("Vertex array extension not present");
    566 }
    567 
    568 //int		texture_mode = GL_NEAREST;
    569 //int		texture_mode = GL_NEAREST_MIPMAP_NEAREST;
    570 //int		texture_mode = GL_NEAREST_MIPMAP_LINEAR;
    571 int		texture_mode = GL_LINEAR;
    572 //int		texture_mode = GL_LINEAR_MIPMAP_NEAREST;
    573 //int		texture_mode = GL_LINEAR_MIPMAP_LINEAR;
    574 
    575 int		texture_extension_number = 1;
    576 
    577 #ifdef _WIN32
    578 void CheckMultiTextureExtensions(void)
    579 {
    580 	if (strstr(gl_extensions, "GL_SGIS_multitexture ") && !COM_CheckParm("-nomtex")) {
    581 		Con_Printf("Multitexture extensions found.\n");
    582 		qglMTexCoord2fSGIS = (void *) wglGetProcAddress("glMTexCoord2fSGIS");
    583 		qglSelectTextureSGIS = (void *) wglGetProcAddress("glSelectTextureSGIS");
    584 		gl_mtexable = true;
    585 	}
    586 }
    587 #else
    588 void CheckMultiTextureExtensions(void)
    589 {
    590 		gl_mtexable = true;
    591 }
    592 #endif
    593 
    594 /*
    595 ===============
    596 GL_Init
    597 ===============
    598 */
    599 void GL_Init (void)
    600 {
    601 	gl_vendor = glGetString (GL_VENDOR);
    602 	Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
    603 	gl_renderer = glGetString (GL_RENDERER);
    604 	Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
    605 
    606 	gl_version = glGetString (GL_VERSION);
    607 	Con_Printf ("GL_VERSION: %s\n", gl_version);
    608 	gl_extensions = glGetString (GL_EXTENSIONS);
    609 	Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
    610 
    611 //	Con_Printf ("%s %s\n", gl_renderer, gl_version);
    612 
    613     if (strnicmp(gl_renderer,"PowerVR",7)==0)
    614          fullsbardraw = true;
    615 
    616     if (strnicmp(gl_renderer,"Permedia",8)==0)
    617          isPermedia = true;
    618 
    619 	CheckTextureExtensions ();
    620 	CheckMultiTextureExtensions ();
    621 
    622 	glClearColor (1,0,0,0);
    623 	glCullFace(GL_FRONT);
    624 	glEnable(GL_TEXTURE_2D);
    625 
    626 	glEnable(GL_ALPHA_TEST);
    627 	glAlphaFunc(GL_GREATER, 0.666);
    628 
    629 	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
    630 	glShadeModel (GL_FLAT);
    631 
    632 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    633 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    634 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    635 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    636 
    637 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    638 
    639 //	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    640 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    641 
    642 #if 0
    643 	CheckArrayExtensions ();
    644 
    645 	glEnable (GL_VERTEX_ARRAY_EXT);
    646 	glEnable (GL_TEXTURE_COORD_ARRAY_EXT);
    647 	glVertexPointerEXT (3, GL_FLOAT, 0, 0, &glv.x);
    648 	glTexCoordPointerEXT (2, GL_FLOAT, 0, 0, &glv.s);
    649 	glColorPointerEXT (3, GL_FLOAT, 0, 0, &glv.r);
    650 #endif
    651 }
    652 
    653 /*
    654 =================
    655 GL_BeginRendering
    656 
    657 =================
    658 */
    659 void GL_BeginRendering (int *x, int *y, int *width, int *height)
    660 {
    661 	extern cvar_t gl_clear;
    662 
    663 	*x = *y = 0;
    664 	*width = WindowRect.right - WindowRect.left;
    665 	*height = WindowRect.bottom - WindowRect.top;
    666 
    667 //    if (!wglMakeCurrent( maindc, baseRC ))
    668 //		Sys_Error ("wglMakeCurrent failed");
    669 
    670 //	glViewport (*x, *y, *width, *height);
    671 }
    672 
    673 
    674 void GL_EndRendering (void)
    675 {
    676 	if (!scr_skipupdate || block_drawing)
    677 		SwapBuffers(maindc);
    678 
    679 // handle the mouse state when windowed if that's changed
    680 	if (modestate == MS_WINDOWED)
    681 	{
    682 		if (!_windowed_mouse.value) {
    683 			if (windowed_mouse)	{
    684 				IN_DeactivateMouse ();
    685 				IN_ShowMouse ();
    686 				windowed_mouse = false;
    687 			}
    688 		} else {
    689 			windowed_mouse = true;
    690 			if (key_dest == key_game && !mouseactive && ActiveApp) {
    691 				IN_ActivateMouse ();
    692 				IN_HideMouse ();
    693 			} else if (mouseactive && key_dest != key_game) {
    694 				IN_DeactivateMouse ();
    695 				IN_ShowMouse ();
    696 			}
    697 		}
    698 	}
    699 	if (fullsbardraw)
    700 		Sbar_Changed();
    701 }
    702 
    703 void	VID_SetPalette (unsigned char *palette)
    704 {
    705 	byte	*pal;
    706 	unsigned r,g,b;
    707 	unsigned v;
    708 	int     r1,g1,b1;
    709 	int		j,k,l,m;
    710 	unsigned short i;
    711 	unsigned	*table;
    712 	FILE *f;
    713 	char s[255];
    714 	HWND hDlg, hProgress;
    715 	float gamma;
    716 
    717 //
    718 // 8 8 8 encoding
    719 //
    720 	pal = palette;
    721 	table = d_8to24table;
    722 	for (i=0 ; i<256 ; i++)
    723 	{
    724 		r = pal[0];
    725 		g = pal[1];
    726 		b = pal[2];
    727 		pal += 3;
    728 
    729 //		v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
    730 //		v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
    731 		v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
    732 		*table++ = v;
    733 	}
    734 	d_8to24table[255] &= 0xffffff;	// 255 is transparent
    735 
    736 	// JACK: 3D distance calcs - k is last closest, l is the distance.
    737 	// FIXME: Precalculate this and cache to disk.
    738 	for (i=0; i < (1<<15); i++) {
    739 		/* Maps
    740 			000000000000000
    741 			000000000011111 = Red  = 0x1F
    742 			000001111100000 = Blue = 0x03E0
    743 			111110000000000 = Grn  = 0x7C00
    744 		*/
    745 		r = ((i & 0x1F) << 3)+4;
    746 		g = ((i & 0x03E0) >> 2)+4;
    747 		b = ((i & 0x7C00) >> 7)+4;
    748 		pal = (unsigned char *)d_8to24table;
    749 		for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4) {
    750 			r1 = r-pal[0];
    751 			g1 = g-pal[1];
    752 			b1 = b-pal[2];
    753 			j = (r1*r1)+(g1*g1)+(b1*b1);
    754 			if (j<l) {
    755 				k=v;
    756 				l=j;
    757 			}
    758 		}
    759 		d_15to8table[i]=k;
    760 	}
    761 }
    762 
    763 BOOL	gammaworks;
    764 
    765 void	VID_ShiftPalette (unsigned char *palette)
    766 {
    767 	extern	byte ramps[3][256];
    768 
    769 //	VID_SetPalette (palette);
    770 
    771 //	gammaworks = SetDeviceGammaRamp (maindc, ramps);
    772 }
    773 
    774 
    775 void VID_SetDefaultMode (void)
    776 {
    777 	IN_DeactivateMouse ();
    778 }
    779 
    780 
    781 void	VID_Shutdown (void)
    782 {
    783    	HGLRC hRC;
    784    	HDC	  hDC;
    785 
    786 	if (vid_initialized)
    787 	{
    788 		vid_canalttab = false;
    789 		hRC = wglGetCurrentContext();
    790     	hDC = wglGetCurrentDC();
    791 
    792     	wglMakeCurrent(NULL, NULL);
    793 
    794     	if (hRC)
    795     	    wglDeleteContext(hRC);
    796 
    797 		if (hDC && dibwindow)
    798 			ReleaseDC(dibwindow, hDC);
    799 
    800 		if (modestate == MS_FULLDIB)
    801 			ChangeDisplaySettings (NULL, 0);
    802 
    803 		if (maindc && dibwindow)
    804 			ReleaseDC (dibwindow, maindc);
    805 
    806 		AppActivate(false, false);
    807 	}
    808 }
    809 
    810 
    811 //==========================================================================
    812 
    813 
    814 BOOL bSetupPixelFormat(HDC hDC)
    815 {
    816     static PIXELFORMATDESCRIPTOR pfd = {
    817 	sizeof(PIXELFORMATDESCRIPTOR),	// size of this pfd
    818 	1,				// version number
    819 	PFD_DRAW_TO_WINDOW 		// support window
    820 	|  PFD_SUPPORT_OPENGL 	// support OpenGL
    821 	|  PFD_DOUBLEBUFFER ,	// double buffered
    822 	PFD_TYPE_RGBA,			// RGBA type
    823 	24,				// 24-bit color depth
    824 	0, 0, 0, 0, 0, 0,		// color bits ignored
    825 	0,				// no alpha buffer
    826 	0,				// shift bit ignored
    827 	0,				// no accumulation buffer
    828 	0, 0, 0, 0, 			// accum bits ignored
    829 	32,				// 32-bit z-buffer
    830 	0,				// no stencil buffer
    831 	0,				// no auxiliary buffer
    832 	PFD_MAIN_PLANE,			// main layer
    833 	0,				// reserved
    834 	0, 0, 0				// layer masks ignored
    835     };
    836     int pixelformat;
    837 
    838     if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
    839     {
    840         MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
    841         return FALSE;
    842     }
    843 
    844     if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE)
    845     {
    846         MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
    847         return FALSE;
    848     }
    849 
    850     return TRUE;
    851 }
    852 
    853 
    854 
    855 byte        scantokey[128] =
    856 					{
    857 //  0           1       2       3       4       5       6       7
    858 //  8           9       A       B       C       D       E       F
    859 	0  ,    27,     '1',    '2',    '3',    '4',    '5',    '6',
    860 	'7',    '8',    '9',    '0',    '-',    '=',    K_BACKSPACE, 9, // 0
    861 	'q',    'w',    'e',    'r',    't',    'y',    'u',    'i',
    862 	'o',    'p',    '[',    ']',    13 ,    K_CTRL,'a',  's',      // 1
    863 	'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';',
    864 	'\'' ,    '`',    K_SHIFT,'\\',  'z',    'x',    'c',    'v',      // 2
    865 	'b',    'n',    'm',    ',',    '.',    '/',    K_SHIFT,'*',
    866 	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3
    867 	K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE  ,    0  , K_HOME,
    868 	K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4
    869 	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11,
    870 	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
    871 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,
    872 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6
    873 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,
    874 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7
    875 					};
    876 
    877 byte        shiftscantokey[128] =
    878 					{
    879 //  0           1       2       3       4       5       6       7
    880 //  8           9       A       B       C       D       E       F
    881 	0  ,    27,     '!',    '@',    '#',    '$',    '%',    '^',
    882 	'&',    '*',    '(',    ')',    '_',    '+',    K_BACKSPACE, 9, // 0
    883 	'Q',    'W',    'E',    'R',    'T',    'Y',    'U',    'I',
    884 	'O',    'P',    '{',    '}',    13 ,    K_CTRL,'A',  'S',      // 1
    885 	'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':',
    886 	'"' ,    '~',    K_SHIFT,'|',  'Z',    'X',    'C',    'V',      // 2
    887 	'B',    'N',    'M',    '<',    '>',    '?',    K_SHIFT,'*',
    888 	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3
    889 	K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE  ,    0  , K_HOME,
    890 	K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4
    891 	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11,
    892 	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
    893 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,
    894 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6
    895 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,
    896 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7
    897 					};
    898 
    899 
    900 /*
    901 =======
    902 MapKey
    903 
    904 Map from windows to quake keynums
    905 =======
    906 */
    907 int MapKey (int key)
    908 {
    909 	key = (key>>16)&255;
    910 	if (key > 127)
    911 		return 0;
    912 	if (scantokey[key] == 0)
    913 		Con_DPrintf("key 0x%02x has no translation\n", key);
    914 	return scantokey[key];
    915 }
    916 
    917 /*
    918 ===================================================================
    919 
    920 MAIN WINDOW
    921 
    922 ===================================================================
    923 */
    924 
    925 /*
    926 ================
    927 ClearAllStates
    928 ================
    929 */
    930 void ClearAllStates (void)
    931 {
    932 	int		i;
    933 
    934 // send an up event for each key, to make sure the server clears them all
    935 	for (i=0 ; i<256 ; i++)
    936 	{
    937 		Key_Event (i, false);
    938 	}
    939 
    940 	Key_ClearStates ();
    941 	IN_ClearStates ();
    942 }
    943 
    944 void AppActivate(BOOL fActive, BOOL minimize)
    945 /****************************************************************************
    946 *
    947 * Function:     AppActivate
    948 * Parameters:   fActive - True if app is activating
    949 *
    950 * Description:  If the application is activating, then swap the system
    951 *               into SYSPAL_NOSTATIC mode so that our palettes will display
    952 *               correctly.
    953 *
    954 ****************************************************************************/
    955 {
    956 	MSG msg;
    957     HDC			hdc;
    958     int			i, t;
    959 	static BOOL	sound_active;
    960 
    961 	ActiveApp = fActive;
    962 	Minimized = minimize;
    963 
    964 // enable/disable sound on focus gain/loss
    965 	if (!ActiveApp && sound_active)
    966 	{
    967 		S_BlockSound ();
    968 		sound_active = false;
    969 	}
    970 	else if (ActiveApp && !sound_active)
    971 	{
    972 		S_UnblockSound ();
    973 		sound_active = true;
    974 	}
    975 
    976 	if (fActive)
    977 	{
    978 		if (modestate == MS_FULLDIB)
    979 		{
    980 			IN_ActivateMouse ();
    981 			IN_HideMouse ();
    982 			if (vid_canalttab && vid_wassuspended) {
    983 				vid_wassuspended = false;
    984 				ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
    985 				ShowWindow(mainwindow, SW_SHOWNORMAL);
    986 			}
    987 		}
    988 		else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game)
    989 		{
    990 			IN_ActivateMouse ();
    991 			IN_HideMouse ();
    992 		}
    993 	}
    994 
    995 	if (!fActive)
    996 	{
    997 		if (modestate == MS_FULLDIB)
    998 		{
    999 			IN_DeactivateMouse ();
   1000 			IN_ShowMouse ();
   1001 			if (vid_canalttab) {
   1002 				ChangeDisplaySettings (NULL, 0);
   1003 				vid_wassuspended = true;
   1004 			}
   1005 		}
   1006 		else if ((modestate == MS_WINDOWED) && _windowed_mouse.value)
   1007 		{
   1008 			IN_DeactivateMouse ();
   1009 			IN_ShowMouse ();
   1010 		}
   1011 	}
   1012 }
   1013 
   1014 
   1015 /* main window procedure */
   1016 LONG WINAPI MainWndProc (
   1017     HWND    hWnd,
   1018     UINT    uMsg,
   1019     WPARAM  wParam,
   1020     LPARAM  lParam)
   1021 {
   1022     LONG    lRet = 1;
   1023 	int		fwKeys, xPos, yPos, fActive, fMinimized, temp;
   1024 	extern unsigned int uiWheelMessage;
   1025 
   1026 	if ( uMsg == uiWheelMessage )
   1027 		uMsg = WM_MOUSEWHEEL;
   1028 
   1029     switch (uMsg)
   1030     {
   1031 		case WM_KILLFOCUS:
   1032 			if (modestate == MS_FULLDIB)
   1033 				ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
   1034 			break;
   1035 
   1036 		case WM_CREATE:
   1037 			break;
   1038 
   1039 		case WM_MOVE:
   1040 			window_x = (int) LOWORD(lParam);
   1041 			window_y = (int) HIWORD(lParam);
   1042 			VID_UpdateWindowStatus ();
   1043 			break;
   1044 
   1045 		case WM_KEYDOWN:
   1046 		case WM_SYSKEYDOWN:
   1047 			Key_Event (MapKey(lParam), true);
   1048 			break;
   1049 
   1050 		case WM_KEYUP:
   1051 		case WM_SYSKEYUP:
   1052 			Key_Event (MapKey(lParam), false);
   1053 			break;
   1054 
   1055 		case WM_SYSCHAR:
   1056 		// keep Alt-Space from happening
   1057 			break;
   1058 
   1059 	// this is complicated because Win32 seems to pack multiple mouse events into
   1060 	// one update sometimes, so we always check all states and look for events
   1061 		case WM_LBUTTONDOWN:
   1062 		case WM_LBUTTONUP:
   1063 		case WM_RBUTTONDOWN:
   1064 		case WM_RBUTTONUP:
   1065 		case WM_MBUTTONDOWN:
   1066 		case WM_MBUTTONUP:
   1067 		case WM_MOUSEMOVE:
   1068 			temp = 0;
   1069 
   1070 			if (wParam & MK_LBUTTON)
   1071 				temp |= 1;
   1072 
   1073 			if (wParam & MK_RBUTTON)
   1074 				temp |= 2;
   1075 
   1076 			if (wParam & MK_MBUTTON)
   1077 				temp |= 4;
   1078 
   1079 			IN_MouseEvent (temp);
   1080 
   1081 			break;
   1082 
   1083 		// JACK: This is the mouse wheel with the Intellimouse
   1084 		// Its delta is either positive or neg, and we generate the proper
   1085 		// Event.
   1086 		case WM_MOUSEWHEEL:
   1087 			if ((short) HIWORD(wParam) > 0) {
   1088 				Key_Event(K_MWHEELUP, true);
   1089 				Key_Event(K_MWHEELUP, false);
   1090 			} else {
   1091 				Key_Event(K_MWHEELDOWN, true);
   1092 				Key_Event(K_MWHEELDOWN, false);
   1093 			}
   1094 			break;
   1095 
   1096     	case WM_SIZE:
   1097             break;
   1098 
   1099    	    case WM_CLOSE:
   1100 			if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
   1101 						MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
   1102 			{
   1103 				Sys_Quit ();
   1104 			}
   1105 
   1106 	        break;
   1107 
   1108 		case WM_ACTIVATE:
   1109 			fActive = LOWORD(wParam);
   1110 			fMinimized = (BOOL) HIWORD(wParam);
   1111 			AppActivate(!(fActive == WA_INACTIVE), fMinimized);
   1112 
   1113 		// fix the leftover Alt from any Alt-Tab or the like that switched us away
   1114 			ClearAllStates ();
   1115 
   1116 			break;
   1117 
   1118    	    case WM_DESTROY:
   1119         {
   1120 			if (dibwindow)
   1121 				DestroyWindow (dibwindow);
   1122 
   1123             PostQuitMessage (0);
   1124         }
   1125         break;
   1126 
   1127 		case MM_MCINOTIFY:
   1128             lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
   1129 			break;
   1130 
   1131     	default:
   1132             /* pass all unhandled messages to DefWindowProc */
   1133             lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
   1134         break;
   1135     }
   1136 
   1137     /* return 1 if handled message, 0 if not */
   1138     return lRet;
   1139 }
   1140 
   1141 
   1142 /*
   1143 =================
   1144 VID_NumModes
   1145 =================
   1146 */
   1147 int VID_NumModes (void)
   1148 {
   1149 	return nummodes;
   1150 }
   1151 
   1152 
   1153 /*
   1154 =================
   1155 VID_GetModePtr
   1156 =================
   1157 */
   1158 vmode_t *VID_GetModePtr (int modenum)
   1159 {
   1160 
   1161 	if ((modenum >= 0) && (modenum < nummodes))
   1162 		return &modelist[modenum];
   1163 	else
   1164 		return &badmode;
   1165 }
   1166 
   1167 
   1168 /*
   1169 =================
   1170 VID_GetModeDescription
   1171 =================
   1172 */
   1173 char *VID_GetModeDescription (int mode)
   1174 {
   1175 	char		*pinfo;
   1176 	vmode_t		*pv;
   1177 	static char	temp[100];
   1178 
   1179 	if ((mode < 0) || (mode >= nummodes))
   1180 		return NULL;
   1181 
   1182 	if (!leavecurrentmode)
   1183 	{
   1184 		pv = VID_GetModePtr (mode);
   1185 		pinfo = pv->modedesc;
   1186 	}
   1187 	else
   1188 	{
   1189 		sprintf (temp, "Desktop resolution (%dx%d)",
   1190 				 modelist[MODE_FULLSCREEN_DEFAULT].width,
   1191 				 modelist[MODE_FULLSCREEN_DEFAULT].height);
   1192 		pinfo = temp;
   1193 	}
   1194 
   1195 	return pinfo;
   1196 }
   1197 
   1198 
   1199 // KJB: Added this to return the mode driver name in description for console
   1200 
   1201 char *VID_GetExtModeDescription (int mode)
   1202 {
   1203 	static char	pinfo[40];
   1204 	vmode_t		*pv;
   1205 
   1206 	if ((mode < 0) || (mode >= nummodes))
   1207 		return NULL;
   1208 
   1209 	pv = VID_GetModePtr (mode);
   1210 	if (modelist[mode].type == MS_FULLDIB)
   1211 	{
   1212 		if (!leavecurrentmode)
   1213 		{
   1214 			sprintf(pinfo,"%s fullscreen", pv->modedesc);
   1215 		}
   1216 		else
   1217 		{
   1218 			sprintf (pinfo, "Desktop resolution (%dx%d)",
   1219 					 modelist[MODE_FULLSCREEN_DEFAULT].width,
   1220 					 modelist[MODE_FULLSCREEN_DEFAULT].height);
   1221 		}
   1222 	}
   1223 	else
   1224 	{
   1225 		if (modestate == MS_WINDOWED)
   1226 			sprintf(pinfo, "%s windowed", pv->modedesc);
   1227 		else
   1228 			sprintf(pinfo, "windowed");
   1229 	}
   1230 
   1231 	return pinfo;
   1232 }
   1233 
   1234 
   1235 /*
   1236 =================
   1237 VID_DescribeCurrentMode_f
   1238 =================
   1239 */
   1240 void VID_DescribeCurrentMode_f (void)
   1241 {
   1242 	Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
   1243 }
   1244 
   1245 
   1246 /*
   1247 =================
   1248 VID_NumModes_f
   1249 =================
   1250 */
   1251 void VID_NumModes_f (void)
   1252 {
   1253 
   1254 	if (nummodes == 1)
   1255 		Con_Printf ("%d video mode is available\n", nummodes);
   1256 	else
   1257 		Con_Printf ("%d video modes are available\n", nummodes);
   1258 }
   1259 
   1260 
   1261 /*
   1262 =================
   1263 VID_DescribeMode_f
   1264 =================
   1265 */
   1266 void VID_DescribeMode_f (void)
   1267 {
   1268 	int		t, modenum;
   1269 
   1270 	modenum = Q_atoi (Cmd_Argv(1));
   1271 
   1272 	t = leavecurrentmode;
   1273 	leavecurrentmode = 0;
   1274 
   1275 	Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
   1276 
   1277 	leavecurrentmode = t;
   1278 }
   1279 
   1280 
   1281 /*
   1282 =================
   1283 VID_DescribeModes_f
   1284 =================
   1285 */
   1286 void VID_DescribeModes_f (void)
   1287 {
   1288 	int			i, lnummodes, t;
   1289 	char		*pinfo;
   1290 	vmode_t		*pv;
   1291 
   1292 	lnummodes = VID_NumModes ();
   1293 
   1294 	t = leavecurrentmode;
   1295 	leavecurrentmode = 0;
   1296 
   1297 	for (i=1 ; i<lnummodes ; i++)
   1298 	{
   1299 		pv = VID_GetModePtr (i);
   1300 		pinfo = VID_GetExtModeDescription (i);
   1301 		Con_Printf ("%2d: %s\n", i, pinfo);
   1302 	}
   1303 
   1304 	leavecurrentmode = t;
   1305 }
   1306 
   1307 
   1308 void VID_InitDIB (HINSTANCE hInstance)
   1309 {
   1310 	WNDCLASS		wc;
   1311 	HDC				hdc;
   1312 	int				i;
   1313 
   1314 	/* Register the frame class */
   1315     wc.style         = 0;
   1316     wc.lpfnWndProc   = (WNDPROC)MainWndProc;
   1317     wc.cbClsExtra    = 0;
   1318     wc.cbWndExtra    = 0;
   1319     wc.hInstance     = hInstance;
   1320     wc.hIcon         = 0;
   1321     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
   1322 	wc.hbrBackground = NULL;
   1323     wc.lpszMenuName  = 0;
   1324     wc.lpszClassName = "WinQuake";
   1325 
   1326     if (!RegisterClass (&wc) )
   1327 		Sys_Error ("Couldn't register window class");
   1328 
   1329 	modelist[0].type = MS_WINDOWED;
   1330 
   1331 	if (COM_CheckParm("-width"))
   1332 		modelist[0].width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
   1333 	else
   1334 		modelist[0].width = 640;
   1335 
   1336 	if (modelist[0].width < 320)
   1337 		modelist[0].width = 320;
   1338 
   1339 	if (COM_CheckParm("-height"))
   1340 		modelist[0].height= Q_atoi(com_argv[COM_CheckParm("-height")+1]);
   1341 	else
   1342 		modelist[0].height = modelist[0].width * 240/320;
   1343 
   1344 	if (modelist[0].height < 240)
   1345 		modelist[0].height = 240;
   1346 
   1347 	sprintf (modelist[0].modedesc, "%dx%d",
   1348 			 modelist[0].width, modelist[0].height);
   1349 
   1350 	modelist[0].modenum = MODE_WINDOWED;
   1351 	modelist[0].dib = 1;
   1352 	modelist[0].fullscreen = 0;
   1353 	modelist[0].halfscreen = 0;
   1354 	modelist[0].bpp = 0;
   1355 
   1356 	nummodes = 1;
   1357 }
   1358 
   1359 
   1360 /*
   1361 =================
   1362 VID_InitFullDIB
   1363 =================
   1364 */
   1365 void VID_InitFullDIB (HINSTANCE hInstance)
   1366 {
   1367 	DEVMODE	devmode;
   1368 	int		i, modenum, cmodes, originalnummodes, existingmode, numlowresmodes;
   1369 	int		j, bpp, done;
   1370 	BOOL	stat;
   1371 
   1372 // enumerate >8 bpp modes
   1373 	originalnummodes = nummodes;
   1374 	modenum = 0;
   1375 
   1376 	do
   1377 	{
   1378 		stat = EnumDisplaySettings (NULL, modenum, &devmode);
   1379 
   1380 		if ((devmode.dmBitsPerPel >= 15) &&
   1381 			(devmode.dmPelsWidth <= MAXWIDTH) &&
   1382 			(devmode.dmPelsHeight <= MAXHEIGHT) &&
   1383 			(nummodes < MAX_MODE_LIST))
   1384 		{
   1385 			devmode.dmFields = DM_BITSPERPEL |
   1386 							   DM_PELSWIDTH |
   1387 							   DM_PELSHEIGHT;
   1388 
   1389 			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
   1390 					DISP_CHANGE_SUCCESSFUL)
   1391 			{
   1392 				modelist[nummodes].type = MS_FULLDIB;
   1393 				modelist[nummodes].width = devmode.dmPelsWidth;
   1394 				modelist[nummodes].height = devmode.dmPelsHeight;
   1395 				modelist[nummodes].modenum = 0;
   1396 				modelist[nummodes].halfscreen = 0;
   1397 				modelist[nummodes].dib = 1;
   1398 				modelist[nummodes].fullscreen = 1;
   1399 				modelist[nummodes].bpp = devmode.dmBitsPerPel;
   1400 				sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
   1401 						 devmode.dmPelsWidth, devmode.dmPelsHeight,
   1402 						 devmode.dmBitsPerPel);
   1403 
   1404 			// if the width is more than twice the height, reduce it by half because this
   1405 			// is probably a dual-screen monitor
   1406 				if (!COM_CheckParm("-noadjustaspect"))
   1407 				{
   1408 					if (modelist[nummodes].width > (modelist[nummodes].height << 1))
   1409 					{
   1410 						modelist[nummodes].width >>= 1;
   1411 						modelist[nummodes].halfscreen = 1;
   1412 						sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
   1413 								 modelist[nummodes].width,
   1414 								 modelist[nummodes].height,
   1415 								 modelist[nummodes].bpp);
   1416 					}
   1417 				}
   1418 
   1419 				for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
   1420 				{
   1421 					if ((modelist[nummodes].width == modelist[i].width)   &&
   1422 						(modelist[nummodes].height == modelist[i].height) &&
   1423 						(modelist[nummodes].bpp == modelist[i].bpp))
   1424 					{
   1425 						existingmode = 1;
   1426 						break;
   1427 					}
   1428 				}
   1429 
   1430 				if (!existingmode)
   1431 				{
   1432 					nummodes++;
   1433 				}
   1434 			}
   1435 		}
   1436 
   1437 		modenum++;
   1438 	} while (stat);
   1439 
   1440 // see if there are any low-res modes that aren't being reported
   1441 	numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]);
   1442 	bpp = 16;
   1443 	done = 0;
   1444 
   1445 	do
   1446 	{
   1447 		for (j=0 ; (j<numlowresmodes) && (nummodes < MAX_MODE_LIST) ; j++)
   1448 		{
   1449 			devmode.dmBitsPerPel = bpp;
   1450 			devmode.dmPelsWidth = lowresmodes[j].width;
   1451 			devmode.dmPelsHeight = lowresmodes[j].height;
   1452 			devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
   1453 
   1454 			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
   1455 					DISP_CHANGE_SUCCESSFUL)
   1456 			{
   1457 				modelist[nummodes].type = MS_FULLDIB;
   1458 				modelist[nummodes].width = devmode.dmPelsWidth;
   1459 				modelist[nummodes].height = devmode.dmPelsHeight;
   1460 				modelist[nummodes].modenum = 0;
   1461 				modelist[nummodes].halfscreen = 0;
   1462 				modelist[nummodes].dib = 1;
   1463 				modelist[nummodes].fullscreen = 1;
   1464 				modelist[nummodes].bpp = devmode.dmBitsPerPel;
   1465 				sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
   1466 						 devmode.dmPelsWidth, devmode.dmPelsHeight,
   1467 						 devmode.dmBitsPerPel);
   1468 
   1469 				for (i=originalnummodes, existingmode = 0 ; i<nummodes ; i++)
   1470 				{
   1471 					if ((modelist[nummodes].width == modelist[i].width)   &&
   1472 						(modelist[nummodes].height == modelist[i].height) &&
   1473 						(modelist[nummodes].bpp == modelist[i].bpp))
   1474 					{
   1475 						existingmode = 1;
   1476 						break;
   1477 					}
   1478 				}
   1479 
   1480 				if (!existingmode)
   1481 				{
   1482 					nummodes++;
   1483 				}
   1484 			}
   1485 		}
   1486 		switch (bpp)
   1487 		{
   1488 			case 16:
   1489 				bpp = 32;
   1490 				break;
   1491 
   1492 			case 32:
   1493 				bpp = 24;
   1494 				break;
   1495 
   1496 			case 24:
   1497 				done = 1;
   1498 				break;
   1499 		}
   1500 	} while (!done);
   1501 
   1502 	if (nummodes == originalnummodes)
   1503 		Con_SafePrintf ("No fullscreen DIB modes found\n");
   1504 }
   1505 
   1506 qboolean VID_Is8bit() {
   1507 	return is8bit;
   1508 }
   1509 
   1510 #define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
   1511 
   1512 void VID_Init8bitPalette()
   1513 {
   1514 	// Check for 8bit Extensions and initialize them.
   1515 	int i;
   1516 	char thePalette[256*3];
   1517 	char *oldPalette, *newPalette;
   1518 
   1519 	glColorTableEXT = (void *)wglGetProcAddress("glColorTableEXT");
   1520     if (!glColorTableEXT || strstr(gl_extensions, "GL_EXT_shared_texture_palette") ||
   1521 		COM_CheckParm("-no8bit"))
   1522 		return;
   1523 
   1524 	Con_SafePrintf("8-bit GL extensions enabled.\n");
   1525     glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
   1526 	oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
   1527 	newPalette = thePalette;
   1528 	for (i=0;i<256;i++) {
   1529 		*newPalette++ = *oldPalette++;
   1530 		*newPalette++ = *oldPalette++;
   1531 		*newPalette++ = *oldPalette++;
   1532 		oldPalette++;
   1533 	}
   1534 	glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE,
   1535 		(void *) thePalette);
   1536 	is8bit = TRUE;
   1537 }
   1538 
   1539 static void Check_Gamma (unsigned char *pal)
   1540 {
   1541 	float	f, inf;
   1542 	unsigned char	palette[768];
   1543 	int		i;
   1544 
   1545 	if ((i = COM_CheckParm("-gamma")) == 0) {
   1546 		if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
   1547 			(gl_vendor && strstr(gl_vendor, "3Dfx")))
   1548 			vid_gamma = 1;
   1549 		else
   1550 			vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
   1551 	} else
   1552 		vid_gamma = Q_atof(com_argv[i+1]);
   1553 
   1554 	for (i=0 ; i<768 ; i++)
   1555 	{
   1556 		f = pow ( (pal[i]+1)/256.0 , vid_gamma );
   1557 		inf = f*255 + 0.5;
   1558 		if (inf < 0)
   1559 			inf = 0;
   1560 		if (inf > 255)
   1561 			inf = 255;
   1562 		palette[i] = inf;
   1563 	}
   1564 
   1565 	memcpy (pal, palette, sizeof(palette));
   1566 }
   1567 
   1568 /*
   1569 ===================
   1570 VID_Init
   1571 ===================
   1572 */
   1573 void	VID_Init (unsigned char *palette)
   1574 {
   1575 	int		i, existingmode;
   1576 	int		basenummodes, width, height, bpp, findbpp, done;
   1577 	byte	*ptmp;
   1578 	char	gldir[MAX_OSPATH];
   1579 	HDC		hdc;
   1580 	DEVMODE	devmode;
   1581 
   1582 	memset(&devmode, 0, sizeof(devmode));
   1583 
   1584 	Cvar_RegisterVariable (&vid_mode);
   1585 	Cvar_RegisterVariable (&vid_wait);
   1586 	Cvar_RegisterVariable (&vid_nopageflip);
   1587 	Cvar_RegisterVariable (&_vid_wait_override);
   1588 	Cvar_RegisterVariable (&_vid_default_mode);
   1589 	Cvar_RegisterVariable (&_vid_default_mode_win);
   1590 	Cvar_RegisterVariable (&vid_config_x);
   1591 	Cvar_RegisterVariable (&vid_config_y);
   1592 	Cvar_RegisterVariable (&vid_stretch_by_2);
   1593 	Cvar_RegisterVariable (&_windowed_mouse);
   1594 	Cvar_RegisterVariable (&gl_ztrick);
   1595 
   1596 	Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
   1597 	Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
   1598 	Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
   1599 	Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
   1600 
   1601 	hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));
   1602 
   1603 	InitCommonControls();
   1604 
   1605 	VID_InitDIB (global_hInstance);
   1606 	basenummodes = nummodes = 1;
   1607 
   1608 	VID_InitFullDIB (global_hInstance);
   1609 
   1610 	if (COM_CheckParm("-window"))
   1611 	{
   1612 		hdc = GetDC (NULL);
   1613 
   1614 		if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
   1615 		{
   1616 			Sys_Error ("Can't run in non-RGB mode");
   1617 		}
   1618 
   1619 		ReleaseDC (NULL, hdc);
   1620 
   1621 		windowed = true;
   1622 
   1623 		vid_default = MODE_WINDOWED;
   1624 	}
   1625 	else
   1626 	{
   1627 		if (nummodes == 1)
   1628 			Sys_Error ("No RGB fullscreen modes available");
   1629 
   1630 		windowed = false;
   1631 
   1632 		if (COM_CheckParm("-mode"))
   1633 		{
   1634 			vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]);
   1635 		}
   1636 		else
   1637 		{
   1638 			if (COM_CheckParm("-current"))
   1639 			{
   1640 				modelist[MODE_FULLSCREEN_DEFAULT].width =
   1641 						GetSystemMetrics (SM_CXSCREEN);
   1642 				modelist[MODE_FULLSCREEN_DEFAULT].height =
   1643 						GetSystemMetrics (SM_CYSCREEN);
   1644 				vid_default = MODE_FULLSCREEN_DEFAULT;
   1645 				leavecurrentmode = 1;
   1646 			}
   1647 			else
   1648 			{
   1649 				if (COM_CheckParm("-width"))
   1650 				{
   1651 					width = Q_atoi(com_argv[COM_CheckParm("-width")+1]);
   1652 				}
   1653 				else
   1654 				{
   1655 					width = 640;
   1656 				}
   1657 
   1658 				if (COM_CheckParm("-bpp"))
   1659 				{
   1660 					bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]);
   1661 					findbpp = 0;
   1662 				}
   1663 				else
   1664 				{
   1665 					bpp = 15;
   1666 					findbpp = 1;
   1667 				}
   1668 
   1669 				if (COM_CheckParm("-height"))
   1670 					height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);
   1671 
   1672 			// if they want to force it, add the specified mode to the list
   1673 				if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST))
   1674 				{
   1675 					modelist[nummodes].type = MS_FULLDIB;
   1676 					modelist[nummodes].width = width;
   1677 					modelist[nummodes].height = height;
   1678 					modelist[nummodes].modenum = 0;
   1679 					modelist[nummodes].halfscreen = 0;
   1680 					modelist[nummodes].dib = 1;
   1681 					modelist[nummodes].fullscreen = 1;
   1682 					modelist[nummodes].bpp = bpp;
   1683 					sprintf (modelist[nummodes].modedesc, "%dx%dx%d",
   1684 							 devmode.dmPelsWidth, devmode.dmPelsHeight,
   1685 							 devmode.dmBitsPerPel);
   1686 
   1687 					for (i=nummodes, existingmode = 0 ; i<nummodes ; i++)
   1688 					{
   1689 						if ((modelist[nummodes].width == modelist[i].width)   &&
   1690 							(modelist[nummodes].height == modelist[i].height) &&
   1691 							(modelist[nummodes].bpp == modelist[i].bpp))
   1692 						{
   1693 							existingmode = 1;
   1694 							break;
   1695 						}
   1696 					}
   1697 
   1698 					if (!existingmode)
   1699 					{
   1700 						nummodes++;
   1701 					}
   1702 				}
   1703 
   1704 				done = 0;
   1705 
   1706 				do
   1707 				{
   1708 					if (COM_CheckParm("-height"))
   1709 					{
   1710 						height = Q_atoi(com_argv[COM_CheckParm("-height")+1]);
   1711 
   1712 						for (i=1, vid_default=0 ; i<nummodes ; i++)
   1713 						{
   1714 							if ((modelist[i].width == width) &&
   1715 								(modelist[i].height == height) &&
   1716 								(modelist[i].bpp == bpp))
   1717 							{
   1718 								vid_default = i;
   1719 								done = 1;
   1720 								break;
   1721 							}
   1722 						}
   1723 					}
   1724 					else
   1725 					{
   1726 						for (i=1, vid_default=0 ; i<nummodes ; i++)
   1727 						{
   1728 							if ((modelist[i].width == width) && (modelist[i].bpp == bpp))
   1729 							{
   1730 								vid_default = i;
   1731 								done = 1;
   1732 								break;
   1733 							}
   1734 						}
   1735 					}
   1736 
   1737 					if (!done)
   1738 					{
   1739 						if (findbpp)
   1740 						{
   1741 							switch (bpp)
   1742 							{
   1743 							case 15:
   1744 								bpp = 16;
   1745 								break;
   1746 							case 16:
   1747 								bpp = 32;
   1748 								break;
   1749 							case 32:
   1750 								bpp = 24;
   1751 								break;
   1752 							case 24:
   1753 								done = 1;
   1754 								break;
   1755 							}
   1756 						}
   1757 						else
   1758 						{
   1759 							done = 1;
   1760 						}
   1761 					}
   1762 				} while (!done);
   1763 
   1764 				if (!vid_default)
   1765 				{
   1766 					Sys_Error ("Specified video mode not available");
   1767 				}
   1768 			}
   1769 		}
   1770 	}
   1771 
   1772 	vid_initialized = true;
   1773 
   1774 	if ((i = COM_CheckParm("-conwidth")) != 0)
   1775 		vid.conwidth = Q_atoi(com_argv[i+1]);
   1776 	else
   1777 		vid.conwidth = 640;
   1778 
   1779 	vid.conwidth &= 0xfff8; // make it a multiple of eight
   1780 
   1781 	if (vid.conwidth < 320)
   1782 		vid.conwidth = 320;
   1783 
   1784 	// pick a conheight that matches with correct aspect
   1785 	vid.conheight = vid.conwidth*3 / 4;
   1786 
   1787 	if ((i = COM_CheckParm("-conheight")) != 0)
   1788 		vid.conheight = Q_atoi(com_argv[i+1]);
   1789 	if (vid.conheight < 200)
   1790 		vid.conheight = 200;
   1791 
   1792 	vid.maxwarpwidth = WARP_WIDTH;
   1793 	vid.maxwarpheight = WARP_HEIGHT;
   1794 	vid.colormap = host_colormap;
   1795 	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
   1796 
   1797 	DestroyWindow (hwnd_dialog);
   1798 
   1799 	Check_Gamma(palette);
   1800 	VID_SetPalette (palette);
   1801 
   1802 	VID_SetMode (vid_default, palette);
   1803 
   1804     maindc = GetDC(mainwindow);
   1805 	bSetupPixelFormat(maindc);
   1806 
   1807     baseRC = wglCreateContext( maindc );
   1808 	if (!baseRC)
   1809 		Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
   1810     if (!wglMakeCurrent( maindc, baseRC ))
   1811 		Sys_Error ("wglMakeCurrent failed");
   1812 
   1813 	GL_Init ();
   1814 
   1815 	sprintf (gldir, "%s/glquake", com_gamedir);
   1816 	Sys_mkdir (gldir);
   1817 
   1818 	vid_realmode = vid_modenum;
   1819 
   1820 	// Check for 3DFX Extensions and initialize them.
   1821 	VID_Init8bitPalette();
   1822 
   1823 	vid_menudrawfn = VID_MenuDraw;
   1824 	vid_menukeyfn = VID_MenuKey;
   1825 
   1826 	strcpy (badmode.modedesc, "Bad mode");
   1827 	vid_canalttab = true;
   1828 
   1829 	if (COM_CheckParm("-fullsbar"))
   1830 		fullsbardraw = true;
   1831 }
   1832 
   1833 
   1834 //========================================================
   1835 // Video menu stuff
   1836 //========================================================
   1837 
   1838 extern void M_Menu_Options_f (void);
   1839 extern void M_Print (int cx, int cy, char *str);
   1840 extern void M_PrintWhite (int cx, int cy, char *str);
   1841 extern void M_DrawCharacter (int cx, int line, int num);
   1842 extern void M_DrawTransPic (int x, int y, qpic_t *pic);
   1843 extern void M_DrawPic (int x, int y, qpic_t *pic);
   1844 
   1845 static int	vid_line, vid_wmodes;
   1846 
   1847 typedef struct
   1848 {
   1849 	int		modenum;
   1850 	char	*desc;
   1851 	int		iscur;
   1852 } modedesc_t;
   1853 
   1854 #define MAX_COLUMN_SIZE		9
   1855 #define MODE_AREA_HEIGHT	(MAX_COLUMN_SIZE + 2)
   1856 #define MAX_MODEDESCS		(MAX_COLUMN_SIZE*3)
   1857 
   1858 static modedesc_t	modedescs[MAX_MODEDESCS];
   1859 
   1860 /*
   1861 ================
   1862 VID_MenuDraw
   1863 ================
   1864 */
   1865 void VID_MenuDraw (void)
   1866 {
   1867 	qpic_t		*p;
   1868 	char		*ptr;
   1869 	int			lnummodes, i, j, k, column, row, dup, dupmode;
   1870 	char		temp[100];
   1871 	vmode_t		*pv;
   1872 
   1873 	p = Draw_CachePic ("gfx/vidmodes.lmp");
   1874 	M_DrawPic ( (320-p->width)/2, 4, p);
   1875 
   1876 	vid_wmodes = 0;
   1877 	lnummodes = VID_NumModes ();
   1878 
   1879 	for (i=1 ; (i<lnummodes) && (vid_wmodes < MAX_MODEDESCS) ; i++)
   1880 	{
   1881 		ptr = VID_GetModeDescription (i);
   1882 		pv = VID_GetModePtr (i);
   1883 
   1884 		k = vid_wmodes;
   1885 
   1886 		modedescs[k].modenum = i;
   1887 		modedescs[k].desc = ptr;
   1888 		modedescs[k].iscur = 0;
   1889 
   1890 		if (i == vid_modenum)
   1891 			modedescs[k].iscur = 1;
   1892 
   1893 		vid_wmodes++;
   1894 
   1895 	}
   1896 
   1897 	if (vid_wmodes > 0)
   1898 	{
   1899 		M_Print (2*8, 36+0*8, "Fullscreen Modes (WIDTHxHEIGHTxBPP)");
   1900 
   1901 		column = 8;
   1902 		row = 36+2*8;
   1903 
   1904 		for (i=0 ; i<vid_wmodes ; i++)
   1905 		{
   1906 			if (modedescs[i].iscur)
   1907 				M_PrintWhite (column, row, modedescs[i].desc);
   1908 			else
   1909 				M_Print (column, row, modedescs[i].desc);
   1910 
   1911 			column += 13*8;
   1912 
   1913 			if ((i % VID_ROW_SIZE) == (VID_ROW_SIZE - 1))
   1914 			{
   1915 				column = 8;
   1916 				row += 8;
   1917 			}
   1918 		}
   1919 	}
   1920 
   1921 	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*2,
   1922 			 "Video modes must be set from the");
   1923 	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3,
   1924 			 "command line with -width <width>");
   1925 	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4,
   1926 			 "and -bpp <bits-per-pixel>");
   1927 	M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6,
   1928 			 "Select windowed mode with -window");
   1929 }
   1930 
   1931 
   1932 /*
   1933 ================
   1934 VID_MenuKey
   1935 ================
   1936 */
   1937 void VID_MenuKey (int key)
   1938 {
   1939 	switch (key)
   1940 	{
   1941 	case K_ESCAPE:
   1942 		S_LocalSound ("misc/menu1.wav");
   1943 		M_Menu_Options_f ();
   1944 		break;
   1945 
   1946 	default:
   1947 		break;
   1948 	}
   1949 }
   1950