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