From b119341948c0800dcbec346ea7c6355013183e38 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 25 Aug 2025 18:36:01 +0100 Subject: [PATCH 1/7] G_SetGameModified exists for this very purpose, use the srb2kart/rr function signature version instead of direct write to modifiedgame --- src/w_wad.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 7e359c362..293c1e3f3 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -959,8 +959,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, const if (important && !mainfile) { - //G_SetGameModified(true); - modifiedgame = true; // avoid savemoddata being set to false + G_SetGameModified(true, false); } // From 4d6fe8f23399558735abc9afc0788101653114c3 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 25 Aug 2025 19:51:48 +0100 Subject: [PATCH 2/7] W_VerifyNMUSlumps: Clean up - Bake W_VerifyFile in, since it was a stub never called anywhere else - Make it operate off file handles, since the following locations quickly filesearch'd more than once in quick succession. - W_InitFile - Command_Addfile - Remove spurious call from W_InitMultipleFiles for `-file` startup param --- src/d_main.cpp | 34 ++++++++++++++---------- src/d_netcmd.c | 70 +++++++++++++++++++++++++++----------------------- src/w_wad.cpp | 51 ++++++++++++------------------------ src/w_wad.h | 2 +- 4 files changed, 77 insertions(+), 80 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 98190cacf..2eba82a6d 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1433,21 +1433,29 @@ static void IdentifyVersion(void) #endif #define MUSICTEST(str) \ - {\ - const char *musicpath = va(spandf,srb2waddir,"data",str);\ - int ms = W_VerifyNMUSlumps(musicpath, false); \ - if (ms == 1) \ + musicpath = va(spandf,srb2waddir,"data",str);\ + handle = W_OpenWadFile(&musicpath, false); \ + if (handle) \ { \ - D_AddFile(startupiwads, num_startupiwads++, musicpath, NULL); \ - musicwads++; \ - } \ - else if (ms == 0) \ - I_Error("File " str " has been modified with non-music/sound lumps"); \ - } + int ms = W_VerifyNMUSlumps(musicpath, handle, false); \ + fclose(handle); \ + if (ms == 0) \ + I_Error("File " str " has been modified with non-music/sound lumps"); \ + if (ms == 1) \ + { \ + D_AddFile(startupiwads, num_startupiwads++, musicpath, NULL); \ + musicwads++; \ + } \ + } - MUSICTEST("sounds.pk3") - MUSICTEST("music.pk3") - MUSICTEST("altmusic.pk3") + { + const char *musicpath; + FILE *handle; + + MUSICTEST("sounds.pk3") + MUSICTEST("music.pk3") + MUSICTEST("altmusic.pk3") + } #undef MUSICTEST } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 026189ad9..58bee1b6a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4352,6 +4352,8 @@ static void Command_Addfile(void) const char **addedfiles = Z_Calloc(sizeof(const char*) * argc, PU_STATIC, NULL); size_t numfilesadded = 0; // the amount of filenames processed + FILE *fhandle = NULL; + // start at one to skip command name for (curarg = 1; curarg < argc; curarg++) { @@ -4360,24 +4362,22 @@ static void Command_Addfile(void) char *buf_p = buf; INT32 i; size_t ii; - int musiconly; // W_VerifyNMUSlumps isn't boolean - boolean fileadded = false; + int musiconly = -1; // W_VerifyNMUSlumps isn't boolean fn = COM_Argv(curarg); // For the amount of filenames previously processed... for (ii = 0; ii < numfilesadded; ii++) { + if (strcmp(fn, addedfiles[ii])) + continue; + // If this is one of them, don't try to add it. - if (!strcmp(fn, addedfiles[ii])) - { - fileadded = true; - break; - } + break; } // If we've added this one, skip to the next one. - if (fileadded) + if (ii < numfilesadded) { CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn); continue; @@ -4385,13 +4385,22 @@ static void Command_Addfile(void) // Disallow non-printing characters and semicolons. for (i = 0; fn[i] != '\0'; i++) - if (!isprint(fn[i]) || fn[i] == ';') - { - Z_Free(addedfiles); - return; - } + { + if (isprint(fn[i]) && fn[i] != ';') + continue; + goto addfile_finally; + } - musiconly = W_VerifyNMUSlumps(fn, false); + if (fhandle) + { + fclose(fhandle); + fhandle = NULL; + } + + if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) + { + musiconly = W_VerifyNMUSlumps(fn, fhandle, false); + } if (musiconly == -1) { @@ -4429,47 +4438,40 @@ static void Command_Addfile(void) if (numwadfiles >= MAX_WADFILES) { CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); - Z_Free(addedfiles); - return; + goto addfile_finally; } - WRITESTRINGN(buf_p,p,240); - // calculate and check md5 { UINT8 md5sum[16]; #ifdef NOMD5 memset(md5sum,0,16); #else - FILE *fhandle; - boolean valid = true; - - if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) { tic_t t = I_GetTime(); CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn); md5_stream(fhandle, md5sum); CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE); - fclose(fhandle); } - else // file not found - continue; for (i = 0; i < numwadfiles; i++) { - if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) - { - CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); - valid = false; - break; - } + if (memcmp(wadfiles[i]->md5sum, md5sum, 16)) + continue; + + CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); + break; } - if (valid == false) + if (i < numwadfiles) { + // Already loaded, try next continue; } #endif + + // Finally okay to write this important data + WRITESTRINGN(buf_p,p,240); WRITEMEM(buf_p, md5sum, 16); } @@ -4481,6 +4483,10 @@ static void Command_Addfile(void) SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); } +addfile_finally: + + if (fhandle) + fclose(fhandle); Z_Free(addedfiles); #endif/*TESTERS*/ } diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 293c1e3f3..857be69ab 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -848,7 +848,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, const if ((handle = W_OpenWadFile(&filename, true)) == NULL) return W_InitFileError(filename, startup); - important = W_VerifyNMUSlumps(filename, startup); + important = W_VerifyNMUSlumps(filename, handle, startup); if (important == -1) { @@ -1071,8 +1071,8 @@ INT32 W_InitMultipleFiles(const initmultiplefilesentry_t *entries, INT32 count, { const initmultiplefilesentry_t *entry = &entries[i]; - if (addons && !W_VerifyNMUSlumps(entry->filename, !addons)) - G_SetGameModified(true, false); + // Previously, W_VerifyNMUSlumps was called to mark game modified + // for addons... but W_InitFile already does exactly that! //CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames); rc = W_InitFile(entry->filename, !addons, true, entry->md5sum); @@ -2368,35 +2368,6 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) } } -// Note: This never opens lumps themselves and therefore doesn't have to -// deal with compressed lumps. -static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, - boolean status) -{ - FILE *handle; - int goodfile = false; - - if (!checklist) - I_Error("No checklist for %s\n", filename); - // open wad file - if ((handle = W_OpenWadFile(&filename, false)) == NULL) - return -1; - - if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0) - goodfile = W_VerifyPK3(handle, checklist, status); - else - { - // detect wad file by the absence of the other supported extensions - if (stricmp(&filename[strlen(filename) - 4], ".soc") - && stricmp(&filename[strlen(filename) - 4], ".lua")) - { - goodfile = W_VerifyWAD(handle, checklist, status); - } - } - fclose(handle); - return goodfile; -} - /** Checks a wad for lumps other than music and sound. * Used during game load to verify music.dta is a good file and during a @@ -2410,7 +2381,7 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, * file exists with that filename * \author Alam Arias */ -int W_VerifyNMUSlumps(const char *filename, boolean exit_on_error) +int W_VerifyNMUSlumps(const char *filename, FILE *handle, boolean exit_on_error) { lumpchecklist_t NMUSlist[] = { @@ -2463,7 +2434,19 @@ int W_VerifyNMUSlumps(const char *filename, boolean exit_on_error) {NULL, 0}, }; - int status = W_VerifyFile(filename, NMUSlist, false); + int status = 0; + + if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0) + status = W_VerifyPK3(handle, NMUSlist, false); + else + { + // detect wad file by the absence of the other supported extensions + if (stricmp(&filename[strlen(filename) - 4], ".soc") + && stricmp(&filename[strlen(filename) - 4], ".lua")) + { + status = W_VerifyWAD(handle, NMUSlist, false); + } + } if (status == -1) W_InitFileError(filename, exit_on_error); diff --git a/src/w_wad.h b/src/w_wad.h index b56e05248..6c479aae5 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -226,7 +226,7 @@ void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag); void W_UnlockCachedPatch(void *patch); -int W_VerifyNMUSlumps(const char *filename, boolean exit_on_error); +int W_VerifyNMUSlumps(const char *filename, FILE *handle, boolean exit_on_error); /// Initialize non-legacy GL shader lookup, which lives outside the lump management system. void W_InitShaderLookup(const char *filename); From 8230bbbca4140cb509c1c7c4902f805226b9f9eb Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 25 Aug 2025 20:03:02 +0100 Subject: [PATCH 3/7] filesearch: Ignore certain high-content, low-utility folders A blacklist for "logs", "media", and "luafiles" at the root of the search, and ".git" in all subfolders Also some minor code cleanup for improved readability --- src/filesrch.c | 94 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/src/filesrch.c b/src/filesrch.c index 3f6428bfb..17b7d70c7 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -435,6 +435,13 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) #else +static const char *filesearch_exclude[] = { + "media", + "logs", + "luafiles", + NULL +}; + filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) { filestatus_t retval = FS_NOTFOUND; @@ -442,7 +449,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want struct dirent *dent; struct stat fsstat = {0}; int found = 0; - char *searchname = strdup(filename); + char *searchname; int depthleft = maxsearchdepth; char searchpath[1024]; size_t *searchpathindex; @@ -457,12 +464,13 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want if (dirhandle[depthleft] == NULL) { - free(searchname); free(dirhandle); free(searchpathindex); return FS_NOTFOUND; } + searchname = strdup(filename); + if (searchpath[searchpathindex[depthleft]-2] != PATHSEP[0]) { searchpath[searchpathindex[depthleft]-1] = PATHSEP[0]; @@ -492,42 +500,68 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want } // okay, now we actually want searchpath to incorporate d_name - strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); + strcpy(&searchpath[searchpathindex[depthleft]], dent->d_name); if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat - ; // was the file (re)moved? can't stat it - else if (S_ISDIR(fsstat.st_mode) && depthleft) + continue; // was the file (re)moved? can't stat it + + if (S_ISDIR(fsstat.st_mode)) { - searchpathindex[--depthleft] = strlen(searchpath) + 1; - dirhandle[depthleft] = opendir(searchpath); - if (!dirhandle[depthleft]) + // I am a folder! + + if (!depthleft) + continue; // No additional folder delving permitted... + + const char **path = filesearch_exclude; + + if (depthleft == maxsearchdepth-1) { - // can't open it... maybe no read-permissions - // go back to previous dir - depthleft++; + // When we're at the root of the search, we exclude certain folders. + for (; *path; path++) + { + if (strcasecmp(*path, dent->d_name)) + continue; + + break; + } + + if (*path) + continue; // This folder is excluded } - searchpath[searchpathindex[depthleft]-1] = PATHSEP[0]; - searchpath[searchpathindex[depthleft]] = 0; - } - else if (!strcasecmp(searchname, dent->d_name)) - { - switch (checkfilemd5(searchpath, wantedmd5sum)) + if (strcasecmp(".git", dent->d_name) // sanity if you're weird like me + && (dirhandle[depthleft-1] = opendir(searchpath)) != NULL) { - case FS_FOUND: - if (completepath) - strcpy(filename,searchpath); - else - strcpy(filename,dent->d_name); - retval = FS_FOUND; - found = 1; - break; - case FS_MD5SUMBAD: - retval = FS_MD5SUMBAD; - break; - default: // prevent some compiler warnings - break; + // Got read permissions! + searchpathindex[--depthleft] = strlen(searchpath) + 1; + + searchpath[searchpathindex[depthleft]-1] = PATHSEP[0]; + searchpath[searchpathindex[depthleft]] = 0; } + + continue; + } + + // I am a file! + + if (strcasecmp(searchname, dent->d_name)) + continue; // Not what we're looking for! + + switch (checkfilemd5(searchpath, wantedmd5sum)) + { + case FS_FOUND: + if (completepath) + strcpy(filename,searchpath); + else + strcpy(filename,dent->d_name); + retval = FS_FOUND; + found = 1; + break; + case FS_MD5SUMBAD: + retval = FS_MD5SUMBAD; + break; + default: // prevent some compiler warnings + break; } } From 48261ae4b5ea1a0a561909e4b6b0e91977a1adeb Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 25 Aug 2025 20:14:37 +0100 Subject: [PATCH 4/7] filesearch: Add "Priority folder" string parameter If non-NULL, filesearch will begin in that subfolder of the desired searchpath, but can go back up to the root of the search later if not found in that location. Primarily a small optimisation for checking the addons folder first --- src/command.c | 2 +- src/d_main.cpp | 2 +- src/d_netcmd.c | 8 ++++---- src/d_netfil.c | 10 +++++----- src/d_netfil.h | 2 +- src/filesrch.c | 44 +++++++++++++++++++++++++++++++++++++++----- src/filesrch.h | 3 ++- src/g_demo.cpp | 4 ++-- src/lua_script.c | 2 +- src/sdl/i_system.cpp | 2 +- src/sdl/i_ttf.c | 2 +- src/sdl12/i_system.c | 2 +- src/w_wad.cpp | 20 +++++++------------- src/w_wad.h | 2 +- 14 files changed, 67 insertions(+), 38 deletions(-) diff --git a/src/command.c b/src/command.c index 90a28d59c..b60bed77e 100644 --- a/src/command.c +++ b/src/command.c @@ -853,7 +853,7 @@ static void COM_Exec_f(void) // Now try by searching the file path // filename is modified with the full found path strcpy(filename, COM_Argv(1)); - if (findfile(filename, NULL, true) != FS_NOTFOUND) + if (findfile(filename, NULL, NULL, true) != FS_NOTFOUND) FIL_ReadFile(filename, &buf); if (!buf) diff --git a/src/d_main.cpp b/src/d_main.cpp index 2eba82a6d..0b367f1d2 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1434,7 +1434,7 @@ static void IdentifyVersion(void) #define MUSICTEST(str) \ musicpath = va(spandf,srb2waddir,"data",str);\ - handle = W_OpenWadFile(&musicpath, false); \ + handle = W_OpenWadFile(&musicpath, NULL, false); \ if (handle) \ { \ int ms = W_VerifyNMUSlumps(musicpath, handle, false); \ diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 58bee1b6a..090c7edaf 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4311,7 +4311,7 @@ static void Got_RunSOCcmd(const UINT8 **cp, INT32 playernum) // Maybe add md5 support? if (strstr(filename, ".soc") != NULL) { - ncs = findfile(filename,NULL,true); + ncs = findfile(filename, "addons", NULL, true); if (ncs != FS_FOUND) { @@ -4397,7 +4397,7 @@ static void Command_Addfile(void) fhandle = NULL; } - if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) + if ((fhandle = W_OpenWadFile(&fn, "addons", true)) != NULL) { musiconly = W_VerifyNMUSlumps(fn, fhandle, false); } @@ -4523,7 +4523,7 @@ static void Got_RequestAddfilecmd(const UINT8 **cp, INT32 playernum) if (numwadfiles >= MAX_WADFILES) toomany = true; else - ncs = findfile(filename,md5sum,true); + ncs = findfile(filename, "addons", md5sum, true); if (ncs != FS_FOUND || toomany) { @@ -4567,7 +4567,7 @@ static void Got_Addfilecmd(const UINT8 **cp, INT32 playernum) return; } - ncs = findfile(filename,md5sum,true); + ncs = findfile(filename, "addons", md5sum, true); if (ncs != FS_FOUND || !P_AddWadFile(filename)) { diff --git a/src/d_netfil.c b/src/d_netfil.c index 6b23abbdb..061f587a0 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -636,7 +636,7 @@ INT32 CL_CheckFiles(void) packetsize += nameonlylength(fileneeded[i].filename) + 22; - fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true); + fileneeded[i].status = findfile(fileneeded[i].filename, "addons", fileneeded[i].md5sum, true); CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status); return 4; } @@ -1759,13 +1759,13 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum) // Rewritten by Monster Iestyn to be less stupid // Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned // (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore) -filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath) +filestatus_t findfile(char *filename, const char *priorityfolder, const UINT8 *wantedmd5sum, boolean completepath) { filestatus_t homecheck; // store result of last file search boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third) // first, check SRB2's "home" directory - homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10); + homecheck = filesearch(filename, srb2home, priorityfolder, wantedmd5sum, completepath, 10); if (homecheck == FS_FOUND) // we found the file, so return that we have :) return FS_FOUND; @@ -1774,7 +1774,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet // if not found at all, just move on without doing anything // next, check SRB2's "path" directory - homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10); + homecheck = filesearch(filename, srb2path, priorityfolder, wantedmd5sum, completepath, 10); if (homecheck == FS_FOUND) // we found the file, so return that we have :) return FS_FOUND; @@ -1783,7 +1783,7 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet // if not found at all, just move on without doing anything // finally check "." directory - homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10); + homecheck = filesearch(filename, ".", priorityfolder, wantedmd5sum, completepath, 10); if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement return homecheck; // otherwise return the result we got diff --git a/src/d_netfil.h b/src/d_netfil.h index 71eaca2de..d457cb43f 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -157,7 +157,7 @@ void Command_Downloads_f(void); boolean fileexist(char *filename, time_t ptime); // Search a file in the wadpath, return FS_FOUND when found -filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, +filestatus_t findfile(char *filename, const char *suggestedfolder, const UINT8 *wantedmd5sum, boolean completepath); filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum); diff --git a/src/filesrch.c b/src/filesrch.c index 17b7d70c7..5ec0c8a9f 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -333,7 +333,8 @@ char *refreshdirname = NULL; #if defined (_XBOX) && defined (_MSC_VER) -filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, +filestatus_t filesearch(char *filename, const char *startpath, + const char *priorityfolder, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) { //NONE? @@ -364,7 +365,8 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) } #elif defined (_WIN32_WCE) -filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, +filestatus_t filesearch(char *filename, const char *startpath, + const char *priorityfolder, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) { #ifdef __GNUC__ @@ -378,6 +380,8 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want HANDLE searchhandle = INVALID_HANDLE_VALUE; const wchar_t wm[4] = L"*.*"; + (void)priorityfolder; + //if (startpath) SetCurrentDirectory(startpath); if (FIL_ReadFileOK(filename)) { @@ -396,7 +400,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want //if (SetCurrentDirectory(dta.cFileName)) { // can fail if we haven't the right filestatus_t found; - found = filesearch(filename,NULL,wantedmd5sum,completepath,maxsearchdepth-1); + found = filesearch(filename,NULL,NULL,wantedmd5sum,completepath,maxsearchdepth-1); //SetCurrentDirectory(".."); if (found == FS_FOUND || found == FS_MD5SUMBAD) { @@ -442,7 +446,9 @@ static const char *filesearch_exclude[] = { NULL }; -filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) +filestatus_t filesearch(char *filename, const char *startpath, + const char *priorityfolder, const UINT8 *wantedmd5sum, + boolean completepath, int maxsearchdepth) { filestatus_t retval = FS_NOTFOUND; DIR **dirhandle; @@ -479,6 +485,27 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want else searchpathindex[depthleft]--; + if (priorityfolder != NULL) + { + // Start the search at [startpath]/priorityfolder + + strcpy(&searchpath[searchpathindex[depthleft]], priorityfolder); + + if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat + ; // was the file (re)moved? can't stat it + else if (S_ISDIR(fsstat.st_mode) && depthleft) + { + if ((dirhandle[depthleft-1] = opendir(searchpath)) != NULL) + { + // Got read permissions! + searchpathindex[--depthleft] = strlen(searchpath) + 1; + + searchpath[searchpathindex[depthleft]-1] = PATHSEP[0]; + searchpath[searchpathindex[depthleft]] = 0; + } + } + } + while ((!found) && (depthleft < maxsearchdepth)) { searchpath[searchpathindex[depthleft]]=0; @@ -517,7 +544,14 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want if (depthleft == maxsearchdepth-1) { // When we're at the root of the search, we exclude certain folders. - for (; *path; path++) + + if (priorityfolder != NULL + && strcasecmp(priorityfolder, dent->d_name)) + { + // We skip revisiting the priority by pretending + // it matched the first exclude directory instead + } + else for (; *path; path++) { if (strcasecmp(*path, dent->d_name)) continue; diff --git a/src/filesrch.h b/src/filesrch.h index f29360f87..d151af035 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -31,6 +31,7 @@ extern consvar_t cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_add \param filename the file to look for \param startpath where to start look from + \param priorityfolder priority for starting checking, then go back up? \param wantedmd5sum want to check with MD5 \param completepath want to return the complete path of the file? \param maxsearchdepth the max depth to search for the file @@ -40,7 +41,7 @@ extern consvar_t cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_add */ -filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, +filestatus_t filesearch(char *filename, const char *startpath, const char *priorityfolder, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth); #define menudepth 20 diff --git a/src/g_demo.cpp b/src/g_demo.cpp index c4ceaa65d..5564f5506 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -1785,7 +1785,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp) if (numwadfiles >= MAX_WADFILES) toomany = true; else - ncs = findfile(filename, md5sum, false); + ncs = findfile(filename, "addons", md5sum, false); if (toomany) { @@ -1894,7 +1894,7 @@ static UINT8 G_CheckDemoExtraFiles(savebuffer_t *info, boolean quick) if (numwadfiles >= MAX_WADFILES) error = DFILE_ERROR_CANNOTLOAD; - else if (!quick && findfile(filename, md5sum, false) != FS_FOUND) + else if (!quick && findfile(filename, "addons", md5sum, false) != FS_FOUND) error = DFILE_ERROR_CANNOTLOAD; else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER) error |= DFILE_ERROR_NOTLOADED; diff --git a/src/lua_script.c b/src/lua_script.c index 26ea7d8e7..b0ba602f4 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -628,7 +628,7 @@ void LUA_DumpFile(const char *filename) // If findfile finds the file, the full path will be returned // in filenamebuf == filename. - if (findfile(filenamebuf, NULL, true)) + if (findfile(filenamebuf, NULL, NULL, true)) { if ((handle = fopen(filename, "rb")) == NULL) { diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index 31fb8bbef..4014e980c 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -2160,7 +2160,7 @@ static const char *searchWad(const char *searchDir) filestatus_t fstemp; strcpy(tempsw, WADKEYWORD); - fstemp = filesearch(tempsw,searchDir,NULL,true,20); + fstemp = filesearch(tempsw, searchDir, NULL, NULL, true, 20); if (fstemp == FS_FOUND) { pathonly(tempsw); diff --git a/src/sdl/i_ttf.c b/src/sdl/i_ttf.c index fe8547289..a0eccf36c 100644 --- a/src/sdl/i_ttf.c +++ b/src/sdl/i_ttf.c @@ -53,7 +53,7 @@ static char *searchFont(const char *fontsearchDir) filestatus_t fstemp; strcpy(tempsw, FONTFILE); - fstemp = filesearch(tempsw, fontsearchDir, NULL, true, 20); + fstemp = filesearch(tempsw, fontsearchDir, NULL, NULL, true, 20); if (fstemp == FS_FOUND) { return tempsw; diff --git a/src/sdl12/i_system.c b/src/sdl12/i_system.c index 18d28abd4..0050fdb21 100644 --- a/src/sdl12/i_system.c +++ b/src/sdl12/i_system.c @@ -3432,7 +3432,7 @@ static const char *searchWad(const char *searchDir) filestatus_t fstemp; strcpy(tempsw, WADKEYWORD); - fstemp = filesearch(tempsw,searchDir,NULL,true,20); + fstemp = filesearch(tempsw, searchDir, NULL, NULL, true, 20); if (fstemp == FS_FOUND) { pathonly(tempsw); diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 857be69ab..efbc752cc 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -186,7 +186,7 @@ static char filenamebuf[MAX_WADPATH]; // Returns the FILE * handle for the file, or NULL if not found or could not be opened // If "useerrors" is true then print errors in the console, else just don't bother // "filename" may be modified to have the correct path the actual file is located in, if necessary -FILE *W_OpenWadFile(const char **filename, boolean useerrors) +FILE *W_OpenWadFile(const char **filename, const char *priorityfolder, boolean useerrors) { FILE *handle; @@ -209,7 +209,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) // If findfile finds the file, the full path will be returned // in filenamebuf == *filename. - if (findfile(filenamebuf, NULL, true)) + if (findfile(filenamebuf, priorityfolder, NULL, true)) { if ((handle = fopen(*filename, "rb")) == NULL) { @@ -845,7 +845,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, const } // open wad file - if ((handle = W_OpenWadFile(&filename, true)) == NULL) + if ((handle = W_OpenWadFile(&filename, (mainfile ? NULL : "addons"), true)) == NULL) return W_InitFileError(filename, startup); important = W_VerifyNMUSlumps(filename, handle, startup); @@ -2472,17 +2472,11 @@ void W_InitShaderLookup(const char *filename) { nameonly(filename_buf); - if (findfile(filename_buf, NULL, true)) - { - if ((handle = fopen(filename_buf, "rb")) == NULL) - { - return; - } - } - else - { + if (!findfile(filename_buf, "data", NULL, true)) + return; + + if ((handle = fopen(filename_buf, "rb")) == NULL) return; - } } // It is acceptable to fail opening the pk3 lookup. diff --git a/src/w_wad.h b/src/w_wad.h index 6c479aae5..06553ea28 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -147,7 +147,7 @@ extern wadfile_t *wadfiles[MAX_WADFILES]; void W_Shutdown(void); // Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened -FILE *W_OpenWadFile(const char **filename, boolean useerrors); +FILE *W_OpenWadFile(const char **filename, const char *priorityfolder, boolean useerrors); // Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, const char *md5expected); From 2b2b20718f7ebe0a2de36644a0e7864aad0482a0 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 25 Aug 2025 21:00:44 +0100 Subject: [PATCH 5/7] findfile aggressive optimisation: If srb2home and srb2path are the current working directory, don't search in them srb2path will report "." while this optimisation is in play, but this can be disabled if necessary by modifying the small #if (1) in IdentifyVersion --- src/d_main.cpp | 20 +++++++++++++------- src/d_netfil.c | 34 ++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 0b367f1d2..98acff85e 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1395,19 +1395,25 @@ static void IdentifyVersion(void) srb2waddir = I_LocateWad(); #endif + char tempsrb2path[256] = "."; + getcwd(tempsrb2path, 256); + // get the current directory (possible problem on NT with "." as current dir) - if (srb2waddir) + if (!srb2waddir) { - strlcpy(srb2path,srb2waddir,sizeof (srb2path)); - } - else - { - if (getcwd(srb2path, 256) != NULL) - srb2waddir = srb2path; + if (tempsrb2path[0]) + srb2waddir = tempsrb2path; else srb2waddir = "."; } +#if (1) // reduce the amount of findfile by only using full cwd in this func + if (strcmp(tempsrb2path, srb2waddir)) +#endif + { + strlcpy(srb2path, srb2waddir, sizeof (srb2path)); + } + // Load the IWAD if (! AddIWAD()) { diff --git a/src/d_netfil.c b/src/d_netfil.c index 061f587a0..a95767d5b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -1764,23 +1764,29 @@ filestatus_t findfile(char *filename, const char *priorityfolder, const UINT8 *w filestatus_t homecheck; // store result of last file search boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third) - // first, check SRB2's "home" directory - homecheck = filesearch(filename, srb2home, priorityfolder, wantedmd5sum, completepath, 10); + // first, check SRB2's "home" directory (if non-'.') + if (strcmp(srb2home, ".")) + { + homecheck = filesearch(filename, srb2home, priorityfolder, wantedmd5sum, completepath, 10); - if (homecheck == FS_FOUND) // we found the file, so return that we have :) - return FS_FOUND; - else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 - badmd5 = true; - // if not found at all, just move on without doing anything + if (homecheck == FS_FOUND) // we found the file, so return that we have :) + return FS_FOUND; + else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 + badmd5 = true; + // if not found at all, just move on without doing anything + } - // next, check SRB2's "path" directory - homecheck = filesearch(filename, srb2path, priorityfolder, wantedmd5sum, completepath, 10); + // next, check SRB2's "path" directory (also if non-'.') + if (strcmp(srb2path, ".")) + { + homecheck = filesearch(filename, srb2path, priorityfolder, wantedmd5sum, completepath, 10); - if (homecheck == FS_FOUND) // we found the file, so return that we have :) - return FS_FOUND; - else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 - badmd5 = true; - // if not found at all, just move on without doing anything + if (homecheck == FS_FOUND) // we found the file, so return that we have :) + return FS_FOUND; + else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 + badmd5 = true; + // if not found at all, just move on without doing anything + } // finally check "." directory homecheck = filesearch(filename, ".", priorityfolder, wantedmd5sum, completepath, 10); From 2bd83082e4c1eab3612a1ced7fc59a5b85a170e7 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 25 Aug 2025 21:11:58 +0100 Subject: [PATCH 6/7] Fix incorrect count on Add-Ons menu --- src/k_menudraw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index fca3b148c..bf85955a9 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -6739,7 +6739,7 @@ void M_DrawAddons(void) if (modifiedgame) V_DrawSmallScaledPatch(x, y, 0, addonsp[NUM_EXT+2]); - m = numwadfiles-(mainwads+musicwads+1); + m = numwadfiles-(mainwads+musicwads); V_DrawCenteredMenuString(BASEVIDWIDTH/2, y+4, (majormods ? highlightflags : V_TRANSLUCENT), va("%ld ADD-ON%s LOADED", (long)m, (m == 1) ? "" : "S")); //+2 for music, sounds, +1 for bios.pk3 } From ebdd9b8b7e52426db7bdde165628e74d11f07460 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 25 Aug 2025 22:46:10 +0100 Subject: [PATCH 7/7] W_VerifyNMUSlumps: Rewind back to beginning of file handle for WAD --- src/w_wad.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/w_wad.cpp b/src/w_wad.cpp index efbc752cc..47f48a0af 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -2437,7 +2437,9 @@ int W_VerifyNMUSlumps(const char *filename, FILE *handle, boolean exit_on_error) int status = 0; if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0) + { status = W_VerifyPK3(handle, NMUSlist, false); + } else { // detect wad file by the absence of the other supported extensions @@ -2445,6 +2447,9 @@ int W_VerifyNMUSlumps(const char *filename, FILE *handle, boolean exit_on_error) && stricmp(&filename[strlen(filename) - 4], ".lua")) { status = W_VerifyWAD(handle, NMUSlist, false); + + // repair file handle in this specific case + fseek(handle, 0, SEEK_SET); } }