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