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