2005-08-26 22:52:26 +00:00
# include "quakedef.h"
2007-08-20 02:24:43 +00:00
# include "netinc.h"
2005-08-26 22:52:26 +00:00
2005-12-21 03:07:33 +00:00
//#define com_gamedir com__gamedir
2005-08-26 22:52:26 +00:00
# include <ctype.h>
2009-04-01 22:03:56 +00:00
# include <limits.h>
2005-08-26 22:52:26 +00:00
2009-04-01 22:03:56 +00:00
# include "fs.h"
2011-03-12 13:51:40 +00:00
# include "shader.h"
2013-06-23 02:17:02 +00:00
# ifdef _WIN32
# include "winquake.h"
# endif
2005-08-26 22:52:26 +00:00
2014-02-11 17:51:29 +00:00
void fs_game_callback ( cvar_t * var , char * oldvalue ) ;
2005-08-26 22:52:26 +00:00
hashtable_t filesystemhash ;
qboolean com_fschanged = true ;
2010-07-11 02:22:39 +00:00
static unsigned int fs_restarts ;
2014-02-11 17:51:29 +00:00
cvar_t com_fs_cache = CVARF ( " fs_cache " , IFMINIMAL ( " 2 " , " 1 " ) , CVAR_ARCHIVE ) ;
cvar_t cfg_reload_on_gamedir = CVAR ( " cfg_reload_on_gamedir " , " 1 " ) ;
cvar_t fs_game = CVARFDC ( " game " , " " , CVAR_NOSAVE | CVAR_NORESET , " Provided for Q2 compat. " , fs_game_callback ) ;
cvar_t fs_gamedir = CVARFD ( " fs_gamedir " , " " , CVAR_NOUNSAFEEXPAND | CVAR_NOSET | CVAR_NOSAVE , " Provided for Q2 compat. " ) ;
cvar_t fs_basedir = CVARFD ( " fs_basedir " , " " , CVAR_NOUNSAFEEXPAND | CVAR_NOSET | CVAR_NOSAVE , " Provided for Q2 compat. " ) ;
2005-08-26 22:52:26 +00:00
int active_fs_cachetype ;
2011-12-05 15:23:40 +00:00
static int fs_referencetype ;
2012-02-27 12:23:15 +00:00
int fs_finds ;
2013-09-26 09:24:52 +00:00
void COM_CheckRegistered ( void ) ;
2005-08-26 22:52:26 +00:00
2014-02-11 17:51:29 +00:00
void fs_game_callback ( cvar_t * var , char * oldvalue )
{
static qboolean runaway = false ;
char buf [ MAX_OSPATH ] ;
if ( ! strcmp ( var - > string , oldvalue ) )
return ; //no change here.
if ( runaway )
return ; //ignore that
runaway = true ;
Cmd_ExecuteString ( va ( " gamedir %s \n " , COM_QuotedString ( var - > string , buf , sizeof ( buf ) ) ) , Cmd_ExecLevel ) ;
runaway = false ;
}
2009-06-03 09:09:35 +00:00
struct
2005-08-26 22:52:26 +00:00
{
2013-05-03 04:28:08 +00:00
void * module ;
2009-04-01 22:03:56 +00:00
const char * extension ;
2013-06-23 02:17:02 +00:00
searchpathfuncs_t * ( QDECL * OpenNew ) ( vfsfile_t * file , const char * desc ) ;
2012-01-28 10:30:44 +00:00
qboolean loadscan ;
2009-04-01 22:03:56 +00:00
} searchpathformats [ 64 ] ;
2005-12-21 03:07:33 +00:00
2013-06-23 02:17:02 +00:00
int FS_RegisterFileSystemType ( void * module , const char * extension , searchpathfuncs_t * ( QDECL * OpenNew ) ( vfsfile_t * file , const char * desc ) , qboolean loadscan )
2005-08-26 22:52:26 +00:00
{
2009-04-01 22:03:56 +00:00
unsigned int i ;
for ( i = 0 ; i < sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) ; i + + )
2005-08-26 22:52:26 +00:00
{
2009-04-01 22:03:56 +00:00
if ( searchpathformats [ i ] . extension & & ! strcmp ( searchpathformats [ i ] . extension , extension ) )
break ; //extension match always replaces
2013-06-23 02:17:02 +00:00
if ( ! searchpathformats [ i ] . extension & & ! searchpathformats [ i ] . OpenNew )
2009-04-01 22:03:56 +00:00
break ;
2005-08-26 22:52:26 +00:00
}
2009-04-01 22:03:56 +00:00
if ( i = = sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) )
return 0 ;
2005-08-26 22:52:26 +00:00
2013-05-03 04:28:08 +00:00
searchpathformats [ i ] . module = module ;
2009-04-01 22:03:56 +00:00
searchpathformats [ i ] . extension = extension ;
2013-06-23 02:17:02 +00:00
searchpathformats [ i ] . OpenNew = OpenNew ;
2012-01-28 10:30:44 +00:00
searchpathformats [ i ] . loadscan = loadscan ;
2009-04-01 22:03:56 +00:00
com_fschanged = true ;
2005-08-26 22:52:26 +00:00
2009-04-01 22:03:56 +00:00
return i + 1 ;
2005-08-26 22:52:26 +00:00
}
2009-04-01 22:03:56 +00:00
void FS_UnRegisterFileSystemType ( int idx )
2005-08-26 22:52:26 +00:00
{
2009-04-01 22:03:56 +00:00
if ( ( unsigned int ) ( idx - 1 ) > = sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) )
2005-08-26 22:52:26 +00:00
return ;
2013-06-23 02:17:02 +00:00
searchpathformats [ idx - 1 ] . OpenNew = NULL ;
2013-05-03 04:28:08 +00:00
searchpathformats [ idx - 1 ] . module = NULL ;
2009-04-01 22:03:56 +00:00
com_fschanged = true ;
2005-08-26 22:52:26 +00:00
2009-04-01 22:03:56 +00:00
//FS_Restart will be needed
2005-08-26 22:52:26 +00:00
}
2013-05-03 04:28:08 +00:00
void FS_UnRegisterFileSystemModule ( void * module )
{
int i ;
qboolean found = false ;
for ( i = 0 ; i < sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) ; i + + )
{
if ( searchpathformats [ i ] . module = = module )
{
2013-06-23 02:17:02 +00:00
searchpathformats [ i ] . OpenNew = NULL ;
2013-05-03 04:28:08 +00:00
searchpathformats [ i ] . module = NULL ;
found = true ;
}
}
if ( found )
{
Cmd_ExecuteString ( " fs_restart " , RESTRICT_LOCAL ) ;
}
}
2005-08-26 22:52:26 +00:00
2008-02-13 14:09:02 +00:00
2009-04-01 22:03:56 +00:00
vfsfile_t * FS_OpenVFSLoc ( flocation_t * loc , char * mode ) ;
2005-08-26 22:52:26 +00:00
2009-04-01 22:03:56 +00:00
char * VFS_GETS ( vfsfile_t * vf , char * buffer , int buflen )
2005-08-26 22:52:26 +00:00
{
2009-04-01 22:03:56 +00:00
char in ;
char * out = buffer ;
int len ;
len = buflen - 1 ;
if ( len = = 0 )
return NULL ;
while ( len > 0 )
2005-08-26 22:52:26 +00:00
{
2010-03-25 22:56:11 +00:00
if ( VFS_READ ( vf , & in , 1 ) ! = 1 )
2005-08-26 22:52:26 +00:00
{
2009-04-01 22:03:56 +00:00
if ( len = = buflen - 1 )
return NULL ;
* out = ' \0 ' ;
return buffer ;
2005-08-26 22:52:26 +00:00
}
2009-04-01 22:03:56 +00:00
if ( in = = ' \n ' )
break ;
* out + + = in ;
len - - ;
2005-08-26 22:52:26 +00:00
}
2009-04-01 22:03:56 +00:00
* out = ' \0 ' ;
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
//if there's a trailing \r, strip it.
if ( out > buffer )
if ( out [ - 1 ] = = ' \r ' )
out [ - 1 ] = 0 ;
2009-04-01 22:03:56 +00:00
return buffer ;
2005-08-26 22:52:26 +00:00
}
2009-04-06 00:34:32 +00:00
void VARGS VFS_PRINTF ( vfsfile_t * vf , char * format , . . . )
2005-12-21 03:07:33 +00:00
{
2009-04-01 22:03:56 +00:00
va_list argptr ;
char string [ 1024 ] ;
2005-12-21 03:07:33 +00:00
2009-04-01 22:03:56 +00:00
va_start ( argptr , format ) ;
vsnprintf ( string , sizeof ( string ) - 1 , format , argptr ) ;
va_end ( argptr ) ;
2005-12-21 03:07:33 +00:00
2009-04-01 22:03:56 +00:00
VFS_PUTS ( vf , string ) ;
2005-12-21 03:07:33 +00:00
}
2006-03-15 20:05:25 +00:00
2005-12-21 03:07:33 +00:00
2006-03-15 20:05:25 +00:00
2009-04-01 22:03:56 +00:00
char gamedirfile [ MAX_OSPATH ] ;
2006-03-15 20:05:25 +00:00
2005-12-21 03:07:33 +00:00
2009-04-01 22:03:56 +00:00
//the various COM_LoadFiles set these on return
int com_filesize ;
2013-06-23 02:17:02 +00:00
qboolean com_file_copyprotected ; //file should not be available for download.
qboolean com_file_untrusted ; //file was downloaded inside a package
2005-12-21 03:07:33 +00:00
2009-04-01 22:03:56 +00:00
//char *com_basedir; //obsolete
2005-12-21 03:07:33 +00:00
2009-04-01 22:03:56 +00:00
char com_quakedir [ MAX_OSPATH ] ;
char com_homedir [ MAX_OSPATH ] ;
2006-03-15 20:05:25 +00:00
2009-04-01 22:03:56 +00:00
char com_configdir [ MAX_OSPATH ] ; //homedir/fte/configs
2006-03-15 20:05:25 +00:00
2009-04-01 22:03:56 +00:00
int fs_hash_dups ;
int fs_hash_files ;
2005-12-21 03:07:33 +00:00
2006-03-15 20:05:25 +00:00
2005-12-21 03:07:33 +00:00
2006-01-02 22:53:29 +00:00
2005-12-21 03:07:33 +00:00
2009-04-01 22:03:56 +00:00
static const char * FS_GetCleanPath ( const char * pattern , char * outbuf , int outlen ) ;
void FS_RegisterDefaultFileSystems ( void ) ;
2010-07-18 08:42:59 +00:00
static void COM_CreatePath ( char * path ) ;
2005-12-21 03:07:33 +00:00
2009-04-01 22:03:56 +00:00
# define ENFORCEFOPENMODE(mode) {if (strcmp(mode, "r") && strcmp(mode, "w") /* && strcmp(mode, "rw")*/ )Sys_Error("fs mode %s is not permitted here\n");}
2005-12-21 03:07:33 +00:00
2006-03-15 20:05:25 +00:00
2005-12-21 03:07:33 +00:00
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
//forget a manifest entirely.
void FS_Manifest_Free ( ftemanifest_t * man )
{
int i , j ;
if ( ! man )
return ;
Z_Free ( man - > updateurl ) ;
Z_Free ( man - > installation ) ;
Z_Free ( man - > formalname ) ;
Z_Free ( man - > protocolname ) ;
Z_Free ( man - > defaultexec ) ;
for ( i = 0 ; i < sizeof ( man - > gamepath ) / sizeof ( man - > gamepath [ 0 ] ) ; i + + )
{
Z_Free ( man - > gamepath [ i ] . path ) ;
}
for ( i = 0 ; i < sizeof ( man - > package ) / sizeof ( man - > package [ 0 ] ) ; i + + )
{
Z_Free ( man - > package [ i ] . path ) ;
for ( j = 0 ; j < sizeof ( man - > package [ i ] . mirrors ) / sizeof ( man - > package [ i ] . mirrors [ 0 ] ) ; j + + )
Z_Free ( man - > package [ i ] . mirrors [ j ] ) ;
}
Z_Free ( man ) ;
}
//clone a manifest, so we can hack at it.
static ftemanifest_t * FS_Manifest_Clone ( ftemanifest_t * oldm )
{
ftemanifest_t * newm ;
int i , j ;
newm = Z_Malloc ( sizeof ( * newm ) ) ;
if ( oldm - > updateurl )
newm - > updateurl = Z_StrDup ( oldm - > updateurl ) ;
if ( oldm - > installation )
newm - > installation = Z_StrDup ( oldm - > installation ) ;
if ( oldm - > formalname )
newm - > formalname = Z_StrDup ( oldm - > formalname ) ;
if ( oldm - > protocolname )
newm - > protocolname = Z_StrDup ( oldm - > protocolname ) ;
2013-08-07 14:13:18 +00:00
if ( oldm - > defaultexec )
newm - > defaultexec = Z_StrDup ( oldm - > defaultexec ) ;
2013-06-23 02:17:02 +00:00
for ( i = 0 ; i < sizeof ( newm - > gamepath ) / sizeof ( newm - > gamepath [ 0 ] ) ; i + + )
{
if ( oldm - > gamepath [ i ] . path )
newm - > gamepath [ i ] . path = Z_StrDup ( oldm - > gamepath [ i ] . path ) ;
newm - > gamepath [ i ] . base = oldm - > gamepath [ i ] . base ;
}
for ( i = 0 ; i < sizeof ( newm - > package ) / sizeof ( newm - > package [ 0 ] ) ; i + + )
{
if ( oldm - > package [ i ] . path )
newm - > package [ i ] . path = Z_StrDup ( oldm - > package [ i ] . path ) ;
for ( j = 0 ; j < sizeof ( newm - > package [ i ] . mirrors ) / sizeof ( newm - > package [ i ] . mirrors [ 0 ] ) ; j + + )
if ( oldm - > package [ i ] . mirrors [ j ] )
newm - > package [ i ] . mirrors [ j ] = Z_StrDup ( oldm - > package [ i ] . mirrors [ j ] ) ;
}
return newm ;
}
void FS_Manifest_Print ( ftemanifest_t * man )
{
2013-08-07 14:13:18 +00:00
char buffer [ 1024 ] ;
2013-06-23 02:17:02 +00:00
int i , j ;
if ( man - > updateurl )
2013-08-21 07:14:39 +00:00
Con_Printf ( " updateurl %s \n " , COM_QuotedString ( man - > updateurl , buffer , sizeof ( buffer ) ) ) ;
2013-06-23 02:17:02 +00:00
if ( man - > installation )
2013-08-21 07:14:39 +00:00
Con_Printf ( " game %s \n " , COM_QuotedString ( man - > installation , buffer , sizeof ( buffer ) ) ) ;
2013-06-23 02:17:02 +00:00
if ( man - > formalname )
2013-08-21 07:14:39 +00:00
Con_Printf ( " name %s \n " , COM_QuotedString ( man - > formalname , buffer , sizeof ( buffer ) ) ) ;
2013-06-23 02:17:02 +00:00
if ( man - > protocolname )
2013-08-21 07:14:39 +00:00
Con_Printf ( " protocolname %s \n " , COM_QuotedString ( man - > protocolname , buffer , sizeof ( buffer ) ) ) ;
2013-08-07 14:13:18 +00:00
if ( man - > defaultexec )
Con_Printf ( " defaultexec %s \n " , COM_QuotedString ( man - > defaultexec , buffer , sizeof ( buffer ) ) ) ;
2013-06-23 02:17:02 +00:00
for ( i = 0 ; i < sizeof ( man - > gamepath ) / sizeof ( man - > gamepath [ 0 ] ) ; i + + )
{
if ( man - > gamepath [ i ] . path )
{
if ( man - > gamepath [ i ] . base )
2013-08-21 07:14:39 +00:00
Con_Printf ( " basegame %s \n " , COM_QuotedString ( man - > gamepath [ i ] . path , buffer , sizeof ( buffer ) ) ) ;
2013-06-23 02:17:02 +00:00
else
2013-08-21 07:14:39 +00:00
Con_Printf ( " gamedir %s \n " , COM_QuotedString ( man - > gamepath [ i ] . path , buffer , sizeof ( buffer ) ) ) ;
2013-06-23 02:17:02 +00:00
}
}
for ( i = 0 ; i < sizeof ( man - > package ) / sizeof ( man - > package [ 0 ] ) ; i + + )
{
if ( man - > package [ i ] . path )
{
2013-08-06 02:19:06 +00:00
if ( man - > package [ i ] . crcknown )
2013-08-21 07:14:39 +00:00
Con_Printf ( " package %s 0x%x " , COM_QuotedString ( man - > package [ i ] . path , buffer , sizeof ( buffer ) ) , man - > package [ i ] . crc ) ;
2013-08-06 02:19:06 +00:00
else
2013-08-21 07:14:39 +00:00
Con_Printf ( " package %s - " , COM_QuotedString ( man - > package [ i ] . path , buffer , sizeof ( buffer ) ) ) ;
2013-06-23 02:17:02 +00:00
for ( j = 0 ; j < sizeof ( man - > package [ i ] . mirrors ) / sizeof ( man - > package [ i ] . mirrors [ 0 ] ) ; j + + )
if ( man - > package [ i ] . mirrors [ j ] )
2013-08-21 07:14:39 +00:00
Con_Printf ( " \" %s \" " , COM_QuotedString ( man - > package [ i ] . mirrors [ j ] , buffer , sizeof ( buffer ) ) ) ;
2013-06-23 03:59:48 +00:00
Con_Printf ( " \n " ) ;
2013-06-23 02:17:02 +00:00
}
}
}
//forget any mod dirs.
static void FS_Manifest_PurgeGamedirs ( ftemanifest_t * man )
{
int i ;
for ( i = 0 ; i < sizeof ( man - > gamepath ) / sizeof ( man - > gamepath [ 0 ] ) ; i + + )
{
if ( man - > gamepath [ i ] . path & & ! man - > gamepath [ i ] . base )
{
Z_Free ( man - > gamepath [ i ] . path ) ;
man - > gamepath [ i ] . path = NULL ;
}
}
}
//create a new empty manifest with default values.
static ftemanifest_t * FS_Manifest_Create ( void )
{
ftemanifest_t * man = Z_Malloc ( sizeof ( * man ) ) ;
// man->installation = Z_StrDup("quake");
man - > formalname = Z_StrDup ( FULLENGINENAME ) ;
return man ;
}
//parse Cmd_Argv tokens into the manifest.
static void FS_Manifest_ParseTokens ( ftemanifest_t * man )
{
char * fname ;
if ( ! Cmd_Argc ( ) )
return ;
fname = Cmd_Argv ( 0 ) ;
if ( * fname = = ' * ' )
fname + + ;
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( fname , " game " ) )
2013-06-23 02:17:02 +00:00
{
Z_Free ( man - > installation ) ;
man - > installation = Z_StrDup ( Cmd_Argv ( 1 ) ) ;
}
2014-02-07 08:38:40 +00:00
else if ( ! Q_strcasecmp ( fname , " name " ) )
2013-06-23 02:17:02 +00:00
{
Z_Free ( man - > formalname ) ;
man - > formalname = Z_StrDup ( Cmd_Argv ( 1 ) ) ;
}
2014-02-07 08:38:40 +00:00
else if ( ! Q_strcasecmp ( fname , " protocolname " ) )
2013-06-23 02:17:02 +00:00
{
Z_Free ( man - > protocolname ) ;
man - > protocolname = Z_StrDup ( Cmd_Argv ( 1 ) ) ;
}
2014-02-07 08:38:40 +00:00
else if ( ! Q_strcasecmp ( fname , " defaultexec " ) )
2013-08-07 14:13:18 +00:00
{
Z_Free ( man - > defaultexec ) ;
man - > defaultexec = Z_StrDup ( Cmd_Argv ( 1 ) ) ;
}
2014-02-07 08:38:40 +00:00
else if ( ! Q_strcasecmp ( fname , " basegame " ) | | ! Q_strcasecmp ( fname , " gamedir " ) )
2013-06-23 02:17:02 +00:00
{
int i ;
char * newdir = Cmd_Argv ( 1 ) ;
//reject various evil path arguments.
2013-10-29 17:38:22 +00:00
if ( ! * newdir | | strchr ( newdir , ' \n ' ) | | strchr ( newdir , ' \r ' ) | | ! strcmp ( newdir , " . " ) | | ! strcmp ( newdir , " .. " ) | | strchr ( newdir , ' : ' ) | | strchr ( newdir , ' / ' ) | | strchr ( newdir , ' \\ ' ) | | strchr ( newdir , ' $ ' ) )
2013-06-23 02:17:02 +00:00
{
Con_Printf ( " Illegal path specified: %s \n " , newdir ) ;
}
else
{
for ( i = 0 ; i < sizeof ( man - > gamepath ) / sizeof ( man - > gamepath [ 0 ] ) ; i + + )
{
if ( ! man - > gamepath [ i ] . path )
{
2014-02-07 08:38:40 +00:00
man - > gamepath [ i ] . base = ! Q_strcasecmp ( fname , " basegame " ) ;
2013-06-23 02:17:02 +00:00
man - > gamepath [ i ] . path = Z_StrDup ( newdir ) ;
break ;
}
}
if ( i = = sizeof ( man - > gamepath ) / sizeof ( man - > gamepath [ 0 ] ) )
{
Con_Printf ( " Too many game paths specified in manifest \n " ) ;
}
}
}
else
{
2013-08-06 02:19:06 +00:00
qboolean crcknown ;
2013-06-23 02:17:02 +00:00
int crc ;
int i , j ;
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( fname , " package " ) )
2013-06-23 02:17:02 +00:00
Cmd_ShiftArgs ( 1 , false ) ;
2013-08-06 02:19:06 +00:00
crcknown = ( strcmp ( Cmd_Argv ( 1 ) , " - " ) & & * Cmd_Argv ( 1 ) ) ;
2013-06-23 02:17:02 +00:00
crc = strtoul ( Cmd_Argv ( 1 ) , NULL , 0 ) ;
for ( i = 0 ; i < sizeof ( man - > package ) / sizeof ( man - > package [ 0 ] ) ; i + + )
{
if ( ! man - > package [ i ] . path )
{
man - > package [ i ] . path = Z_StrDup ( Cmd_Argv ( 0 ) ) ;
2013-08-06 02:19:06 +00:00
man - > package [ i ] . crcknown = crcknown ;
2013-06-23 02:17:02 +00:00
man - > package [ i ] . crc = crc ;
for ( j = 0 ; j < Cmd_Argc ( ) - 2 & & j < sizeof ( man - > package [ i ] . mirrors ) / sizeof ( man - > package [ i ] . mirrors [ 0 ] ) ; j + + )
{
man - > package [ i ] . mirrors [ j ] = Z_StrDup ( Cmd_Argv ( 2 + j ) ) ;
}
break ;
}
}
if ( i = = sizeof ( man - > package ) / sizeof ( man - > package [ 0 ] ) )
{
Con_Printf ( " Too many packages specified in manifest \n " ) ;
}
}
}
//read a manifest file
ftemanifest_t * FS_Manifest_Parse ( const char * data )
{
ftemanifest_t * man ;
if ( ! data )
return NULL ;
while ( * data = = ' ' | | * data = = ' \t ' | | * data = = ' \r ' | | * data = = ' \n ' )
data + + ;
if ( ! * data )
return NULL ;
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
man = FS_Manifest_Create ( ) ;
while ( data & & * data )
{
data = Cmd_TokenizeString ( ( char * ) data , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
}
2013-08-06 02:19:06 +00:00
if ( ! man - > installation )
{ //every manifest should have an internal name specified, so we can use the correct basedir
//if we don't recognise it, then we'll typically prompt (or just use the working directory), but always assuming a default at least ensures things are sane.
//fixme: we should probably fill in the basegame here (and share that logic with the legacy manifest generation code)
data = Cmd_TokenizeString ( ( char * ) " game quake " , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
}
2013-06-23 02:17:02 +00:00
return man ;
}
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
//======================================================================================================
2005-08-26 22:52:26 +00:00
typedef struct searchpath_s
{
2013-06-23 02:17:02 +00:00
searchpathfuncs_t * handle ;
unsigned int flags ;
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
char logicalpath [ MAX_OSPATH ] ; //printable hunam-readable location of the package. generally includes a system path, including nested packages.
2008-11-09 22:29:28 +00:00
char purepath [ 256 ] ; //server tracks the path used to load them so it can tell the client
2005-08-26 22:52:26 +00:00
int crc_check ; //client sorts packs according to this checksum
int crc_reply ; //client sends a different crc back to the server, for the paks it's actually loaded.
struct searchpath_s * next ;
struct searchpath_s * nextpure ;
} searchpath_t ;
2013-06-23 02:17:02 +00:00
static ftemanifest_t * fs_manifest ; //currently active manifest.
static searchpath_t * com_searchpaths ;
static searchpath_t * com_purepaths ;
static searchpath_t * com_base_searchpaths ; // without gamedirs
static int fs_puremode ; //0=deprioritise pure, 1=prioritise pure, 2=pure only.
static char * fs_purenames ; //list of allowed packages
static char * fs_purecrcs ; //list of crcs for those packages. one token per package.
static unsigned int fs_pureseed ; //used as a key so the server knows we're obeying. completely unreliable/redundant in an open source project, but needed for q3 network compat.
2005-08-26 22:52:26 +00:00
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
int QDECL COM_FileSize ( const char * path )
2005-08-26 22:52:26 +00:00
{
int len ;
2005-12-21 03:07:33 +00:00
flocation_t loc ;
len = FS_FLocateFile ( path , FSLFRT_LENGTH , & loc ) ;
2005-08-26 22:52:26 +00:00
return len ;
}
2013-06-23 02:17:02 +00:00
//appends a / on the end of the directory if it does not already have one.
void FS_CleanDir ( char * out , int outlen )
{
int olen = strlen ( out ) ;
if ( ! olen | | olen > = outlen - 1 )
return ;
if ( out [ olen - 1 ] = = ' \\ ' )
out [ olen - 1 ] = ' / ' ;
else if ( out [ olen - 1 ] ! = ' / ' )
{
out [ olen + 1 ] = ' \0 ' ;
out [ olen ] = ' / ' ;
}
}
2005-08-26 22:52:26 +00:00
/*
= = = = = = = = = = = =
COM_Path_f
= = = = = = = = = = = =
*/
2013-12-17 22:45:37 +00:00
static void COM_PathLine ( searchpath_t * s )
{
Con_Printf ( " %s %s%s%s%s%s \n " , s - > logicalpath ,
( s - > flags & SPF_REFERENCED ) ? " ^[(ref) \\ tip \\ Referenced \\ desc \\ Package will auto-download to clients^] " : " " ,
( s - > flags & SPF_TEMPORARY ) ? " ^[(temp) \\ tip \\ Temporary \\ desc \\ Flushed on map change^] " : " " ,
( s - > flags & SPF_COPYPROTECTED ) ? " ^[(c) \\ tip \\ Copyrighted \\ desc \\ Copy-Protected and is not downloadable^] " : " " ,
( s - > flags & SPF_EXPLICIT ) ? " ^[(e) \\ tip \\ Explicit \\ desc \\ Loaded explicitly by the gamedir^] " : " " ,
( s - > flags & SPF_UNTRUSTED ) ? " ^[(u) \\ tip \\ Untrusted \\ desc \\ Configs and scripts will not be given access to passwords^] " : " " ) ;
}
2005-08-26 22:52:26 +00:00
void COM_Path_f ( void )
{
searchpath_t * s ;
2005-11-21 21:09:11 +00:00
2013-11-29 14:36:47 +00:00
Con_TPrintf ( " Current search path: \n " ) ;
2005-11-21 21:09:11 +00:00
2013-06-23 02:17:02 +00:00
if ( com_purepaths | | fs_puremode )
2005-08-26 22:52:26 +00:00
{
2007-09-17 20:35:39 +00:00
Con_Printf ( " Pure paths: \n " ) ;
2005-08-26 22:52:26 +00:00
for ( s = com_purepaths ; s ; s = s - > nextpure )
{
2013-12-17 22:45:37 +00:00
COM_PathLine ( s ) ;
2005-08-26 22:52:26 +00:00
}
Con_Printf ( " ---------- \n " ) ;
2013-06-23 02:17:02 +00:00
if ( fs_puremode = = 2 )
Con_Printf ( " Inactive paths: \n " ) ;
else
Con_Printf ( " Impure paths: \n " ) ;
2005-08-26 22:52:26 +00:00
}
for ( s = com_searchpaths ; s ; s = s - > next )
{
if ( s = = com_base_searchpaths )
Con_Printf ( " ---------- \n " ) ;
2013-12-17 22:45:37 +00:00
COM_PathLine ( s ) ;
2005-08-26 22:52:26 +00:00
}
}
/*
= = = = = = = = = = = =
COM_Dir_f
= = = = = = = = = = = =
*/
2014-02-07 08:38:40 +00:00
static int QDECL COM_Dir_List ( const char * name , qofs_t size , void * parm , searchpathfuncs_t * spath )
2005-08-26 22:52:26 +00:00
{
2013-03-31 04:21:08 +00:00
searchpath_t * s ;
for ( s = com_searchpaths ; s ; s = s - > next )
{
if ( s - > handle = = spath )
break ;
}
2014-02-07 08:38:40 +00:00
if ( size > 1.0 * 1024 * 1024 * 1024 )
Con_Printf ( " %s \t (%#.3ggb) (%s) \n " , name , size / ( 1024.0 * 1024 * 1024 ) , s ? s - > logicalpath : " ?? " ) ;
else if ( size > 1.0 * 1024 * 1024 )
Con_Printf ( " %s \t (%#.3gmb) (%s) \n " , name , size / ( 1024.0 * 1024 ) , s ? s - > logicalpath : " ?? " ) ;
else if ( size > 1.0 * 1024 )
Con_Printf ( " %s \t (%#.3gkb) (%s) \n " , name , size / 1024.0 , s ? s - > logicalpath : " ?? " ) ;
else
Con_Printf ( " %s \t (%ub) (%s) \n " , name , ( unsigned int ) size , s ? s - > logicalpath : " ?? " ) ;
2005-08-26 22:52:26 +00:00
return 1 ;
}
void COM_Dir_f ( void )
{
char match [ MAX_QPATH ] ;
Q_strncpyz ( match , Cmd_Argv ( 1 ) , sizeof ( match ) ) ;
if ( Cmd_Argc ( ) > 2 )
{
strncat ( match , " /*. " , sizeof ( match ) - 1 ) ;
match [ sizeof ( match ) - 1 ] = ' \0 ' ;
strncat ( match , Cmd_Argv ( 2 ) , sizeof ( match ) - 1 ) ;
match [ sizeof ( match ) - 1 ] = ' \0 ' ;
}
2013-05-03 04:28:08 +00:00
// else
// strncat(match, "/*", sizeof(match)-1);
2005-08-26 22:52:26 +00:00
COM_EnumerateFiles ( match , COM_Dir_List , NULL ) ;
}
/*
= = = = = = = = = = = =
COM_Locate_f
= = = = = = = = = = = =
*/
void COM_Locate_f ( void )
{
flocation_t loc ;
2005-10-16 03:47:26 +00:00
if ( FS_FLocateFile ( Cmd_Argv ( 1 ) , FSLFRT_LENGTH , & loc ) > = 0 )
2005-08-26 22:52:26 +00:00
{
if ( ! * loc . rawname )
2005-10-16 03:47:26 +00:00
{
2014-03-30 00:39:37 +00:00
Con_Printf ( " File is %u bytes compressed inside %s \n " , ( unsigned ) loc . len , loc . search - > logicalpath ) ;
2005-10-16 03:47:26 +00:00
}
2005-08-26 22:52:26 +00:00
else
2006-01-02 22:53:29 +00:00
{
2014-03-30 00:39:37 +00:00
Con_Printf ( " Inside %s (%u bytes) \n %s \n " , loc . rawname , ( unsigned ) loc . len , loc . search - > logicalpath ) ;
2006-01-02 22:53:29 +00:00
}
2005-08-26 22:52:26 +00:00
}
else
Con_Printf ( " Not found \n " ) ;
}
/*
= = = = = = = = = = = =
COM_WriteFile
The filename will be prefixed by the current game directory
= = = = = = = = = = = =
*/
2009-04-02 22:25:54 +00:00
void COM_WriteFile ( const char * filename , const void * data , int len )
2005-08-26 22:52:26 +00:00
{
2006-03-11 03:12:10 +00:00
vfsfile_t * vfs ;
2005-08-26 22:52:26 +00:00
2006-03-11 03:12:10 +00:00
Sys_Printf ( " COM_WriteFile: %s \n " , filename ) ;
2005-11-21 21:09:11 +00:00
2006-03-11 03:12:10 +00:00
FS_CreatePath ( filename , FS_GAMEONLY ) ;
vfs = FS_OpenVFS ( filename , " wb " , FS_GAMEONLY ) ;
if ( vfs )
2005-08-26 22:52:26 +00:00
{
2006-03-11 03:12:10 +00:00
VFS_WRITE ( vfs , data , len ) ;
VFS_CLOSE ( vfs ) ;
2005-08-26 22:52:26 +00:00
}
2005-11-21 21:09:11 +00:00
2005-08-26 22:52:26 +00:00
com_fschanged = true ;
}
/*
= = = = = = = = = = = =
COM_CreatePath
Only used for CopyFile and download
= = = = = = = = = = = =
*/
2010-07-18 08:42:59 +00:00
static void COM_CreatePath ( char * path )
2005-08-26 22:52:26 +00:00
{
char * ofs ;
2005-11-21 21:09:11 +00:00
2005-08-26 22:52:26 +00:00
for ( ofs = path + 1 ; * ofs ; ofs + + )
{
if ( * ofs = = ' / ' )
{ // create the directory
* ofs = 0 ;
Sys_mkdir ( path ) ;
* ofs = ' / ' ;
}
}
}
/*
= = = = = = = = = = =
COM_CopyFile
Copies a file over from the net to the local cache , creating any directories
needed . This is for the convenience of developers using ISDN from home .
= = = = = = = = = = =
*/
2009-03-03 01:52:30 +00:00
/*
static void COM_CopyFile ( char * netpath , char * cachepath )
2005-08-26 22:52:26 +00:00
{
FILE * in , * out ;
int remaining , count ;
char buf [ 4096 ] ;
2005-11-21 21:09:11 +00:00
remaining = COM_FileOpenRead ( netpath , & in ) ;
2005-08-26 22:52:26 +00:00
COM_CreatePath ( cachepath ) ; // create directories up to the cache file
out = fopen ( cachepath , " wb " ) ;
if ( ! out )
Sys_Error ( " Error opening %s " , cachepath ) ;
2005-11-21 21:09:11 +00:00
2005-08-26 22:52:26 +00:00
while ( remaining )
{
if ( remaining < sizeof ( buf ) )
count = remaining ;
else
count = sizeof ( buf ) ;
fread ( buf , 1 , count , in ) ;
fwrite ( buf , 1 , count , out ) ;
remaining - = count ;
}
fclose ( in ) ;
fclose ( out ) ;
}
2009-03-03 01:52:30 +00:00
//*/
2005-08-26 22:52:26 +00:00
int fs_hash_dups ;
int fs_hash_files ;
2014-02-07 08:38:40 +00:00
//normally the filesystem drivers pass a pre-allocated bucket and static strings to us
//the OS driver can't really be expected to track things that reliably however, so it just gives names via the stack.
//these files are grouped up to avoid excessive memory allocations.
struct fsbucketblock
{
struct fsbucketblock * prev ;
int used ;
int total ;
qbyte data [ 1 ] ;
} ;
static struct fsbucketblock * fs_hash_filebuckets ;
2012-05-09 15:30:53 +00:00
void FS_FlushFSHashReally ( void )
2005-08-26 22:52:26 +00:00
{
if ( filesystemhash . numbuckets )
{
int i ;
for ( i = 0 ; i < filesystemhash . numbuckets ; i + + )
filesystemhash . bucket [ i ] = NULL ;
2014-02-07 08:38:40 +00:00
}
while ( fs_hash_filebuckets )
{
struct fsbucketblock * n = fs_hash_filebuckets - > prev ;
Z_Free ( fs_hash_filebuckets ) ;
fs_hash_filebuckets = n ;
2005-08-26 22:52:26 +00:00
}
com_fschanged = true ;
}
2012-05-09 15:30:53 +00:00
void FS_FlushFSHashWritten ( void )
{
/*automatically handled*/
}
void FS_FlushFSHashRemoved ( void )
{
FS_FlushFSHashReally ( ) ;
}
2013-05-03 04:28:08 +00:00
static void QDECL FS_AddFileHash ( int depth , const char * fname , fsbucket_t * filehandle , void * pathhandle )
2012-05-09 15:30:53 +00:00
{
fsbucket_t * old ;
old = Hash_GetInsensativeBucket ( & filesystemhash , fname ) ;
if ( old )
{
fs_hash_dups + + ;
2014-02-07 08:38:40 +00:00
if ( depth > = old - > depth )
2012-05-09 15:30:53 +00:00
{
return ;
}
//remove the old version
Hash_RemoveBucket ( & filesystemhash , fname , & old - > buck ) ;
}
if ( ! filehandle )
{
2014-02-07 08:38:40 +00:00
int nlen = strlen ( fname ) + 1 ;
if ( ! fs_hash_filebuckets | | fs_hash_filebuckets - > used + sizeof ( * filehandle ) + nlen > fs_hash_filebuckets - > total )
{
void * o = fs_hash_filebuckets ;
fs_hash_filebuckets = Z_Malloc ( 65536 ) ;
fs_hash_filebuckets - > total = 65536 - sizeof ( * fs_hash_filebuckets ) ;
fs_hash_filebuckets - > prev = o ;
}
filehandle = ( fsbucket_t * ) ( fs_hash_filebuckets - > data + fs_hash_filebuckets - > used ) ;
fs_hash_filebuckets - > used + = sizeof ( * filehandle ) + nlen ;
2012-05-09 15:30:53 +00:00
if ( ! filehandle )
return ; //eep!
2014-02-07 08:38:40 +00:00
memcpy ( ( char * ) ( filehandle + 1 ) , fname , nlen ) ;
2012-05-09 15:30:53 +00:00
fname = ( char * ) ( filehandle + 1 ) ;
}
2014-02-07 08:38:40 +00:00
filehandle - > depth = depth ;
2012-05-09 15:30:53 +00:00
Hash_AddInsensative ( & filesystemhash , fname , pathhandle , & filehandle - > buck ) ;
fs_hash_files + + ;
}
2005-08-26 22:52:26 +00:00
void FS_RebuildFSHash ( void )
{
2012-05-09 15:30:53 +00:00
int depth = 1 ;
2005-08-26 22:52:26 +00:00
searchpath_t * search ;
2014-02-07 08:38:40 +00:00
if ( ! com_fschanged )
return ;
2005-08-26 22:52:26 +00:00
if ( ! filesystemhash . numbuckets )
{
filesystemhash . numbuckets = 1024 ;
2008-05-25 01:06:37 +00:00
filesystemhash . bucket = ( bucket_t * * ) Z_Malloc ( Hash_BytesForBuckets ( filesystemhash . numbuckets ) ) ;
2005-08-26 22:52:26 +00:00
}
else
{
2012-05-09 15:30:53 +00:00
FS_FlushFSHashRemoved ( ) ;
2005-08-26 22:52:26 +00:00
}
Hash_InitTable ( & filesystemhash , filesystemhash . numbuckets , filesystemhash . bucket ) ;
fs_hash_dups = 0 ;
fs_hash_files = 0 ;
if ( com_purepaths )
{ //go for the pure paths first.
for ( search = com_purepaths ; search ; search = search - > nextpure )
{
2013-06-23 02:17:02 +00:00
search - > handle - > BuildHash ( search - > handle , depth + + , FS_AddFileHash ) ;
2005-08-26 22:52:26 +00:00
}
}
2013-06-23 02:17:02 +00:00
if ( fs_puremode < 2 )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
for ( search = com_searchpaths ; search ; search = search - > next )
{
search - > handle - > BuildHash ( search - > handle , depth + + , FS_AddFileHash ) ;
}
2005-08-26 22:52:26 +00:00
}
com_fschanged = false ;
2010-11-02 23:17:25 +00:00
Con_DPrintf ( " %i unique files, %i duplicates \n " , fs_hash_files , fs_hash_dups ) ;
2005-08-26 22:52:26 +00:00
}
/*
= = = = = = = = = = =
COM_FindFile
Finds the file in the search path .
Sets com_filesize and one of handle or file
= = = = = = = = = = =
*/
//if loc is valid, loc->search is always filled in, the others are filled on success.
//returns -1 if couldn't find.
2009-04-01 22:03:56 +00:00
int FS_FLocateFile ( const char * filename , FSLF_ReturnType_e returntype , flocation_t * loc )
2005-08-26 22:52:26 +00:00
{
2014-01-13 02:42:25 +00:00
int depth = 0 ;
2005-08-26 22:52:26 +00:00
searchpath_t * search ;
2009-04-01 22:03:56 +00:00
char cleanpath [ MAX_QPATH ] ;
2014-01-13 02:42:25 +00:00
flocation_t allownoloc ;
2005-08-26 22:52:26 +00:00
void * pf ;
2014-01-13 02:42:25 +00:00
unsigned int found = FF_NOTFOUND ;
if ( ! loc )
loc = & allownoloc ;
loc - > index = 0 ;
loc - > offset = 0 ;
* loc - > rawname = 0 ;
loc - > search = NULL ;
loc - > len = - 1 ;
2005-08-26 22:52:26 +00:00
2009-04-01 22:03:56 +00:00
filename = FS_GetCleanPath ( filename , cleanpath , sizeof ( cleanpath ) ) ;
if ( ! filename )
2009-03-03 01:52:30 +00:00
{
pf = NULL ;
goto fail ;
}
2014-02-07 08:38:40 +00:00
if ( com_fs_cache . ival & & ! com_fschanged )
2005-08-26 22:52:26 +00:00
{
pf = Hash_GetInsensative ( & filesystemhash , filename ) ;
if ( ! pf )
goto fail ;
}
else
pf = NULL ;
2014-01-13 02:42:25 +00:00
if ( com_purepaths & & found = = FF_NOTFOUND )
2005-08-26 22:52:26 +00:00
{
2014-01-13 02:42:25 +00:00
//check if its in one of the 'pure' packages. these override the default ones.
2005-08-26 22:52:26 +00:00
for ( search = com_purepaths ; search ; search = search - > nextpure )
{
2013-09-26 09:24:52 +00:00
depth + = ( ( search - > flags & SPF_EXPLICIT ) | | returntype = = FSLFRT_DEPTH_ANYPATH ) ;
2012-02-27 12:23:15 +00:00
fs_finds + + ;
2014-01-13 02:42:25 +00:00
found = search - > handle - > FindFile ( search - > handle , loc , filename , pf ) ;
if ( found )
2005-08-26 22:52:26 +00:00
{
2014-01-13 02:42:25 +00:00
search - > flags | = fs_referencetype ;
loc - > search = search ;
2013-06-23 02:17:02 +00:00
com_file_copyprotected = ! ! ( search - > flags & SPF_COPYPROTECTED ) ;
com_file_untrusted = ! ! ( search - > flags & SPF_UNTRUSTED ) ;
2014-01-13 02:42:25 +00:00
break ;
2005-08-26 22:52:26 +00:00
}
}
}
2014-01-13 02:42:25 +00:00
if ( fs_puremode < 2 & & found = = FF_NOTFOUND )
2013-06-23 02:17:02 +00:00
{
2014-01-13 02:42:25 +00:00
// optionally check the non-pure paths too.
2013-06-23 02:17:02 +00:00
for ( search = com_searchpaths ; search ; search = search - > next )
2005-08-26 22:52:26 +00:00
{
2013-09-26 09:24:52 +00:00
depth + = ( ( search - > flags & SPF_EXPLICIT ) | | returntype = = FSLFRT_DEPTH_ANYPATH ) ;
2013-06-23 02:17:02 +00:00
fs_finds + + ;
2014-01-13 02:42:25 +00:00
found = search - > handle - > FindFile ( search - > handle , loc , filename , pf ) ;
if ( found )
2005-12-21 03:07:33 +00:00
{
2013-06-23 02:17:02 +00:00
search - > flags | = fs_referencetype ;
2014-01-13 02:42:25 +00:00
loc - > search = search ;
2013-06-23 02:17:02 +00:00
com_file_copyprotected = ! ! ( search - > flags & SPF_COPYPROTECTED ) ;
com_file_untrusted = ! ! ( search - > flags & SPF_UNTRUSTED ) ;
2014-01-13 02:42:25 +00:00
break ;
2005-12-21 03:07:33 +00:00
}
2005-08-26 22:52:26 +00:00
}
}
fail :
2014-01-13 02:42:25 +00:00
if ( found = = FF_SYMLINK )
{
static int blocklink ;
if ( blocklink < 4 & & loc - > len < MAX_QPATH )
{
//read the link target
char * s , * b ;
char targname [ MAX_QPATH ] ;
char mergedname [ MAX_QPATH ] ;
targname [ loc - > len ] = 0 ;
loc - > search - > handle - > ReadFile ( loc - > search - > handle , loc , targname ) ;
//properlyish unixify
2014-02-13 23:54:57 +00:00
while ( ( s = strchr ( targname , ' \\ ' ) ) )
2014-01-13 02:42:25 +00:00
* s = ' / ' ;
if ( * targname = = ' / ' )
Q_strncpyz ( mergedname , targname + 1 , sizeof ( mergedname ) ) ;
else
{
Q_strncpyz ( mergedname , filename , sizeof ( mergedname ) ) ;
2014-02-13 23:54:57 +00:00
while ( ( s = strchr ( mergedname , ' \\ ' ) ) )
2014-01-13 02:42:25 +00:00
* s = ' / ' ;
b = COM_SkipPath ( mergedname ) ;
* b = 0 ;
for ( s = targname ; ! strncmp ( s , " ../ " , 3 ) & & b > mergedname ; )
{
s + = 3 ;
if ( b [ - 1 ] = = ' / ' )
* - - b = 0 ;
* b = 0 ;
b = strrchr ( mergedname , ' / ' ) ;
if ( b )
* + + b = 0 ;
else
{
//no prefix left.
* mergedname = 0 ;
break ;
}
}
b = mergedname + strlen ( mergedname ) ;
Q_strncpyz ( b , s , sizeof ( mergedname ) - ( b - mergedname ) ) ;
}
//and locate that instead.
blocklink + + ;
depth = FS_FLocateFile ( mergedname , returntype , loc ) ;
blocklink - - ;
if ( ! loc - > search )
Con_Printf ( " Symlink %s -> %s (%s) is dead \n " , filename , targname , mergedname ) ;
return depth ;
}
}
2005-08-26 22:52:26 +00:00
/* if (len>=0)
{
if ( loc )
Con_Printf ( " Found %s:%i \n " , loc - > rawname , loc - > len ) ;
else
Con_Printf ( " Found %s \n " , filename ) ;
}
else
Con_Printf ( " Failed \n " ) ;
2006-03-04 20:43:48 +00:00
*/
2006-01-28 19:34:21 +00:00
if ( returntype = = FSLFRT_IFFOUND )
2014-01-13 02:42:25 +00:00
return ( found ! = FF_NOTFOUND ) & & ( loc - > len ! = - 1 ) ;
2006-01-28 19:34:21 +00:00
else if ( returntype = = FSLFRT_LENGTH )
2014-01-13 02:42:25 +00:00
{
if ( found = = FF_NOTFOUND )
return - 1 ;
return loc - > len ;
}
2005-08-26 22:52:26 +00:00
else
2014-01-13 02:42:25 +00:00
{
if ( found = = FF_NOTFOUND )
return 0x7fffffff ;
2005-08-26 22:52:26 +00:00
return depth ;
2014-01-13 02:42:25 +00:00
}
2005-08-26 22:52:26 +00:00
}
2006-01-02 22:53:29 +00:00
2013-12-17 22:45:37 +00:00
char * FS_WhichPackForLocation ( flocation_t * loc , qboolean makereferenced )
2008-11-09 22:29:28 +00:00
{
char * ret ;
if ( ! loc - > search )
return NULL ; //huh? not a valid location.
ret = strchr ( loc - > search - > purepath , ' / ' ) ;
2013-12-17 22:45:37 +00:00
if ( ret )
{
ret + + ;
if ( ! strchr ( ret , ' / ' ) )
{
if ( makereferenced )
loc - > search - > flags | = SPF_REFERENCED ;
return ret ;
}
}
return NULL ;
2008-11-09 22:29:28 +00:00
}
2011-12-05 15:23:40 +00:00
/*requires extension*/
2012-01-24 04:24:14 +00:00
qboolean FS_GetPackageDownloadable ( const char * package )
2011-12-05 15:23:40 +00:00
{
searchpath_t * search ;
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
for ( search = com_searchpaths ; search ; search = search - > next )
2011-12-05 15:23:40 +00:00
{
if ( ! strcmp ( package , search - > purepath ) )
2013-06-23 02:17:02 +00:00
return ! ( search - > flags & SPF_COPYPROTECTED ) ;
2011-12-05 15:23:40 +00:00
}
return false ;
}
2006-01-02 22:53:29 +00:00
char * FS_GetPackHashes ( char * buffer , int buffersize , qboolean referencedonly )
{
searchpath_t * search ;
buffersize - - ;
* buffer = 0 ;
if ( com_purepaths )
{
for ( search = com_purepaths ; search ; search = search - > nextpure )
{
Q_strncatz ( buffer , va ( " %i " , search - > crc_check ) , buffersize ) ;
}
return buffer ;
}
else
{
for ( search = com_searchpaths ; search ; search = search - > next )
{
2013-06-23 02:17:02 +00:00
if ( ! search - > crc_check & & search - > handle - > GeneratePureCRC )
search - > crc_check = search - > handle - > GeneratePureCRC ( search - > handle , 0 , 0 ) ;
2006-01-02 22:53:29 +00:00
if ( search - > crc_check )
{
Q_strncatz ( buffer , va ( " %i " , search - > crc_check ) , buffersize ) ;
}
}
return buffer ;
}
}
2011-12-05 15:23:40 +00:00
/*
referencedonly = 0 : show all paks
referencedonly = 1 : show only paks that are referenced ( q3 - compat )
referencedonly = 2 : show all paks , but paks that are referenced are prefixed with a star
ext = 0 : hide extensions ( q3 - compat )
ext = 1 : show extensions .
*/
char * FS_GetPackNames ( char * buffer , int buffersize , int referencedonly , qboolean ext )
2006-01-02 22:53:29 +00:00
{
2010-11-10 03:32:47 +00:00
char temp [ MAX_OSPATH ] ;
2008-11-09 22:29:28 +00:00
searchpath_t * search ;
buffersize - - ;
* buffer = 0 ;
2009-06-03 09:09:35 +00:00
2008-11-09 22:29:28 +00:00
if ( com_purepaths )
{
for ( search = com_purepaths ; search ; search = search - > nextpure )
{
2013-06-23 02:17:02 +00:00
if ( referencedonly = = 0 & & ! ( search - > flags & SPF_REFERENCED ) )
2011-12-05 15:23:40 +00:00
continue ;
2013-06-23 02:17:02 +00:00
if ( referencedonly = = 2 & & ( search - > flags & SPF_REFERENCED ) )
2011-12-05 15:23:40 +00:00
Q_strncatz ( buffer , " * " , buffersize ) ;
2011-10-27 16:16:29 +00:00
if ( ! ext )
{
COM_StripExtension ( search - > purepath , temp , sizeof ( temp ) ) ;
Q_strncatz ( buffer , va ( " %s " , temp ) , buffersize ) ;
}
else
{
Q_strncatz ( buffer , va ( " %s " , search - > purepath ) , buffersize ) ;
}
2008-11-09 22:29:28 +00:00
}
return buffer ;
}
else
{
for ( search = com_searchpaths ; search ; search = search - > next )
{
2013-06-23 02:17:02 +00:00
if ( ! search - > crc_check & & search - > handle - > GeneratePureCRC )
search - > crc_check = search - > handle - > GeneratePureCRC ( search - > handle , 0 , 0 ) ;
2008-11-09 22:29:28 +00:00
if ( search - > crc_check )
{
2013-06-23 02:17:02 +00:00
if ( referencedonly = = 0 & & ! ( search - > flags & SPF_REFERENCED ) )
2011-12-05 15:23:40 +00:00
continue ;
2013-06-23 02:17:02 +00:00
if ( referencedonly = = 2 & & ( search - > flags & SPF_REFERENCED ) )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
{
// '*' prefix is meant to mean 'referenced'.
//really all that means to the client is that it definitely wants to download it.
//if its copyrighted, the client shouldn't try to do so, as it won't be allowed.
2013-06-23 02:17:02 +00:00
if ( ! ( search - > flags & SPF_COPYPROTECTED ) )
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
Q_strncatz ( buffer , " * " , buffersize ) ;
}
2011-12-05 15:23:40 +00:00
2011-10-27 16:16:29 +00:00
if ( ! ext )
{
COM_StripExtension ( search - > purepath , temp , sizeof ( temp ) ) ;
Q_strncatz ( buffer , va ( " %s " , temp ) , buffersize ) ;
}
else
{
Q_strncatz ( buffer , va ( " %s " , search - > purepath ) , buffersize ) ;
}
2008-11-09 22:29:28 +00:00
}
}
return buffer ;
}
2006-01-02 22:53:29 +00:00
}
2011-12-05 15:23:40 +00:00
void FS_ReferenceControl ( unsigned int refflag , unsigned int resetflags )
{
searchpath_t * s ;
2013-06-23 02:17:02 +00:00
refflag & = SPF_REFERENCED ;
resetflags & = SPF_REFERENCED ;
2011-12-05 15:23:40 +00:00
if ( resetflags )
{
for ( s = com_searchpaths ; s ; s = s - > next )
{
2013-06-23 02:17:02 +00:00
s - > flags & = ~ resetflags ;
2011-12-05 15:23:40 +00:00
}
}
fs_referencetype = refflag ;
}
2009-04-01 22:03:56 +00:00
//outbuf might not be written into
static const char * FS_GetCleanPath ( const char * pattern , char * outbuf , int outlen )
2005-12-21 03:07:33 +00:00
{
2009-03-03 01:52:30 +00:00
char * s ;
2009-04-01 22:03:56 +00:00
2005-12-21 03:07:33 +00:00
if ( strchr ( pattern , ' \\ ' ) )
{
2009-04-01 22:03:56 +00:00
Q_strncpyz ( outbuf , pattern , outlen ) ;
pattern = outbuf ;
2013-10-29 17:38:22 +00:00
Con_DPrintf ( " Warning: \\ characters in filename %s \n " , pattern ) ;
2006-03-04 20:43:48 +00:00
while ( ( s = strchr ( pattern , ' \\ ' ) ) )
2009-04-01 22:03:56 +00:00
{
2005-12-21 03:07:33 +00:00
* s = ' / ' ;
2009-04-01 22:03:56 +00:00
}
2005-12-21 03:07:33 +00:00
}
2009-03-03 01:52:30 +00:00
if ( strstr ( pattern , " // " ) )
{
//amiga uses // as equivelent to /../
2010-12-18 17:02:47 +00:00
//so strip those out
//any other system ignores the extras
2009-04-01 22:03:56 +00:00
Q_strncpyz ( outbuf , pattern , outlen ) ;
pattern = outbuf ;
2010-12-18 17:02:47 +00:00
Con_DPrintf ( " Warning: // characters in filename %s \n " , pattern ) ;
2009-04-02 22:25:54 +00:00
while ( ( s = strstr ( pattern , " // " ) ) )
2009-03-03 01:52:30 +00:00
{
s + + ;
while ( * s )
{
* s = * ( s + 1 ) ;
s + + ;
}
}
}
2010-12-18 17:02:47 +00:00
if ( * pattern = = ' / ' )
{
/*'fix up' and ignore, compat with q3*/
Con_DPrintf ( " Error: absolute path in filename %s \n " , pattern ) ;
pattern + + ;
}
2009-03-03 01:52:30 +00:00
2005-12-21 03:07:33 +00:00
if ( strstr ( pattern , " .. " ) )
2008-01-28 13:27:30 +00:00
Con_Printf ( " Error: '..' characters in filename %s \n " , pattern ) ;
2009-03-03 01:52:30 +00:00
else if ( strstr ( pattern , " : " ) ) //win32 drive seperator (or mac path seperator, but / works there and they're used to it) (or amiga device separator)
2005-12-21 03:07:33 +00:00
Con_Printf ( " Error: absolute path in filename %s \n " , pattern ) ;
2013-05-03 04:28:08 +00:00
else if ( strlen ( pattern ) > outlen )
Con_Printf ( " Error: path %s too long \n " , pattern ) ;
2005-12-21 03:07:33 +00:00
else
2009-03-03 01:52:30 +00:00
{
2009-04-01 22:03:56 +00:00
return pattern ;
2009-03-03 01:52:30 +00:00
}
2009-04-01 22:03:56 +00:00
return NULL ;
2005-12-21 03:07:33 +00:00
}
2009-04-01 22:03:56 +00:00
vfsfile_t * VFS_Filter ( const char * filename , vfsfile_t * handle )
2006-02-11 02:09:43 +00:00
{
// char *ext;
if ( ! handle | | handle - > WriteBytes | | handle - > seekingisabadplan ) //only on readonly files
return handle ;
// ext = COM_FileExtension (filename);
2006-10-05 21:59:43 +00:00
# ifdef AVAIL_ZLIB
2014-02-07 08:38:40 +00:00
// if (!Q_strcasecmp(ext, ".gz"))
2006-02-11 02:09:43 +00:00
{
2013-06-23 02:17:02 +00:00
return FS_DecompressGZip ( handle , NULL ) ;
2006-02-11 02:09:43 +00:00
}
2009-04-01 22:03:56 +00:00
# endif
return handle ;
}
qboolean FS_NativePath ( const char * fname , enum fs_relative relativeto , char * out , int outlen )
{
char cleanname [ MAX_QPATH ] ;
fname = FS_GetCleanPath ( fname , cleanname , sizeof ( cleanname ) ) ;
if ( ! fname )
return false ;
switch ( relativeto )
{
case FS_GAMEONLY :
case FS_GAME :
if ( * com_homedir )
snprintf ( out , outlen , " %s%s/%s " , com_homedir , gamedirfile , fname ) ;
else
snprintf ( out , outlen , " %s%s/%s " , com_quakedir , gamedirfile , fname ) ;
break ;
case FS_SKINS :
2013-06-23 02:17:02 +00:00
//FIXME: validate that qw/ is actually loaded and valid
2009-04-01 22:03:56 +00:00
if ( * com_homedir )
snprintf ( out , outlen , " %sqw/skins/%s " , com_homedir , fname ) ;
else
snprintf ( out , outlen , " %sqw/skins/%s " , com_quakedir , fname ) ;
break ;
2013-05-03 04:28:08 +00:00
case FS_BINARYPATH :
if ( host_parms . binarydir & & * host_parms . binarydir )
snprintf ( out , outlen , " %s%s " , host_parms . binarydir , fname ) ;
else
snprintf ( out , outlen , " %s%s " , host_parms . basedir , fname ) ;
break ;
2009-04-01 22:03:56 +00:00
case FS_ROOT :
if ( * com_homedir )
snprintf ( out , outlen , " %s%s " , com_homedir , fname ) ;
else
snprintf ( out , outlen , " %s%s " , com_quakedir , fname ) ;
break ;
case FS_CONFIGONLY :
2013-06-23 02:17:02 +00:00
//FIXME: use the highest-precidence active system path instead
2009-04-01 22:03:56 +00:00
if ( * com_homedir )
snprintf ( out , outlen , " %sfte/%s " , com_homedir , fname ) ;
else
snprintf ( out , outlen , " %sfte/%s " , com_quakedir , fname ) ;
break ;
default :
2013-05-03 04:28:08 +00:00
Sys_Error ( " FS_NativePath case not handled \n " ) ;
2009-04-01 22:03:56 +00:00
}
return true ;
2006-02-11 02:09:43 +00:00
}
2011-10-27 16:16:29 +00:00
/*locates and opens a file*/
2009-04-01 22:03:56 +00:00
vfsfile_t * FS_OpenVFS ( const char * filename , const char * mode , enum fs_relative relativeto )
2005-12-21 03:07:33 +00:00
{
2009-04-01 22:03:56 +00:00
char cleanname [ MAX_QPATH ] ;
2005-12-21 03:07:33 +00:00
char fullname [ MAX_OSPATH ] ;
flocation_t loc ;
vfsfile_t * vfs ;
//eventually, this function will be the *ONLY* way to get at files
//blanket-bans
2009-06-03 09:09:35 +00:00
2009-04-01 22:03:56 +00:00
filename = FS_GetCleanPath ( filename , cleanname , sizeof ( cleanname ) ) ;
if ( ! filename )
2005-12-21 03:07:33 +00:00
return NULL ;
2006-01-02 22:53:29 +00:00
if ( strcmp ( mode , " rb " ) )
2010-07-11 02:22:39 +00:00
if ( strcmp ( mode , " r+b " ) )
if ( strcmp ( mode , " wb " ) )
if ( strcmp ( mode , " w+b " ) )
if ( strcmp ( mode , " ab " ) )
return NULL ; //urm, unable to write/append
2006-01-02 22:53:29 +00:00
2008-11-09 22:29:28 +00:00
//if there can only be one file (eg: write access) find out where it is.
2005-12-21 03:07:33 +00:00
switch ( relativeto )
{
case FS_GAMEONLY : //OS access only, no paks
if ( * com_homedir )
{
2006-03-06 01:41:09 +00:00
snprintf ( fullname , sizeof ( fullname ) , " %s%s/%s " , com_homedir , gamedirfile , filename ) ;
2013-05-07 19:37:00 +00:00
if ( * mode = = ' w ' )
COM_CreatePath ( fullname ) ;
2005-12-21 03:07:33 +00:00
vfs = VFSOS_Open ( fullname , mode ) ;
if ( vfs )
return vfs ;
}
2006-03-06 01:41:09 +00:00
snprintf ( fullname , sizeof ( fullname ) , " %s%s/%s " , com_quakedir , gamedirfile , filename ) ;
2013-05-07 19:37:00 +00:00
if ( * mode = = ' w ' )
COM_CreatePath ( fullname ) ;
2005-12-21 03:07:33 +00:00
return VFSOS_Open ( fullname , mode ) ;
2013-06-23 02:17:02 +00:00
case FS_GAME : //load from paks in preference to system paths. overwriting be damned.
case FS_SKINS : //load from paks in preference to system paths. overwriting be damned.
FS_NativePath ( filename , relativeto , fullname , sizeof ( fullname ) ) ;
2006-03-11 05:12:33 +00:00
break ;
2013-11-29 14:36:47 +00:00
case FS_BINARYPATH :
if ( * mode = = ' w ' )
COM_CreatePath ( fullname ) ;
FS_NativePath ( filename , relativeto , fullname , sizeof ( fullname ) ) ;
return VFSOS_Open ( fullname , mode ) ;
2013-06-23 02:17:02 +00:00
case FS_ROOT : //always bypass packs and gamedirs
2005-12-21 03:07:33 +00:00
if ( * com_homedir )
{
2006-03-06 01:41:09 +00:00
snprintf ( fullname , sizeof ( fullname ) , " %s%s " , com_homedir , filename ) ;
2005-12-21 03:07:33 +00:00
vfs = VFSOS_Open ( fullname , mode ) ;
if ( vfs )
return vfs ;
}
2006-03-06 01:41:09 +00:00
snprintf ( fullname , sizeof ( fullname ) , " %s%s " , com_quakedir , filename ) ;
2005-12-21 03:07:33 +00:00
return VFSOS_Open ( fullname , mode ) ;
2013-06-23 02:17:02 +00:00
case FS_CONFIGONLY : //always bypass packs+pure.
2005-12-21 03:07:33 +00:00
if ( * com_homedir )
{
2006-03-06 01:41:09 +00:00
snprintf ( fullname , sizeof ( fullname ) , " %sfte/%s " , com_homedir , filename ) ;
2005-12-21 03:07:33 +00:00
vfs = VFSOS_Open ( fullname , mode ) ;
if ( vfs )
return vfs ;
}
2006-03-06 01:41:09 +00:00
snprintf ( fullname , sizeof ( fullname ) , " %sfte/%s " , com_quakedir , filename ) ;
2005-12-21 03:07:33 +00:00
return VFSOS_Open ( fullname , mode ) ;
default :
2006-03-11 05:12:33 +00:00
Sys_Error ( " FS_OpenVFS: Bad relative path (%i) " , relativeto ) ;
2005-12-21 03:07:33 +00:00
break ;
}
FS_FLocateFile ( filename , FSLFRT_IFFOUND , & loc ) ;
if ( loc . search )
{
2013-06-23 02:17:02 +00:00
com_file_copyprotected = ! ! ( loc . search - > flags & SPF_COPYPROTECTED ) ;
com_file_untrusted = ! ! ( loc . search - > flags & SPF_UNTRUSTED ) ;
return VFS_Filter ( filename , loc . search - > handle - > OpenVFS ( loc . search - > handle , & loc , mode ) ) ;
2005-12-21 03:07:33 +00:00
}
2006-01-02 23:46:44 +00:00
//if we're meant to be writing, best write to it.
2007-07-27 21:24:31 +00:00
if ( strchr ( mode , ' w ' ) | | strchr ( mode , ' a ' ) )
2011-02-25 04:22:14 +00:00
{
COM_CreatePath ( fullname ) ;
2006-01-02 23:46:44 +00:00
return VFSOS_Open ( fullname , mode ) ;
2011-02-25 04:22:14 +00:00
}
2005-12-21 03:07:33 +00:00
return NULL ;
}
2011-10-27 16:16:29 +00:00
/*opens a vfsfile from an already discovered location*/
2008-11-09 22:29:28 +00:00
vfsfile_t * FS_OpenReadLocation ( flocation_t * location )
{
if ( location - > search )
{
2013-06-23 02:17:02 +00:00
com_file_copyprotected = ! ! ( location - > search - > flags & SPF_COPYPROTECTED ) ;
com_file_untrusted = ! ! ( location - > search - > flags & SPF_UNTRUSTED ) ;
return VFS_Filter ( NULL , location - > search - > handle - > OpenVFS ( location - > search - > handle , location , " rb " ) ) ;
2008-11-09 22:29:28 +00:00
}
return NULL ;
}
2012-04-24 07:59:11 +00:00
qboolean FS_Rename2 ( const char * oldf , const char * newf , enum fs_relative oldrelativeto , enum fs_relative newrelativeto )
2006-01-21 00:06:49 +00:00
{
char oldfullname [ MAX_OSPATH ] ;
char newfullname [ MAX_OSPATH ] ;
2009-04-01 22:03:56 +00:00
if ( ! FS_NativePath ( oldf , oldrelativeto , oldfullname , sizeof ( oldfullname ) ) )
2012-04-24 07:59:11 +00:00
return false ;
2009-04-01 22:03:56 +00:00
if ( ! FS_NativePath ( newf , newrelativeto , newfullname , sizeof ( newfullname ) ) )
2012-04-24 07:59:11 +00:00
return false ;
2006-01-28 06:41:20 +00:00
FS_CreatePath ( newf , newrelativeto ) ;
2012-04-24 07:59:11 +00:00
return Sys_Rename ( oldfullname , newfullname ) ;
2006-01-21 00:06:49 +00:00
}
2012-04-24 07:59:11 +00:00
qboolean FS_Rename ( const char * oldf , const char * newf , enum fs_relative relativeto )
2005-12-21 03:07:33 +00:00
{
2009-04-01 22:03:56 +00:00
return FS_Rename2 ( oldf , newf , relativeto , relativeto ) ;
2005-12-21 03:07:33 +00:00
}
2012-04-24 07:59:11 +00:00
qboolean FS_Remove ( const char * fname , enum fs_relative relativeto )
2005-12-21 03:07:33 +00:00
{
2006-01-28 06:41:20 +00:00
char fullname [ MAX_OSPATH ] ;
2009-04-01 22:03:56 +00:00
if ( ! FS_NativePath ( fname , relativeto , fullname , sizeof ( fullname ) ) )
2012-04-24 07:59:11 +00:00
return false ;
2006-01-28 06:41:20 +00:00
2009-04-01 22:03:56 +00:00
return Sys_remove ( fullname ) ;
2005-12-21 03:07:33 +00:00
}
2009-04-01 22:03:56 +00:00
//create a path for the given filename (dir-only must have trailing slash)
void FS_CreatePath ( const char * pname , enum fs_relative relativeto )
2005-12-21 03:07:33 +00:00
{
char fullname [ MAX_OSPATH ] ;
2009-04-01 22:03:56 +00:00
if ( ! FS_NativePath ( pname , relativeto , fullname , sizeof ( fullname ) ) )
return ;
2009-06-03 09:09:35 +00:00
2005-12-21 03:07:33 +00:00
COM_CreatePath ( fullname ) ;
}
2005-08-26 22:52:26 +00:00
2009-04-02 22:25:54 +00:00
qboolean FS_WriteFile ( const char * filename , const void * data , int len , enum fs_relative relativeto )
2006-01-02 22:53:29 +00:00
{
vfsfile_t * f ;
FS_CreatePath ( filename , relativeto ) ;
f = FS_OpenVFS ( filename , " wb " , relativeto ) ;
if ( ! f )
return false ;
VFS_WRITE ( f , data , len ) ;
VFS_CLOSE ( f ) ;
return true ;
}
2009-04-01 22:03:56 +00:00
qboolean FS_Copy ( const char * source , const char * dest , enum fs_relative relativesource , enum fs_relative relativedest )
{
vfsfile_t * d , * s ;
char buffer [ 8192 * 8 ] ;
int read ;
qboolean result = false ;
FS_CreatePath ( dest , relativedest ) ;
s = FS_OpenVFS ( source , " rb " , relativesource ) ;
if ( s )
{
d = FS_OpenVFS ( dest , " wb " , relativedest ) ;
if ( d )
{
result = true ;
for ( ; ; )
{
read = VFS_READ ( s , buffer , sizeof ( buffer ) ) ;
if ( read < = 0 )
break ;
if ( VFS_WRITE ( d , buffer , read ) ! = read )
{
result = false ;
break ;
}
}
VFS_CLOSE ( d ) ;
if ( ! result )
FS_Remove ( dest , relativedest ) ;
}
VFS_CLOSE ( s ) ;
}
return result ;
}
2005-08-26 22:52:26 +00:00
static qbyte * loadbuf ;
static int loadsize ;
/*
= = = = = = = = = = = =
COM_LoadFile
Filename are reletive to the quake directory .
Always appends a 0 qbyte to the loaded data .
= = = = = = = = = = = =
*/
2009-04-01 22:03:56 +00:00
qbyte * COM_LoadFile ( const char * path , int usehunk )
2005-08-26 22:52:26 +00:00
{
2005-12-21 03:07:33 +00:00
vfsfile_t * f ;
2005-08-26 22:52:26 +00:00
qbyte * buf ;
2014-02-07 08:38:40 +00:00
qofs_t len ;
2006-06-04 01:43:52 +00:00
char base [ MAX_OSPATH ] ;
2005-08-26 22:52:26 +00:00
flocation_t loc ;
FS_FLocateFile ( path , FSLFRT_LENGTH , & loc ) ;
if ( ! loc . search )
return NULL ; //wasn't found
2014-02-07 08:38:40 +00:00
if ( loc . len > 0x7fffffff ) //don't malloc 5000gb sparse files or anything crazy on a 32bit system...
return NULL ;
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
f = loc . search - > handle - > OpenVFS ( loc . search - > handle , & loc , " rb " ) ;
2005-12-21 03:07:33 +00:00
if ( ! f )
return NULL ;
com_filesize = len = VFS_GETLEN ( f ) ;
2005-08-26 22:52:26 +00:00
// extract the filename base name for hunk tag
2006-03-11 03:12:10 +00:00
COM_FileBase ( path , base , sizeof ( base ) ) ;
2005-08-26 22:52:26 +00:00
if ( usehunk = = 0 )
buf = ( qbyte * ) Z_Malloc ( len + 1 ) ;
else if ( usehunk = = 2 )
buf = ( qbyte * ) Hunk_TempAlloc ( len + 1 ) ;
else if ( usehunk = = 4 )
{
if ( len + 1 > loadsize )
buf = ( qbyte * ) Hunk_TempAlloc ( len + 1 ) ;
else
buf = loadbuf ;
}
else if ( usehunk = = 5 )
buf = ( qbyte * ) BZ_Malloc ( len + 1 ) ;
else if ( usehunk = = 6 )
buf = ( qbyte * ) Hunk_TempAllocMore ( len + 1 ) ;
else
{
Sys_Error ( " COM_LoadFile: bad usehunk " ) ;
buf = NULL ;
}
if ( ! buf )
Sys_Error ( " COM_LoadFile: not enough space for %s " , path ) ;
( ( qbyte * ) buf ) [ len ] = 0 ;
2005-12-21 03:07:33 +00:00
VFS_READ ( f , buf , len ) ;
VFS_CLOSE ( f ) ;
2005-08-26 22:52:26 +00:00
return buf ;
}
2009-11-04 21:16:50 +00:00
qbyte * FS_LoadMallocFile ( const char * path )
2005-08-26 22:52:26 +00:00
{
return COM_LoadFile ( path , 5 ) ;
}
2013-07-14 12:22:51 +00:00
void * FS_LoadMallocGroupFile ( zonegroup_t * ctx , char * path )
2005-08-26 22:52:26 +00:00
{
2013-07-14 12:22:51 +00:00
char * mem = NULL ;
vfsfile_t * f = FS_OpenVFS ( path , " rb " , FS_GAME ) ;
if ( f )
{
int len = VFS_GETLEN ( f ) ;
mem = ZG_Malloc ( ctx , len + 1 ) ;
if ( mem )
{
mem [ len ] = 0 ;
if ( VFS_READ ( f , mem , len ) = = len )
com_filesize = len ;
else
mem = NULL ;
}
VFS_CLOSE ( f ) ;
}
return mem ;
2005-08-26 22:52:26 +00:00
}
2009-04-01 22:03:56 +00:00
qbyte * COM_LoadTempFile ( const char * path )
2005-08-26 22:52:26 +00:00
{
return COM_LoadFile ( path , 2 ) ;
}
2012-02-27 12:23:15 +00:00
qbyte * COM_LoadTempMoreFile ( const char * path )
2005-08-26 22:52:26 +00:00
{
return COM_LoadFile ( path , 6 ) ;
}
// uses temp hunk if larger than bufsize
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
qbyte * QDECL COM_LoadStackFile ( const char * path , void * buffer , int bufsize )
2005-08-26 22:52:26 +00:00
{
qbyte * buf ;
2005-11-21 21:09:11 +00:00
2005-08-26 22:52:26 +00:00
loadbuf = ( qbyte * ) buffer ;
loadsize = bufsize ;
buf = COM_LoadFile ( path , 4 ) ;
2005-11-21 21:09:11 +00:00
2005-08-26 22:52:26 +00:00
return buf ;
}
2009-05-24 10:11:17 +00:00
/*warning: at some point I'll change this function to return only read-only buffers*/
2014-02-07 08:38:40 +00:00
qofs_t FS_LoadFile ( char * name , void * * file )
2009-03-03 01:52:30 +00:00
{
2009-11-04 21:16:50 +00:00
* file = FS_LoadMallocFile ( name ) ;
2009-05-24 10:11:17 +00:00
if ( ! * file )
2014-02-07 08:38:40 +00:00
return ( qofs_t ) - 1 ;
2009-03-03 01:52:30 +00:00
return com_filesize ;
}
void FS_FreeFile ( void * file )
{
BZ_Free ( file ) ;
}
2014-02-07 08:38:40 +00:00
void COM_EnumerateFiles ( const char * match , int ( QDECL * func ) ( const char * , qofs_t , void * , searchpathfuncs_t * ) , void * parm )
2005-08-26 22:52:26 +00:00
{
searchpath_t * search ;
for ( search = com_searchpaths ; search ; search = search - > next )
{
// is the element a pak file?
2013-06-23 02:17:02 +00:00
if ( ! search - > handle - > EnumerateFiles ( search - > handle , match , func , parm ) )
2005-08-26 22:52:26 +00:00
break ;
}
}
void COM_FlushTempoaryPacks ( void )
{
2011-10-27 16:16:29 +00:00
searchpath_t * sp , * * link ;
link = & com_searchpaths ;
while ( * link )
2005-08-26 22:52:26 +00:00
{
2011-10-27 16:16:29 +00:00
sp = * link ;
2013-06-23 02:17:02 +00:00
if ( sp - > flags & SPF_TEMPORARY )
2011-10-27 16:16:29 +00:00
{
2012-05-09 15:30:53 +00:00
FS_FlushFSHashReally ( ) ;
2011-10-27 16:16:29 +00:00
* link = sp - > next ;
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
sp - > handle - > ClosePath ( sp - > handle ) ;
2011-10-27 16:16:29 +00:00
Z_Free ( sp ) ;
}
else
link = & sp - > next ;
2005-08-26 22:52:26 +00:00
}
2011-10-27 16:16:29 +00:00
com_purepaths = NULL ;
2005-08-26 22:52:26 +00:00
}
2014-02-07 08:38:40 +00:00
qboolean COM_LoadMapPackFile ( const char * filename , qofs_t ofs )
2005-08-26 22:52:26 +00:00
{
2005-12-21 03:07:33 +00:00
return false ;
2013-06-23 02:17:02 +00:00
}
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
static searchpath_t * FS_AddPathHandle ( searchpath_t * * oldpaths , const char * purepath , const char * probablepath , searchpathfuncs_t * handle , unsigned int flags , unsigned int loadstuff ) ;
2013-12-17 22:45:37 +00:00
searchpathfuncs_t * FS_GetOldPath ( searchpath_t * * oldpaths , const char * dir , unsigned int * keepflags )
2013-06-23 02:17:02 +00:00
{
searchpath_t * p ;
searchpathfuncs_t * r = NULL ;
2013-12-17 22:45:37 +00:00
* keepflags = 0 ;
2013-06-23 02:17:02 +00:00
while ( * oldpaths )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
p = * oldpaths ;
2005-08-26 22:52:26 +00:00
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( p - > logicalpath , dir ) )
2013-06-23 02:17:02 +00:00
{
2013-12-17 22:45:37 +00:00
* keepflags | = p - > flags & ( SPF_REFERENCED | SPF_UNTRUSTED ) ;
2013-06-23 02:17:02 +00:00
* oldpaths = p - > next ;
r = p - > handle ;
Z_Free ( p ) ;
break ;
}
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
oldpaths = & ( * oldpaths ) - > next ;
2005-08-26 22:52:26 +00:00
}
2013-06-23 02:17:02 +00:00
return r ;
2005-08-26 22:52:26 +00:00
}
2005-12-21 03:07:33 +00:00
typedef struct {
2013-06-23 02:17:02 +00:00
searchpathfuncs_t * ( QDECL * OpenNew ) ( vfsfile_t * file , const char * desc ) ;
searchpath_t * * oldpaths ;
2009-04-01 22:03:56 +00:00
const char * parentdesc ;
const char * puredesc ;
2005-12-21 03:07:33 +00:00
} wildpaks_t ;
2014-02-07 08:38:40 +00:00
static int QDECL FS_AddWildDataFiles ( const char * descriptor , qofs_t size , void * vparam , searchpathfuncs_t * funcs )
2005-08-26 22:52:26 +00:00
{
2005-12-21 03:07:33 +00:00
wildpaks_t * param = vparam ;
vfsfile_t * vfs ;
2005-08-26 22:52:26 +00:00
searchpath_t * search ;
2013-06-23 02:17:02 +00:00
searchpathfuncs_t * newpak ;
2005-08-26 22:52:26 +00:00
char pakfile [ MAX_OSPATH ] ;
2008-11-09 22:29:28 +00:00
char purefile [ MAX_OSPATH ] ;
2005-12-21 03:07:33 +00:00
flocation_t loc ;
2013-12-17 22:45:37 +00:00
unsigned int keptflags = 0 ;
2005-08-26 22:52:26 +00:00
2011-07-22 15:11:35 +00:00
Q_snprintfz ( pakfile , sizeof ( pakfile ) , " %s%s " , param - > parentdesc , descriptor ) ;
2005-08-26 22:52:26 +00:00
for ( search = com_searchpaths ; search ; search = search - > next )
{
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( search - > logicalpath , pakfile ) ) //assumption: first member of structure is a char array
2005-08-26 22:52:26 +00:00
return true ; //already loaded (base paths?)
}
2013-12-17 22:45:37 +00:00
newpak = FS_GetOldPath ( param - > oldpaths , pakfile , & keptflags ) ;
2013-06-23 02:17:02 +00:00
if ( ! newpak )
2012-07-05 19:42:36 +00:00
{
2013-10-29 17:38:22 +00:00
if ( param - > OpenNew = = VFSOS_OpenPath )
{
vfs = NULL ;
}
else
{
fs_finds + + ;
if ( ! funcs - > FindFile ( funcs , & loc , descriptor , NULL ) )
return true ; //not found..
vfs = funcs - > OpenVFS ( funcs , & loc , " rb " ) ;
if ( ! vfs )
return true ;
}
2013-06-23 02:17:02 +00:00
newpak = param - > OpenNew ( vfs , pakfile ) ;
if ( ! newpak )
{
VFS_CLOSE ( vfs ) ;
return true ;
}
2012-07-05 19:42:36 +00:00
}
2005-12-21 03:07:33 +00:00
2013-06-23 02:17:02 +00:00
Q_snprintfz ( pakfile , sizeof ( pakfile ) , " %s%s " , param - > parentdesc , descriptor ) ;
2008-11-09 22:29:28 +00:00
if ( * param - > puredesc )
snprintf ( purefile , sizeof ( purefile ) , " %s/%s " , param - > puredesc , descriptor ) ;
else
Q_strncpyz ( purefile , descriptor , sizeof ( purefile ) ) ;
2013-12-17 22:45:37 +00:00
FS_AddPathHandle ( param - > oldpaths , purefile , pakfile , newpak , ( ( ! Q_strncasecmp ( descriptor , " pak " , 3 ) ) ? SPF_COPYPROTECTED : 0 ) | keptflags , ( unsigned int ) - 1 ) ;
2005-08-26 22:52:26 +00:00
return true ;
}
2005-12-21 03:07:33 +00:00
2013-06-23 02:17:02 +00:00
static void FS_AddDataFiles ( searchpath_t * * oldpaths , const char * purepath , const char * logicalpath , searchpath_t * search , const char * extension , searchpathfuncs_t * ( QDECL * OpenNew ) ( vfsfile_t * file , const char * desc ) )
2005-08-26 22:52:26 +00:00
{
2005-12-21 03:07:33 +00:00
//search is the parent
2005-08-26 22:52:26 +00:00
int i ;
2013-06-23 02:17:02 +00:00
searchpathfuncs_t * handle ;
2005-08-26 22:52:26 +00:00
char pakfile [ MAX_OSPATH ] ;
2013-06-23 02:17:02 +00:00
char logicalpaths [ MAX_OSPATH ] ; //with a slash
2008-11-09 22:29:28 +00:00
char purefile [ MAX_OSPATH ] ;
2013-12-17 22:45:37 +00:00
unsigned int keptflags ;
2005-12-21 03:07:33 +00:00
vfsfile_t * vfs ;
flocation_t loc ;
wildpaks_t wp ;
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
Q_strncpyz ( logicalpaths , logicalpath , sizeof ( logicalpaths ) ) ;
FS_CleanDir ( logicalpaths , sizeof ( logicalpaths ) ) ;
2008-11-09 22:29:28 +00:00
//first load all the numbered pak files
2005-08-26 22:52:26 +00:00
for ( i = 0 ; ; i + + )
{
2006-03-06 01:41:09 +00:00
snprintf ( pakfile , sizeof ( pakfile ) , " pak%i.%s " , i , extension ) ;
2012-02-27 12:23:15 +00:00
fs_finds + + ;
2013-06-23 02:17:02 +00:00
if ( ! search - > handle - > FindFile ( search - > handle , & loc , pakfile , NULL ) )
2005-12-21 03:07:33 +00:00
break ; //not found..
2013-06-23 02:17:02 +00:00
snprintf ( pakfile , sizeof ( pakfile ) , " %spak%i.%s " , logicalpaths , i , extension ) ;
snprintf ( purefile , sizeof ( purefile ) , " %s/pak%i.%s " , purepath , i , extension ) ;
2013-12-17 22:45:37 +00:00
handle = FS_GetOldPath ( oldpaths , pakfile , & keptflags ) ;
2005-08-26 22:52:26 +00:00
if ( ! handle )
2013-06-23 02:17:02 +00:00
{
vfs = search - > handle - > OpenVFS ( search - > handle , & loc , " r " ) ;
if ( ! vfs )
break ;
handle = OpenNew ( vfs , pakfile ) ;
if ( ! handle )
break ;
}
2013-12-17 22:45:37 +00:00
FS_AddPathHandle ( oldpaths , purefile , pakfile , handle , SPF_COPYPROTECTED | keptflags , ( unsigned int ) - 1 ) ;
2005-08-26 22:52:26 +00:00
}
2008-11-09 22:29:28 +00:00
//now load the random ones
2011-07-22 15:11:35 +00:00
Q_snprintfz ( pakfile , sizeof ( pakfile ) , " *.%s " , extension ) ;
2013-06-23 02:17:02 +00:00
wp . OpenNew = OpenNew ;
wp . parentdesc = logicalpaths ;
2008-11-09 22:29:28 +00:00
wp . puredesc = purepath ;
2013-06-23 02:17:02 +00:00
wp . oldpaths = oldpaths ;
search - > handle - > EnumerateFiles ( search - > handle , pakfile , FS_AddWildDataFiles , & wp ) ;
//and load any named in the manifest (this happens when they're crced or whatever)
{
int ptlen , palen ;
ptlen = strlen ( purepath ) ;
for ( i = 0 ; i < sizeof ( fs_manifest - > package ) / sizeof ( fs_manifest - > package [ 0 ] ) ; i + + )
{
if ( fs_manifest - > package [ i ] . path & & ! strcmp ( COM_FileExtension ( fs_manifest - > package [ i ] . path ) , extension ) )
{
palen = strlen ( fs_manifest - > package [ i ] . path ) ;
if ( palen > ptlen & & ( fs_manifest - > package [ i ] . path [ ptlen ] = = ' / ' | | fs_manifest - > package [ i ] . path [ ptlen ] = = ' \\ ' ) & & ! strncmp ( purepath , fs_manifest - > package [ i ] . path , ptlen ) )
{
searchpath_t * oldp ;
char pname [ MAX_OSPATH ] ;
char lname [ MAX_OSPATH ] ;
2013-08-06 02:19:06 +00:00
if ( fs_manifest - > package [ i ] . crcknown )
snprintf ( lname , sizeof ( lname ) , " %#x " , fs_manifest - > package [ i ] . crc ) ;
else
snprintf ( lname , sizeof ( lname ) , " " ) ;
2013-06-23 02:17:02 +00:00
if ( ! FS_GenCachedPakName ( fs_manifest - > package [ i ] . path , lname , pname , sizeof ( pname ) ) )
continue ;
2013-08-06 02:19:06 +00:00
snprintf ( lname , sizeof ( lname ) , " %s%s " , logicalpaths , pname + ptlen + 1 ) ;
2013-06-23 02:17:02 +00:00
for ( oldp = com_searchpaths ; oldp ; oldp = oldp - > next )
{
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( oldp - > purepath , fs_manifest - > package [ i ] . path ) )
2013-06-23 02:17:02 +00:00
break ;
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( oldp - > logicalpath , lname ) )
2013-06-23 02:17:02 +00:00
break ;
}
if ( ! oldp )
{
2013-12-17 22:45:37 +00:00
handle = FS_GetOldPath ( oldpaths , lname , & keptflags ) ;
2013-06-23 02:17:02 +00:00
if ( ! handle )
{
if ( search - > handle - > FindFile ( search - > handle , & loc , pname + ptlen + 1 , NULL ) )
{
vfs = search - > handle - > OpenVFS ( search - > handle , & loc , " r " ) ;
if ( vfs )
handle = OpenNew ( vfs , lname ) ;
}
}
2013-08-06 02:19:06 +00:00
if ( handle & & fs_manifest - > package [ i ] . crcknown )
2013-06-23 02:17:02 +00:00
{
int truecrc = handle - > GeneratePureCRC ( handle , 0 , false ) ;
if ( truecrc ! = fs_manifest - > package [ i ] . crc )
{
Con_Printf ( CON_ERROR " File \" %s \" has hash %#x (required: %#x). Please delete it or move it away \n " , lname , truecrc , fs_manifest - > package [ i ] . crc ) ;
handle - > ClosePath ( handle ) ;
handle = NULL ;
}
}
if ( handle )
2013-12-17 22:45:37 +00:00
FS_AddPathHandle ( oldpaths , fs_manifest - > package [ i ] . path , lname , handle , SPF_COPYPROTECTED | SPF_UNTRUSTED | keptflags , ( unsigned int ) - 1 ) ;
2013-06-23 02:17:02 +00:00
}
}
}
}
}
2009-04-01 22:03:56 +00:00
}
2013-06-23 02:17:02 +00:00
static searchpath_t * FS_AddPathHandle ( searchpath_t * * oldpaths , const char * purepath , const char * logicalpath , searchpathfuncs_t * handle , unsigned int flags , unsigned int loadstuff )
2009-04-01 22:03:56 +00:00
{
unsigned int i ;
2011-10-27 16:16:29 +00:00
searchpath_t * search , * * link ;
2009-04-01 22:03:56 +00:00
2013-06-23 02:17:02 +00:00
if ( ! handle )
{
Con_Printf ( " COM_AddPathHandle: not a valid handle (%s) \n " , logicalpath ) ;
return NULL ;
}
if ( handle - > fsver ! = FSVER )
2009-04-01 22:03:56 +00:00
{
2013-06-23 02:17:02 +00:00
Con_Printf ( " %s: file system driver is outdated (%u should be %u) \n " , logicalpath , handle - > fsver , FSVER ) ;
handle - > ClosePath ( handle ) ;
2009-04-01 22:03:56 +00:00
return NULL ;
}
search = ( searchpath_t * ) Z_Malloc ( sizeof ( searchpath_t ) ) ;
2013-06-23 02:17:02 +00:00
search - > flags = flags ;
2009-04-01 22:03:56 +00:00
search - > handle = handle ;
2013-06-23 02:17:02 +00:00
Q_strncpyz ( search - > purepath , purepath , sizeof ( search - > purepath ) ) ;
Q_strncpyz ( search - > logicalpath , logicalpath , sizeof ( search - > logicalpath ) ) ;
2009-04-01 22:03:56 +00:00
2013-03-12 22:35:33 +00:00
//temp packages also do not nest
2013-06-23 02:17:02 +00:00
if ( ! ( flags & SPF_TEMPORARY ) )
2013-03-12 22:35:33 +00:00
{
for ( i = 0 ; i < sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) ; i + + )
{
2013-06-23 02:17:02 +00:00
if ( ! searchpathformats [ i ] . extension | | ! searchpathformats [ i ] . OpenNew | | ! searchpathformats [ i ] . loadscan )
2013-03-12 22:35:33 +00:00
continue ;
if ( loadstuff & ( 1 < < i ) )
{
2013-06-23 02:17:02 +00:00
FS_AddDataFiles ( oldpaths , purepath , logicalpath , search , searchpathformats [ i ] . extension , searchpathformats [ i ] . OpenNew ) ;
2013-03-12 22:35:33 +00:00
}
}
}
2013-06-23 02:17:02 +00:00
if ( flags & SPF_TEMPORARY )
2011-10-27 16:16:29 +00:00
{
//add at end. pureness will reorder if needed.
link = & com_searchpaths ;
while ( * link )
{
link = & ( * link ) - > next ;
}
* link = search ;
}
else
{
search - > next = com_searchpaths ;
com_searchpaths = search ;
}
2009-04-01 22:03:56 +00:00
com_fschanged = true ;
return search ;
2005-08-26 22:52:26 +00:00
}
void COM_RefreshFSCache_f ( void )
{
com_fschanged = true ;
}
void COM_FlushFSCache ( void )
{
2012-05-09 15:30:53 +00:00
searchpath_t * search ;
2013-10-29 17:38:22 +00:00
if ( com_fs_cache . ival & & com_fs_cache . ival ! = 2 )
2012-05-09 15:30:53 +00:00
{
for ( search = com_searchpaths ; search ; search = search - > next )
{
2013-06-23 02:17:02 +00:00
if ( search - > handle - > PollChanges )
com_fschanged | = search - > handle - > PollChanges ( search - > handle ) ;
2012-05-09 15:30:53 +00:00
}
}
2014-02-07 08:38:40 +00:00
//rebuild it if needed
FS_RebuildFSHash ( ) ;
2005-08-26 22:52:26 +00:00
}
2010-07-11 02:22:39 +00:00
/*since should start as 0, otherwise this can be used to poll*/
qboolean FS_Restarted ( unsigned int * since )
{
if ( * since < fs_restarts )
{
* since = fs_restarts ;
return true ;
}
return false ;
}
2005-08-26 22:52:26 +00:00
/*
= = = = = = = = = = = = = = = =
2009-04-01 22:03:56 +00:00
FS_AddGameDirectory
2005-08-26 22:52:26 +00:00
Sets com_gamedir , adds the directory to the head of the path ,
2005-11-21 21:09:11 +00:00
then loads and adds pak1 . pak pak2 . pak . . .
2005-08-26 22:52:26 +00:00
= = = = = = = = = = = = = = = =
*/
2013-06-23 02:17:02 +00:00
void FS_AddGameDirectory ( searchpath_t * * oldpaths , const char * puredir , const char * dir , unsigned int loadstuff )
2005-08-26 22:52:26 +00:00
{
2013-12-17 22:45:37 +00:00
unsigned int keptflags ;
2005-08-26 22:52:26 +00:00
searchpath_t * search ;
char * p ;
2012-05-09 15:30:53 +00:00
void * handle ;
2005-08-26 22:52:26 +00:00
2010-07-11 02:22:39 +00:00
fs_restarts + + ;
2005-08-26 22:52:26 +00:00
if ( ( p = strrchr ( dir , ' / ' ) ) ! = NULL )
strcpy ( gamedirfile , + + p ) ;
else
2006-03-06 01:41:09 +00:00
strcpy ( gamedirfile , dir ) ;
2005-08-26 22:52:26 +00:00
for ( search = com_searchpaths ; search ; search = search - > next )
{
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( search - > logicalpath , dir ) )
2005-08-26 22:52:26 +00:00
return ; //already loaded (base paths?)
}
//
// add the directory to the search path
//
2013-12-17 22:45:37 +00:00
handle = FS_GetOldPath ( oldpaths , dir , & keptflags ) ;
2013-06-23 02:17:02 +00:00
if ( ! handle )
handle = VFSOS_OpenPath ( NULL , dir ) ;
2005-10-31 00:52:03 +00:00
2013-12-17 22:45:37 +00:00
FS_AddPathHandle ( oldpaths , puredir , dir , handle , SPF_EXPLICIT | keptflags , loadstuff ) ;
2005-08-26 22:52:26 +00:00
}
2013-06-23 02:17:02 +00:00
searchpathfuncs_t * COM_IteratePaths ( void * * iterator , char * buffer , int buffersize )
2005-08-26 22:52:26 +00:00
{
searchpath_t * s ;
2013-06-23 02:17:02 +00:00
void * prev ;
2005-08-26 22:52:26 +00:00
2009-04-01 22:03:56 +00:00
prev = NULL ;
2005-08-26 22:52:26 +00:00
for ( s = com_searchpaths ; s ; s = s - > next )
{
2013-06-23 02:17:02 +00:00
if ( ! ( s - > flags & SPF_EXPLICIT ) )
2005-08-26 22:52:26 +00:00
continue ;
2013-06-23 02:17:02 +00:00
if ( * iterator = = prev )
{
* iterator = s - > handle ;
Q_strncpyz ( buffer , s - > logicalpath , buffersize - 1 ) ;
FS_CleanDir ( buffer , buffersize ) ;
return s - > handle ;
}
prev = s - > handle ;
2005-08-26 22:52:26 +00:00
}
2013-06-23 02:17:02 +00:00
* iterator = NULL ;
* buffer = 0 ;
2005-08-26 22:52:26 +00:00
return NULL ;
}
2013-06-23 02:17:02 +00:00
char * FS_GetGamedir ( void )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
return gamedirfile ;
2009-04-01 22:03:56 +00:00
}
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
2013-06-23 02:17:02 +00:00
//given a 'c:/foo/bar/' path, will extract 'bar'.
void FS_ExtractDir ( char * in , char * out , int outlen )
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
{
char * end ;
if ( ! outlen )
return ;
end = in + strlen ( in ) ;
//skip over any trailing slashes
while ( end > in )
{
if ( end [ - 1 ] = = ' / ' | | end [ - 1 ] = = ' \\ ' )
end - - ;
else
break ;
}
//skip over the path
while ( end > in )
{
if ( end [ - 1 ] ! = ' / ' & & end [ - 1 ] ! = ' \\ ' )
end - - ;
else
break ;
}
//copy string into the dest
while ( - - outlen )
{
if ( * end = = ' / ' | | * end = = ' \\ ' | | ! * end )
break ;
* out + + = * end + + ;
}
* out = 0 ;
}
2013-06-23 02:17:02 +00:00
2005-08-26 22:52:26 +00:00
/*
= = = = = = = = = = = = = = = =
COM_Gamedir
Sets the gamedir and path to a different directory .
= = = = = = = = = = = = = = = =
*/
2009-04-01 22:03:56 +00:00
void COM_Gamedir ( const char * dir )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
ftemanifest_t * man ;
if ( ! fs_manifest )
FS_ChangeGame ( NULL , true ) ;
2013-11-29 14:36:47 +00:00
//don't allow leading dots, hidden files are evil.
//don't allow complex paths. those are evil too.
if ( ! * dir | | * dir = = ' . ' | | ! strcmp ( dir , " . " ) | | strstr ( dir , " .. " ) | | strstr ( dir , " / " )
| | strstr ( dir , " \\ " ) | | strstr ( dir , " : " ) )
{
Con_Printf ( " Gamedir should be a single filename, not a path \n " ) ;
return ;
}
2013-06-23 02:17:02 +00:00
man = FS_Manifest_Clone ( fs_manifest ) ;
FS_Manifest_PurgeGamedirs ( man ) ;
if ( * dir )
{
char * dup = Z_StrDup ( dir ) ;
dir = dup ;
while ( ( dir = COM_ParseStringSet ( dir ) ) )
{
if ( ! strcmp ( dir , " ; " ) )
continue ;
if ( ! * com_token )
continue ;
Cmd_TokenizeString ( va ( " gamedir \" %s \" " , com_token ) , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
}
Z_Free ( dup ) ;
}
2013-12-19 16:36:17 +00:00
FS_ChangeGame ( man , cfg_reload_on_gamedir . ival ) ;
2013-06-23 02:17:02 +00:00
#if 0
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
char thispath [ 64 ] ;
2005-08-26 22:52:26 +00:00
searchpath_t * next ;
2009-11-04 21:16:50 +00:00
qboolean isbase ;
2005-08-26 22:52:26 +00:00
2013-05-11 14:02:55 +00:00
//don't allow leading dots, hidden files are evil.
//don't allow complex paths. those are evil too.
if ( ! * dir | | * dir = = ' . ' | | ! strcmp ( dir , " . " ) | | strstr ( dir , " .. " ) | | strstr ( dir , " / " )
2005-08-26 22:52:26 +00:00
| | strstr ( dir , " \\ " ) | | strstr ( dir , " : " ) )
{
Con_TPrintf ( TL_GAMEDIRAINTPATH ) ;
return ;
}
2009-11-04 21:16:50 +00:00
isbase = false ;
for ( next = com_searchpaths ; next ; next = next - > next )
2009-04-01 22:03:56 +00:00
{
2009-11-04 21:16:50 +00:00
if ( next = = com_base_searchpaths )
isbase = true ;
2013-06-23 02:17:02 +00:00
2009-04-01 22:03:56 +00:00
if ( next - > funcs = = & osfilefuncs )
{
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
FS_CleanDir ( next - > purepath , thispath , sizeof ( thispath ) ) ;
if ( ! strcmp ( dir , thispath ) )
2009-04-01 22:03:56 +00:00
{
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
if ( isbase & & com_searchpaths = = com_base_searchpaths )
2009-04-01 22:03:56 +00:00
{
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
Q_strncpyz ( gamedirfile , dir , sizeof ( gamedirfile ) ) ;
return ;
2009-04-01 22:03:56 +00:00
}
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
if ( ! isbase )
return ;
break ;
2009-04-01 22:03:56 +00:00
}
}
}
2005-08-26 22:52:26 +00:00
FS_ForceToPure ( NULL , NULL , 0 ) ;
# ifndef SERVERONLY
2012-05-09 15:30:53 +00:00
// Host_WriteConfiguration(); //before we change anything.
2005-08-26 22:52:26 +00:00
# endif
2009-11-04 21:16:50 +00:00
Q_strncpyz ( gamedirfile , dir , sizeof ( gamedirfile ) ) ;
2005-08-26 22:52:26 +00:00
# ifndef CLIENTONLY
sv . gamedirchanged = true ;
# endif
# ifndef SERVERONLY
cl . gamedirchanged = true ;
# endif
2012-05-09 15:30:53 +00:00
FS_FlushFSHashReally ( ) ;
2005-08-26 22:52:26 +00:00
//
// free up any current game dir info
//
while ( com_searchpaths ! = com_base_searchpaths )
{
2013-06-23 02:17:02 +00:00
com_searchpaths - > handle - > ClosePath ( com_searchpaths - > handle ) ;
2005-08-26 22:52:26 +00:00
next = com_searchpaths - > next ;
Z_Free ( com_searchpaths ) ;
com_searchpaths = next ;
}
com_fschanged = true ;
//
// flush all data, so it will be forced to reload
//
Cache_Flush ( ) ;
2009-04-01 22:03:56 +00:00
if ( strchr ( dir , ' ; ' ) )
{
//separate case because parsestringset splits by whitespace too
2010-07-11 10:53:13 +00:00
while ( ( dir = COM_ParseStringSet ( dir ) ) )
2009-04-01 22:03:56 +00:00
{
if ( ! strcmp ( dir , " ; " ) )
continue ;
if ( ! * dir )
continue ;
FS_AddGameDirectory ( dir , va ( " %s%s " , com_quakedir , com_token ) , ~ 0 ) ;
if ( * com_homedir )
FS_AddGameDirectory ( dir , va ( " %s%s " , com_homedir , com_token ) , ~ 0 ) ;
}
}
else
{
FS_AddGameDirectory ( dir , va ( " %s%s " , com_quakedir , dir ) , ~ 0 ) ;
if ( * com_homedir )
FS_AddGameDirectory ( dir , va ( " %s%s " , com_homedir , dir ) , ~ 0 ) ;
}
2005-08-26 22:52:26 +00:00
# ifndef SERVERONLY
2008-11-09 22:29:28 +00:00
if ( ! isDedicated )
2005-08-26 22:52:26 +00:00
{
2010-02-06 01:25:04 +00:00
// if (qrenderer != QR_NONE) //only do this if we have already started the renderer
2005-08-26 22:52:26 +00:00
// Cbuf_InsertText("vid_restart\n", RESTRICT_LOCAL);
2009-04-01 22:03:56 +00:00
if ( COM_FDepthFile ( " config.cfg " , true ) < = ( * com_homedir ? 1 : 0 ) )
2005-08-26 22:52:26 +00:00
{
Cbuf_InsertText ( " cl_warncmd 0 \n "
" exec config.cfg \n "
" exec fte.cfg \n "
2006-02-06 01:06:17 +00:00
" cl_warncmd 1 \n " , RESTRICT_LOCAL , false ) ;
2005-08-26 22:52:26 +00:00
}
}
2011-03-12 13:51:40 +00:00
Shader_Init ( ) ; //FIXME!
2005-08-26 22:52:26 +00:00
2008-11-28 20:34:51 +00:00
COM_Effectinfo_Clear ( ) ;
2008-11-09 22:29:28 +00:00
2005-08-26 22:52:26 +00:00
Validation_FlushFileList ( ) ; //prevent previous hacks from making a difference.
//FIXME: load new palette, if different cause a vid_restart.
2013-06-23 02:17:02 +00:00
# endif
2005-08-26 22:52:26 +00:00
# endif
}
2013-06-23 02:17:02 +00:00
# define QCFG "set allow_download_refpackages 0\n"
2011-06-29 18:39:11 +00:00
/*stuff that makes dp-only mods work a bit better*/
2013-06-23 02:17:02 +00:00
# define DPCOMPAT QCFG "set _cl_playermodel \"\"\n set dpcompat_set 1\n set dpcompat_trailparticles 1\nset dpcompat_corruptglobals 1\nset vid_pixelheight 1\n"
2012-11-27 03:23:19 +00:00
/*nexuiz/xonotic has a few quirks/annoyances...*/
2013-10-29 17:38:22 +00:00
# define NEXCFG DPCOMPAT "set r_particlesdesc effectinfo\nset sv_bigcoords 1\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\npr_enable_uriget 0\n"
2011-06-29 18:39:11 +00:00
/*some modern non-compat settings*/
2011-08-16 04:12:15 +00:00
# define DMFCFG "set com_parseutf8 1\npm_airstep 1\nsv_demoExtensions 1\n"
2011-06-29 18:39:11 +00:00
/*set some stuff so our regular qw client appears more like hexen2*/
2013-05-03 04:28:08 +00:00
# define HEX2CFG "set com_parseutf8 -1\nset gl_font gfx / hexen2\nset in_builtinkeymap 0\nset_calc cl_playerclass int (random * 5) + 1\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx / thngland.wav\"\n"
2013-03-12 23:13:39 +00:00
/*yay q2!*/
2013-10-08 14:28:11 +00:00
# define Q2CFG "com_nogamedirnativecode 0\n"
2011-06-29 18:39:11 +00:00
/*Q3's ui doesn't like empty model/headmodel/handicap cvars, even if the gamecode copes*/
2013-05-11 14:02:55 +00:00
# define Q3CFG "gl_overbright 2\nseta model sarge\nseta headmodel sarge\nseta handicap 100\ncom_nogamedirnativecode 0\n"
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
# define RMQCFG "sv_bigcoords 1\n"
2005-08-26 22:52:26 +00:00
typedef struct {
2009-04-01 22:03:56 +00:00
const char * argname ; //used if this was used as a parameter.
2012-07-05 19:42:36 +00:00
const char * exename ; //used if the exe name contains this
const char * protocolname ; //sent to the master server when this is the current gamemode (Typically set for DP compat).
const char * auniquefile [ 4 ] ; //used if this file is relative from the gamedir. needs just one file
2005-08-26 22:52:26 +00:00
2009-04-01 22:03:56 +00:00
const char * customexec ;
2007-06-20 00:02:54 +00:00
2009-04-01 22:03:56 +00:00
const char * dir [ 4 ] ;
2009-04-12 16:57:30 +00:00
const char * poshname ; //Full name for the game.
2013-06-23 02:17:02 +00:00
const char * manifestfile ;
2005-08-26 22:52:26 +00:00
} gamemode_info_t ;
2009-04-01 22:03:56 +00:00
const gamemode_info_t gamemode_info [ ] = {
2013-06-23 02:17:02 +00:00
# define MASTER_PREFIX "FTE-"
2005-08-26 22:52:26 +00:00
//note that there is no basic 'fte' gamemode, this is because we aim for network compatability. Darkplaces-Quake is the closest we get.
//this is to avoid having too many gamemodes anyway.
2007-06-20 00:02:54 +00:00
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
//mission packs should generally come after the main game to avoid prefering the main game. we violate this for hexen2 as the mission pack is mostly a superset.
//whereas the quake mission packs replace start.bsp making the original episodes unreachable.
//for quake, we also allow extracting all files from paks. some people think it loads faster that way or something.
2012-07-05 19:42:36 +00:00
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
2013-06-23 02:17:02 +00:00
{ " -quake " , " q1 " , MASTER_PREFIX " Quake " , { " id1/pak0.pak " ,
" id1/quake.rc " } , QCFG , { " id1 " , " qw " , " fte " } , " Quake " /*, "id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/ } ,
{ " -hipnotic " , " hipnotic " , MASTER_PREFIX " Hipnotic " , { " hipnotic/pak0.pak " } , QCFG , { " id1 " , " qw " , " hipnotic " , " fte " } , " Quake: Scourge of Armagon " } ,
{ " -rogue " , " rogue " , MASTER_PREFIX " Rogue " , { " rogue/pak0.pak " } , QCFG , { " id1 " , " qw " , " rogue " , " fte " } , " Quake: Dissolution of Eternity " } ,
2012-07-05 19:42:36 +00:00
{ " -nexuiz " , " nexuiz " , " Nexuiz " , { " nexuiz.exe " } , NEXCFG , { " data " , " ftedata " } , " Nexuiz " } ,
2013-06-23 02:17:02 +00:00
{ " -xonotic " , " xonotic " , " Xonotic " , { " xonotic.exe " } , NEXCFG , { " data " , " ftedata " } , " Xonotic " } ,
2012-07-05 19:42:36 +00:00
{ " -spark " , " spark " , " Spark " , { " base/src/progs.src " ,
" base/qwprogs.dat " ,
" base/pak0.pak " } , DMFCFG , { " base " , } , " Spark " } ,
2013-05-03 04:28:08 +00:00
{ " -scouts " , " scouts " , " FTE-SJ " , { " basesj/src/progs.src " ,
" basesj/progs.dat " ,
" basesj/pak0.pak " } , NULL , { " basesj " , } , " Scouts Journey " } ,
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
{ " -rmq " , " rmq " , " RMQ " , { NULL } , RMQCFG , { " id1 " , " qw " , " rmq " , " fte " } , " Remake Quake " } ,
2005-08-26 22:52:26 +00:00
//supported commercial mods (some are currently only partially supported)
2012-07-05 19:42:36 +00:00
{ " -portals " , " h2mp " , " FTE-H2MP " , { " portals/hexen.rc " ,
" portals/pak3.pak " } , HEX2CFG , { " data1 " , " portals " , " fteh2 " } , " Hexen II MP " } ,
{ " -hexen2 " , " hexen2 " , " FTE-Hexen2 " , { " data1/pak0.pak " } , HEX2CFG , { " data1 " , " fteh2 " } , " Hexen II " } ,
2013-06-23 02:17:02 +00:00
{ " -quake2 " , " q2 " , " FTE-Quake2 " , { " baseq2/pak0.pak " } , Q2CFG , { " baseq2 " , " fteq2 " } , " Quake II " } ,
{ " -quake3 " , " q3 " , " FTE-Quake3 " , { " baseq3/pak0.pk3 " } , Q3CFG , { " baseq3 " , " fteq3 " } , " Quake III Arena " } ,
2011-07-30 14:14:56 +00:00
2012-07-05 19:42:36 +00:00
//can run in windows, needs
{ " -halflife " , " hl " , " FTE-HalfLife " , { " valve/liblist.gam " } , NULL , { " valve " , " ftehl " } , " Half-Life " } ,
2005-08-26 22:52:26 +00:00
2012-07-05 19:42:36 +00:00
//the rest are not supported in any real way. maps-only mostly, if that
2013-07-29 17:36:44 +00:00
{ " -quake4 " , " q4 " , " FTE-Quake4 " , { " q4base/pak00.pk4 " } , NULL , { " q4base " , " fteq4 " } , " Quake 4 " } ,
2012-07-05 19:42:36 +00:00
{ " -et " , " et " , " FTE-EnemyTerritory " , { " etmain/pak0.pk3 " } , NULL , { " etmain " , " fteet " } , " Wolfenstein - Enemy Territory " } ,
2005-08-26 22:52:26 +00:00
2013-10-29 17:38:22 +00:00
{ " -jk2 " , " jk2 " , " FTE-JK2 " , { " base/assets0.pk3 " } , NULL , { " base " , " ftejk2 " } , " Jedi Knight II: Jedi Outcast " } ,
{ " -warsow " , " warsow " , " FTE-Warsow " , { " basewsw/pak0.pk3 " } , NULL , { " basewsw " , " ftewsw " } , " Warsow " } ,
2012-07-05 19:42:36 +00:00
{ " -doom " , " doom " , " FTE-Doom " , { " doom.wad " } , NULL , { " *doom.wad " , " ftedoom " } , " Doom " } ,
{ " -doom2 " , " doom2 " , " FTE-Doom2 " , { " doom2.wad " } , NULL , { " *doom2.wad " , " ftedoom " } , " Doom2 " } ,
2013-12-07 00:30:48 +00:00
{ " -doom3 " , " doom3 " , " FTE-Doom3 " , { " doom3.wad " } , NULL , { " based3 " , " ftedoom3 " } , " Doom3 " } ,
2009-03-03 01:52:30 +00:00
2013-10-29 17:38:22 +00:00
//for the luls
{ " -diablo2 " , NULL , " FTE-Diablo2 " , { " d2music.mpq " } , NULL , { " **.mpq " , " fted2 " } , " Diablo 2 " } ,
2005-08-26 22:52:26 +00:00
{ NULL }
} ;
2013-06-23 02:17:02 +00:00
qboolean FS_GenCachedPakName ( char * pname , char * crc , char * local , int llen )
2011-10-27 16:16:29 +00:00
{
char * fn ;
2013-06-23 02:17:02 +00:00
char hex [ 16 ] ;
2011-10-27 16:16:29 +00:00
if ( strstr ( pname , " dlcache " ) )
{
2013-06-23 02:17:02 +00:00
* local = 0 ;
return false ;
2011-10-27 16:16:29 +00:00
}
fn = COM_SkipPath ( pname ) ;
2013-06-23 02:17:02 +00:00
if ( fn = = pname )
{ //only allow it if it has some game path first.
* local = 0 ;
return false ;
}
2011-10-27 16:16:29 +00:00
Q_strncpyz ( local , pname , min ( ( fn - pname ) + 1 , llen ) ) ;
Q_strncatz ( local , " dlcache/ " , llen ) ;
Q_strncatz ( local , fn , llen ) ;
if ( * crc )
{
Q_strncatz ( local , " . " , llen ) ;
2013-06-23 03:59:48 +00:00
snprintf ( hex , sizeof ( hex ) , " %x " , ( unsigned int ) strtoul ( crc , NULL , 0 ) ) ;
2013-06-23 02:17:02 +00:00
Q_strncatz ( local , hex , llen ) ;
2011-10-27 16:16:29 +00:00
}
2013-06-23 02:17:02 +00:00
return true ;
2011-10-27 16:16:29 +00:00
}
2013-06-23 02:17:02 +00:00
#if 0
qboolean FS_LoadPackageFromFile ( vfsfile_t * vfs , char * pname , char * localname , int * crc , unsigned int flags )
2013-03-12 23:01:08 +00:00
{
int i ;
char * ext = COM_FileExtension ( pname ) ;
2013-06-23 02:17:02 +00:00
searchpathfuncs_t * handle ;
searchpath_t * oldlist = NULL ;
2013-03-12 23:01:08 +00:00
searchpath_t * sp ;
for ( i = 0 ; i < sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) ; i + + )
{
2013-06-23 02:17:02 +00:00
if ( ! searchpathformats [ i ] . extension | | ! searchpathformats [ i ] . OpenNew )
2013-03-12 23:01:08 +00:00
continue ;
if ( ! strcmp ( ext , searchpathformats [ i ] . extension ) )
{
2013-06-23 02:17:02 +00:00
handle = searchpathformats [ i ] . OpenNew ( vfs , localname ) ;
2013-03-12 23:01:08 +00:00
if ( ! handle )
2013-03-12 23:09:25 +00:00
{
Con_Printf ( " file %s isn't a %s after all \n " , pname , searchpathformats [ i ] . extension ) ;
2013-03-12 23:01:08 +00:00
break ;
2013-03-12 23:09:25 +00:00
}
2013-03-12 23:01:08 +00:00
if ( crc )
{
2013-06-23 02:17:02 +00:00
int truecrc = handle - > GeneratePureCRC ( handle , 0 , false ) ;
2013-03-12 23:01:08 +00:00
if ( truecrc ! = * crc )
{
* crc = truecrc ;
VFS_CLOSE ( vfs ) ;
return false ;
}
}
2013-06-23 02:17:02 +00:00
sp = FS_AddPathHandle ( & oldlist , pname , localname , handle , flags , ( unsigned int ) - 1 ) ;
2013-03-12 23:01:08 +00:00
if ( sp )
{
FS_FlushFSHashReally ( ) ;
return true ;
}
}
}
VFS_CLOSE ( vfs ) ;
return false ;
}
2013-06-23 02:17:02 +00:00
# endif
void FS_PureMode ( int puremode , char * packagenames , char * packagecrcs , int pureseed )
{
qboolean pureflush ;
Z_Free ( fs_purenames ) ;
Z_Free ( fs_purecrcs ) ;
pureflush = ( fs_puremode ! = 2 & & puremode = = 2 ) ;
fs_puremode = puremode ;
fs_purenames = packagenames ? Z_StrDup ( packagenames ) : NULL ;
fs_purecrcs = packagecrcs ? Z_StrDup ( packagecrcs ) : NULL ;
fs_pureseed = pureseed ;
FS_ChangeGame ( fs_manifest , false ) ;
if ( pureflush )
{
# ifndef SERVERONLY
Shader_NeedReload ( true ) ;
# endif
Mod_ClearAll ( ) ;
Cache_Flush ( ) ;
}
}
2013-03-12 23:01:08 +00:00
2009-04-01 22:03:56 +00:00
char * FSQ3_GenerateClientPacksList ( char * buffer , int maxlen , int basechecksum )
{ //this is for q3 compatibility.
2005-08-26 22:52:26 +00:00
flocation_t loc ;
int numpaks = 0 ;
searchpath_t * sp ;
FS_FLocateFile ( " vm/cgame.qvm " , FSLFRT_LENGTH , & loc ) ;
Q_strncatz ( buffer , va ( " %i " , loc . search - > crc_reply ) , maxlen ) ;
basechecksum ^ = loc . search - > crc_reply ;
FS_FLocateFile ( " vm/ui.qvm " , FSLFRT_LENGTH , & loc ) ;
Q_strncatz ( buffer , va ( " %i " , loc . search - > crc_reply ) , maxlen ) ;
basechecksum ^ = loc . search - > crc_reply ;
Q_strncatz ( buffer , " @ " , maxlen ) ;
for ( sp = com_purepaths ; sp ; sp = sp - > nextpure )
{
if ( sp - > crc_reply )
{
Q_strncatz ( buffer , va ( " %i " , sp - > crc_reply ) , maxlen ) ;
basechecksum ^ = sp - > crc_reply ;
numpaks + + ;
}
}
basechecksum ^ = numpaks ;
Q_strncatz ( buffer , va ( " %i " , basechecksum ) , maxlen ) ;
return buffer ;
}
2005-10-16 12:49:15 +00:00
/*
= = = = = = = = = = = = = = = =
FS_ReloadPackFiles
= = = = = = = = = = = = = = = =
Called when the client has downloaded a new pak / pk3 file
*/
2005-10-31 00:52:03 +00:00
void FS_ReloadPackFilesFlags ( unsigned int reloadflags )
2005-10-16 12:49:15 +00:00
{
searchpath_t * oldpaths ;
searchpath_t * next ;
2013-06-23 02:17:02 +00:00
int i ;
2005-10-16 12:49:15 +00:00
2012-05-09 15:30:53 +00:00
FS_FlushFSHashReally ( ) ;
2005-10-16 12:49:15 +00:00
oldpaths = com_searchpaths ;
com_searchpaths = NULL ;
com_purepaths = NULL ;
com_base_searchpaths = NULL ;
2013-06-23 02:17:02 +00:00
for ( i = 0 ; i < sizeof ( fs_manifest - > gamepath ) / sizeof ( fs_manifest - > gamepath [ 0 ] ) ; i + + )
2005-10-16 12:49:15 +00:00
{
2013-11-29 14:36:47 +00:00
char * dir = fs_manifest - > gamepath [ i ] . path ;
if ( dir & & fs_manifest - > gamepath [ i ] . base )
2013-06-23 02:17:02 +00:00
{
2013-11-29 14:36:47 +00:00
//don't allow leading dots, hidden files are evil.
//don't allow complex paths. those are evil too.
if ( ! * dir | | * dir = = ' . ' | | ! strcmp ( dir , " . " ) | | strstr ( dir , " .. " ) | | strstr ( dir , " / " )
| | strstr ( dir , " \\ " ) | | strstr ( dir , " : " ) )
{
Con_Printf ( " Gamedir should be a single filename, not a path \n " ) ;
continue ;
}
2013-10-29 17:38:22 +00:00
//paths with '*' actually result in loading packages without an actual gamedir. note that this does not imply that we can write anything.
2013-11-29 14:36:47 +00:00
if ( * dir = = ' * ' )
2013-10-29 17:38:22 +00:00
{
int j ;
searchpathfuncs_t * handle = VFSOS_OpenPath ( NULL , com_quakedir ) ;
searchpath_t * search = ( searchpath_t * ) Z_Malloc ( sizeof ( searchpath_t ) ) ;
search - > flags = 0 ;
search - > handle = handle ;
Q_strncpyz ( search - > purepath , " " , sizeof ( search - > purepath ) ) ;
Q_strncpyz ( search - > logicalpath , com_quakedir , sizeof ( search - > logicalpath ) ) ;
for ( j = 0 ; j < sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) ; j + + )
{
if ( ! searchpathformats [ j ] . extension | | ! searchpathformats [ j ] . OpenNew | | ! searchpathformats [ j ] . loadscan )
continue ;
if ( reloadflags & ( 1 < < j ) )
{
FS_AddDataFiles ( & oldpaths , search - > purepath , search - > logicalpath , search , searchpathformats [ j ] . extension , searchpathformats [ j ] . OpenNew ) ;
}
}
handle - > ClosePath ( handle ) ;
Z_Free ( search ) ;
}
else
{
2013-11-29 14:36:47 +00:00
FS_AddGameDirectory ( & oldpaths , dir , va ( " %s%s " , com_quakedir , dir ) , reloadflags ) ;
2013-10-29 17:38:22 +00:00
if ( * com_homedir )
2013-11-29 14:36:47 +00:00
FS_AddGameDirectory ( & oldpaths , dir , va ( " %s%s " , com_homedir , dir ) , reloadflags ) ;
2013-10-29 17:38:22 +00:00
}
2013-06-23 02:17:02 +00:00
}
2005-10-16 12:49:15 +00:00
}
2013-06-23 02:17:02 +00:00
com_base_searchpaths = com_searchpaths ;
for ( i = 0 ; i < sizeof ( fs_manifest - > gamepath ) / sizeof ( fs_manifest - > gamepath [ 0 ] ) ; i + + )
2005-10-16 12:49:15 +00:00
{
2013-11-29 14:36:47 +00:00
char * dir = fs_manifest - > gamepath [ i ] . path ;
if ( dir & & ! fs_manifest - > gamepath [ i ] . base )
2013-06-23 02:17:02 +00:00
{
2013-11-29 14:36:47 +00:00
//don't allow leading dots, hidden files are evil.
//don't allow complex paths. those are evil too.
if ( ! * dir | | * dir = = ' . ' | | ! strcmp ( dir , " . " ) | | strstr ( dir , " .. " ) | | strstr ( dir , " / " )
| | strstr ( dir , " \\ " ) | | strstr ( dir , " : " ) )
{
Con_Printf ( " Gamedir should be a single filename, not a path \n " ) ;
continue ;
}
if ( * dir = = ' * ' )
2013-10-29 17:38:22 +00:00
{
}
else
{
2013-11-29 14:36:47 +00:00
FS_AddGameDirectory ( & oldpaths , dir , va ( " %s%s " , com_quakedir , dir ) , reloadflags ) ;
2013-10-29 17:38:22 +00:00
if ( * com_homedir )
2013-11-29 14:36:47 +00:00
FS_AddGameDirectory ( & oldpaths , dir , va ( " %s%s " , com_homedir , dir ) , reloadflags ) ;
2013-10-29 17:38:22 +00:00
}
2013-06-23 02:17:02 +00:00
}
}
2005-10-16 12:49:15 +00:00
2013-06-23 02:17:02 +00:00
/*sv_pure: Reload pure paths*/
if ( fs_purenames & & fs_purecrcs )
{
char crctok [ 64 ] ;
char nametok [ MAX_QPATH ] ;
searchpath_t * sp , * lastpure = NULL ;
char * names = fs_purenames , * pname ;
char * crcs = fs_purecrcs ;
int crc ;
2005-10-16 12:49:15 +00:00
2013-06-23 02:17:02 +00:00
for ( sp = com_searchpaths ; sp ; sp = sp - > next )
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
{
2013-06-23 02:17:02 +00:00
if ( sp - > handle - > GeneratePureCRC )
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
{
2013-06-23 02:17:02 +00:00
sp - > nextpure = ( void * ) 0x1 ;
sp - > crc_check = sp - > handle - > GeneratePureCRC ( sp - > handle , fs_pureseed , 0 ) ;
sp - > crc_reply = sp - > handle - > GeneratePureCRC ( sp - > handle , fs_pureseed , 1 ) ;
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
}
else
2013-06-23 02:17:02 +00:00
{
sp - > nextpure = NULL ;
sp - > crc_check = 0 ;
sp - > crc_reply = 0 ;
}
}
while ( names & & crcs )
{
crcs = COM_ParseOut ( crcs , crctok , sizeof ( crctok ) ) ;
names = COM_ParseOut ( names , nametok , sizeof ( nametok ) ) ;
crc = strtoul ( crctok , NULL , 0 ) ;
if ( ! crc )
continue ;
pname = nametok ;
if ( * pname = = ' * ' ) // * means that its 'referenced' (read: actually useful) thus should be downloaded, which is not relevent here.
pname + + ;
for ( sp = com_searchpaths ; sp ; sp = sp - > next )
{
if ( sp - > nextpure = = ( void * ) 0x1 ) //don't add twice.
if ( sp - > crc_check = = crc )
{
if ( fs_puremode )
{
if ( lastpure )
lastpure - > nextpure = sp ;
else
com_purepaths = sp ;
sp - > nextpure = NULL ;
lastpure = sp ;
}
break ;
}
}
if ( ! fs_puremode & & ! sp )
{ //if we're not pure, we don't care if the version differs. don't load the server's version.
//this works around 1.01 vs 1.06 issues.
for ( sp = com_searchpaths ; sp ; sp = sp - > next )
{
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( pname , sp - > purepath ) )
2013-06-23 02:17:02 +00:00
break ;
}
}
//if its not already loaded (via wildcards), load it from the download cache, if we can
if ( ! sp )
{
char local [ MAX_OSPATH ] ;
vfsfile_t * vfs ;
char * ext = COM_FileExtension ( pname ) ;
void * handle ;
int i ;
if ( FS_GenCachedPakName ( pname , va ( " %i " , crc ) , local , sizeof ( local ) ) )
vfs = FS_OpenVFS ( local , " rb " , FS_ROOT ) ;
else
vfs = NULL ;
if ( vfs )
{
for ( i = 0 ; i < sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) ; i + + )
{
if ( ! searchpathformats [ i ] . extension | | ! searchpathformats [ i ] . OpenNew )
continue ;
if ( ! strcmp ( ext , searchpathformats [ i ] . extension ) )
{
handle = searchpathformats [ i ] . OpenNew ( vfs , local ) ;
if ( ! handle )
break ;
sp = FS_AddPathHandle ( & oldpaths , pname , local , handle , SPF_COPYPROTECTED | SPF_TEMPORARY , ( unsigned int ) - 1 ) ;
sp - > crc_check = sp - > handle - > GeneratePureCRC ( sp - > handle , fs_pureseed , 0 ) ;
sp - > crc_reply = sp - > handle - > GeneratePureCRC ( sp - > handle , fs_pureseed , 1 ) ;
if ( sp - > crc_check = = crc )
{
if ( fs_puremode )
{
if ( lastpure )
lastpure - > nextpure = sp ;
else
com_purepaths = sp ;
sp - > nextpure = NULL ;
lastpure = sp ;
}
}
break ;
}
}
}
if ( ! sp )
Con_DPrintf ( " Pure crc %i wasn't found \n " , crc ) ;
}
Android: fat presses, vibrator, onscreen keyboard, keep-screen-on, console scaling, touch-based console scrolling, additional bindables.
Some memory leaks fixed.
latency with the nq protocol over loopback is much reduced.
Terrain: now mostly a property of a (q1 for now) bsp map, file format changed, glsl now built in, terrain editor builtin improved/changed, holes supported.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4067 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-07-14 16:25:18 +00:00
}
2005-10-16 12:49:15 +00:00
}
2013-06-23 02:17:02 +00:00
while ( oldpaths )
{
next = oldpaths - > next ;
2011-10-27 16:16:29 +00:00
2013-06-23 02:17:02 +00:00
Con_Printf ( " %s is no longer needed \n " , oldpaths - > logicalpath ) ;
oldpaths - > handle - > ClosePath ( oldpaths - > handle ) ;
Z_Free ( oldpaths ) ;
oldpaths = next ;
}
2005-10-16 12:49:15 +00:00
}
2006-01-28 06:41:20 +00:00
void FS_UnloadPackFiles ( void )
{
FS_ReloadPackFilesFlags ( 1 ) ;
}
2005-10-31 00:52:03 +00:00
void FS_ReloadPackFiles ( void )
{
2009-04-01 22:03:56 +00:00
FS_ReloadPackFilesFlags ( ~ 0 ) ;
2005-10-31 00:52:03 +00:00
}
void FS_ReloadPackFiles_f ( void )
{
if ( atoi ( Cmd_Argv ( 1 ) ) )
FS_ReloadPackFilesFlags ( atoi ( Cmd_Argv ( 1 ) ) ) ;
else
2009-04-01 22:03:56 +00:00
FS_ReloadPackFilesFlags ( ~ 0 ) ;
2005-10-31 00:52:03 +00:00
}
2009-03-03 01:52:30 +00:00
# ifdef _WIN32
# include <windows.h>
2009-05-24 10:11:17 +00:00
# ifdef MINGW
# define byte BYTE //some versions of mingw headers are broken slightly. this lets it compile.
# endif
2009-04-12 16:57:30 +00:00
# include <shlobj.h>
2010-08-16 02:03:02 +00:00
static qboolean Sys_SteamHasFile ( char * basepath , int basepathlen , char * steamdir , char * fname )
{
/*
Find where Valve ' s Steam distribution platform is installed .
Then take a look at that location for the relevent installed app .
*/
FILE * f ;
DWORD resultlen ;
HKEY key = NULL ;
2012-11-27 03:23:19 +00:00
if ( RegOpenKeyEx ( HKEY_CURRENT_USER , " SOFTWARE \\ Valve \\ Steam " , 0 , STANDARD_RIGHTS_READ | KEY_QUERY_VALUE , & key ) = = ERROR_SUCCESS )
2010-08-16 02:03:02 +00:00
{
resultlen = basepathlen ;
2011-03-09 03:42:30 +00:00
RegQueryValueEx ( key , " SteamPath " , NULL , NULL , basepath , & resultlen ) ;
2010-08-16 02:03:02 +00:00
RegCloseKey ( key ) ;
Q_strncatz ( basepath , va ( " /SteamApps/common/%s " , steamdir ) , basepathlen ) ;
2011-05-30 13:36:44 +00:00
if ( ( f = fopen ( va ( " %s/%s " , basepath , fname ) , " rb " ) ) )
2010-08-16 02:03:02 +00:00
{
fclose ( f ) ;
return true ;
}
}
return false ;
}
2009-04-12 16:57:30 +00:00
qboolean Sys_FindGameData ( const char * poshname , const char * gamename , char * basepath , int basepathlen )
2009-03-03 01:52:30 +00:00
{
2009-04-12 16:57:30 +00:00
DWORD resultlen ;
HKEY key = NULL ;
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
# endif
//first, try and find it in our game paths location
2012-11-27 03:23:19 +00:00
if ( RegOpenKeyEx ( HKEY_CURRENT_USER , " SOFTWARE \\ " FULLENGINENAME " \\ GamePaths " , 0 , STANDARD_RIGHTS_READ | KEY_QUERY_VALUE , & key ) = = ERROR_SUCCESS )
2009-04-12 16:57:30 +00:00
{
resultlen = basepathlen ;
if ( ! RegQueryValueEx ( key , gamename , NULL , NULL , basepath , & resultlen ) )
{
if ( GetFileAttributes ( basepath ) ! = INVALID_FILE_ATTRIBUTES )
{
RegCloseKey ( key ) ;
return true ;
}
}
RegCloseKey ( key ) ;
}
2013-06-23 03:59:48 +00:00
if ( ! strcmp ( gamename , " quake " ) )
2009-03-03 01:52:30 +00:00
{
2013-10-29 17:38:22 +00:00
char * prefix [ ] =
{
" c:/quake/ " , //quite a lot of people have it in c:\quake, as that's the default install location from the quake cd.
" c:/games/quake/ " , //personally I use this
# ifdef _WIN64
//quite a few people have nquake installed. we need to an api function to read the directory for non-english-windows users.
va ( " %s/nQuake/ " , getenv ( " %ProgramFiles(x86)% " ) ) , //64bit builds should look in both places
va ( " %s/nQuake/ " , getenv ( " %ProgramFiles% " ) ) , //
# else
va ( " %s/nQuake/ " , getenv ( " %ProgramFiles% " ) ) , //32bit builds will get the x86 version anyway.
# endif
NULL
} ;
int i ;
2010-08-16 02:03:02 +00:00
FILE * f ;
2009-03-03 01:52:30 +00:00
//try and find it via steam
//reads HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam\InstallPath
//append SteamApps\common\quake
//use it if we find winquake.exe there
2010-08-16 02:03:02 +00:00
if ( Sys_SteamHasFile ( basepath , basepathlen , " quake " , " Winquake.exe " ) )
return true ;
2009-03-03 01:52:30 +00:00
//well, okay, so they don't have quake installed from steam.
2013-10-29 17:38:22 +00:00
//check various 'unadvertised' paths
for ( i = 0 ; prefix [ i ] ; i + + )
2009-03-03 01:52:30 +00:00
{
2013-10-29 17:38:22 +00:00
char syspath [ MAX_OSPATH ] ;
Q_snprintfz ( syspath , sizeof ( syspath ) , " %sid1/pak0.pak " , prefix [ i ] ) ;
if ( ( f = fopen ( " c:/quake/quake.exe " , " rb " ) ) )
{
fclose ( f ) ;
Q_strncpyz ( basepath , prefix [ i ] , sizeof ( basepath ) ) ;
return true ;
}
2009-03-03 01:52:30 +00:00
}
}
2013-06-23 03:59:48 +00:00
if ( ! strcmp ( gamename , " quake2 " ) )
2009-03-03 01:52:30 +00:00
{
FILE * f ;
DWORD resultlen ;
HKEY key = NULL ;
2010-08-16 02:03:02 +00:00
//look for HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Quake2_exe\Path
2012-11-27 03:23:19 +00:00
if ( RegOpenKeyEx ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ App Paths \\ Quake2_exe " , 0 , STANDARD_RIGHTS_READ | KEY_QUERY_VALUE , & key ) = = ERROR_SUCCESS )
2009-03-03 01:52:30 +00:00
{
resultlen = basepathlen ;
2010-08-16 02:03:02 +00:00
RegQueryValueEx ( key , " Path " , NULL , NULL , basepath , & resultlen ) ;
2009-03-03 01:52:30 +00:00
RegCloseKey ( key ) ;
2011-05-30 13:36:44 +00:00
if ( ( f = fopen ( va ( " %s/quake2.exe " , basepath ) , " rb " ) ) )
2009-03-03 01:52:30 +00:00
{
fclose ( f ) ;
return true ;
}
}
2010-08-16 02:03:02 +00:00
if ( Sys_SteamHasFile ( basepath , basepathlen , " quake 2 " , " quake2.exe " ) )
return true ;
}
if ( ! strcmp ( gamename , " et " ) )
{
FILE * f ;
DWORD resultlen ;
HKEY key = NULL ;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\Activision\Wolfenstein - Enemy Territory
2012-11-27 03:23:19 +00:00
if ( RegOpenKeyEx ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Activision \\ Wolfenstein - Enemy Territory " , 0 , STANDARD_RIGHTS_READ | KEY_QUERY_VALUE , & key ) = = ERROR_SUCCESS )
2009-03-03 01:52:30 +00:00
{
resultlen = basepathlen ;
2010-08-16 02:03:02 +00:00
RegQueryValueEx ( key , " InstallPath " , NULL , NULL , basepath , & resultlen ) ;
2009-03-03 01:52:30 +00:00
RegCloseKey ( key ) ;
2010-08-16 02:03:02 +00:00
2011-05-30 13:36:44 +00:00
if ( ( f = fopen ( va ( " %s/ET.exe " , basepath ) , " rb " ) ) )
2009-03-03 01:52:30 +00:00
{
fclose ( f ) ;
return true ;
}
2010-08-16 02:03:02 +00:00
return true ;
2009-03-03 01:52:30 +00:00
}
}
2013-06-23 03:59:48 +00:00
if ( ! strcmp ( gamename , " quake3 " ) )
2009-03-03 01:52:30 +00:00
{
2010-08-16 02:03:02 +00:00
FILE * f ;
2009-03-03 01:52:30 +00:00
DWORD resultlen ;
HKEY key = NULL ;
2010-08-16 02:03:02 +00:00
2009-03-03 01:52:30 +00:00
//reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Quake III Arena\InstallPath
2012-11-27 03:23:19 +00:00
if ( RegOpenKeyEx ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ id \\ Quake III Arena " , 0 , STANDARD_RIGHTS_READ | KEY_QUERY_VALUE , & key ) = = ERROR_SUCCESS )
2009-03-03 01:52:30 +00:00
{
resultlen = basepathlen ;
RegQueryValueEx ( key , " InstallPath " , NULL , NULL , basepath , & resultlen ) ;
RegCloseKey ( key ) ;
2010-08-16 02:03:02 +00:00
2011-05-30 13:36:44 +00:00
if ( ( f = fopen ( va ( " %s/quake3.exe " , basepath ) , " rb " ) ) )
2010-08-16 02:03:02 +00:00
{
fclose ( f ) ;
return true ;
}
2009-03-03 01:52:30 +00:00
}
2010-08-16 02:03:02 +00:00
if ( Sys_SteamHasFile ( basepath , basepathlen , " quake 3 arena " , " quake3.exe " ) )
return true ;
2009-03-03 01:52:30 +00:00
}
2010-03-14 14:35:56 +00:00
if ( ! strcmp ( gamename , " wop " ) )
{
DWORD resultlen ;
HKEY key = NULL ;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\World Of Padman\Path
2012-11-27 03:23:19 +00:00
if ( RegOpenKeyEx ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ World Of Padman " , 0 , STANDARD_RIGHTS_READ | KEY_QUERY_VALUE , & key ) = = ERROR_SUCCESS )
2010-03-14 14:35:56 +00:00
{
resultlen = basepathlen ;
RegQueryValueEx ( key , " Path " , NULL , NULL , basepath , & resultlen ) ;
RegCloseKey ( key ) ;
return true ;
}
}
2009-03-03 01:52:30 +00:00
/*
if ( ! strcmp ( gamename , " d3 " ) )
{
DWORD resultlen ;
HKEY key = NULL ;
//reads HKEY_LOCAL_MACHINE\SOFTWARE\id\Doom 3\InstallPath
2012-11-27 03:23:19 +00:00
if ( RegOpenKeyEx ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ id \\ Doom 3 " , 0 , STANDARD_RIGHTS_READ | KEY_QUERY_VALUE , & key ) = = ERROR_SUCCESS )
2009-03-03 01:52:30 +00:00
{
resultlen = basepathlen ;
RegQueryValueEx ( key , " InstallPath " , NULL , NULL , basepath , & resultlen ) ;
RegCloseKey ( key ) ;
return true ;
}
}
*/
2013-06-23 02:17:02 +00:00
if ( ! strcmp ( gamename , " hexen2 " ) | | ! strcmp ( gamename , " h2mp " ) )
2009-03-03 01:52:30 +00:00
{
//append SteamApps\common\hexen 2
2011-03-09 03:42:30 +00:00
if ( Sys_SteamHasFile ( basepath , basepathlen , " hexen 2 " , " glh2.exe " ) )
2010-08-16 02:03:02 +00:00
return true ;
2009-03-03 01:52:30 +00:00
}
2011-09-16 05:56:54 +00:00
# if !defined(NPFTE) && !defined(SERVERONLY) //this is *really* unfortunate, but doing this crashes the browser
2013-03-12 23:01:55 +00:00
if ( poshname & & ! COM_CheckParm ( " -manifest " ) )
2009-04-12 16:57:30 +00:00
{
char resultpath [ MAX_PATH ] ;
BROWSEINFO bi ;
LPITEMIDLIST il ;
memset ( & bi , 0 , sizeof ( bi ) ) ;
2014-02-07 08:38:40 +00:00
bi . hwndOwner = mainwindow ; //note that this is usually still null
2009-04-12 16:57:30 +00:00
bi . pidlRoot = NULL ;
bi . pszDisplayName = resultpath ;
bi . lpszTitle = va ( " Please locate your existing %s installation " , poshname ) ;
bi . ulFlags = BIF_RETURNONLYFSDIRS ;
bi . lpfn = NULL ;
bi . lParam = 0 ;
bi . iImage = 0 ;
il = SHBrowseForFolder ( & bi ) ;
if ( il )
{
SHGetPathFromIDList ( il , resultpath ) ;
CoTaskMemFree ( il ) ;
Q_strncpyz ( basepath , resultpath , basepathlen - 1 ) ;
//and save it into the windows registry
2012-11-27 03:23:19 +00:00
if ( RegCreateKeyEx ( HKEY_CURRENT_USER , " SOFTWARE \\ " FULLENGINENAME " \\ GamePaths " ,
2009-04-12 16:57:30 +00:00
0 , NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_WRITE ,
NULL ,
& key ,
2012-11-27 03:23:19 +00:00
NULL ) = = ERROR_SUCCESS )
2009-04-12 16:57:30 +00:00
{
RegSetValueEx ( key , gamename , 0 , REG_SZ , basepath , strlen ( basepath ) ) ;
RegCloseKey ( key ) ;
}
return true ;
}
}
2009-04-19 00:50:42 +00:00
# endif
2009-04-12 16:57:30 +00:00
2009-03-03 01:52:30 +00:00
return false ;
}
# else
2012-11-30 02:50:50 +00:00
# ifdef __linux__
# include <sys/stat.h>
# endif
2009-04-13 12:54:18 +00:00
qboolean Sys_FindGameData ( const char * poshname , const char * gamename , char * basepath , int basepathlen )
2009-03-03 01:52:30 +00:00
{
2012-11-27 03:23:19 +00:00
# ifdef __linux__
2012-11-30 02:50:50 +00:00
struct stat sb ;
2013-06-23 03:59:48 +00:00
if ( ! strcmp ( gamename , " quake " ) )
2012-11-30 02:50:50 +00:00
{
if ( stat ( " /usr/share/quake/ " , & sb ) = = 0 )
{
// /usr/share/quake
if ( S_ISDIR ( sb . st_mode ) )
{
Q_strncpyz ( basepath , " /usr/share/quake/ " , basepathlen ) ;
return true ;
}
}
}
2012-11-27 03:23:19 +00:00
# endif
2009-03-03 01:52:30 +00:00
return false ;
}
# endif
2009-04-01 22:03:56 +00:00
void FS_Shutdown ( void )
{
searchpath_t * next ;
2012-05-09 15:30:53 +00:00
FS_FlushFSHashReally ( ) ;
2009-04-01 22:03:56 +00:00
//
// free up any current game dir info
//
while ( com_searchpaths )
{
2013-06-23 02:17:02 +00:00
com_searchpaths - > handle - > ClosePath ( com_searchpaths - > handle ) ;
2009-04-01 22:03:56 +00:00
next = com_searchpaths - > next ;
Z_Free ( com_searchpaths ) ;
com_searchpaths = next ;
}
com_fschanged = true ;
2012-07-05 19:42:36 +00:00
if ( filesystemhash . numbuckets )
{
BZ_Free ( filesystemhash . bucket ) ;
filesystemhash . bucket = NULL ;
filesystemhash . numbuckets = 0 ;
}
2013-06-23 02:17:02 +00:00
FS_Manifest_Free ( fs_manifest ) ;
fs_manifest = NULL ;
2009-04-01 22:03:56 +00:00
}
2013-06-23 02:17:02 +00:00
#if 0
static void FS_AddGamePack ( const char * pakname )
2012-02-12 05:18:31 +00:00
{
int j ;
char * ext = COM_FileExtension ( pakname ) ;
vfsfile_t * vfs = VFSOS_Open ( pakname , " rb " ) ;
void * pak ;
2013-06-23 02:17:02 +00:00
searchpath_t * oldlist = NULL ;
2012-02-12 05:18:31 +00:00
if ( ! vfs )
Con_Printf ( " Unable to open %s - missing? \n " , pakname ) ;
else
{
for ( j = 0 ; j < sizeof ( searchpathformats ) / sizeof ( searchpathformats [ 0 ] ) ; j + + )
{
2013-06-23 02:17:02 +00:00
if ( ! searchpathformats [ j ] . extension | | ! searchpathformats [ j ] . OpenNew )
2012-02-12 05:18:31 +00:00
continue ;
if ( ! strcmp ( ext , searchpathformats [ j ] . extension ) )
{
2013-06-23 02:17:02 +00:00
pak = searchpathformats [ j ] . OpenNew ( vfs , pakname ) ;
2012-02-12 05:18:31 +00:00
if ( pak )
{
2013-06-23 02:17:02 +00:00
FS_AddPathHandle ( & oldlist , " " , pakname , pak , SPF_COPYPROTECTED | SPF_EXPLICIT , ( unsigned int ) - 1 ) ;
2012-02-12 05:18:31 +00:00
}
else
{
Con_Printf ( " Unable to open %s - corrupt? \n " , pakname ) ;
VFS_CLOSE ( vfs ) ;
}
vfs = NULL ;
break ;
}
}
if ( vfs )
{
VFS_CLOSE ( vfs ) ;
Con_Printf ( " Unable to open %s - unsupported? \n " , pakname ) ;
}
}
}
2013-06-23 02:17:02 +00:00
static void FS_StartupWithGame ( int gamenum )
2010-08-16 02:03:02 +00:00
{
2012-02-12 05:18:31 +00:00
int i ;
2013-06-23 02:17:02 +00:00
searchpath_t * oldlist = NULL ;
2010-08-16 02:03:02 +00:00
2010-12-23 06:09:25 +00:00
# ifdef AVAIL_ZLIB
2010-11-11 04:03:16 +00:00
LibZ_Init ( ) ;
2010-12-23 06:09:25 +00:00
# endif
2010-11-11 04:03:16 +00:00
2011-07-30 14:14:56 +00:00
Cvar_Set ( & com_protocolname , gamemode_info [ gamenum ] . protocolname ) ;
Cvar_ForceSet ( & fs_gamename , gamemode_info [ gamenum ] . poshname ) ;
2013-06-23 02:17:02 +00:00
// Cvar_ForceSet(&fs_gamemanifest, gamemode_info[gamenum].manifestaddr?gamemode_info[gamenum].manifestaddr:"");
2010-08-16 02:03:02 +00:00
2012-01-28 10:30:44 +00:00
i = COM_CheckParm ( " -basepack " ) ;
while ( i & & i < com_argc - 1 )
{
// Con_Printf("found -basepack: %s\n", com_argv[i+1]);
2012-02-12 05:18:31 +00:00
FS_AddGamePack ( com_argv [ i + 1 ] ) ;
2012-01-28 10:30:44 +00:00
i = COM_CheckNextParm ( " -basepack " , i ) ;
}
2010-08-16 02:03:02 +00:00
//
// start up with id1 by default
//
i = COM_CheckParm ( " -basegame " ) ;
if ( i & & i < com_argc - 1 )
{
do //use multiple -basegames
{
2013-06-23 02:17:02 +00:00
FS_AddGameDirectory ( & oldlist , com_argv [ i + 1 ] , va ( " %s%s " , com_quakedir , com_argv [ i + 1 ] ) , ~ 0 ) ;
2010-08-16 02:03:02 +00:00
if ( * com_homedir )
2013-06-23 02:17:02 +00:00
FS_AddGameDirectory ( & oldlist , com_argv [ i + 1 ] , va ( " %s%s " , com_homedir , com_argv [ i + 1 ] ) , ~ 0 ) ;
2010-08-16 02:03:02 +00:00
i = COM_CheckNextParm ( " -basegame " , i ) ;
}
while ( i & & i < com_argc - 1 ) ;
}
else
{
for ( i = 0 ; i < sizeof ( gamemode_info [ gamenum ] . dir ) / sizeof ( gamemode_info [ gamenum ] . dir [ 0 ] ) ; i + + )
{
2012-02-12 05:18:31 +00:00
if ( gamemode_info [ gamenum ] . dir [ i ] & & * gamemode_info [ gamenum ] . dir [ i ] = = ' * ' )
{
char buf [ MAX_OSPATH ] ;
snprintf ( buf , sizeof ( buf ) , " %s%s " , com_quakedir , gamemode_info [ gamenum ] . dir [ i ] + 1 ) ;
FS_AddGamePack ( buf ) ;
}
else if ( gamemode_info [ gamenum ] . dir [ i ] )
2010-08-16 02:03:02 +00:00
{
2013-06-23 02:17:02 +00:00
FS_AddGameDirectory ( & oldlist , gamemode_info [ gamenum ] . dir [ i ] , va ( " %s%s " , com_quakedir , gamemode_info [ gamenum ] . dir [ i ] ) , ~ 0 ) ;
2010-08-16 02:03:02 +00:00
if ( * com_homedir )
2013-06-23 02:17:02 +00:00
FS_AddGameDirectory ( & oldlist , gamemode_info [ gamenum ] . dir [ i ] , va ( " %s%s " , com_homedir , gamemode_info [ gamenum ] . dir [ i ] ) , ~ 0 ) ;
2010-08-16 02:03:02 +00:00
}
}
}
i = COM_CheckParm ( " -addbasegame " ) ;
while ( i & & i < com_argc - 1 ) //use multiple -addbasegames (this is so the basic dirs don't die)
{
2013-03-12 23:09:25 +00:00
//reject various evil path arguments.
if ( * com_argv [ i + 1 ] & & ! ( strchr ( com_argv [ i + 1 ] , ' . ' ) | | strchr ( com_argv [ i + 1 ] , ' : ' ) | | strchr ( com_argv [ i + 1 ] , ' ? ' ) | | strchr ( com_argv [ i + 1 ] , ' * ' ) | | strchr ( com_argv [ i + 1 ] , ' / ' ) | | strchr ( com_argv [ i + 1 ] , ' \\ ' ) | | strchr ( com_argv [ i + 1 ] , ' $ ' ) ) )
{
2013-06-23 02:17:02 +00:00
FS_AddGameDirectory ( & oldlist , com_argv [ i + 1 ] , va ( " %s%s " , com_quakedir , com_argv [ i + 1 ] ) , ~ 0 ) ;
2013-03-12 23:09:25 +00:00
if ( * com_homedir )
2013-06-23 02:17:02 +00:00
FS_AddGameDirectory ( & oldlist , com_argv [ i + 1 ] , va ( " %s%s " , com_homedir , com_argv [ i + 1 ] ) , ~ 0 ) ;
2013-03-12 23:09:25 +00:00
}
2010-08-16 02:03:02 +00:00
i = COM_CheckNextParm ( " -addbasegame " , i ) ;
}
// any set gamedirs will be freed up to here
com_base_searchpaths = com_searchpaths ;
//-game specifies the mod gamedir to use in NQ
i = COM_CheckParm ( " -game " ) ; //effectivly replace with +gamedir x (But overridable)
if ( i & & i < com_argc - 1 )
{
COM_Gamedir ( com_argv [ i + 1 ] ) ;
2012-10-01 14:29:44 +00:00
# ifndef CLIENTONLY
Info_SetValueForStarKey ( svs . info , " *gamedir " , com_argv [ i + 1 ] , MAX_SERVERINFO_STRING ) ;
# endif
2010-08-16 02:03:02 +00:00
}
//+gamedir specifies the mod gamedir to use in QW
//hack - we parse the commandline after the config so commandline always overrides
//but this means ktpro/server.cfg (for example) is not found
//so if they specify a gamedir on the commandline, let the default configs be loaded from that gamedir
//note that -game +gamedir will result in both being loaded. but hey, who cares
i = COM_CheckParm ( " +gamedir " ) ; //effectivly replace with +gamedir x (But overridable)
if ( i & & i < com_argc - 1 )
{
COM_Gamedir ( com_argv [ i + 1 ] ) ;
2013-09-26 09:24:52 +00:00
# ifndef CLIENTONLY
Info_SetValueForStarKey ( svs . info , " *gamedir " , com_argv [ i + 1 ] , MAX_SERVERINFO_STRING ) ;
# endif
2010-08-16 02:03:02 +00:00
}
2012-11-27 03:23:19 +00:00
# ifdef ANDROID
2012-08-04 01:35:52 +00:00
{
vfsfile_t * f ;
//write a .nomedia file to avoid people from getting random explosion sounds etc intersperced with their music
f = FS_OpenVFS ( " .nomedia " , " rb " , FS_ROOT ) ;
if ( f )
VFS_CLOSE ( f ) ;
else
FS_WriteFile ( " .nomedia " , NULL , 0 , FS_ROOT ) ;
}
# endif
2010-08-16 02:03:02 +00:00
if ( gamemode_info [ gamenum ] . customexec )
Cbuf_AddText ( gamemode_info [ gamenum ] . customexec , RESTRICT_LOCAL ) ;
}
2013-06-23 02:17:02 +00:00
# endif
2010-08-16 02:03:02 +00:00
2013-10-29 17:38:22 +00:00
static qboolean FS_DirHasAPackage ( char * basedir , ftemanifest_t * man )
{
int j ;
vfsfile_t * f ;
for ( j = 0 ; j < sizeof ( fs_manifest - > package ) / sizeof ( fs_manifest - > package [ 0 ] ) ; j + + )
{
if ( ! man - > package [ j ] . path )
continue ;
f = VFSOS_Open ( va ( " %s%s " , basedir , man - > package [ j ] . path ) , " rb " ) ;
if ( f )
{
VFS_CLOSE ( f ) ;
return true ;
}
}
return false ;
}
2013-06-23 02:17:02 +00:00
//just check each possible file, see if one is there.
static qboolean FS_DirHasGame ( char * basedir , int gameidx )
2012-07-05 19:42:36 +00:00
{
2013-06-23 02:17:02 +00:00
int j ;
vfsfile_t * f ;
for ( j = 0 ; j < 4 ; j + + )
2012-07-05 19:42:36 +00:00
{
2013-06-23 02:17:02 +00:00
if ( ! gamemode_info [ gameidx ] . auniquefile [ j ] )
continue ; //no more
f = VFSOS_Open ( va ( " %s%s " , basedir , gamemode_info [ gameidx ] . auniquefile [ j ] ) , " rb " ) ;
if ( f )
2012-07-05 19:42:36 +00:00
{
2013-06-23 02:17:02 +00:00
VFS_CLOSE ( f ) ;
return true ;
2012-07-05 19:42:36 +00:00
}
}
2013-06-23 02:17:02 +00:00
return false ;
2012-07-05 19:42:36 +00:00
}
2013-06-23 02:17:02 +00:00
//check em all
static int FS_IdentifyDefaultGameFromDir ( char * basedir )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
int i ;
for ( i = 0 ; gamemode_info [ i ] . argname ; i + + )
{
if ( FS_DirHasGame ( basedir , i ) )
return i ;
}
return - 1 ;
}
2009-04-01 22:03:56 +00:00
2013-06-23 02:17:02 +00:00
//attempt to work out which game we're meant to be trying to run based upon a few things
//1: fs_changegame console command override. fixme: needs to cope with manifests too.
//2: -quake3 argument implies that the user wants to run quake3.
//3: if we are ftequake3.exe then we always try to run quake3.
//4: identify characteristic files within the working directory (like id1/pak0.pak implies we're running quake)
//5: check where the exe actually is instead of simply where we're being run from.
//6: fallback to quake
//if autobasedir is not set, block gamedir changes/prompts.
static int FS_IdentifyDefaultGame ( char * newbase , int sizeof_newbase , qboolean fixedbase )
{
int i ;
int gamenum = - 1 ;
2005-10-16 12:49:15 +00:00
2013-06-23 02:17:02 +00:00
if ( gamenum = = - 1 )
2010-12-05 02:46:07 +00:00
{
2013-06-23 02:17:02 +00:00
for ( i = 0 ; gamemode_info [ i ] . argname ; i + + )
{
if ( COM_CheckParm ( gamemode_info [ i ] . argname ) )
{
gamenum = i ;
break ;
}
}
2010-12-05 02:46:07 +00:00
}
2013-06-23 02:17:02 +00:00
//use the game based on an exe name over the filesystem one (could easily have multiple fs path matches).
if ( gamenum = = - 1 )
2006-03-06 01:41:09 +00:00
{
2013-10-29 17:38:22 +00:00
char * ev , * v0 = COM_SkipPath ( com_argv [ 0 ] ) ;
2013-06-23 02:17:02 +00:00
for ( i = 0 ; gamemode_info [ i ] . argname ; i + + )
2006-03-06 01:41:09 +00:00
{
2013-10-29 17:38:22 +00:00
if ( ! gamemode_info [ i ] . exename )
continue ;
ev = strstr ( v0 , gamemode_info [ i ] . exename ) ;
2013-06-23 02:17:02 +00:00
if ( ev & & ( ! strchr ( ev , ' \\ ' ) & & ! strchr ( ev , ' / ' ) ) )
gamenum = i ;
2006-03-06 01:41:09 +00:00
}
}
2013-06-23 02:17:02 +00:00
//identify the game from a telling file in the working directory
if ( gamenum = = - 1 )
gamenum = FS_IdentifyDefaultGameFromDir ( newbase ) ;
//identify the game from a telling file relative to the exe's directory. for when shortcuts don't set the working dir sensibly.
if ( gamenum = = - 1 & & host_parms . binarydir & & * host_parms . binarydir & & ! fixedbase )
{
gamenum = FS_IdentifyDefaultGameFromDir ( host_parms . binarydir ) ;
if ( gamenum ! = - 1 )
Q_strncpyz ( newbase , host_parms . binarydir , sizeof_newbase ) ;
}
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
//still failed? find quake and use that one by default
if ( gamenum < 0 )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
for ( i = 0 ; gamemode_info [ i ] . argname ; i + + )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
if ( ! strcmp ( gamemode_info [ i ] . argname , " -quake " ) )
2010-11-02 23:17:25 +00:00
{
gamenum = i ;
break ;
}
2005-08-26 22:52:26 +00:00
}
}
2013-06-23 02:17:02 +00:00
return gamenum ;
}
//allowed to modify newbasedir if fixedbasedir isn't set
ftemanifest_t * FS_GenerateLegacyManifest ( char * newbasedir , int sizeof_newbasedir , qboolean fixedbasedir , int game )
{
int i ;
ftemanifest_t * man ;
if ( game = = - 1 )
game = FS_IdentifyDefaultGame ( newbasedir , sizeof_newbasedir , fixedbasedir ) ;
if ( gamemode_info [ game ] . manifestfile )
man = FS_Manifest_Parse ( gamemode_info [ game ] . manifestfile ) ;
else
2012-11-27 03:23:19 +00:00
{
2013-06-23 02:17:02 +00:00
man = FS_Manifest_Create ( ) ;
Cmd_TokenizeString ( va ( " game \" %s \" " , gamemode_info [ game ] . argname + 1 ) , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
if ( gamemode_info [ game ] . poshname )
{
Cmd_TokenizeString ( va ( " name \" %s \" " , gamemode_info [ game ] . poshname ) , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
}
i = COM_CheckParm ( " -basegame " ) ;
if ( i )
2012-11-27 03:23:19 +00:00
{
2013-06-23 02:17:02 +00:00
do
2012-11-27 03:23:19 +00:00
{
2013-06-23 02:17:02 +00:00
Cmd_TokenizeString ( va ( " basegame \" %s \" " , com_argv [ i + 1 ] ) , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
i = COM_CheckNextParm ( " -basegame " , i ) ;
2012-11-27 03:23:19 +00:00
}
2013-06-23 02:17:02 +00:00
while ( i & & i < com_argc - 1 ) ;
}
i = COM_CheckParm ( " -game " ) ;
if ( i )
{
do
{
Cmd_TokenizeString ( va ( " gamedir \" %s \" " , com_argv [ i + 1 ] ) , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
i = COM_CheckNextParm ( " -game " , i ) ;
}
while ( i & & i < com_argc - 1 ) ;
}
i = COM_CheckParm ( " +gamedir " ) ;
if ( i )
{
do
{
Cmd_TokenizeString ( va ( " gamedir \" %s \" " , com_argv [ i + 1 ] ) , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
i = COM_CheckNextParm ( " +gamedir " , i ) ;
}
while ( i & & i < com_argc - 1 ) ;
2012-11-27 03:23:19 +00:00
}
}
2013-06-23 02:17:02 +00:00
return man ;
}
static char * FS_RelativeURL ( char * base , char * file , char * buffer , int bufferlen )
{
//fixme: cope with windows paths
qboolean baseisurl = ! ! strchr ( base , ' : ' ) ;
qboolean fileisurl = ! ! strchr ( file , ' : ' ) ;
2013-06-23 03:59:48 +00:00
//qboolean baseisabsolute = (*base == '/' || *base == '\\');
2013-06-23 02:17:02 +00:00
qboolean fileisabsolute = ( * file = = ' / ' | | * file = = ' \\ ' ) ;
char * ebase ;
if ( fileisurl )
return file ;
if ( fileisabsolute )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
if ( baseisurl )
{
ebase = strchr ( base , ' : ' ) ;
ebase + + ;
while ( * ebase = = ' / ' )
ebase + + ;
while ( * ebase & & * ebase ! = ' / ' )
ebase + + ;
}
else
ebase = base ;
2005-08-26 22:52:26 +00:00
}
2013-06-23 02:17:02 +00:00
else
ebase = COM_SkipPath ( base ) ;
memcpy ( buffer , base , ebase - base ) ;
strcpy ( buffer + ( ebase - base ) , file ) ;
return buffer ;
}
# ifdef WEBCLIENT
static struct dl_download * curpackagedownload ;
static char fspdl_temppath [ MAX_OSPATH ] ;
static char fspdl_finalpath [ MAX_OSPATH ] ;
static void FS_BeginNextPackageDownload ( void ) ;
static void FS_PackageDownloaded ( struct dl_download * dl )
{
curpackagedownload = NULL ;
if ( dl - > file )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
VFS_CLOSE ( dl - > file ) ;
dl - > file = NULL ;
}
if ( dl - > status = = DL_FINISHED )
{
//rename the file as needed.
COM_CreatePath ( fspdl_finalpath ) ;
if ( ! Sys_Rename ( fspdl_temppath , fspdl_finalpath ) )
2009-03-03 01:52:30 +00:00
{
2013-06-23 02:17:02 +00:00
Con_Printf ( " Unable to rename \" %s \" to \" %s \" \n " , fspdl_temppath , fspdl_finalpath ) ;
}
}
Sys_remove ( fspdl_temppath ) ;
FS_ChangeGame ( fs_manifest , true ) ;
FS_BeginNextPackageDownload ( ) ;
}
static void FS_BeginNextPackageDownload ( void )
{
2013-08-06 02:19:06 +00:00
char * crcstr ;
2013-06-23 02:17:02 +00:00
int j ;
ftemanifest_t * man = fs_manifest ;
vfsfile_t * check ;
if ( curpackagedownload | | ! man )
return ;
for ( j = 0 ; j < sizeof ( fs_manifest - > package ) / sizeof ( fs_manifest - > package [ 0 ] ) ; j + + )
{
char buffer [ MAX_OSPATH ] , * url ;
if ( ! man - > package [ j ] . path )
continue ;
2013-08-06 02:19:06 +00:00
if ( man - > package [ j ] . crcknown )
crcstr = va ( " %#x " , man - > package [ j ] . crc ) ;
else
crcstr = " " ;
if ( ! FS_GenCachedPakName ( man - > package [ j ] . path , crcstr , buffer , sizeof ( buffer ) ) )
2013-06-23 02:17:02 +00:00
continue ;
check = FS_OpenVFS ( buffer , " rb " , FS_ROOT ) ;
if ( check )
{
VFS_CLOSE ( check ) ;
continue ;
}
FS_NativePath ( buffer , FS_ROOT , fspdl_finalpath , sizeof ( fspdl_finalpath ) ) ;
2013-08-06 02:19:06 +00:00
if ( ! FS_GenCachedPakName ( va ( " %s.tmp " , man - > package [ j ] . path ) , crcstr , buffer , sizeof ( buffer ) ) )
2013-06-23 02:17:02 +00:00
continue ;
FS_NativePath ( buffer , FS_ROOT , fspdl_temppath , sizeof ( fspdl_temppath ) ) ;
url = NULL ;
while ( ! url )
{
//ran out of mirrors?
if ( man - > package [ j ] . mirrornum = = ( sizeof ( man - > package [ j ] . mirrors ) / sizeof ( man - > package [ j ] . mirrors [ 0 ] ) ) )
break ;
if ( man - > package [ j ] . mirrors [ man - > package [ j ] . mirrornum ] )
url = FS_RelativeURL ( man - > updateurl , man - > package [ j ] . mirrors [ man - > package [ j ] . mirrornum ] , buffer , sizeof ( buffer ) ) ;
man - > package [ j ] . mirrornum + + ;
}
//no valid mirrors
if ( ! url )
continue ;
curpackagedownload = HTTP_CL_Get ( url , NULL , FS_PackageDownloaded ) ;
if ( curpackagedownload )
{
COM_CreatePath ( fspdl_temppath ) ;
curpackagedownload - > file = VFSOS_Open ( fspdl_temppath , " wb " ) ;
return ;
}
}
}
# else
void FS_BeginNextPackageDownload ( void )
{
}
# endif
//this is potentially unsafe. needs lots of testing.
qboolean FS_ChangeGame ( ftemanifest_t * man , qboolean allowreloadconfigs )
{
int i , j ;
char realpath [ MAX_OSPATH - 1 ] ;
char newbasedir [ MAX_OSPATH ] ;
qboolean fixedbasedir ;
qboolean reloadconfigs = false ;
2013-10-29 17:38:22 +00:00
qboolean builtingame = false ;
2013-06-23 02:17:02 +00:00
flocation_t loc ;
2009-03-03 01:52:30 +00:00
2013-06-23 02:17:02 +00:00
//if any of these files change location, the configs will be re-execed.
//note that we reuse path handles if they're still valid, so we can just check the pointer to see if it got unloaded/replaced.
char * conffile [ ] = { " quake.rc " , " hexen.rc " , " default.cfg " , " server.cfg " , NULL } ;
2013-12-19 16:36:17 +00:00
searchpathfuncs_t * confpath [ sizeof ( conffile ) / sizeof ( conffile [ 0 ] ) ] ;
2013-06-23 02:17:02 +00:00
for ( i = 0 ; conffile [ i ] ; i + + )
{
FS_FLocateFile ( conffile [ i ] , FSLFRT_IFFOUND , & loc ) ; //q1
2013-12-19 16:36:17 +00:00
confpath [ i ] = loc . search ? loc . search - > handle : NULL ;
2013-06-23 02:17:02 +00:00
}
i = COM_CheckParm ( " -basedir " ) ;
fixedbasedir = i & & i < com_argc - 1 ;
Q_strncpyz ( newbasedir , fixedbasedir ? com_argv [ i + 1 ] : host_parms . basedir , sizeof ( newbasedir ) ) ;
//make sure it has a trailing slash, or is empty. woo.
FS_CleanDir ( newbasedir , sizeof ( newbasedir ) ) ;
if ( ! man )
{
//if we're already running a game, don't autodetect.
if ( fs_manifest )
return false ;
man = FS_GenerateLegacyManifest ( newbasedir , sizeof ( newbasedir ) , fixedbasedir , - 1 ) ;
}
if ( man = = fs_manifest )
{
//don't close anything. theoretically nothing is changing, and we don't want to load new defaults either.
}
else if ( ! fs_manifest | | ! strcmp ( fs_manifest - > installation ? fs_manifest - > installation : " " , man - > installation ? man - > installation : " " ) )
{
if ( ! fs_manifest )
reloadconfigs = true ;
FS_Manifest_Free ( fs_manifest ) ;
}
else
{
FS_Shutdown ( ) ;
reloadconfigs = true ;
}
fs_manifest = man ;
if ( man - > installation & & * man - > installation )
{
for ( i = 0 ; gamemode_info [ i ] . argname ; i + + )
{
if ( ! strcmp ( man - > installation , gamemode_info [ i ] . argname + 1 ) )
2009-03-03 01:52:30 +00:00
{
2013-06-23 02:17:02 +00:00
//if there's no base dirs, edit the manifest to give it its default ones.
for ( j = 0 ; j < sizeof ( man - > gamepath ) / sizeof ( man - > gamepath [ 0 ] ) ; j + + )
2009-03-03 01:52:30 +00:00
{
2013-06-23 02:17:02 +00:00
if ( man - > gamepath [ j ] . path & & man - > gamepath [ j ] . base )
break ;
2012-11-27 03:23:19 +00:00
}
2013-06-23 02:17:02 +00:00
if ( j = = sizeof ( man - > gamepath ) / sizeof ( man - > gamepath [ 0 ] ) )
2012-11-27 03:23:19 +00:00
{
for ( j = 0 ; j < 4 ; j + + )
2013-06-23 02:17:02 +00:00
if ( gamemode_info [ i ] . dir [ j ] )
2010-11-02 23:17:25 +00:00
{
2013-06-23 02:17:02 +00:00
Cmd_TokenizeString ( va ( " basegame \" %s \" " , gamemode_info [ i ] . dir [ j ] ) , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
2010-11-02 23:17:25 +00:00
}
2012-11-27 03:23:19 +00:00
}
2013-06-23 02:17:02 +00:00
if ( ! man - > protocolname & & * gamemode_info [ i ] . protocolname )
2012-11-27 03:23:19 +00:00
{
2013-06-23 02:17:02 +00:00
Cmd_TokenizeString ( va ( " protocolname \" %s \" " , gamemode_info [ i ] . protocolname ) , false , false ) ;
FS_Manifest_ParseTokens ( man ) ;
}
if ( ! man - > defaultexec & & gamemode_info [ i ] . customexec )
{
man - > defaultexec = Z_StrDup ( gamemode_info [ i ] . customexec ) ;
2009-03-03 01:52:30 +00:00
}
2013-06-23 02:17:02 +00:00
2013-10-29 17:38:22 +00:00
builtingame = true ;
2013-06-23 02:17:02 +00:00
if ( ! fixedbasedir & & ! FS_DirHasGame ( newbasedir , i ) )
if ( Sys_FindGameData ( man - > formalname , man - > installation , realpath , sizeof ( realpath ) ) )
Q_strncpyz ( newbasedir , realpath , sizeof ( newbasedir ) ) ;
break ;
2009-03-03 01:52:30 +00:00
}
}
2005-08-26 22:52:26 +00:00
}
2013-10-29 17:38:22 +00:00
if ( ! builtingame & & ! fixedbasedir & & ! FS_DirHasAPackage ( newbasedir , man ) )
if ( Sys_FindGameData ( man - > formalname , man - > installation , realpath , sizeof ( realpath ) ) )
Q_strncpyz ( newbasedir , realpath , sizeof ( newbasedir ) ) ;
2013-06-23 02:17:02 +00:00
Q_strncpyz ( com_quakedir , newbasedir , sizeof ( com_quakedir ) ) ;
//make sure it has a trailing slash, or is empty. woo.
FS_CleanDir ( com_quakedir , sizeof ( com_quakedir ) ) ;
2005-08-26 22:52:26 +00:00
2013-06-23 02:17:02 +00:00
# ifdef ANDROID
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
vfsfile_t * f ;
//write a .nomedia file to avoid people from getting random explosion sounds etc intersperced with their music
f = FS_OpenVFS ( " .nomedia " , " rb " , FS_ROOT ) ;
if ( f )
VFS_CLOSE ( f ) ;
else
FS_WriteFile ( " .nomedia " , NULL , 0 , FS_ROOT ) ;
}
# endif
FS_ReloadPackFilesFlags ( ~ 0 ) ;
FS_BeginNextPackageDownload ( ) ;
2013-09-26 09:24:52 +00:00
COM_CheckRegistered ( ) ;
2013-06-23 02:17:02 +00:00
if ( allowreloadconfigs )
{
for ( i = 0 ; conffile [ i ] ; i + + )
2005-08-26 22:52:26 +00:00
{
2013-06-23 02:17:02 +00:00
FS_FLocateFile ( conffile [ i ] , FSLFRT_IFFOUND , & loc ) ;
2013-12-19 16:36:17 +00:00
if ( confpath [ i ] ! = ( loc . search ? loc . search - > handle : NULL ) )
{
2013-06-23 02:17:02 +00:00
reloadconfigs = true ;
2013-12-19 16:36:17 +00:00
Con_DPrintf ( " Reloading configs because %s has changed \n " , conffile [ i ] ) ;
}
2013-06-23 02:17:02 +00:00
}
if ( reloadconfigs )
{
//FIXME: flag this instead and do it after a delay
Cvar_ForceSet ( & fs_gamename , man - > formalname ? man - > formalname : " FTE " ) ;
Cvar_ForceSet ( & com_protocolname , man - > protocolname ? man - > protocolname : " FTE " ) ;
if ( isDedicated )
2010-12-05 02:46:07 +00:00
{
2013-06-23 02:17:02 +00:00
# ifndef CLIENTONLY
SV_ExecInitialConfigs ( man - > defaultexec ? man - > defaultexec : " " ) ;
# endif
}
else
{
# ifndef SERVERONLY
CL_ExecInitialConfigs ( man - > defaultexec ? man - > defaultexec : " " ) ;
# endif
}
}
}
2014-02-07 08:38:40 +00:00
//rebuild the cache now, should be safe to waste some cycles on it
FS_RebuildFSHash ( ) ;
2010-12-05 02:46:07 +00:00
2013-06-23 02:17:02 +00:00
COM_Effectinfo_Clear ( ) ;
# ifndef SERVERONLY
Validation_FlushFileList ( ) ; //prevent previous hacks from making a difference.
# endif
2014-02-11 17:51:29 +00:00
Cvar_ForceSet ( & fs_game , FS_GetGamedir ( ) ) ;
# ifdef Q2SERVER
Cvar_ForceSet ( & fs_gamedir , va ( " %s%s " , com_quakedir , FS_GetGamedir ( ) ) ) ;
Cvar_ForceSet ( & fs_basedir , com_quakedir ) ;
# endif
2013-06-23 02:17:02 +00:00
return true ;
}
void FS_ChangeGame_f ( void )
{
int i ;
char * arg = Cmd_Argv ( 1 ) ;
if ( ! * arg )
{
Con_Printf ( " Valid games are: \n " ) ;
for ( i = 0 ; gamemode_info [ i ] . argname ; i + + )
{
Con_Printf ( " %s \n " , gamemode_info [ i ] . argname + 1 ) ;
}
}
else
{
for ( i = 0 ; gamemode_info [ i ] . argname ; i + + )
{
2014-02-07 08:38:40 +00:00
if ( ! Q_strcasecmp ( gamemode_info [ i ] . argname + 1 , arg ) )
2013-06-23 02:17:02 +00:00
{
Con_Printf ( " Switching to %s \n " , gamemode_info [ i ] . argname + 1 ) ;
FS_ChangeGame ( FS_GenerateLegacyManifest ( NULL , 0 , true , i ) , true ) ;
return ;
2010-12-05 02:46:07 +00:00
}
2005-08-26 22:52:26 +00:00
}
2013-08-06 10:48:51 +00:00
2013-08-21 08:06:35 +00:00
# ifndef SERVERONLY
2013-08-06 10:48:51 +00:00
if ( ! Host_RunFile ( arg , strlen ( arg ) , NULL ) )
Con_Printf ( " Game unknown \n " ) ;
2013-08-21 08:06:35 +00:00
# endif
2005-08-26 22:52:26 +00:00
}
2013-06-23 02:17:02 +00:00
}
void FS_ShowManifest_f ( void )
{
if ( fs_manifest )
FS_Manifest_Print ( fs_manifest ) ;
else
Con_Printf ( " no manifest loaded... \n " ) ;
}
/*
= = = = = = = = = = = = = = = =
COM_InitFilesystem
note : does not actually load any packs , just makes sure the basedir + cvars + etc is set up . vfs_fopens will still fail .
= = = = = = = = = = = = = = = =
*/
void COM_InitFilesystem ( void )
{
int i ;
char * ev ;
qboolean usehome ;
FS_RegisterDefaultFileSystems ( ) ;
Cmd_AddCommand ( " fs_restart " , FS_ReloadPackFiles_f ) ;
Cmd_AddCommand ( " fs_changegame " , FS_ChangeGame_f ) ;
Cmd_AddCommand ( " fs_showmanifest " , FS_ShowManifest_f ) ;
//
// -basedir <path>
// Overrides the system supplied base directory (under id1)
//
i = COM_CheckParm ( " -basedir " ) ;
if ( i & & i < com_argc - 1 )
strcpy ( com_quakedir , com_argv [ i + 1 ] ) ;
else
strcpy ( com_quakedir , host_parms . basedir ) ;
FS_CleanDir ( com_quakedir , sizeof ( com_quakedir ) ) ;
2014-02-11 17:51:29 +00:00
Cvar_Register ( & cfg_reload_on_gamedir , " Filesystem " ) ;
Cvar_Register ( & com_fs_cache , " Filesystem " ) ;
Cvar_Register ( & fs_gamename , " Filesystem " ) ;
Cvar_Register ( & fs_gamemanifest , " Filesystem " ) ;
2013-06-23 02:17:02 +00:00
Cvar_Register ( & com_protocolname , " Server Info " ) ;
Cvar_Register ( & com_modname , " Server Info " ) ;
2014-02-11 17:51:29 +00:00
Cvar_Register ( & fs_game , " Filesystem " ) ;
# ifdef Q2SERVER
Cvar_Register ( & fs_gamedir , " Filesystem " ) ;
Cvar_Register ( & fs_basedir , " Filesystem " ) ;
# endif
2009-03-03 01:52:30 +00:00
2008-06-13 05:03:54 +00:00
usehome = false ;
2005-08-26 22:52:26 +00:00
# ifdef _WIN32
{ //win32 sucks.
2008-06-13 05:03:54 +00:00
HMODULE shfolder = LoadLibrary ( " shfolder.dll " ) ;
DWORD winver = ( DWORD ) LOBYTE ( LOWORD ( GetVersion ( ) ) ) ;
if ( shfolder )
{
HRESULT ( WINAPI * dSHGetFolderPath ) ( HWND hwndOwner , int nFolder , HANDLE hToken , DWORD dwFlags , LPTSTR pszPath ) ;
dSHGetFolderPath = ( void * ) GetProcAddress ( shfolder , " SHGetFolderPathA " ) ;
if ( dSHGetFolderPath )
{
char folder [ MAX_PATH ] ;
// 0x5 == CSIDL_PERSONAL
if ( dSHGetFolderPath ( NULL , 0x5 , NULL , 0 , folder ) = = S_OK )
Q_snprintfz ( com_homedir , sizeof ( com_homedir ) , " %s/My Games/%s/ " , folder , FULLENGINENAME ) ;
}
2010-12-23 06:09:25 +00:00
// FreeLibrary(shfolder);
2008-06-13 05:03:54 +00:00
}
2009-04-01 22:03:56 +00:00
if ( ! * com_homedir )
{
ev = getenv ( " USERPROFILE " ) ;
if ( ev )
Q_snprintfz ( com_homedir , sizeof ( com_homedir ) , " %s/My Documents/My Games/%s/ " , ev , FULLENGINENAME ) ;
}
2011-09-16 05:56:54 +00:00
# ifdef NPFTE
2009-04-01 22:03:56 +00:00
if ( ! * com_homedir )
2009-04-07 01:26:47 +00:00
Q_snprintfz ( com_homedir , sizeof ( com_homedir ) , " /%s/ " , FULLENGINENAME ) ;
2009-04-01 22:03:56 +00:00
//as a browser plugin, always use their home directory
usehome = true ;
# else
2010-08-16 02:03:02 +00:00
/*would it not be better to just check to see if we have write permission to the basedir?*/
2008-06-13 05:03:54 +00:00
if ( winver > = 0x6 ) // Windows Vista and above
usehome = true ; // always use home directory by default, as Vista+ mimics this behavior anyway
else if ( winver > = 0x5 ) // Windows 2000/XP/2003
{
2009-04-07 01:26:47 +00:00
HMODULE advapi32 ;
2008-06-13 07:24:11 +00:00
advapi32 = LoadLibrary ( " advapi32.dll " ) ;
if ( advapi32 )
2009-06-03 09:09:35 +00:00
{
2008-06-13 07:24:11 +00:00
BOOL ( WINAPI * dCheckTokenMembership ) ( HANDLE TokenHandle , PSID SidToCheck , PBOOL IsMember ) ;
dCheckTokenMembership = ( void * ) GetProcAddress ( advapi32 , " CheckTokenMembership " ) ;
2008-06-13 05:03:54 +00:00
2008-06-13 07:24:11 +00:00
if ( dCheckTokenMembership )
{
2009-06-03 09:09:35 +00:00
// on XP systems, only use a home directory by default if we're a limited user or if we're on a network
2008-06-13 07:24:11 +00:00
BOOL isadmin , isonnetwork ;
2013-06-24 09:04:00 +00:00
SID_IDENTIFIER_AUTHORITY ntauth = { SECURITY_NT_AUTHORITY } ;
2008-06-13 07:24:11 +00:00
PSID adminSID , networkSID ;
isadmin = AllocateAndInitializeSid ( & ntauth ,
2 ,
SECURITY_BUILTIN_DOMAIN_RID ,
DOMAIN_ALIAS_RID_ADMINS ,
0 , 0 , 0 , 0 , 0 , 0 ,
2009-06-03 09:09:35 +00:00
& adminSID ) ;
2008-06-13 07:24:11 +00:00
// just checking the network rid should be close enough to matching domain logins
isonnetwork = AllocateAndInitializeSid ( & ntauth ,
1 ,
SECURITY_NETWORK_RID ,
0 , 0 , 0 , 0 , 0 , 0 , 0 ,
& networkSID ) ;
if ( isadmin & & ! dCheckTokenMembership ( 0 , adminSID , & isadmin ) )
isadmin = 0 ;
if ( isonnetwork & & ! dCheckTokenMembership ( 0 , networkSID , & isonnetwork ) )
isonnetwork = 0 ;
usehome = isonnetwork | | ! isadmin ;
FreeSid ( networkSID ) ;
FreeSid ( adminSID ) ;
}
FreeLibrary ( advapi32 ) ;
}
}
2009-04-01 22:03:56 +00:00
# endif
2005-08-26 22:52:26 +00:00
}
# else
//yay for unix!.
ev = getenv ( " HOME " ) ;
2009-02-03 00:12:50 +00:00
if ( ev & & * ev )
2008-06-13 05:03:54 +00:00
{
2009-02-03 00:12:50 +00:00
if ( ev [ strlen ( ev ) - 1 ] = = ' / ' )
Q_snprintfz ( com_homedir , sizeof ( com_homedir ) , " %s.fte/ " , ev ) ;
else
Q_snprintfz ( com_homedir , sizeof ( com_homedir ) , " %s/.fte/ " , ev ) ;
2008-06-13 05:03:54 +00:00
usehome = true ; // always use home on unix unless told not to
}
2005-08-26 22:52:26 +00:00
else
* com_homedir = ' \0 ' ;
# endif
2008-06-13 05:03:54 +00:00
if ( ! usehome & & ! COM_CheckParm ( " -usehome " ) )
2005-08-26 22:52:26 +00:00
* com_homedir = ' \0 ' ;
2005-11-30 01:20:53 +00:00
if ( COM_CheckParm ( " -nohome " ) )
* com_homedir = ' \0 ' ;
2005-08-26 22:52:26 +00:00
if ( * com_homedir )
2013-11-29 14:36:47 +00:00
Con_TPrintf ( " Using home directory \" %s \" \n " , com_homedir ) ;
2005-08-26 22:52:26 +00:00
2013-05-03 04:28:08 +00:00
# ifdef PLUGINS
Plug_Initialise ( false ) ;
# endif
2005-08-26 22:52:26 +00:00
}
2009-04-01 22:03:56 +00:00
//this is at the bottom of the file to ensure these globals are not used elsewhere
2013-06-23 02:17:02 +00:00
extern searchpathfuncs_t * ( QDECL VFSOS_OpenPath ) ( vfsfile_t * file , const char * desc ) ;
# ifdef AVAIL_ZLIB
extern searchpathfuncs_t * ( QDECL FSZIP_LoadArchive ) ( vfsfile_t * packhandle , const char * desc ) ;
# endif
extern searchpathfuncs_t * ( QDECL FSPAK_LoadArchive ) ( vfsfile_t * packhandle , const char * desc ) ;
# ifdef DOOMWADS
extern searchpathfuncs_t * ( QDECL FSDWD_LoadArchive ) ( vfsfile_t * packhandle , const char * desc ) ;
# endif
2009-04-01 22:03:56 +00:00
void FS_RegisterDefaultFileSystems ( void )
{
2013-06-23 02:17:02 +00:00
FS_RegisterFileSystemType ( NULL , " pak " , FSPAK_LoadArchive , true ) ;
2011-09-16 05:56:54 +00:00
# if !defined(_WIN32) && !defined(ANDROID)
2010-07-11 10:53:13 +00:00
/*for systems that have case sensitive paths, also include *.PAK */
2013-06-23 02:17:02 +00:00
FS_RegisterFileSystemType ( NULL , " PAK " , FSPAK_LoadArchive , true ) ;
2010-07-11 10:53:13 +00:00
# endif
2013-10-29 17:38:22 +00:00
FS_RegisterFileSystemType ( NULL , " pk3dir " , VFSOS_OpenPath , true ) ;
2009-04-01 22:03:56 +00:00
# ifdef AVAIL_ZLIB
2013-06-23 02:17:02 +00:00
FS_RegisterFileSystemType ( NULL , " pk3 " , FSZIP_LoadArchive , true ) ;
FS_RegisterFileSystemType ( NULL , " pk4 " , FSZIP_LoadArchive , true ) ;
FS_RegisterFileSystemType ( NULL , " apk " , FSZIP_LoadArchive , false ) ;
FS_RegisterFileSystemType ( NULL , " zip " , FSZIP_LoadArchive , false ) ;
2009-04-01 22:03:56 +00:00
# endif
# ifdef DOOMWADS
2013-06-23 02:17:02 +00:00
FS_RegisterFileSystemType ( NULL , " wad " , FSDWD_LoadArchive , true ) ;
2009-04-01 22:03:56 +00:00
# endif
2009-04-02 22:25:54 +00:00
}