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