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