Skip to content

Commit

Permalink
Merged pull request "Sync with Q2PRO: More filesystem changes": #360
Browse files Browse the repository at this point in the history
  • Loading branch information
apanteleev committed Nov 22, 2023
2 parents b319f34 + 341c26d commit 119c4e7
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 45 deletions.
3 changes: 2 additions & 1 deletion inc/common/cvar.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ interface from being ambiguous.
#define CVAR_CUSTOM (1 << 9) // created by user
#define CVAR_WEAK (1 << 10) // doesn't have value
#define CVAR_GAME (1 << 11) // created by game library
#define CVAR_NOARCHIVE (1 << 12) // never saved to config
#define CVAR_FILES (1 << 13) // r_reload when changed
#define CVAR_REFRESH (1 << 14) // vid_restart when changed
#define CVAR_SOUND (1 << 15) // snd_restart when changed

#define CVAR_INFOMASK (CVAR_USERINFO | CVAR_SERVERINFO)
#define CVAR_MODIFYMASK (CVAR_INFOMASK | CVAR_FILES | CVAR_REFRESH | CVAR_SOUND)
#define CVAR_NOARCHIVEMASK (CVAR_NOSET | CVAR_CHEAT | CVAR_PRIVATE | CVAR_ROM)
#define CVAR_NOARCHIVEMASK (CVAR_NOSET | CVAR_CHEAT | CVAR_PRIVATE | CVAR_ROM | CVAR_NOARCHIVE)
#define CVAR_EXTENDED_MASK (~31)

extern cvar_t *cvar_vars;
Expand Down
1 change: 1 addition & 0 deletions inc/common/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ typedef struct file_info_s {
void FS_Init(void);
void FS_Shutdown(void);
void FS_Restart(bool total);
void FS_AddConfigFiles(bool init);

#if USE_CLIENT
int FS_RenameFile(const char *from, const char *to);
Expand Down
8 changes: 1 addition & 7 deletions src/common/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -969,13 +969,7 @@ void Qcommon_Init(int argc, char **argv)
logfile_name->changed = logfile_param_changed;
logfile_enable_changed(logfile_enable);

// execute configs: default.cfg and q2rtx.cfg may come from the packfile, but config.cfg
// and autoexec.cfg must be real files within the game directory
Com_AddConfigFile(COM_DEFAULT_CFG, 0);
Com_AddConfigFile(COM_Q2RTX_CFG, 0);
Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | FS_PATH_GAME);
Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_GAME);
Com_AddConfigFile(COM_POSTEXEC_CFG, FS_TYPE_REAL);
FS_AddConfigFiles(true);

Com_AddEarlyCommands(true);

Expand Down
135 changes: 98 additions & 37 deletions src/common/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ static int fs_count_strlwr;
#define FS_COUNT_STRLWR (void)0
#endif

static cvar_t *fs_autoexec;

#if USE_DEBUG
static cvar_t *fs_debug;
#endif
Expand Down Expand Up @@ -635,6 +637,8 @@ int FS_CreatePath(char *path)
ofs = p + 1;
}
}
} else if (Q_isalpha(*path) && path[1] == ':') {
ofs = path + 2; // skip drive part
}
#endif

Expand Down Expand Up @@ -2149,39 +2153,39 @@ static pack_t *load_pak_file(const char *packfile)

if (!fread(&header, sizeof(header), 1, fp)) {
Com_SetLastError("reading header failed");
goto fail;
goto fail1;
}

if (LittleLong(header.ident) != IDPAKHEADER) {
Com_SetLastError("bad header ident");
goto fail;
goto fail1;
}

header.dirlen = LittleLong(header.dirlen);
if (header.dirlen > INT_MAX || header.dirlen % sizeof(dpackfile_t)) {
Com_SetLastError("bad directory length");
goto fail;
goto fail1;
}

num_files = header.dirlen / sizeof(dpackfile_t);
if (num_files < 1) {
Com_SetLastError("no files");
goto fail;
goto fail1;
}

