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