diff --git a/Descent3/Game2DLL.cpp b/Descent3/Game2DLL.cpp index 0bc4a98d..1dd1718a 100644 --- a/Descent3/Game2DLL.cpp +++ b/Descent3/Game2DLL.cpp @@ -565,7 +565,7 @@ bool InitGameModule(const char *name, module *mod) { std::filesystem::path dll_name; std::filesystem::path tmp_dll_name; // Make the hog filename - lib_name = Base_directory / "netgames" / name; + lib_name = std::filesystem::path("netgames") / name; lib_name.replace_extension(".d3m"); // Make the dll filename dll_name = name; diff --git a/Descent3/Mission.cpp b/Descent3/Mission.cpp index dcde32a1..00e8cbe2 100644 --- a/Descent3/Mission.cpp +++ b/Descent3/Mission.cpp @@ -921,7 +921,7 @@ bool LoadMission(const char *mssn) { if (IS_MN3_FILE(mssn)) { strcpy(mission, mssn); - ddio_MakePath(pathname, D3MissionsDir, mission, NULL); + ddio_MakePath(pathname, "missions", mission, NULL); } else { strcpy(mission, mssn); strcpy(pathname, mssn); @@ -1645,9 +1645,7 @@ void DoMissionMovie(const char *movie) { return; #endif if (movie && *movie) { - char mpath[_MAX_PATH]; - ddio_MakePath(mpath, LocalD3Dir, "movies", movie, NULL); - PlayMovie(mpath); + PlayMovie(movie); } } @@ -1835,11 +1833,11 @@ bool mn3_Open(const char *mn3file) { char voice_hog[_MAX_PATH*2]; if ((stricmp(filename, "d3") == 0) || (stricmp(filename, "training") == 0)) { // Open audio hog file - ddio_MakePath(voice_hog, D3MissionsDir, "d3voice1.hog", nullptr); // Audio for levels 1-4 + ddio_MakePath(voice_hog, "missions", "d3voice1.hog", nullptr); // Audio for levels 1-4 Mission_voice_hog_handle = cf_OpenLibrary(voice_hog); } else if (stricmp(filename, "d3_2") == 0) { // Open audio hog file - ddio_MakePath(voice_hog, D3MissionsDir, "d3voice2.hog", nullptr); // Audio for levels 5-17 + ddio_MakePath(voice_hog, "missions", "d3voice2.hog", nullptr); // Audio for levels 5-17 Mission_voice_hog_handle = cf_OpenLibrary(voice_hog); } strcat(filename, ".gam"); @@ -1855,7 +1853,7 @@ bool mn3_GetInfo(const char *mn3file, tMissionInfo *msn) { char pathname[_MAX_PATH]; char filename[PSFILENAME_LEN + 1]; - ddio_MakePath(pathname, D3MissionsDir, mn3file, nullptr); + ddio_MakePath(pathname, "missions", mn3file, nullptr); handle = cf_OpenLibrary(pathname); if (handle == 0) { LOG_ERROR << "MISSION: MN3 failed to open."; diff --git a/Descent3/PilotPicsAPI.cpp b/Descent3/PilotPicsAPI.cpp index 7d8de7cc..520254d7 100644 --- a/Descent3/PilotPicsAPI.cpp +++ b/Descent3/PilotPicsAPI.cpp @@ -132,9 +132,7 @@ bool PPic_InitDatabase(void) { // attempt to open the hog database // -------------------------------- - char fullpath[_MAX_PATH]; - ddio_MakePath(fullpath, LocalD3Dir, PILOTPIC_DATABASE_HOG, NULL); - PilotPic_database_hog_handle = cf_OpenLibrary(fullpath); + PilotPic_database_hog_handle = cf_OpenLibrary(PILOTPIC_DATABASE_HOG); if (PilotPic_database_hog_handle == 0) { // there was an error opening the hog database diff --git a/Descent3/d3movie.cpp b/Descent3/d3movie.cpp index aab0f796..3a123c2a 100644 --- a/Descent3/d3movie.cpp +++ b/Descent3/d3movie.cpp @@ -71,47 +71,11 @@ void mve_SetCallback(MovieFrameCallback_fp callBack) { // used to tell movie library how to render movies. void mve_SetRenderProperties(int16_t x, int16_t y, int16_t w, int16_t h, renderer_type type, bool hicolor) {} -#if defined(POSIX) -// locates the case-sensitive movie file name -std::filesystem::path mve_FindMovieFileRealName(const std::filesystem::path &movie) { - // split into directory and file... - std::filesystem::path t_file = movie.filename(); - std::filesystem::path t_dir = movie.parent_path(); - std::filesystem::path t_out; - - // found a directory? - if (!t_dir.empty()) { - // map the bits (or fail) - t_out = cf_FindRealFileNameCaseInsensitive(t_file, t_dir); - if (t_out.empty()) - return t_out; - // re-assemble - return (t_dir / t_out); - } else { - // just a file, map that - t_out = cf_FindRealFileNameCaseInsensitive(t_file); - if (t_out.empty()) - return t_out; - // re-assemble - return t_out; - } -} -#endif - // plays a movie using the current screen. int mve_PlayMovie(const std::filesystem::path &pMovieName, oeApplication *pApp) { #ifndef NO_MOVIES // first, find that movie.. - std::filesystem::path real_name; -#if defined(POSIX) - real_name = mve_FindMovieFileRealName(pMovieName); - if (real_name.empty()) { - LOG_WARNING.printf("MOVIE: No such file %s", pMovieName.u8string().c_str()); - return MVELIB_FILE_ERROR; - } -#else - real_name = pMovieName; -#endif + std::filesystem::path real_name = cf_LocatePath("movies" / pMovieName); // open movie file. FILE *hFile = fopen(real_name.u8string().c_str(), "rb"); if (hFile == nullptr) { @@ -354,17 +318,7 @@ void CallbackShowFrameNoFlip(unsigned char *buf, unsigned int bufw, unsigned int intptr_t mve_SequenceStart(const char *mvename, void *fhandle, oeApplication *app, bool looping) { #ifndef NO_MOVIES // first, find that movie.. - std::filesystem::path real_name; -#if defined(POSIX) - real_name = mve_FindMovieFileRealName(mvename); - if (real_name.empty()) { - LOG_WARNING.printf("MOVIE: No such file %s", mvename); - fhandle = nullptr; - return 0; - } -#else - real_name = mvename; -#endif + std::filesystem::path real_name = cf_LocatePath(std::filesystem::path("movies") / mvename); fhandle = fopen(real_name.u8string().c_str(), "rb"); if (fhandle == nullptr) { diff --git a/Descent3/descent.cpp b/Descent3/descent.cpp index 5910d155..46cabed3 100644 --- a/Descent3/descent.cpp +++ b/Descent3/descent.cpp @@ -490,7 +490,7 @@ void Descent3() { }; for (auto const &intro : intros) { - PlayMovie(Base_directory / "movies" / intro); + PlayMovie(intro); } } diff --git a/Descent3/gamesequence.cpp b/Descent3/gamesequence.cpp index d4474866..fd8a2659 100644 --- a/Descent3/gamesequence.cpp +++ b/Descent3/gamesequence.cpp @@ -1311,10 +1311,10 @@ void CheckHogfile() { if (new_mn3) { // close the mission hog file and open the new one mn3_Close(); - char hogpath[_MAX_PATH * 2]; - ddio_MakePath(hogpath, D3MissionsDir, new_mn3, nullptr); - if (cfexist(hogpath)) { - mn3_Open(hogpath); + auto relative_path = std::filesystem::path("missions") / new_mn3; + auto absolute_path = cf_LocatePath(relative_path); + if (std::filesystem::exists(absolute_path)) { + mn3_Open(relative_path.u8string().c_str()); mem_free(Current_mission.filename); Current_mission.filename = mem_strdup(new_mn3); } else { diff --git a/Descent3/gamespy.cpp b/Descent3/gamespy.cpp index 7100d571..1eaa747c 100644 --- a/Descent3/gamespy.cpp +++ b/Descent3/gamespy.cpp @@ -124,7 +124,7 @@ int gspy_Init() { } // Read the config, resolve the name if needed and setup the server addresses - cfgpath = Base_directory / gspy_cfgfilename; + cfgpath = cf_LocatePath(gspy_cfgfilename); gspy_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); diff --git a/Descent3/init.cpp b/Descent3/init.cpp index 47ade601..ca31afcf 100644 --- a/Descent3/init.cpp +++ b/Descent3/init.cpp @@ -1465,42 +1465,36 @@ void InitIOSystems(bool editor) { // Init hogfiles INIT_MESSAGE(("Checking for HOG files.")); int d3_hid, extra_hid, sys_hid, extra13_hid; - char fullname[_MAX_PATH]; + std::filesystem::path hog_name; #ifdef DEMO // DAJ d3_hid = cf_OpenLibrary("d3demo.hog"); - ddio_MakePath(fullname, LocalD3Dir, "d3demo.hog", NULL); + hog_name = "d3demo.hog"; #else - ddio_MakePath(fullname, LocalD3Dir, "d3.hog", NULL); + hog_name = "d3.hog"; #endif - d3_hid = cf_OpenLibrary(fullname); + d3_hid = cf_OpenLibrary(hog_name); // JC: Steam release uses extra1.hog instead of extra.hog, so try loading it first // Open this file if it's present for stuff we might add later - ddio_MakePath(fullname, LocalD3Dir, "extra1.hog", NULL); - extra_hid = cf_OpenLibrary(fullname); + extra_hid = cf_OpenLibrary("extra1.hog"); if (extra_hid == 0) { - ddio_MakePath(fullname, LocalD3Dir, "extra.hog", NULL); - extra_hid = cf_OpenLibrary(fullname); + extra_hid = cf_OpenLibrary("extra.hog"); } // JC: Steam release uses extra.hog instead of merc.hog, so try loading it last (so we don't conflict with the above) // Open mercenary hog if it exists - ddio_MakePath(fullname, LocalD3Dir, "merc.hog", NULL); - merc_hid = cf_OpenLibrary(fullname); + merc_hid = cf_OpenLibrary("merc.hog"); if (merc_hid == 0) { - ddio_MakePath(fullname, LocalD3Dir, "extra.hog", NULL); - merc_hid = cf_OpenLibrary(fullname); + merc_hid = cf_OpenLibrary("extra.hog"); } // Open this for extra 1.3 code (Black Pyro, etc) - ddio_MakePath(fullname, LocalD3Dir, "extra13.hog", NULL); - extra13_hid = cf_OpenLibrary(fullname); + extra13_hid = cf_OpenLibrary("extra13.hog"); // last library opened is the first to be searched for dynamic libs, so put // this one at the end to find our newly build script libraries first - ddio_MakePath(fullname, LocalD3Dir, PRIMARY_HOG, NULL); - sys_hid = cf_OpenLibrary(fullname); + sys_hid = cf_OpenLibrary(PRIMARY_HOG); // Check to see if there is a -mission command line option // if there is, attempt to open that hog/mn3 so it can override such diff --git a/Descent3/mmItem.cpp b/Descent3/mmItem.cpp index a211b59a..34292cdf 100644 --- a/Descent3/mmItem.cpp +++ b/Descent3/mmItem.cpp @@ -330,9 +330,7 @@ void mmInterface::Create() { m_movie = NULL; static_menu_background = true; } else { - char filename[_MAX_PATH]; - ddio_MakePath(filename, Base_directory.u8string().c_str(), "movies", "mainmenu", NULL); - m_movie = StartMovie(filename, true); + m_movie = StartMovie("mainmenu", true); if (!m_movie) //[ISB] Didn't find the menu movie? { diff --git a/Descent3/multi_dll_mgr.cpp b/Descent3/multi_dll_mgr.cpp index 4655063c..fe678480 100644 --- a/Descent3/multi_dll_mgr.cpp +++ b/Descent3/multi_dll_mgr.cpp @@ -608,7 +608,7 @@ int LoadMultiDLL(const char *name) { }); // Make the hog filename - lib_name = Base_directory / "online" / name; + lib_name = std::filesystem::path("online") / name; lib_name.replace_extension(".d3c"); // Make the dll filename dll_name = name; diff --git a/cfile/cfile.cpp b/cfile/cfile.cpp index 93709767..ab1a6e09 100644 --- a/cfile/cfile.cpp +++ b/cfile/cfile.cpp @@ -78,6 +78,68 @@ void cf_SetBaseDirectory(const std::filesystem::path &base_directory) { Base_directory = base_directory; } +std::filesystem::path cf_LocatePathCaseInsensitiveHelper(const std::filesystem::path &relative_path) { +#ifdef WIN32 + std::filesystem::path result = Base_directory / relative_path; + if (std::filesystem::exists(result)) { + return result; + } else { + return {}; + } +#else + auto &starting_dir = Base_directory; + // Dumb check, maybe there already all ok? + if (exists((starting_dir / relative_path))) { + return starting_dir / relative_path; + } + + std::filesystem::path result, search_path, search_file; + + search_path = starting_dir / relative_path.parent_path(); + search_file = relative_path.filename(); + + // If directory does not exist, nothing to search. + if (!std::filesystem::is_directory(search_path) || search_file.empty()) { + return {}; + } + + + // Search component in search_path + auto const &it = std::filesystem::directory_iterator(search_path); + + auto found = std::find_if(it, end(it), [&search_file, &search_path, &result](const auto& dir_entry) { + return stricmp(dir_entry.path().filename().u8string().c_str(), search_file.u8string().c_str()) == 0; + }); + + if (found != end(it)) { + // Match, append to result + result = found->path(); + search_path = result; + } else { + // Component not found, mission failed + return {}; + } + + return result; +#endif +} + +/** + * Tries to find a relative path inside of Base_directory. + * + * @param relative_path A relative path that we’ll hopefully find in + * Base_directory. You don’t have to get the capitalization + * of relative_path correct, even on macOS and Linux. + * + * @return If the path is found, an absolute path that’s inside + * Base_directory. Otherwise, a path that probably doesn’t exist + * will be returned. + */ +std::filesystem::path cf_LocatePath(const std::filesystem::path &relative_path) { + ASSERT(("realative_path should be a relative path.", relative_path.is_relative())); + return cf_LocatePathCaseInsensitiveHelper(relative_path); +} + // Generates a cfile error void ThrowCFileError(int type, CFILE *file, const char *msg) { cfe.read_write = type; @@ -92,9 +154,9 @@ static void cf_Close(); static CFILE *open_file_in_lib(const char *filename); // Opens a HOG file. Future calls to cfopen(), etc. will look in this HOG. -// Parameters: libname - the path & filename of the HOG file -// NOTE: libname must be valid for the entire execution of the program. Therefore, it should either -// be a fully-specified path name, or the current directory must not change. +// Parameters: libname - path to the HOG file, relative to Base_directory. +// NOTE: libname must be valid for the entire execution of the program. Therefore, Base_directory +// must not change. // Returns: 0 if error, else library handle that can be used to close the library int cf_OpenLibrary(const std::filesystem::path &libname) { FILE *fp; @@ -106,25 +168,7 @@ int cf_OpenLibrary(const std::filesystem::path &libname) { // allocation library structure std::shared_ptr lib = std::make_shared(); - - // resolve library name - std::filesystem::path resolve_dir = libname.parent_path(); - std::filesystem::path resolve_name = libname; - - if (!resolve_dir.empty()) { - resolve_name = libname.filename(); - } - - std::filesystem::path t_out = cf_FindRealFileNameCaseInsensitive(resolve_name, resolve_dir); - if (t_out.empty()) { - return 0; // CF_NO_FILE - } - // re-assemble - if (!resolve_dir.empty()) - lib->name = resolve_dir / t_out; - else - lib->name = t_out; - + lib->name = cf_LocatePath(libname); fp = fopen(lib->name.u8string().c_str(), "rb"); if (fp == nullptr) { return 0; // CF_NO_FILE; @@ -363,42 +407,6 @@ CFILE *open_file_in_lib(const char *filename) { return nullptr; } -std::filesystem::path cf_FindRealFileNameCaseInsensitive(const std::filesystem::path &relative_path, - const std::filesystem::path &starting_dir) { - // Dumb check, maybe there already all ok? - if (exists((starting_dir / relative_path))) { - return relative_path.filename(); - } - - std::filesystem::path result, search_path, search_file; - - search_path = starting_dir / relative_path.parent_path(); - search_file = relative_path.filename(); - - // If directory does not exist, nothing to search. - if (!std::filesystem::is_directory(search_path) || search_file.empty()) { - return {}; - } - - // Search component in search_path - auto const &it = std::filesystem::directory_iterator(search_path); - - auto found = std::find_if(it, end(it), [&search_file, &search_path, &result](const auto &dir_entry) { - return stricmp(dir_entry.path().filename().u8string().c_str(), search_file.u8string().c_str()) == 0; - }); - - if (found != end(it)) { - // Match, append to result - result = found->path(); - search_path = result; - } else { - // Component not found, mission failed - return {}; - } - - return result.filename(); -} - // look for the file in the specified directory static CFILE *open_file_in_directory(const std::filesystem::path &filename, const char *mode, const std::filesystem::path &directory); @@ -413,9 +421,12 @@ CFILE *open_file_in_directory(const std::filesystem::path &filename, const char if (std::filesystem::is_directory(directory)) { // Make a full path using_filename = directory / filename; - } else { - // no directory specified, so just use filename passed + } else if (filename.is_absolute()) { + // no directory specified, and filename is an absolute path using_filename = filename; + } else { + // no directory specified, and filename is a relative path + using_filename = cf_LocatePath(filename); } // set read or write mode @@ -426,34 +437,8 @@ CFILE *open_file_in_directory(const std::filesystem::path &filename, const char fp = fopen(using_filename.u8string().c_str(), tmode); if (!fp) { -#if defined(POSIX) - // If we tried to open file for reading, assume there maybe case-sensitive files - if (tmode[0] == 'r') { - // Try different cases of the filename - using_filename = cf_FindRealFileNameCaseInsensitive(filename, directory); - if (using_filename.empty()) { - // just give up - return nullptr; - } - - if (std::filesystem::is_directory(directory)) { - // Make a full path - using_filename = directory / using_filename; - } - - fp = fopen(using_filename.u8string().c_str(), tmode); - if (!fp) { - // no dice - return nullptr; - } - } else { - // Error on writing file - return nullptr; - } -#else - // We on incase-sensitive filesystem, no file means no file. + // File not found return nullptr; -#endif } else { using_filename = filename; } diff --git a/cfile/cfile.h b/cfile/cfile.h index 265915df..e49ea579 100644 --- a/cfile/cfile.h +++ b/cfile/cfile.h @@ -148,13 +148,24 @@ extern std::filesystem::path Base_directory; */ void cf_SetBaseDirectory(const std::filesystem::path &base_directory); +/** + * Tries to find a relative path inside of Base_directory. + * + * @param relative_path A relative path that we’ll hopefully find in + * Base_directory. You don’t have to get the capitalization + * of relative_path correct, even on macOS and Linux. + * + * @return An absolute path that’s inside Base_directory. + */ +std::filesystem::path cf_LocatePath(const std::filesystem::path &relative_path); + // See if a file is in a hog bool cf_IsFileInHog(const std::filesystem::path &filename, const std::filesystem::path &hogname); // Opens a HOG file. Future calls to cfopen(), etc. will look in this HOG. -// Parameters: libname - the path & filename of the HOG file -// NOTE: libname must be valid for the entire execution of the program. Therefore, it should either -// be a fully-specified path name, or the current directory must not change. +// Parameters: libname - path to the HOG file, relative to Base_directory. +// NOTE: libname must be valid for the entire execution of the program. Therefore, Base_directory +// must not change. // Returns: 0 if error, else library handle that can be used to close the library int cf_OpenLibrary(const std::filesystem::path &libname); @@ -162,17 +173,6 @@ int cf_OpenLibrary(const std::filesystem::path &libname); // Parameters: handle: the handle returned by cf_OpenLibrary() void cf_CloseLibrary(int handle); -/** - * Returns fixed case file name to actual case on disk for case-sensitive filesystems (Linux). - * @param relative_path the fixed case name to map to reality - * @param starting_dir optional directory to search within (default - current path) - * @return filename with actual case name or empty path if there no mapping in filesystem - * @note This function returns only filename without directory part, i.e. - * cf_FindRealFileNameCaseInsensitive("test/test.txt") will return only "test.txt" on success. - */ -std::filesystem::path cf_FindRealFileNameCaseInsensitive(const std::filesystem::path &relative_path, - const std::filesystem::path &starting_dir = "."); - /** * Add directory path into paths to look in for files. If ext_list is empty, * look in this directory for all files. Otherwise, the directory will only diff --git a/cfile/tests/cfile_tests.cpp b/cfile/tests/cfile_tests.cpp index 10b64d89..3ca94f0d 100644 --- a/cfile/tests/cfile_tests.cpp +++ b/cfile/tests/cfile_tests.cpp @@ -76,55 +76,41 @@ TEST(D3, CFileLibrary) { EXPECT_EQ(file_handle, nullptr); } -TEST(D3, CFileCaseSensitiveSearchNew) { +TEST(D3, CFileLocatePath) { const std::vector test_paths = { std::filesystem::path("TestDir") / "CamelCase.txt", std::filesystem::path("TestDir") / "lowercase.txt", std::filesystem::path("TestDir") / "UPPERCASE.TXT", }; - std::filesystem::path filename_new = cf_FindRealFileNameCaseInsensitive("no-exist-file.txt", "no-exist-dir"); + std::filesystem::path filename_new = cf_LocatePath(std::filesystem::path("no-exist-dir") / "no-exist-file.txt"); EXPECT_TRUE(filename_new.empty()); - filename_new = cf_FindRealFileNameCaseInsensitive("no-exist-file.txt"); + filename_new = cf_LocatePath("no-exist-file.txt"); EXPECT_TRUE(filename_new.empty()); auto cwd = std::filesystem::current_path(); for (auto const &item : test_paths) { auto directory = cwd / item.parent_path(); + cf_SetBaseDirectory(directory); std::filesystem::path file = item.filename(); std::string file_lc = item.filename().u8string(); std::transform(file_lc.begin(), file_lc.end(), file_lc.begin(), ::tolower); std::string file_uc = item.filename().u8string(); std::transform(file_uc.begin(), file_uc.end(), file_uc.begin(), ::toupper); - EXPECT_FALSE(cf_FindRealFileNameCaseInsensitive(file_lc, directory).empty()); - EXPECT_FALSE(cf_FindRealFileNameCaseInsensitive(file_uc, directory).empty()); + EXPECT_FALSE(cf_LocatePath(file_lc).empty()); + EXPECT_FALSE(cf_LocatePath(file_uc).empty()); - EXPECT_FALSE(cf_FindRealFileNameCaseInsensitive(directory / file_lc).empty()); - EXPECT_FALSE(cf_FindRealFileNameCaseInsensitive(directory / file_uc).empty()); - - // Now try case-insensitive path with non-existing directory in search. + // Now try case-insensitive path with non-existing path. // Expected not found on case-sensitive fs. file_lc = item.u8string(); std::transform(file_lc.begin(), file_lc.end(), file_lc.begin(), ::tolower); file_uc = item.u8string(); std::transform(file_uc.begin(), file_uc.end(), file_uc.begin(), ::toupper); - if (std::filesystem::is_regular_file(file_lc)) { - EXPECT_FALSE(cf_FindRealFileNameCaseInsensitive(file_lc, cwd).empty()); - EXPECT_FALSE(cf_FindRealFileNameCaseInsensitive(file_lc).empty()); - } else { - EXPECT_TRUE(cf_FindRealFileNameCaseInsensitive(file_lc, cwd).empty()); - EXPECT_TRUE(cf_FindRealFileNameCaseInsensitive(file_lc).empty()); - } - if (std::filesystem::is_regular_file(file_uc)) { - EXPECT_FALSE(cf_FindRealFileNameCaseInsensitive(file_uc, cwd).empty()); - EXPECT_FALSE(cf_FindRealFileNameCaseInsensitive(file_uc).empty()); - } else { - EXPECT_TRUE(cf_FindRealFileNameCaseInsensitive(file_uc, cwd).empty()); - EXPECT_TRUE(cf_FindRealFileNameCaseInsensitive(file_uc).empty()); - } + EXPECT_TRUE(cf_LocatePath(file_lc).empty()); + EXPECT_TRUE(cf_LocatePath(file_uc).empty()); } } diff --git a/module/module.cpp b/module/module.cpp index 6442b854..121b6907 100644 --- a/module/module.cpp +++ b/module/module.cpp @@ -183,8 +183,8 @@ bool mod_LoadModule(module *handle, const std::filesystem::path &imodfilename, i handle->handle = dlopen(modfilename.u8string().c_str(), f); if (!handle->handle) { // ok we couldn't find the given name...try other ways - std::filesystem::path parent_path = modfilename.parent_path(); - std::filesystem::path new_filename = cf_FindRealFileNameCaseInsensitive(modfilename.filename(), parent_path); + std::filesystem::path parent_path = modfilename.parent_path().filename(); + std::filesystem::path new_filename = cf_LocatePath(parent_path / modfilename.filename()); if (new_filename.empty()) { LOG_ERROR.printf("Module Load Err: %s", dlerror());