1 /*
2  * gl_vidnt.c -- NT GL vid component
3  * $Id: gl_vidnt.c 6029 2018-04-04 05:56:12Z sezero $
4  *
5  * Copyright (C) 1996-1997  Id Software, Inc.
6  * Copyright (C) 1997-1998  Raven Software Corp.
7  * Copyright (C) 2005-2016  O.Sezer <sezero@users.sourceforge.net>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or (at
12  * your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * See the GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  */
24 
25 #define	__GL_FUNC_EXTERN
26 
27 #include "quakedef.h"
28 #include "winquake.h"
29 #include <mmsystem.h>
30 #include "cfgfile.h"
31 #include "bgmusic.h"
32 #include "cdaudio.h"
33 #include "resource.h"
34 #include "wgl_func.h"
35 
36 #define WARP_WIDTH		320
37 #define WARP_HEIGHT		200
38 #define MAXWIDTH		10000
39 #define MAXHEIGHT		10000
40 #define MIN_WIDTH		320
41 //#define MIN_HEIGHT		200
42 #define MIN_HEIGHT		240
43 #define MAX_DESC		33
44 #define MAX_NUMBPP		8
45 
46 typedef struct {
47 	modestate_t	type;
48 	int			width;
49 	int			height;
50 	int			modenum;
51 	int			dib;
52 	int			fullscreen;
53 	int			bpp;
54 	int			halfscreen;
55 	char		modedesc[MAX_DESC];
56 } vmode_t;
57 
58 typedef struct {
59 	int	width;
60 	int	height;
61 } stdmode_t;
62 
63 #define RES_640X480	3
64 static const stdmode_t	std_modes[] = {
65 // NOTE: keep this list in order
66 	{320, 240},	// 0
67 	{400, 300},	// 1
68 	{512, 384},	// 2
69 	{640, 480},	// 3 == RES_640X480, this is our default, below
70 			//		this is the lowresmodes region.
71 			//		either do not change its order,
72 			//		or change the above define, too
73 	{800,  600},	// 4, RES_640X480 + 1
74 	{1024, 768},	// 5, RES_640X480 + 2
75 	{1280, 1024},	// 6
76 	{1600, 1200}	// 7
77 };
78 
79 #define MAX_MODE_LIST	128
80 #define MAX_STDMODES	(sizeof(std_modes) / sizeof(std_modes[0]))
81 #define NUM_LOWRESMODES	(RES_640X480)
82 static vmode_t	fmodelist[MAX_MODE_LIST+1];	// list of enumerated fullscreen modes
83 static vmode_t	wmodelist[MAX_STDMODES +1];	// list of standart 4:3 windowed modes
84 static vmode_t	*modelist;	// modelist in use, points to one of the above lists
85 static int	bpplist[MAX_NUMBPP][2];
86 
87 static int	num_fmodes;
88 static int	num_wmodes;
89 static int	*nummodes;
90 static vmode_t	badmode;
91 
92 #if defined(H2W)
93 #define WM_CLASSNAME	"HexenWorld"
94 #define WM_WINDOWNAME	"HexenWorld"
95 #else
96 #define WM_CLASSNAME	"HexenII"
97 #define WM_WINDOWNAME	"HexenII"
98 #endif
99 
100 static HGLRC	baseRC;
101 static HDC	maindc;
102 static DEVMODE	gdevmode;
103 static qboolean	classregistered;
104 HWND		mainwindow;
105 static HICON	hIcon;
106 static int	DIBWidth, DIBHeight;
107 static RECT	WindowRect;
108 int		window_center_x, window_center_y, window_x, window_y, window_width, window_height;
109 RECT		window_rect;
110 static LONG	WindowStyle, ExWindowStyle;
111 qboolean	DDActive;
112 
113 static PIXELFORMATDESCRIPTOR pfd =
114 {
115 	sizeof(PIXELFORMATDESCRIPTOR),	// size of this pfd
116 	1,				// version number
117 	PFD_DRAW_TO_WINDOW		// support window
118 		| PFD_SUPPORT_OPENGL	// support OpenGL
119 		| PFD_DOUBLEBUFFER ,	// double buffered
120 	PFD_TYPE_RGBA,			// RGBA type
121 	24,				// 24-bit color depth
122 	0, 0, 0, 0, 0, 0,		// color bits ignored
123 	0,				// no alpha buffer
124 	0,				// shift bit ignored
125 	0,				// no accumulation buffer
126 	0, 0, 0, 0,			// accum bits ignored
127 	32,				// 32-bit z-buffer
128 	0,				// no stencil buffer
129 	0,				// no auxiliary buffer
130 	PFD_MAIN_PLANE,			// main layer
131 	0,				// reserved
132 	0, 0, 0				// layer masks ignored
133 };
134 
135 typedef struct {
136 	int	red,
137 		green,
138 		blue,
139 		alpha,
140 		depth,
141 		stencil;
142 } attributes_t;
143 static attributes_t	vid_attribs;
144 
145 // main vid functions
146 static LRESULT WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
147 static void AppActivate(BOOL fActive, BOOL minimize);
148 static void VID_UpdateWindowStatus (void);
149 static const char *VID_GetModeDescription (int mode);
150 
151 // vars for vid state
152 viddef_t	vid;			// global video state
153 modestate_t	modestate = MS_UNINIT;
154 static int	vid_default = MODE_WINDOWED;
155 static int	vid_modenum = NO_MODE;	// current video mode, set after mode setting succeeds
156 static int	vid_deskwidth, vid_deskheight, vid_deskbpp, vid_deskmode;
157 static qboolean	vid_conscale = false;
158 
159 static qboolean	vid_initialized = false;
160 static qboolean	vid_canalttab = false;
161 static qboolean	vid_wassuspended = false;
162 
163 // cvar vid_mode must be set before calling
164 // VID_SetMode, VID_ChangeVideoMode or VID_Restart_f
165 static cvar_t	vid_mode = {"vid_mode", "0", CVAR_NONE};
166 static cvar_t	vid_config_consize = {"vid_config_consize", "640", CVAR_ARCHIVE};
167 static cvar_t	vid_config_glx = {"vid_config_glx", "640", CVAR_ARCHIVE};
168 static cvar_t	vid_config_gly = {"vid_config_gly", "480", CVAR_ARCHIVE};
169 static cvar_t	vid_config_bpp = {"vid_config_bpp", "16", CVAR_ARCHIVE};
170 static cvar_t	vid_config_fscr= {"vid_config_fscr", "1", CVAR_ARCHIVE};
171 // cvars for compatibility with the software version
172 static cvar_t	vid_wait = {"vid_wait", "-1", CVAR_ARCHIVE};
173 static cvar_t	vid_maxpages = {"vid_maxpages", "3", CVAR_ARCHIVE};
174 static cvar_t	vid_nopageflip = {"vid_nopageflip", "1", CVAR_ARCHIVE};
175 // Note that 0 is MODE_WINDOWED
176 // Note that 3 is MODE_FULLSCREEN_DEFAULT
177 static cvar_t	_vid_default_mode = {"_vid_default_mode", "0", CVAR_ARCHIVE};
178 static cvar_t	_vid_default_mode_win = {"_vid_default_mode_win", "3", CVAR_ARCHIVE};
179 static cvar_t	vid_stretch_by_2 = {"vid_stretch_by_2", "1", CVAR_ARCHIVE};
180 static cvar_t	vid_config_x = {"vid_config_x", "800", CVAR_ARCHIVE};
181 static cvar_t	vid_config_y = {"vid_config_y", "600", CVAR_ARCHIVE};
182 
183 byte		globalcolormap[VID_GRADES*256];
184 float		RTint[256], GTint[256], BTint[256];
185 unsigned short	d_8to16table[256];
186 unsigned int	d_8to24table[256];
187 unsigned int	d_8to24TranslucentTable[256];
188 unsigned char	*inverse_pal;
189 
190 // gl stuff
191 static void GL_Init (void);
192 
193 static HINSTANCE	hInstGL;
194 #ifdef GL_DLSYM
195 static const char	*gl_library;
196 #endif
197 
198 static const char	*gl_vendor;
199 static const char	*gl_renderer;
200 static const char	*gl_version;
201 static const char	*gl_extensions;
202 qboolean	is_3dfx = false;
203 
204 GLint		gl_max_size = 256;
205 static qboolean	have_NPOT = false;
206 qboolean	gl_tex_NPOT = false;
207 static cvar_t	gl_texture_NPOT = {"gl_texture_NPOT", "0", CVAR_ARCHIVE};
208 GLfloat		gl_max_anisotropy;
209 float		gldepthmin, gldepthmax;
210 
211 // palettized textures
212 static qboolean	have8bit = false;
213 qboolean	is8bit = false;
214 static cvar_t	vid_config_gl8bit = {"vid_config_gl8bit", "0", CVAR_ARCHIVE};
215 
216 // Gamma stuff
217 typedef BOOL	(WINAPI *GAMMA_RAMP_FN)(HDC, LPVOID);
218 static GAMMA_RAMP_FN	GetDeviceGammaRamp_f;
219 static GAMMA_RAMP_FN	SetDeviceGammaRamp_f;
220 extern unsigned short	ramps[3][256];	// for hw- or 3dfx-gamma
221 static unsigned short	orig_ramps[3][256];	// for hw- or 3dfx-gamma
222 static qboolean	gammaworks = false;	// whether hw-gamma works
223 
224 // multitexturing
225 qboolean	gl_mtexable = false;
226 static GLint	num_tmus = 1;
227 static qboolean	have_mtex = false;
228 static cvar_t	gl_multitexture = {"gl_multitexture", "0", CVAR_ARCHIVE};
229 
230 // stencil buffer
231 qboolean	have_stencil = false;
232 
233 // this is useless: things aren't like those in quake
234 //static qboolean	fullsbardraw = false;
235 
236 // menu drawing
237 static void VID_MenuDraw (void);
238 static void VID_MenuKey (int key);
239 
240 // input stuff
241 static void ClearAllStates (void);
242 static int	enable_mouse;
243 cvar_t		_enable_mouse = {"_enable_mouse", "0", CVAR_ARCHIVE};
244 
245 
246 //====================================
247 
GL_ParseExtensionList(const char * list,const char * name)248 static qboolean GL_ParseExtensionList (const char *list, const char *name)
249 {
250 	const char	*start;
251 	const char	*where, *terminator;
252 
253 	if (!list || !name || !*name)
254 		return false;
255 	if (strchr(name, ' ') != NULL)
256 		return false;	// extension names must not have spaces
257 
258 	start = list;
259 	while (1) {
260 		where = strstr (start, name);
261 		if (!where)
262 			break;
263 		terminator = where + strlen (name);
264 		if (where == start || where[-1] == ' ')
265 			if (*terminator == ' ' || *terminator == '\0')
266 				return true;
267 		start = terminator;
268 	}
269 	return false;
270 }
271 
272 //====================================
273 
VID_LockBuffer(void)274 void VID_LockBuffer (void)
275 {
276 // nothing to do
277 }
278 
VID_UnlockBuffer(void)279 void VID_UnlockBuffer (void)
280 {
281 // nothing to do
282 }
283 
VID_HandlePause(qboolean paused)284 void VID_HandlePause (qboolean paused)
285 {
286 	if ((modestate == MS_WINDOWED) && _enable_mouse.integer)
287 	{
288 		if (paused)
289 		{
290 			IN_DeactivateMouse ();
291 			IN_ShowMouse ();
292 		}
293 		else
294 		{
295 			IN_ActivateMouse ();
296 			IN_HideMouse ();
297 		}
298 	}
299 }
300 
301 
302 //====================================
303 
CenterWindow(HWND hWndCenter,int width,int height)304 static void CenterWindow (HWND hWndCenter, int width, int height)
305 {
306 	int	CenterX, CenterY;
307 
308 	CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
309 	CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
310 	if (CenterX > 2*CenterY)
311 		CenterX >>= 1;	// dual screen?
312 	if (CenterX < 0)
313 		CenterX = 0;
314 	if (CenterY < 0)
315 		CenterY = 0;
316 	SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
317 			SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
318 }
319 
VID_ConWidth(int modenum)320 static void VID_ConWidth (int modenum)
321 {
322 	int	w, h;
323 
324 	if (!vid_conscale)
325 	{
326 		Cvar_SetValueQuick (&vid_config_consize, modelist[modenum].width);
327 		return;
328 	}
329 
330 	w = vid_config_consize.integer;
331 	w &= ~7; /* make it a multiple of eight */
332 	if (w < MIN_WIDTH)
333 		w = MIN_WIDTH;
334 	else if (w > modelist[modenum].width)
335 		w = modelist[modenum].width;
336 
337 	h = w * modelist[modenum].height / modelist[modenum].width;
338 	if (h < 200 /* MIN_HEIGHT */ ||
339 	    h > modelist[modenum].height || w > modelist[modenum].width)
340 	{
341 		vid_conscale = false;
342 		Cvar_SetValueQuick (&vid_config_consize, modelist[modenum].width);
343 		return;
344 	}
345 	vid.width = vid.conwidth = w;
346 	vid.height = vid.conheight = h;
347 	if (w != modelist[modenum].width)
348 		vid_conscale = true;
349 	else	vid_conscale = false;
350 }
351 
VID_ChangeConsize(int dir)352 void VID_ChangeConsize (int dir)
353 {
354 	int	w, h;
355 
356 	switch (dir)
357 	{
358 	case -1: /* smaller text */
359 		w = ((float)vid.conwidth/(float)vid.width + 0.05f) * vid.width; /* use 0.10f increment ?? */
360 		w &= ~7; /* make it a multiple of eight */
361 		if (w > modelist[vid_modenum].width)
362 			w = modelist[vid_modenum].width;
363 		break;
364 
365 	case 1: /* bigger text */
366 		w = ((float)vid.conwidth/(float)vid.width - 0.05f) * vid.width;
367 		w &= ~7; /* make it a multiple of eight */
368 		if (w < MIN_WIDTH)
369 			w = MIN_WIDTH;
370 		break;
371 
372 	default:	/* bad key */
373 		return;
374 	}
375 
376 	h = w * modelist[vid_modenum].height / modelist[vid_modenum].width;
377 	if (h < 200)
378 		return;
379 	vid.width = vid.conwidth = w;
380 	vid.height = vid.conheight = h;
381 	Cvar_SetValueQuick (&vid_config_consize, vid.conwidth);
382 	vid.recalc_refdef = 1;
383 	if (vid.conwidth != modelist[vid_modenum].width)
384 		vid_conscale = true;
385 	else	vid_conscale = false;
386 }
387 
VID_ReportConsize(void)388 float VID_ReportConsize(void)
389 {
390 	return (float)modelist[vid_modenum].width/vid.conwidth;
391 }
392 
393 
VID_SetWindowedMode(int modenum)394 static qboolean VID_SetWindowedMode (int modenum)
395 {
396 	int	width, height;
397 	RECT	rect;
398 
399 	pfd.cColorBits = 24;
400 	pfd.cRedBits = 0;
401 	pfd.cGreenBits = 0;
402 	pfd.cBlueBits = 0;
403 	pfd.cAlphaBits = 0;
404 	pfd.cDepthBits = 32;
405 	pfd.cStencilBits = 0;
406 	if (vid_deskbpp >= 32) {
407 		pfd.cRedBits = 8;
408 		pfd.cGreenBits = 8;
409 		pfd.cBlueBits = 8;
410 		pfd.cAlphaBits = 8;
411 		pfd.cDepthBits = 24;
412 		pfd.cStencilBits = 8;
413 	}
414 
415 	// Pa3PyX: set the original fullscreen mode if
416 	// we are switching to window from fullscreen.
417 	if (modestate == MS_FULLDIB)
418 		ChangeDisplaySettings(NULL, 0);
419 
420 	WindowRect.top = WindowRect.left = 0;
421 
422 	WindowRect.right = modelist[modenum].width;
423 	WindowRect.bottom = modelist[modenum].height;
424 
425 	DIBWidth = modelist[modenum].width;
426 	DIBHeight = modelist[modenum].height;
427 
428 	WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE;
429 	ExWindowStyle = 0;
430 
431 	rect = WindowRect;
432 	AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
433 
434 	width = rect.right - rect.left;
435 	height = rect.bottom - rect.top;
436 
437 	mainwindow = CreateWindowEx (ExWindowStyle, WM_CLASSNAME, WM_WINDOWNAME, WindowStyle,
438 					rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
439 	if (!mainwindow)
440 		Sys_Error ("Couldn't create DIB window");
441 
442 	// center the DIB window
443 	CenterWindow(mainwindow, WindowRect.right - WindowRect.left,
444 				 WindowRect.bottom - WindowRect.top);
445 
446 	modestate = MS_WINDOWED;
447 	Cvar_SetQuick (&vid_config_fscr, "0");
448 
449 	return true;
450 }
451 
452 
VID_SetFullDIBMode(int modenum)453 static qboolean VID_SetFullDIBMode (int modenum)
454 {
455 	int	width, height;
456 	RECT	rect;
457 
458 	pfd.cColorBits = modelist[modenum].bpp;
459 	if (modelist[modenum].bpp >= 32) {
460 		pfd.cRedBits = 8;
461 		pfd.cGreenBits = 8;
462 		pfd.cBlueBits = 8;
463 		pfd.cAlphaBits = 8;
464 		pfd.cDepthBits = 24;
465 		pfd.cStencilBits = 8;
466 	}
467 	else {
468 		pfd.cRedBits = 5;
469 		pfd.cGreenBits = 5;
470 		pfd.cBlueBits = 5;
471 		pfd.cAlphaBits = 0;
472 		pfd.cDepthBits = 16;
473 		pfd.cStencilBits = 0;
474 	}
475 
476 	gdevmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
477 	if (!Win95old)
478 	{
479 		gdevmode.dmFields |= DM_BITSPERPEL;
480 		gdevmode.dmBitsPerPel = modelist[modenum].bpp;
481 	}
482 	gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].halfscreen;
483 	gdevmode.dmPelsHeight = modelist[modenum].height;
484 	gdevmode.dmSize = sizeof (gdevmode);
485 
486 	if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
487 		Sys_Error ("Couldn't set fullscreen DIB mode");
488 
489 	WindowRect.top = WindowRect.left = 0;
490 
491 	WindowRect.right = modelist[modenum].width;
492 	WindowRect.bottom = modelist[modenum].height;
493 
494 	DIBWidth = modelist[modenum].width;
495 	DIBHeight = modelist[modenum].height;
496 
497 	WindowStyle = WS_POPUP | WS_SYSMENU | WS_VISIBLE;
498 	ExWindowStyle = WS_EX_TOPMOST;
499 
500 	rect = WindowRect;
501 	AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
502 
503 	width = rect.right - rect.left;
504 	height = rect.bottom - rect.top;
505 
506 	mainwindow = CreateWindowEx (ExWindowStyle, WM_CLASSNAME, WM_WINDOWNAME, WindowStyle,
507 					rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL);
508 	if (!mainwindow)
509 		Sys_Error ("Couldn't create DIB window");
510 
511 	modestate = MS_FULLDIB;
512 	Cvar_SetQuick (&vid_config_fscr, "1");
513 
514 // needed because we're not getting WM_MOVE messages fullscreen on NT
515 	window_x = 0;
516 	window_y = 0;
517 
518 	return true;
519 }
520 
521 
VID_SetMode(int modenum,const unsigned char * palette)522 static qboolean VID_SetMode (int modenum, const unsigned char *palette)
523 {
524 	qboolean	status = false;
525 	MSG		msg;
526 	HDC		hdc;
527 
528 	if (modenum < 0 || modenum >= *nummodes)
529 		Sys_Error ("Bad video mode\n");
530 
531 	CDAudio_Pause ();
532 
533 	// Set either the fullscreen or windowed mode
534 	if (modelist[modenum].type == MS_WINDOWED)
535 	{
536 		if (_enable_mouse.integer)
537 		{
538 			status = VID_SetWindowedMode(modenum);
539 			IN_ActivateMouse ();
540 			IN_HideMouse ();
541 		}
542 		else
543 		{
544 			status = VID_SetWindowedMode(modenum);
545 			IN_DeactivateMouse ();
546 			IN_ShowMouse ();
547 		}
548 	}
549 	else if (modelist[modenum].type == MS_FULLDIB)
550 	{
551 		status = VID_SetFullDIBMode(modenum);
552 		IN_ActivateMouse ();
553 		IN_HideMouse ();
554 	}
555 	else
556 	{
557 		Sys_Error ("%s: Bad mode type in modelist", __thisfunc__);
558 	}
559 
560 	if (!status)
561 	{
562 		Sys_Error ("Couldn't set video mode");
563 	}
564 
565 	ShowWindow (mainwindow, SW_SHOWDEFAULT);
566 	UpdateWindow (mainwindow);
567 	SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
568 	SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
569 
570 	// Because we have set the background brush for the window to NULL
571 	// (to avoid flickering when re-sizing the window on the desktop),
572 	// we clear the window to black when created, otherwise it will be
573 	// empty while Quake starts up.
574 	hdc = GetDC(mainwindow);
575 	PatBlt(hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS);
576 	ReleaseDC(mainwindow, hdc);
577 
578 	vid.numpages = 2;
579 	vid.width  = vid.conwidth  = modelist[modenum].width;
580 	vid.height = vid.conheight = modelist[modenum].height;
581 
582 	// setup the effective console width
583 	VID_ConWidth(modenum);
584 
585 	window_width = DIBWidth;
586 	window_height = DIBHeight;
587 	VID_UpdateWindowStatus ();
588 
589 // now we try to make sure we get the focus on the mode switch, because
590 // sometimes in some systems we don't.  We grab the foreground, then
591 // finish setting up, pump all our messages, and sleep for a little while
592 // to let messages finish bouncing around the system, then we put
593 // ourselves at the top of the z order, then grab the foreground again,
594 // Who knows if it helps, but it probably doesn't hurt
595 	SetForegroundWindow (mainwindow);
596 	vid_modenum = modenum;
597 	Cvar_SetValueQuick (&vid_config_glx, modelist[vid_modenum].width);
598 	Cvar_SetValueQuick (&vid_config_gly, modelist[vid_modenum].height);
599 	if (modestate != MS_WINDOWED)
600 		Cvar_SetValueQuick (&vid_config_bpp, modelist[vid_modenum].bpp);
601 
602 	while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
603 	{
604 		TranslateMessage (&msg);
605 		DispatchMessage (&msg);
606 	}
607 
608 	Sleep (100);
609 
610 	SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
611 				  SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
612 				  SWP_NOCOPYBITS);
613 
614 	SetForegroundWindow (mainwindow);
615 
616 // fix the leftover Alt from any Alt-Tab or the like that switched us away
617 	ClearAllStates ();
618 
619 	CDAudio_Resume ();
620 
621 	return true;
622 }
623 
624 
625 //====================================
626 
627 #if 0 /* No.. */
628 static void CheckSetGlobalPalette (void)
629 {
630 	gl3DfxSetPaletteEXT_f gl3DfxSetPaletteEXT_fp;
631 
632 	if (GL_ParseExtensionList(gl_extensions, "3DFX_set_global_palette"))
633 	{
634 		gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) wglGetProcAddress_fp("gl3DfxSetPaletteEXT");
635 		if (!gl3DfxSetPaletteEXT_fp)
636 			gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) wglGetProcAddress_fp("3DFX_set_global_palette");
637 		if (!gl3DfxSetPaletteEXT_fp)
638 			return;
639 		Con_SafePrintf("Found 3DFX_set_global_palette\n");
640 	}
641 	else if (GL_ParseExtensionList(gl_extensions, "POWERVR_set_global_palette"))
642 	{
643 		gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) wglGetProcAddress_fp("glSetGlobalPalettePOWERVR");
644 		if (!gl3DfxSetPaletteEXT_fp)
645 			gl3DfxSetPaletteEXT_fp = (gl3DfxSetPaletteEXT_f) wglGetProcAddress_fp("POWERVR_set_global_palette");
646 		if (!gl3DfxSetPaletteEXT_fp)
647 			return;
648 		Con_SafePrintf("Found POWERVR_set_global_palette\n");
649 	}
650 	else {
651 		return;
652 	}
653 
654 	have8bit = true;
655 	if (!vid_config_gl8bit.integer)
656 		return;
657 	else
658 	{
659 		int i;
660 		GLubyte table[256][4];
661 		char *oldpal;
662 
663 		is8bit = true;
664 		oldpal = (char *) d_8to24table;
665 		for (i = 0; i < 256; i++) {
666 			table[i][2] = *oldpal++;
667 			table[i][1] = *oldpal++;
668 			table[i][0] = *oldpal++;
669 			table[i][3] = 255;
670 			oldpal++;
671 		}
672 		glEnable_fp (GL_SHARED_TEXTURE_PALETTE_EXT);
673 		gl3DfxSetPaletteEXT_fp ((GLuint *)table);
674 	}
675 }
676 #endif /* #if 0 */
677 
CheckSharedTexturePalette(void)678 static void CheckSharedTexturePalette (void)
679 {
680 	glColorTableEXT_f glColorTableEXT_fp;
681 
682 	if (!GL_ParseExtensionList(gl_extensions, "GL_EXT_shared_texture_palette"))
683 		return;
684 
685 	glColorTableEXT_fp = (glColorTableEXT_f) wglGetProcAddress_fp("glColorTableEXT");
686 	if (glColorTableEXT_fp == NULL)
687 		return;
688 
689 	have8bit = true;
690 	Con_SafePrintf("Found GL_EXT_shared_texture_palette\n");
691 	if (!vid_config_gl8bit.integer)
692 		return;
693 	else
694 	{
695 		int i;
696 		char thePalette[256*3];
697 		char *oldPalette, *newPalette;
698 
699 		is8bit = true;
700 		oldPalette = (char *) d_8to24table;
701 		newPalette = thePalette;
702 		for (i = 0; i < 256; i++) {
703 			*newPalette++ = *oldPalette++;
704 			*newPalette++ = *oldPalette++;
705 			*newPalette++ = *oldPalette++;
706 			oldPalette++;
707 		}
708 
709 		glEnable_fp (GL_SHARED_TEXTURE_PALETTE_EXT);
710 		glColorTableEXT_fp (GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256,
711 					GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
712 	}
713 }
714 
VID_Init8bitPalette(void)715 static void VID_Init8bitPalette (void)
716 {
717 	have8bit = false;
718 	is8bit = false;
719 
720 	/* Check for 8bit Extensions and initialize them */
721 	CheckSharedTexturePalette();
722 #if 0	/* No.. */
723 	if (!have8bit)
724 		CheckSetGlobalPalette();
725 #endif
726 
727 	if (is8bit)
728 		Con_SafePrintf("8-bit palettized textures enabled\n");
729 }
730 
731 
VID_Check3dfxGamma(void)732 static void VID_Check3dfxGamma (void)
733 {
734 	if (!GL_ParseExtensionList(gl_extensions, "WGL_3DFX_gamma_control"))
735 	{
736 		GetDeviceGammaRamp_f = GetDeviceGammaRamp;
737 		SetDeviceGammaRamp_f = SetDeviceGammaRamp;
738 	}
739 	else
740 	{
741 		GetDeviceGammaRamp_f = (GAMMA_RAMP_FN) wglGetProcAddress_fp("wglGetDeviceGammaRamp3DFX");
742 		SetDeviceGammaRamp_f = (GAMMA_RAMP_FN) wglGetProcAddress_fp("wglSetDeviceGammaRamp3DFX");
743 		if (GetDeviceGammaRamp_f && SetDeviceGammaRamp_f)
744 			Con_SafePrintf("Using 3Dfx specific gamma control\n");
745 		else
746 		{
747 			GetDeviceGammaRamp_f = GetDeviceGammaRamp;
748 			SetDeviceGammaRamp_f = SetDeviceGammaRamp;
749 		}
750 	}
751 }
752 
VID_InitGamma(void)753 static void VID_InitGamma (void)
754 {
755 	GetDeviceGammaRamp_f = NULL;
756 	SetDeviceGammaRamp_f = NULL;
757 	gammaworks = false;
758 
759 	VID_Check3dfxGamma ();
760 
761 	if (GetDeviceGammaRamp_f)
762 		gammaworks = GetDeviceGammaRamp_f(maindc, orig_ramps);
763 
764 	if (!gammaworks)
765 		Con_SafePrintf("gamma adjustment not available\n");
766 }
767 
VID_ShiftPalette(const unsigned char * palette)768 void VID_ShiftPalette (const unsigned char *palette)
769 {
770 	if (gammaworks && SetDeviceGammaRamp_f)
771 		SetDeviceGammaRamp_f (maindc, ramps);
772 }
773 
774 
CheckMultiTextureExtensions(void)775 static void CheckMultiTextureExtensions (void)
776 {
777 	gl_mtexable = have_mtex = false;
778 
779 	if (COM_CheckParm("-nomtex"))
780 	{
781 		Con_SafePrintf("Multitexture extensions disabled\n");
782 	}
783 	else if (GL_ParseExtensionList(gl_extensions, "GL_ARB_multitexture"))
784 	{
785 		Con_SafePrintf("ARB Multitexture extensions found\n");
786 
787 		glGetIntegerv_fp(GL_MAX_TEXTURE_UNITS_ARB, &num_tmus);
788 		if (num_tmus < 2)
789 		{
790 			Con_SafePrintf("ignoring multitexture (%i TMUs)\n", (int) num_tmus);
791 			return;
792 		}
793 
794 		glMultiTexCoord2fARB_fp = (glMultiTexCoord2fARB_f) wglGetProcAddress_fp("glMultiTexCoord2fARB");
795 		glActiveTextureARB_fp = (glActiveTextureARB_f) wglGetProcAddress_fp("glActiveTextureARB");
796 		if (glMultiTexCoord2fARB_fp == NULL || glActiveTextureARB_fp == NULL)
797 		{
798 			Con_SafePrintf ("Couldn't link to multitexture functions\n");
799 			return;
800 		}
801 
802 		have_mtex = true;
803 		if (!gl_multitexture.integer)
804 		{
805 			Con_SafePrintf("ignoring multitexture (cvar disabled)\n");
806 			return;
807 		}
808 
809 		Con_SafePrintf("Found %i TMUs support\n", num_tmus);
810 		gl_mtexable = true;
811 		glDisable_fp(GL_TEXTURE_2D);
812 		glActiveTextureARB_fp(GL_TEXTURE0_ARB);
813 	}
814 	else
815 	{
816 		Con_SafePrintf("GL_ARB_multitexture not found\n");
817 	}
818 }
819 
CheckAnisotropyExtensions(void)820 static void CheckAnisotropyExtensions (void)
821 {
822 	gl_max_anisotropy = 1;
823 
824 	Con_SafePrintf("Anisotropic filtering ");
825 	if (GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_filter_anisotropic"))
826 	{
827 		GLfloat test1 = 0, test2 = 0;
828 		GLuint tex;
829 		glGetTexParameterfv_f glGetTexParameterfv_fp;
830 
831 		glGetTexParameterfv_fp = (glGetTexParameterfv_f) GetProcAddress(hInstGL, "glGetTexParameterfv");
832 		if (glGetTexParameterfv_fp == NULL)
833 		{
834 			Con_SafePrintf("... can't check driver-lock status\n... ");
835 			goto _skiptest;
836 		}
837 		// test to make sure we really have control over it
838 		// 1.0 and 2.0 should always be legal values.
839 		glGenTextures_fp(1, &tex);
840 		glBindTexture_fp(GL_TEXTURE_2D, tex);
841 		glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
842 		glGetTexParameterfv_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test1);
843 		glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f);
844 		glGetTexParameterfv_fp(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &test2);
845 		glDeleteTextures_fp(1, &tex);
846 		if (test1 != 1 || test2 != 2)
847 		{
848 			Con_SafePrintf("driver-locked @ %.1f\n", test1);
849 		}
850 		else
851 		{
852 		_skiptest:
853 			glGetFloatv_fp(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max_anisotropy);
854 			if (gl_max_anisotropy < 2)
855 				Con_SafePrintf("broken\n");
856 			else	Con_SafePrintf("found, max %.1f\n", gl_max_anisotropy);
857 		}
858 	}
859 	else
860 	{
861 		Con_SafePrintf("not found\n");
862 	}
863 }
864 
CheckNonPowerOfTwoTextures(void)865 static void CheckNonPowerOfTwoTextures (void)
866 {
867 /* On Mac OS X, old Radeons lie about NPOT textures capability, they
868  * fallback to software with mipmap NPOT textures.  see, e.g.:
869  * http://lists.apple.com/archives/mac-opengl/2006/Dec/msg00000.html
870  * http://lists.apple.com/archives/mac-opengl/2009/Oct/msg00040.html
871  * http://www.idevgames.com/forums/printthread.php?tid=3814&page=2
872  * MH says NVIDIA once did the same with their GeForce FX on Windows:
873  * http://forums.inside3d.com/viewtopic.php?f=10&t=4832
874  * Therefore, advertisement of this extension is an unreliable way of
875  * detecting the actual capability.
876  */
877 	gl_tex_NPOT = have_NPOT = false;
878 	if (GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_non_power_of_two"))
879 	{
880 		have_NPOT = true;
881 		Con_SafePrintf("Found ARB_texture_non_power_of_two\n");
882 		if (!gl_texture_NPOT.integer) {
883 			Con_SafePrintf("ignoring texture_NPOT (cvar disabled)\n");
884 		}
885 		else {
886 			gl_tex_NPOT = true;
887 		}
888 	}
889 	else
890 	{
891 		Con_SafePrintf("GL_ARB_texture_non_power_of_two not found\n");
892 	}
893 }
894 
CheckStencilBuffer(void)895 static void CheckStencilBuffer (void)
896 {
897 	have_stencil = !!vid_attribs.stencil;
898 }
899 
900 
901 #ifdef GL_DLSYM
GL_OpenLibrary(const char * name)902 static qboolean GL_OpenLibrary (const char *name)
903 {
904 	int drv_standalone = q_strcasecmp(name, "opengl32.dll");
905 
906 	Con_SafePrintf("Loading OpenGL library %s\n", name);
907 
908 	// open the library
909 	if (!(hInstGL = LoadLibrary(name)))
910 	{
911 		Con_SafePrintf("Unable to LoadLibrary %s\n", name);
912 		return false;
913 	}
914 
915 	// link to necessary wgl functions
916 #define GL_FUNCTION(ret, func, params)				\
917     do {							\
918 	func##_fp = (func##_f) GetProcAddress(hInstGL, #func);	\
919 	if (func##_fp == NULL)					\
920 		Sys_Error("Couldn't link to %s", #func);	\
921     } while (0);
922 #define GL_FUNCTION_OPT(ret,func,def,params)			\
923     do {							\
924 	func##_fp = (drv_standalone)?				\
925 	   (func##_f) GetProcAddress(hInstGL, #func) : def;	\
926 	if (func##_fp == NULL)					\
927 		Sys_Error("Couldn't link to %s", #func);	\
928     } while (0);
929 #include "wgl_func.h"
930 
931 	return true;
932 }
933 
GL_CloseLibrary(void)934 static void GL_CloseLibrary (void)
935 {
936 	// clear the wgl function pointers
937 #define GL_FUNCTION(ret, func, params)	\
938 	func##_fp = NULL;
939 #define GL_FUNCTION_OPT(ret,func,def,params) \
940 	func##_fp = NULL;
941 #include "wgl_func.h"
942 
943 	// free the library
944 	if (hInstGL != NULL)
945 		FreeLibrary(hInstGL);
946 	hInstGL = NULL;
947 }
948 
GL_Init_Functions(void)949 static void GL_Init_Functions (void)
950 {
951 #define GL_FUNCTION(ret, func, params)				\
952     do {							\
953 	func##_fp = (func##_f) GetProcAddress(hInstGL, #func);	\
954 	if (func##_fp == NULL)					\
955 		Sys_Error("%s not found in GL library", #func);	\
956     } while (0);
957 #define GL_FUNCTION_OPT(ret, func, params)
958 #include "gl_func.h"
959 }
960 #endif	/* GL_DLSYM */
961 
GL_ResetFunctions(void)962 static void GL_ResetFunctions (void)
963 {
964 #ifdef	GL_DLSYM
965 #define GL_FUNCTION(ret, func, params)	\
966 	func##_fp = NULL;
967 #endif
968 #define GL_FUNCTION_OPT(ret, func, params) \
969 	func##_fp = NULL;
970 #include "gl_func.h"
971 
972 	GetDeviceGammaRamp_f = NULL;
973 	SetDeviceGammaRamp_f = NULL;
974 
975 	have_stencil = false;
976 	gl_mtexable = false;
977 	have_mtex = false;
978 	have8bit = false;
979 	is8bit = false;
980 	have_NPOT = false;
981 	gl_tex_NPOT = false;
982 }
983 
984 
985 /*
986 ===============
987 GL_Init
988 ===============
989 */
GL_Init(void)990 static void GL_Init (void)
991 {
992 	PIXELFORMATDESCRIPTOR	new_pfd;
993 
994 	Con_SafePrintf ("Video mode %s initialized\n", VID_GetModeDescription (vid_modenum));
995 
996 #ifdef GL_DLSYM
997 	// initialize gl function pointers
998 	GL_Init_Functions();
999 #endif
1000 
1001 	// collect the visual attributes
1002 	memset (&new_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
1003 	memset (&vid_attribs, 0, sizeof(attributes_t));
1004 	glGetIntegerv_fp(GL_RED_BITS, &vid_attribs.red);
1005 	glGetIntegerv_fp(GL_GREEN_BITS, &vid_attribs.green);
1006 	glGetIntegerv_fp(GL_BLUE_BITS, &vid_attribs.blue);
1007 	glGetIntegerv_fp(GL_ALPHA_BITS, &vid_attribs.alpha);
1008 	glGetIntegerv_fp(GL_DEPTH_BITS, &vid_attribs.depth);
1009 	glGetIntegerv_fp(GL_STENCIL_BITS, &vid_attribs.stencil);
1010 	Con_SafePrintf ("R:%d G:%d B:%d A:%d, Z:%d, S:%d\n",
1011 			vid_attribs.red, vid_attribs.green, vid_attribs.blue, vid_attribs.alpha,
1012 			vid_attribs.depth, vid_attribs.stencil);
1013 	/* FIXME: DescribePixelFormat() used to fail with old 3dfx minigl drivers ??? */
1014 	if (wglDescribePixelFormat_fp(maindc, wglGetPixelFormat_fp(maindc), sizeof(PIXELFORMATDESCRIPTOR), &new_pfd))
1015 	{
1016 		Con_SafeDPrintf ("PFD: C:%d, R:%d G:%d B:%d A:%d, Z:%d, S:%d\n",
1017 			new_pfd.cColorBits, new_pfd.cRedBits, new_pfd.cGreenBits, new_pfd.cBlueBits,
1018 			new_pfd.cAlphaBits, new_pfd.cDepthBits, new_pfd.cStencilBits);
1019 		if ((new_pfd.dwFlags & PFD_GENERIC_FORMAT) && !(new_pfd.dwFlags & PFD_GENERIC_ACCELERATED))
1020 			Con_SafePrintf ("WARNING: Hardware acceleration not present\n");
1021 		else if (new_pfd.dwFlags & PFD_GENERIC_ACCELERATED)
1022 			Con_SafePrintf ("OpenGL: MCD acceleration found\n");
1023 	}
1024 
1025 	gl_vendor = (const char *)glGetString_fp (GL_VENDOR);
1026 	Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
1027 	gl_renderer = (const char *)glGetString_fp (GL_RENDERER);
1028 	Con_SafePrintf ("GL_RENDERER: %s\n", gl_renderer);
1029 
1030 	gl_version = (const char *)glGetString_fp (GL_VERSION);
1031 	Con_SafePrintf ("GL_VERSION: %s\n", gl_version);
1032 	gl_extensions = (const char *)glGetString_fp (GL_EXTENSIONS);
1033 	Con_SafeDPrintf ("GL_EXTENSIONS: %s\n", gl_extensions);
1034 
1035 	glGetIntegerv_fp(GL_MAX_TEXTURE_SIZE, &gl_max_size);
1036 	if (gl_max_size < 256)	// Refuse to work when less than 256
1037 		Sys_Error ("hardware capable of min. 256k opengl texture size needed");
1038 	Con_SafePrintf("OpenGL max.texture size: %i\n", gl_max_size);
1039 
1040 	is_3dfx = false;
1041 	if (!q_strncasecmp(gl_renderer, "3dfx", 4)	  ||
1042 	    !q_strncasecmp(gl_renderer, "SAGE Glide", 10) ||
1043 	    !q_strncasecmp(gl_renderer, "Glide ", 6)	  || /* possible with Mesa 3.x/4.x/5.0.x */
1044 	    !q_strncasecmp(gl_renderer, "Mesa Glide", 10))
1045 	{
1046 		Con_SafePrintf("3dfx Voodoo found\n");
1047 		is_3dfx = true;
1048 	}
1049 
1050 //	if (!q_strncasecmp(gl_renderer, "PowerVR", 7))
1051 //		fullsbardraw = true;
1052 
1053 	VID_InitGamma ();
1054 
1055 	CheckMultiTextureExtensions();
1056 	CheckAnisotropyExtensions();
1057 	CheckNonPowerOfTwoTextures();
1058 	CheckStencilBuffer();
1059 
1060 	glClearColor_fp (1,0,0,0);
1061 	glCullFace_fp(GL_FRONT);
1062 	glEnable_fp(GL_TEXTURE_2D);
1063 
1064 	glEnable_fp(GL_ALPHA_TEST);
1065 	glAlphaFunc_fp(GL_GREATER, 0.632); // 1 - e^-1 : replaced 0.666 to avoid clipping of smaller fonts/graphics
1066 #if 0 /* causes side effects at least in 16 bpp.  */
1067 	/* Get rid of Z-fighting for textures by offsetting the
1068 	 * drawing of entity models compared to normal polygons.
1069 	 * (See: R_DrawBrushModel.)
1070 	 * (Only works if gl_ztrick is turned off) */
1071 	glPolygonOffset_fp(0.05f, 25.0f);
1072 #endif /* #if 0 */
1073 	glPolygonMode_fp (GL_FRONT_AND_BACK, GL_FILL);
1074 	glShadeModel_fp (GL_FLAT);
1075 
1076 	glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1077 	glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1078 
1079 	glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1080 	glTexParameterf_fp(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1081 
1082 	glBlendFunc_fp (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1083 
1084 //	glTexEnvf_fp(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1085 	glTexEnvf_fp(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1086 }
1087 
1088 
1089 /*
1090 =================
1091 GL_BeginRendering
1092 
1093 =================
1094 */
GL_BeginRendering(int * x,int * y,int * width,int * height)1095 void GL_BeginRendering (int *x, int *y, int *width, int *height)
1096 {
1097 	*x = *y = 0;
1098 	*width = WindowRect.right - WindowRect.left;
1099 	*height = WindowRect.bottom - WindowRect.top;
1100 
1101 //	if (!wglMakeCurrent_fp( maindc, baseRC ))
1102 //		Sys_Error ("wglMakeCurrent failed");
1103 
1104 //	glViewport_fp (*x, *y, *width, *height);
1105 }
1106 
1107 
GL_EndRendering(void)1108 void GL_EndRendering (void)
1109 {
1110 	if (!scr_skipupdate)
1111 		wglSwapBuffers_fp(maindc);
1112 
1113 // handle the mouse state when windowed if that's changed
1114 	if (modestate == MS_WINDOWED)
1115 	{
1116 		if (_enable_mouse.integer != enable_mouse)
1117 		{
1118 			if (_enable_mouse.integer)
1119 			{
1120 				IN_ActivateMouse ();
1121 				IN_HideMouse ();
1122 			}
1123 			else
1124 			{
1125 				IN_DeactivateMouse ();
1126 				IN_ShowMouse ();
1127 			}
1128 
1129 			enable_mouse = _enable_mouse.integer;
1130 		}
1131 	}
1132 
1133 //	if (fullsbardraw)
1134 //		Sbar_Changed();
1135 }
1136 
1137 
1138 const int ColorIndex[16] = {
1139 	0, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 199, 207, 223, 231
1140 };
1141 
1142 const unsigned int ColorPercent[16] = {
1143 	25, 51, 76, 102, 114, 127, 140, 153, 165, 178, 191, 204, 216, 229, 237, 247
1144 };
1145 
1146 #define	INVERSE_PALNAME	"gfx/invpal.lmp"
ConvertTrueColorToPal(const unsigned char * true_color,const unsigned char * palette)1147 static int ConvertTrueColorToPal (const unsigned char *true_color, const unsigned char *palette)
1148 {
1149 	int	i;
1150 	long	min_dist;
1151 	int	min_index;
1152 	long	r, g, b;
1153 
1154 	min_dist = 256 * 256 + 256 * 256 + 256 * 256;
1155 	min_index = -1;
1156 	r = (long) true_color[0];
1157 	g = (long) true_color[1];
1158 	b = (long) true_color[2];
1159 
1160 	for (i = 0; i < 256; i++)
1161 	{
1162 		long palr, palg, palb, dist;
1163 		long dr, dg, db;
1164 
1165 		palr = palette[3*i];
1166 		palg = palette[3*i+1];
1167 		palb = palette[3*i+2];
1168 		dr = palr - r;
1169 		dg = palg - g;
1170 		db = palb - b;
1171 		dist = dr * dr + dg * dg + db * db;
1172 		if (dist < min_dist)
1173 		{
1174 			min_dist = dist;
1175 			min_index = i;
1176 		}
1177 	}
1178 	return min_index;
1179 }
1180 
VID_CreateInversePalette(const unsigned char * palette)1181 static void VID_CreateInversePalette (const unsigned char *palette)
1182 {
1183 	long	r, g, b;
1184 	long	idx = 0;
1185 	unsigned char	true_color[3];
1186 
1187 	Con_SafePrintf ("Creating inverse palette\n");
1188 
1189 	for (r = 0; r < (1 << INVERSE_PAL_R_BITS); r++)
1190 	{
1191 		for (g = 0; g < (1 << INVERSE_PAL_G_BITS); g++)
1192 		{
1193 			for (b = 0; b < (1 << INVERSE_PAL_B_BITS); b++)
1194 			{
1195 				true_color[0] = (unsigned char)(r << (8 - INVERSE_PAL_R_BITS));
1196 				true_color[1] = (unsigned char)(g << (8 - INVERSE_PAL_G_BITS));
1197 				true_color[2] = (unsigned char)(b << (8 - INVERSE_PAL_B_BITS));
1198 				inverse_pal[idx] = ConvertTrueColorToPal(true_color, palette);
1199 				idx++;
1200 			}
1201 		}
1202 	}
1203 
1204 	FS_CreatePath(FS_MakePath(FS_USERDIR, NULL, INVERSE_PALNAME));
1205 	FS_WriteFile (INVERSE_PALNAME, inverse_pal, INVERSE_PAL_SIZE);
1206 }
1207 
VID_InitPalette(const unsigned char * palette)1208 static void VID_InitPalette (const unsigned char *palette)
1209 {
1210 	const unsigned char	*pal;
1211 	unsigned short	r, g, b;
1212 	unsigned short	i, p, c;
1213 	unsigned int	v, *table;
1214 	int		mark;
1215 
1216 #if ENDIAN_RUNTIME_DETECT
1217 	switch (host_byteorder)
1218 	{
1219 	case BIG_ENDIAN:	/* R G B A */
1220 		MASK_r	=	0xff000000;
1221 		MASK_g	=	0x00ff0000;
1222 		MASK_b	=	0x0000ff00;
1223 		MASK_a	=	0x000000ff;
1224 		SHIFT_r	=	24;
1225 		SHIFT_g	=	16;
1226 		SHIFT_b	=	8;
1227 		SHIFT_a	=	0;
1228 		break;
1229 	case LITTLE_ENDIAN:	/* A B G R */
1230 		MASK_r	=	0x000000ff;
1231 		MASK_g	=	0x0000ff00;
1232 		MASK_b	=	0x00ff0000;
1233 		MASK_a	=	0xff000000;
1234 		SHIFT_r	=	0;
1235 		SHIFT_g	=	8;
1236 		SHIFT_b	=	16;
1237 		SHIFT_a	=	24;
1238 		break;
1239 	default:
1240 		break;
1241 	}
1242 	MASK_rgb	=	(MASK_r|MASK_g|MASK_b);
1243 #endif	/* ENDIAN_RUNTIME_DETECT */
1244 
1245 //
1246 // 8 8 8 encoding
1247 //
1248 	pal = palette;
1249 	table = d_8to24table;
1250 	for (i = 0; i < 256; i++)
1251 	{
1252 		r = pal[0];
1253 		g = pal[1];
1254 		b = pal[2];
1255 		pal += 3;
1256 
1257 		v = (255 << SHIFT_a) + (r << SHIFT_r) + (g << SHIFT_g) + (b << SHIFT_b);
1258 		*table++ = v;
1259 	}
1260 
1261 	d_8to24table[255] &= MASK_rgb;	// 255 is transparent
1262 
1263 	pal = palette;
1264 	table = d_8to24TranslucentTable;
1265 
1266 	for (i = 0; i < 16; i++)
1267 	{
1268 		c = ColorIndex[i] * 3;
1269 
1270 		r = pal[c];
1271 		g = pal[c + 1];
1272 		b = pal[c + 2];
1273 
1274 		for (p = 0; p < 16; p++)
1275 		{
1276 			v = (ColorPercent[15 - p] << SHIFT_a) + (r << SHIFT_r) + (g << SHIFT_g) + (b << SHIFT_b);
1277 			*table++ = v;
1278 
1279 			RTint[i*16 + p] = ((float)r) / ((float)ColorPercent[15-p]);
1280 			GTint[i*16 + p] = ((float)g) / ((float)ColorPercent[15-p]);
1281 			BTint[i*16 + p] = ((float)b) / ((float)ColorPercent[15-p]);
1282 		}
1283 	}
1284 
1285 	// Initialize the palettized textures data
1286 	mark = Hunk_LowMark ();
1287 	inverse_pal = (unsigned char *) FS_LoadHunkFile (INVERSE_PALNAME, NULL);
1288 	if (inverse_pal != NULL && fs_filesize != INVERSE_PAL_SIZE)
1289 	{
1290 		Hunk_FreeToLowMark (mark);
1291 		inverse_pal = NULL;
1292 	}
1293 	if (inverse_pal == NULL)
1294 	{
1295 		inverse_pal = (unsigned char *) Hunk_AllocName (INVERSE_PAL_SIZE + 1, INVERSE_PALNAME);
1296 		VID_CreateInversePalette (palette);
1297 	}
1298 }
1299 
VID_SetPalette(const unsigned char * palette)1300 void VID_SetPalette (const unsigned char *palette)
1301 {
1302 // nothing to do
1303 }
1304 
1305 
1306 //==========================================================================
1307 
bSetupPixelFormat(HDC hDC)1308 static BOOL bSetupPixelFormat (HDC hDC)
1309 {
1310 	int	pixelformat;
1311 
1312 	if ( (pixelformat = wglChoosePixelFormat_fp(hDC, &pfd)) == 0 )
1313 	{
1314 		MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
1315 		return FALSE;
1316 	}
1317 
1318 	if (wglSetPixelFormat_fp(hDC, pixelformat, &pfd) == FALSE)
1319 	{
1320 		MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
1321 		return FALSE;
1322 	}
1323 
1324 	return TRUE;
1325 }
1326 
1327 
1328 /*
1329 =======
1330 MapKey
1331 
1332 Map from windows to quake keynums
1333 =======
1334 */
1335 static byte scantokey[128] =
1336 {
1337 //	0        1       2       3       4       5       6       7
1338 //	8        9       A       B       C       D       E       F
1339 	0  ,    27,     '1',    '2',    '3',    '4',    '5',    '6',
1340 	'7',    '8',    '9',    '0',    '-',    '=', K_BACKSPACE, 9,	// 0
1341 	'q',    'w',    'e',    'r',    't',    'y',    'u',    'i',
1342 	'o',    'p',    '[',    ']',  K_ENTER, K_CTRL,  'a',    's',	// 1
1343 	'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';',
1344 	'\'',   '`',  K_SHIFT,  '\\',   'z',    'x',    'c',    'v',	// 2
1345 	'b',    'n',    'm',    ',',    '.',    '/',  K_SHIFT, K_KP_STAR,
1346 	K_ALT,  ' ',     0 ,    K_F1,   K_F2,   K_F3,   K_F4,  K_F5,	// 3
1347 	K_F6,  K_F7,   K_F8,    K_F9,  K_F10, K_PAUSE,   0 , K_HOME,
1348 	K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW,K_KP_PLUS,K_END,	// 4
1349 	K_DOWNARROW,K_PGDN,K_INS,K_DEL,   0 ,    0 ,     0 ,  K_F11,
1350 	K_F12,   0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0 ,	// 5
1351 	0  ,     0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0 ,
1352 	0  ,     0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0 ,	// 6
1353 	0  ,     0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0 ,
1354 	0  ,     0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0	// 7
1355 };
1356 
1357 #if 0	/* not used */
1358 static byte shiftscantokey[128] =
1359 {
1360 //	0       1       2       3       4       5       6       7
1361 //	8       9       A       B       C       D       E       F
1362 	0  ,    27,     '!',    '@',    '#',    '$',    '%',    '^',
1363 	'&',    '*',    '(',    ')',    '_',    '+', K_BACKSPACE, 9,	// 0
1364 	'Q',    'W',    'E',    'R',    'T',    'Y',    'U',    'I',
1365 	'O',    'P',    '{',    '}',  K_ENTER, K_CTRL,  'A',    'S',	// 1
1366 	'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':',
1367 	'"' ,    '~', K_SHIFT,  '|',    'Z',    'X',    'C',    'V',	// 2
1368 	'B',    'N',    'M',    '<',    '>',    '?',  K_SHIFT, K_KP_STAR,
1369 	K_ALT,  ' ',     0 ,    K_F1,   K_F2,   K_F3,   K_F4,  K_F5,	// 3
1370 	K_F6,  K_F7,   K_F8,    K_F9,  K_F10, K_PAUSE,   0 , K_HOME,
1371 	K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW,K_KP_PLUS,K_END,	// 4
1372 	K_DOWNARROW,K_PGDN,K_INS,K_DEL,   0 ,    0 ,     0 ,  K_F11,
1373 	K_F12,   0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0 ,	// 5
1374 	0  ,     0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0 ,
1375 	0  ,     0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0 ,	// 6
1376 	0  ,     0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0 ,
1377 	0  ,     0 ,     0 ,     0 ,      0 ,    0 ,     0 ,     0	// 7
1378 };
1379 #endif
1380 
MapKey(int key)1381 static int MapKey (int key)
1382 {
1383 	int result = (key >> 16) & 255;
1384 
1385 	if (result > 127)
1386 		return 0;
1387 	result = scantokey[result];
1388 
1389 	if (key & (1 << 24)) /* extended */
1390 	{
1391 		switch (result)
1392 		{
1393 		case K_PAUSE:
1394 			return	(Key_IsGameKey()) ? K_KP_NUMLOCK : 0;
1395 		case K_ENTER:
1396 			return	(Key_IsGameKey()) ? K_KP_ENTER : K_ENTER;
1397 		case '/':
1398 			return	(Key_IsGameKey()) ? K_KP_SLASH : '/';
1399 		}
1400 	}
1401 	else /* standart */
1402 	{
1403 		switch (result)
1404 		{
1405 		case K_KP_STAR:
1406 			return	(Key_IsGameKey()) ? K_KP_STAR : '*';
1407 		case K_KP_PLUS:
1408 			return	(Key_IsGameKey()) ? K_KP_PLUS : '+';
1409 		case K_KP_MINUS:
1410 			return	(Key_IsGameKey()) ? K_KP_MINUS : '-';
1411 		case K_HOME:
1412 			return	(Key_IsGameKey()) ? K_KP_HOME :
1413 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '7' : K_HOME;
1414 		case K_UPARROW:
1415 			return	(Key_IsGameKey()) ? K_KP_UPARROW :
1416 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '8' : K_UPARROW;
1417 		case K_PGUP:
1418 			return	(Key_IsGameKey()) ? K_KP_PGUP :
1419 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '9' : K_PGUP;
1420 		case K_LEFTARROW:
1421 			return	(Key_IsGameKey()) ? K_KP_LEFTARROW :
1422 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '4' : K_LEFTARROW;
1423 		case K_KP_5:
1424 			return	(Key_IsGameKey()) ? K_KP_5 : '5';
1425 		case K_RIGHTARROW:
1426 			return	(Key_IsGameKey()) ? K_KP_RIGHTARROW :
1427 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '6' : K_RIGHTARROW;
1428 		case K_END:
1429 			return	(Key_IsGameKey()) ? K_KP_END :
1430 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '1' : K_END;
1431 		case K_DOWNARROW:
1432 			return	(Key_IsGameKey()) ? K_KP_DOWNARROW :
1433 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '2' : K_DOWNARROW;
1434 		case K_PGDN:
1435 			return	(Key_IsGameKey()) ? K_KP_PGDN :
1436 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '3' : K_PGDN;
1437 		case K_INS:
1438 			return	(Key_IsGameKey()) ? K_KP_INS :
1439 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '0' : K_INS;
1440 		case K_DEL:
1441 			return	(Key_IsGameKey()) ? K_KP_DEL :
1442 				(GetKeyState(VK_NUMLOCK) & 0x01) ? '.' : K_DEL;
1443 		}
1444 	}
1445 
1446 	return result;
1447 }
1448 
1449 /*
1450 ===================================================================
1451 
1452 MAIN WINDOW
1453 
1454 ===================================================================
1455 */
1456 
1457 /*
1458 ================
1459 ClearAllStates
1460 ================
1461 */
ClearAllStates(void)1462 static void ClearAllStates (void)
1463 {
1464 	Key_ClearStates ();
1465 	IN_ClearStates ();
1466 }
1467 
1468 /*
1469 ================
1470 VID_UpdateWindowStatus
1471 ================
1472 */
VID_UpdateWindowStatus(void)1473 static void VID_UpdateWindowStatus (void)
1474 {
1475 	window_rect.left = window_x;
1476 	window_rect.top = window_y;
1477 	window_rect.right = window_x + window_width;
1478 	window_rect.bottom = window_y + window_height;
1479 	window_center_x = (window_rect.left + window_rect.right) / 2;
1480 	window_center_y = (window_rect.top + window_rect.bottom) / 2;
1481 
1482 	IN_UpdateClipCursor ();
1483 }
1484 
1485 
AppActivate(BOOL fActive,BOOL minimize)1486 static void AppActivate (BOOL fActive, BOOL minimize)
1487 /****************************************************************************
1488 *
1489 * Function:	AppActivate
1490 * Parameters:	fActive - True if app is activating
1491 *
1492 * Description:	If the application is activating, then swap the system
1493 *		into SYSPAL_NOSTATIC mode so that our palettes will display
1494 *		correctly.
1495 *
1496 ****************************************************************************/
1497 {
1498 	static BOOL	sound_active;
1499 
1500 	ActiveApp = fActive;
1501 	Minimized = minimize;
1502 
1503 // enable/disable sound on focus gain/loss
1504 	if (!ActiveApp && sound_active)
1505 	{
1506 		S_BlockSound ();
1507 		sound_active = false;
1508 	}
1509 	else if (ActiveApp && !sound_active)
1510 	{
1511 		S_UnblockSound ();
1512 		sound_active = true;
1513 	}
1514 
1515 	if (fActive)
1516 	{
1517 		if (modestate == MS_FULLDIB)
1518 		{
1519 			if (vid_canalttab && vid_wassuspended)
1520 			{
1521 				vid_wassuspended = false;
1522 				ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
1523 				ShowWindow(mainwindow, SW_SHOWNORMAL);
1524 				// Fix for alt-tab bug in NVidia drivers, from quakeforge
1525 				MoveWindow(mainwindow, 0, 0, gdevmode.dmPelsWidth,
1526 						gdevmode.dmPelsHeight, false);
1527 			}
1528 			IN_ActivateMouse ();
1529 			IN_HideMouse ();
1530 		}
1531 		else if (modestate == MS_WINDOWED && _enable_mouse.integer)
1532 		{
1533 		// with winmouse, we may fail having our
1534 		// window back from the iconified state. yuck...
1535 			if (dinput_init)
1536 			{
1537 				IN_ActivateMouse ();
1538 				IN_HideMouse ();
1539 			}
1540 		}
1541 
1542 		if (host_initialized && !draw_reinit)	// paranoia, but just in case..
1543 			VID_ShiftPalette(NULL);
1544 	}
1545 
1546 	if (!fActive)
1547 	{
1548 		if (maindc && gammaworks && SetDeviceGammaRamp_f)
1549 		{
1550 			SetDeviceGammaRamp_f(maindc, orig_ramps);
1551 		}
1552 		if (modestate == MS_FULLDIB)
1553 		{
1554 			IN_DeactivateMouse ();
1555 			IN_ShowMouse ();
1556 			if (vid_canalttab)
1557 			{
1558 				ChangeDisplaySettings (NULL, 0);
1559 				vid_wassuspended = true;
1560 			}
1561 		}
1562 		else if (modestate == MS_WINDOWED && _enable_mouse.integer)
1563 		{
1564 			IN_DeactivateMouse ();
1565 			IN_ShowMouse ();
1566 		}
1567 	}
1568 }
1569 
1570 
1571 static int	MWheelAccumulator;
1572 static UINT	uMSG_MOUSEWHEEL = 0;
1573 extern cvar_t	mwheelthreshold;
1574 
1575 /* main window procedure */
MainWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1576 static LRESULT WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1577 {
1578 	LRESULT	ret = 0;
1579 	int	fActive, fMinimized, temp;
1580 
1581 	if (uMSG_MOUSEWHEEL && uMsg == uMSG_MOUSEWHEEL)
1582 	{
1583 		/* Win95/WinNT-3.51 code using MSH_MOUSEWHEEL, see:
1584 		 * http://msdn.microsoft.com/en-us/library/ms645617.aspx */
1585 		if (mwheelthreshold.integer >= 1)
1586 		{
1587 			MWheelAccumulator += (int) wParam;
1588 			while (MWheelAccumulator >= mwheelthreshold.integer)
1589 			{
1590 				Key_Event(K_MWHEELUP, true);
1591 				Key_Event(K_MWHEELUP, false);
1592 				MWheelAccumulator -= mwheelthreshold.integer;
1593 			}
1594 			while (MWheelAccumulator <= -mwheelthreshold.integer)
1595 			{
1596 				Key_Event(K_MWHEELDOWN, true);
1597 				Key_Event(K_MWHEELDOWN, false);
1598 				MWheelAccumulator += mwheelthreshold.integer;
1599 			}
1600 		}
1601 		return DefWindowProc (hWnd, uMsg, wParam, lParam);
1602 	}
1603 
1604 	switch (uMsg)
1605 	{
1606 	case WM_ERASEBKGND:
1607 		return 1;
1608 
1609 	case WM_KILLFOCUS:
1610 		if (modestate == MS_FULLDIB)
1611 			ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
1612 		break;
1613 
1614 	case WM_CREATE:
1615 		if (Win95)
1616 		{
1617 			uMSG_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG");
1618 			if (!uMSG_MOUSEWHEEL)
1619 				Con_SafePrintf ("couldn't register mousewheel\n");
1620 		}
1621 		break;
1622 
1623 	case WM_MOVE:
1624 		// ignore when fullscreen
1625 		if (modestate == MS_FULLDIB)
1626 			break;
1627 		window_x = (short) LOWORD(lParam);
1628 		window_y = (short) HIWORD(lParam);
1629 		VID_UpdateWindowStatus ();
1630 		break;
1631 
1632 	case WM_SIZE:
1633 		break;
1634 
1635 	case WM_SYSCHAR:
1636 		// keep Alt-Space from happening
1637 		break;
1638 
1639 	case WM_ACTIVATE:
1640 		fActive = LOWORD(wParam);
1641 		fMinimized = (BOOL) HIWORD(wParam);
1642 		AppActivate(!(fActive == WA_INACTIVE), fMinimized);
1643 
1644 		// fix the leftover Alt from any Alt-Tab or the like that switched us away
1645 		ClearAllStates ();
1646 
1647 		break;
1648 
1649 	case WM_KEYDOWN:
1650 	case WM_SYSKEYDOWN:
1651 		Key_Event (MapKey(lParam), true);
1652 		break;
1653 
1654 	case WM_KEYUP:
1655 	case WM_SYSKEYUP:
1656 		Key_Event (MapKey(lParam), false);
1657 		break;
1658 
1659 	// this is complicated because Win32 seems to pack multiple mouse
1660 	// events into one update sometimes, so we always check all states
1661 	// and look for events
1662 	case WM_LBUTTONDOWN:
1663 	case WM_LBUTTONUP:
1664 	case WM_RBUTTONDOWN:
1665 	case WM_RBUTTONUP:
1666 	case WM_MBUTTONDOWN:
1667 	case WM_MBUTTONUP:
1668 	case WM_XBUTTONDOWN:
1669 	case WM_XBUTTONUP:
1670 	case WM_MOUSEMOVE:
1671 		temp = 0;
1672 
1673 		if (wParam & MK_LBUTTON)
1674 			temp |= 1;
1675 
1676 		if (wParam & MK_RBUTTON)
1677 			temp |= 2;
1678 
1679 		if (wParam & MK_MBUTTON)
1680 			temp |= 4;
1681 
1682 		// intellimouse explorer
1683 		if (wParam & MK_XBUTTON1)
1684 			temp |= 8;
1685 
1686 		if (wParam & MK_XBUTTON2)
1687 			temp |= 16;
1688 
1689 		IN_MouseEvent (temp);
1690 
1691 		break;
1692 
1693 	case WM_MOUSEWHEEL:
1694 		if ((short) HIWORD(wParam) > 0)
1695 		{
1696 			Key_Event(K_MWHEELUP, true);
1697 			Key_Event(K_MWHEELUP, false);
1698 		}
1699 		else
1700 		{
1701 			Key_Event(K_MWHEELDOWN, true);
1702 			Key_Event(K_MWHEELDOWN, false);
1703 		}
1704 		return 0;
1705 
1706 	case WM_CLOSE:
1707 		if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
1708 					MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
1709 		{
1710 			Sys_Quit ();
1711 		}
1712 		break;
1713 
1714 	case WM_DESTROY:
1715 	//	PostQuitMessage (0);
1716 		break;
1717 
1718 	case MM_MCINOTIFY:
1719 #if !defined(_NO_CDAUDIO)
1720 		ret = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
1721 #endif	/* ! _NO_CDAUDIO */
1722 		break;
1723 
1724 	default:
1725 		/* pass all unhandled messages to DefWindowProc */
1726 		ret = DefWindowProc (hWnd, uMsg, wParam, lParam);
1727 		break;
1728 	}
1729 
1730 	/* return 1 if handled message, 0 if not */
1731 	return ret;
1732 }
1733 
1734 
1735 /*
1736 =================
1737 VID_NumModes
1738 =================
1739 */
VID_NumModes(void)1740 static int VID_NumModes (void)
1741 {
1742 	return *nummodes;
1743 }
1744 
1745 
1746 /*
1747 =================
1748 VID_GetModePtr
1749 =================
1750 */
VID_GetModePtr(int modenum)1751 static vmode_t *VID_GetModePtr (int modenum)
1752 {
1753 	if ((modenum >= 0) && (modenum < *nummodes))
1754 		return &modelist[modenum];
1755 	else
1756 		return &badmode;
1757 }
1758 
1759 
1760 /*
1761 =================
1762 VID_GetModeDescription
1763 =================
1764 */
VID_GetModeDescription(int mode)1765 static const char *VID_GetModeDescription (int mode)
1766 {
1767 	const char	*pinfo;
1768 	vmode_t		*pv;
1769 
1770 	if ((mode < 0) || (mode >= *nummodes))
1771 		return NULL;
1772 
1773 	pv = VID_GetModePtr (mode);
1774 	pinfo = pv->modedesc;
1775 
1776 	return pinfo;
1777 }
1778 
1779 
1780 // KJB: Added this to return the mode driver name in description for console
1781 
VID_GetExtModeDescription(int mode)1782 static const char *VID_GetExtModeDescription (int mode)
1783 {
1784 	static char	pinfo[100];
1785 	vmode_t		*pv;
1786 
1787 	if ((mode < 0) || (mode >= *nummodes))
1788 		return NULL;
1789 
1790 	pv = VID_GetModePtr (mode);
1791 	if (modelist[mode].type == MS_FULLDIB)
1792 	{
1793 		q_snprintf(pinfo, sizeof(pinfo), "%s fullscreen", pv->modedesc);
1794 	}
1795 	else
1796 	{
1797 		if (modestate == MS_WINDOWED)
1798 			q_snprintf(pinfo, sizeof(pinfo), "%s windowed", pv->modedesc);
1799 		else
1800 			q_snprintf(pinfo, sizeof(pinfo), "windowed");
1801 	}
1802 
1803 	return pinfo;
1804 }
1805 
1806 
1807 /*
1808 =================
1809 VID_DescribeCurrentMode_f
1810 =================
1811 */
VID_DescribeCurrentMode_f(void)1812 static void VID_DescribeCurrentMode_f (void)
1813 {
1814 	Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum));
1815 }
1816 
1817 
1818 /*
1819 =================
1820 VID_NumModes_f
1821 =================
1822 */
VID_NumModes_f(void)1823 static void VID_NumModes_f (void)
1824 {
1825 	if (*nummodes == 1)
1826 		Con_Printf ("1 video mode is available\n");
1827 	else
1828 		Con_Printf ("%d video modes are available\n", *nummodes);
1829 }
1830 
1831 
1832 /*
1833 =================
1834 VID_DescribeMode_f
1835 =================
1836 */
VID_DescribeMode_f(void)1837 static void VID_DescribeMode_f (void)
1838 {
1839 	int	modenum;
1840 
1841 	modenum = atoi (Cmd_Argv(1));
1842 
1843 	Con_Printf ("%s\n", VID_GetExtModeDescription (modenum));
1844 }
1845 
1846 /*
1847 =================
1848 VID_DescribeModes_f
1849 =================
1850 */
VID_DescribeModes_f(void)1851 static void VID_DescribeModes_f (void)
1852 {
1853 	int	i, lnummodes;
1854 	const char	*pinfo;
1855 	vmode_t	*pv;
1856 
1857 	lnummodes = VID_NumModes ();
1858 
1859 	for (i = 0; i < lnummodes; i++)
1860 	{
1861 		pv = VID_GetModePtr (i);
1862 		pinfo = VID_GetExtModeDescription (i);
1863 		Con_Printf ("%2d: %s\n", i, pinfo);
1864 	}
1865 }
1866 
1867 
VID_RegisterWndClass(HINSTANCE hInstance)1868 static void VID_RegisterWndClass (HINSTANCE hInstance)
1869 {
1870 	WNDCLASS	wc;
1871 
1872 	wc.style		= CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
1873 	wc.lpfnWndProc		= MainWndProc;
1874 	wc.cbClsExtra		= 0;
1875 	wc.cbWndExtra		= 0;
1876 	wc.hInstance		= hInstance;
1877 	wc.hIcon		= NULL;
1878 	wc.hCursor		= LoadCursor (NULL, IDC_ARROW);
1879 	wc.hbrBackground	= NULL;
1880 	wc.lpszMenuName		= NULL;
1881 	wc.lpszClassName	= WM_CLASSNAME;
1882 
1883 	if (!RegisterClass(&wc))
1884 		Sys_Error ("Couldn't register main window class");
1885 
1886 	classregistered = true;
1887 }
1888 
VID_InitDIB(HINSTANCE hInstance)1889 static void VID_InitDIB (HINSTANCE hInstance)
1890 {
1891 	int		i;
1892 	HDC	tempDC;
1893 
1894 	// get desktop settings, hope that the user don't do a silly
1895 	// thing like going back to desktop and changing its settings
1896 	//vid_deskwidth = GetSystemMetrics (SM_CXSCREEN);
1897 	//vid_deskheight = GetSystemMetrics (SM_CXSCREEN);
1898 	tempDC = GetDC (GetDesktopWindow());
1899 	vid_deskwidth = GetDeviceCaps (tempDC, HORZRES);
1900 	vid_deskheight = GetDeviceCaps(tempDC, VERTRES);
1901 	vid_deskbpp = GetDeviceCaps (tempDC, BITSPIXEL);
1902 	ReleaseDC (GetDesktopWindow(), tempDC);
1903 
1904 	// refuse to run if vid_deskbpp < 15
1905 	if (vid_deskbpp < 15)
1906 		Sys_Error ("Desktop color depth too low\n"
1907 			   "Make sure you are running at 16 bpp or better");
1908 
1909 	/* Register the frame class */
1910 	VID_RegisterWndClass(hInstance);
1911 
1912 	// initialize standart windowed modes list
1913 	num_wmodes = 0;
1914 
1915 	for (i = 0, num_wmodes = 0; i < (int)MAX_STDMODES; i++)
1916 	{
1917 		if (std_modes[i].width <= vid_deskwidth && std_modes[i].height <= vid_deskheight)
1918 		{
1919 			wmodelist[num_wmodes].type = MS_WINDOWED;
1920 			wmodelist[num_wmodes].width = std_modes[i].width;
1921 			wmodelist[num_wmodes].height = std_modes[i].height;
1922 			q_snprintf (wmodelist[num_wmodes].modedesc, MAX_DESC, "%dx%d",
1923 				 wmodelist[num_wmodes].width, wmodelist[num_wmodes].height);
1924 			wmodelist[num_wmodes].modenum = MODE_WINDOWED;
1925 			wmodelist[num_wmodes].dib = 1;
1926 			wmodelist[num_wmodes].fullscreen = 0;
1927 			wmodelist[num_wmodes].halfscreen = 0;
1928 			wmodelist[num_wmodes].bpp = 0;
1929 			num_wmodes++;
1930 		}
1931 	}
1932 }
1933 
1934 
1935 /*
1936 =================
1937 VID_InitFullDIB
1938 =================
1939 */
VID_InitFullDIB(HINSTANCE hInstance)1940 static void VID_InitFullDIB (HINSTANCE hInstance)
1941 {
1942 	DEVMODE	devmode;
1943 	int	i, modenum, existingmode;
1944 	int	j, bpp, done;
1945 	BOOL	status;
1946 
1947 	num_fmodes = 0;
1948 
1949 	modenum = 0;
1950 
1951 	// enumerate >8 bpp modes
1952 	do
1953 	{
1954 		status = EnumDisplaySettings (NULL, modenum, &devmode);
1955 
1956 		if ((devmode.dmBitsPerPel >= 15) &&
1957 			(devmode.dmPelsWidth <= MAXWIDTH) &&
1958 			(devmode.dmPelsHeight <= MAXHEIGHT) &&
1959 			(num_fmodes < MAX_MODE_LIST))
1960 		{
1961 			devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1962 
1963 			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
1964 								DISP_CHANGE_SUCCESSFUL)
1965 			{
1966 				fmodelist[num_fmodes].type = MS_FULLDIB;
1967 				fmodelist[num_fmodes].width = devmode.dmPelsWidth;
1968 				fmodelist[num_fmodes].height = devmode.dmPelsHeight;
1969 				fmodelist[num_fmodes].modenum = 0;
1970 				fmodelist[num_fmodes].halfscreen = 0;
1971 				fmodelist[num_fmodes].dib = 1;
1972 				fmodelist[num_fmodes].fullscreen = 1;
1973 				fmodelist[num_fmodes].bpp = devmode.dmBitsPerPel;
1974 				q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%dx%dx%d",
1975 						(int)devmode.dmPelsWidth, (int)devmode.dmPelsHeight,
1976 						(int)devmode.dmBitsPerPel);
1977 
1978 			// if the width is more than twice the height, reduce it by half because this
1979 			// is probably a dual-screen monitor
1980 				if (!COM_CheckParm("-noadjustaspect"))
1981 				{
1982 					if (fmodelist[num_fmodes].width > (fmodelist[num_fmodes].height << 1))
1983 					{
1984 						fmodelist[num_fmodes].width >>= 1;
1985 						fmodelist[num_fmodes].halfscreen = 1;
1986 						q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%dx%dx%d",
1987 								 fmodelist[num_fmodes].width,
1988 								 fmodelist[num_fmodes].height,
1989 								 fmodelist[num_fmodes].bpp);
1990 					}
1991 				}
1992 
1993 				for (i = 0, existingmode = 0; i < num_fmodes; i++)
1994 				{
1995 					if ((fmodelist[num_fmodes].width == fmodelist[i].width)   &&
1996 						(fmodelist[num_fmodes].height == fmodelist[i].height) &&
1997 						(fmodelist[num_fmodes].bpp == fmodelist[i].bpp))
1998 					{
1999 						existingmode = 1;
2000 						break;
2001 					}
2002 				}
2003 
2004 				if (!existingmode)
2005 				{
2006 					num_fmodes++;
2007 				}
2008 			}
2009 		}
2010 
2011 		modenum++;
2012 	} while (status);
2013 
2014 	// see if there are any low-res modes that aren't being reported
2015 	bpp = 16;
2016 	done = 0;
2017 
2018 	do
2019 	{
2020 		for (j = 0; (j < NUM_LOWRESMODES) && (num_fmodes < MAX_MODE_LIST); j++)
2021 		{
2022 			devmode.dmBitsPerPel = bpp;
2023 			devmode.dmPelsWidth = std_modes[j].width;
2024 			devmode.dmPelsHeight = std_modes[j].height;
2025 			devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
2026 
2027 			if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) ==
2028 					DISP_CHANGE_SUCCESSFUL)
2029 			{
2030 				fmodelist[num_fmodes].type = MS_FULLDIB;
2031 				fmodelist[num_fmodes].width = devmode.dmPelsWidth;
2032 				fmodelist[num_fmodes].height = devmode.dmPelsHeight;
2033 				fmodelist[num_fmodes].modenum = 0;
2034 				fmodelist[num_fmodes].halfscreen = 0;
2035 				fmodelist[num_fmodes].dib = 1;
2036 				fmodelist[num_fmodes].fullscreen = 1;
2037 				fmodelist[num_fmodes].bpp = devmode.dmBitsPerPel;
2038 				q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%dx%dx%d",
2039 						(int)devmode.dmPelsWidth, (int)devmode.dmPelsHeight,
2040 						(int)devmode.dmBitsPerPel);
2041 
2042 				for (i = 0, existingmode = 0; i < num_fmodes; i++)
2043 				{
2044 					if ((fmodelist[num_fmodes].width == fmodelist[i].width)   &&
2045 						(fmodelist[num_fmodes].height == fmodelist[i].height) &&
2046 						(fmodelist[num_fmodes].bpp == fmodelist[i].bpp))
2047 					{
2048 						existingmode = 1;
2049 						break;
2050 					}
2051 				}
2052 
2053 				if (!existingmode)
2054 				{
2055 					num_fmodes++;
2056 				}
2057 			}
2058 		}
2059 		switch (bpp)
2060 		{
2061 			case 16:
2062 				bpp = 32;
2063 				break;
2064 
2065 			case 32:
2066 #if 0	/* O.S: don't mess with silly 24 bit lowres modes, they may not work correctly */
2067 				bpp = 24;
2068 				break;
2069 
2070 			case 24:
2071 #endif
2072 				done = 1;
2073 				break;
2074 		}
2075 	} while (!done);
2076 
2077 	if (num_fmodes == 0)
2078 		Con_SafePrintf ("No fullscreen DIB modes found\n");
2079 }
2080 
2081 /*
2082 =================
2083 VID_ChangeVideoMode
2084 intended only as a callback for VID_Restart_f
2085 =================
2086 */
VID_ChangeVideoMode(int newmode)2087 static void VID_ChangeVideoMode (int newmode)
2088 {
2089 	int	temp, temp2;
2090 
2091 	// Avoid window updates and alt+tab handling (which sets modes back)
2092 	temp = scr_disabled_for_loading;
2093 	temp2 = vid_canalttab;
2094 	scr_disabled_for_loading = true;
2095 	vid_canalttab = false;
2096 
2097 	// restore gamma
2098 	if (maindc && gammaworks && SetDeviceGammaRamp_f)
2099 		SetDeviceGammaRamp_f(maindc, orig_ramps);
2100 	CDAudio_Pause ();
2101 	BGM_Pause ();
2102 	S_ClearBuffer ();
2103 
2104 	// Unload all textures and reset texture counts
2105 	D_ClearOpenGLTextures(0);
2106 	memset (lightmap_textures, 0, sizeof(lightmap_textures));
2107 
2108 	// reset all opengl function pointers
2109 	GL_ResetFunctions();
2110 
2111 	// Avoid re-registering commands and re-allocating memory
2112 	draw_reinit = true;
2113 
2114 	// temporarily disable input devices
2115 	IN_DeactivateMouse();
2116 
2117 	// Kill device and rendering contexts
2118 	wglMakeCurrent_fp(NULL, NULL);
2119 	if (baseRC)
2120 		wglDeleteContext_fp(baseRC);
2121 	baseRC = NULL;
2122 	if (maindc && mainwindow)
2123 		ReleaseDC(mainwindow, maindc);
2124 	maindc = NULL;
2125 	// Destroy main window and unregister its class
2126 	if (mainwindow)
2127 	{
2128 		ShowWindow(mainwindow, SW_HIDE);
2129 		DestroyWindow(mainwindow);
2130 	}
2131 	if (classregistered)
2132 		UnregisterClass(WM_CLASSNAME, global_hInstance);
2133 	mainwindow = NULL;
2134 	classregistered = false;
2135 
2136 #if 0	/* some setups (Vista) don't like this: */
2137 	/* the dll already loaded at program init
2138 	   is still valid, we aren't changing the
2139 	   opengl library, so no problems...	*/
2140 #ifdef GL_DLSYM
2141 	// reload the opengl library
2142 	GL_CloseLibrary();
2143 	Sleep (100);
2144 	if (!GL_OpenLibrary(gl_library))
2145 		Sys_Error ("Unable to load GL library %s", gl_library);
2146 #endif
2147 #endif /* #if 0 */
2148 
2149 	// Register main window class and create main window
2150 	VID_RegisterWndClass(global_hInstance);
2151 	VID_SetMode(newmode, host_basepal);
2152 
2153 	// Obtain device context and set up pixel format
2154 	maindc = GetDC(mainwindow);
2155 	bSetupPixelFormat(maindc);
2156 
2157 	// Create OpenGL rendering context and make it current
2158 	baseRC = wglCreateContext_fp(maindc);
2159 	if (!baseRC)
2160 		Sys_Error("wglCreateContext failed");
2161 	if (!wglMakeCurrent_fp(maindc, baseRC ))
2162 		Sys_Error("wglMakeCurrent failed");
2163 
2164 	// Reload graphics wad file (Draw_PicFromWad writes glpic_t data (sizes,
2165 	// texnums) right on top of the original pic data, so the pic data will
2166 	// be dirty after gl textures are loaded the first time; we need to load
2167 	// a clean version)
2168 	W_LoadWadFile ("gfx.wad");
2169 	// Initialize extensions and default OpenGL parameters
2170 	GL_Init();
2171 	VID_Init8bitPalette();
2172 
2173 	// Reload pre-map pics, fonts, console, etc
2174 	Draw_Init();
2175 	SCR_Init();
2176 	// R_Init() stuff:
2177 	R_InitParticleTexture();
2178 	R_InitExtraTextures ();
2179 #if defined(H2W)
2180 	R_InitNetgraphTexture();
2181 #endif	/* H2W */
2182 	Sbar_Init();
2183 	vid.recalc_refdef = 1;
2184 
2185 	IN_ReInit ();
2186 	CDAudio_Resume ();
2187 	BGM_Resume ();
2188 
2189 	// Reload model textures and player skins
2190 	Mod_ReloadTextures();
2191 	// rebuild the lightmaps
2192 	GL_BuildLightmaps();
2193 	// finished reloading all images
2194 	draw_reinit = false;
2195 	scr_disabled_for_loading = temp;
2196 	// apply our gamma
2197 	VID_ShiftPalette(NULL);
2198 	vid_canalttab = temp2;
2199 }
2200 
VID_Restart_f(void)2201 static void VID_Restart_f (void)
2202 {
2203 	if (vid_mode.integer < 0 || vid_mode.integer >= *nummodes)
2204 	{
2205 		Con_Printf ("Bad video mode %d\n", vid_mode.integer);
2206 		Cvar_SetValueQuick (&vid_mode, vid_modenum);
2207 		return;
2208 	}
2209 
2210 	Con_Printf ("Re-initializing video:\n");
2211 	VID_ChangeVideoMode (vid_mode.integer);
2212 }
2213 
sort_modes(const void * arg1,const void * arg2)2214 static int sort_modes (const void *arg1, const void *arg2)
2215 {
2216 	const vmode_t *a1, *a2;
2217 	a1 = (vmode_t *) arg1;
2218 	a2 = (vmode_t *) arg2;
2219 
2220 	/* low to high bpp ? */
2221 	if (a1->bpp != a2->bpp)
2222 		return a1->bpp - a2->bpp;
2223 	/* lowres to highres */
2224 	if (a1->width == a2->width)
2225 		return a1->height - a2->height;
2226 	return a1->width - a2->width;
2227 }
2228 
VID_SortModes(void)2229 static void VID_SortModes (void)
2230 {
2231 	int	i, j;
2232 
2233 	if (num_fmodes == 0)
2234 		return;
2235 
2236 	// sort the fullscreen modes list
2237 	if (num_fmodes > 1)
2238 		qsort(fmodelist, num_fmodes, sizeof fmodelist[0], sort_modes);
2239 	// find which bpp values are reported to us
2240 	for (i = 0; i < MAX_NUMBPP; i++)
2241 	{
2242 		bpplist[i][0] = 0;
2243 		bpplist[i][1] = 0;
2244 	}
2245 	bpplist[0][0] = fmodelist[0].bpp;
2246 	bpplist[0][1] = 0;
2247 	for (i = 1, j = 0; i < num_fmodes && j < MAX_NUMBPP; i++)
2248 	{
2249 		if (fmodelist[i-1].bpp != fmodelist[i].bpp)
2250 		{
2251 			bpplist[++j][0] = fmodelist[i].bpp;
2252 			bpplist[j][1] = i;
2253 		}
2254 	}
2255 
2256 	vid_deskmode = -1;
2257 
2258 	// find the desktop mode number. shouldn't fail!
2259 	for (i = 1; i < num_fmodes; i++)
2260 	{
2261 		if ((fmodelist[i].width == vid_deskwidth) &&
2262 			(fmodelist[i].height == vid_deskheight) &&
2263 			(fmodelist[i].bpp == vid_deskbpp))
2264 		{
2265 			vid_deskmode = i;
2266 			break;
2267 		}
2268 	}
2269 	if (vid_deskmode < 0)
2270 		Con_SafePrintf ("WARNING: desktop resolution not found in modelist\n");
2271 }
2272 
2273 
2274 /*
2275 ===================
2276 VID_Init
2277 ===================
2278 */
VID_Init(const unsigned char * palette)2279 void	VID_Init (const unsigned char *palette)
2280 {
2281 	static char fxmesa_env_multitex[32] = "FX_DONT_FAKE_MULTITEX=1";
2282 	static char fxglide_env_nosplash[32] = "FX_GLIDE_NO_SPLASH=1";
2283 	int	i, j, existingmode;
2284 	int	width, height, bpp, findbpp, done;
2285 	HDC	hdc;
2286 	const char	*read_vars[] = {
2287 				"vid_config_fscr",
2288 				"vid_config_gl8bit",
2289 				"vid_config_bpp",
2290 				"vid_config_glx",
2291 				"vid_config_gly",
2292 				"vid_config_consize",
2293 				"gl_texture_NPOT",
2294 				"gl_multitexture",
2295 				"gl_lightmapfmt" };
2296 #define num_readvars	( sizeof(read_vars)/sizeof(read_vars[0]) )
2297 
2298 	Cvar_RegisterVariable (&vid_config_gl8bit);
2299 	Cvar_RegisterVariable (&vid_config_fscr);
2300 	Cvar_RegisterVariable (&vid_config_bpp);
2301 	Cvar_RegisterVariable (&vid_config_gly);
2302 	Cvar_RegisterVariable (&vid_config_glx);
2303 	Cvar_RegisterVariable (&vid_config_consize);
2304 	Cvar_RegisterVariable (&vid_mode);
2305 	Cvar_RegisterVariable (&_enable_mouse);
2306 	Cvar_RegisterVariable (&gl_texture_NPOT);
2307 	Cvar_RegisterVariable (&gl_lightmapfmt);
2308 	Cvar_RegisterVariable (&gl_multitexture);
2309 	// these are for compatibility with the software version
2310 	Cvar_RegisterVariable (&vid_wait);
2311 	Cvar_RegisterVariable (&_vid_default_mode);
2312 	Cvar_RegisterVariable (&_vid_default_mode_win);
2313 	Cvar_RegisterVariable (&vid_config_x);
2314 	Cvar_RegisterVariable (&vid_config_y);
2315 	Cvar_RegisterVariable (&vid_stretch_by_2);
2316 	Cvar_RegisterVariable (&vid_maxpages);
2317 	Cvar_RegisterVariable (&vid_nopageflip);
2318 
2319 	Cmd_AddCommand ("vid_nummodes", VID_NumModes_f);
2320 	Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f);
2321 	Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f);
2322 	Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f);
2323 	Cmd_AddCommand ("vid_restart", VID_Restart_f);
2324 
2325 	VID_InitPalette (palette);
2326 
2327 	// don't let fxMesa cheat multitexturing
2328 	_putenv (fxmesa_env_multitex);
2329 	// disable the 3dfx splash screen.
2330 	_putenv (fxglide_env_nosplash);
2331 
2332 #ifdef GL_DLSYM
2333 	i = COM_CheckParm ("-gllibrary");
2334 	if (i == 0)
2335 		i = COM_CheckParm ("-g");
2336 	if (i && i < com_argc - 1)
2337 		gl_library = com_argv[i+1];
2338 	else
2339 		gl_library = "opengl32.dll";
2340 	if (!GL_OpenLibrary(gl_library))
2341 		Sys_Error ("Unable to load GL library %s", gl_library);
2342 #else
2343 	hInstGL = GetModuleHandle("opengl32.dll");
2344 #endif
2345 
2346 	hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2));
2347 
2348 	VID_InitDIB (global_hInstance);
2349 
2350 	VID_InitFullDIB (global_hInstance);
2351 
2352 	Con_SafePrintf ("Desktop settings: %d x %d x %d\n", vid_deskwidth, vid_deskheight, vid_deskbpp);
2353 
2354 	// sort the modes
2355 	VID_SortModes();
2356 	// make sure our vid_config_bpp default is supported by the OS
2357 	// (we have a findbpp code below, but let's be on the safe side..)
2358 	for (i = 0; i < MAX_NUMBPP; i++)
2359 	{
2360 		if (!bpplist[i][0])
2361 			break;
2362 		if (vid_config_bpp.integer == bpplist[i][0])
2363 			break; // OK.
2364 	}
2365 	if (i == MAX_NUMBPP || vid_config_bpp.integer != bpplist[i][0]) // not OK
2366 		Cvar_SetValueQuick(&vid_config_bpp, bpplist[0][0]);
2367 
2368 	// perform an early read of config.cfg
2369 	CFG_ReadCvars (read_vars, num_readvars);
2370 
2371 	width = vid_config_glx.integer;
2372 	height = vid_config_gly.integer;
2373 
2374 	if (COM_CheckParm("-window") || COM_CheckParm("-w"))
2375 	{
2376 		Cvar_SetQuick (&vid_config_fscr, "0");
2377 	}
2378 	else if (COM_CheckParm("-fullscreen") || COM_CheckParm("-f"))
2379 	{
2380 		Cvar_SetQuick (&vid_config_fscr, "1");
2381 	}
2382 
2383 	if (vid_config_consize.integer != width)
2384 		vid_conscale = true;
2385 
2386 	if (!vid_config_fscr.integer)
2387 	{
2388 		hdc = GetDC (NULL);
2389 		if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
2390 		{
2391 			Sys_Error ("Can't run in non-RGB mode");
2392 		}
2393 		ReleaseDC (NULL, hdc);
2394 
2395 		modelist = wmodelist;
2396 		nummodes = &num_wmodes;
2397 		vid_default = RES_640X480;
2398 
2399 		// start parsing any dimension request from user
2400 		i = COM_CheckParm("-width");
2401 		if (i && i < com_argc-1)
2402 		{
2403 			j = atoi(com_argv[i+1]);
2404 			// don't allow requests larger than desktop
2405 			if (j <= vid_deskwidth && j >= 320)
2406 			{
2407 				width = j;
2408 				height = width * 3 / 4;
2409 				i = COM_CheckParm("-height");
2410 				if (i && i < com_argc-1)
2411 				{
2412 					j = atoi(com_argv[i+1]);
2413 					if (j <= vid_deskheight && j >= 240)
2414 					{
2415 						height= j;
2416 					}
2417 				}
2418 			}
2419 		}
2420 		// end of parsing user commandline
2421 
2422 		wmodelist[num_wmodes].width = width;
2423 		wmodelist[num_wmodes].height = height;
2424 		wmodelist[num_wmodes].type = MS_WINDOWED;
2425 		q_snprintf (wmodelist[num_wmodes].modedesc, MAX_DESC, "%dx%d",
2426 			 wmodelist[num_wmodes].width, wmodelist[num_wmodes].height);
2427 		wmodelist[num_wmodes].modenum = MODE_WINDOWED;
2428 		wmodelist[num_wmodes].dib = 1;
2429 		wmodelist[num_wmodes].fullscreen = 0;
2430 		wmodelist[num_wmodes].halfscreen = 0;
2431 		wmodelist[num_wmodes].bpp = 0;
2432 
2433 		for (i = 0, existingmode = 0; i < num_wmodes; i++)
2434 		{
2435 			if ((wmodelist[num_wmodes].width == wmodelist[i].width) &&
2436 				(wmodelist[num_wmodes].height == wmodelist[i].height))
2437 			{
2438 				existingmode = 1;
2439 				vid_default = i;
2440 				break;
2441 			}
2442 		}
2443 
2444 		if (!existingmode)
2445 		{
2446 			q_strlcat (wmodelist[num_wmodes].modedesc, " (user mode)", MAX_DESC);
2447 			vid_default = num_wmodes;
2448 			num_wmodes++;
2449 		}
2450 
2451 	}
2452 	else	// fullscreen, default
2453 	{
2454 		if (num_fmodes == 0)
2455 		{
2456 			Sys_Error ("No RGB fullscreen modes available");
2457 		}
2458 
2459 		modelist = fmodelist;
2460 		nummodes = &num_fmodes;
2461 		vid_default = -1;
2462 
2463 		findbpp = 1;
2464 		bpp = vid_config_bpp.integer;
2465 		if (Win95old)
2466 		{	// don't bother with multiple bpp values on
2467 			// windows versions older than win95-osr2.
2468 			// in fact, should we stop supporting it?
2469 			bpp = vid_deskbpp;
2470 			findbpp = 0;
2471 		}
2472 
2473 		if (COM_CheckParm("-current"))
2474 		{	// user wants fullscreen and
2475 			// with desktop dimensions
2476 			if (vid_deskmode >= 0)
2477 			{
2478 				q_strlcat (modelist[vid_deskmode].modedesc, " (desktop)", MAX_DESC);
2479 				vid_default = vid_deskmode;
2480 			}
2481 			else
2482 			{
2483 				Con_SafePrintf ("WARNING: desktop mode not available for the -current switch\n");
2484 			}
2485 		}
2486 		else
2487 		{
2488 			// start parsing any dimension/bpp request from user
2489 			i = COM_CheckParm("-width");
2490 			if (i && i < com_argc-1)
2491 			{
2492 				width = atoi(com_argv[i+1]);
2493 				if (width < 320)
2494 					width = 320;
2495 				height = 3 * width / 4;
2496 				i = COM_CheckParm("-height");
2497 				if (i && i < com_argc-1)
2498 				{
2499 					height = atoi(com_argv[i+1]);
2500 					if (height < 240)
2501 						height = 240;
2502 				}
2503 			}
2504 
2505 			i = COM_CheckParm("-bpp");
2506 			if (i && i < com_argc-1 && !Win95old)
2507 			{
2508 				bpp = atoi(com_argv[i+1]);
2509 				findbpp = 0;
2510 			}
2511 
2512 			// if they want to force it, add the specified mode to the list
2513 			if (COM_CheckParm("-force"))
2514 			{
2515 				fmodelist[num_fmodes].type = MS_FULLDIB;
2516 				fmodelist[num_fmodes].width = width;
2517 				fmodelist[num_fmodes].height = height;
2518 				fmodelist[num_fmodes].modenum = 0;
2519 				fmodelist[num_fmodes].halfscreen = 0;
2520 				fmodelist[num_fmodes].dib = 1;
2521 				fmodelist[num_fmodes].fullscreen = 1;
2522 				fmodelist[num_fmodes].bpp = bpp;
2523 				q_snprintf (fmodelist[num_fmodes].modedesc, MAX_DESC, "%dx%dx%d",
2524 						fmodelist[num_fmodes].width, fmodelist[num_fmodes].height,
2525 						fmodelist[num_fmodes].bpp);
2526 
2527 				for (i = 0, existingmode = 0; i < num_fmodes; i++)
2528 				{
2529 					if ((fmodelist[num_fmodes].width == fmodelist[i].width)   &&
2530 						(fmodelist[num_fmodes].height == fmodelist[i].height) &&
2531 						(fmodelist[num_fmodes].bpp == modelist[i].bpp))
2532 					{
2533 						existingmode = 1;
2534 						break;
2535 					}
2536 				}
2537 
2538 				if (!existingmode)
2539 				{
2540 					q_strlcat (fmodelist[num_fmodes].modedesc, " (user mode)", MAX_DESC);
2541 					num_fmodes++;
2542 					// re-sort the modes
2543 					VID_SortModes();
2544 					if (findbpp)
2545 						bpp = bpplist[0][0];
2546 				}
2547 			}
2548 
2549 			if (vid_deskmode >= 0)
2550 				q_strlcat (fmodelist[vid_deskmode].modedesc, " (desktop)", MAX_DESC);
2551 
2552 			j = done = 0;
2553 
2554 			do
2555 			{
2556 				for (i = 0; i < *nummodes; i++)
2557 				{
2558 					if ((modelist[i].width == width) &&
2559 						(modelist[i].height == height) &&
2560 						(modelist[i].bpp == bpp))
2561 					{
2562 						vid_default = i;
2563 						done = 1;
2564 						break;
2565 					}
2566 				}
2567 
2568 				if (!done)
2569 				{
2570 					if (findbpp)
2571 					{
2572 						if (bpp == bpplist[j][0])
2573 							j++;
2574 						if (j >= MAX_NUMBPP || !bpplist[j][0])
2575 							done = 1;
2576 						if (!done)
2577 							bpp = bpplist[j][0];
2578 						j++;
2579 					}
2580 					else
2581 					{
2582 						done = 1;
2583 					}
2584 				}
2585 			} while (!done);
2586 
2587 			if (vid_default < 0)
2588 			{
2589 				Sys_Error ("Specified video mode not available:\n\n"
2590 					   "If you used -width,-height or -bpp commandline arguments,\n"
2591 					   "try changing their values. If your config.cfg has bad or stale\n"
2592 					   "video options, try changing them, or delete your config.cfg\n"
2593 					   "altogether and try again.");
2594 			}
2595 		}
2596 	}	// end of fullscreen parsing
2597 
2598 	if (!vid_conscale)
2599 		Cvar_SetValueQuick (&vid_config_consize, width);
2600 
2601 	// This will display a bigger hud and readable fonts at high
2602 	// resolutions. The fonts will be somewhat distorted, though
2603 	i = COM_CheckParm("-conwidth");
2604 	if (i != 0 && i < com_argc-1)
2605 		i = atoi(com_argv[i + 1]);
2606 	else	i = vid_config_consize.integer;
2607 	if (i < MIN_WIDTH)	i = MIN_WIDTH;
2608 	else if (i > width)	i = width;
2609 	Cvar_SetValueQuick(&vid_config_consize, i);
2610 	if (vid_config_consize.integer != width)
2611 		vid_conscale = true;
2612 
2613 	vid_initialized = true;
2614 
2615 	vid.maxwarpwidth = WARP_WIDTH;
2616 	vid.maxwarpheight = WARP_HEIGHT;
2617 	vid.colormap = host_colormap;
2618 	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
2619 
2620 #if !defined(NO_SPLASHES)
2621 	DestroyWindow (hwnd_dialog);
2622 #endif
2623 
2624 	if (COM_CheckParm("-paltex"))
2625 		Cvar_SetQuick (&vid_config_gl8bit, "1");
2626 
2627 	j = scr_disabled_for_loading;
2628 	scr_disabled_for_loading = true;
2629 
2630 	Cvar_SetValueQuick (&vid_mode, vid_default);
2631 	VID_SetMode (vid_default, palette);
2632 
2633 	maindc = GetDC(mainwindow);
2634 	bSetupPixelFormat(maindc);
2635 
2636 	baseRC = wglCreateContext_fp( maindc );
2637 	if (!baseRC)
2638 		Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window.");
2639 	if (!wglMakeCurrent_fp( maindc, baseRC ))
2640 		Sys_Error ("wglMakeCurrent failed");
2641 
2642 	GL_SetupLightmapFmt();
2643 	GL_Init ();
2644 	VID_Init8bitPalette();
2645 
2646 	// lock the early-read cvars until Host_Init is finished
2647 	for (i = 0; i < (int)num_readvars; i++)
2648 		Cvar_LockVar (read_vars[i]);
2649 
2650 	scr_disabled_for_loading = j;
2651 	vid.recalc_refdef = 1;
2652 
2653 	vid_menudrawfn = VID_MenuDraw;
2654 	vid_menukeyfn = VID_MenuKey;
2655 
2656 	q_strlcpy (badmode.modedesc,"Bad mode", MAX_DESC);
2657 	vid_canalttab = true;
2658 
2659 //	if (COM_CheckParm("-fullsbar"))
2660 //		fullsbardraw = true;
2661 }
2662 
2663 
VID_Shutdown(void)2664 void	VID_Shutdown (void)
2665 {
2666 	HGLRC	hRC;
2667 	HDC	hDC;
2668 
2669 	if (vid_initialized)
2670 	{
2671 		vid_canalttab = false;
2672 		hRC = wglGetCurrentContext_fp();
2673 		hDC = wglGetCurrentDC_fp();
2674 
2675 		if (maindc && gammaworks && SetDeviceGammaRamp_f)
2676 			SetDeviceGammaRamp_f(maindc, orig_ramps);
2677 
2678 		wglMakeCurrent_fp(NULL, NULL);
2679 
2680 		if (hRC)
2681 			wglDeleteContext_fp(hRC);
2682 
2683 		if (hDC && mainwindow)
2684 			ReleaseDC(mainwindow, hDC);
2685 
2686 		if (modestate == MS_FULLDIB)
2687 			ChangeDisplaySettings (NULL, 0);
2688 
2689 		if (maindc && mainwindow)
2690 			ReleaseDC (mainwindow, maindc);
2691 		maindc = NULL;
2692 
2693 		AppActivate(false, false);
2694 		if (mainwindow)
2695 		{
2696 			ShowWindow(mainwindow, SW_HIDE);
2697 			DestroyWindow(mainwindow);
2698 		}
2699 		if (classregistered)
2700 			UnregisterClass(WM_CLASSNAME, global_hInstance);
2701 		mainwindow = NULL;
2702 		classregistered = false;
2703 #ifdef GL_DLSYM
2704 		GL_CloseLibrary();
2705 #endif
2706 	}
2707 }
2708 
2709 
VID_ToggleFullscreen(void)2710 void VID_ToggleFullscreen (void)
2711 {
2712 }
2713 
2714 
2715 #ifndef H2W /* unused in hexenworld */
D_ShowLoadingSize(void)2716 void D_ShowLoadingSize (void)
2717 {
2718 #if defined(DRAW_PROGRESSBARS)
2719 	int cur_perc;
2720 	static int prev_perc;
2721 
2722 	if (!vid_initialized)
2723 		return;
2724 
2725 	cur_perc = loading_stage * 100;
2726 	if (total_loading_size)
2727 		cur_perc += current_loading_size * 100 / total_loading_size;
2728 	if (cur_perc == prev_perc)
2729 		return;
2730 	prev_perc = cur_perc;
2731 
2732 	glDrawBuffer_fp (GL_FRONT);
2733 
2734 	SCR_DrawLoading();
2735 
2736 	glFlush_fp();
2737 
2738 	glDrawBuffer_fp (GL_BACK);
2739 #endif	/* DRAW_PROGRESSBARS */
2740 }
2741 #endif
2742 
2743 
2744 //========================================================
2745 // Video menu stuff
2746 //========================================================
2747 
2748 static int	vid_menunum;
2749 static int	vid_cursor;
2750 static vmode_t	*vid_menulist;	// this changes when vid_menu_fs changes
2751 static int	vid_menubpp;	// if this changes, vid_menunum already changes
2752 static qboolean	vid_menu_fs;
2753 static qboolean	want_fstoggle, need_apply;
2754 static qboolean	vid_menu_firsttime = true;
2755 
2756 enum {
2757 	VID_FULLSCREEN,
2758 	VID_RESOLUTION,
2759 	VID_BPP,
2760 	VID_MULTITEXTURE,
2761 	VID_NPOT,
2762 	VID_PALTEX,
2763 	VID_BLANKLINE,	// spacer line
2764 	VID_RESET,
2765 	VID_APPLY,
2766 	VID_ITEMS
2767 };
2768 
2769 
M_DrawYesNo(int x,int y,int on,int white)2770 static void M_DrawYesNo (int x, int y, int on, int white)
2771 {
2772 	if (on)
2773 	{
2774 		if (white)
2775 			M_PrintWhite (x, y, "yes");
2776 		else
2777 			M_Print (x, y, "yes");
2778 	}
2779 	else
2780 	{
2781 		if (white)
2782 			M_PrintWhite (x, y, "no");
2783 		else
2784 			M_Print (x, y, "no");
2785 	}
2786 }
2787 
2788 /*
2789 ================
2790 VID_MenuDraw
2791 ================
2792 */
VID_MenuDraw(void)2793 static void VID_MenuDraw (void)
2794 {
2795 	ScrollTitle("gfx/menu/title7.lmp");
2796 
2797 	if (vid_menu_firsttime)
2798 	{	// settings for entering the menu first time
2799 		vid_menunum = vid_modenum;
2800 		vid_menubpp = modelist[vid_modenum].bpp;
2801 		vid_menu_fs = (modestate != MS_WINDOWED);
2802 		vid_menulist = (modestate == MS_WINDOWED) ? wmodelist : fmodelist;
2803 		vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2804 		vid_menu_firsttime = false;
2805 	}
2806 
2807 	want_fstoggle = ( ((modestate == MS_WINDOWED) && vid_menu_fs) || ((modestate != MS_WINDOWED) && !vid_menu_fs) );
2808 
2809 	need_apply = (vid_menunum != vid_modenum) || want_fstoggle ||
2810 			(have_mtex && (gl_mtexable != !!gl_multitexture.integer)) ||
2811 			(have_NPOT && (gl_tex_NPOT != !!gl_texture_NPOT.integer)) ||
2812 			(have8bit && (is8bit != !!vid_config_gl8bit.integer));
2813 
2814 	M_Print (76, 92 + 8*VID_FULLSCREEN, "Fullscreen: ");
2815 	M_DrawYesNo (76+12*8, 92 + 8*VID_FULLSCREEN, vid_menu_fs, !want_fstoggle);
2816 
2817 	M_Print (76, 92 + 8*VID_RESOLUTION, "Resolution: ");
2818 	if (vid_menunum == vid_modenum)
2819 		M_PrintWhite (76+12*8, 92 + 8*VID_RESOLUTION, vid_menulist[vid_menunum].modedesc);
2820 	else
2821 		M_Print (76+12*8, 92 + 8*VID_RESOLUTION, vid_menulist[vid_menunum].modedesc);
2822 
2823 	if (vid_menu_fs && num_fmodes && !Win95old)
2824 	{
2825 		M_Print (76, 92 + 8*VID_BPP, "Color BPP : ");
2826 		if (vid_menubpp == modelist[vid_modenum].bpp)
2827 			M_PrintWhite (76+12*8, 92 + 8*VID_BPP, va("%d",vid_menubpp));
2828 		else
2829 			M_Print (76+12*8, 92 + 8*VID_BPP, va("%d",vid_menubpp));
2830 	}
2831 
2832 	M_Print (76, 92 + 8*VID_MULTITEXTURE, "Multitexturing:");
2833 	if (have_mtex)
2834 		M_DrawYesNo (76+16*8, 92 + 8*VID_MULTITEXTURE, gl_multitexture.integer, (gl_mtexable == !!gl_multitexture.integer));
2835 	else
2836 		M_PrintWhite (76+16*8, 92 + 8*VID_MULTITEXTURE, "Not found");
2837 
2838 	M_Print (76, 92 + 8*VID_NPOT, "NPOT textures :");
2839 	if (have_NPOT)
2840 		M_DrawYesNo (76+16*8, 92 + 8*VID_NPOT, gl_texture_NPOT.integer, (gl_tex_NPOT == !!gl_texture_NPOT.integer));
2841 	else
2842 		M_PrintWhite (76+16*8, 92 + 8*VID_NPOT, "Not found");
2843 
2844 	M_Print (76, 92 + 8*VID_PALTEX, "8 bit textures:");
2845 	if (have8bit)
2846 		M_DrawYesNo (76+16*8, 92 + 8*VID_PALTEX, vid_config_gl8bit.integer, (is8bit == !!vid_config_gl8bit.integer));
2847 	else
2848 		M_PrintWhite (76+16*8, 92 + 8*VID_PALTEX, "Not found");
2849 
2850 	if (need_apply)
2851 	{
2852 		M_Print (76, 92 + 8*VID_RESET, "RESET CHANGES");
2853 		M_Print (76, 92 + 8*VID_APPLY, "APPLY CHANGES");
2854 	}
2855 
2856 	M_DrawCharacter (64, 92 + vid_cursor*8, 12+((int)(realtime*4)&1));
2857 }
2858 
find_bppnum(int incr)2859 static int find_bppnum (int incr)
2860 {
2861 	int	j, pos = -1;
2862 
2863 	if (!vid_menu_fs)	// then it doesn't matter
2864 		return 0;
2865 
2866 	for (j = 0; j < MAX_NUMBPP; j++)
2867 	{	// find the pos in the bpplist
2868 		if (vid_menubpp == bpplist[j][0])
2869 		{
2870 			pos = j;
2871 			j = j+incr;
2872 			break;
2873 		}
2874 	}
2875 	if (pos < 0)
2876 		Sys_Error ("bpp unexpectedly not found in list");
2877 	if (incr == 0)
2878 		return pos;
2879 	// find the next available bpp
2880 	while (1)
2881 	{
2882 		if (j >= MAX_NUMBPP)
2883 			j = 0;
2884 		if (j < 0)
2885 			j = MAX_NUMBPP-1;
2886 		if (bpplist[j][0])
2887 			break;
2888 		j = j + incr;
2889 	}
2890 	return j;
2891 }
2892 
match_mode_to_bpp(int bppnum)2893 static int match_mode_to_bpp (int bppnum)
2894 {
2895 	int	k, l;
2896 
2897 	k = bpplist[bppnum][1];
2898 	l = bpplist[bppnum][1] + 1;
2899 	for ( ; l < num_fmodes && fmodelist[l].bpp == vid_menubpp; l++)
2900 	{
2901 		if (fmodelist[vid_menunum].width == fmodelist[l].width &&
2902 		    fmodelist[vid_menunum].height == fmodelist[l].height)
2903 		{
2904 			k = l;
2905 			break;
2906 		}
2907 	}
2908 	return k;
2909 }
2910 
match_windowed_fullscr_modes(void)2911 static int match_windowed_fullscr_modes (void)
2912 {
2913 	int	l;
2914 	vmode_t	*tmplist;
2915 	int	*tmpcount;
2916 
2917 	// choose the new mode
2918 	tmplist = (vid_menu_fs) ? fmodelist : wmodelist;
2919 	tmpcount = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
2920 	for (l = 0; l < *tmpcount; l++)
2921 	{
2922 		if (tmplist[l].width == vid_menulist[vid_menunum].width &&
2923 		    tmplist[l].height == vid_menulist[vid_menunum].height)
2924 		{
2925 			return l;
2926 		}
2927 	}
2928 	return 0;
2929 }
2930 
2931 /*
2932 ================
2933 VID_MenuKey
2934 ================
2935 */
VID_MenuKey(int key)2936 static void VID_MenuKey (int key)
2937 {
2938 	int	i;
2939 	int	*tmpnum;
2940 
2941 	switch (key)
2942 	{
2943 	case K_ESCAPE:
2944 		vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2945 		M_Menu_Options_f ();
2946 		break;
2947 
2948 	case K_UPARROW:
2949 		S_LocalSound ("raven/menu1.wav");
2950 		vid_cursor--;
2951 		if (vid_cursor < 0)
2952 		{
2953 			vid_cursor = (need_apply) ? VID_ITEMS-1 : VID_BLANKLINE-1;
2954 		}
2955 		else if (vid_cursor == VID_BLANKLINE)
2956 		{
2957 			vid_cursor--;
2958 		}
2959 		if (!num_fmodes && vid_cursor == 0)
2960 		{
2961 			vid_cursor = VID_RESOLUTION;
2962 		}
2963 		if ( vid_cursor == VID_BPP && (!vid_menu_fs || !num_fmodes || Win95old ))
2964 		{
2965 			vid_cursor--;
2966 		}
2967 		break;
2968 
2969 	case K_DOWNARROW:
2970 		S_LocalSound ("raven/menu1.wav");
2971 		vid_cursor++;
2972 		if (vid_cursor >= VID_ITEMS)
2973 		{
2974 			vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2975 			break;
2976 		}
2977 		if ( vid_cursor == VID_BPP && (!vid_menu_fs || !num_fmodes || Win95old ))
2978 			vid_cursor++;
2979 		if (vid_cursor >= VID_BLANKLINE)
2980 		{
2981 			if (need_apply)
2982 			{
2983 				if (vid_cursor == VID_BLANKLINE)
2984 					vid_cursor++;
2985 			}
2986 			else
2987 			{
2988 				vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
2989 			}
2990 		}
2991 		break;
2992 
2993 	case K_ENTER:
2994 		switch (vid_cursor)
2995 		{
2996 		case VID_RESET:
2997 			vid_menunum = vid_modenum;
2998 			vid_menubpp = modelist[vid_modenum].bpp;
2999 			vid_menu_fs = (modestate != MS_WINDOWED);
3000 			vid_menulist = (modestate == MS_WINDOWED) ? wmodelist : fmodelist;
3001 			Cvar_SetValueQuick (&vid_config_gl8bit, is8bit);
3002 			vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
3003 			break;
3004 		case VID_APPLY:
3005 			if (need_apply)
3006 			{
3007 				Cvar_SetValueQuick(&vid_mode, vid_menunum);
3008 				modelist = (vid_menu_fs) ? fmodelist : wmodelist;
3009 				nummodes = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
3010 				VID_Restart_f();
3011 			}
3012 			vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION;
3013 			break;
3014 		}
3015 		return;
3016 
3017 	case K_LEFTARROW:
3018 		switch (vid_cursor)
3019 		{
3020 		case VID_FULLSCREEN:
3021 			if (!num_fmodes)
3022 				break;
3023 			vid_menu_fs = !vid_menu_fs;
3024 			vid_menunum = match_windowed_fullscr_modes();
3025 			vid_menulist = (vid_menu_fs) ? fmodelist : wmodelist;
3026 			vid_menubpp = vid_menulist[vid_menunum].bpp;
3027 			break;
3028 		case VID_RESOLUTION:
3029 			S_LocalSound ("raven/menu1.wav");
3030 			vid_menunum--;
3031 			if (vid_menunum < 0 || vid_menubpp != vid_menulist[vid_menunum].bpp)
3032 				vid_menunum++;
3033 			break;
3034 		case VID_BPP:
3035 			i = find_bppnum (-1);
3036 			if (vid_menubpp == bpplist[i][0])
3037 				break;
3038 			vid_menubpp = bpplist[i][0];
3039 			//find a matching video mode for this bpp
3040 			vid_menunum = match_mode_to_bpp(i);
3041 			break;
3042 		case VID_MULTITEXTURE:
3043 			if (have_mtex)
3044 				Cvar_SetQuick (&gl_multitexture, gl_multitexture.integer ? "0" : "1");
3045 			break;
3046 		case VID_NPOT:
3047 			if (have_NPOT)
3048 				Cvar_SetQuick (&gl_texture_NPOT, gl_texture_NPOT.integer ? "0" : "1");
3049 			break;
3050 		case VID_PALTEX:
3051 			if (have8bit)
3052 				Cvar_SetQuick (&vid_config_gl8bit, vid_config_gl8bit.integer ? "0" : "1");
3053 			break;
3054 		}
3055 		return;
3056 
3057 	case K_RIGHTARROW:
3058 		switch (vid_cursor)
3059 		{
3060 		case VID_FULLSCREEN:
3061 			if (!num_fmodes)
3062 				break;
3063 			vid_menu_fs = !vid_menu_fs;
3064 			vid_menunum = match_windowed_fullscr_modes();
3065 			vid_menulist = (vid_menu_fs) ? fmodelist : wmodelist;
3066 			vid_menubpp = vid_menulist[vid_menunum].bpp;
3067 			break;
3068 		case VID_RESOLUTION:
3069 			S_LocalSound ("raven/menu1.wav");
3070 			tmpnum = (vid_menu_fs) ? &num_fmodes : &num_wmodes;
3071 			vid_menunum++;
3072 			if (vid_menunum >= *tmpnum || vid_menubpp != vid_menulist[vid_menunum].bpp)
3073 				vid_menunum--;
3074 			break;
3075 		case VID_BPP:
3076 			i = find_bppnum (1);
3077 			if (vid_menubpp == bpplist[i][0])
3078 				break;
3079 			vid_menubpp = bpplist[i][0];
3080 			//find a matching video mode for this bpp
3081 			vid_menunum = match_mode_to_bpp(i);
3082 			break;
3083 		case VID_MULTITEXTURE:
3084 			if (have_mtex)
3085 				Cvar_SetQuick (&gl_multitexture, gl_multitexture.integer ? "0" : "1");
3086 			break;
3087 		case VID_NPOT:
3088 			if (have_NPOT)
3089 				Cvar_SetQuick (&gl_texture_NPOT, gl_texture_NPOT.integer ? "0" : "1");
3090 			break;
3091 		case VID_PALTEX:
3092 			if (have8bit)
3093 				Cvar_SetQuick (&vid_config_gl8bit, vid_config_gl8bit.integer ? "0" : "1");
3094 			break;
3095 		}
3096 		return;
3097 
3098 	default:
3099 		break;
3100 	}
3101 }
3102 
3103