From 2883553ed25c19fb5728ea445f15791c2bcf8d85 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Apr 2020 00:07:52 +0200 Subject: [PATCH] - moved file lookup functions to utilities and matched to GZDoom's version. --- source/blood/src/demo.cpp | 8 +- source/common/utility/findfile.cpp | 247 +++++++++++++++++++++++++- source/common/utility/findfile.h | 15 +- source/core/console/c_dispatch.cpp | 6 +- source/core/console/c_dispatch.h | 2 +- source/core/gamecontrol.h | 2 - source/core/initfs.cpp | 276 +++-------------------------- 7 files changed, 288 insertions(+), 268 deletions(-) diff --git a/source/blood/src/demo.cpp b/source/blood/src/demo.cpp index a769e05f3..4c77c0419 100644 --- a/source/blood/src/demo.cpp +++ b/source/blood/src/demo.cpp @@ -45,6 +45,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "view.h" #include "gamecontrol.h" #include "menu/menu.h" +#include "gameconfigfile.h" +#include "findfile.h" BEGIN_BLD_NS @@ -411,7 +413,7 @@ void CDemo::LoadDemoInfo(void) char zFN[BMAX_PATH]; snprintf(zFN, BMAX_PATH, "%s%s*.dem", G_GetDemoPath().GetChars(), BloodIniPre); TArray demos; - D_AddWildFile(demos, zFN); + D_AddWildFile(demos, zFN, ".dem", GameConfig); FStringf ini("%s.ini", BloodIniPre); int lump = fileSystem.FindFile(ini); @@ -419,7 +421,7 @@ void CDemo::LoadDemoInfo(void) { auto path = fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(lump)); ini.Format("%s*.dem", path); - D_AddWildFile(demos, ini); + D_AddWildFile(demos, ini, ".dem", GameConfig); } for (auto &filename : demos) @@ -431,7 +433,7 @@ void CDemo::LoadDemoInfo(void) #if B_BIG_ENDIAN == 1 atf.signature = B_LITTLE32(atf.signature); atf.nVersion = B_LITTLE16(atf.nVersion); -#endif +#endif, "." if ((atf.signature == 0x1a4d4544 /* '\x1aMED' */&& atf.nVersion == BloodVersion) || (atf.signature == 0x1a4d4445 /* '\x1aMDE' */ && atf.nVersion == BYTEVERSION)) { diff --git a/source/common/utility/findfile.cpp b/source/common/utility/findfile.cpp index 9f581c25b..1adf08896 100644 --- a/source/common/utility/findfile.cpp +++ b/source/common/utility/findfile.cpp @@ -34,10 +34,13 @@ #include "findfile.h" #include "zstring.h" - +#include "cmdlib.h" +#include "printf.h" +#include "configfile.h" #ifndef _WIN32 +#include #include static const char *pattern; @@ -128,7 +131,8 @@ int I_FindAttr(findstate_t *const fileinfo) #else #include - +#include + //========================================================================== // // I_FindFirst @@ -187,4 +191,241 @@ const char *I_FindName(findstate_t *fileinfo) return fileinfo->UTF8Name.GetChars(); } -#endif \ No newline at end of file +#endif + +//========================================================================== +// +// D_AddFile +// +//========================================================================== + +bool D_AddFile(TArray& wadfiles, const char* file, bool check, int position, FConfigFile* config) +{ + if (file == nullptr || *file == '\0') + { + return false; + } + + if (check && !DirEntryExists(file)) + { + const char* f = BaseFileSearch(file, ".wad", false, config); + if (f == nullptr) + { + Printf("Can't find '%s'\n", file); + return false; + } + file = f; + } + + FString f = file; + FixPathSeperator(f); + if (position == -1) wadfiles.Push(f); + else wadfiles.Insert(position, f); + return true; +} + +//========================================================================== +// +// D_AddWildFile +// +//========================================================================== + +void D_AddWildFile(TArray& wadfiles, const char* value, const char *extension, FConfigFile* config) +{ + if (value == nullptr || *value == '\0') + { + return; + } + const char* wadfile = BaseFileSearch(value, extension, false, config); + + if (wadfile != nullptr) + { + D_AddFile(wadfiles, wadfile, true, -1, config); + } + else + { // Try pattern matching + findstate_t findstate; + char path[ZPATH_MAX]; + char* sep; + void* handle = I_FindFirst(value, &findstate); + + strcpy(path, value); + sep = strrchr(path, '/'); + if (sep == nullptr) + { + sep = strrchr(path, '\\'); +#ifdef _WIN32 + if (sep == nullptr && path[1] == ':') + { + sep = path + 1; + } +#endif + } + + if (handle != ((void*)-1)) + { + do + { + if (!(I_FindAttr(&findstate) & FA_DIREC)) + { + if (sep == nullptr) + { + D_AddFile(wadfiles, I_FindName(&findstate), true, -1, config); + } + else + { + strcpy(sep + 1, I_FindName(&findstate)); + D_AddFile(wadfiles, path, true, -1, config); + } + } + } while (I_FindNext(handle, &findstate) == 0); + } + I_FindClose(handle); + } +} + +//========================================================================== +// +// D_AddConfigWads +// +// Adds all files in the specified config file section. +// +//========================================================================== + +void D_AddConfigFiles(TArray& wadfiles, const char* section, const char* extension, FConfigFile *config) +{ + if (config && config->SetSection(section)) + { + const char* key; + const char* value; + FConfigFile::Position pos; + + while (config->NextInSection(key, value)) + { + if (stricmp(key, "Path") == 0) + { + // D_AddWildFile resets config's position, so remember it + config->GetPosition(pos); + D_AddWildFile(wadfiles, ExpandEnvVars(value), extension, config); + // Reset config's position to get next wad + config->SetPosition(pos); + } + } + } +} + +//========================================================================== +// +// D_AddDirectory +// +// Add all .wad files in a directory. Does not descend into subdirectories. +// +//========================================================================== + +void D_AddDirectory(TArray& wadfiles, const char* dir, const char *filespec, FConfigFile* config) +{ + char curdir[ZPATH_MAX]; + + if (getcwd(curdir, ZPATH_MAX)) + { + char skindir[ZPATH_MAX]; + findstate_t findstate; + void* handle; + size_t stuffstart; + + stuffstart = strlen(dir); + memcpy(skindir, dir, stuffstart * sizeof(*dir)); + skindir[stuffstart] = 0; + + if (skindir[stuffstart - 1] == '/') + { + skindir[--stuffstart] = 0; + } + + if (!chdir(skindir)) + { + skindir[stuffstart++] = '/'; + if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1) + { + do + { + if (!(I_FindAttr(&findstate) & FA_DIREC)) + { + strcpy(skindir + stuffstart, I_FindName(&findstate)); + D_AddFile(wadfiles, skindir, true, -1, config); + } + } while (I_FindNext(handle, &findstate) == 0); + I_FindClose(handle); + } + } + chdir(curdir); + } +} + +//========================================================================== +// +// BaseFileSearch +// +// If a file does not exist at , looks for it in the directories +// specified in the config file. Returns the path to the file, if found, +// or nullptr if it could not be found. +// +//========================================================================== + +const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinprogdir, FConfigFile* config) +{ + static char wad[ZPATH_MAX]; + + if (file == nullptr || *file == '\0') + { + return nullptr; + } + if (lookfirstinprogdir) + { + mysnprintf(wad, countof(wad), "%s%s%s", progdir.GetChars(), progdir.Back() == '/' ? "" : "/", file); + if (DirEntryExists(wad)) + { + return wad; + } + } + + if (DirEntryExists(file)) + { + mysnprintf(wad, countof(wad), "%s", file); + return wad; + } + + if (config != nullptr && config->SetSection("FileSearch.Directories")) + { + const char* key; + const char* value; + + while (config->NextInSection(key, value)) + { + if (stricmp(key, "Path") == 0) + { + FString dir; + + dir = NicePath(value); + if (dir.IsNotEmpty()) + { + mysnprintf(wad, countof(wad), "%s%s%s", dir.GetChars(), dir.Back() == '/' ? "" : "/", file); + if (DirEntryExists(wad)) + { + return wad; + } + } + } + } + } + + // Retry, this time with a default extension + if (ext != nullptr) + { + FString tmp = file; + DefaultExtension(tmp, ext); + return BaseFileSearch(tmp, nullptr, lookfirstinprogdir, config); + } + return nullptr; +} + diff --git a/source/common/utility/findfile.h b/source/common/utility/findfile.h index 65f121ef5..f4984a894 100644 --- a/source/common/utility/findfile.h +++ b/source/common/utility/findfile.h @@ -4,6 +4,11 @@ #include #include "zstring.h" +enum +{ + ZPATH_MAX = 260 +}; + #ifndef _WIN32 @@ -53,7 +58,7 @@ private: FileTime Times[3]; uint32_t Size[2]; uint32_t Reserved[2]; - wchar_t Name[260]; + wchar_t Name[ZPATH_MAX]; wchar_t AltName[14]; }; WinData FindData; @@ -83,3 +88,11 @@ inline int I_FindAttr(findstate_t *fileinfo) void *I_FindFirst (const char *filespec, findstate_t *fileinfo); int I_FindNext (void *handle, findstate_t *fileinfo); int I_FindClose (void *handle); + +class FConfigFile; + +bool D_AddFile(TArray& wadfiles, const char* file, bool check, int position, FConfigFile* config); +void D_AddWildFile(TArray& wadfiles, const char* value, const char *extension, FConfigFile* config); +void D_AddConfigFiles(TArray& wadfiles, const char* section, const char* extension, FConfigFile* config); +void D_AddDirectory(TArray& wadfiles, const char* dir, const char *filespec, FConfigFile* config); +const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinprogdir, FConfigFile* config); diff --git a/source/core/console/c_dispatch.cpp b/source/core/console/c_dispatch.cpp index fc10898f2..4ce262253 100644 --- a/source/core/console/c_dispatch.cpp +++ b/source/core/console/c_dispatch.cpp @@ -49,9 +49,9 @@ #include "printf.h" #include "c_cvars.h" #include "c_buttons.h" +#include "findfile.h" // Todo: Get rid of #include "inputstate.h" -bool D_AddFile(TArray& wadfiles, const char* file, bool check = true, int position = -1); // MACROS ------------------------------------------------------------------ @@ -1027,11 +1027,11 @@ void FExecList::ExecCommands() const } } -void FExecList::AddPullins(TArray &wads) const +void FExecList::AddPullins(TArray &wads, FConfigFile *config) const { for (unsigned i = 0; i < Pullins.Size(); ++i) { - D_AddFile(wads, Pullins[i]); + D_AddFile(wads, Pullins[i], true, -1, config); } } diff --git a/source/core/console/c_dispatch.h b/source/core/console/c_dispatch.h index b1f5e6564..b381b6884 100644 --- a/source/core/console/c_dispatch.h +++ b/source/core/console/c_dispatch.h @@ -52,7 +52,7 @@ struct FExecList void AddCommand(const char *cmd, const char *file = nullptr); void ExecCommands() const; - void AddPullins(TArray &wads) const; + void AddPullins(TArray &wads, FConfigFile *config) const; }; extern bool ParsingKeyConf, UnsafeExecutionContext; diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 402d83a6d..0131034eb 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -18,8 +18,6 @@ extern FMemArena dump; // this is for memory blocks than cannot be deallocated w extern TMap NameToTileIndex; -void D_AddWildFile(TArray& wadfiles, const char* value); - int CONFIG_Init(); void CONFIG_SetDefaultKeys(const char *defbinds); diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index d8a07d144..6de69d937 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -51,247 +51,7 @@ #define PATH_MAX 260 #endif -//========================================================================== -// -// BaseFileSearch -// -// If a file does not exist at , looks for it in the directories -// specified in the config file. Returns the path to the file, if found, -// or nullptr if it could not be found. -// -//========================================================================== - -FString BaseFileSearch (const char *file, const char *ext, bool lookfirstinprogdir) -{ - FString wad; - - if (file == nullptr || *file == '\0') - { - return nullptr; - } - if (lookfirstinprogdir) - { - wad.Format("%s%s%s", progdir.GetChars(), progdir.Back() == '/' ? "" : "/", file); - if (DirEntryExists (wad)) - { - return wad; - } - } - - if (DirEntryExists (file)) - { - wad.Format("%s", file); - return wad; - } - - if (GameConfig != nullptr && GameConfig->SetSection ("FileSearch.Directories")) - { - const char *key; - const char *value; - - while (GameConfig->NextInSection (key, value)) - { - if (stricmp (key, "Path") == 0) - { - FString dir; - - dir = NicePath(value); - if (dir.IsNotEmpty()) - { - wad.Format("%s%s%s", dir.GetChars(), dir.Back() == '/' ? "" : "/", file); - if (DirEntryExists (wad)) - { - return wad; - } - } - } - } - } - - // Retry, this time with a default extension - if (ext != nullptr) - { - FString tmp = file; - DefaultExtension (tmp, ext); - return BaseFileSearch (tmp, nullptr, lookfirstinprogdir); - } - return nullptr; -} - -//========================================================================== -// -// D_AddFile -// -//========================================================================== - -bool D_AddFile (TArray &wadfiles, const char *file, bool check = true, int position = -1) -{ - if (file == NULL || *file == '\0') - { - return false; - } - - if (check && !DirEntryExists (file)) - { - const char *f = BaseFileSearch (file, ".grp", false); - if (f == NULL) - { - Printf ("Can't find '%s'\n", file); - return false; - } - file = f; - } - - FString f = file; - f.Substitute("\\", "/"); - if (position == -1) wadfiles.Push(f); - else wadfiles.Insert(position, f); - return true; -} - - //========================================================================== -// -// D_AddWildFile -// -//========================================================================== - -void D_AddWildFile (TArray &wadfiles, const char *value) -{ - if (value == NULL || *value == '\0') - { - return; - } - FString wadfile = BaseFileSearch (value, ".wad", false); - - if (wadfile.Len() != 0) - { - D_AddFile (wadfiles, wadfile); - } - else - { // Try pattern matching - findstate_t findstate; - char path[260]; - char *sep; - void *handle = I_FindFirst (value, &findstate); - - strcpy (path, value); - sep = strrchr (path, '/'); - if (sep == NULL) - { - sep = strrchr (path, '\\'); -#ifdef _WIN32 - if (sep == NULL && path[1] == ':') - { - sep = path + 1; - } -#endif - } - - if (handle != ((void *)-1)) - { - do - { - if (!(I_FindAttr(&findstate) & FA_DIREC)) - { - if (sep == NULL) - { - D_AddFile (wadfiles, I_FindName (&findstate)); - } - else - { - strcpy (sep+1, I_FindName (&findstate)); - D_AddFile (wadfiles, path, false ); - } - } - } while (I_FindNext (handle, &findstate) == 0); - } - I_FindClose (handle); - } -} - -//========================================================================== -// -// D_AddConfigWads -// -// Adds all files in the specified config file section. -// -//========================================================================== - -void D_AddConfigWads (TArray &wadfiles, const char *section) -{ - if (GameConfig->SetSection (section)) - { - const char *key; - const char *value; - FConfigFile::Position pos; - - while (GameConfig->NextInSection (key, value)) - { - if (stricmp (key, "Path") == 0) - { - // D_AddWildFile resets GameConfig's position, so remember it - GameConfig->GetPosition (pos); - D_AddWildFile (wadfiles, ExpandEnvVars(value)); - // Reset GameConfig's position to get next wad - GameConfig->SetPosition (pos); - } - } - } -} - - //========================================================================== -// -// D_AddDirectory -// -// Add all .wad files in a directory. Does not descend into subdirectories. -// -//========================================================================== - -static void D_AddDirectory (TArray &wadfiles, const char *dir) -{ - char curdir[PATH_MAX]; - - if (getcwd (curdir, PATH_MAX)) - { - char skindir[PATH_MAX]; - findstate_t findstate; - void *handle; - size_t stuffstart; - - stuffstart = strlen (dir); - memcpy (skindir, dir, stuffstart*sizeof(*dir)); - skindir[stuffstart] = 0; - - if (skindir[stuffstart-1] == '/') - { - skindir[--stuffstart] = 0; - } - - if (!chdir (skindir)) - { - skindir[stuffstart++] = '/'; - int savedstart = stuffstart; - static const char* validexts[] = { "*.grp", "*.zip", "*.pk3", "*.pk4", "*.7z", "*.pk7", "*.dat", "*.rff" }; - for (auto ext : validexts) - { - stuffstart = savedstart; - if ((handle = I_FindFirst(ext, &findstate)) != (void*)-1) - { - do - { - if (!(I_FindAttr(&findstate) & FA_DIREC)) - { - strcpy(skindir + stuffstart, I_FindName(&findstate)); - D_AddFile(wadfiles, skindir); - } - } while (I_FindNext(handle, &findstate) == 0); - I_FindClose(handle); - } - } - } - chdir (curdir); - } -} +static const char* validexts[] = { "*.grp", "*.zip", "*.pk3", "*.pk4", "*.7z", "*.pk7", "*.dat", "*.rff" }; //========================================================================== // @@ -340,11 +100,11 @@ static FString ParseGameInfo(TArray& pwads, const char* fn, const char* } if (!FileExists(checkpath)) { - pos += D_AddFile(pwads, sc.String, true, pos); + pos += D_AddFile(pwads, sc.String, true, pos, GameConfig); } else { - pos += D_AddFile(pwads, checkpath, true, pos); + pos += D_AddFile(pwads, checkpath, true, pos, GameConfig); } } while (sc.CheckToken(',')); } @@ -446,13 +206,13 @@ FString GetGameFronUserFiles() if (userConfig.AddFilesPre) for (auto& file : *userConfig.AddFilesPre) { - D_AddFile(Files, file); + D_AddFile(Files, file, true, -1, GameConfig); } if (userConfig.AddFiles) { for (auto& file : *userConfig.AddFiles) { - D_AddFile(Files, file); + D_AddFile(Files, file, true, -1, GameConfig); } // Finally, if the last entry in the chain is a directory, it's being considered the mod directory, and all GRPs inside need to be loaded, too. @@ -465,7 +225,10 @@ FString GetGameFronUserFiles() // Insert the GRPs before this entry itself. FString lastfn; Files.Pop(lastfn); - D_AddDirectory(Files, fn); + for (auto ext : validexts) + { + D_AddDirectory(Files, fn, ext, GameConfig); + } Files.Push(lastfn); } } @@ -518,7 +281,7 @@ void InitFileSystem(TArray& groups) // First comes the engine's own stuff. FString baseres = progdir + ENGINERES_FILE; - D_AddFile(Files, baseres); + D_AddFile(Files, baseres, true, -1, GameConfig); bool insertdirectoriesafter = Args->CheckParm("-insertdirafter"); @@ -532,7 +295,7 @@ void InitFileSystem(TArray& groups) // This can be overridden via command line switch if needed. if (!grp.FileInfo.loaddirectory && grp.FileName.IsNotEmpty()) { - D_AddFile(Files, grp.FileName); + D_AddFile(Files, grp.FileName, true, -1, GameConfig); fn = ExtractFilePath(grp.FileName); if (fn.Len() > 0 && fn.Back() != '/') fn += '/'; } @@ -540,7 +303,7 @@ void InitFileSystem(TArray& groups) for (auto& fname : grp.FileInfo.loadfiles) { FString newname = fn + fname; - D_AddFile(Files, newname); + D_AddFile(Files, newname, true, -1, GameConfig); } bool insert = (!insertdirectoriesafter && &grp == &groups[0]) || (insertdirectoriesafter && &grp == &groups.Last()); @@ -551,10 +314,10 @@ void InitFileSystem(TArray& groups) // Do this only if explicitly requested because this severely limits the usability of GRP files. if (insertdirectoriesafter && userConfig.AddFilesPre) for (auto& file : *userConfig.AddFilesPre) { - D_AddFile(Files, '*' + file); // The * tells the file system not to pull in all subdirectories. + D_AddFile(Files, file, true, -1, GameConfig); } - D_AddFile(Files, fn); + D_AddFile(Files, fn, true, -1, GameConfig); } i--; } @@ -568,20 +331,20 @@ void InitFileSystem(TArray& groups) if (stricmp(key, "Path") == 0) { FString nice = NicePath(value); - D_AddFile(Files, nice); + D_AddFile(Files, nice, true, -1, GameConfig); } } } if (!insertdirectoriesafter && userConfig.AddFilesPre) for (auto& file : *userConfig.AddFilesPre) { - D_AddFile(Files, file); + D_AddFile(Files, file, true, -1, GameConfig); } if (userConfig.AddFiles) { for (auto& file : *userConfig.AddFiles) { - D_AddFile(Files, file); + D_AddFile(Files, file, true, -1, GameConfig); } // Finally, if the last entry in the chain is a directory, it's being considered the mod directory, and all GRPs inside need to be loaded, too. @@ -594,7 +357,10 @@ void InitFileSystem(TArray& groups) // Insert the GRPs before this entry itself. FString lastfn; Files.Pop(lastfn); - D_AddDirectory(Files, fn); + for (auto ext : validexts) + { + D_AddDirectory(Files, fn, ext, GameConfig); + } Files.Push(lastfn); } }