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