1 /* -------------------------------------------------------------------------------
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
6 This file is part of GtkRadiant.
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 ----------------------------------------------------------------------------------
24 This code has been altered significantly from its original form, to support
25 several games based on the Quake III Arena engine, in the form of "Q3Map2."
27 ------------------------------------------------------------------------------- */
42 #define MAX_BASE_PATHS 10
43 #define MAX_GAME_PATHS 10
46 char installPath[ MAX_OS_PATH ];
49 char *basePaths[ MAX_BASE_PATHS ];
51 char *gamePaths[ MAX_GAME_PATHS ];
56 some of this code is based off the original q3map port from loki
57 and finds various paths. moved here from bsp.c for clarity.
62 gets the user's home dir (for ~/.q3a)
65 char *LokiGetHomeDir( void ){
69 static char buf[ 4096 ];
70 struct passwd pw, *pwp;
74 /* get the home environment variable */
75 home = getenv( "HOME" );
77 return Q_strncpyz( buf, home, sizeof( buf ) );
80 /* look up home dir in password database */
81 if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 ) {
93 initializes some paths on linux/os x
96 void LokiInitPaths( char *argv0 ){
98 /* this is kinda crap, but hey */
99 strcpy( installPath, "../" );
101 char temp[ MAX_OS_PATH ];
109 home = LokiGetHomeDir();
110 if ( home == NULL ) {
114 path = getenv( "PATH" );
116 /* do some path divining */
117 Q_strncpyz( temp, argv0, sizeof( temp ) );
118 if ( strrchr( temp, '/' ) ) {
119 argv0 = strrchr( argv0, '/' ) + 1;
125 /* go through each : segment of path */
126 while ( last[ 0 ] != '\0' && found == qfalse )
131 /* find next chunk */
132 last = strchr( path, ':' );
133 if ( last == NULL ) {
134 last = path + strlen( path );
137 /* found home dir candidate */
138 if ( *path == '~' ) {
139 Q_strncpyz( temp, home, sizeof( temp ) );
144 if ( last > ( path + 1 ) ) {
145 Q_strncat( temp, sizeof( temp ), path, ( last - path ) );
146 Q_strcat( temp, sizeof( temp ), "/" );
148 Q_strcat( temp, sizeof( temp ), "./" );
149 Q_strcat( temp, sizeof( temp ), argv0 );
151 /* verify the path */
152 if ( access( temp, X_OK ) == 0 ) {
160 if ( realpath( temp, installPath ) ) {
161 /* q3map is in "tools/" */
162 *( strrchr( installPath, '/' ) ) = '\0';
163 *( strrchr( installPath, '/' ) + 1 ) = '\0';
175 cleans a dos path \ -> /
178 void CleanPath( char *path ){
181 if ( *path == '\\' ) {
192 gets the game_t based on a -game argument
193 returns NULL if no match found
196 game_t *GetGame( char *arg ){
201 if ( arg == NULL || arg[ 0 ] == '\0' ) {
206 if ( !Q_stricmp( arg, "quake1" ) ||
207 !Q_stricmp( arg, "quake2" ) ||
208 !Q_stricmp( arg, "unreal" ) ||
209 !Q_stricmp( arg, "ut2k3" ) ||
210 !Q_stricmp( arg, "dn3d" ) ||
211 !Q_stricmp( arg, "dnf" ) ||
212 !Q_stricmp( arg, "hl" ) ) {
213 Sys_Printf( "April fools, silly rabbit!\n" );
219 while ( games[ i ].arg != NULL )
221 if ( Q_stricmp( arg, games[ i ].arg ) == 0 ) {
227 /* no matching game */
234 AddBasePath() - ydnar
235 adds a base path to the list
238 void AddBasePath( char *path ){
240 if ( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS ) {
244 /* add it to the list */
245 basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
246 strcpy( basePaths[ numBasePaths ], path );
247 CleanPath( basePaths[ numBasePaths ] );
254 AddHomeBasePath() - ydnar
255 adds a base path to the beginning of the list, prefixed by ~/
258 void AddHomeBasePath( char *path ){
261 char temp[ MAX_OS_PATH ];
265 if ( path == NULL || path[ 0 ] == '\0' ) {
270 for ( i = 0; i < ( MAX_BASE_PATHS - 1 ); i++ )
271 basePaths[ i + 1 ] = basePaths[ i ];
273 /* concatenate home dir and path */
274 sprintf( temp, "%s/%s", homePath, path );
276 /* add it to the list */
277 basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
278 strcpy( basePaths[ 0 ], temp );
279 CleanPath( basePaths[ 0 ] );
287 AddGamePath() - ydnar
288 adds a game path to the list
291 void AddGamePath( char *path ){
295 if ( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS ) {
299 /* add it to the list */
300 gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
301 strcpy( gamePaths[ numGamePaths ], path );
302 CleanPath( gamePaths[ numGamePaths ] );
305 /* don't add it if it's already there */
306 for ( i = 0; i < numGamePaths - 1; i++ )
308 if ( strcmp( gamePaths[i], gamePaths[numGamePaths - 1] ) == 0 ) {
309 free( gamePaths[numGamePaths - 1] );
310 gamePaths[numGamePaths - 1] = NULL;
323 cleaned up some of the path initialization code from bsp.c
324 will remove any arguments it uses
327 void InitPaths( int *argc, char **argv ){
328 int i, j, k, len, len2;
329 char temp[ MAX_OS_PATH ];
333 Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
335 /* get the install path for backup */
336 LokiInitPaths( argv[ 0 ] );
338 /* set game to default (q3a) */
343 /* parse through the arguments and extract those relevant to paths */
344 for ( i = 0; i < *argc; i++ )
347 if ( argv[ i ] == NULL ) {
352 if ( strcmp( argv[ i ], "-game" ) == 0 ) {
353 if ( ++i >= *argc ) {
354 Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
356 argv[ i - 1 ] = NULL;
357 game = GetGame( argv[ i ] );
358 if ( game == NULL ) {
365 else if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
366 if ( ++i >= *argc ) {
367 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
369 argv[ i - 1 ] = NULL;
370 AddBasePath( argv[ i ] );
375 else if ( strcmp( argv[ i ], "-fs_game" ) == 0 ) {
376 if ( ++i >= *argc ) {
377 Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
379 argv[ i - 1 ] = NULL;
380 AddGamePath( argv[ i ] );
385 /* remove processed arguments */
386 for ( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
388 for ( ; j < *argc && argv[ j ] == NULL; j++ ) ;
389 argv[ i ] = argv[ j ];
390 if ( argv[ i ] != NULL ) {
396 /* add standard game path */
397 AddGamePath( game->gamePath );
399 /* if there is no base path set, figure it out */
400 if ( numBasePaths == 0 ) {
401 /* this is another crappy replacement for SetQdirFromPath() */
402 len2 = strlen( game->magic );
403 for ( i = 0; i < *argc && numBasePaths == 0; i++ )
405 /* extract the arg */
406 strcpy( temp, argv[ i ] );
408 len = strlen( temp );
409 Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
411 /* this is slow, but only done once */
412 for ( j = 0; j < ( len - len2 ); j++ )
414 /* check for the game's magic word */
415 if ( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 ) {
416 /* now find the next slash and nuke everything after it */
417 while ( temp[ ++j ] != '/' && temp[ j ] != '\0' ) ;
420 /* add this as a base path */
427 /* add install path */
428 if ( numBasePaths == 0 ) {
429 AddBasePath( installPath );
433 if ( numBasePaths == 0 ) {
434 Error( "Failed to find a valid base path." );
438 /* this only affects unix */
439 AddHomeBasePath( game->homeBasePath );
441 /* initialize vfs paths */
442 if ( numBasePaths > MAX_BASE_PATHS ) {
443 numBasePaths = MAX_BASE_PATHS;
445 if ( numGamePaths > MAX_GAME_PATHS ) {
446 numGamePaths = MAX_GAME_PATHS;
449 /* walk the list of game paths */
450 for ( j = 0; j < numGamePaths; j++ )
452 /* walk the list of base paths */
453 for ( i = 0; i < numBasePaths; i++ )
455 /* create a full path and initialize it */
456 sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
457 vfsInitDirectory( temp );