|
|
1.1 root 1: /* 1.1.1.2 ! root 2: Copyright (C) 1997-2001 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: /* 1.1 root 21: ** RW_IMP.C 22: ** 23: ** This file contains ALL Win32 specific stuff having to do with the 24: ** software refresh. When a port is being made the following functions 25: ** must be implemented by the port: 26: ** 27: ** SWimp_EndFrame 28: ** SWimp_Init 29: ** SWimp_SetPalette 30: ** SWimp_Shutdown 31: */ 32: #include "..\ref_soft\r_local.h" 33: #include "rw_win.h" 34: #include "winquake.h" 35: 36: // Console variables that we need to access from this module 37: 38: swwstate_t sww_state; 39: 40: /* 41: ** VID_CreateWindow 42: */ 43: #define WINDOW_CLASS_NAME "Quake 2" 44: 45: void VID_CreateWindow( int width, int height, int stylebits ) 46: { 47: WNDCLASS wc; 48: RECT r; 49: cvar_t *vid_xpos, *vid_ypos, *vid_fullscreen; 50: int x, y, w, h; 51: int exstyle; 52: 53: vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0); 54: vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0); 55: vid_fullscreen = ri.Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE ); 56: 57: if ( vid_fullscreen->value ) 58: exstyle = WS_EX_TOPMOST; 59: else 60: exstyle = 0; 61: 62: /* Register the frame class */ 63: wc.style = 0; 64: wc.lpfnWndProc = (WNDPROC)sww_state.wndproc; 65: wc.cbClsExtra = 0; 66: wc.cbWndExtra = 0; 67: wc.hInstance = sww_state.hInstance; 68: wc.hIcon = 0; 69: wc.hCursor = LoadCursor (NULL,IDC_ARROW); 70: wc.hbrBackground = (void *)COLOR_GRAYTEXT; 71: wc.lpszMenuName = 0; 72: wc.lpszClassName = WINDOW_CLASS_NAME; 73: 74: if (!RegisterClass (&wc) ) 75: ri.Sys_Error (ERR_FATAL, "Couldn't register window class"); 76: 77: r.left = 0; 78: r.top = 0; 79: r.right = width; 80: r.bottom = height; 81: 82: AdjustWindowRect (&r, stylebits, FALSE); 83: 84: w = r.right - r.left; 85: h = r.bottom - r.top; 86: x = vid_xpos->value; 87: y = vid_ypos->value; 88: 89: sww_state.hWnd = CreateWindowEx ( 90: exstyle, 91: WINDOW_CLASS_NAME, 92: "Quake 2", 93: stylebits, 94: x, y, w, h, 95: NULL, 96: NULL, 97: sww_state.hInstance, 98: NULL); 99: 100: if (!sww_state.hWnd) 101: ri.Sys_Error (ERR_FATAL, "Couldn't create window"); 102: 103: ShowWindow( sww_state.hWnd, SW_SHOWNORMAL ); 104: UpdateWindow( sww_state.hWnd ); 105: SetForegroundWindow( sww_state.hWnd ); 106: SetFocus( sww_state.hWnd ); 107: 108: // let the sound and input subsystems know about the new window 109: ri.Vid_NewWindow (width, height); 110: } 111: 112: /* 113: ** SWimp_Init 114: ** 115: ** This routine is responsible for initializing the implementation 116: ** specific stuff in a software rendering subsystem. 117: */ 118: int SWimp_Init( void *hInstance, void *wndProc ) 119: { 120: sww_state.hInstance = ( HINSTANCE ) hInstance; 121: sww_state.wndproc = wndProc; 122: 123: return true; 124: } 125: 126: /* 127: ** SWimp_InitGraphics 128: ** 129: ** This initializes the software refresh's implementation specific 130: ** graphics subsystem. In the case of Windows it creates DIB or 131: ** DDRAW surfaces. 132: ** 133: ** The necessary width and height parameters are grabbed from 134: ** vid.width and vid.height. 135: */ 136: static qboolean SWimp_InitGraphics( qboolean fullscreen ) 137: { 138: // free resources in use 139: SWimp_Shutdown (); 140: 141: // create a new window 142: VID_CreateWindow (vid.width, vid.height, WINDOW_STYLE); 143: 144: // initialize the appropriate subsystem 145: if ( !fullscreen ) 146: { 147: if ( !DIB_Init( &vid.buffer, &vid.rowbytes ) ) 148: { 149: vid.buffer = 0; 150: vid.rowbytes = 0; 151: 152: return false; 153: } 154: } 155: else 156: { 157: if ( !DDRAW_Init( &vid.buffer, &vid.rowbytes ) ) 158: { 159: vid.buffer = 0; 160: vid.rowbytes = 0; 161: 162: return false; 163: } 164: } 165: 166: return true; 167: } 168: 169: /* 170: ** SWimp_EndFrame 171: ** 172: ** This does an implementation specific copy from the backbuffer to the 173: ** front buffer. In the Win32 case it uses BitBlt or BltFast depending 174: ** on whether we're using DIB sections/GDI or DDRAW. 175: */ 176: void SWimp_EndFrame (void) 177: { 178: if ( !sw_state.fullscreen ) 179: { 180: if ( sww_state.palettized ) 181: { 182: // holdpal = SelectPalette(hdcScreen, hpalDIB, FALSE); 183: // RealizePalette(hdcScreen); 184: } 185: 186: 187: BitBlt( sww_state.hDC, 188: 0, 0, 189: vid.width, 190: vid.height, 191: sww_state.hdcDIBSection, 192: 0, 0, 193: SRCCOPY ); 194: 195: if ( sww_state.palettized ) 196: { 197: // SelectPalette(hdcScreen, holdpal, FALSE); 198: } 199: } 200: else 201: { 202: RECT r; 203: HRESULT rval; 204: DDSURFACEDESC ddsd; 205: 206: r.left = 0; 207: r.top = 0; 208: r.right = vid.width; 209: r.bottom = vid.height; 210: 211: sww_state.lpddsOffScreenBuffer->lpVtbl->Unlock( sww_state.lpddsOffScreenBuffer, vid.buffer ); 212: 213: if ( sww_state.modex ) 214: { 215: if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer, 216: 0, 0, 217: sww_state.lpddsOffScreenBuffer, 218: &r, 219: DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST ) 220: { 221: sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsBackBuffer ); 222: sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer, 223: 0, 0, 224: sww_state.lpddsOffScreenBuffer, 225: &r, 226: DDBLTFAST_WAIT ); 227: } 228: 229: if ( ( rval = sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer, 230: NULL, DDFLIP_WAIT ) ) == DDERR_SURFACELOST ) 231: { 232: sww_state.lpddsFrontBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer ); 233: sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer, NULL, DDFLIP_WAIT ); 234: } 235: } 236: else 237: { 238: if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer, 239: 0, 0, 240: sww_state.lpddsOffScreenBuffer, 241: &r, 242: DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST ) 243: { 244: sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer ); 245: sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer, 246: 0, 0, 247: sww_state.lpddsOffScreenBuffer, 248: &r, 249: DDBLTFAST_WAIT ); 250: } 251: } 252: 253: memset( &ddsd, 0, sizeof( ddsd ) ); 254: ddsd.dwSize = sizeof( ddsd ); 255: 256: sww_state.lpddsOffScreenBuffer->lpVtbl->Lock( sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL ); 257: 258: vid.buffer = ddsd.lpSurface; 259: vid.rowbytes = ddsd.lPitch; 260: } 261: } 262: 263: /* 264: ** SWimp_SetMode 265: */ 266: rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ) 267: { 268: const char *win_fs[] = { "W", "FS" }; 269: rserr_t retval = rserr_ok; 270: 271: ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode ); 272: 273: if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) ) 274: { 275: ri.Con_Printf( PRINT_ALL, " invalid mode\n" ); 276: return rserr_invalid_mode; 277: } 278: 279: ri.Con_Printf( PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] ); 280: 281: sww_state.initializing = true; 282: if ( fullscreen ) 283: { 284: if ( !SWimp_InitGraphics( 1 ) ) 285: { 286: if ( SWimp_InitGraphics( 0 ) ) 287: { 288: // mode is legal but not as fullscreen 289: fullscreen = 0; 290: retval = rserr_invalid_fullscreen; 291: } 292: else 293: { 294: // failed to set a valid mode in windowed mode 295: retval = rserr_unknown; 296: } 297: } 298: } 299: else 300: { 301: // failure to set a valid mode in windowed mode 302: if ( !SWimp_InitGraphics( fullscreen ) ) 303: { 304: sww_state.initializing = true; 305: return rserr_unknown; 306: } 307: } 308: 309: sw_state.fullscreen = fullscreen; 310: #if 0 311: if ( retval != rserr_unknown ) 312: { 313: if ( retval == rserr_invalid_fullscreen || 314: ( retval == rserr_ok && !fullscreen ) ) 315: { 316: SetWindowLong( sww_state.hWnd, GWL_STYLE, WINDOW_STYLE ); 317: } 318: } 319: #endif 320: R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table ); 321: sww_state.initializing = true; 322: 323: return retval; 324: } 325: 326: /* 327: ** SWimp_SetPalette 328: ** 329: ** System specific palette setting routine. A NULL palette means 330: ** to use the existing palette. The palette is expected to be in 331: ** a padded 4-byte xRGB format. 332: */ 333: void SWimp_SetPalette( const unsigned char *palette ) 334: { 335: // MGL - what the fuck was kendall doing here?! 336: // clear screen to black and change palette 337: // for (i=0 ; i<vid.height ; i++) 338: // memset (vid.buffer + i*vid.rowbytes, 0, vid.width); 339: 340: if ( !palette ) 341: palette = ( const unsigned char * ) sw_state.currentpalette; 342: 343: if ( !sw_state.fullscreen ) 344: { 345: DIB_SetPalette( ( const unsigned char * ) palette ); 346: } 347: else 348: { 349: DDRAW_SetPalette( ( const unsigned char * ) palette ); 350: } 351: } 352: 353: /* 354: ** SWimp_Shutdown 355: ** 356: ** System specific graphics subsystem shutdown routine. Destroys 357: ** DIBs or DDRAW surfaces as appropriate. 358: */ 359: void SWimp_Shutdown( void ) 360: { 361: ri.Con_Printf( PRINT_ALL, "Shutting down SW imp\n" ); 362: DIB_Shutdown(); 363: DDRAW_Shutdown(); 364: 365: if ( sww_state.hWnd ) 366: { 367: ri.Con_Printf( PRINT_ALL, "...destroying window\n" ); 368: ShowWindow( sww_state.hWnd, SW_SHOWNORMAL ); // prevents leaving empty slots in the taskbar 369: DestroyWindow (sww_state.hWnd); 370: sww_state.hWnd = NULL; 371: UnregisterClass (WINDOW_CLASS_NAME, sww_state.hInstance); 372: } 373: } 374: 375: /* 376: ** SWimp_AppActivate 377: */ 378: void SWimp_AppActivate( qboolean active ) 379: { 380: if ( active ) 381: { 382: if ( sww_state.hWnd ) 383: { 384: SetForegroundWindow( sww_state.hWnd ); 385: ShowWindow( sww_state.hWnd, SW_RESTORE ); 386: } 387: } 388: else 389: { 390: if ( sww_state.hWnd ) 391: { 392: if ( sww_state.initializing ) 393: return; 394: if ( vid_fullscreen->value ) 395: ShowWindow( sww_state.hWnd, SW_MINIMIZE ); 396: } 397: } 398: } 399: 400: //=============================================================================== 401: 402: 403: /* 404: ================ 405: Sys_MakeCodeWriteable 406: ================ 407: */ 408: void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) 409: { 410: DWORD flOldProtect; 411: 412: if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect)) 413: ri.Sys_Error(ERR_FATAL, "Protection change failed\n"); 414: } 415: 416: /* 417: ** Sys_SetFPCW 418: ** 419: ** For reference: 420: ** 421: ** 1 422: ** 5 0 423: ** xxxxRRPP.xxxxxxxx 424: ** 425: ** PP = 00 = 24-bit single precision 426: ** PP = 01 = reserved 427: ** PP = 10 = 53-bit double precision 428: ** PP = 11 = 64-bit extended precision 429: ** 430: ** RR = 00 = round to nearest 431: ** RR = 01 = round down (towards -inf, floor) 432: ** RR = 10 = round up (towards +inf, ceil) 433: ** RR = 11 = round to zero (truncate/towards 0) 434: ** 435: */ 436: #if !id386 437: void Sys_SetFPCW (void) 438: { 439: } 440: #else 441: unsigned fpu_ceil_cw, fpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw; 442: unsigned fpu_sp24_cw, fpu_sp24_ceil_cw; 443: 444: void Sys_SetFPCW( void ) 445: { 446: __asm xor eax, eax 447: 448: __asm fnstcw word ptr fpu_cw 449: __asm mov ax, word ptr fpu_cw 450: 451: __asm and ah, 0f0h 452: __asm or ah, 003h ; round to nearest mode, extended precision 453: __asm mov fpu_full_cw, eax 454: 455: __asm and ah, 0f0h 456: __asm or ah, 00fh ; RTZ/truncate/chop mode, extended precision 457: __asm mov fpu_chop_cw, eax 458: 459: __asm and ah, 0f0h 460: __asm or ah, 00bh ; ceil mode, extended precision 461: __asm mov fpu_ceil_cw, eax 462: 463: __asm and ah, 0f0h ; round to nearest, 24-bit single precision 464: __asm mov fpu_sp24_cw, eax 465: 466: __asm and ah, 0f0h ; ceil mode, 24-bit single precision 467: __asm or ah, 008h ; 468: __asm mov fpu_sp24_ceil_cw, eax 469: } 470: #endif 471:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.