|
|
1.1.1.2 ! root 1: /* ! 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: */ 1.1 root 20: // Main windowed and fullscreen graphics interface module. This module 21: // is used for both the software and OpenGL rendering versions of the 22: // Quake refresh engine. 23: 24: #define SO_FILE "/etc/quake2.conf" 25: 26: #include <errno.h> 27: #include <assert.h> 28: #include <dlfcn.h> // ELF dl loader 29: #include <sys/stat.h> 30: #include <unistd.h> 31: 32: #include "../client/client.h" 33: 34: #include "../linux/rw_linux.h" 35: 36: // Structure containing functions exported from refresh DLL 37: refexport_t re; 38: 39: #ifdef REF_HARD_LINKED 40: refexport_t GetRefAPI (refimport_t rimp); 41: #endif 42: 43: // Console variables that we need to access from this module 44: cvar_t *vid_gamma; 45: cvar_t *vid_ref; // Name of Refresh DLL loaded 46: cvar_t *vid_xpos; // X coordinate of window position 47: cvar_t *vid_ypos; // Y coordinate of window position 48: cvar_t *vid_fullscreen; 49: 50: // Global variables used internally by this module 51: viddef_t viddef; // global video state; used by other modules 52: void *reflib_library; // Handle to refresh DLL 53: qboolean reflib_active = 0; 54: 55: #define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ) ) 56: 57: /** KEYBOARD **************************************************************/ 58: 59: void Do_Key_Event(int key, qboolean down); 60: 61: void (*KBD_Update_fp)(void); 62: void (*KBD_Init_fp)(Key_Event_fp_t fp); 63: void (*KBD_Close_fp)(void); 64: 65: /** MOUSE *****************************************************************/ 66: 67: in_state_t in_state; 68: 69: void (*RW_IN_Init_fp)(in_state_t *in_state_p); 70: void (*RW_IN_Shutdown_fp)(void); 71: void (*RW_IN_Activate_fp)(qboolean active); 72: void (*RW_IN_Commands_fp)(void); 73: void (*RW_IN_Move_fp)(usercmd_t *cmd); 74: void (*RW_IN_Frame_fp)(void); 75: 76: void Real_IN_Init (void); 77: 78: /* 79: ========================================================================== 80: 81: DLL GLUE 82: 83: ========================================================================== 84: */ 85: 86: #define MAXPRINTMSG 4096 87: void VID_Printf (int print_level, char *fmt, ...) 88: { 89: va_list argptr; 90: char msg[MAXPRINTMSG]; 91: static qboolean inupdate; 92: 93: va_start (argptr,fmt); 94: vsprintf (msg,fmt,argptr); 95: va_end (argptr); 96: 97: if (print_level == PRINT_ALL) 98: Com_Printf ("%s", msg); 99: else 100: Com_DPrintf ("%s", msg); 101: } 102: 103: void VID_Error (int err_level, char *fmt, ...) 104: { 105: va_list argptr; 106: char msg[MAXPRINTMSG]; 107: static qboolean inupdate; 108: 109: va_start (argptr,fmt); 110: vsprintf (msg,fmt,argptr); 111: va_end (argptr); 112: 113: Com_Error (err_level,"%s", msg); 114: } 115: 116: //========================================================================== 117: 118: /* 119: ============ 120: VID_Restart_f 121: 122: Console command to re-start the video mode and refresh DLL. We do this 123: simply by setting the modified flag for the vid_ref variable, which will 124: cause the entire video mode and refresh DLL to be reset on the next frame. 125: ============ 126: */ 127: void VID_Restart_f (void) 128: { 129: vid_ref->modified = true; 130: } 131: 132: /* 133: ** VID_GetModeInfo 134: */ 135: typedef struct vidmode_s 136: { 137: const char *description; 138: int width, height; 139: int mode; 140: } vidmode_t; 141: 142: vidmode_t vid_modes[] = 143: { 144: { "Mode 0: 320x240", 320, 240, 0 }, 145: { "Mode 1: 400x300", 400, 300, 1 }, 146: { "Mode 2: 512x384", 512, 384, 2 }, 147: { "Mode 3: 640x480", 640, 480, 3 }, 148: { "Mode 4: 800x600", 800, 600, 4 }, 149: { "Mode 5: 960x720", 960, 720, 5 }, 150: { "Mode 6: 1024x768", 1024, 768, 6 }, 151: { "Mode 7: 1152x864", 1152, 864, 7 }, 152: { "Mode 8: 1280x1024", 1280, 1024, 8 }, 1.1.1.2 ! root 153: { "Mode 9: 1600x1200", 1600, 1200, 9 }, ! 154: { "Mode 10: 2048x1536", 2048, 1536, 10 } 1.1 root 155: }; 156: 157: qboolean VID_GetModeInfo( int *width, int *height, int mode ) 158: { 159: if ( mode < 0 || mode >= VID_NUM_MODES ) 160: return false; 161: 162: *width = vid_modes[mode].width; 163: *height = vid_modes[mode].height; 164: 165: return true; 166: } 167: 168: /* 169: ** VID_NewWindow 170: */ 171: void VID_NewWindow ( int width, int height) 172: { 173: viddef.width = width; 174: viddef.height = height; 175: } 176: 177: void VID_FreeReflib (void) 178: { 179: if (reflib_library) { 180: if (KBD_Close_fp) 181: KBD_Close_fp(); 182: if (RW_IN_Shutdown_fp) 183: RW_IN_Shutdown_fp(); 184: #ifndef REF_HARD_LINKED 185: dlclose(reflib_library); 186: #endif 187: } 188: 189: KBD_Init_fp = NULL; 190: KBD_Update_fp = NULL; 191: KBD_Close_fp = NULL; 192: RW_IN_Init_fp = NULL; 193: RW_IN_Shutdown_fp = NULL; 194: RW_IN_Activate_fp = NULL; 195: RW_IN_Commands_fp = NULL; 196: RW_IN_Move_fp = NULL; 197: RW_IN_Frame_fp = NULL; 198: 199: memset (&re, 0, sizeof(re)); 200: reflib_library = NULL; 201: reflib_active = false; 202: } 203: 204: /* 205: ============== 206: VID_LoadRefresh 207: ============== 208: */ 209: qboolean VID_LoadRefresh( char *name ) 210: { 211: refimport_t ri; 212: #ifndef REF_HARD_LINKED 213: GetRefAPI_t GetRefAPI; 214: #endif 215: char fn[MAX_OSPATH]; 216: struct stat st; 217: extern uid_t saved_euid; 218: FILE *fp; 219: char *path; 220: char curpath[MAX_OSPATH]; 221: 222: if ( reflib_active ) 223: { 224: if (KBD_Close_fp) 225: KBD_Close_fp(); 226: if (RW_IN_Shutdown_fp) 227: RW_IN_Shutdown_fp(); 228: KBD_Close_fp = NULL; 229: RW_IN_Shutdown_fp = NULL; 230: re.Shutdown(); 231: VID_FreeReflib (); 232: } 233: 234: #ifndef REF_HARD_LINKED 235: getcwd(curpath, sizeof(curpath)); 236: 237: Com_Printf( "------- Loading %s -------\n", name ); 238: 239: // now run through the search paths 240: path = NULL; 241: while (1) 242: { 243: path = FS_NextPath (path); 244: if (!path) 245: return NULL; // couldn't find one anywhere 246: sprintf (fn, "%s/%s/%s", curpath, path, name); 247: Com_Printf ("Trying to load library (%s)\n", fn); 248: 249: reflib_library = dlopen( fn, RTLD_NOW ); 250: if (reflib_library) 251: { 252: Com_DPrintf ("LoadLibrary (%s)\n",name); 253: break; 254: } 255: } 256: 257: #endif 258: 259: ri.Cmd_AddCommand = Cmd_AddCommand; 260: ri.Cmd_RemoveCommand = Cmd_RemoveCommand; 261: ri.Cmd_Argc = Cmd_Argc; 262: ri.Cmd_Argv = Cmd_Argv; 263: ri.Cmd_ExecuteText = Cbuf_ExecuteText; 264: ri.Con_Printf = VID_Printf; 265: ri.Sys_Error = VID_Error; 266: ri.FS_LoadFile = FS_LoadFile; 267: ri.FS_FreeFile = FS_FreeFile; 268: ri.FS_Gamedir = FS_Gamedir; 269: ri.Cvar_Get = Cvar_Get; 270: ri.Cvar_Set = Cvar_Set; 271: ri.Cvar_SetValue = Cvar_SetValue; 272: ri.Vid_GetModeInfo = VID_GetModeInfo; 273: ri.Vid_MenuInit = VID_MenuInit; 274: ri.Vid_NewWindow = VID_NewWindow; 275: 276: #ifndef REF_HARD_LINKED 277: if ( ( GetRefAPI = (void *) dlsym( reflib_library, "GetRefAPI" ) ) == 0 ) 278: Com_Error( ERR_FATAL, "dlsym failed on %s", name ); 279: #endif 280: re = GetRefAPI( ri ); 281: 282: if (re.api_version != API_VERSION) 283: { 284: VID_FreeReflib (); 285: Com_Error (ERR_FATAL, "%s has incompatible api_version", name); 286: } 287: 288: /* Init IN (Mouse) */ 289: in_state.IN_CenterView_fp = IN_CenterView; 290: in_state.Key_Event_fp = Do_Key_Event; 291: in_state.viewangles = cl.viewangles; 292: in_state.in_strafe_state = &in_strafe.state; 293: 294: #ifndef REF_HARD_LINKED 295: if ((RW_IN_Init_fp = dlsym(reflib_library, "RW_IN_Init")) == NULL || 296: (RW_IN_Shutdown_fp = dlsym(reflib_library, "RW_IN_Shutdown")) == NULL || 297: (RW_IN_Activate_fp = dlsym(reflib_library, "RW_IN_Activate")) == NULL || 298: (RW_IN_Commands_fp = dlsym(reflib_library, "RW_IN_Commands")) == NULL || 299: (RW_IN_Move_fp = dlsym(reflib_library, "RW_IN_Move")) == NULL || 300: (RW_IN_Frame_fp = dlsym(reflib_library, "RW_IN_Frame")) == NULL) 301: Sys_Error("No RW_IN functions in REF.\n"); 302: #else 303: { 304: void RW_IN_Init(in_state_t *in_state_p); 305: void RW_IN_Shutdown(void); 306: void RW_IN_Commands (void); 307: void RW_IN_Move (usercmd_t *cmd); 308: void RW_IN_Frame (void); 309: void RW_IN_Activate(void); 310: 311: RW_IN_Init_fp = RW_IN_Init; 312: RW_IN_Shutdown_fp = RW_IN_Shutdown; 313: RW_IN_Activate_fp = RW_IN_Activate; 314: RW_IN_Commands_fp = RW_IN_Commands; 315: RW_IN_Move_fp = RW_IN_Move; 316: RW_IN_Frame_fp = RW_IN_Frame; 317: } 318: #endif 319: 320: if ( re.Init( 0, 0 ) == -1 ) 321: { 322: re.Shutdown(); 323: VID_FreeReflib (); 324: return false; 325: } 326: 327: // give up root now 328: setreuid(getuid(), getuid()); 329: setegid(getgid()); 330: 331: /* Init KBD */ 332: #ifndef REF_HARD_LINKED 333: if ((KBD_Init_fp = dlsym(reflib_library, "KBD_Init")) == NULL || 334: (KBD_Update_fp = dlsym(reflib_library, "KBD_Update")) == NULL || 335: (KBD_Close_fp = dlsym(reflib_library, "KBD_Close")) == NULL) 336: Sys_Error("No KBD functions in REF.\n"); 337: #else 338: { 339: void KBD_Init(void); 340: void KBD_Update(void); 341: void KBD_Close(void); 342: 343: KBD_Init_fp = KBD_Init; 344: KBD_Update_fp = KBD_Update; 345: KBD_Close_fp = KBD_Close; 346: } 347: #endif 348: KBD_Init_fp(Do_Key_Event); 349: Real_IN_Init(); 350: 351: Com_Printf( "------------------------------------\n"); 352: reflib_active = true; 353: return true; 354: } 355: 356: /* 357: ============ 358: VID_CheckChanges 359: 360: This function gets called once just before drawing each frame, and it's sole purpose in life 361: is to check to see if any of the video mode parameters have changed, and if they have to 362: update the rendering DLL and/or video mode to match. 363: ============ 364: */ 365: void VID_CheckChanges (void) 366: { 367: char name[100]; 368: cvar_t *sw_mode; 369: 370: if ( vid_ref->modified ) 371: { 372: S_StopAllSounds(); 373: } 374: 375: while (vid_ref->modified) 376: { 377: /* 378: ** refresh has changed 379: */ 380: vid_ref->modified = false; 381: vid_fullscreen->modified = true; 382: cl.refresh_prepped = false; 383: cls.disable_screen = true; 384: 385: sprintf( name, "ref_%s.so", vid_ref->string ); 386: if ( !VID_LoadRefresh( name ) ) 387: { 388: if ( strcmp (vid_ref->string, "soft") == 0 ) { 389: Com_Printf("Refresh failed\n"); 390: sw_mode = Cvar_Get( "sw_mode", "0", 0 ); 391: if (sw_mode->value != 0) { 392: Com_Printf("Trying mode 0\n"); 393: Cvar_SetValue("sw_mode", 0); 394: if ( !VID_LoadRefresh( name ) ) 395: Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!"); 396: } else 397: Com_Error (ERR_FATAL, "Couldn't fall back to software refresh!"); 398: } 399: 400: Cvar_Set( "vid_ref", "soft" ); 401: 402: /* 403: ** drop the console if we fail to load a refresh 404: */ 405: if ( cls.key_dest != key_console ) 406: { 407: Con_ToggleConsole_f(); 408: } 409: } 410: cls.disable_screen = false; 411: } 412: 413: } 414: 415: /* 416: ============ 417: VID_Init 418: ============ 419: */ 420: void VID_Init (void) 421: { 422: /* Create the video variables so we know how to start the graphics drivers */ 423: vid_ref = Cvar_Get ("vid_ref", "soft", CVAR_ARCHIVE); 424: vid_xpos = Cvar_Get ("vid_xpos", "3", CVAR_ARCHIVE); 425: vid_ypos = Cvar_Get ("vid_ypos", "22", CVAR_ARCHIVE); 426: vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE); 427: vid_gamma = Cvar_Get( "vid_gamma", "1", CVAR_ARCHIVE ); 428: 429: /* Add some console commands that we want to handle */ 430: Cmd_AddCommand ("vid_restart", VID_Restart_f); 431: 432: /* Disable the 3Dfx splash screen */ 433: putenv("FX_GLIDE_NO_SPLASH=0"); 434: 435: /* Start the graphics mode and load refresh DLL */ 436: VID_CheckChanges(); 437: } 438: 439: /* 440: ============ 441: VID_Shutdown 442: ============ 443: */ 444: void VID_Shutdown (void) 445: { 446: if ( reflib_active ) 447: { 448: if (KBD_Close_fp) 449: KBD_Close_fp(); 450: if (RW_IN_Shutdown_fp) 451: RW_IN_Shutdown_fp(); 452: KBD_Close_fp = NULL; 453: RW_IN_Shutdown_fp = NULL; 454: re.Shutdown (); 455: VID_FreeReflib (); 456: } 457: } 458: 459: 460: /*****************************************************************************/ 461: /* INPUT */ 462: /*****************************************************************************/ 463: 464: cvar_t *in_joystick; 465: 466: // This if fake, it's acutally done by the Refresh load 467: void IN_Init (void) 468: { 469: in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE); 470: } 471: 472: void Real_IN_Init (void) 473: { 474: if (RW_IN_Init_fp) 475: RW_IN_Init_fp(&in_state); 476: } 477: 478: void IN_Shutdown (void) 479: { 480: if (RW_IN_Shutdown_fp) 481: RW_IN_Shutdown_fp(); 482: } 483: 484: void IN_Commands (void) 485: { 486: if (RW_IN_Commands_fp) 487: RW_IN_Commands_fp(); 488: } 489: 490: void IN_Move (usercmd_t *cmd) 491: { 492: if (RW_IN_Move_fp) 493: RW_IN_Move_fp(cmd); 494: } 495: 496: void IN_Frame (void) 497: { 498: if (RW_IN_Frame_fp) 499: RW_IN_Frame_fp(); 500: } 501: 502: void IN_Activate (qboolean active) 503: { 504: if (RW_IN_Activate_fp) 505: RW_IN_Activate_fp(active); 506: } 507: 508: void Do_Key_Event(int key, qboolean down) 509: { 510: Key_Event(key, down, Sys_Milliseconds()); 511: } 512:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.