From 0d6137ee4025c53f6600dbfcec8450f9787be889 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 8 Jun 2023 22:14:12 +0300 Subject: [PATCH] filesystem: make generic archive loading functions (with the exception of WADs). Do not alter global searchpath from archives. --- filesystem/VFileSystem009.cpp | 14 +++- filesystem/dir.c | 19 +---- filesystem/filesystem.c | 138 +++++++++++++++++++------------ filesystem/filesystem_internal.h | 20 ++++- filesystem/pak.c | 77 ++++++----------- filesystem/wad.c | 65 ++++++--------- filesystem/zip.c | 78 ++++++----------- 7 files changed, 184 insertions(+), 227 deletions(-) diff --git a/filesystem/VFileSystem009.cpp b/filesystem/VFileSystem009.cpp index 1dcde90e..f0ed6be1 100644 --- a/filesystem/VFileSystem009.cpp +++ b/filesystem/VFileSystem009.cpp @@ -470,11 +470,19 @@ 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 ); - Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", IdToDir( dir, sizeof( dir ), id ), path ); - CopyAndFixSlashes( fullpath, path, sizeof( fullpath )); + IdToDir( dir, sizeof( dir ), id ); + Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", dir, path ); + COM_FixSlashes( fullpath ); - return !!FS_AddPak_Fullpath( fullpath, nullptr, FS_CUSTOM_PATH ); + 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; } FileHandle_t OpenFromCacheForRead( const char *path , const char *mode, const char *id ) override diff --git a/filesystem/dir.c b/filesystem/dir.c index 910790dc..8e9c3b6f 100644 --- a/filesystem/dir.c +++ b/filesystem/dir.c @@ -480,29 +480,12 @@ void FS_InitDirectorySearchpath( searchpath_t *search, const char *path, int fla FS_PopulateDirEntries( search->dir, path ); } -searchpath_t *FS_AddDir_Fullpath( const char *path, qboolean *already_loaded, int flags ) +searchpath_t *FS_AddDir_Fullpath( const char *path, int flags ) { searchpath_t *search; - for( search = fs_searchpaths; search; search = search->next ) - { - if( search->type == SEARCHPATH_PLAIN && !Q_stricmp( search->filename, path )) - { - if( already_loaded ) - *already_loaded = true; - return search; - } - } - - if( already_loaded ) - *already_loaded = false; - search = (searchpath_t *)Mem_Calloc( fs_mempool, sizeof( searchpath_t )); FS_InitDirectorySearchpath( search, path, flags ); - - search->next = fs_searchpaths; - fs_searchpaths = search; - Con_Printf( "Adding directory: %s\n", path ); return search; diff --git a/filesystem/filesystem.c b/filesystem/filesystem.c index 9cabcdf7..6c292114 100644 --- a/filesystem/filesystem.c +++ b/filesystem/filesystem.c @@ -56,6 +56,23 @@ searchpath_t *fs_writepath; static char fs_basedir[MAX_SYSPATH]; // base game directory static char fs_gamedir[MAX_SYSPATH]; // game current directory +// 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[] = +{ +{ "pak", SEARCHPATH_PAK, FS_AddPak_Fullpath, true }, +{ "pk3", SEARCHPATH_ZIP, FS_AddZip_Fullpath, true }, +{ "wad", SEARCHPATH_WAD, FS_AddWad_Fullpath, false }, +{ NULL }, // end marker +}; + +// special fs_archive_t for plain directories +static const fs_archive_t g_directory_archive = +{ NULL, SEARCHPATH_PLAIN, FS_AddDir_Fullpath, false }; + +// static const fs_archive_t g_android_archive = +// { NULL, SEARCHPATH_ANDROID, FS_AddAndroid_Fullpath, false, false }; + #ifdef XASH_REDUCE_FD static file_t *fs_last_readfile; static zip_t *fs_last_zip; @@ -278,23 +295,69 @@ void FS_CreatePath( char *path ) } } +searchpath_t *FS_AddArchive_Fullpath( const fs_archive_t *archive, const char *file, int flags ) +{ + searchpath_t *search; + for( search = fs_searchpaths; search; search = search->next ) + { + if( search->type == archive->type && !Q_stricmp( search->filename, file )) + return search; // already loaded + } + + search = archive->pfnAddArchive_Fullpath( file, flags ); + + if( !search ) + return NULL; + + search->next = fs_searchpaths; + fs_searchpaths = search; + + // time to add in search list all the wads from this archive + if( archive->load_wads ) + { + stringlist_t list; + int i; + + stringlistinit( &list ); + search->pfnSearch( search, &list, "*.wad", true ); + stringlistsort( &list ); // keep always sorted + + for( i = 0; i < list.numstrings; i++ ) + { + searchpath_t *wad; + char fullpath[MAX_SYSPATH]; + + Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", file, list.strings[i] ); + if(( wad = FS_AddWad_Fullpath( fullpath, flags ))) + { + wad->next = fs_searchpaths; + fs_searchpaths = wad; + } + } + + stringlistfreecontents( &list ); + } + + return search; +} /* ================ FS_AddArchive_Fullpath ================ */ -static searchpath_t *FS_AddArchive_Fullpath( const char *file, qboolean *already_loaded, int flags ) +static searchpath_t *FS_AddExtras_Fullpath( const char *file, int flags ) { + const fs_archive_t *archive; const char *ext = COM_FileExtension( file ); - if( !Q_stricmp( ext, "pk3" )) - return FS_AddZip_Fullpath( file, already_loaded, flags ); - else if ( !Q_stricmp( ext, "pak" )) - return FS_AddPak_Fullpath( file, already_loaded, flags ); + for( archive = g_archives; archive->ext; archive++ ) + { + if( !Q_stricmp( ext, archive->ext )) + return FS_AddArchive_Fullpath( archive, file, flags ); + } - // skip wads, this function only meant to be used for extras return NULL; } @@ -308,6 +371,7 @@ 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]; @@ -317,48 +381,30 @@ void FS_AddGameDirectory( const char *dir, uint flags ) listdirectory( &list, dir ); stringlistsort( &list ); - // add archives in specific order PAK -> PK3 -> WAD - // so raw WADs takes precedence over WADs included into PAKs and PK3s - for( i = 0; i < list.numstrings; i++ ) + for( archive = g_archives; archive->ext; archive++ ) { - const char *ext = COM_FileExtension( list.strings[i] ); - - if( !Q_stricmp( ext, "pak" )) - { - Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", dir, list.strings[i] ); - FS_AddPak_Fullpath( fullpath, NULL, flags ); - } - } - - for( i = 0; i < list.numstrings; i++ ) - { - const char *ext = COM_FileExtension( list.strings[i] ); - - if( !Q_stricmp( ext, "pk3" )) - { - Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", dir, list.strings[i] ); - FS_AddZip_Fullpath( fullpath, NULL, flags ); - } - } - - for( i = 0; i < list.numstrings; i++ ) - { - const char *ext = COM_FileExtension( list.strings[i] ); - - if( !Q_stricmp( ext, "wad" )) - { + if( archive->type == SEARCHPATH_WAD ) // HACKHACK: wads need direct paths but only in this function FS_AllowDirectPaths( true ); + + for( i = 0; i < list.numstrings; i++ ) + { + const char *ext = COM_FileExtension( list.strings[i] ); + + if( Q_stricmp( ext, archive->ext )) + continue; + Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", dir, list.strings[i] ); - FS_AddWad_Fullpath( fullpath, NULL, flags ); - FS_AllowDirectPaths( false ); + FS_AddArchive_Fullpath( archive, fullpath, flags ); } + + FS_AllowDirectPaths( false ); } stringlistfreecontents( &list ); // add the directory to the search path // (unpacked files have the priority over packed files) - search = FS_AddDir_Fullpath( dir, NULL, flags ); + search = FS_AddArchive_Fullpath( &g_directory_archive, dir, flags ); if( !FBitSet( flags, FS_NOWRITE_PATH )) fs_writepath = search; } @@ -1108,25 +1154,13 @@ void FS_Rescan( void ) FS_ClearSearchPath(); -#if XASH_IOS - { - char buf[MAX_VA_STRING]; - - Q_snprintf( buf, sizeof( buf ), "%sextras.pak", SDL_GetBasePath() ); - FS_AddPak_Fullpath( buf, NULL, extrasFlags ); - Q_snprintf( buf, sizeof( buf ), "%sextras_%s.pak", SDL_GetBasePath(), GI->gamefolder ); - FS_AddPak_Fullpath( buf, NULL, extrasFlags ); - } -#else str = getenv( "XASH3D_EXTRAS_PAK1" ); if( COM_CheckString( str )) - FS_AddArchive_Fullpath( str, NULL, extrasFlags ); + FS_AddExtras_Fullpath( str, extrasFlags ); str = getenv( "XASH3D_EXTRAS_PAK2" ); if( COM_CheckString( str )) - FS_AddArchive_Fullpath( str, NULL, extrasFlags ); -#endif - + FS_AddExtras_Fullpath( str, extrasFlags ); if( Q_stricmp( GI->basedir, GI->gamefolder )) FS_AddGameHierarchy( GI->basedir, 0 ); diff --git a/filesystem/filesystem_internal.h b/filesystem/filesystem_internal.h index a09ef4e3..17c77dda 100644 --- a/filesystem/filesystem_internal.h +++ b/filesystem/filesystem_internal.h @@ -93,6 +93,16 @@ typedef struct searchpath_s byte *(*pfnLoadFile)( struct searchpath_s *search, const char *path, int pack_ind, fs_offset_t *filesize ); } searchpath_t; +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 +} fs_archive_t; + extern fs_globals_t FI; extern searchpath_t *fs_searchpaths; extern searchpath_t *fs_writepath; @@ -102,6 +112,7 @@ extern qboolean fs_ext_path; extern char fs_rodir[MAX_SYSPATH]; extern char fs_rootdir[MAX_SYSPATH]; extern fs_api_t g_api; +extern const fs_archive_t g_archives[]; #define GI FI.GameInfo @@ -123,6 +134,7 @@ extern fs_api_t g_api; // 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 ); // search path utils void FS_Rescan( void ); @@ -193,22 +205,22 @@ searchpath_t *FS_FindFile( const char *name, int *index, char *fixedname, size_t // // pak.c // -searchpath_t *FS_AddPak_Fullpath( const char *pakfile, qboolean *already_loaded, int flags ); +searchpath_t *FS_AddPak_Fullpath( const char *pakfile, int flags ); // // wad.c // -searchpath_t *FS_AddWad_Fullpath( const char *wadfile, qboolean *already_loaded, int flags ); +searchpath_t *FS_AddWad_Fullpath( const char *wadfile, int flags ); // // zip.c // -searchpath_t *FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int flags ); +searchpath_t *FS_AddZip_Fullpath( const char *zipfile, int flags ); // // dir.c // -searchpath_t *FS_AddDir_Fullpath( const char *path, qboolean *already_loaded, int flags ); +searchpath_t *FS_AddDir_Fullpath( const char *path, int flags ); qboolean FS_FixFileCase( dir_t *dir, const char *path, char *dst, const size_t len, qboolean createpath ); void FS_InitDirectorySearchpath( searchpath_t *search, const char *path, int flags ); diff --git a/filesystem/pak.c b/filesystem/pak.c index 2bf21a80..f7310a7b 100644 --- a/filesystem/pak.c +++ b/filesystem/pak.c @@ -330,66 +330,35 @@ If keep_plain_dirs is set, the pack will be added AFTER the first sequence of plain directories. ================ */ -searchpath_t *FS_AddPak_Fullpath( const char *pakfile, qboolean *already_loaded, int flags ) +searchpath_t *FS_AddPak_Fullpath( const char *pakfile, int flags ) { - searchpath_t *search; - pack_t *pak = NULL; - const char *ext = COM_FileExtension( pakfile ); - int i, errorcode = PAK_LOAD_COULDNT_OPEN; + searchpath_t *search; + pack_t *pak; + int i, errorcode = PAK_LOAD_COULDNT_OPEN; - for( search = fs_searchpaths; search; search = search->next ) - { - if( search->type == SEARCHPATH_PAK && !Q_stricmp( search->filename, pakfile )) - { - if( already_loaded ) *already_loaded = true; - return search; // already loaded - } - } + pak = FS_LoadPackPAK( pakfile, &errorcode ); - if( already_loaded ) - *already_loaded = false; - - if( !Q_stricmp( ext, "pak" )) - pak = FS_LoadPackPAK( pakfile, &errorcode ); - - if( pak ) - { - search = (searchpath_t *)Mem_Calloc( fs_mempool, sizeof( searchpath_t )); - Q_strncpy( search->filename, pakfile, sizeof( search->filename )); - search->pack = pak; - search->type = SEARCHPATH_PAK; - search->next = fs_searchpaths; - search->flags = flags; - - search->pfnPrintInfo = FS_PrintInfo_PAK; - search->pfnClose = FS_Close_PAK; - search->pfnOpenFile = FS_OpenFile_PAK; - search->pfnFileTime = FS_FileTime_PAK; - search->pfnFindFile = FS_FindFile_PAK; - search->pfnSearch = FS_Search_PAK; - - fs_searchpaths = search; - - Con_Reportf( "Adding pakfile: %s (%i files)\n", pakfile, pak->numfiles ); - - // time to add in search list all the wads that contains in current pakfile (if do) - for( i = 0; i < pak->numfiles; i++ ) - { - if( !Q_stricmp( COM_FileExtension( pak->files[i].name ), "wad" )) - { - char fullpath[MAX_SYSPATH]; - - Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", pakfile, pak->files[i].name ); - FS_AddWad_Fullpath( fullpath, NULL, flags ); - } - } - - return search; - } - else + if( !pak ) { if( errorcode != PAK_LOAD_NO_FILES ) Con_Reportf( S_ERROR "FS_AddPak_Fullpath: unable to load pak \"%s\"\n", pakfile ); return NULL; } + + search = (searchpath_t *)Mem_Calloc( fs_mempool, sizeof( searchpath_t )); + Q_strncpy( search->filename, pakfile, sizeof( search->filename )); + search->pack = pak; + search->type = SEARCHPATH_PAK; + search->flags = flags; + + search->pfnPrintInfo = FS_PrintInfo_PAK; + search->pfnClose = FS_Close_PAK; + search->pfnOpenFile = FS_OpenFile_PAK; + search->pfnFileTime = FS_FileTime_PAK; + search->pfnFindFile = FS_FindFile_PAK; + search->pfnSearch = FS_Search_PAK; + + Con_Reportf( "Adding pakfile: %s (%i files)\n", pakfile, pak->numfiles ); + + return search; } diff --git a/filesystem/wad.c b/filesystem/wad.c index 04ae1d10..b11d3f49 100644 --- a/filesystem/wad.c +++ b/filesystem/wad.c @@ -635,52 +635,35 @@ static byte *W_ReadLump( searchpath_t *search, const char *path, int pack_ind, f FS_AddWad_Fullpath ==================== */ -searchpath_t *FS_AddWad_Fullpath( const char *wadfile, qboolean *already_loaded, int flags ) +searchpath_t *FS_AddWad_Fullpath( const char *wadfile, int flags ) { - searchpath_t *search; - wfile_t *wad = NULL; - const char *ext = COM_FileExtension( wadfile ); - int errorcode = WAD_LOAD_COULDNT_OPEN; + searchpath_t *search; + wfile_t *wad; + int errorcode = WAD_LOAD_COULDNT_OPEN; - for( search = fs_searchpaths; search; search = search->next ) + wad = W_Open( wadfile, &errorcode ); + + if( !wad ) { - if( search->type == SEARCHPATH_WAD && !Q_stricmp( search->filename, wadfile )) - { - if( already_loaded ) *already_loaded = true; - return search; // already loaded - } + if( errorcode != WAD_LOAD_NO_FILES ) + Con_Reportf( S_ERROR "FS_AddWad_Fullpath: unable to load wad \"%s\"\n", wadfile ); + return NULL; } - if( already_loaded ) - *already_loaded = false; + search = (searchpath_t *)Mem_Calloc( fs_mempool, sizeof( searchpath_t )); + Q_strncpy( search->filename, wadfile, sizeof( search->filename )); + search->wad = wad; + search->type = SEARCHPATH_WAD; + search->flags = flags; - if( !Q_stricmp( ext, "wad" )) - wad = W_Open( wadfile, &errorcode ); + search->pfnPrintInfo = FS_PrintInfo_WAD; + search->pfnClose = FS_Close_WAD; + search->pfnOpenFile = FS_OpenFile_WAD; + search->pfnFileTime = FS_FileTime_WAD; + search->pfnFindFile = FS_FindFile_WAD; + search->pfnSearch = FS_Search_WAD; + search->pfnLoadFile = W_ReadLump; - if( wad ) - { - search = (searchpath_t *)Mem_Calloc( fs_mempool, sizeof( searchpath_t )); - Q_strncpy( search->filename, wadfile, sizeof( search->filename )); - search->wad = wad; - search->type = SEARCHPATH_WAD; - search->next = fs_searchpaths; - search->flags = flags; - - search->pfnPrintInfo = FS_PrintInfo_WAD; - search->pfnClose = FS_Close_WAD; - search->pfnOpenFile = FS_OpenFile_WAD; - search->pfnFileTime = FS_FileTime_WAD; - search->pfnFindFile = FS_FindFile_WAD; - search->pfnSearch = FS_Search_WAD; - search->pfnLoadFile = W_ReadLump; - - fs_searchpaths = search; - - Con_Reportf( "Adding wadfile: %s (%i files)\n", wadfile, wad->numlumps ); - return search; - } - - if( errorcode != WAD_LOAD_NO_FILES ) - Con_Reportf( S_ERROR "FS_AddWad_Fullpath: unable to load wad \"%s\"\n", wadfile ); - return NULL; + Con_Reportf( "Adding wadfile: %s (%i files)\n", wadfile, wad->numlumps ); + return search; } diff --git a/filesystem/zip.c b/filesystem/zip.c index 1ec8a7a2..856c0e74 100644 --- a/filesystem/zip.c +++ b/filesystem/zip.c @@ -664,68 +664,36 @@ FS_AddZip_Fullpath =========== */ -searchpath_t *FS_AddZip_Fullpath( const char *zipfile, qboolean *already_loaded, int flags ) +searchpath_t *FS_AddZip_Fullpath( const char *zipfile, int flags ) { - searchpath_t *search; - zip_t *zip = NULL; - const char *ext = COM_FileExtension( zipfile ); - int errorcode = ZIP_LOAD_COULDNT_OPEN; + searchpath_t *search; + zip_t *zip; + int i, errorcode = ZIP_LOAD_COULDNT_OPEN; - for( search = fs_searchpaths; search; search = search->next ) - { - if( search->type == SEARCHPATH_ZIP && !Q_stricmp( search->filename, zipfile )) - { - if( already_loaded ) *already_loaded = true; - return search; // already loaded - } - } + zip = FS_LoadZip( zipfile, &errorcode ); - if( already_loaded ) *already_loaded = false; - - if( !Q_stricmp( ext, "pk3" ) ) - zip = FS_LoadZip( zipfile, &errorcode ); - - if( zip ) - { - string fullpath; - int i; - - search = (searchpath_t *)Mem_Calloc( fs_mempool, sizeof( searchpath_t ) ); - Q_strncpy( search->filename, zipfile, sizeof( search->filename )); - search->zip = zip; - search->type = SEARCHPATH_ZIP; - search->next = fs_searchpaths; - search->flags = flags; - - search->pfnPrintInfo = FS_PrintInfo_ZIP; - search->pfnClose = FS_Close_ZIP; - search->pfnOpenFile = FS_OpenFile_ZIP; - search->pfnFileTime = FS_FileTime_ZIP; - search->pfnFindFile = FS_FindFile_ZIP; - search->pfnSearch = FS_Search_ZIP; - search->pfnLoadFile = FS_LoadZIPFile; - - fs_searchpaths = search; - - Con_Reportf( "Adding zipfile: %s (%i files)\n", zipfile, zip->numfiles ); - - // time to add in search list all the wads that contains in current pakfile (if do) - for( i = 0; i < zip->numfiles; i++ ) - { - if( !Q_stricmp( COM_FileExtension( zip->files[i].name ), "wad" )) - { - Q_snprintf( fullpath, MAX_STRING, "%s/%s", zipfile, zip->files[i].name ); - FS_AddWad_Fullpath( fullpath, NULL, flags ); - } - } - - return search; - } - else + if( !zip ) { if( errorcode != ZIP_LOAD_NO_FILES ) Con_Reportf( S_ERROR "FS_AddZip_Fullpath: unable to load zip \"%s\"\n", zipfile ); return NULL; } + + search = (searchpath_t *)Mem_Calloc( fs_mempool, sizeof( searchpath_t ) ); + Q_strncpy( search->filename, zipfile, sizeof( search->filename )); + search->zip = zip; + search->type = SEARCHPATH_ZIP; + search->flags = flags; + + search->pfnPrintInfo = FS_PrintInfo_ZIP; + search->pfnClose = FS_Close_ZIP; + search->pfnOpenFile = FS_OpenFile_ZIP; + search->pfnFileTime = FS_FileTime_ZIP; + search->pfnFindFile = FS_FindFile_ZIP; + search->pfnSearch = FS_Search_ZIP; + search->pfnLoadFile = FS_LoadZIPFile; + + Con_Reportf( "Adding zipfile: %s (%i files)\n", zipfile, zip->numfiles ); + return search; }