1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, 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 40typedef 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 52typedef struct { 53 int width; 54 int height; 55} lmode_t; 56 57lmode_t lowresmodes[] = { 58 {320, 200}, 59 {320, 240}, 60 {400, 300}, 61 {512, 384}, 62}; 63 64const char *gl_vendor; 65const char *gl_renderer; 66const char *gl_version; 67const char *gl_extensions; 68 69qboolean DDActive; 70qboolean scr_skipupdate; 71 72static vmode_t modelist[MAX_MODE_LIST]; 73static int nummodes; 74static vmode_t *pcurrentmode; 75static vmode_t badmode; 76 77static DEVMODE gdevmode; 78static qboolean vid_initialized = false; 79static qboolean windowed, leavecurrentmode; 80static qboolean vid_canalttab = false; 81static qboolean vid_wassuspended = false; 82static int windowed_mouse; 83extern qboolean mouseactive; // from in_win.c 84static HICON hIcon; 85 86int DIBWidth, DIBHeight; 87RECT WindowRect; 88DWORD WindowStyle, ExWindowStyle; 89 90HWND mainwindow, dibwindow; 91 92int vid_modenum = NO_MODE; 93int vid_realmode; 94int vid_default = MODE_WINDOWED; 95static int windowed_default; 96unsigned char vid_curpal[256*3]; 97static qboolean fullsbardraw = false; 98 99static float vid_gamma = 1.0; 100 101HGLRC baseRC; 102HDC maindc; 103 104glvert_t glv; 105 106cvar_t gl_ztrick = {"gl_ztrick","1"}; 107 108HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); 109 110viddef_t vid; // global video state 111 112unsigned short d_8to16table[256]; 113unsigned d_8to24table[256]; 114unsigned char d_15to8table[65536]; 115 116float gldepthmin, gldepthmax; 117 118modestate_t modestate = MS_UNINIT; 119 120void VID_MenuDraw (void); 121void VID_MenuKey (int key); 122 123LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 124void AppActivate(BOOL fActive, BOOL minimize); 125char *VID_GetModeDescription (int mode); 126void ClearAllStates (void); 127void VID_UpdateWindowStatus (void); 128void GL_Init (void); 129 130PROC glArrayElementEXT; 131PROC glColorPointerEXT; 132PROC glTexCoordPointerEXT; 133PROC glVertexPointerEXT; 134 135typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*); 136lp3DFXFUNC glColorTableEXT; 137qboolean is8bit = false; 138qboolean isPermedia = false; 139qboolean gl_mtexable = false; 140 141//==================================== 142 143cvar_t vid_mode = {"vid_mode","0", false}; 144// Note that 0 is MODE_WINDOWED 145cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; 146// Note that 3 is MODE_FULLSCREEN_DEFAULT 147cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; 148cvar_t vid_wait = {"vid_wait","0"}; 149cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; 150cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; 151cvar_t vid_config_x = {"vid_config_x","800", true}; 152cvar_t vid_config_y = {"vid_config_y","600", true}; 153cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; 154cvar_t _windowed_mouse = {"_windowed_mouse","1", true}; 155 156int window_center_x, window_center_y, window_x, window_y, window_width, window_height; 157RECT window_rect; 158 159// direct draw software compatability stuff 160 161void VID_HandlePause (qboolean pause) 162{ 163} 164 165void VID_ForceLockState (int lk) 166{ 167} 168 169void VID_LockBuffer (void) 170{ 171} 172 173void VID_UnlockBuffer (void) 174{ 175} 176 177int VID_ForceUnlockedAndReturnState (void) 178{ 179 return 0; 180} 181 182void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) 183{ 184} 185 186void D_EndDirectRect (int x, int y, int width, int height) 187{ 188} 189 190 191void 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 206qboolean 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 284qboolean 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 373int 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================ 478VID_UpdateWindowStatus 479================ 480*/ 481void 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 497BINDTEXFUNCPTR bindTexFunc; 498 499#define TEXTURE_EXT_STRING "GL_EXT_texture_object" 500 501 502void 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 541void 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; 571int texture_mode = GL_LINEAR; 572//int texture_mode = GL_LINEAR_MIPMAP_NEAREST; 573//int texture_mode = GL_LINEAR_MIPMAP_LINEAR; 574 575int texture_extension_number = 1; 576 577#ifdef _WIN32 578void 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 588void CheckMultiTextureExtensions(void) 589{ 590 gl_mtexable = true; 591} 592#endif 593 594/* 595=============== 596GL_Init 597=============== 598*/ 599void 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================= 655GL_BeginRendering 656 657================= 658*/ 659void 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 674void 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 703void 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 763BOOL gammaworks; 764 765void 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 775void VID_SetDefaultMode (void) 776{ 777 IN_DeactivateMouse (); 778} 779 780 781void 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 814BOOL 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 855byte 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 877byte 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======= 902MapKey 903 904Map from windows to quake keynums 905======= 906*/ 907int 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 920MAIN WINDOW 921 922=================================================================== 923*/ 924 925/* 926================ 927ClearAllStates 928================ 929*/ 930void 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 944void 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 */ 1016LONG 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================= 1144VID_NumModes 1145================= 1146*/ 1147int VID_NumModes (void) 1148{ 1149 return nummodes; 1150} 1151 1152 1153/* 1154================= 1155VID_GetModePtr 1156================= 1157*/ 1158vmode_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================= 1170VID_GetModeDescription 1171================= 1172*/ 1173char *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 1201char *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================= 1237VID_DescribeCurrentMode_f 1238================= 1239*/ 1240void VID_DescribeCurrentMode_f (void) 1241{ 1242 Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); 1243} 1244 1245 1246/* 1247================= 1248VID_NumModes_f 1249================= 1250*/ 1251void 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================= 1263VID_DescribeMode_f 1264================= 1265*/ 1266void 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================= 1283VID_DescribeModes_f 1284================= 1285*/ 1286void 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 1308void 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================= 1362VID_InitFullDIB 1363================= 1364*/ 1365void 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 1506qboolean VID_Is8bit() { 1507 return is8bit; 1508} 1509 1510#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB 1511 1512void 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 1539static 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=================== 1570VID_Init 1571=================== 1572*/ 1573void 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 1838extern void M_Menu_Options_f (void); 1839extern void M_Print (int cx, int cy, char *str); 1840extern void M_PrintWhite (int cx, int cy, char *str); 1841extern void M_DrawCharacter (int cx, int line, int num); 1842extern void M_DrawTransPic (int x, int y, qpic_t *pic); 1843extern void M_DrawPic (int x, int y, qpic_t *pic); 1844 1845static int vid_line, vid_wmodes; 1846 1847typedef 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 1858static modedesc_t modedescs[MAX_MODEDESCS]; 1859 1860/* 1861================ 1862VID_MenuDraw 1863================ 1864*/ 1865void 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================ 1934VID_MenuKey 1935================ 1936*/ 1937void 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