|
|
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.