- moved file lookup functions to utilities and matched to GZDoom's version.

This commit is contained in:
Christoph Oelckers 2020-04-12 00:07:52 +02:00
parent a60a0eeefa
commit 2883553ed2
7 changed files with 288 additions and 268 deletions

View file

@ -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<FString> 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))
{

View file

@ -34,10 +34,13 @@
#include "findfile.h"
#include "zstring.h"
#include "cmdlib.h"
#include "printf.h"
#include "configfile.h"
#ifndef _WIN32
#include <unistd.h>
#include <fnmatch.h>
static const char *pattern;
@ -128,7 +131,8 @@ int I_FindAttr(findstate_t *const fileinfo)
#else
#include <windows.h>
#include <direct.h>
//==========================================================================
//
// I_FindFirst
@ -187,4 +191,241 @@ const char *I_FindName(findstate_t *fileinfo)
return fileinfo->UTF8Name.GetChars();
}
#endif
#endif
//==========================================================================
//
// D_AddFile
//
//==========================================================================
bool D_AddFile(TArray<FString>& 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<FString>& 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<FString>& 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<FString>& 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 <file>, 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;
}

View file

@ -4,6 +4,11 @@
#include <stdint.h>
#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<FString>& wadfiles, const char* file, bool check, int position, FConfigFile* config);
void D_AddWildFile(TArray<FString>& wadfiles, const char* value, const char *extension, FConfigFile* config);
void D_AddConfigFiles(TArray<FString>& wadfiles, const char* section, const char* extension, FConfigFile* config);
void D_AddDirectory(TArray<FString>& wadfiles, const char* dir, const char *filespec, FConfigFile* config);
const char* BaseFileSearch(const char* file, const char* ext, bool lookfirstinprogdir, FConfigFile* config);

View file

@ -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<FString>& wadfiles, const char* file, bool check = true, int position = -1);
// MACROS ------------------------------------------------------------------
@ -1027,11 +1027,11 @@ void FExecList::ExecCommands() const
}
}
void FExecList::AddPullins(TArray<FString> &wads) const
void FExecList::AddPullins(TArray<FString> &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);
}
}

View file

@ -52,7 +52,7 @@ struct FExecList
void AddCommand(const char *cmd, const char *file = nullptr);
void ExecCommands() const;
void AddPullins(TArray<FString> &wads) const;
void AddPullins(TArray<FString> &wads, FConfigFile *config) const;
};
extern bool ParsingKeyConf, UnsafeExecutionContext;

View file

@ -18,8 +18,6 @@ extern FMemArena dump; // this is for memory blocks than cannot be deallocated w
extern TMap<FName, int32_t> NameToTileIndex;
void D_AddWildFile(TArray<FString>& wadfiles, const char* value);
int CONFIG_Init();
void CONFIG_SetDefaultKeys(const char *defbinds);

View file

@ -51,247 +51,7 @@
#define PATH_MAX 260
#endif
//==========================================================================
//
// BaseFileSearch
//
// If a file does not exist at <file>, 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<FString> &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<FString> &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<FString> &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<FString> &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<FString>& 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<GrpEntry>& 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<GrpEntry>& 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<GrpEntry>& 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<GrpEntry>& 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<GrpEntry>& 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<GrpEntry>& 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);
}
}