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