header.dirofs = LittleLong(header.dirofs);
if (header.dirofs > INT_MAX) {
Com_SetLastError("bad directory offset");
goto fail;
goto fail1;
}
if (os_fseek(fp, header.dirofs, SEEK_SET)) {
Com_SetLastError("seeking to directory failed");
goto fail;
goto fail1;
}
info = FS_Malloc(header.dirlen);
info = FS_AllocTempMem(header.dirlen);
if (!fread(info, header.dirlen, 1, fp)) {
Com_SetLastError("reading directory failed");
goto fail;
goto fail2;
}

names_len = 0;
Expand All @@ -2190,7 +2194,7 @@ static pack_t *load_pak_file(const char *packfile)
dfile->filelen = LittleLong(dfile->filelen);
if (dfile->filelen > INT_MAX || dfile->filepos > INT_MAX - dfile->filelen) {
Com_SetLastError("file length or position too big");
goto fail;
goto fail2;
}
names_len += Q_strnlen(dfile->name, sizeof(dfile->name)) + 1;
}
Expand Down Expand Up @@ -2225,11 +2229,12 @@ static pack_t *load_pak_file(const char *packfile)
FS_DPrintf("%s: %u files, %u hash\n",
packfile, pack->num_files, pack->hash_size);

Z_Free(info);

FS_FreeTempMem(info);
return pack;

fail:
fail2:
FS_FreeTempMem(info);
fail1:
fclose(fp);
Z_Free(info);
return NULL;
Expand Down Expand Up @@ -3530,6 +3535,11 @@ static void setup_base_paths(void)
// the GAME bit will be removed once gamedir is set,
// and will be put back once gamedir is reset to basegame
add_game_dir(FS_PATH_BASE | FS_PATH_GAME, "%s/"BASEGAME, sys_basedir->string);

if (sys_homedir->string[0]) {
add_game_dir(FS_PATH_BASE | FS_PATH_GAME, "%s/"BASEGAME, sys_homedir->string);
}

fs_base_searchpaths = fs_searchpaths;
}

Expand All @@ -3544,7 +3554,6 @@ static void setup_game_paths(void)

// home paths override system paths
if (sys_homedir->string[0]) {
add_game_dir(FS_PATH_BASE, "%s/"BASEGAME, sys_homedir->string);
add_game_dir(FS_PATH_GAME, "%s/%s", sys_homedir->string, fs_game->string);
}

Expand All @@ -3555,13 +3564,7 @@ static void setup_game_paths(void)

// this var is set for compatibility with server browsers, etc
Cvar_FullSet("gamedir", fs_game->string, CVAR_ROM | CVAR_SERVERINFO, FROM_CODE);

} else {
if (sys_homedir->string[0]) {
add_game_dir(FS_PATH_BASE | FS_PATH_GAME,
"%s/"BASEGAME, sys_homedir->string);
}

// add the game bit to base paths
for (path = fs_base_searchpaths; path; path = path->next) {
path->mode |= FS_PATH_GAME;
Expand All @@ -3574,6 +3577,18 @@ static void setup_game_paths(void)
Cvar_FullSet("fs_gamedir", fs_gamedir, CVAR_ROM, FROM_CODE);
}

static void setup_base_gamedir(void)
{
if (sys_homedir->string[0]) {
Q_snprintf(fs_gamedir, sizeof(fs_gamedir), "%s/"BASEGAME, sys_homedir->string);
} else {
Q_snprintf(fs_gamedir, sizeof(fs_gamedir), "%s/"BASEGAME, sys_basedir->string);
}
#ifdef _WIN32
FS_ReplaceSeparators(fs_gamedir, '/');
#endif
}

/*
================
FS_Restart
Expand All @@ -3592,10 +3607,7 @@ void FS_Restart(bool total)
} else {
// just change gamedir
free_game_paths();
Q_snprintf(fs_gamedir, sizeof(fs_gamedir), "%s/"BASEGAME, sys_basedir->string);
#ifdef _WIN32
FS_ReplaceSeparators(fs_gamedir, '/');
#endif
setup_base_gamedir();
}

setup_game_paths();
Expand Down Expand Up @@ -3673,6 +3685,34 @@ void FS_Shutdown(void)
Cmd_Deregister(c_fs);
}

/*
================
FS_AddConfigFiles
================
*/
void FS_AddConfigFiles(bool init)
{
int flag = init ? FS_PATH_ANY : FS_PATH_GAME;

if (!init && !fs_autoexec->integer)
return;

// default.cfg and q2rtx.cfg may come from packfile, but config.cfg and autoexec.cfg
// must be real files within the game directory.
Com_AddConfigFile(COM_DEFAULT_CFG, flag);
Com_AddConfigFile(COM_Q2RTX_CFG, FS_PATH_ANY);
Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | flag);

// autoexec.cfg is executed twice, first from basedir and then from
// gamedir. This ensures user settings configured in baseq2/autoexec.cfg
// override those in default.cfg and config.cfg.
if (*fs_game->string)
Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE);
Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_GAME);

