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