From d457d7d093832c1b765612d87e7a5338ed347c73 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Mon, 28 Apr 2025 22:27:16 +0300 Subject: [PATCH] filesystem: archive mounting refactoring --- filesystem/VFileSystem009.cpp | 10 +-- filesystem/filesystem.c | 108 ++++++++++++++++++++++--------- filesystem/filesystem_internal.h | 14 +--- 3 files changed, 79 insertions(+), 53 deletions(-) diff --git a/filesystem/VFileSystem009.cpp b/filesystem/VFileSystem009.cpp index c00b882d..6b462f70 100644 --- a/filesystem/VFileSystem009.cpp +++ b/filesystem/VFileSystem009.cpp @@ -470,19 +470,11 @@ public: bool AddPackFile( const char *path, const char *id ) override { char dir[MAX_VA_STRING], fullpath[MAX_VA_STRING]; - const char *ext = COM_FileExtension( path ); IdToDir( dir, sizeof( dir ), id ); Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", dir, path ); COM_FixSlashes( fullpath ); - - for( const fs_archive_t *archive = g_archives; archive->ext; archive++ ) - { - if( archive->type == SEARCHPATH_PAK && !Q_stricmp( ext, archive->ext )) - return FS_AddArchive_Fullpath( archive, fullpath, FS_CUSTOM_PATH ); - } - - return false; + return FS_MountArchive_Fullpath( fullpath, FS_CUSTOM_PATH ) != NULL; } FileHandle_t OpenFromCacheForRead( const char *path , const char *mode, const char *id ) override diff --git a/filesystem/filesystem.c b/filesystem/filesystem.c index 1579c6ad..b7e17a1c 100644 --- a/filesystem/filesystem.c +++ b/filesystem/filesystem.c @@ -52,35 +52,70 @@ GNU General Public License for more details. #define SAVE_AGED_COUNT 2 // the default count of quick and auto saves fs_globals_t FI; -qboolean fs_ext_path = false; // attempt to read\write from ./ or ../ pathes poolhandle_t fs_mempool; -char fs_rodir[MAX_SYSPATH]; char fs_rootdir[MAX_SYSPATH]; searchpath_t *fs_writepath; static searchpath_t *fs_searchpaths = NULL; // chain static char fs_basedir[MAX_SYSPATH]; // base game directory static char fs_gamedir[MAX_SYSPATH]; // game current directory +static char fs_rodir[MAX_SYSPATH]; static string fs_language; +static qboolean fs_ext_path = false; // attempt to read\write from ./ or ../ pathes + +typedef struct fs_archive_s +{ + const char *ext; + int type; + FS_ADDARCHIVE_FULLPATH pfnAddArchive_Fullpath; + qboolean load_wads; // load wads from this archive + qboolean real_archive; +} fs_archive_t; // add archives in specific order PAK -> PK3 -> WAD // so raw WADs takes precedence over WADs included into PAKs and PK3s -const fs_archive_t g_archives[] = +static const fs_archive_t g_archives[] = { -{ "pak", SEARCHPATH_PAK, FS_AddPak_Fullpath, true, true }, -{ "pk3", SEARCHPATH_ZIP, FS_AddZip_Fullpath, true, true }, -{ "pk3dir", SEARCHPATH_PK3DIR, FS_AddDir_Fullpath, true, false }, -{ "wad", SEARCHPATH_WAD, FS_AddWad_Fullpath, false, true }, -{ NULL }, // end marker + { + .ext = "pak", + .type = SEARCHPATH_PAK, + .pfnAddArchive_Fullpath = FS_AddPak_Fullpath, + .load_wads = true, + .real_archive = true, + }, { + .ext = "pk3", + .type = SEARCHPATH_ZIP, + .pfnAddArchive_Fullpath = FS_AddZip_Fullpath, + .load_wads = true, + .real_archive = true, + }, { + .ext = "pk3dir", + .type = SEARCHPATH_PK3DIR, + .pfnAddArchive_Fullpath = FS_AddDir_Fullpath, + .load_wads = true, + .real_archive = false, + }, { + .ext = "wad", + .type = SEARCHPATH_WAD, + .pfnAddArchive_Fullpath = FS_AddWad_Fullpath, + .load_wads = false, + .real_archive = true, + }, }; // special fs_archive_t for plain directories static const fs_archive_t g_directory_archive = -{ NULL, SEARCHPATH_PLAIN, FS_AddDir_Fullpath, false }; +{ + .type = SEARCHPATH_PLAIN, + .pfnAddArchive_Fullpath = FS_AddDir_Fullpath, +}; #if XASH_ANDROID static const fs_archive_t g_android_archive = -{ NULL, SEARCHPATH_ANDROID_ASSETS, FS_AddAndroidAssets_Fullpath, false }; +{ + .type = SEARCHPATH_ANDROID_ASSETS, + .pfnAddArchive_Fullpath = FS_AddAndroidAssets_Fullpath +}; #endif #ifdef XASH_REDUCE_FD @@ -328,10 +363,31 @@ void FS_CreatePath( char *path ) } } -searchpath_t *FS_AddArchive_Fullpath( const fs_archive_t *archive, const char *file, int flags ) +static searchpath_t *FS_AddArchive_Fullpath( const fs_archive_t *archive, const char *file, int flags ) { searchpath_t *search; + if( !archive ) + { + int i; + const char *ext = COM_FileExtension( file ); + + for( i = 0; i < sizeof( g_archives ) / sizeof( g_archives[0] ); i++ ) + { + if( !Q_stricmp( g_archives[i].ext, ext )) + { + archive = &g_archives[i]; + break; + } + } + + if( !archive ) + { + Con_Printf( S_ERROR "%s: unknown archive format %s, not mounted\n", __func__, file ); + return NULL; + } + } + for( search = fs_searchpaths; search; search = search->next ) { if( search->type == archive->type && !Q_stricmp( search->filename, file )) @@ -380,18 +436,9 @@ searchpath_t *FS_AddArchive_Fullpath( const fs_archive_t *archive, const char *f FS_AddArchive_Fullpath ================ */ -static searchpath_t *FS_MountArchive_Fullpath( const char *file, int flags ) +searchpath_t *FS_MountArchive_Fullpath( const char *file, int flags ) { - const fs_archive_t *archive; - const char *ext = COM_FileExtension( file ); - - for( archive = g_archives; archive->ext; archive++ ) - { - if( !Q_stricmp( ext, archive->ext )) - return FS_AddArchive_Fullpath( archive, file, flags ); - } - - return NULL; + return FS_AddArchive_Fullpath( NULL, file, flags ); } /* @@ -404,27 +451,26 @@ then loads and adds pak1.pak pak2.pak ... */ void FS_AddGameDirectory( const char *dir, uint flags ) { - const fs_archive_t *archive; stringlist_t list; searchpath_t *search; - char fullpath[MAX_SYSPATH]; - int i; + int i, j; stringlistinit( &list ); listdirectory( &list, dir, false ); stringlistsort( &list ); - for( archive = g_archives; archive->ext; archive++ ) + for( j = 0; j < sizeof( g_archives ) / sizeof( g_archives[0] ); j++ ) { + char fullpath[MAX_SYSPATH]; + int i; + for( i = 0; i < list.numstrings; i++ ) { - const char *ext = COM_FileExtension( list.strings[i] ); - - if( Q_stricmp( ext, archive->ext )) + if( Q_stricmp( COM_FileExtension( list.strings[i] ), g_archives[j].ext )) continue; Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", dir, list.strings[i] ); - FS_AddArchive_Fullpath( archive, fullpath, flags ); + FS_AddArchive_Fullpath( &g_archives[j], fullpath, flags ); } } @@ -3294,7 +3340,7 @@ static qboolean FS_IsArchiveExtensionSupported( const char *ext, uint flags ) if( ext == NULL ) return false; - for( i = 0; i < ( sizeof( g_archives ) / sizeof( g_archives[0] )) - 1; i++ ) + for( i = 0; i < sizeof( g_archives ) / sizeof( g_archives[0] ); i++ ) { if( FBitSet( flags, IAES_ONLY_REAL_ARCHIVES ) && !g_archives[i].real_archive ) continue; diff --git a/filesystem/filesystem_internal.h b/filesystem/filesystem_internal.h index ce717747..ed7c241e 100644 --- a/filesystem/filesystem_internal.h +++ b/filesystem/filesystem_internal.h @@ -122,24 +122,12 @@ typedef struct searchpath_s typedef searchpath_t *(*FS_ADDARCHIVE_FULLPATH)( const char *path, int flags ); -typedef struct fs_archive_s -{ - const char *ext; - int type; - FS_ADDARCHIVE_FULLPATH pfnAddArchive_Fullpath; - qboolean load_wads; // load wads from this archive - qboolean real_archive; -} fs_archive_t; - extern fs_globals_t FI; extern searchpath_t *fs_writepath; extern poolhandle_t fs_mempool; extern fs_interface_t g_engfuncs; -extern qboolean fs_ext_path; -extern char fs_rodir[MAX_SYSPATH]; extern char fs_rootdir[MAX_SYSPATH]; extern const fs_api_t g_api; -extern const fs_archive_t g_archives[]; #define GI FI.GameInfo @@ -161,7 +149,7 @@ extern const fs_archive_t g_archives[]; // qboolean FS_InitStdio( qboolean caseinsensitive, const char *rootdir, const char *basedir, const char *gamedir, const char *rodir ); void FS_ShutdownStdio( void ); -searchpath_t *FS_AddArchive_Fullpath( const fs_archive_t *archive, const char *file, int flags ); +searchpath_t *FS_MountArchive_Fullpath( const char *file, int flags ); void _Mem_Free( void *data, const char *filename, int fileline ); void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline ) ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;