Com_AddConfigFile(COM_POSTEXEC_CFG, FS_TYPE_REAL);
}

// this is called when local server starts up and gets it's latched variables,
// client receives a serverdata packet, or user changes the game by hand while
// disconnected
Expand All @@ -3683,7 +3723,7 @@ static void fs_game_changed(cvar_t *self)
// validate it
if (*s) {
if (!Q_stricmp(s, BASEGAME)) {
Cvar_Reset(self);
Cvar_SetByVar(self, "", FROM_CODE);
} else if (!COM_IsPath(s)) {
Com_Printf("'%s' should contain characters [A-Za-z0-9_-] only.\n", self->name);
Cvar_Reset(self);
Expand Down Expand Up @@ -3720,22 +3760,40 @@ static void fs_game_changed(cvar_t *self)
// otherwise, restart the filesystem
CL_RestartFilesystem(false);

Com_AddConfigFile(COM_DEFAULT_CFG, FS_PATH_GAME);
Com_AddConfigFile(COM_Q2RTX_CFG, 0);
Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | FS_PATH_GAME);
FS_AddConfigFiles(false);
}

// If baseq2/autoexec.cfg exists exec it again after default.cfg and config.cfg.
// Assumes user prefers to do configuration via autoexec.cfg and hopefully
// settings and binds will be restored to their preference whenever gamedir changes after startup.
if(Q_stricmp(s, BASEGAME) && FS_FileExistsEx(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE)) {
Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE);
static void list_dirs(genctx_t *ctx, const char *path)
{
listfiles_t list = {
.flags = FS_SEARCH_DIRSONLY,
};

Sys_ListFiles_r(&list, path, 0);

for (int i = 0; i < list.count; i++) {
char *s = list.files[i];

if (COM_IsPath(s))
Prompt_AddMatch(ctx, s);

Z_Free(s);
}

// exec autoexec.cfg (must be a real file within the game directory)
Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_GAME);
Z_Free(list.files);
}

// exec postexec.cfg (must be a real file)
Com_AddConfigFile(COM_POSTEXEC_CFG, FS_TYPE_REAL);
static void fs_game_generator(genctx_t *ctx)
{
ctx->ignoredups = true;
#ifdef _WIN32
ctx->ignorecase = true;
#endif

list_dirs(ctx, sys_basedir->string);

if (sys_homedir->string[0])
list_dirs(ctx, sys_homedir->string);
}

/*
Expand All @@ -3752,15 +3810,18 @@ void FS_Init(void)

Cmd_Register(c_fs);

fs_autoexec = Cvar_Get("fs_autoexec", "1", 0);

#if USE_DEBUG
fs_debug = Cvar_Get("fs_debug", "0", 0);
#endif

fs_shareware = Cvar_Get("fs_shareware", "0", CVAR_ROM);

// get the game cvar and start the filesystem
fs_game = Cvar_Get("game", DEFGAME, CVAR_LATCH | CVAR_SERVERINFO);
fs_game = Cvar_Get("game", DEFGAME, CVAR_LATCH | CVAR_SERVERINFO | CVAR_NOARCHIVE);
fs_game->changed = fs_game_changed;
fs_game->generator = fs_game_generator;
fs_game_changed(fs_game);

Com_Printf("-----------------------\n");
Expand Down

0 comments on commit 119c4e7

Please sign in to comment.