From ca268ecb2cb548e3826da0908e7acaecdaeedc6f Mon Sep 17 00:00:00 2001 From: Alexander Batalov Date: Sat, 3 Jun 2023 08:14:19 +0300 Subject: [PATCH] Fix global scripts on non-Windows platforms --- src/dfile.cc | 31 ++++++++++++++++++++++++++++--- src/sfall_global_scripts.cc | 16 ++++++++++------ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/dfile.cc b/src/dfile.cc index 52be55e..39d857e 100644 --- a/src/dfile.cc +++ b/src/dfile.cc @@ -43,6 +43,8 @@ static int dfileReadCharInternal(DFile* stream); static bool dfileReadCompressed(DFile* stream, void* ptr, size_t size); static void dfileUngetCompressed(DFile* stream, int ch); +static void dfile_normalize_path(char* path); + // Reads .DAT file contents. // // 0x4E4F58 @@ -122,6 +124,9 @@ DBase* dbaseOpen(const char* filePath) entry->path[pathLength] = '\0'; + // CE: Normalize entry path. + dfile_normalize_path(entry->path); + if (fread(&(entry->compressed), sizeof(entry->compressed), 1, stream) != 1) { break; } @@ -201,11 +206,18 @@ bool dbaseClose(DBase* dbase) // 0x4E5308 bool dbaseFindFirstEntry(DBase* dbase, DFileFindData* findFileData, const char* pattern) { + // CE: Normalize pattern to match entries. Underlying `fpattern` + // implementation is case-sensitive on non-Windows platforms, so both + // pattern and entries should match in case and have native path separators. + char normalizedPattern[COMPAT_MAX_PATH]; + strcpy(normalizedPattern, pattern); + dfile_normalize_path(normalizedPattern); + for (int index = 0; index < dbase->entriesLength; index++) { DBaseEntry* entry = &(dbase->entries[index]); - if (fpattern_match(pattern, entry->path)) { + if (fpattern_match(normalizedPattern, entry->path)) { strcpy(findFileData->fileName, entry->path); - strcpy(findFileData->pattern, pattern); + strcpy(findFileData->pattern, normalizedPattern); findFileData->index = index; return true; } @@ -632,7 +644,14 @@ static int dbaseFindEntryByFilePath(const void* a1, const void* a2) // 0x4E5D9C static DFile* dfileOpenInternal(DBase* dbase, const char* filePath, const char* mode, DFile* dfile) { - DBaseEntry* entry = (DBaseEntry*)bsearch(filePath, dbase->entries, dbase->entriesLength, sizeof(*dbase->entries), dbaseFindEntryByFilePath); + // CE: Normalize path to match entries. Even though + // `dbaseFindEntryByFilePath` uses case-insensitive compare, it still needs + // native path separators. + char normalizedFilePath[COMPAT_MAX_PATH]; + strcpy(normalizedFilePath, filePath); + dfile_normalize_path(normalizedFilePath); + + DBaseEntry* entry = (DBaseEntry*)bsearch(normalizedFilePath, dbase->entries, dbase->entriesLength, sizeof(*dbase->entries), dbaseFindEntryByFilePath); if (entry == NULL) { goto err; } @@ -854,4 +873,10 @@ static void dfileUngetCompressed(DFile* stream, int ch) stream->position--; } +static void dfile_normalize_path(char* path) +{ + compat_windows_path_to_native(path); + compat_strlwr(path); +} + } // namespace fallout diff --git a/src/sfall_global_scripts.cc b/src/sfall_global_scripts.cc index 067d4fb..c6ff320 100644 --- a/src/sfall_global_scripts.cc +++ b/src/sfall_global_scripts.cc @@ -46,17 +46,21 @@ bool sfall_gl_scr_init() *end = '\0'; } - char drive[COMPAT_MAX_DRIVE]; - char dir[COMPAT_MAX_DIR]; - compat_splitpath(curr, drive, dir, nullptr, nullptr); + char path[COMPAT_MAX_PATH]; + strcpy(path, curr); + + char *fname = strrchr(path, '\\'); + if (fname != nullptr) { + fname += 1; + } else { + fname = path; + } char** files; int filesLength = fileNameListInit(curr, &files, 0, 0); if (filesLength != 0) { for (int index = 0; index < filesLength; index++) { - char path[COMPAT_MAX_PATH]; - compat_makepath(path, drive, dir, files[index], nullptr); - + strcpy(fname, files[index]); state->paths.push_back(std::string { path }); }