From 06a115070bc78897d9029680585bcaa4707e6253 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Tue, 25 Jun 2019 22:32:52 +0800 Subject: [PATCH] Added AutoSearchPath option to [ExtraPatches]. * this provides a simpler way to load assorted .dat files without the need of adding/editing PatchFileXX options in ddraw.ini. --- artifacts/ddraw.ini | 10 +++++++- sfall/Modules/LoadOrder.cpp | 47 ++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 65094436..284d712e 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -11,11 +11,19 @@ UseCommandLine=0 ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [ExtraPatches] ;This section allows you to set multiple paths to folders containing mods or patches that will be loaded by the game -;The priority of read files will be higher than the files in patchXXX.dat. If DataLoadOrderPatch is enabled, the data load order will be: +;The priority of read files will be higher than the files in patchXXX.dat +;If DataLoadOrderPatch is enabled, the data load order will be: ;master_patches > critter_patches > PatchFile99 - PatchFile0 > patchXXX.dat > ... ;Paths to folders and Fallout .dat files are supported. The available range for PatchFile option names is from 0 to 99 +;The greater numbers take precedence over lesser numbers ;PatchFile0=mods\RP_data +;Path to the folder in which the game will automatically search and load custom .dat files +;The data load order of the .dat files in the folder will be in reverse alphabetical order of the filenames +;The .dat files specified in the PatchFileXX options will have higher priority than others +;Uncomment the option to specify a different folder path. The default path is \mods\ +;AutoSearchPath=mods + ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [Sound] ;Sets the number of allowed simultaneous sound effects diff --git a/sfall/Modules/LoadOrder.cpp b/sfall/Modules/LoadOrder.cpp index d4eb39d7..ad0cfe96 100644 --- a/sfall/Modules/LoadOrder.cpp +++ b/sfall/Modules/LoadOrder.cpp @@ -155,8 +155,11 @@ end: static void __stdcall InitExtraPatches() { for (auto it = patchFiles.begin(); it != patchFiles.end(); it++) { - fo::func::db_init(it->c_str(), 0); + if (!it->empty()) fo::func::db_init(it->c_str(), 0); } + // free memory + patchFiles.clear(); + patchFiles.shrink_to_fit(); } static void __fastcall game_init_databases_hook() { @@ -176,14 +179,52 @@ static void __fastcall game_init_databases_hook() { fo::var::paths = master_patches; // set master_patches node at the beginning of the load order } +static bool NormalizePath(std::string &path) { + if (path.find(':') != std::string::npos) return false; + int pos = 0; + do { // replace all '/' char to '\' + pos = path.find('/', pos); + if (pos != std::string::npos) path[pos] = '\\'; + } while (pos != std::string::npos); + if (path.find(".\\") != std::string::npos || path.find("..\\") != std::string::npos) return false; + while (path.front() == '\\') path.erase(0, 1); // remove firsts '\' + return true; +} + static void GetExtraPatches() { + std::string searchPath = GetConfigString("ExtraPatches", "AutoSearchPath", "mods\\", MAX_PATH); + if (!searchPath.empty() && NormalizePath(searchPath)) { + if (searchPath.back() != '\\') searchPath += "\\"; + + std::string path(".\\" + searchPath + "*.dat"); + dlogr("Loading custom patches:", DL_MAIN); + WIN32_FIND_DATA findData; + HANDLE hFind = FindFirstFile(path.c_str(), &findData); + if (hFind != INVALID_HANDLE_VALUE) { + do { + std::string name(searchPath + findData.cFileName); + dlog_f(">%s\n", DL_MAIN, name.c_str()); + patchFiles.push_back(name); + } while (FindNextFile(hFind, &findData)); + FindClose(hFind); + } + } char patchFile[12] = "PatchFile"; for (int i = 0; i < 100; i++) { _itoa(i, &patchFile[9], 10); auto patch = GetConfigString("ExtraPatches", patchFile, "", MAX_PATH); - if (patch.empty() || GetFileAttributes(patch.c_str()) == INVALID_FILE_ATTRIBUTES) continue; + if (patch.empty() || !NormalizePath(patch) || GetFileAttributes(patch.c_str()) == INVALID_FILE_ATTRIBUTES) continue; patchFiles.push_back(patch); } + // Remove first duplicates + size_t size = patchFiles.size(); + for (size_t i = 1; i < size; ++i) { + for(size_t j = size - 1; j > i; --j) { + if (patchFiles[j] == patchFiles[i]) { + patchFiles[i].clear(); + } + } + } } ////////////////////////////// SAVE PARTY MEMBER PROTOTYPES ////////////////////////////// @@ -325,7 +366,7 @@ static void RemoveSavFiles() { } void LoadOrder::init() { - // Load external sfall resource file + // Load external sfall resource file (load order is before patchXXX.dat) patchFiles.push_back("sfall.dat"); GetExtraPatches();