Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 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 | // vid_win.c -- Win32 video driver |
||
21 | |||
22 | #include "quakedef.h" |
||
23 | #include "winquake.h" |
||
24 | #include "d_local.h" |
||
25 | #include "resource.h" |
||
26 | |||
27 | #define MAX_MODE_LIST 30 |
||
28 | #define VID_ROW_SIZE 3 |
||
29 | |||
30 | qboolean dibonly; |
||
31 | |||
32 | extern int Minimized; |
||
33 | |||
34 | HWND mainwindow; |
||
35 | |||
36 | HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); |
||
37 | |||
38 | int DIBWidth, DIBHeight; |
||
39 | qboolean DDActive; |
||
40 | RECT WindowRect; |
||
41 | DWORD WindowStyle, ExWindowStyle; |
||
42 | |||
43 | int window_center_x, window_center_y, window_x, window_y, window_width, window_height; |
||
44 | RECT window_rect; |
||
45 | |||
46 | static DEVMODE gdevmode; |
||
47 | static qboolean startwindowed = 0, windowed_mode_set; |
||
48 | static int firstupdate = 1; |
||
49 | static qboolean vid_initialized = false, vid_palettized; |
||
50 | static int lockcount; |
||
51 | static int vid_fulldib_on_focus_mode; |
||
52 | static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set; |
||
53 | static int vid_stretched, windowed_mouse; |
||
54 | static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic; |
||
55 | static HICON hIcon; |
||
56 | |||
57 | viddef_t vid; // global video state |
||
58 | |||
59 | #define MODE_WINDOWED 0 |
||
60 | #define MODE_SETTABLE_WINDOW 2 |
||
61 | #define NO_MODE (MODE_WINDOWED - 1) |
||
62 | #define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) |
||
63 | |||
64 | // Note that 0 is MODE_WINDOWED |
||
65 | cvar_t vid_mode = {"vid_mode","0", false}; |
||
66 | // Note that 0 is MODE_WINDOWED |
||
67 | cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; |
||
68 | // Note that 3 is MODE_FULLSCREEN_DEFAULT |
||
69 | cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; |
||
70 | cvar_t vid_wait = {"vid_wait","0"}; |
||
71 | cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; |
||
72 | cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; |
||
73 | cvar_t vid_config_x = {"vid_config_x","800", true}; |
||
74 | cvar_t vid_config_y = {"vid_config_y","600", true}; |
||
75 | cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; |
||
76 | cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; |
||
77 | cvar_t vid_fullscreen_mode = {"vid_fullscreen_mode","3", true}; |
||
78 | cvar_t vid_windowed_mode = {"vid_windowed_mode","0", true}; |
||
79 | cvar_t block_switch = {"block_switch","0", true}; |
||
80 | cvar_t vid_window_x = {"vid_window_x", "0", true}; |
||
81 | cvar_t vid_window_y = {"vid_window_y", "0", true}; |
||
82 | |||
83 | typedef struct { |
||
84 | int width; |
||
85 | int height; |
||
86 | } lmode_t; |
||
87 | |||
88 | lmode_t lowresmodes[] = { |
||
89 | {320, 200}, |
||
90 | {320, 240}, |
||
91 | {400, 300}, |
||
92 | {512, 384}, |
||
93 | }; |
||
94 | |||
95 | int vid_modenum = NO_MODE; |
||
96 | int vid_testingmode, vid_realmode; |
||
97 | double vid_testendtime; |
||
98 | int vid_default = MODE_WINDOWED; |
||
99 | static int windowed_default; |
||
100 | |||
101 | modestate_t modestate = MS_UNINIT; |
||
102 | |||
103 | static byte *vid_surfcache; |
||
104 | static int vid_surfcachesize; |
||
105 | static int VID_highhunkmark; |
||
106 | |||
107 | unsigned char vid_curpal[256*3]; |
||
108 | |||
109 | unsigned short d_8to16table[256]; |
||
110 | unsigned d_8to24table[256]; |
||
111 | |||
112 | int driver = grDETECT,mode; |
||
113 | bool useWinDirect = true, useDirectDraw = true; |
||
114 | MGLDC *mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL; |
||
115 | |||
116 | typedef struct { |
||
117 | modestate_t type; |
||
118 | int width; |
||
119 | int height; |
||
120 | int modenum; |
||
121 | int mode13; |
||
122 | int stretched; |
||
123 | int dib; |
||
124 | int fullscreen; |
||
125 | int bpp; |
||
126 | int halfscreen; |
||
127 | char modedesc[13]; |
||
128 | } vmode_t; |
||
129 | |||
130 | static vmode_t modelist[MAX_MODE_LIST]; |
||
131 | static int nummodes; |
||
132 | static vmode_t *pcurrentmode; |
||
133 | |||
134 | int aPage; // Current active display page |
||
135 | int vPage; // Current visible display page |
||
136 | int waitVRT = true; // True to wait for retrace on flip |
||
137 | |||
138 | static vmode_t badmode; |
||
139 | |||
140 | static byte backingbuf[48*24]; |
||
141 | |||
142 | void VID_MenuDraw (void); |
||
143 | void VID_MenuKey (int key); |
||
144 | |||
145 | LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); |
||
146 | void AppActivate(BOOL fActive, BOOL minimize); |
||
147 | |||
148 | |||
149 | /* |
||
150 | ================ |
||
151 | VID_RememberWindowPos |
||
152 | ================ |
||
153 | */ |
||
154 | void VID_RememberWindowPos (void) |
||
155 | { |
||
156 | RECT rect; |
||
157 | |||
158 | if (GetWindowRect (mainwindow, &rect)) |
||
159 | { |
||
160 | if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && |
||
161 | (rect.top < GetSystemMetrics (SM_CYSCREEN)) && |
||
162 | (rect.right > 0) && |
||
163 | (rect.bottom > 0)) |
||
164 | { |
||
165 | Cvar_SetValue ("vid_window_x", (float)rect.left); |
||
166 | Cvar_SetValue ("vid_window_y", (float)rect.top); |
||
167 | } |
||
168 | } |
||
169 | } |
||
170 | |||
171 | |||
172 | /* |
||
173 | ================ |
||
174 | VID_CheckWindowXY |
||
175 | ================ |
||
176 | */ |
||
177 | void VID_CheckWindowXY (void) |
||
178 | { |
||
179 | |||
180 | if (((int)vid_window_x.value > (GetSystemMetrics (SM_CXSCREEN) - 160)) || |
||
181 | ((int)vid_window_y.value > (GetSystemMetrics (SM_CYSCREEN) - 120)) || |
||
182 | ((int)vid_window_x.value < 0) || |
||
183 | ((int)vid_window_y.value < 0)) |
||
184 | { |
||
185 | Cvar_SetValue ("vid_window_x", 0.0); |
||
186 | Cvar_SetValue ("vid_window_y", 0.0 ); |
||
187 | } |
||
188 | } |
||
189 | |||
190 | |||
191 | /* |
||
192 | ================ |
||
193 | VID_UpdateWindowStatus |
||
194 | ================ |
||
195 | */ |
||
196 | void VID_UpdateWindowStatus (void) |
||
197 | { |
||
198 | |||
199 | window_rect.left = window_x; |
||
200 | window_rect.top = window_y; |
||
201 | window_rect.right = window_x + window_width; |
||
202 | window_rect.bottom = window_y + window_height; |
||
203 | window_center_x = (window_rect.left + window_rect.right) / 2; |
||
204 | window_center_y = (window_rect.top + window_rect.bottom) / 2; |
||
205 | |||
206 | IN_UpdateClipCursor (); |
||
207 | } |
||
208 | |||
209 | |||
210 | /* |
||
211 | ================ |
||
212 | ClearAllStates |
||
213 | ================ |
||
214 | */ |
||
215 | void ClearAllStates (void) |
||
216 | { |
||
217 | int i; |
||
218 | |||
219 | // send an up event for each key, to make sure the server clears them all |
||
220 | for (i=0 ; i<256 ; i++) |
||
221 | { |
||
222 | Key_Event (i, false); |
||
223 | } |
||
224 | |||
225 | Key_ClearStates (); |
||
226 | IN_ClearStates (); |
||
227 | } |
||
228 | |||
229 | |||
230 | /* |
||
231 | ================ |
||
232 | VID_CheckAdequateMem |
||
233 | ================ |
||
234 | */ |
||
235 | qboolean VID_CheckAdequateMem (int width, int height) |
||
236 | { |
||
237 | int tbuffersize; |
||
238 | |||
239 | tbuffersize = width * height * sizeof (*d_pzbuffer); |
||
240 | |||
241 | tbuffersize += D_SurfaceCacheForRes (width, height); |
||
242 | |||
243 | // see if there's enough memory, allowing for the normal mode 0x13 pixel, |
||
244 | // z, and surface buffers |
||
245 | if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + |
||
246 | 0x10000 * 3) < minimum_memory) |
||
247 | { |
||
248 | return false; // not enough memory for mode |
||
249 | } |
||
250 | |||
251 | return true; |
||
252 | } |
||
253 | |||
254 | |||
255 | /* |
||
256 | ================ |
||
257 | VID_AllocBuffers |
||
258 | ================ |
||
259 | */ |
||
260 | qboolean VID_AllocBuffers (int width, int height) |
||
261 | { |
||
262 | int tsize, tbuffersize; |
||
263 | |||
264 | tbuffersize = width * height * sizeof (*d_pzbuffer); |
||
265 | |||
266 | tsize = D_SurfaceCacheForRes (width, height); |
||
267 | |||
268 | tbuffersize += tsize; |
||
269 | |||
270 | // see if there's enough memory, allowing for the normal mode 0x13 pixel, |
||
271 | // z, and surface buffers |
||
272 | if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 + |
||
273 | 0x10000 * 3) < minimum_memory) |
||
274 | { |
||
275 | Con_SafePrintf ("Not enough memory for video mode\n"); |
||
276 | return false; // not enough memory for mode |
||
277 | } |
||
278 | |||
279 | vid_surfcachesize = tsize; |
||
280 | |||
281 | if (d_pzbuffer) |
||
282 | { |
||
283 | D_FlushCaches (); |
||
284 | Hunk_FreeToHighMark (VID_highhunkmark); |
||
285 | d_pzbuffer = NULL; |
||
286 | } |
||
287 | |||
288 | VID_highhunkmark = Hunk_HighMark (); |
||
289 | |||
290 | d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video"); |
||
291 | |||
292 | vid_surfcache = (byte *)d_pzbuffer + |
||
293 | width * height * sizeof (*d_pzbuffer); |
||
294 | |||
295 | return true; |
||
296 | } |
||
297 | |||
298 | |||
299 | void initFatalError(void) |
||
300 | { |
||
301 | MGL_exit(); |
||
302 | MGL_fatalError(MGL_errorMsg(MGL_result())); |
||
303 | exit(EXIT_FAILURE); |
||
304 | } |
||
305 | |||
306 | |||
307 | int VID_Suspend (MGLDC *dc,m_int flags) |
||
308 | { |
||
309 | |||
310 | if (flags & MGL_DEACTIVATE) |
||
311 | { |
||
312 | // FIXME: this doesn't currently work on NT |
||
313 | if (block_switch.value && !WinNT) |
||
314 | { |
||
315 | return MGL_NO_DEACTIVATE; |
||
316 | } |
||
317 | |||
318 | S_BlockSound (); |
||
319 | S_ClearBuffer (); |
||
320 | |||
321 | IN_RestoreOriginalMouseState (); |
||
322 | CDAudio_Pause (); |
||
323 | |||
324 | // keep WM_PAINT from trying to redraw |
||
325 | in_mode_set = true; |
||
326 | |||
327 | block_drawing = true; // so we don't try to draw while switched away |
||
328 | |||
329 | return MGL_NO_SUSPEND_APP; |
||
330 | } |
||
331 | else if (flags & MGL_REACTIVATE) |
||
332 | { |
||
333 | IN_SetQuakeMouseState (); |
||
334 | // fix the leftover Alt from any Alt-Tab or the like that switched us away |
||
335 | ClearAllStates (); |
||
336 | CDAudio_Resume (); |
||
337 | S_UnblockSound (); |
||
338 | |||
339 | in_mode_set = false; |
||
340 | |||
341 | vid.recalc_refdef = 1; |
||
342 | |||
343 | block_drawing = false; |
||
344 | |||
345 | return MGL_NO_SUSPEND_APP; |
||
346 | } |
||
347 | |||
348 | } |
||
349 | |||
350 | |||
351 | void registerAllDispDrivers(void) |
||
352 | { |
||
353 | /* Event though these driver require WinDirect, we register |
||
354 | * them so that they will still be available even if DirectDraw |
||
355 | * is present and the user has disable the high performance |
||
356 | * WinDirect modes. |
||
357 | */ |
||
358 | MGL_registerDriver(MGL_VGA8NAME,VGA8_driver); |
||
359 | // MGL_registerDriver(MGL_VGAXNAME,VGAX_driver); |
||
360 | |||
361 | /* Register display drivers */ |
||
362 | if (useWinDirect) |
||
363 | { |
||
364 | //we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver); |
||
365 | MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver); |
||
366 | |||
367 | if (!COM_CheckParm ("-novbeaf")) |
||
368 | MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver); |
||
369 | } |
||
370 | |||
371 | if (useDirectDraw) |
||
372 | { |
||
373 | MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver); |
||
374 | } |
||
375 | } |
||
376 | |||
377 | |||
378 | void registerAllMemDrivers(void) |
||
379 | { |
||
380 | /* Register memory context drivers */ |
||
381 | MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver); |
||
382 | } |
||
383 | |||
384 | |||
385 | void VID_InitMGLFull (HINSTANCE hInstance) |
||
386 | { |
||
387 | int i, xRes, yRes, bits, vMode, lowres, curmode, temp; |
||
388 | int lowstretchedres, stretchedmode, lowstretched; |
||
389 | uchar *m; |
||
390 | |||
391 | // FIXME: NT is checked for because MGL currently has a bug that causes it |
||
392 | // to try to use WinDirect modes even on NT |
||
393 | if (COM_CheckParm("-nowindirect") || |
||
394 | COM_CheckParm("-nowd") || |
||
395 | COM_CheckParm("-novesa") || |
||
396 | WinNT) |
||
397 | { |
||
398 | useWinDirect = false; |
||
399 | } |
||
400 | |||
401 | if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd")) |
||
402 | useDirectDraw = false; |
||
403 | |||
404 | // Initialise the MGL |
||
405 | MGL_unregisterAllDrivers(); |
||
406 | registerAllDispDrivers(); |
||
407 | registerAllMemDrivers(); |
||
408 | MGL_detectGraph(&driver,&mode); |
||
409 | m = MGL_availableModes(); |
||
410 | |||
411 | if (m[0] != 0xFF) |
||
412 | { |
||
413 | lowres = lowstretchedres = 99999; |
||
414 | lowstretched = 0; |
||
415 | curmode = 0; |
||
416 | |||
417 | // find the lowest-res mode, or a mode we can stretch up to and get |
||
418 | // lowest-res that way |
||
419 | for (i = 0; m[i] != 0xFF; i++) |
||
420 | { |
||
421 | MGL_modeResolution(m[i], &xRes, &yRes,&bits); |
||
422 | |||
423 | if ((bits == 8) && |
||
424 | (xRes <= MAXWIDTH) && |
||
425 | (yRes <= MAXHEIGHT) && |
||
426 | (curmode < MAX_MODE_LIST)) |
||
427 | { |
||
428 | if (m[i] == grVGA_320x200x256) |
||
429 | is_mode0x13 = true; |
||
430 | |||
431 | if (!COM_CheckParm("-noforcevga")) |
||
432 | { |
||
433 | if (m[i] == grVGA_320x200x256) |
||
434 | { |
||
435 | mode = i; |
||
436 | break; |
||
437 | } |
||
438 | } |
||
439 | |||
440 | if (xRes < lowres) |
||
441 | { |
||
442 | lowres = xRes; |
||
443 | mode = i; |
||
444 | } |
||
445 | |||
446 | if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320)) |
||
447 | { |
||
448 | lowstretchedres = xRes >> 1; |
||
449 | stretchedmode = i; |
||
450 | } |
||
451 | } |
||
452 | |||
453 | curmode++; |
||
454 | } |
||
455 | |||
456 | // if there's a mode we can stretch by 2 up to, thereby effectively getting |
||
457 | // a lower-res mode than the lowest-res real but still at least 320x200, that |
||
458 | // will be our default mode |
||
459 | if (lowstretchedres < lowres) |
||
460 | { |
||
461 | mode = stretchedmode; |
||
462 | lowres = lowstretchedres; |
||
463 | lowstretched = 1; |
||
464 | } |
||
465 | |||
466 | // build the mode list, leaving room for the low-res stretched mode, if any |
||
467 | nummodes++; // leave room for default mode |
||
468 | |||
469 | for (i = 0; m[i] != 0xFF; i++) |
||
470 | { |
||
471 | MGL_modeResolution(m[i], &xRes, &yRes,&bits); |
||
472 | |||
473 | if ((bits == 8) && |
||
474 | (xRes <= MAXWIDTH) && |
||
475 | (yRes <= MAXHEIGHT) && |
||
476 | (nummodes < MAX_MODE_LIST)) |
||
477 | { |
||
478 | if (i == mode) |
||
479 | { |
||
480 | if (lowstretched) |
||
481 | { |
||
482 | stretchedmode = nummodes; |
||
483 | curmode = nummodes++; |
||
484 | } |
||
485 | else |
||
486 | { |
||
487 | curmode = MODE_FULLSCREEN_DEFAULT; |
||
488 | } |
||
489 | } |
||
490 | else |
||
491 | { |
||
492 | curmode = nummodes++; |
||
493 | } |
||
494 | |||
495 | modelist[curmode].type = MS_FULLSCREEN; |
||
496 | modelist[curmode].width = xRes; |
||
497 | modelist[curmode].height = yRes; |
||
498 | sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes); |
||
499 | |||
500 | if (m[i] == grVGA_320x200x256) |
||
501 | modelist[curmode].mode13 = 1; |
||
502 | else |
||
503 | modelist[curmode].mode13 = 0; |
||
504 | |||
505 | modelist[curmode].modenum = m[i]; |
||
506 | modelist[curmode].stretched = 0; |
||
507 | modelist[curmode].dib = 0; |
||
508 | modelist[curmode].fullscreen = 1; |
||
509 | modelist[curmode].halfscreen = 0; |
||
510 | modelist[curmode].bpp = 8; |
||
511 | } |
||
512 | } |
||
513 | |||
514 | if (lowstretched) |
||
515 | { |
||
516 | modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode]; |
||
517 | modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1; |
||
518 | modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1; |
||
519 | modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1; |
||
520 | sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d", |
||
521 | modelist[MODE_FULLSCREEN_DEFAULT].width, |
||
522 | modelist[MODE_FULLSCREEN_DEFAULT].height); |
||
523 | } |
||
524 | |||
525 | vid_default = MODE_FULLSCREEN_DEFAULT; |
||
526 | |||
527 | temp = m[0]; |
||
528 | |||
529 | if (!MGL_init(&driver, &temp, "")) |
||
530 | { |
||
531 | initFatalError(); |
||
532 | } |
||
533 | } |
||
534 | |||
535 | MGL_setSuspendAppCallback(VID_Suspend); |
||
536 | } |
||
537 | |||
538 | |||
539 | MGLDC *createDisplayDC(int forcemem) |
||
540 | /**************************************************************************** |
||
541 | * |
||
542 | * Function: createDisplayDC |
||
543 | * Returns: Pointer to the MGL device context to use for the application |
||
544 | * |
||
545 | * Description: Initialises the MGL and creates an appropriate display |
||
546 | * device context to be used by the GUI. This creates and |
||
547 | * apropriate device context depending on the system being |
||
548 | * compile for, and should be the only place where system |
||
549 | * specific code is required. |
||
550 | * |
||
551 | ****************************************************************************/ |
||
552 | { |
||
553 | MGLDC *dc; |
||
554 | pixel_format_t pf; |
||
555 | int npages; |
||
556 | |||
557 | // Start the specified video mode |
||
558 | if (!MGL_changeDisplayMode(mode)) |
||
559 | initFatalError(); |
||
560 | |||
561 | npages = MGL_availablePages(mode); |
||
562 | |||
563 | if (npages > 3) |
||
564 | npages = 3; |
||
565 | |||
566 | if (!COM_CheckParm ("-notriplebuf")) |
||
567 | { |
||
568 | if (npages > 2) |
||
569 | { |
||
570 | npages = 2; |
||
571 | } |
||
572 | } |
||
573 | |||
574 | if ((dc = MGL_createDisplayDC(npages)) == NULL) |
||
575 | return NULL; |
||
576 | |||
577 | if (!forcemem && (MGL_surfaceAccessType(dc)) == MGL_LINEAR_ACCESS && (dc->mi.maxPage > 0)) |
||
578 | { |
||
579 | MGL_makeCurrentDC(dc); |
||
580 | memdc = NULL; |
||
581 | } |
||
582 | else |
||
583 | { |
||
584 | // Set up for blitting from a memory buffer |
||
585 | memdc = MGL_createMemoryDC(MGL_sizex(dc)+1,MGL_sizey(dc)+1,8,&pf); |
||
586 | MGL_makeCurrentDC(memdc); |
||
587 | } |
||
588 | |||
589 | // Enable page flipping even for even for blitted surfaces |
||
590 | if (forcemem) |
||
591 | { |
||
592 | vid.numpages = 1; |
||
593 | } |
||
594 | else |
||
595 | { |
||
596 | vid.numpages = dc->mi.maxPage + 1; |
||
597 | |||
598 | if (vid.numpages > 1) |
||
599 | { |
||
600 | // Set up for page flipping |
||
601 | MGL_setActivePage(dc, aPage = 1); |
||
602 | MGL_setVisualPage(dc, vPage = 0, false); |
||
603 | } |
||
604 | |||
605 | if (vid.numpages > 3) |
||
606 | vid.numpages = 3; |
||
607 | } |
||
608 | |||
609 | if (vid.numpages == 2) |
||
610 | waitVRT = true; |
||
611 | else |
||
612 | waitVRT = false; |
||
613 | |||
614 | return dc; |
||
615 | } |
||
616 | |||
617 | |||
618 | void VID_InitMGLDIB (HINSTANCE hInstance) |
||
619 | { |
||
620 | WNDCLASS wc; |
||
621 | HDC hdc; |
||
622 | int i; |
||
623 | |||
624 | hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); |
||
625 | |||
626 | /* Register the frame class */ |
||
627 | wc.style = 0; |
||
628 | wc.lpfnWndProc = (WNDPROC)MainWndProc; |
||
629 | wc.cbClsExtra = 0; |
||
630 | wc.cbWndExtra = 0; |
||
631 | wc.hInstance = hInstance; |
||
632 | wc.hIcon = 0; |
||
633 | wc.hCursor = LoadCursor (NULL,IDC_ARROW); |
||
634 | wc.hbrBackground = NULL; |
||
635 | wc.lpszMenuName = 0; |
||
636 | wc.lpszClassName = "WinQuake"; |
||
637 | |||
638 | if (!RegisterClass (&wc) ) |
||
639 | Sys_Error ("Couldn't register window class"); |
||
640 | |||
641 | /* Find the size for the DIB window */ |
||
642 | /* Initialise the MGL for windowed operation */ |
||
643 | MGL_setAppInstance(hInstance); |
||
644 | registerAllMemDrivers(); |
||
645 | MGL_initWindowed(""); |
||
646 | |||
647 | modelist[0].type = MS_WINDOWED; |
||
648 | modelist[0].width = 320; |
||
649 | modelist[0].height = 240; |
||
650 | strcpy (modelist[0].modedesc, "320x240"); |
||
651 | modelist[0].mode13 = 0; |
||
652 | modelist[0].modenum = MODE_WINDOWED; |
||
653 | modelist[0].stretched = 0; |
||
654 | modelist[0].dib = 1; |
||
655 | modelist[0].fullscreen = 0; |
||
656 | modelist[0].halfscreen = 0; |
||
657 | modelist[0].bpp = 8; |
||
658 | |||
659 | modelist[1].type = MS_WINDOWED; |
||
660 | modelist[1].width = 640; |
||
661 | modelist[1].height = 480; |
||
662 | strcpy (modelist[1].modedesc, "640x480"); |
||
663 | modelist[1].mode13 = 0; |
||
664 | modelist[1].modenum = MODE_WINDOWED + 1; |
||
665 | modelist[1].stretched = 1; |
||
666 | modelist[1].dib = 1; |
||
667 | modelist[1].fullscreen = 0; |
||
668 | modelist[1].halfscreen = 0; |
||
669 | modelist[1].bpp = 8; |
||
670 | |||
671 | modelist[2].type = MS_WINDOWED; |
||
672 | modelist[2].width = 800; |
||
673 | modelist[2].height = 600; |
||
674 | strcpy (modelist[2].modedesc, "800x600"); |
||
675 | modelist[2].mode13 = 0; |
||
676 | modelist[2].modenum = MODE_WINDOWED + 2; |
||
677 | modelist[2].stretched = 1; |
||
678 | modelist[2].dib = 1; |
||
679 | modelist[2].fullscreen = 0; |
||
680 | modelist[2].halfscreen = 0; |
||
681 | modelist[2].bpp = 8; |
||
682 | |||
683 | // automatically stretch the default mode up if > 640x480 desktop resolution |
||
684 | hdc = GetDC(NULL); |
||
685 | |||
686 | if ((GetDeviceCaps(hdc, HORZRES) > 640) && !COM_CheckParm("-noautostretch")) |
||
687 | { |
||
688 | vid_default = MODE_WINDOWED + 1; |
||
689 | } |
||
690 | else |
||
691 | { |
||
692 | vid_default = MODE_WINDOWED; |
||
693 | } |
||
694 | |||
695 | windowed_default = vid_default; |
||
696 | |||
697 | ReleaseDC(NULL,hdc); |
||
698 | |||
699 | nummodes = 3; // reserve space for windowed mode |
||
700 | |||
701 | DDActive = 0; |
||
702 | } |
||
703 | |||
704 | |||
705 | /* |
||
706 | ================= |
||
707 | VID_InitFullDIB |
||
708 | ================= |
||
709 | */ |
||
710 | void VID_InitFullDIB (HINSTANCE hInstance) |
||
711 | { |
||
712 | DEVMODE devmode; |
||
713 | int i, j, modenum, cmodes, existingmode, originalnummodes, lowestres; |
||
714 | int numlowresmodes, bpp, done; |
||
715 | int cstretch, istretch, mstretch; |
||
716 | BOOL stat; |
||
717 | |||
718 | // enumerate 8 bpp modes |
||
719 | originalnummodes = nummodes; |
||
720 | modenum = 0; |
||
721 | lowestres = 99999; |
||
722 | |||
723 | do |
||
724 | { |
||
725 | stat = EnumDisplaySettings (NULL, modenum, &devmode); |
||
726 | |||
727 | if ((devmode.dmBitsPerPel == 8) && |
||
728 | (devmode.dmPelsWidth <= MAXWIDTH) && |
||
729 | (devmode.dmPelsHeight <= MAXHEIGHT) && |
||
730 | (nummodes < MAX_MODE_LIST)) |
||
731 | { |
||
732 | devmode.dmFields = DM_BITSPERPEL | |
||
733 | DM_PELSWIDTH | |
||
734 | DM_PELSHEIGHT; |
||
735 | |||
736 | if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == |
||
737 | DISP_CHANGE_SUCCESSFUL) |
||
738 | { |
||
739 | modelist[nummodes].type = MS_FULLDIB; |
||
740 | modelist[nummodes].width = devmode.dmPelsWidth; |
||
741 | modelist[nummodes].height = devmode.dmPelsHeight; |
||
742 | modelist[nummodes].modenum = 0; |
||
743 | modelist[nummodes].mode13 = 0; |
||
744 | modelist[nummodes].stretched = 0; |
||
745 | modelist[nummodes].halfscreen = 0; |
||
746 | modelist[nummodes].dib = 1; |
||
747 | modelist[nummodes].fullscreen = 1; |
||
748 | modelist[nummodes].bpp = devmode.dmBitsPerPel; |
||
749 | sprintf (modelist[nummodes].modedesc, "%dx%d", |
||
750 | devmode.dmPelsWidth, devmode.dmPelsHeight); |
||
751 | |||
752 | // if the width is more than twice the height, reduce it by half because this |
||
753 | // is probably a dual-screen monitor |
||
754 | if (!COM_CheckParm("-noadjustaspect")) |
||
755 | { |
||
756 | if (modelist[nummodes].width > (modelist[nummodes].height << 1)) |
||
757 | { |
||
758 | modelist[nummodes].width >>= 1; |
||
759 | modelist[nummodes].halfscreen = 1; |
||
760 | sprintf (modelist[nummodes].modedesc, "%dx%d", |
||
761 | modelist[nummodes].width, |
||
762 | modelist[nummodes].height); |
||
763 | } |
||
764 | } |
||
765 | |||
766 | for (i=originalnummodes, existingmode = 0 ; i |
||
767 | { |
||
768 | if ((modelist[nummodes].width == modelist[i].width) && |
||
769 | (modelist[nummodes].height == modelist[i].height)) |
||
770 | { |
||
771 | existingmode = 1; |
||
772 | break; |
||
773 | } |
||
774 | } |
||
775 | |||
776 | if (!existingmode) |
||
777 | { |
||
778 | if (modelist[nummodes].width < lowestres) |
||
779 | lowestres = modelist[nummodes].width; |
||
780 | |||
781 | nummodes++; |
||
782 | } |
||
783 | } |
||
784 | } |
||
785 | |||
786 | modenum++; |
||
787 | } while (stat); |
||
788 | |||
789 | // see if any of them were actually settable; if so, this is our mode list, |
||
790 | // else enumerate all modes; our mode list is whichever ones are settable |
||
791 | // with > 8 bpp |
||
792 | if (nummodes == originalnummodes) |
||
793 | { |
||
794 | modenum = 0; |
||
795 | lowestres = 99999; |
||
796 | |||
797 | Con_SafePrintf ("No 8-bpp fullscreen DIB modes found\n"); |
||
798 | |||
799 | do |
||
800 | { |
||
801 | stat = EnumDisplaySettings (NULL, modenum, &devmode); |
||
802 | |||
803 | if ((((devmode.dmPelsWidth <= MAXWIDTH) && |
||
804 | (devmode.dmPelsHeight <= MAXHEIGHT)) || |
||
805 | (!COM_CheckParm("-noadjustaspect") && |
||
806 | (devmode.dmPelsWidth <= (MAXWIDTH*2)) && |
||
807 | (devmode.dmPelsWidth > (devmode.dmPelsHeight*2)))) && |
||
808 | (nummodes < MAX_MODE_LIST) && |
||
809 | (devmode.dmBitsPerPel > 8)) |
||
810 | { |
||
811 | devmode.dmFields = DM_BITSPERPEL | |
||
812 | DM_PELSWIDTH | |
||
813 | DM_PELSHEIGHT; |
||
814 | |||
815 | if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == |
||
816 | DISP_CHANGE_SUCCESSFUL) |
||
817 | { |
||
818 | modelist[nummodes].type = MS_FULLDIB; |
||
819 | modelist[nummodes].width = devmode.dmPelsWidth; |
||
820 | modelist[nummodes].height = devmode.dmPelsHeight; |
||
821 | modelist[nummodes].modenum = 0; |
||
822 | modelist[nummodes].mode13 = 0; |
||
823 | modelist[nummodes].stretched = 0; |
||
824 | modelist[nummodes].halfscreen = 0; |
||
825 | modelist[nummodes].dib = 1; |
||
826 | modelist[nummodes].fullscreen = 1; |
||
827 | modelist[nummodes].bpp = devmode.dmBitsPerPel; |
||
828 | sprintf (modelist[nummodes].modedesc, "%dx%d", |
||
829 | devmode.dmPelsWidth, devmode.dmPelsHeight); |
||
830 | |||
831 | // if the width is more than twice the height, reduce it by half because this |
||
832 | // is probably a dual-screen monitor |
||
833 | if (!COM_CheckParm("-noadjustaspect")) |
||
834 | { |
||
835 | if (modelist[nummodes].width > (modelist[nummodes].height*2)) |
||
836 | { |
||
837 | modelist[nummodes].width >>= 1; |
||
838 | modelist[nummodes].halfscreen = 1; |
||
839 | sprintf (modelist[nummodes].modedesc, "%dx%d", |
||
840 | modelist[nummodes].width, |
||
841 | modelist[nummodes].height); |
||
842 | } |
||
843 | } |
||
844 | |||
845 | for (i=originalnummodes, existingmode = 0 ; i |
||
846 | { |
||
847 | if ((modelist[nummodes].width == modelist[i].width) && |
||
848 | (modelist[nummodes].height == modelist[i].height)) |
||
849 | { |
||
850 | // pick the lowest available bpp |
||
851 | if (modelist[nummodes].bpp < modelist[i].bpp) |
||
852 | modelist[i] = modelist[nummodes]; |
||
853 | |||
854 | existingmode = 1; |
||
855 | break; |
||
856 | } |
||
857 | } |
||
858 | |||
859 | if (!existingmode) |
||
860 | { |
||
861 | if (modelist[nummodes].width < lowestres) |
||
862 | lowestres = modelist[nummodes].width; |
||
863 | |||
864 | nummodes++; |
||
865 | } |
||
866 | } |
||
867 | } |
||
868 | |||
869 | modenum++; |
||
870 | } while (stat); |
||
871 | } |
||
872 | |||
873 | // see if there are any low-res modes that aren't being reported |
||
874 | numlowresmodes = sizeof(lowresmodes) / sizeof(lowresmodes[0]); |
||
875 | bpp = 8; |
||
876 | done = 0; |
||
877 | |||
878 | // first make sure the driver doesn't just answer yes to all tests |
||
879 | devmode.dmBitsPerPel = 8; |
||
880 | devmode.dmPelsWidth = 42; |
||
881 | devmode.dmPelsHeight = 37; |
||
882 | devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; |
||
883 | |||
884 | if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == |
||
885 | DISP_CHANGE_SUCCESSFUL) |
||
886 | { |
||
887 | done = 1; |
||
888 | } |
||
889 | |||
890 | while (!done) |
||
891 | { |
||
892 | for (j=0 ; (j |
||
893 | { |
||
894 | devmode.dmBitsPerPel = bpp; |
||
895 | devmode.dmPelsWidth = lowresmodes[j].width; |
||
896 | devmode.dmPelsHeight = lowresmodes[j].height; |
||
897 | devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; |
||
898 | |||
899 | if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == |
||
900 | DISP_CHANGE_SUCCESSFUL) |
||
901 | { |
||
902 | modelist[nummodes].type = MS_FULLDIB; |
||
903 | modelist[nummodes].width = devmode.dmPelsWidth; |
||
904 | modelist[nummodes].height = devmode.dmPelsHeight; |
||
905 | modelist[nummodes].modenum = 0; |
||
906 | modelist[nummodes].mode13 = 0; |
||
907 | modelist[nummodes].stretched = 0; |
||
908 | modelist[nummodes].halfscreen = 0; |
||
909 | modelist[nummodes].dib = 1; |
||
910 | modelist[nummodes].fullscreen = 1; |
||
911 | modelist[nummodes].bpp = devmode.dmBitsPerPel; |
||
912 | sprintf (modelist[nummodes].modedesc, "%dx%d", |
||
913 | devmode.dmPelsWidth, devmode.dmPelsHeight); |
||
914 | |||
915 | // we only want the lowest-bpp version of each mode |
||
916 | for (i=originalnummodes, existingmode = 0 ; i |
||
917 | { |
||
918 | if ((modelist[nummodes].width == modelist[i].width) && |
||
919 | (modelist[nummodes].height == modelist[i].height) && |
||
920 | (modelist[nummodes].bpp >= modelist[i].bpp)) |
||
921 | { |
||
922 | existingmode = 1; |
||
923 | break; |
||
924 | } |
||
925 | } |
||
926 | |||
927 | if (!existingmode) |
||
928 | { |
||
929 | if (modelist[nummodes].width < lowestres) |
||
930 | lowestres = modelist[nummodes].width; |
||
931 | |||
932 | nummodes++; |
||
933 | } |
||
934 | } |
||
935 | } |
||
936 | |||
937 | switch (bpp) |
||
938 | { |
||
939 | case 8: |
||
940 | bpp = 16; |
||
941 | break; |
||
942 | |||
943 | case 16: |
||
944 | bpp = 32; |
||
945 | break; |
||
946 | |||
947 | case 32: |
||
948 | done = 1; |
||
949 | break; |
||
950 | } |
||
951 | } |
||
952 | |||
953 | // now add the lowest stretch-by-2 pseudo-modes between 320-wide |
||
954 | // (inclusive) and lowest real res (not inclusive) |
||
955 | // don't bother if we have a real VGA mode 0x13 mode |
||
956 | if (!is_mode0x13) |
||
957 | { |
||
958 | for (i=originalnummodes, cstretch=0 ; i |
||
959 | { |
||
960 | if (((modelist[i].width >> 1) < lowestres) && |
||
961 | ((modelist[i].width >> 1) >= 320)) |
||
962 | { |
||
963 | lowestres = modelist[i].width >> 1; |
||
964 | cstretch = 1; |
||
965 | mstretch = i; |
||
966 | } |
||
967 | } |
||
968 | |||
969 | if ((nummodes + cstretch) > MAX_MODE_LIST) |
||
970 | cstretch = MAX_MODE_LIST - nummodes; |
||
971 | |||
972 | if (cstretch > 0) |
||
973 | { |
||
974 | for (i=(nummodes-1) ; i>=originalnummodes ; i--) |
||
975 | modelist[i+cstretch] = modelist[i]; |
||
976 | |||
977 | nummodes += cstretch; |
||
978 | istretch = originalnummodes; |
||
979 | |||
980 | modelist[istretch] = modelist[mstretch]; |
||
981 | modelist[istretch].width >>= 1; |
||
982 | modelist[istretch].height >>= 1; |
||
983 | modelist[istretch].stretched = 1; |
||
984 | sprintf (modelist[istretch].modedesc, "%dx%d", |
||
985 | modelist[istretch].width, modelist[istretch].height); |
||
986 | } |
||
987 | } |
||
988 | |||
989 | if (nummodes != originalnummodes) |
||
990 | vid_default = MODE_FULLSCREEN_DEFAULT; |
||
991 | else |
||
992 | Con_SafePrintf ("No fullscreen DIB modes found\n"); |
||
993 | } |
||
994 | |||
995 | |||
996 | /* |
||
997 | ================= |
||
998 | VID_NumModes |
||
999 | ================= |
||
1000 | */ |
||
1001 | int VID_NumModes (void) |
||
1002 | { |
||
1003 | return nummodes; |
||
1004 | } |
||
1005 | |||
1006 | |||
1007 | /* |
||
1008 | ================= |
||
1009 | VID_GetModePtr |
||
1010 | ================= |
||
1011 | */ |
||
1012 | vmode_t *VID_GetModePtr (int modenum) |
||
1013 | { |
||
1014 | |||
1015 | if ((modenum >= 0) && (modenum < nummodes)) |
||
1016 | return &modelist[modenum]; |
||
1017 | else |
||
1018 | return &badmode; |
||
1019 | } |
||
1020 | |||
1021 | |||
1022 | /* |
||
1023 | ================= |
||
1024 | VID_CheckModedescFixup |
||
1025 | ================= |
||
1026 | */ |
||
1027 | void VID_CheckModedescFixup (int mode) |
||
1028 | { |
||
1029 | int x, y, stretch; |
||
1030 | |||
1031 | if (mode == MODE_SETTABLE_WINDOW) |
||
1032 | { |
||
1033 | modelist[mode].stretched = (int)vid_stretch_by_2.value; |
||
1034 | stretch = modelist[mode].stretched; |
||
1035 | |||
1036 | if (vid_config_x.value < (320 << stretch)) |
||
1037 | vid_config_x.value = 320 << stretch; |
||
1038 | |||
1039 | if (vid_config_y.value < (200 << stretch)) |
||
1040 | vid_config_y.value = 200 << stretch; |
||
1041 | |||
1042 | x = (int)vid_config_x.value; |
||
1043 | y = (int)vid_config_y.value; |
||
1044 | sprintf (modelist[mode].modedesc, "%dx%d", x, y); |
||
1045 | modelist[mode].width = x; |
||
1046 | modelist[mode].height = y; |
||
1047 | } |
||
1048 | } |
||
1049 | |||
1050 | |||
1051 | /* |
||
1052 | ================= |
||
1053 | VID_GetModeDescriptionMemCheck |
||
1054 | ================= |
||
1055 | */ |
||
1056 | char *VID_GetModeDescriptionMemCheck (int mode) |
||
1057 | { |
||
1058 | char *pinfo; |
||
1059 | vmode_t *pv; |
||
1060 | |||
1061 | if ((mode < 0) || (mode >= nummodes)) |
||
1062 | return NULL; |
||
1063 | |||
1064 | VID_CheckModedescFixup (mode); |
||
1065 | |||
1066 | pv = VID_GetModePtr (mode); |
||
1067 | pinfo = pv->modedesc; |
||
1068 | |||
1069 | if (VID_CheckAdequateMem (pv->width, pv->height)) |
||
1070 | { |
||
1071 | return pinfo; |
||
1072 | } |
||
1073 | else |
||
1074 | { |
||
1075 | return NULL; |
||
1076 | } |
||
1077 | } |
||
1078 | |||
1079 | |||
1080 | /* |
||
1081 | ================= |
||
1082 | VID_GetModeDescription |
||
1083 | ================= |
||
1084 | */ |
||
1085 | char *VID_GetModeDescription (int mode) |
||
1086 | { |
||
1087 | char *pinfo; |
||
1088 | vmode_t *pv; |
||
1089 | |||
1090 | if ((mode < 0) || (mode >= nummodes)) |
||
1091 | return NULL; |
||
1092 | |||
1093 | VID_CheckModedescFixup (mode); |
||
1094 | |||
1095 | pv = VID_GetModePtr (mode); |
||
1096 | pinfo = pv->modedesc; |
||
1097 | return pinfo; |
||
1098 | } |
||
1099 | |||
1100 | |||
1101 | /* |
||
1102 | ================= |
||
1103 | VID_GetModeDescription2 |
||
1104 | |||
1105 | Tacks on "windowed" or "fullscreen" |
||
1106 | ================= |
||
1107 | */ |
||
1108 | char *VID_GetModeDescription2 (int mode) |
||
1109 | { |
||
1110 | static char pinfo[40]; |
||
1111 | vmode_t *pv; |
||
1112 | |||
1113 | if ((mode < 0) || (mode >= nummodes)) |
||
1114 | return NULL; |
||
1115 | |||
1116 | VID_CheckModedescFixup (mode); |
||
1117 | |||
1118 | pv = VID_GetModePtr (mode); |
||
1119 | |||
1120 | if (modelist[mode].type == MS_FULLSCREEN) |
||
1121 | { |
||
1122 | sprintf(pinfo,"%s fullscreen", pv->modedesc); |
||
1123 | } |
||
1124 | else if (modelist[mode].type == MS_FULLDIB) |
||
1125 | { |
||
1126 | sprintf(pinfo,"%s fullscreen", pv->modedesc); |
||
1127 | } |
||
1128 | else |
||
1129 | { |
||
1130 | sprintf(pinfo, "%s windowed", pv->modedesc); |
||
1131 | } |
||
1132 | |||
1133 | return pinfo; |
||
1134 | } |
||
1135 | |||
1136 | |||
1137 | // KJB: Added this to return the mode driver name in description for console |
||
1138 | |||
1139 | char *VID_GetExtModeDescription (int mode) |
||
1140 | { |
||
1141 | static char pinfo[40]; |
||
1142 | vmode_t *pv; |
||
1143 | |||
1144 | if ((mode < 0) || (mode >= nummodes)) |
||
1145 | return NULL; |
||
1146 | |||
1147 | VID_CheckModedescFixup (mode); |
||
1148 | |||
1149 | pv = VID_GetModePtr (mode); |
||
1150 | if (modelist[mode].type == MS_FULLSCREEN) |
||
1151 | { |
||
1152 | sprintf(pinfo,"%s fullscreen %s",pv->modedesc, |
||
1153 | MGL_modeDriverName(pv->modenum)); |
||
1154 | } |
||
1155 | else if (modelist[mode].type == MS_FULLDIB) |
||
1156 | { |
||
1157 | sprintf(pinfo,"%s fullscreen DIB", pv->modedesc); |
||
1158 | } |
||
1159 | else |
||
1160 | { |
||
1161 | sprintf(pinfo, "%s windowed", pv->modedesc); |
||
1162 | } |
||
1163 | |||
1164 | return pinfo; |
||
1165 | } |
||
1166 | |||
1167 | |||
1168 | void DestroyDIBWindow (void) |
||
1169 | { |
||
1170 | |||
1171 | if (modestate == MS_WINDOWED) |
||
1172 | { |
||
1173 | // destroy the associated MGL DC's; the window gets reused |
||
1174 | if (windc) |
||
1175 | MGL_destroyDC(windc); |
||
1176 | if (dibdc) |
||
1177 | MGL_destroyDC(dibdc); |
||
1178 | windc = dibdc = NULL; |
||
1179 | } |
||
1180 | } |
||
1181 | |||
1182 | |||
1183 | void DestroyFullscreenWindow (void) |
||
1184 | { |
||
1185 | |||
1186 | if (modestate == MS_FULLSCREEN) |
||
1187 | { |
||
1188 | // destroy the existing fullscreen mode and DC's |
||
1189 | if (mgldc) |
||
1190 | MGL_destroyDC (mgldc); |
||
1191 | if (memdc) |
||
1192 | MGL_destroyDC (memdc); |
||
1193 | mgldc = memdc = NULL; |
||
1194 | } |
||
1195 | } |
||
1196 | |||
1197 | |||
1198 | |||
1199 | void DestroyFullDIBWindow (void) |
||
1200 | { |
||
1201 | if (modestate == MS_FULLDIB) |
||
1202 | { |
||
1203 | ChangeDisplaySettings (NULL, CDS_FULLSCREEN); |
||
1204 | |||
1205 | // Destroy the fullscreen DIB window and associated MGL DC's |
||
1206 | if (windc) |
||
1207 | MGL_destroyDC(windc); |
||
1208 | if (dibdc) |
||
1209 | MGL_destroyDC(dibdc); |
||
1210 | windc = dibdc = NULL; |
||
1211 | } |
||
1212 | } |
||
1213 | |||
1214 | |||
1215 | qboolean VID_SetWindowedMode (int modenum) |
||
1216 | { |
||
1217 | HDC hdc; |
||
1218 | pixel_format_t pf; |
||
1219 | qboolean stretched; |
||
1220 | int lastmodestate; |
||
1221 | LONG wlong; |
||
1222 | |||
1223 | if (!windowed_mode_set) |
||
1224 | { |
||
1225 | if (COM_CheckParm ("-resetwinpos")) |
||
1226 | { |
||
1227 | Cvar_SetValue ("vid_window_x", 0.0); |
||
1228 | Cvar_SetValue ("vid_window_y", 0.0); |
||
1229 | } |
||
1230 | |||
1231 | windowed_mode_set; |
||
1232 | } |
||
1233 | |||
1234 | VID_CheckModedescFixup (modenum); |
||
1235 | |||
1236 | DDActive = 0; |
||
1237 | lastmodestate = modestate; |
||
1238 | |||
1239 | DestroyFullscreenWindow (); |
||
1240 | DestroyFullDIBWindow (); |
||
1241 | |||
1242 | if (windc) |
||
1243 | MGL_destroyDC(windc); |
||
1244 | if (dibdc) |
||
1245 | MGL_destroyDC(dibdc); |
||
1246 | windc = dibdc = NULL; |
||
1247 | |||
1248 | // KJB: Signal to the MGL that we are going back to windowed mode |
||
1249 | if (!MGL_changeDisplayMode(grWINDOWED)) |
||
1250 | initFatalError(); |
||
1251 | |||
1252 | WindowRect.top = WindowRect.left = 0; |
||
1253 | |||
1254 | WindowRect.right = modelist[modenum].width; |
||
1255 | WindowRect.bottom = modelist[modenum].height; |
||
1256 | stretched = modelist[modenum].stretched; |
||
1257 | |||
1258 | DIBWidth = modelist[modenum].width; |
||
1259 | DIBHeight = modelist[modenum].height; |
||
1260 | |||
1261 | if (stretched) |
||
1262 | { |
||
1263 | DIBWidth >>= 1; |
||
1264 | DIBHeight >>= 1; |
||
1265 | } |
||
1266 | |||
1267 | WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | |
||
1268 | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | |
||
1269 | WS_CLIPCHILDREN; |
||
1270 | ExWindowStyle = 0; |
||
1271 | AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); |
||
1272 | |||
1273 | // the first time we're called to set the mode, create the window we'll use |
||
1274 | // for the rest of the session |
||
1275 | if (!vid_mode_set) |
||
1276 | { |
||
1277 | mainwindow = CreateWindowEx ( |
||
1278 | ExWindowStyle, |
||
1279 | "WinQuake", |
||
1280 | "WinQuake", |
||
1281 | WindowStyle, |
||
1282 | 0, 0, |
||
1283 | WindowRect.right - WindowRect.left, |
||
1284 | WindowRect.bottom - WindowRect.top, |
||
1285 | NULL, |
||
1286 | NULL, |
||
1287 | global_hInstance, |
||
1288 | NULL); |
||
1289 | |||
1290 | if (!mainwindow) |
||
1291 | Sys_Error ("Couldn't create DIB window"); |
||
1292 | |||
1293 | // tell MGL to use this window for fullscreen modes |
||
1294 | MGL_registerFullScreenWindow (mainwindow); |
||
1295 | |||
1296 | vid_mode_set = true; |
||
1297 | } |
||
1298 | else |
||
1299 | { |
||
1300 | SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); |
||
1301 | SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); |
||
1302 | } |
||
1303 | |||
1304 | if (!SetWindowPos (mainwindow, |
||
1305 | NULL, |
||
1306 | 0, 0, |
||
1307 | WindowRect.right - WindowRect.left, |
||
1308 | WindowRect.bottom - WindowRect.top, |
||
1309 | SWP_NOCOPYBITS | SWP_NOZORDER | |
||
1310 | SWP_HIDEWINDOW)) |
||
1311 | { |
||
1312 | Sys_Error ("Couldn't resize DIB window"); |
||
1313 | } |
||
1314 | |||
1315 | if (hide_window) |
||
1316 | return true; |
||
1317 | |||
1318 | // position and show the DIB window |
||
1319 | VID_CheckWindowXY (); |
||
1320 | SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, |
||
1321 | (int)vid_window_y.value, 0, 0, |
||
1322 | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); |
||
1323 | |||
1324 | if (force_minimized) |
||
1325 | ShowWindow (mainwindow, SW_MINIMIZE); |
||
1326 | else |
||
1327 | ShowWindow (mainwindow, SW_SHOWDEFAULT); |
||
1328 | |||
1329 | UpdateWindow (mainwindow); |
||
1330 | |||
1331 | modestate = MS_WINDOWED; |
||
1332 | vid_fulldib_on_focus_mode = 0; |
||
1333 | |||
1334 | // because we have set the background brush for the window to NULL |
||
1335 | // (to avoid flickering when re-sizing the window on the desktop), |
||
1336 | // we clear the window to black when created, otherwise it will be |
||
1337 | // empty while Quake starts up. |
||
1338 | hdc = GetDC(mainwindow); |
||
1339 | PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); |
||
1340 | ReleaseDC(mainwindow, hdc); |
||
1341 | |||
1342 | /* Create the MGL window DC and the MGL memory DC */ |
||
1343 | if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) |
||
1344 | MGL_fatalError("Unable to create Windowed DC!"); |
||
1345 | |||
1346 | if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) |
||
1347 | MGL_fatalError("Unable to create Memory DC!"); |
||
1348 | |||
1349 | MGL_makeCurrentDC(dibdc); |
||
1350 | |||
1351 | vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; |
||
1352 | vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; |
||
1353 | vid.numpages = 1; |
||
1354 | vid.maxwarpwidth = WARP_WIDTH; |
||
1355 | vid.maxwarpheight = WARP_HEIGHT; |
||
1356 | vid.height = vid.conheight = DIBHeight; |
||
1357 | vid.width = vid.conwidth = DIBWidth; |
||
1358 | vid.aspect = ((float)vid.height / (float)vid.width) * |
||
1359 | (320.0 / 240.0); |
||
1360 | |||
1361 | vid_stretched = stretched; |
||
1362 | |||
1363 | SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); |
||
1364 | SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); |
||
1365 | |||
1366 | return true; |
||
1367 | } |
||
1368 | |||
1369 | |||
1370 | qboolean VID_SetFullscreenMode (int modenum) |
||
1371 | { |
||
1372 | |||
1373 | DDActive = 1; |
||
1374 | |||
1375 | DestroyDIBWindow (); |
||
1376 | DestroyFullDIBWindow (); |
||
1377 | |||
1378 | mode = modelist[modenum].modenum; |
||
1379 | |||
1380 | // Destroy old DC's, resetting back to fullscreen mode |
||
1381 | if (mgldc) |
||
1382 | MGL_destroyDC (mgldc); |
||
1383 | if (memdc) |
||
1384 | MGL_destroyDC (memdc); |
||
1385 | mgldc = memdc = NULL; |
||
1386 | |||
1387 | if ((mgldc = createDisplayDC (modelist[modenum].stretched || |
||
1388 | (int)vid_nopageflip.value)) == NULL) |
||
1389 | { |
||
1390 | return false; |
||
1391 | } |
||
1392 | |||
1393 | modestate = MS_FULLSCREEN; |
||
1394 | vid_fulldib_on_focus_mode = 0; |
||
1395 | |||
1396 | vid.buffer = vid.conbuffer = vid.direct = NULL; |
||
1397 | vid.maxwarpwidth = WARP_WIDTH; |
||
1398 | vid.maxwarpheight = WARP_HEIGHT; |
||
1399 | DIBHeight = vid.height = vid.conheight = modelist[modenum].height; |
||
1400 | DIBWidth = vid.width = vid.conwidth = modelist[modenum].width; |
||
1401 | vid.aspect = ((float)vid.height / (float)vid.width) * |
||
1402 | (320.0 / 240.0); |
||
1403 | |||
1404 | vid_stretched = modelist[modenum].stretched; |
||
1405 | |||
1406 | // needed because we're not getting WM_MOVE messages fullscreen on NT |
||
1407 | window_x = 0; |
||
1408 | window_y = 0; |
||
1409 | |||
1410 | // set the large icon, so the Quake icon will show up in the taskbar |
||
1411 | SendMessage (mainwindow, WM_SETICON, (WPARAM)1, (LPARAM)hIcon); |
||
1412 | SendMessage (mainwindow, WM_SETICON, (WPARAM)0, (LPARAM)hIcon); |
||
1413 | |||
1414 | // shouldn't be needed, but Kendall needs to let us get the activation |
||
1415 | // message for this not to be needed on NT |
||
1416 | AppActivate (true, false); |
||
1417 | |||
1418 | return true; |
||
1419 | } |
||
1420 | |||
1421 | |||
1422 | qboolean VID_SetFullDIBMode (int modenum) |
||
1423 | { |
||
1424 | HDC hdc; |
||
1425 | pixel_format_t pf; |
||
1426 | int lastmodestate; |
||
1427 | |||
1428 | DDActive = 0; |
||
1429 | |||
1430 | DestroyFullscreenWindow (); |
||
1431 | DestroyDIBWindow (); |
||
1432 | |||
1433 | if (windc) |
||
1434 | MGL_destroyDC(windc); |
||
1435 | if (dibdc) |
||
1436 | MGL_destroyDC(dibdc); |
||
1437 | windc = dibdc = NULL; |
||
1438 | |||
1439 | // KJB: Signal to the MGL that we are going back to windowed mode |
||
1440 | if (!MGL_changeDisplayMode(grWINDOWED)) |
||
1441 | initFatalError(); |
||
1442 | |||
1443 | gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; |
||
1444 | gdevmode.dmBitsPerPel = modelist[modenum].bpp; |
||
1445 | gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].stretched << |
||
1446 | modelist[modenum].halfscreen; |
||
1447 | gdevmode.dmPelsHeight = modelist[modenum].height << modelist[modenum].stretched; |
||
1448 | gdevmode.dmSize = sizeof (gdevmode); |
||
1449 | |||
1450 | if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) |
||
1451 | Sys_Error ("Couldn't set fullscreen DIB mode"); |
||
1452 | |||
1453 | lastmodestate = modestate; |
||
1454 | modestate = MS_FULLDIB; |
||
1455 | vid_fulldib_on_focus_mode = modenum; |
||
1456 | |||
1457 | WindowRect.top = WindowRect.left = 0; |
||
1458 | |||
1459 | hdc = GetDC(NULL); |
||
1460 | |||
1461 | WindowRect.right = modelist[modenum].width << modelist[modenum].stretched; |
||
1462 | WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched; |
||
1463 | |||
1464 | ReleaseDC(NULL,hdc); |
||
1465 | |||
1466 | DIBWidth = modelist[modenum].width; |
||
1467 | DIBHeight = modelist[modenum].height; |
||
1468 | |||
1469 | WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; |
||
1470 | ExWindowStyle = 0; |
||
1471 | AdjustWindowRectEx(&WindowRect, WindowStyle, FALSE, 0); |
||
1472 | |||
1473 | SetWindowLong(mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); |
||
1474 | SetWindowLong(mainwindow, GWL_EXSTYLE, ExWindowStyle); |
||
1475 | |||
1476 | if (!SetWindowPos (mainwindow, |
||
1477 | NULL, |
||
1478 | 0, 0, |
||
1479 | WindowRect.right - WindowRect.left, |
||
1480 | WindowRect.bottom - WindowRect.top, |
||
1481 | SWP_NOCOPYBITS | SWP_NOZORDER)) |
||
1482 | { |
||
1483 | Sys_Error ("Couldn't resize DIB window"); |
||
1484 | } |
||
1485 | |||
1486 | // position and show the DIB window |
||
1487 | SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0, |
||
1488 | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); |
||
1489 | ShowWindow (mainwindow, SW_SHOWDEFAULT); |
||
1490 | UpdateWindow (mainwindow); |
||
1491 | |||
1492 | // Because we have set the background brush for the window to NULL |
||
1493 | // (to avoid flickering when re-sizing the window on the desktop), we |
||
1494 | // clear the window to black when created, otherwise it will be |
||
1495 | // empty while Quake starts up. |
||
1496 | hdc = GetDC(mainwindow); |
||
1497 | PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); |
||
1498 | ReleaseDC(mainwindow, hdc); |
||
1499 | |||
1500 | /* Create the MGL window DC and the MGL memory DC */ |
||
1501 | if ((windc = MGL_createWindowedDC(mainwindow)) == NULL) |
||
1502 | MGL_fatalError("Unable to create Fullscreen DIB DC!"); |
||
1503 | |||
1504 | if ((dibdc = MGL_createMemoryDC(DIBWidth,DIBHeight,8,&pf)) == NULL) |
||
1505 | MGL_fatalError("Unable to create Memory DC!"); |
||
1506 | |||
1507 | MGL_makeCurrentDC(dibdc); |
||
1508 | |||
1509 | vid.buffer = vid.conbuffer = vid.direct = dibdc->surface; |
||
1510 | vid.rowbytes = vid.conrowbytes = dibdc->mi.bytesPerLine; |
||
1511 | vid.numpages = 1; |
||
1512 | vid.maxwarpwidth = WARP_WIDTH; |
||
1513 | vid.maxwarpheight = WARP_HEIGHT; |
||
1514 | vid.height = vid.conheight = DIBHeight; |
||
1515 | vid.width = vid.conwidth = DIBWidth; |
||
1516 | vid.aspect = ((float)vid.height / (float)vid.width) * |
||
1517 | (320.0 / 240.0); |
||
1518 | |||
1519 | vid_stretched = modelist[modenum].stretched; |
||
1520 | |||
1521 | // needed because we're not getting WM_MOVE messages fullscreen on NT |
||
1522 | window_x = 0; |
||
1523 | window_y = 0; |
||
1524 | |||
1525 | return true; |
||
1526 | } |
||
1527 | |||
1528 | |||
1529 | void VID_RestoreOldMode (int original_mode) |
||
1530 | { |
||
1531 | static qboolean inerror = false; |
||
1532 | |||
1533 | if (inerror) |
||
1534 | return; |
||
1535 | |||
1536 | in_mode_set = false; |
||
1537 | inerror = true; |
||
1538 | |||
1539 | // make sure mode set happens (video mode changes) |
||
1540 | vid_modenum = original_mode - 1; |
||
1541 | |||
1542 | if (!VID_SetMode (original_mode, vid_curpal)) |
||
1543 | { |
||
1544 | vid_modenum = MODE_WINDOWED - 1; |
||
1545 | |||
1546 | if (!VID_SetMode (windowed_default, vid_curpal)) |
||
1547 | Sys_Error ("Can't set any video mode"); |
||
1548 | } |
||
1549 | |||
1550 | inerror = false; |
||
1551 | } |
||
1552 | |||
1553 | |||
1554 | void VID_SetDefaultMode (void) |
||
1555 | { |
||
1556 | |||
1557 | if (vid_initialized) |
||
1558 | VID_SetMode (0, vid_curpal); |
||
1559 | |||
1560 | IN_DeactivateMouse (); |
||
1561 | } |
||
1562 | |||
1563 | |||
1564 | int VID_SetMode (int modenum, unsigned char *palette) |
||
1565 | { |
||
1566 | int original_mode, temp, dummy; |
||
1567 | qboolean stat; |
||
1568 | MSG msg; |
||
1569 | HDC hdc; |
||
1570 | |||
1571 | while ((modenum >= nummodes) || (modenum < 0)) |
||
1572 | { |
||
1573 | if (vid_modenum == NO_MODE) |
||
1574 | { |
||
1575 | if (modenum == vid_default) |
||
1576 | { |
||
1577 | modenum = windowed_default; |
||
1578 | } |
||
1579 | else |
||
1580 | { |
||
1581 | modenum = vid_default; |
||
1582 | } |
||
1583 | |||
1584 | Cvar_SetValue ("vid_mode", (float)modenum); |
||
1585 | } |
||
1586 | else |
||
1587 | { |
||
1588 | Cvar_SetValue ("vid_mode", (float)vid_modenum); |
||
1589 | return 0; |
||
1590 | } |
||
1591 | } |
||
1592 | |||
1593 | if (!force_mode_set && (modenum == vid_modenum)) |
||
1594 | return true; |
||
1595 | |||
1596 | // so Con_Printfs don't mess us up by forcing vid and snd updates |
||
1597 | temp = scr_disabled_for_loading; |
||
1598 | scr_disabled_for_loading = true; |
||
1599 | in_mode_set = true; |
||
1600 | |||
1601 | CDAudio_Pause (); |
||
1602 | S_ClearBuffer (); |
||
1603 | |||
1604 | if (vid_modenum == NO_MODE) |
||
1605 | original_mode = windowed_default; |
||
1606 | else |
||
1607 | original_mode = vid_modenum; |
||
1608 | |||
1609 | // Set either the fullscreen or windowed mode |
||
1610 | if (modelist[modenum].type == MS_WINDOWED) |
||
1611 | { |
||
1612 | if (_windowed_mouse.value) |
||
1613 | { |
||
1614 | stat = VID_SetWindowedMode(modenum); |
||
1615 | IN_ActivateMouse (); |
||
1616 | IN_HideMouse (); |
||
1617 | } |
||
1618 | else |
||
1619 | { |
||
1620 | IN_DeactivateMouse (); |
||
1621 | IN_ShowMouse (); |
||
1622 | stat = VID_SetWindowedMode(modenum); |
||
1623 | } |
||
1624 | } |
||
1625 | else if (modelist[modenum].type == MS_FULLDIB) |
||
1626 | { |
||
1627 | stat = VID_SetFullDIBMode(modenum); |
||
1628 | IN_ActivateMouse (); |
||
1629 | IN_HideMouse (); |
||
1630 | } |
||
1631 | else |
||
1632 | { |
||
1633 | stat = VID_SetFullscreenMode(modenum); |
||
1634 | IN_ActivateMouse (); |
||
1635 | IN_HideMouse (); |
||
1636 | } |
||
1637 | |||
1638 | window_width = vid.width << vid_stretched; |
||
1639 | window_height = vid.height << vid_stretched; |
||
1640 | VID_UpdateWindowStatus (); |
||
1641 | |||
1642 | CDAudio_Resume (); |
||
1643 | scr_disabled_for_loading = temp; |
||
1644 | |||
1645 | if (!stat) |
||
1646 | { |
||
1647 | VID_RestoreOldMode (original_mode); |
||
1648 | return false; |
||
1649 | } |
||
1650 | |||
1651 | if (hide_window) |
||
1652 | return true; |
||
1653 | |||
1654 | // now we try to make sure we get the focus on the mode switch, because |
||
1655 | // sometimes in some systems we don't. We grab the foreground, then |
||
1656 | // finish setting up, pump all our messages, and sleep for a little while |
||
1657 | // to let messages finish bouncing around the system, then we put |
||
1658 | // ourselves at the top of the z order, then grab the foreground again, |
||
1659 | // Who knows if it helps, but it probably doesn't hurt |
||
1660 | if (!force_minimized) |
||
1661 | SetForegroundWindow (mainwindow); |
||
1662 | |||
1663 | hdc = GetDC(NULL); |
||
1664 | |||
1665 | if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) |
||
1666 | vid_palettized = true; |
||
1667 | else |
||
1668 | vid_palettized = false; |
||
1669 | |||
1670 | VID_SetPalette (palette); |
||
1671 | |||
1672 | ReleaseDC(NULL,hdc); |
||
1673 | |||
1674 | vid_modenum = modenum; |
||
1675 | Cvar_SetValue ("vid_mode", (float)vid_modenum); |
||
1676 | |||
1677 | if (!VID_AllocBuffers (vid.width, vid.height)) |
||
1678 | { |
||
1679 | // couldn't get memory for this mode; try to fall back to previous mode |
||
1680 | VID_RestoreOldMode (original_mode); |
||
1681 | return false; |
||
1682 | } |
||
1683 | |||
1684 | D_InitCaches (vid_surfcache, vid_surfcachesize); |
||
1685 | |||
1686 | while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) |
||
1687 | { |
||
1688 | TranslateMessage (&msg); |
||
1689 | DispatchMessage (&msg); |
||
1690 | } |
||
1691 | |||
1692 | Sleep (100); |
||
1693 | |||
1694 | if (!force_minimized) |
||
1695 | { |
||
1696 | SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, |
||
1697 | SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | |
||
1698 | SWP_NOCOPYBITS); |
||
1699 | |||
1700 | SetForegroundWindow (mainwindow); |
||
1701 | } |
||
1702 | |||
1703 | // fix the leftover Alt from any Alt-Tab or the like that switched us away |
||
1704 | ClearAllStates (); |
||
1705 | |||
1706 | if (!msg_suppress_1) |
||
1707 | Con_SafePrintf ("%s\n", VID_GetModeDescription (vid_modenum)); |
||
1708 | |||
1709 | VID_SetPalette (palette); |
||
1710 | |||
1711 | in_mode_set = false; |
||
1712 | vid.recalc_refdef = 1; |
||
1713 | |||
1714 | return true; |
||
1715 | } |
||
1716 | |||
1717 | void VID_LockBuffer (void) |
||
1718 | { |
||
1719 | |||
1720 | if (dibdc) |
||
1721 | return; |
||
1722 | |||
1723 | lockcount++; |
||
1724 | |||
1725 | if (lockcount > 1) |
||
1726 | return; |
||
1727 | |||
1728 | MGL_beginDirectAccess(); |
||
1729 | |||
1730 | if (memdc) |
||
1731 | { |
||
1732 | // Update surface pointer for linear access modes |
||
1733 | vid.buffer = vid.conbuffer = vid.direct = memdc->surface; |
||
1734 | vid.rowbytes = vid.conrowbytes = memdc->mi.bytesPerLine; |
||
1735 | } |
||
1736 | else if (mgldc) |
||
1737 | { |
||
1738 | // Update surface pointer for linear access modes |
||
1739 | vid.buffer = vid.conbuffer = vid.direct = mgldc->surface; |
||
1740 | vid.rowbytes = vid.conrowbytes = mgldc->mi.bytesPerLine; |
||
1741 | } |
||
1742 | |||
1743 | if (r_dowarp) |
||
1744 | d_viewbuffer = r_warpbuffer; |
||
1745 | else |
||
1746 | d_viewbuffer = (void *)(byte *)vid.buffer; |
||
1747 | |||
1748 | if (r_dowarp) |
||
1749 | screenwidth = WARP_WIDTH; |
||
1750 | else |
||
1751 | screenwidth = vid.rowbytes; |
||
1752 | |||
1753 | if (lcd_x.value) |
||
1754 | screenwidth <<= 1; |
||
1755 | } |
||
1756 | |||
1757 | |||
1758 | void VID_UnlockBuffer (void) |
||
1759 | { |
||
1760 | if (dibdc) |
||
1761 | return; |
||
1762 | |||
1763 | lockcount--; |
||
1764 | |||
1765 | if (lockcount > 0) |
||
1766 | return; |
||
1767 | |||
1768 | if (lockcount < 0) |
||
1769 | Sys_Error ("Unbalanced unlock"); |
||
1770 | |||
1771 | MGL_endDirectAccess(); |
||
1772 | |||
1773 | // to turn up any unlocked accesses |
||
1774 | vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL; |
||
1775 | |||
1776 | } |
||
1777 | |||
1778 | |||
1779 | int VID_ForceUnlockedAndReturnState (void) |
||
1780 | { |
||
1781 | int lk; |
||
1782 | |||
1783 | if (!lockcount) |
||
1784 | return 0; |
||
1785 | |||
1786 | lk = lockcount; |
||
1787 | |||
1788 | if (dibdc) |
||
1789 | { |
||
1790 | lockcount = 0; |
||
1791 | } |
||
1792 | else |
||
1793 | { |
||
1794 | lockcount = 1; |
||
1795 | VID_UnlockBuffer (); |
||
1796 | } |
||
1797 | |||
1798 | return lk; |
||
1799 | } |
||
1800 | |||
1801 | |||
1802 | void VID_ForceLockState (int lk) |
||
1803 | { |
||
1804 | |||
1805 | if (!dibdc && lk) |
||
1806 | { |
||
1807 | lockcount = 0; |
||
1808 | VID_LockBuffer (); |
||
1809 | } |
||
1810 | |||
1811 | lockcount = lk; |
||
1812 | } |
||
1813 | |||
1814 | |||
1815 | void VID_SetPalette (unsigned char *palette) |
||
1816 | { |
||
1817 | INT i; |
||
1818 | palette_t pal[256]; |
||
1819 | HDC hdc; |
||
1820 | |||
1821 | if (!Minimized) |
||
1822 | { |
||
1823 | palette_changed = true; |
||
1824 | |||
1825 | // make sure we have the static colors if we're the active app |
||
1826 | hdc = GetDC(NULL); |
||
1827 | |||
1828 | if (vid_palettized && ActiveApp) |
||
1829 | { |
||
1830 | if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) |
||
1831 | { |
||
1832 | // switch to SYSPAL_NOSTATIC and remap the colors |
||
1833 | SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); |
||
1834 | syscolchg = true; |
||
1835 | pal_is_nostatic = true; |
||
1836 | } |
||
1837 | } |
||
1838 | |||
1839 | ReleaseDC(NULL,hdc); |
||
1840 | |||
1841 | // Translate the palette values to an MGL palette array and |
||
1842 | // set the values. |
||
1843 | for (i = 0; i < 256; i++) |
||
1844 | { |
||
1845 | pal[i].red = palette[i*3]; |
||
1846 | pal[i].green = palette[i*3+1]; |
||
1847 | pal[i].blue = palette[i*3+2]; |
||
1848 | } |
||
1849 | |||
1850 | if (DDActive) |
||
1851 | { |
||
1852 | if (!mgldc) |
||
1853 | return; |
||
1854 | |||
1855 | MGL_setPalette(mgldc,pal,256,0); |
||
1856 | MGL_realizePalette(mgldc,256,0,false); |
||
1857 | if (memdc) |
||
1858 | MGL_setPalette(memdc,pal,256,0); |
||
1859 | } |
||
1860 | else |
||
1861 | { |
||
1862 | if (!windc) |
||
1863 | return; |
||
1864 | |||
1865 | MGL_setPalette(windc,pal,256,0); |
||
1866 | MGL_realizePalette(windc,256,0,false); |
||
1867 | if (dibdc) |
||
1868 | { |
||
1869 | MGL_setPalette(dibdc,pal,256,0); |
||
1870 | MGL_realizePalette(dibdc,256,0,false); |
||
1871 | } |
||
1872 | } |
||
1873 | } |
||
1874 | |||
1875 | memcpy (vid_curpal, palette, sizeof(vid_curpal)); |
||
1876 | |||
1877 | if (syscolchg) |
||
1878 | { |
||
1879 | PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); |
||
1880 | syscolchg = false; |
||
1881 | } |
||
1882 | } |
||
1883 | |||
1884 | |||
1885 | void VID_ShiftPalette (unsigned char *palette) |
||
1886 | { |
||
1887 | VID_SetPalette (palette); |
||
1888 | } |
||
1889 | |||
1890 | |||
1891 | /* |
||
1892 | ================= |
||
1893 | VID_DescribeCurrentMode_f |
||
1894 | ================= |
||
1895 | */ |
||
1896 | void VID_DescribeCurrentMode_f (void) |
||
1897 | { |
||
1898 | Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); |
||
1899 | } |
||
1900 | |||
1901 | |||
1902 | /* |
||
1903 | ================= |
||
1904 | VID_NumModes_f |
||
1905 | ================= |
||
1906 | */ |
||
1907 | void VID_NumModes_f (void) |
||
1908 | { |
||
1909 | |||
1910 | if (nummodes == 1) |
||
1911 | Con_Printf ("%d video mode is available\n", nummodes); |
||
1912 | else |
||
1913 | Con_Printf ("%d video modes are available\n", nummodes); |
||
1914 | } |
||
1915 | |||
1916 | |||
1917 | /* |
||
1918 | ================= |
||
1919 | VID_DescribeMode_f |
||
1920 | ================= |
||
1921 | */ |
||
1922 | void VID_DescribeMode_f (void) |
||
1923 | { |
||
1924 | int modenum; |
||
1925 | |||
1926 | modenum = Q_atoi (Cmd_Argv(1)); |
||
1927 | |||
1928 | Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); |
||
1929 | } |
||
1930 | |||
1931 | |||
1932 | /* |
||
1933 | ================= |
||
1934 | VID_DescribeModes_f |
||
1935 | ================= |
||
1936 | */ |
||
1937 | void VID_DescribeModes_f (void) |
||
1938 | { |
||
1939 | int i, lnummodes; |
||
1940 | char *pinfo; |
||
1941 | qboolean na; |
||
1942 | vmode_t *pv; |
||
1943 | |||
1944 | na = false; |
||
1945 | |||
1946 | lnummodes = VID_NumModes (); |
||
1947 | |||
1948 | for (i=0 ; i |
||
1949 | { |
||
1950 | pv = VID_GetModePtr (i); |
||
1951 | pinfo = VID_GetExtModeDescription (i); |
||
1952 | |||
1953 | if (VID_CheckAdequateMem (pv->width, pv->height)) |
||
1954 | { |
||
1955 | Con_Printf ("%2d: %s\n", i, pinfo); |
||
1956 | } |
||
1957 | else |
||
1958 | { |
||
1959 | Con_Printf ("**: %s\n", pinfo); |
||
1960 | na = true; |
||
1961 | } |
||
1962 | } |
||
1963 | |||
1964 | if (na) |
||
1965 | { |
||
1966 | Con_Printf ("\n[**: not enough system RAM for mode]\n"); |
||
1967 | } |
||
1968 | } |
||
1969 | |||
1970 | |||
1971 | /* |
||
1972 | ================= |
||
1973 | VID_TestMode_f |
||
1974 | ================= |
||
1975 | */ |
||
1976 | void VID_TestMode_f (void) |
||
1977 | { |
||
1978 | int modenum; |
||
1979 | double testduration; |
||
1980 | |||
1981 | if (!vid_testingmode) |
||
1982 | { |
||
1983 | modenum = Q_atoi (Cmd_Argv(1)); |
||
1984 | |||
1985 | if (VID_SetMode (modenum, vid_curpal)) |
||
1986 | { |
||
1987 | vid_testingmode = 1; |
||
1988 | testduration = Q_atof (Cmd_Argv(2)); |
||
1989 | if (testduration == 0) |
||
1990 | testduration = 5.0; |
||
1991 | vid_testendtime = realtime + testduration; |
||
1992 | } |
||
1993 | } |
||
1994 | } |
||
1995 | |||
1996 | |||
1997 | /* |
||
1998 | ================= |
||
1999 | VID_Windowed_f |
||
2000 | ================= |
||
2001 | */ |
||
2002 | void VID_Windowed_f (void) |
||
2003 | { |
||
2004 | |||
2005 | VID_SetMode ((int)vid_windowed_mode.value, vid_curpal); |
||
2006 | } |
||
2007 | |||
2008 | |||
2009 | /* |
||
2010 | ================= |
||
2011 | VID_Fullscreen_f |
||
2012 | ================= |
||
2013 | */ |
||
2014 | void VID_Fullscreen_f (void) |
||
2015 | { |
||
2016 | |||
2017 | VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); |
||
2018 | } |
||
2019 | |||
2020 | |||
2021 | /* |
||
2022 | ================= |
||
2023 | VID_Minimize_f |
||
2024 | ================= |
||
2025 | */ |
||
2026 | void VID_Minimize_f (void) |
||
2027 | { |
||
2028 | |||
2029 | // we only support minimizing windows; if you're fullscreen, |
||
2030 | // switch to windowed first |
||
2031 | if (modestate == MS_WINDOWED) |
||
2032 | ShowWindow (mainwindow, SW_MINIMIZE); |
||
2033 | } |
||
2034 | |||
2035 | |||
2036 | |||
2037 | /* |
||
2038 | ================= |
||
2039 | VID_ForceMode_f |
||
2040 | ================= |
||
2041 | */ |
||
2042 | void VID_ForceMode_f (void) |
||
2043 | { |
||
2044 | int modenum; |
||
2045 | double testduration; |
||
2046 | |||
2047 | if (!vid_testingmode) |
||
2048 | { |
||
2049 | modenum = Q_atoi (Cmd_Argv(1)); |
||
2050 | |||
2051 | force_mode_set = 1; |
||
2052 | VID_SetMode (modenum, vid_curpal); |
||
2053 | force_mode_set = 0; |
||
2054 | } |
||
2055 | } |
||
2056 | |||
2057 | |||
2058 | void VID_Init (unsigned char *palette) |
||
2059 | { |
||
2060 | int i, bestmatch, bestmatchmetric, t, dr, dg, db; |
||
2061 | int basenummodes; |
||
2062 | byte *ptmp; |
||
2063 | |||
2064 | Cvar_RegisterVariable (&vid_mode); |
||
2065 | Cvar_RegisterVariable (&vid_wait); |
||
2066 | Cvar_RegisterVariable (&vid_nopageflip); |
||
2067 | Cvar_RegisterVariable (&_vid_wait_override); |
||
2068 | Cvar_RegisterVariable (&_vid_default_mode); |
||
2069 | Cvar_RegisterVariable (&_vid_default_mode_win); |
||
2070 | Cvar_RegisterVariable (&vid_config_x); |
||
2071 | Cvar_RegisterVariable (&vid_config_y); |
||
2072 | Cvar_RegisterVariable (&vid_stretch_by_2); |
||
2073 | Cvar_RegisterVariable (&_windowed_mouse); |
||
2074 | Cvar_RegisterVariable (&vid_fullscreen_mode); |
||
2075 | Cvar_RegisterVariable (&vid_windowed_mode); |
||
2076 | Cvar_RegisterVariable (&block_switch); |
||
2077 | Cvar_RegisterVariable (&vid_window_x); |
||
2078 | Cvar_RegisterVariable (&vid_window_y); |
||
2079 | |||
2080 | Cmd_AddCommand ("vid_testmode", VID_TestMode_f); |
||
2081 | Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); |
||
2082 | Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); |
||
2083 | Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); |
||
2084 | Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); |
||
2085 | Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f); |
||
2086 | Cmd_AddCommand ("vid_windowed", VID_Windowed_f); |
||
2087 | Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f); |
||
2088 | Cmd_AddCommand ("vid_minimize", VID_Minimize_f); |
||
2089 | |||
2090 | if (COM_CheckParm ("-dibonly")) |
||
2091 | dibonly = true; |
||
2092 | |||
2093 | VID_InitMGLDIB (global_hInstance); |
||
2094 | |||
2095 | basenummodes = nummodes; |
||
2096 | |||
2097 | if (!dibonly) |
||
2098 | VID_InitMGLFull (global_hInstance); |
||
2099 | |||
2100 | // if there are no non-windowed modes, or only windowed and mode 0x13, then use |
||
2101 | // fullscreen DIBs as well |
||
2102 | if (((nummodes == basenummodes) || |
||
2103 | ((nummodes == (basenummodes + 1)) && is_mode0x13)) && |
||
2104 | !COM_CheckParm ("-nofulldib")) |
||
2105 | |||
2106 | { |
||
2107 | VID_InitFullDIB (global_hInstance); |
||
2108 | } |
||
2109 | |||
2110 | vid.maxwarpwidth = WARP_WIDTH; |
||
2111 | vid.maxwarpheight = WARP_HEIGHT; |
||
2112 | vid.colormap = host_colormap; |
||
2113 | vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); |
||
2114 | vid_testingmode = 0; |
||
2115 | |||
2116 | // GDI doesn't let us remap palette index 0, so we'll remap color |
||
2117 | // mappings from that black to another one |
||
2118 | bestmatchmetric = 256*256*3; |
||
2119 | |||
2120 | for (i=1 ; i<256 ; i++) |
||
2121 | { |
||
2122 | dr = palette[0] - palette[i*3]; |
||
2123 | dg = palette[1] - palette[i*3+1]; |
||
2124 | db = palette[2] - palette[i*3+2]; |
||
2125 | |||
2126 | t = (dr * dr) + (dg * dg) + (db * db); |
||
2127 | |||
2128 | if (t < bestmatchmetric) |
||
2129 | { |
||
2130 | bestmatchmetric = t; |
||
2131 | bestmatch = i; |
||
2132 | |||
2133 | if (t == 0) |
||
2134 | break; |
||
2135 | } |
||
2136 | } |
||
2137 | |||
2138 | for (i=0, ptmp = vid.colormap ; i<(1<<(VID_CBITS+8)) ; i++, ptmp++) |
||
2139 | { |
||
2140 | if (*ptmp == 0) |
||
2141 | *ptmp = bestmatch; |
||
2142 | } |
||
2143 | |||
2144 | if (COM_CheckParm("-startwindowed")) |
||
2145 | { |
||
2146 | startwindowed = 1; |
||
2147 | vid_default = windowed_default; |
||
2148 | } |
||
2149 | |||
2150 | if (hwnd_dialog) |
||
2151 | DestroyWindow (hwnd_dialog); |
||
2152 | |||
2153 | // sound initialization has to go here, preceded by a windowed mode set, |
||
2154 | // so there's a window for DirectSound to work with but we're not yet |
||
2155 | // fullscreen so the "hardware already in use" dialog is visible if it |
||
2156 | // gets displayed |
||
2157 | |||
2158 | // keep the window minimized until we're ready for the first real mode set |
||
2159 | hide_window = true; |
||
2160 | VID_SetMode (MODE_WINDOWED, palette); |
||
2161 | hide_window = false; |
||
2162 | S_Init (); |
||
2163 | |||
2164 | vid_initialized = true; |
||
2165 | |||
2166 | force_mode_set = true; |
||
2167 | VID_SetMode (vid_default, palette); |
||
2168 | force_mode_set = false; |
||
2169 | |||
2170 | vid_realmode = vid_modenum; |
||
2171 | |||
2172 | VID_SetPalette (palette); |
||
2173 | |||
2174 | vid_menudrawfn = VID_MenuDraw; |
||
2175 | vid_menukeyfn = VID_MenuKey; |
||
2176 | |||
2177 | strcpy (badmode.modedesc, "Bad mode"); |
||
2178 | } |
||
2179 | |||
2180 | |||
2181 | void VID_Shutdown (void) |
||
2182 | { |
||
2183 | HDC hdc; |
||
2184 | int dummy; |
||
2185 | |||
2186 | if (vid_initialized) |
||
2187 | { |
||
2188 | if (modestate == MS_FULLDIB) |
||
2189 | ChangeDisplaySettings (NULL, CDS_FULLSCREEN); |
||
2190 | |||
2191 | PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)mainwindow, (LPARAM)0); |
||
2192 | PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0); |
||
2193 | |||
2194 | AppActivate(false, false); |
||
2195 | DestroyDIBWindow (); |
||
2196 | DestroyFullscreenWindow (); |
||
2197 | DestroyFullDIBWindow (); |
||
2198 | |||
2199 | if (hwnd_dialog) |
||
2200 | DestroyWindow (hwnd_dialog); |
||
2201 | |||
2202 | if (mainwindow) |
||
2203 | DestroyWindow(mainwindow); |
||
2204 | |||
2205 | MGL_exit(); |
||
2206 | |||
2207 | vid_testingmode = 0; |
||
2208 | vid_initialized = 0; |
||
2209 | } |
||
2210 | } |
||
2211 | |||
2212 | |||
2213 | /* |
||
2214 | ================ |
||
2215 | FlipScreen |
||
2216 | ================ |
||
2217 | */ |
||
2218 | void FlipScreen(vrect_t *rects) |
||
2219 | { |
||
2220 | HRESULT ddrval; |
||
2221 | |||
2222 | // Flip the surfaces |
||
2223 | |||
2224 | if (DDActive) |
||
2225 | { |
||
2226 | if (mgldc) |
||
2227 | { |
||
2228 | if (memdc) |
||
2229 | { |
||
2230 | while (rects) |
||
2231 | { |
||
2232 | if (vid_stretched) |
||
2233 | { |
||
2234 | MGL_stretchBltCoord(mgldc, memdc, |
||
2235 | rects->x, |
||
2236 | rects->y, |
||
2237 | rects->x + rects->width, |
||
2238 | rects->y + rects->height, |
||
2239 | rects->x << 1, |
||
2240 | rects->y << 1, |
||
2241 | (rects->x + rects->width) << 1, |
||
2242 | (rects->y + rects->height) << 1); |
||
2243 | } |
||
2244 | else |
||
2245 | { |
||
2246 | MGL_bitBltCoord(mgldc, memdc, |
||
2247 | rects->x, rects->y, |
||
2248 | (rects->x + rects->width), |
||
2249 | (rects->y + rects->height), |
||
2250 | rects->x, rects->y, MGL_REPLACE_MODE); |
||
2251 | } |
||
2252 | |||
2253 | rects = rects->pnext; |
||
2254 | } |
||
2255 | } |
||
2256 | |||
2257 | if (vid.numpages > 1) |
||
2258 | { |
||
2259 | // We have a flipping surface, so do a hard page flip |
||
2260 | aPage = (aPage+1) % vid.numpages; |
||
2261 | vPage = (vPage+1) % vid.numpages; |
||
2262 | MGL_setActivePage(mgldc,aPage); |
||
2263 | MGL_setVisualPage(mgldc,vPage,waitVRT); |
||
2264 | } |
||
2265 | } |
||
2266 | } |
||
2267 | else |
||
2268 | { |
||
2269 | HDC hdcScreen; |
||
2270 | |||
2271 | hdcScreen = GetDC(mainwindow); |
||
2272 | |||
2273 | if (windc && dibdc) |
||
2274 | { |
||
2275 | MGL_setWinDC(windc,hdcScreen); |
||
2276 | |||
2277 | while (rects) |
||
2278 | { |
||
2279 | if (vid_stretched) |
||
2280 | { |
||
2281 | MGL_stretchBltCoord(windc,dibdc, |
||
2282 | rects->x, rects->y, |
||
2283 | rects->x + rects->width, rects->y + rects->height, |
||
2284 | rects->x << 1, rects->y << 1, |
||
2285 | (rects->x + rects->width) << 1, |
||
2286 | (rects->y + rects->height) << 1); |
||
2287 | } |
||
2288 | else |
||
2289 | { |
||
2290 | MGL_bitBltCoord(windc,dibdc, |
||
2291 | rects->x, rects->y, |
||
2292 | rects->x + rects->width, rects->y + rects->height, |
||
2293 | rects->x, rects->y, MGL_REPLACE_MODE); |
||
2294 | } |
||
2295 | |||
2296 | rects = rects->pnext; |
||
2297 | } |
||
2298 | } |
||
2299 | |||
2300 | ReleaseDC(mainwindow, hdcScreen); |
||
2301 | } |
||
2302 | } |
||
2303 | |||
2304 | |||
2305 | void VID_Update (vrect_t *rects) |
||
2306 | { |
||
2307 | vrect_t rect; |
||
2308 | RECT trect; |
||
2309 | |||
2310 | if (!vid_palettized && palette_changed) |
||
2311 | { |
||
2312 | palette_changed = false; |
||
2313 | rect.x = 0; |
||
2314 | rect.y = 0; |
||
2315 | rect.width = vid.width; |
||
2316 | rect.height = vid.height; |
||
2317 | rect.pnext = NULL; |
||
2318 | rects = ▭ |
||
2319 | } |
||
2320 | |||
2321 | if (firstupdate) |
||
2322 | { |
||
2323 | if (modestate == MS_WINDOWED) |
||
2324 | { |
||
2325 | GetWindowRect (mainwindow, &trect); |
||
2326 | |||
2327 | if ((trect.left != (int)vid_window_x.value) || |
||
2328 | (trect.top != (int)vid_window_y.value)) |
||
2329 | { |
||
2330 | if (COM_CheckParm ("-resetwinpos")) |
||
2331 | { |
||
2332 | Cvar_SetValue ("vid_window_x", 0.0); |
||
2333 | Cvar_SetValue ("vid_window_y", 0.0); |
||
2334 | } |
||
2335 | |||
2336 | VID_CheckWindowXY (); |
||
2337 | SetWindowPos (mainwindow, NULL, (int)vid_window_x.value, |
||
2338 | (int)vid_window_y.value, 0, 0, |
||
2339 | SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); |
||
2340 | } |
||
2341 | } |
||
2342 | |||
2343 | if ((_vid_default_mode_win.value != vid_default) && |
||
2344 | (!startwindowed || (_vid_default_mode_win.value < MODE_FULLSCREEN_DEFAULT))) |
||
2345 | { |
||
2346 | firstupdate = 0; |
||
2347 | |||
2348 | if (COM_CheckParm ("-resetwinpos")) |
||
2349 | { |
||
2350 | Cvar_SetValue ("vid_window_x", 0.0); |
||
2351 | Cvar_SetValue ("vid_window_y", 0.0); |
||
2352 | } |
||
2353 | |||
2354 | if ((_vid_default_mode_win.value < 0) || |
||
2355 | (_vid_default_mode_win.value >= nummodes)) |
||
2356 | { |
||
2357 | Cvar_SetValue ("_vid_default_mode_win", windowed_default); |
||
2358 | } |
||
2359 | |||
2360 | Cvar_SetValue ("vid_mode", _vid_default_mode_win.value); |
||
2361 | } |
||
2362 | } |
||
2363 | |||
2364 | // We've drawn the frame; copy it to the screen |
||
2365 | FlipScreen (rects); |
||
2366 | |||
2367 | if (vid_testingmode) |
||
2368 | { |
||
2369 | if (realtime >= vid_testendtime) |
||
2370 | { |
||
2371 | VID_SetMode (vid_realmode, vid_curpal); |
||
2372 | vid_testingmode = 0; |
||
2373 | } |
||
2374 | } |
||
2375 | else |
||
2376 | { |
||
2377 | if ((int)vid_mode.value != vid_realmode) |
||
2378 | { |
||
2379 | VID_SetMode ((int)vid_mode.value, vid_curpal); |
||
2380 | Cvar_SetValue ("vid_mode", (float)vid_modenum); |
||
2381 | // so if mode set fails, we don't keep on |
||
2382 | // trying to set that mode |
||
2383 | vid_realmode = vid_modenum; |
||
2384 | } |
||
2385 | } |
||
2386 | |||
2387 | // handle the mouse state when windowed if that's changed |
||
2388 | if (modestate == MS_WINDOWED) |
||
2389 | { |
||
2390 | if ((int)_windowed_mouse.value != windowed_mouse) |
||
2391 | { |
||
2392 | if (_windowed_mouse.value) |
||
2393 | { |
||
2394 | IN_ActivateMouse (); |
||
2395 | IN_HideMouse (); |
||
2396 | } |
||
2397 | else |
||
2398 | { |
||
2399 | IN_DeactivateMouse (); |
||
2400 | IN_ShowMouse (); |
||
2401 | } |
||
2402 | |||
2403 | windowed_mouse = (int)_windowed_mouse.value; |
||
2404 | } |
||
2405 | } |
||
2406 | } |
||
2407 | |||
2408 | |||
2409 | /* |
||
2410 | ================ |
||
2411 | D_BeginDirectRect |
||
2412 | ================ |
||
2413 | */ |
||
2414 | void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) |
||
2415 | { |
||
2416 | int i, j, reps, repshift; |
||
2417 | vrect_t rect; |
||
2418 | |||
2419 | if (!vid_initialized) |
||
2420 | return; |
||
2421 | |||
2422 | if (vid.aspect > 1.5) |
||
2423 | { |
||
2424 | reps = 2; |
||
2425 | repshift = 1; |
||
2426 | } |
||
2427 | else |
||
2428 | { |
||
2429 | reps = 1; |
||
2430 | repshift = 0; |
||
2431 | } |
||
2432 | |||
2433 | if (vid.numpages == 1) |
||
2434 | { |
||
2435 | VID_LockBuffer (); |
||
2436 | |||
2437 | if (!vid.direct) |
||
2438 | Sys_Error ("NULL vid.direct pointer"); |
||
2439 | |||
2440 | for (i=0 ; i<(height << repshift) ; i += reps) |
||
2441 | { |
||
2442 | for (j=0 ; j |
||
2443 | { |
||
2444 | memcpy (&backingbuf[(i + j) * 24], |
||
2445 | vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes, |
||
2446 | width); |
||
2447 | memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes, |
||
2448 | &pbitmap[(i >> repshift) * width], |
||
2449 | width); |
||
2450 | } |
||
2451 | } |
||
2452 | |||
2453 | VID_UnlockBuffer (); |
||
2454 | |||
2455 | rect.x = x; |
||
2456 | rect.y = y; |
||
2457 | rect.width = width; |
||
2458 | rect.height = height << repshift; |
||
2459 | rect.pnext = NULL; |
||
2460 | |||
2461 | FlipScreen (&rect); |
||
2462 | } |
||
2463 | else |
||
2464 | { |
||
2465 | // unlock if locked |
||
2466 | if (lockcount > 0) |
||
2467 | MGL_endDirectAccess(); |
||
2468 | |||
2469 | // set the active page to the displayed page |
||
2470 | MGL_setActivePage (mgldc, vPage); |
||
2471 | |||
2472 | // lock the screen |
||
2473 | MGL_beginDirectAccess (); |
||
2474 | |||
2475 | // save from and draw to screen |
||
2476 | for (i=0 ; i<(height << repshift) ; i += reps) |
||
2477 | { |
||
2478 | for (j=0 ; j |
||
2479 | { |
||
2480 | memcpy (&backingbuf[(i + j) * 24], |
||
2481 | (byte *)mgldc->surface + x + |
||
2482 | ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, |
||
2483 | width); |
||
2484 | memcpy ((byte *)mgldc->surface + x + |
||
2485 | ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, |
||
2486 | &pbitmap[(i >> repshift) * width], |
||
2487 | width); |
||
2488 | } |
||
2489 | } |
||
2490 | |||
2491 | // unlock the screen |
||
2492 | MGL_endDirectAccess (); |
||
2493 | |||
2494 | // restore the original active page |
||
2495 | MGL_setActivePage (mgldc, aPage); |
||
2496 | |||
2497 | // relock the screen if it was locked |
||
2498 | if (lockcount > 0) |
||
2499 | MGL_beginDirectAccess(); |
||
2500 | } |
||
2501 | } |
||
2502 | |||
2503 | |||
2504 | /* |
||
2505 | ================ |
||
2506 | D_EndDirectRect |
||
2507 | ================ |
||
2508 | */ |
||
2509 | void D_EndDirectRect (int x, int y, int width, int height) |
||
2510 | { |
||
2511 | int i, j, reps, repshift; |
||
2512 | vrect_t rect; |
||
2513 | |||
2514 | if (!vid_initialized) |
||
2515 | return; |
||
2516 | |||
2517 | if (vid.aspect > 1.5) |
||
2518 | { |
||
2519 | reps = 2; |
||
2520 | repshift = 1; |
||
2521 | } |
||
2522 | else |
||
2523 | { |
||
2524 | reps = 1; |
||
2525 | repshift = 0; |
||
2526 | } |
||
2527 | |||
2528 | if (vid.numpages == 1) |
||
2529 | { |
||
2530 | VID_LockBuffer (); |
||
2531 | |||
2532 | if (!vid.direct) |
||
2533 | Sys_Error ("NULL vid.direct pointer"); |
||
2534 | |||
2535 | for (i=0 ; i<(height << repshift) ; i += reps) |
||
2536 | { |
||
2537 | for (j=0 ; j |
||
2538 | { |
||
2539 | memcpy (vid.direct + x + ((y << repshift) + i + j) * vid.rowbytes, |
||
2540 | &backingbuf[(i + j) * 24], |
||
2541 | width); |
||
2542 | } |
||
2543 | } |
||
2544 | |||
2545 | VID_UnlockBuffer (); |
||
2546 | |||
2547 | rect.x = x; |
||
2548 | rect.y = y; |
||
2549 | rect.width = width; |
||
2550 | rect.height = height << repshift; |
||
2551 | rect.pnext = NULL; |
||
2552 | |||
2553 | FlipScreen (&rect); |
||
2554 | } |
||
2555 | else |
||
2556 | { |
||
2557 | // unlock if locked |
||
2558 | if (lockcount > 0) |
||
2559 | MGL_endDirectAccess(); |
||
2560 | |||
2561 | // set the active page to the displayed page |
||
2562 | MGL_setActivePage (mgldc, vPage); |
||
2563 | |||
2564 | // lock the screen |
||
2565 | MGL_beginDirectAccess (); |
||
2566 | |||
2567 | // restore to the screen |
||
2568 | for (i=0 ; i<(height << repshift) ; i += reps) |
||
2569 | { |
||
2570 | for (j=0 ; j |
||
2571 | { |
||
2572 | memcpy ((byte *)mgldc->surface + x + |
||
2573 | ((y << repshift) + i + j) * mgldc->mi.bytesPerLine, |
||
2574 | &backingbuf[(i + j) * 24], |
||
2575 | width); |
||
2576 | } |
||
2577 | } |
||
2578 | |||
2579 | // unlock the screen |
||
2580 | MGL_endDirectAccess (); |
||
2581 | |||
2582 | // restore the original active page |
||
2583 | MGL_setActivePage (mgldc, aPage); |
||
2584 | |||
2585 | // relock the screen if it was locked |
||
2586 | if (lockcount > 0) |
||
2587 | MGL_beginDirectAccess(); |
||
2588 | } |
||
2589 | } |
||
2590 | |||
2591 | |||
2592 | //========================================================================== |
||
2593 | |||
2594 | byte scantokey[128] = |
||
2595 | { |
||
2596 | // 0 1 2 3 4 5 6 7 |
||
2597 | // 8 9 A B C D E F |
||
2598 | |||
2599 | '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0 |
||
2600 | 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', |
||
2601 | 'o', 'p', '[', ']', 13 , K_CTRL,'a', 's', // 1 |
||
2602 | 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', |
||
2603 | '\'' , '`', K_SHIFT,'\\', 'z', 'x', 'c', 'v', // 2 |
||
2604 | 'b', 'n', 'm', ',', '.', '/', K_SHIFT,'*', |
||
2605 | K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 |
||
2606 | K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0 , K_HOME, |
||
2607 | K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4 |
||
2608 | K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, |
||
2609 | K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 |
||
2610 | |||
2611 | |||
2612 | |||
2613 | |||
2614 | }; |
||
2615 | |||
2616 | /* |
||
2617 | ======= |
||
2618 | MapKey |
||
2619 | |||
2620 | Map from windows to quake keynums |
||
2621 | ======= |
||
2622 | */ |
||
2623 | int MapKey (int key) |
||
2624 | { |
||
2625 | key = (key>>16)&255; |
||
2626 | if (key > 127) |
||
2627 | return 0; |
||
2628 | |||
2629 | return scantokey[key]; |
||
2630 | } |
||
2631 | |||
2632 | void AppActivate(BOOL fActive, BOOL minimize) |
||
2633 | /**************************************************************************** |
||
2634 | * |
||
2635 | * Function: AppActivate |
||
2636 | * Parameters: fActive - True if app is activating |
||
2637 | * |
||
2638 | * Description: If the application is activating, then swap the system |
||
2639 | * into SYSPAL_NOSTATIC mode so that our palettes will display |
||
2640 | * correctly. |
||
2641 | * |
||
2642 | ****************************************************************************/ |
||
2643 | { |
||
2644 | HDC hdc; |
||
2645 | int i, t; |
||
2646 | static BOOL sound_active; |
||
2647 | |||
2648 | ActiveApp = fActive; |
||
2649 | |||
2650 | // messy, but it seems to work |
||
2651 | if (vid_fulldib_on_focus_mode) |
||
2652 | { |
||
2653 | Minimized = minimize; |
||
2654 | |||
2655 | if (Minimized) |
||
2656 | ActiveApp = false; |
||
2657 | } |
||
2658 | |||
2659 | MGL_appActivate(windc, ActiveApp); |
||
2660 | |||
2661 | if (vid_initialized) |
||
2662 | { |
||
2663 | // yield the palette if we're losing the focus |
||
2664 | hdc = GetDC(NULL); |
||
2665 | |||
2666 | if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) |
||
2667 | { |
||
2668 | if (ActiveApp) |
||
2669 | { |
||
2670 | if ((modestate == MS_WINDOWED) || (modestate == MS_FULLDIB)) |
||
2671 | { |
||
2672 | if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC) |
||
2673 | { |
||
2674 | // switch to SYSPAL_NOSTATIC and remap the colors |
||
2675 | SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); |
||
2676 | syscolchg = true; |
||
2677 | pal_is_nostatic = true; |
||
2678 | } |
||
2679 | } |
||
2680 | } |
||
2681 | else if (pal_is_nostatic) |
||
2682 | { |
||
2683 | if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC) |
||
2684 | { |
||
2685 | // switch back to SYSPAL_STATIC and the old mapping |
||
2686 | SetSystemPaletteUse(hdc, SYSPAL_STATIC); |
||
2687 | syscolchg = true; |
||
2688 | } |
||
2689 | |||
2690 | pal_is_nostatic = false; |
||
2691 | } |
||
2692 | } |
||
2693 | |||
2694 | if (!Minimized) |
||
2695 | VID_SetPalette (vid_curpal); |
||
2696 | |||
2697 | scr_fullupdate = 0; |
||
2698 | |||
2699 | ReleaseDC(NULL,hdc); |
||
2700 | } |
||
2701 | |||
2702 | // enable/disable sound on focus gain/loss |
||
2703 | if (!ActiveApp && sound_active) |
||
2704 | { |
||
2705 | S_BlockSound (); |
||
2706 | S_ClearBuffer (); |
||
2707 | sound_active = false; |
||
2708 | } |
||
2709 | else if (ActiveApp && !sound_active) |
||
2710 | { |
||
2711 | S_UnblockSound (); |
||
2712 | S_ClearBuffer (); |
||
2713 | sound_active = true; |
||
2714 | } |
||
2715 | |||
2716 | // minimize/restore fulldib windows/mouse-capture normal windows on demand |
||
2717 | if (!in_mode_set) |
||
2718 | { |
||
2719 | if (ActiveApp) |
||
2720 | { |
||
2721 | if (vid_fulldib_on_focus_mode) |
||
2722 | { |
||
2723 | if (vid_initialized) |
||
2724 | { |
||
2725 | msg_suppress_1 = true; // don't want to see normal mode set message |
||
2726 | VID_SetMode (vid_fulldib_on_focus_mode, vid_curpal); |
||
2727 | msg_suppress_1 = false; |
||
2728 | |||
2729 | t = in_mode_set; |
||
2730 | in_mode_set = true; |
||
2731 | AppActivate (true, false); |
||
2732 | in_mode_set = t; |
||
2733 | } |
||
2734 | |||
2735 | IN_ActivateMouse (); |
||
2736 | IN_HideMouse (); |
||
2737 | } |
||
2738 | else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) |
||
2739 | { |
||
2740 | IN_ActivateMouse (); |
||
2741 | IN_HideMouse (); |
||
2742 | } |
||
2743 | } |
||
2744 | |||
2745 | if (!ActiveApp) |
||
2746 | { |
||
2747 | if (modestate == MS_FULLDIB) |
||
2748 | { |
||
2749 | if (vid_initialized) |
||
2750 | { |
||
2751 | force_minimized = true; |
||
2752 | i = vid_fulldib_on_focus_mode; |
||
2753 | msg_suppress_1 = true; // don't want to see normal mode set message |
||
2754 | VID_SetMode (windowed_default, vid_curpal); |
||
2755 | msg_suppress_1 = false; |
||
2756 | vid_fulldib_on_focus_mode = i; |
||
2757 | force_minimized = false; |
||
2758 | |||
2759 | // we never seem to get WM_ACTIVATE inactive from this mode set, so we'll |
||
2760 | // do it manually |
||
2761 | t = in_mode_set; |
||
2762 | in_mode_set = true; |
||
2763 | AppActivate (false, true); |
||
2764 | in_mode_set = t; |
||
2765 | } |
||
2766 | |||
2767 | IN_DeactivateMouse (); |
||
2768 | IN_ShowMouse (); |
||
2769 | } |
||
2770 | else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) |
||
2771 | { |
||
2772 | IN_DeactivateMouse (); |
||
2773 | IN_ShowMouse (); |
||
2774 | } |
||
2775 | } |
||
2776 | } |
||
2777 | } |
||
2778 | |||
2779 | |||
2780 | /* |
||
2781 | ================ |
||
2782 | VID_HandlePause |
||
2783 | ================ |
||
2784 | */ |
||
2785 | void VID_HandlePause (qboolean pause) |
||
2786 | { |
||
2787 | |||
2788 | if ((modestate == MS_WINDOWED) && _windowed_mouse.value) |
||
2789 | { |
||
2790 | if (pause) |
||
2791 | { |
||
2792 | IN_DeactivateMouse (); |
||
2793 | IN_ShowMouse (); |
||
2794 | } |
||
2795 | else |
||
2796 | { |
||
2797 | IN_ActivateMouse (); |
||
2798 | IN_HideMouse (); |
||
2799 | } |
||
2800 | } |
||
2801 | } |
||
2802 | |||
2803 | |||
2804 | /* |
||
2805 | =================================================================== |
||
2806 | |||
2807 | MAIN WINDOW |
||
2808 | |||
2809 | =================================================================== |
||
2810 | */ |
||
2811 | |||
2812 | LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); |
||
2813 | |||
2814 | /* main window procedure */ |
||
2815 | LONG WINAPI MainWndProc ( |
||
2816 | HWND hWnd, |
||
2817 | UINT uMsg, |
||
2818 | WPARAM wParam, |
||
2819 | LPARAM lParam) |
||
2820 | { |
||
2821 | LONG lRet = 0; |
||
2822 | int fwKeys, xPos, yPos, fActive, fMinimized, temp; |
||
2823 | HDC hdc; |
||
2824 | PAINTSTRUCT ps; |
||
2825 | static int recursiveflag; |
||
2826 | |||
2827 | switch (uMsg) |
||
2828 | { |
||
2829 | case WM_CREATE: |
||
2830 | break; |
||
2831 | |||
2832 | case WM_SYSCOMMAND: |
||
2833 | |||
2834 | // Check for maximize being hit |
||
2835 | switch (wParam & ~0x0F) |
||
2836 | { |
||
2837 | case SC_MAXIMIZE: |
||
2838 | // if minimized, bring up as a window before going fullscreen, |
||
2839 | // so MGL will have the right state to restore |
||
2840 | if (Minimized) |
||
2841 | { |
||
2842 | force_mode_set = true; |
||
2843 | VID_SetMode (vid_modenum, vid_curpal); |
||
2844 | force_mode_set = false; |
||
2845 | } |
||
2846 | |||
2847 | VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal); |
||
2848 | break; |
||
2849 | |||
2850 | case SC_SCREENSAVE: |
||
2851 | case SC_MONITORPOWER: |
||
2852 | if (modestate != MS_WINDOWED) |
||
2853 | { |
||
2854 | // don't call DefWindowProc() because we don't want to start |
||
2855 | // the screen saver fullscreen |
||
2856 | break; |
||
2857 | } |
||
2858 | |||
2859 | // fall through windowed and allow the screen saver to start |
||
2860 | |||
2861 | default: |
||
2862 | if (!in_mode_set) |
||
2863 | { |
||
2864 | S_BlockSound (); |
||
2865 | S_ClearBuffer (); |
||
2866 | } |
||
2867 | |||
2868 | lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); |
||
2869 | |||
2870 | if (!in_mode_set) |
||
2871 | { |
||
2872 | S_UnblockSound (); |
||
2873 | } |
||
2874 | } |
||
2875 | break; |
||
2876 | |||
2877 | case WM_MOVE: |
||
2878 | window_x = (int) LOWORD(lParam); |
||
2879 | window_y = (int) HIWORD(lParam); |
||
2880 | VID_UpdateWindowStatus (); |
||
2881 | |||
2882 | if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized) |
||
2883 | VID_RememberWindowPos (); |
||
2884 | |||
2885 | break; |
||
2886 | |||
2887 | case WM_SIZE: |
||
2888 | Minimized = false; |
||
2889 | |||
2890 | if (!(wParam & SIZE_RESTORED)) |
||
2891 | { |
||
2892 | if (wParam & SIZE_MINIMIZED) |
||
2893 | Minimized = true; |
||
2894 | } |
||
2895 | break; |
||
2896 | |||
2897 | case WM_SYSCHAR: |
||
2898 | // keep Alt-Space from happening |
||
2899 | break; |
||
2900 | |||
2901 | case WM_ACTIVATE: |
||
2902 | fActive = LOWORD(wParam); |
||
2903 | fMinimized = (BOOL) HIWORD(wParam); |
||
2904 | AppActivate(!(fActive == WA_INACTIVE), fMinimized); |
||
2905 | |||
2906 | // fix the leftover Alt from any Alt-Tab or the like that switched us away |
||
2907 | ClearAllStates (); |
||
2908 | |||
2909 | if (!in_mode_set) |
||
2910 | { |
||
2911 | if (windc) |
||
2912 | MGL_activatePalette(windc,true); |
||
2913 | |||
2914 | VID_SetPalette(vid_curpal); |
||
2915 | } |
||
2916 | |||
2917 | break; |
||
2918 | |||
2919 | case WM_PAINT: |
||
2920 | hdc = BeginPaint(hWnd, &ps); |
||
2921 | |||
2922 | if (!in_mode_set && host_initialized) |
||
2923 | SCR_UpdateWholeScreen (); |
||
2924 | |||
2925 | EndPaint(hWnd, &ps); |
||
2926 | break; |
||
2927 | |||
2928 | case WM_KEYDOWN: |
||
2929 | case WM_SYSKEYDOWN: |
||
2930 | if (!in_mode_set) |
||
2931 | Key_Event (MapKey(lParam), true); |
||
2932 | break; |
||
2933 | |||
2934 | case WM_KEYUP: |
||
2935 | case WM_SYSKEYUP: |
||
2936 | if (!in_mode_set) |
||
2937 | Key_Event (MapKey(lParam), false); |
||
2938 | break; |
||
2939 | |||
2940 | // this is complicated because Win32 seems to pack multiple mouse events into |
||
2941 | // one update sometimes, so we always check all states and look for events |
||
2942 | case WM_LBUTTONDOWN: |
||
2943 | case WM_LBUTTONUP: |
||
2944 | case WM_RBUTTONDOWN: |
||
2945 | case WM_RBUTTONUP: |
||
2946 | case WM_MBUTTONDOWN: |
||
2947 | case WM_MBUTTONUP: |
||
2948 | case WM_MOUSEMOVE: |
||
2949 | if (!in_mode_set) |
||
2950 | { |
||
2951 | temp = 0; |
||
2952 | |||
2953 | if (wParam & MK_LBUTTON) |
||
2954 | temp |= 1; |
||
2955 | |||
2956 | if (wParam & MK_RBUTTON) |
||
2957 | temp |= 2; |
||
2958 | |||
2959 | if (wParam & MK_MBUTTON) |
||
2960 | temp |= 4; |
||
2961 | |||
2962 | IN_MouseEvent (temp); |
||
2963 | } |
||
2964 | break; |
||
2965 | |||
2966 | // JACK: This is the mouse wheel with the Intellimouse |
||
2967 | // Its delta is either positive or neg, and we generate the proper |
||
2968 | // Event. |
||
2969 | case WM_MOUSEWHEEL: |
||
2970 | if ((short) HIWORD(wParam) > 0) { |
||
2971 | Key_Event(K_MWHEELUP, true); |
||
2972 | Key_Event(K_MWHEELUP, false); |
||
2973 | } else { |
||
2974 | Key_Event(K_MWHEELDOWN, true); |
||
2975 | Key_Event(K_MWHEELDOWN, false); |
||
2976 | } |
||
2977 | break; |
||
2978 | // KJB: Added these new palette functions |
||
2979 | case WM_PALETTECHANGED: |
||
2980 | if ((HWND)wParam == hWnd) |
||
2981 | break; |
||
2982 | /* Fall through to WM_QUERYNEWPALETTE */ |
||
2983 | case WM_QUERYNEWPALETTE: |
||
2984 | hdc = GetDC(NULL); |
||
2985 | |||
2986 | if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) |
||
2987 | vid_palettized = true; |
||
2988 | else |
||
2989 | vid_palettized = false; |
||
2990 | |||
2991 | ReleaseDC(NULL,hdc); |
||
2992 | |||
2993 | scr_fullupdate = 0; |
||
2994 | |||
2995 | if (vid_initialized && !in_mode_set && windc && MGL_activatePalette(windc,false) && !Minimized) |
||
2996 | { |
||
2997 | VID_SetPalette (vid_curpal); |
||
2998 | InvalidateRect (mainwindow, NULL, false); |
||
2999 | |||
3000 | // specifically required if WM_QUERYNEWPALETTE realizes a new palette |
||
3001 | lRet = TRUE; |
||
3002 | } |
||
3003 | break; |
||
3004 | |||
3005 | case WM_DISPLAYCHANGE: |
||
3006 | if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode) |
||
3007 | { |
||
3008 | force_mode_set = true; |
||
3009 | VID_SetMode (vid_modenum, vid_curpal); |
||
3010 | force_mode_set = false; |
||
3011 | } |
||
3012 | break; |
||
3013 | |||
3014 | case WM_CLOSE: |
||
3015 | // this causes Close in the right-click task bar menu not to work, but right |
||
3016 | // now bad things happen if Close is handled in that case (garbage and a |
||
3017 | // crash on Win95) |
||
3018 | if (!in_mode_set) |
||
3019 | { |
||
3020 | if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", |
||
3021 | MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) |
||
3022 | { |
||
3023 | Sys_Quit (); |
||
3024 | } |
||
3025 | } |
||
3026 | break; |
||
3027 | |||
3028 | case MM_MCINOTIFY: |
||
3029 | lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); |
||
3030 | break; |
||
3031 | |||
3032 | default: |
||
3033 | /* pass all unhandled messages to DefWindowProc */ |
||
3034 | lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); |
||
3035 | break; |
||
3036 | } |
||
3037 | |||
3038 | /* return 0 if handled message, 1 if not */ |
||
3039 | return lRet; |
||
3040 | } |
||
3041 | |||
3042 | |||
3043 | extern void M_Menu_Options_f (void); |
||
3044 | extern void M_Print (int cx, int cy, char *str); |
||
3045 | extern void M_PrintWhite (int cx, int cy, char *str); |
||
3046 | extern void M_DrawCharacter (int cx, int line, int num); |
||
3047 | extern void M_DrawTransPic (int x, int y, qpic_t *pic); |
||
3048 | extern void M_DrawPic (int x, int y, qpic_t *pic); |
||
3049 | |||
3050 | static int vid_line, vid_wmodes; |
||
3051 | |||
3052 | typedef struct |
||
3053 | { |
||
3054 | int modenum; |
||
3055 | char *desc; |
||
3056 | int iscur; |
||
3057 | int ismode13; |
||
3058 | int width; |
||
3059 | } modedesc_t; |
||
3060 | |||
3061 | #define MAX_COLUMN_SIZE 5 |
||
3062 | #define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) |
||
3063 | #define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) |
||
3064 | |||
3065 | static modedesc_t modedescs[MAX_MODEDESCS]; |
||
3066 | |||
3067 | /* |
||
3068 | ================ |
||
3069 | VID_MenuDraw |
||
3070 | ================ |
||
3071 | */ |
||
3072 | void VID_MenuDraw (void) |
||
3073 | { |
||
3074 | qpic_t *p; |
||
3075 | char *ptr; |
||
3076 | int lnummodes, i, j, k, column, row, dup, dupmode; |
||
3077 | char temp[100]; |
||
3078 | vmode_t *pv; |
||
3079 | modedesc_t tmodedesc; |
||
3080 | |||
3081 | p = Draw_CachePic ("gfx/vidmodes.lmp"); |
||
3082 | M_DrawPic ( (320-p->width)/2, 4, p); |
||
3083 | |||
3084 | for (i=0 ; i<3 ; i++) |
||
3085 | { |
||
3086 | ptr = VID_GetModeDescriptionMemCheck (i); |
||
3087 | modedescs[i].modenum = modelist[i].modenum; |
||
3088 | modedescs[i].desc = ptr; |
||
3089 | modedescs[i].ismode13 = 0; |
||
3090 | modedescs[i].iscur = 0; |
||
3091 | |||
3092 | if (vid_modenum == i) |
||
3093 | modedescs[i].iscur = 1; |
||
3094 | } |
||
3095 | |||
3096 | vid_wmodes = 3; |
||
3097 | lnummodes = VID_NumModes (); |
||
3098 | |||
3099 | for (i=3 ; i |
||
3100 | { |
||
3101 | ptr = VID_GetModeDescriptionMemCheck (i); |
||
3102 | pv = VID_GetModePtr (i); |
||
3103 | |||
3104 | // we only have room for 15 fullscreen modes, so don't allow |
||
3105 | // 360-wide modes, because if there are 5 320-wide modes and |
||
3106 | // 5 360-wide modes, we'll run out of space |
||
3107 | if (ptr && ((pv->width != 360) || COM_CheckParm("-allow360"))) |
||
3108 | { |
||
3109 | dup = 0; |
||
3110 | |||
3111 | for (j=3 ; j |
||
3112 | { |
||
3113 | if (!strcmp (modedescs[j].desc, ptr)) |
||
3114 | { |
||
3115 | dup = 1; |
||
3116 | dupmode = j; |
||
3117 | break; |
||
3118 | } |
||
3119 | } |
||
3120 | |||
3121 | if (dup || (vid_wmodes < MAX_MODEDESCS)) |
||
3122 | { |
||
3123 | if (!dup || !modedescs[dupmode].ismode13 || COM_CheckParm("-noforcevga")) |
||
3124 | { |
||
3125 | if (dup) |
||
3126 | { |
||
3127 | k = dupmode; |
||
3128 | } |
||
3129 | else |
||
3130 | { |
||
3131 | k = vid_wmodes; |
||
3132 | } |
||
3133 | |||
3134 | modedescs[k].modenum = i; |
||
3135 | modedescs[k].desc = ptr; |
||
3136 | modedescs[k].ismode13 = pv->mode13; |
||
3137 | modedescs[k].iscur = 0; |
||
3138 | modedescs[k].width = pv->width; |
||
3139 | |||
3140 | if (i == vid_modenum) |
||
3141 | modedescs[k].iscur = 1; |
||
3142 | |||
3143 | if (!dup) |
||
3144 | vid_wmodes++; |
||
3145 | } |
||
3146 | } |
||
3147 | } |
||
3148 | } |
||
3149 | |||
3150 | // sort the modes on width (to handle picking up oddball dibonly modes |
||
3151 | // after all the others) |
||
3152 | for (i=3 ; i<(vid_wmodes-1) ; i++) |
||
3153 | { |
||
3154 | for (j=(i+1) ; j |
||
3155 | { |
||
3156 | if (modedescs[i].width > modedescs[j].width) |
||
3157 | { |
||
3158 | tmodedesc = modedescs[i]; |
||
3159 | modedescs[i] = modedescs[j]; |
||
3160 | modedescs[j] = tmodedesc; |
||
3161 | } |
||
3162 | } |
||
3163 | } |
||
3164 | |||
3165 | |||
3166 | M_Print (13*8, 36, "Windowed Modes"); |
||
3167 | |||
3168 | column = 16; |
||
3169 | row = 36+2*8; |
||
3170 | |||
3171 | for (i=0 ; i<3; i++) |
||
3172 | { |
||
3173 | if (modedescs[i].iscur) |
||
3174 | M_PrintWhite (column, row, modedescs[i].desc); |
||
3175 | else |
||
3176 | M_Print (column, row, modedescs[i].desc); |
||
3177 | |||
3178 | column += 13*8; |
||
3179 | } |
||
3180 | |||
3181 | if (vid_wmodes > 3) |
||
3182 | { |
||
3183 | M_Print (12*8, 36+4*8, "Fullscreen Modes"); |
||
3184 | |||
3185 | column = 16; |
||
3186 | row = 36+6*8; |
||
3187 | |||
3188 | for (i=3 ; i |
||
3189 | { |
||
3190 | if (modedescs[i].iscur) |
||
3191 | M_PrintWhite (column, row, modedescs[i].desc); |
||
3192 | else |
||
3193 | M_Print (column, row, modedescs[i].desc); |
||
3194 | |||
3195 | column += 13*8; |
||
3196 | |||
3197 | if (((i - 3) % VID_ROW_SIZE) == (VID_ROW_SIZE - 1)) |
||
3198 | { |
||
3199 | column = 16; |
||
3200 | row += 8; |
||
3201 | } |
||
3202 | } |
||
3203 | } |
||
3204 | |||
3205 | // line cursor |
||
3206 | if (vid_testingmode) |
||
3207 | { |
||
3208 | sprintf (temp, "TESTING %s", |
||
3209 | modedescs[vid_line].desc); |
||
3210 | M_Print (13*8, 36 + MODE_AREA_HEIGHT * 8 + 8*4, temp); |
||
3211 | M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, |
||
3212 | "Please wait 5 seconds..."); |
||
3213 | } |
||
3214 | else |
||
3215 | { |
||
3216 | M_Print (9*8, 36 + MODE_AREA_HEIGHT * 8 + 8, |
||
3217 | "Press Enter to set mode"); |
||
3218 | M_Print (6*8, 36 + MODE_AREA_HEIGHT * 8 + 8*3, |
||
3219 | "T to test mode for 5 seconds"); |
||
3220 | ptr = VID_GetModeDescription2 (vid_modenum); |
||
3221 | |||
3222 | if (ptr) |
||
3223 | { |
||
3224 | sprintf (temp, "D to set default: %s", ptr); |
||
3225 | M_Print (2*8, 36 + MODE_AREA_HEIGHT * 8 + 8*5, temp); |
||
3226 | } |
||
3227 | |||
3228 | ptr = VID_GetModeDescription2 ((int)_vid_default_mode_win.value); |
||
3229 | |||
3230 | if (ptr) |
||
3231 | { |
||
3232 | sprintf (temp, "Current default: %s", ptr); |
||
3233 | M_Print (3*8, 36 + MODE_AREA_HEIGHT * 8 + 8*6, temp); |
||
3234 | } |
||
3235 | |||
3236 | M_Print (15*8, 36 + MODE_AREA_HEIGHT * 8 + 8*8, |
||
3237 | "Esc to exit"); |
||
3238 | |||
3239 | row = 36 + 2*8 + (vid_line / VID_ROW_SIZE) * 8; |
||
3240 | column = 8 + (vid_line % VID_ROW_SIZE) * 13*8; |
||
3241 | |||
3242 | if (vid_line >= 3) |
||
3243 | row += 3*8; |
||
3244 | |||
3245 | M_DrawCharacter (column, row, 12+((int)(realtime*4)&1)); |
||
3246 | } |
||
3247 | } |
||
3248 | |||
3249 | |||
3250 | /* |
||
3251 | ================ |
||
3252 | VID_MenuKey |
||
3253 | ================ |
||
3254 | */ |
||
3255 | void VID_MenuKey (int key) |
||
3256 | { |
||
3257 | if (vid_testingmode) |
||
3258 | return; |
||
3259 | |||
3260 | switch (key) |
||
3261 | { |
||
3262 | case K_ESCAPE: |
||
3263 | S_LocalSound ("misc/menu1.wav"); |
||
3264 | M_Menu_Options_f (); |
||
3265 | break; |
||
3266 | |||
3267 | case K_LEFTARROW: |
||
3268 | S_LocalSound ("misc/menu1.wav"); |
||
3269 | vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + |
||
3270 | ((vid_line + 2) % VID_ROW_SIZE); |
||
3271 | |||
3272 | if (vid_line >= vid_wmodes) |
||
3273 | vid_line = vid_wmodes - 1; |
||
3274 | break; |
||
3275 | |||
3276 | case K_RIGHTARROW: |
||
3277 | S_LocalSound ("misc/menu1.wav"); |
||
3278 | vid_line = ((vid_line / VID_ROW_SIZE) * VID_ROW_SIZE) + |
||
3279 | ((vid_line + 4) % VID_ROW_SIZE); |
||
3280 | |||
3281 | if (vid_line >= vid_wmodes) |
||
3282 | vid_line = (vid_line / VID_ROW_SIZE) * VID_ROW_SIZE; |
||
3283 | break; |
||
3284 | |||
3285 | case K_UPARROW: |
||
3286 | S_LocalSound ("misc/menu1.wav"); |
||
3287 | vid_line -= VID_ROW_SIZE; |
||
3288 | |||
3289 | if (vid_line < 0) |
||
3290 | { |
||
3291 | vid_line += ((vid_wmodes + (VID_ROW_SIZE - 1)) / |
||
3292 | VID_ROW_SIZE) * VID_ROW_SIZE; |
||
3293 | |||
3294 | while (vid_line >= vid_wmodes) |
||
3295 | vid_line -= VID_ROW_SIZE; |
||
3296 | } |
||
3297 | break; |
||
3298 | |||
3299 | case K_DOWNARROW: |
||
3300 | S_LocalSound ("misc/menu1.wav"); |
||
3301 | vid_line += VID_ROW_SIZE; |
||
3302 | |||
3303 | if (vid_line >= vid_wmodes) |
||
3304 | { |
||
3305 | vid_line -= ((vid_wmodes + (VID_ROW_SIZE - 1)) / |
||
3306 | VID_ROW_SIZE) * VID_ROW_SIZE; |
||
3307 | |||
3308 | while (vid_line < 0) |
||
3309 | vid_line += VID_ROW_SIZE; |
||
3310 | } |
||
3311 | break; |
||
3312 | |||
3313 | case K_ENTER: |
||
3314 | S_LocalSound ("misc/menu1.wav"); |
||
3315 | VID_SetMode (modedescs[vid_line].modenum, vid_curpal); |
||
3316 | break; |
||
3317 | |||
3318 | case 'T': |
||
3319 | case 't': |
||
3320 | S_LocalSound ("misc/menu1.wav"); |
||
3321 | // have to set this before setting the mode because WM_PAINT |
||
3322 | // happens during the mode set and does a VID_Update, which |
||
3323 | // checks vid_testingmode |
||
3324 | vid_testingmode = 1; |
||
3325 | vid_testendtime = realtime + 5.0; |
||
3326 | |||
3327 | if (!VID_SetMode (modedescs[vid_line].modenum, vid_curpal)) |
||
3328 | { |
||
3329 | vid_testingmode = 0; |
||
3330 | } |
||
3331 | break; |
||
3332 | |||
3333 | case 'D': |
||
3334 | case 'd': |
||
3335 | S_LocalSound ("misc/menu1.wav"); |
||
3336 | firstupdate = 0; |
||
3337 | Cvar_SetValue ("_vid_default_mode_win", vid_modenum); |
||
3338 | break; |
||
3339 | |||
3340 | default: |
||
3341 | break; |
||
3342 | } |
||
3343 | }>>3;>(vid_wmodes-1)>>3>><>><>(height>><>><>><>(height>><>><>><>(height>><>><>><>><>(height>>>><>><>><>><>><>><>><>><>(VID_CBITS+8))><(VID_CBITS+8))>(1<<(VID_CBITS+8))>>256>>>=><=>><>><>>><>><>><> |