From df2ce202c96dce0835c7c3a09735b0393f1c79f4 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Sun, 26 Jul 2026 17:19:44 +0200 Subject: [PATCH 1/8] refactor(filesystem): Remove obsolete allocation in Win32BIGFileSystem::openArchiveFile() (#3376) (cherry picked from commit 86f2cab5434fab3de07a33e16c995a0b62a2542b) --- .../StdDevice/Common/StdBIGFileSystem.cpp | 20 ++++++++---------- .../Win32Device/Common/Win32BIGFileSystem.cpp | 21 +++++++------------ 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp b/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp index ffd0150f4c5..0fb035e0c3e 100644 --- a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp +++ b/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp @@ -128,7 +128,8 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) { // seek to the beginning of the directory listing. fp->seek(0x10, File::START); // read in each directory listing. - ArchivedFileInfo *fileInfo = NEW ArchivedFileInfo; + ArchivedFileInfo fileInfo; + ArchiveFile *archiveFile = NEW StdBIGFile(filename, AsciiString::TheEmptyString); for (Int i = 0; i < numLittleFiles; ++i) { Int filesize = 0; @@ -139,9 +140,9 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) { filesize = betoh(filesize); fileOffset = betoh(fileOffset); - fileInfo->m_archiveFilename = archiveFileName; - fileInfo->m_offset = fileOffset; - fileInfo->m_size = filesize; + fileInfo.m_archiveFilename = archiveFileName; + fileInfo.m_offset = fileOffset; + fileInfo.m_size = filesize; // read in the path name of the file. Int pathIndex = -1; @@ -155,8 +156,8 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) { --filenameIndex; } - fileInfo->m_filename = (char *)(buffer + filenameIndex + 1); - fileInfo->m_filename.toLower(); + fileInfo.m_filename = (char *)(buffer + filenameIndex + 1); + fileInfo.m_filename.toLower(); buffer[filenameIndex + 1] = 0; AsciiString path; @@ -164,17 +165,14 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) { AsciiString debugpath; debugpath = path; - debugpath.concat(fileInfo->m_filename); + debugpath.concat(fileInfo.m_filename); // DEBUG_LOG(("StdBIGFileSystem::openArchiveFile - adding file %s to archive file %s, file number %d", debugpath.str(), fileInfo->m_archiveFilename.str(), i)); - archiveFile->addFile(path, fileInfo); + archiveFile->addFile(path, &fileInfo); } archiveFile->attachFile(fp); - delete fileInfo; - fileInfo = nullptr; - // leave fp open as the archive file will be using it. return archiveFile; diff --git a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp b/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp index b824dcaed57..004e393ec02 100644 --- a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp +++ b/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp @@ -137,8 +137,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { // seek to the beginning of the directory listing. fp->seek(0x10, File::START); // read in each directory listing. - ArchivedFileInfo *fileInfo = NEW ArchivedFileInfo; - // TheSuperHackers @fix Mauller 23/04/2025 Create new file handle when necessary to prevent memory leak + ArchivedFileInfo fileInfo; ArchiveFile *archiveFile = NEW Win32BIGFile(filename, AsciiString::TheEmptyString); Bool corrupt = FALSE; @@ -153,9 +152,9 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { filesize = betoh(filesize); fileOffset = betoh(fileOffset); - fileInfo->m_archiveFilename = archiveFileName; - fileInfo->m_offset = fileOffset; - fileInfo->m_size = filesize; + fileInfo.m_archiveFilename = archiveFileName; + fileInfo.m_offset = fileOffset; + fileInfo.m_size = filesize; // read in the path name of the file. // the name must terminate within the buffer @@ -179,8 +178,8 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { --filenameIndex; } - fileInfo->m_filename = (char *)(buffer + filenameIndex + 1); - fileInfo->m_filename.toLower(); + fileInfo.m_filename = (char *)(buffer + filenameIndex + 1); + fileInfo.m_filename.toLower(); buffer[filenameIndex + 1] = 0; AsciiString path; @@ -188,16 +187,15 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { AsciiString debugpath; debugpath = path; - debugpath.concat(fileInfo->m_filename); + debugpath.concat(fileInfo.m_filename); // DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - adding file %s to archive file %s, file number %d", debugpath.str(), fileInfo->m_archiveFilename.str(), i)); - archiveFile->addFile(path, fileInfo); + archiveFile->addFile(path, &fileInfo); } if (corrupt) { DEBUG_CRASH(("Truncated or corrupt directory in BIG file %s", filename)); delete archiveFile; - delete fileInfo; fp->close(); fp = nullptr; return nullptr; @@ -205,9 +203,6 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { archiveFile->attachFile(fp); - delete fileInfo; - fileInfo = nullptr; - // leave fp open as the archive file will be using it. return archiveFile; From b6289ec5e962d5d8ed06503de166f23f2a26306e Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Sun, 26 Jul 2026 15:58:22 +0200 Subject: [PATCH 2/8] refactor(archive): Simplify code in ArchiveFile (#3376) (cherry picked from commit 5db4f7598b13955076fe37991a613b8906ea1a6a) --- Core/GameEngine/Include/Common/ArchiveFile.h | 5 ++- .../Include/Common/ArchiveFileSystem.h | 4 +- .../Source/Common/System/ArchiveFile.cpp | 42 +++++++------------ 3 files changed, 21 insertions(+), 30 deletions(-) diff --git a/Core/GameEngine/Include/Common/ArchiveFile.h b/Core/GameEngine/Include/Common/ArchiveFile.h index 63987f9c9cb..4ea8f0c3214 100644 --- a/Core/GameEngine/Include/Common/ArchiveFile.h +++ b/Core/GameEngine/Include/Common/ArchiveFile.h @@ -60,13 +60,16 @@ class ArchiveFile void attachFile(File *file); void getFileListInDirectory(const AsciiString& currentDirectory, const AsciiString& originalDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const; - void getFileListInDirectory(const DetailedArchivedDirectoryInfo *dirInfo, const AsciiString& currentDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const; void addFile(const AsciiString& path, const ArchivedFileInfo *fileInfo); ///< add this file to our directory tree. protected: + void getFileListInDirectory(const DetailedArchivedDirectoryInfo *dirInfo, const AsciiString& currentDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const; const ArchivedFileInfo * getArchivedFileInfo(const AsciiString& filename) const; ///< return the ArchivedFileInfo from the directory tree. +protected: File *m_file; ///< file pointer to the archive file on disk. Kept open so we don't have to continuously open and close the file all the time. + +private: DetailedArchivedDirectoryInfo m_rootDirectory; }; diff --git a/Core/GameEngine/Include/Common/ArchiveFileSystem.h b/Core/GameEngine/Include/Common/ArchiveFileSystem.h index 48d144484c6..5583290bce0 100644 --- a/Core/GameEngine/Include/Common/ArchiveFileSystem.h +++ b/Core/GameEngine/Include/Common/ArchiveFileSystem.h @@ -143,9 +143,6 @@ class ArchiveFileSystem : public SubsystemInterface virtual Bool loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite = FALSE) = 0; - // Unprotected this for copy-protection routines - ArchiveFile* getArchiveFile(const AsciiString& filename, FileInstance instance = 0) const; - void loadMods(); ArchivedDirectoryInfo* friend_getArchivedDirectoryInfo(const Char* directory); @@ -160,6 +157,7 @@ class ArchiveFileSystem : public SubsystemInterface AsciiString lastToken; ///< Synonymous for file name if the search directory was a file path }; + ArchiveFile* getArchiveFile(const AsciiString& filename, FileInstance instance = 0) const; ArchivedDirectoryInfoResult getArchivedDirectoryInfo(const Char* directory); virtual void loadIntoDirectoryTree(ArchiveFile *archiveFile, Bool overwrite = FALSE, Bool sortedByName = FALSE); ///< load the archive file's header information and apply it to the global archive directory tree. sortedByName inserts by archive filename order (addon number convention), ignoring overwrite. diff --git a/Core/GameEngine/Source/Common/System/ArchiveFile.cpp b/Core/GameEngine/Source/Common/System/ArchiveFile.cpp index 1f982b65a1d..8ca721021d4 100644 --- a/Core/GameEngine/Source/Common/System/ArchiveFile.cpp +++ b/Core/GameEngine/Source/Common/System/ArchiveFile.cpp @@ -106,13 +106,11 @@ void ArchiveFile::addFile(const AsciiString& path, const ArchivedFileInfo *fileI while (!token.isEmpty()) { DetailedArchivedDirectoryInfoMap::iterator tempiter = dirInfo->m_directories.find(token); - if (tempiter == dirInfo->m_directories.end()) - { + if (tempiter == dirInfo->m_directories.end()) { dirInfo = &(dirInfo->m_directories[token]); dirInfo->m_directoryName = token; } - else - { + else { dirInfo = &tempiter->second; } @@ -132,18 +130,12 @@ void ArchiveFile::getFileListInDirectory(const AsciiString& currentDirectory, co tokenizer.nextToken(&token, "\\/"); while (!token.isEmpty()) { - DetailedArchivedDirectoryInfoMap::const_iterator it = dirInfo->m_directories.find(token); - if (it != dirInfo->m_directories.end()) - { - dirInfo = &it->second; - } - else - { - // if the directory doesn't exist, then there aren't any files to be had. + // if the directory doesn't exist, then there aren't any files to be had. + if (it == dirInfo->m_directories.end()) return; - } + dirInfo = &it->second; tokenizer.nextToken(&token, "\\/"); } @@ -153,33 +145,31 @@ void ArchiveFile::getFileListInDirectory(const AsciiString& currentDirectory, co void ArchiveFile::getFileListInDirectory(const DetailedArchivedDirectoryInfo *dirInfo, const AsciiString& currentDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const { DetailedArchivedDirectoryInfoMap::const_iterator diriter = dirInfo->m_directories.begin(); - while (diriter != dirInfo->m_directories.end()) { + for (; diriter != dirInfo->m_directories.end(); ++diriter) { const DetailedArchivedDirectoryInfo *tempDirInfo = &(diriter->second); - AsciiString tempdirname; - tempdirname = currentDirectory; - if ((!tempdirname.isEmpty()) && (!tempdirname.endsWith("\\"))) { - tempdirname.concat('\\'); + AsciiString tempDirName = currentDirectory; + if (!tempDirName.isEmpty() && !tempDirName.endsWith("\\")) { + tempDirName.concat('\\'); } - tempdirname.concat(tempDirInfo->m_directoryName); - getFileListInDirectory(tempDirInfo, tempdirname, searchName, filenameList, searchSubdirectories); - diriter++; + tempDirName.concat(tempDirInfo->m_directoryName); + getFileListInDirectory(tempDirInfo, tempDirName, searchName, filenameList, searchSubdirectories); } ArchivedFileInfoMap::const_iterator fileiter = dirInfo->m_files.begin(); - while (fileiter != dirInfo->m_files.end()) { - if (SearchStringMatches(fileiter->second.m_filename, searchName)) { + for (; fileiter != dirInfo->m_files.end(); ++fileiter) { + const ArchivedFileInfo &fileInfo = fileiter->second; + if (SearchStringMatches(fileInfo.m_filename, searchName)) { AsciiString tempfilename; tempfilename = currentDirectory; - if ((!tempfilename.isEmpty()) && (!tempfilename.endsWith("\\"))) { + if (!tempfilename.isEmpty() && !tempfilename.endsWith("\\")) { tempfilename.concat('\\'); } - tempfilename.concat(fileiter->second.m_filename); + tempfilename.concat(fileInfo.m_filename); if (filenameList.find(tempfilename) == filenameList.end()) { // only insert into the list if its not already in there. filenameList.insert(tempfilename); } } - fileiter++; } } From 4f23667b4bc0527140a68d07b4a9b5717b176e9d Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Sun, 27 Sep 2026 10:48:26 +0200 Subject: [PATCH 3/8] fix(filesystem): Fix file path tokenization in ArchiveFile, ArchiveFileSystem, Win32LocalFileSystem (#3374) (cherry picked from commit 3f3ed9fc8cf2eeaa722d1533ea069257563ccf79) --- Core/GameEngine/Source/Common/System/ArchiveFile.cpp | 2 +- .../Source/Common/System/ArchiveFileSystem.cpp | 12 ++++++------ .../Win32Device/Common/Win32LocalFileSystem.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/GameEngine/Source/Common/System/ArchiveFile.cpp b/Core/GameEngine/Source/Common/System/ArchiveFile.cpp index 8ca721021d4..798e3ac841e 100644 --- a/Core/GameEngine/Source/Common/System/ArchiveFile.cpp +++ b/Core/GameEngine/Source/Common/System/ArchiveFile.cpp @@ -191,7 +191,7 @@ const ArchivedFileInfo * ArchiveFile::getArchivedFileInfo(const AsciiString& fil tokenizer.toLower(); tokenizer.nextToken(&token, "\\/"); - while (!token.find('.') || tokenizer.find('.')) + while (!tokenizer.isEmpty()) { DetailedArchivedDirectoryInfoMap::const_iterator it = dirInfo->m_directories.find(token); if (it != dirInfo->m_directories.end()) diff --git a/Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp b/Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp index 5720c5b9417..17d49e8b372 100644 --- a/Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp +++ b/Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp @@ -144,9 +144,9 @@ void ArchiveFileSystem::loadIntoDirectoryTree(ArchiveFile *archiveFile, Bool ove AsciiString token; AsciiString tokenizer = *it; tokenizer.toLower(); - Bool infoInPath = tokenizer.nextToken(&token, "\\/"); + tokenizer.nextToken(&token, "\\/"); - while (infoInPath && (!token.find('.') || tokenizer.find('.'))) + while (!tokenizer.isEmpty()) { path.concat(token); path.concat('\\'); @@ -163,7 +163,7 @@ void ArchiveFileSystem::loadIntoDirectoryTree(ArchiveFile *archiveFile, Bool ove dirInfo = &tempiter->second; } - infoInPath = tokenizer.nextToken(&token, "\\/"); + tokenizer.nextToken(&token, "\\/"); } ArchivedFileLocationMap::iterator fileIt; @@ -306,15 +306,15 @@ ArchiveFileSystem::ArchivedDirectoryInfoResult ArchiveFileSystem::getArchivedDir AsciiString token; AsciiString tokenizer = directory; tokenizer.toLower(); - Bool infoInPath = tokenizer.nextToken(&token, "\\/"); + tokenizer.nextToken(&token, "\\/"); - while (infoInPath && (!token.find('.') || tokenizer.find('.'))) + while (!tokenizer.isEmpty()) { ArchivedDirectoryInfoMap::iterator tempiter = dirInfo->m_directories.find(token); if (tempiter != dirInfo->m_directories.end()) { dirInfo = &tempiter->second; - infoInPath = tokenizer.nextToken(&token, "\\/"); + tokenizer.nextToken(&token, "\\/"); } else { diff --git a/Core/GameEngineDevice/Source/Win32Device/Common/Win32LocalFileSystem.cpp b/Core/GameEngineDevice/Source/Win32Device/Common/Win32LocalFileSystem.cpp index 43a6ca5cbdd..a4ddcb6b59f 100644 --- a/Core/GameEngineDevice/Source/Win32Device/Common/Win32LocalFileSystem.cpp +++ b/Core/GameEngineDevice/Source/Win32Device/Common/Win32LocalFileSystem.cpp @@ -60,7 +60,7 @@ File * Win32LocalFileSystem::openFile(const Char *filename, Int access, size_t b AsciiString dirName; string.nextToken(&token, "\\/"); dirName = token; - while ((token.find('.') == nullptr) || (string.find('.') != nullptr)) { + while (!string.isEmpty()) { createDirectory(dirName); string.nextToken(&token, "\\/"); dirName.concat('\\'); From 23749a25f0687ecbb17768351005031535aeba3d Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Mon, 5 Oct 2026 22:32:53 +0200 Subject: [PATCH 4/8] perf(archivefile): Take timestamps from cached file info in Win32BIGFile::getFileInfo(), StdBIGFile::getFileInfo() (#3415) (cherry picked from commit b805c12ee1aedc0a4b241006803b8e04bbf288a6) --- Core/GameEngine/Include/Common/ArchiveFile.h | 1 + Core/GameEngine/Include/Common/FileSystem.h | 8 ++++++++ .../GameEngine/Source/Common/System/ArchiveFile.cpp | 12 ++++++++++++ .../Source/StdDevice/Common/StdBIGFile.cpp | 13 +++++++------ .../Source/StdDevice/Common/StdLocalFileSystem.cpp | 4 ++-- .../Source/Win32Device/Common/Win32BIGFile.cpp | 13 +++++++------ .../Win32Device/Common/Win32LocalFileSystem.cpp | 4 ++-- 7 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Core/GameEngine/Include/Common/ArchiveFile.h b/Core/GameEngine/Include/Common/ArchiveFile.h index 4ea8f0c3214..b9d4e085567 100644 --- a/Core/GameEngine/Include/Common/ArchiveFile.h +++ b/Core/GameEngine/Include/Common/ArchiveFile.h @@ -69,6 +69,7 @@ class ArchiveFile protected: File *m_file; ///< file pointer to the archive file on disk. Kept open so we don't have to continuously open and close the file all the time. + FileInfo m_fileInfo; ///< file info of the archive file on disk. private: DetailedArchivedDirectoryInfo m_rootDirectory; diff --git a/Core/GameEngine/Include/Common/FileSystem.h b/Core/GameEngine/Include/Common/FileSystem.h index 8a8b99a9f8c..75f93caabb5 100644 --- a/Core/GameEngine/Include/Common/FileSystem.h +++ b/Core/GameEngine/Include/Common/FileSystem.h @@ -109,6 +109,14 @@ typedef UnsignedByte FileInstance; struct FileInfo { + FileInfo() + : sizeHigh(0) + , sizeLow(0) + , timestampHigh(0) + , timestampLow(0) + { + } + Int64 size() const { return (Int64)sizeHigh << 32 | sizeLow; } Int64 timestamp() const { return (Int64)timestampHigh << 32 | timestampLow; } diff --git a/Core/GameEngine/Source/Common/System/ArchiveFile.cpp b/Core/GameEngine/Source/Common/System/ArchiveFile.cpp index 798e3ac841e..e5a6e81d329 100644 --- a/Core/GameEngine/Source/Common/System/ArchiveFile.cpp +++ b/Core/GameEngine/Source/Common/System/ArchiveFile.cpp @@ -30,6 +30,7 @@ #include "Common/ArchiveFile.h" #include "Common/ArchiveFileSystem.h" +#include "Common/LocalFileSystem.h" #include "Common/file.h" #include "Common/PerfTimer.h" @@ -179,7 +180,18 @@ void ArchiveFile::attachFile(File *file) m_file->close(); m_file = nullptr; } + m_file = file; + + if (m_file != nullptr) { + if (!TheLocalFileSystem->getFileInfo(m_file->getName(), &m_fileInfo)) { + DEBUG_CRASH(("ArchiveFile::attachFile - Cannot query file info for '%s' unexpectedly", m_file->getName())); + m_fileInfo = FileInfo(); + } + } + else { + m_fileInfo = FileInfo(); + } } const ArchivedFileInfo * ArchiveFile::getArchivedFileInfo(const AsciiString& filename) const diff --git a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFile.cpp b/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFile.cpp index c873b733524..5f063c2869c 100644 --- a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFile.cpp +++ b/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFile.cpp @@ -151,17 +151,18 @@ void StdBIGFile::close() Bool StdBIGFile::getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const { - const ArchivedFileInfo *tempFileInfo = getArchivedFileInfo(filename); + const ArchivedFileInfo *archivedFileInfo = getArchivedFileInfo(filename); - if (tempFileInfo == nullptr) { + if (archivedFileInfo == nullptr) { return FALSE; } - TheLocalFileSystem->getFileInfo(AsciiString(m_file->getName()), fileInfo); - - // fill in the size info. Since the size can't be bigger than a JUNK file, the high Int will always be 0. + // fill in the size info. Since the size can't be bigger than a JUNK file, the high int will always be 0. fileInfo->sizeHigh = 0; - fileInfo->sizeLow = tempFileInfo->m_size; + fileInfo->sizeLow = archivedFileInfo->m_size; + // the timestamp is taken from the archive file. + fileInfo->timestampHigh = m_fileInfo.timestampHigh; + fileInfo->timestampLow = m_fileInfo.timestampLow; return TRUE; } diff --git a/Core/GameEngineDevice/Source/StdDevice/Common/StdLocalFileSystem.cpp b/Core/GameEngineDevice/Source/StdDevice/Common/StdLocalFileSystem.cpp index d47e473f4d2..ee53db20549 100644 --- a/Core/GameEngineDevice/Source/StdDevice/Common/StdLocalFileSystem.cpp +++ b/Core/GameEngineDevice/Source/StdDevice/Common/StdLocalFileSystem.cpp @@ -304,10 +304,10 @@ Bool StdLocalFileSystem::getFileInfo(const AsciiString& filename, FileInfo *file // TODO: fix this to be win compatible (time since 1601) auto time = write_time.time_since_epoch().count(); + fileInfo->sizeHigh = file_size >> 32; + fileInfo->sizeLow = file_size & UINT32_MAX; fileInfo->timestampHigh = time >> 32; fileInfo->timestampLow = time & UINT32_MAX; - fileInfo->sizeHigh = file_size >> 32; - fileInfo->sizeLow = file_size & UINT32_MAX; return TRUE; } diff --git a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFile.cpp b/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFile.cpp index 3deee01fd82..fa21e09a278 100644 --- a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFile.cpp +++ b/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFile.cpp @@ -151,17 +151,18 @@ void Win32BIGFile::close() Bool Win32BIGFile::getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const { - const ArchivedFileInfo *tempFileInfo = getArchivedFileInfo(filename); + const ArchivedFileInfo *archivedFileInfo = getArchivedFileInfo(filename); - if (tempFileInfo == nullptr) { + if (archivedFileInfo == nullptr) { return FALSE; } - TheLocalFileSystem->getFileInfo(AsciiString(m_file->getName()), fileInfo); - - // fill in the size info. Since the size can't be bigger than a JUNK file, the high Int will always be 0. + // fill in the size info. Since the size can't be bigger than a JUNK file, the high int will always be 0. fileInfo->sizeHigh = 0; - fileInfo->sizeLow = tempFileInfo->m_size; + fileInfo->sizeLow = archivedFileInfo->m_size; + // the timestamp is taken from the archive file. + fileInfo->timestampHigh = m_fileInfo.timestampHigh; + fileInfo->timestampLow = m_fileInfo.timestampLow; return TRUE; } diff --git a/Core/GameEngineDevice/Source/Win32Device/Common/Win32LocalFileSystem.cpp b/Core/GameEngineDevice/Source/Win32Device/Common/Win32LocalFileSystem.cpp index a4ddcb6b59f..5ec6fd35680 100644 --- a/Core/GameEngineDevice/Source/Win32Device/Common/Win32LocalFileSystem.cpp +++ b/Core/GameEngineDevice/Source/Win32Device/Common/Win32LocalFileSystem.cpp @@ -194,10 +194,10 @@ Bool Win32LocalFileSystem::getFileInfo(const AsciiString& filename, FileInfo *fi return FALSE; } - fileInfo->timestampHigh = findData.ftLastWriteTime.dwHighDateTime; - fileInfo->timestampLow = findData.ftLastWriteTime.dwLowDateTime; fileInfo->sizeHigh = findData.nFileSizeHigh; fileInfo->sizeLow = findData.nFileSizeLow; + fileInfo->timestampHigh = findData.ftLastWriteTime.dwHighDateTime; + fileInfo->timestampLow = findData.ftLastWriteTime.dwLowDateTime; FindClose(findHandle); From d86bca80f81deb3bf583f476a98d66ba905365e5 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Mon, 5 Oct 2026 20:08:58 +0200 Subject: [PATCH 5/8] refactor(archivefile): Merge Win32BIGFile and StdBIGFile into ArchiveFile (#3505) Both classes are identical apart from their name and contain no platform specific code. Nothing in them depends on the BIG format either: they open a file from an offset and a size inside the archive file. ArchiveFile takes over their functions and is no longer an abstract class. (cherry picked from commit 52a777aa0cc736dfd166c841f2a3ff5adbbe0d50) --- Core/GameEngine/Include/Common/ArchiveFile.h | 20 ++- .../Source/Common/System/ArchiveFile.cpp | 120 ++++++++++++- Core/GameEngineDevice/CMakeLists.txt | 4 - .../Include/StdDevice/Common/StdBIGFile.h | 53 ------ .../Include/Win32Device/Common/Win32BIGFile.h | 53 ------ .../Source/StdDevice/Common/StdBIGFile.cpp | 169 ------------------ .../StdDevice/Common/StdBIGFileSystem.cpp | 3 +- .../Win32Device/Common/Win32BIGFile.cpp | 169 ------------------ .../Win32Device/Common/Win32BIGFileSystem.cpp | 3 +- Generals/Code/GameEngineDevice/CMakeLists.txt | 2 - .../Code/GameEngineDevice/CMakeLists.txt | 2 - 11 files changed, 132 insertions(+), 466 deletions(-) delete mode 100644 Core/GameEngineDevice/Include/StdDevice/Common/StdBIGFile.h delete mode 100644 Core/GameEngineDevice/Include/Win32Device/Common/Win32BIGFile.h delete mode 100644 Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFile.cpp delete mode 100644 Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFile.cpp diff --git a/Core/GameEngine/Include/Common/ArchiveFile.h b/Core/GameEngine/Include/Common/ArchiveFile.h index b9d4e085567..a7e0ed68bfb 100644 --- a/Core/GameEngine/Include/Common/ArchiveFile.h +++ b/Core/GameEngine/Include/Common/ArchiveFile.h @@ -47,16 +47,16 @@ class File; class ArchiveFile { public: - ArchiveFile(); - virtual ~ArchiveFile(); + ArchiveFile(AsciiString name, AsciiString path); + ~ArchiveFile(); - virtual Bool getFileInfo( const AsciiString& filename, FileInfo *fileInfo) const = 0; ///< fill in the fileInfo struct with info about the file requested. - virtual File* openFile( const Char *filename, Int access = 0) = 0; ///< Open the specified file within the archive file - virtual void closeAllFiles() = 0; ///< Close all file opened in this archive file - virtual AsciiString getName() = 0; ///< Returns the name of the archive file - virtual AsciiString getPath() = 0; ///< Returns full path and name of archive file - virtual void setSearchPriority( Int new_priority ) = 0; ///< Set this archive file's search priority - virtual void close() = 0; ///< Close this archive file + Bool getFileInfo( const AsciiString& filename, FileInfo *fileInfo) const; ///< fill in the fileInfo struct with info about the file requested. + File* openFile( const Char *filename, Int access = 0); ///< Open the specified file within the archive file + void closeAllFiles(); ///< Close all file opened in this archive file + AsciiString getName(); ///< Returns the name of the archive file + AsciiString getPath(); ///< Returns full path and name of archive file + void setSearchPriority( Int new_priority ); ///< Set this archive file's search priority + void close(); ///< Close this archive file void attachFile(File *file); void getFileListInDirectory(const AsciiString& currentDirectory, const AsciiString& originalDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const; @@ -70,6 +70,8 @@ class ArchiveFile protected: File *m_file; ///< file pointer to the archive file on disk. Kept open so we don't have to continuously open and close the file all the time. FileInfo m_fileInfo; ///< file info of the archive file on disk. + AsciiString m_name; ///< archive file name + AsciiString m_path; ///< archive file path private: DetailedArchivedDirectoryInfo m_rootDirectory; diff --git a/Core/GameEngine/Source/Common/System/ArchiveFile.cpp b/Core/GameEngine/Source/Common/System/ArchiveFile.cpp index e5a6e81d329..9e0db3f0ee2 100644 --- a/Core/GameEngine/Source/Common/System/ArchiveFile.cpp +++ b/Core/GameEngine/Source/Common/System/ArchiveFile.cpp @@ -32,7 +32,10 @@ #include "Common/ArchiveFileSystem.h" #include "Common/LocalFileSystem.h" #include "Common/file.h" +#include "Common/LocalFile.h" #include "Common/PerfTimer.h" +#include "Common/RAMFile.h" +#include "Common/StreamingArchiveFile.h" // checks to see if str matches searchString. Search string is done in the @@ -90,8 +93,10 @@ ArchiveFile::~ArchiveFile() } } -ArchiveFile::ArchiveFile() +ArchiveFile::ArchiveFile(AsciiString name, AsciiString path) : m_file(nullptr) + , m_name(name) + , m_path(path) { } @@ -229,3 +234,116 @@ const ArchivedFileInfo * ArchiveFile::getArchivedFileInfo(const AsciiString& fil } } + +//============================================================================ +// ArchiveFile::openFile +//============================================================================ + +File* ArchiveFile::openFile( const Char *filename, Int access ) +{ + const ArchivedFileInfo *fileInfo = getArchivedFileInfo(AsciiString(filename)); + + if (fileInfo == nullptr) { + return nullptr; + } + + RAMFile *ramFile = nullptr; + + if (BitIsSet(access, File::STREAMING)) + ramFile = newInstance( StreamingArchiveFile ); + else + ramFile = newInstance( RAMFile ); + + ramFile->deleteOnClose(); + if (ramFile->openFromArchive(m_file, fileInfo->m_filename, fileInfo->m_offset, fileInfo->m_size) == FALSE) { + ramFile->close(); + ramFile = nullptr; + return nullptr; + } + + if ((access & File::WRITE) == 0) { + // requesting read only access. Just return the RAM file. + return ramFile; + } + + // whoever is opening this file wants write access, so copy the file to the local disk + // and return that file pointer. + + constexpr size_t bufferSize = 0; + File *localFile = TheLocalFileSystem->openFile(filename, access, bufferSize); + if (localFile != nullptr) { + ramFile->copyDataToFile(localFile); + } + + ramFile->close(); + ramFile = nullptr; + + return localFile; +} + +//============================================================================ +// ArchiveFile::closeAllFiles +//============================================================================ + +void ArchiveFile::closeAllFiles() +{ + +} + +//============================================================================ +// ArchiveFile::getName +//============================================================================ + +AsciiString ArchiveFile::getName() +{ + return m_name; +} + +//============================================================================ +// ArchiveFile::getPath +//============================================================================ + +AsciiString ArchiveFile::getPath() +{ + return m_path; +} + +//============================================================================ +// ArchiveFile::setSearchPriority +//============================================================================ + +void ArchiveFile::setSearchPriority( Int new_priority ) +{ + +} + +//============================================================================ +// ArchiveFile::close +//============================================================================ + +void ArchiveFile::close() +{ + +} + +//============================================================================ +// ArchiveFile::getFileInfo +//============================================================================ + +Bool ArchiveFile::getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const +{ + const ArchivedFileInfo *archivedFileInfo = getArchivedFileInfo(filename); + + if (archivedFileInfo == nullptr) { + return FALSE; + } + + // fill in the size info. Since the size can't be bigger than a JUNK file, the high int will always be 0. + fileInfo->sizeHigh = 0; + fileInfo->sizeLow = archivedFileInfo->m_size; + // the timestamp is taken from the archive file. + fileInfo->timestampHigh = m_fileInfo.timestampHigh; + fileInfo->timestampLow = m_fileInfo.timestampLow; + + return TRUE; +} diff --git a/Core/GameEngineDevice/CMakeLists.txt b/Core/GameEngineDevice/CMakeLists.txt index 6added5403b..3315487c387 100644 --- a/Core/GameEngineDevice/CMakeLists.txt +++ b/Core/GameEngineDevice/CMakeLists.txt @@ -83,7 +83,6 @@ set(GAMEENGINEDEVICE_SRC # Include/W3DDevice/GameLogic/W3DGameLogic.h # Include/W3DDevice/GameLogic/W3DGhostObject.h # Include/W3DDevice/GameLogic/W3DTerrainLogic.h - Include/Win32Device/Common/Win32BIGFile.h Include/Win32Device/Common/Win32BIGFileSystem.h # Include/Win32Device/Common/Win32GameEngine.h Include/Win32Device/Common/Win32LocalFile.h @@ -186,7 +185,6 @@ set(GAMEENGINEDEVICE_SRC # Source/W3DDevice/GameLogic/W3DGameLogic.cpp # Source/W3DDevice/GameLogic/W3DGhostObject.cpp # Source/W3DDevice/GameLogic/W3DTerrainLogic.cpp - Source/Win32Device/Common/Win32BIGFile.cpp Source/Win32Device/Common/Win32BIGFileSystem.cpp # Source/Win32Device/Common/Win32GameEngine.cpp Source/Win32Device/Common/Win32LocalFile.cpp @@ -200,11 +198,9 @@ set(GAMEENGINEDEVICE_SRC # Add C++ 17 FileSystem implementation for non-VS6 builds if(NOT IS_VS6_BUILD) list(APPEND GAMEENGINEDEVICE_SRC - Include/StdDevice/Common/StdBIGFile.h Include/StdDevice/Common/StdBIGFileSystem.h Include/StdDevice/Common/StdLocalFile.h Include/StdDevice/Common/StdLocalFileSystem.h - Source/StdDevice/Common/StdBIGFile.cpp Source/StdDevice/Common/StdBIGFileSystem.cpp Source/StdDevice/Common/StdLocalFile.cpp Source/StdDevice/Common/StdLocalFileSystem.cpp diff --git a/Core/GameEngineDevice/Include/StdDevice/Common/StdBIGFile.h b/Core/GameEngineDevice/Include/StdDevice/Common/StdBIGFile.h deleted file mode 100644 index 36538853352..00000000000 --- a/Core/GameEngineDevice/Include/StdDevice/Common/StdBIGFile.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////// StdBIGFile.h //////////////////////////////////// -// Stephan Vedder, April 2025 -/////////////////////////////////////////////////////////// - -#pragma once - -#include "Common/ArchiveFile.h" -#include "Common/AsciiString.h" -#include "Common/List.h" - -class StdBIGFile : public ArchiveFile -{ - public: - StdBIGFile(AsciiString name, AsciiString path); - virtual ~StdBIGFile() override; - - virtual Bool getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const override; ///< fill in the fileInfo struct with info about the requested file. - virtual File* openFile( const Char *filename, Int access = 0 ) override;///< Open the specified file within the BIG file - virtual void closeAllFiles() override; ///< Close all file opened in this BIG file - virtual AsciiString getName() override; ///< Returns the name of the BIG file - virtual AsciiString getPath() override; ///< Returns full path and name of BIG file - virtual void setSearchPriority( Int new_priority ) override; ///< Set this BIG file's search priority - virtual void close() override; ///< Close this BIG file - - protected: - - AsciiString m_name; ///< BIG file name - AsciiString m_path; ///< BIG file path -}; diff --git a/Core/GameEngineDevice/Include/Win32Device/Common/Win32BIGFile.h b/Core/GameEngineDevice/Include/Win32Device/Common/Win32BIGFile.h deleted file mode 100644 index 093aadbcf4c..00000000000 --- a/Core/GameEngineDevice/Include/Win32Device/Common/Win32BIGFile.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -/////// Win32BIGFile.h //////////////////////////////////// -// Bryan Cleveland, August 2002 -/////////////////////////////////////////////////////////// - -#pragma once - -#include "Common/ArchiveFile.h" -#include "Common/AsciiString.h" -#include "Common/List.h" - -class Win32BIGFile : public ArchiveFile -{ - public: - Win32BIGFile(AsciiString name, AsciiString path); - virtual ~Win32BIGFile() override; - - virtual Bool getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const override; ///< fill in the fileInfo struct with info about the requested file. - virtual File* openFile( const Char *filename, Int access = 0 ) override;///< Open the specified file within the BIG file - virtual void closeAllFiles() override; ///< Close all file opened in this BIG file - virtual AsciiString getName() override; ///< Returns the name of the BIG file - virtual AsciiString getPath() override; ///< Returns full path and name of BIG file - virtual void setSearchPriority( Int new_priority ) override; ///< Set this BIG file's search priority - virtual void close() override; ///< Close this BIG file - - protected: - - AsciiString m_name; ///< BIG file name - AsciiString m_path; ///< BIG file path -}; diff --git a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFile.cpp b/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFile.cpp deleted file mode 100644 index 5f063c2869c..00000000000 --- a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFile.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -////// StdBIGFile.cpp ///////////////////////// -// Stephan Vedder, April 2025 -///////////////////////////////////////////////////// - -#include "Common/LocalFile.h" -#include "Common/LocalFileSystem.h" -#include "Common/RAMFile.h" -#include "Common/StreamingArchiveFile.h" -#include "Common/GameMemory.h" -#include "Common/PerfTimer.h" -#include "StdDevice/Common/StdBIGFile.h" - -//============================================================================ -// StdBIGFile::StdBIGFile -//============================================================================ - -StdBIGFile::StdBIGFile(AsciiString name, AsciiString path) - : m_name(name) - , m_path(path) -{ - -} - -//============================================================================ -// StdBIGFile::~StdBIGFile -//============================================================================ - -StdBIGFile::~StdBIGFile() -{ - -} - -//============================================================================ -// StdBIGFile::openFile -//============================================================================ - -File* StdBIGFile::openFile( const Char *filename, Int access ) -{ - const ArchivedFileInfo *fileInfo = getArchivedFileInfo(AsciiString(filename)); - - if (fileInfo == nullptr) { - return nullptr; - } - - RAMFile *ramFile = nullptr; - - if (BitIsSet(access, File::STREAMING)) - ramFile = newInstance( StreamingArchiveFile ); - else - ramFile = newInstance( RAMFile ); - - ramFile->deleteOnClose(); - if (ramFile->openFromArchive(m_file, fileInfo->m_filename, fileInfo->m_offset, fileInfo->m_size) == FALSE) { - ramFile->close(); - ramFile = nullptr; - return nullptr; - } - - if ((access & File::WRITE) == 0) { - // requesting read only access. Just return the RAM file. - return ramFile; - } - - // whoever is opening this file wants write access, so copy the file to the local disk - // and return that file pointer. - - constexpr size_t bufferSize = 0; - File *localFile = TheLocalFileSystem->openFile(filename, access, bufferSize); - if (localFile != nullptr) { - ramFile->copyDataToFile(localFile); - } - - ramFile->close(); - ramFile = nullptr; - - return localFile; -} - -//============================================================================ -// StdBIGFile::closeAllFiles -//============================================================================ - -void StdBIGFile::closeAllFiles() -{ - -} - -//============================================================================ -// StdBIGFile::getName -//============================================================================ - -AsciiString StdBIGFile::getName() -{ - return m_name; -} - -//============================================================================ -// StdBIGFile::getPath -//============================================================================ - -AsciiString StdBIGFile::getPath() -{ - return m_path; -} - -//============================================================================ -// StdBIGFile::setSearchPriority -//============================================================================ - -void StdBIGFile::setSearchPriority( Int new_priority ) -{ - -} - -//============================================================================ -// StdBIGFile::close -//============================================================================ - -void StdBIGFile::close() -{ - -} - -//============================================================================ -// StdBIGFile::getFileInfo -//============================================================================ - -Bool StdBIGFile::getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const -{ - const ArchivedFileInfo *archivedFileInfo = getArchivedFileInfo(filename); - - if (archivedFileInfo == nullptr) { - return FALSE; - } - - // fill in the size info. Since the size can't be bigger than a JUNK file, the high int will always be 0. - fileInfo->sizeHigh = 0; - fileInfo->sizeLow = archivedFileInfo->m_size; - // the timestamp is taken from the archive file. - fileInfo->timestampHigh = m_fileInfo.timestampHigh; - fileInfo->timestampLow = m_fileInfo.timestampLow; - - return TRUE; -} - diff --git a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp b/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp index 0fb035e0c3e..529f5b03648 100644 --- a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp +++ b/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp @@ -38,7 +38,6 @@ #include "Common/Registry.h" #endif -#include "StdDevice/Common/StdBIGFile.h" #include "StdDevice/Common/StdBIGFileSystem.h" #include "Utility/endian_compat.h" @@ -129,7 +128,7 @@ ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) { fp->seek(0x10, File::START); // read in each directory listing. ArchivedFileInfo fileInfo; - ArchiveFile *archiveFile = NEW StdBIGFile(filename, AsciiString::TheEmptyString); + ArchiveFile *archiveFile = NEW ArchiveFile(filename, AsciiString::TheEmptyString); for (Int i = 0; i < numLittleFiles; ++i) { Int filesize = 0; diff --git a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFile.cpp b/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFile.cpp deleted file mode 100644 index fa21e09a278..00000000000 --- a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFile.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -////// Win32BIGFile.cpp ///////////////////////// -// Bryan Cleveland, August 2002 -///////////////////////////////////////////////////// - -#include "Common/LocalFile.h" -#include "Common/LocalFileSystem.h" -#include "Common/RAMFile.h" -#include "Common/StreamingArchiveFile.h" -#include "Common/GameMemory.h" -#include "Common/PerfTimer.h" -#include "Win32Device/Common/Win32BIGFile.h" - -//============================================================================ -// Win32BIGFile::Win32BIGFile -//============================================================================ - -Win32BIGFile::Win32BIGFile(AsciiString name, AsciiString path) - : m_name(name) - , m_path(path) -{ - -} - -//============================================================================ -// Win32BIGFile::~Win32BIGFile -//============================================================================ - -Win32BIGFile::~Win32BIGFile() -{ - -} - -//============================================================================ -// Win32BIGFile::openFile -//============================================================================ - -File* Win32BIGFile::openFile( const Char *filename, Int access ) -{ - const ArchivedFileInfo *fileInfo = getArchivedFileInfo(AsciiString(filename)); - - if (fileInfo == nullptr) { - return nullptr; - } - - RAMFile *ramFile = nullptr; - - if (BitIsSet(access, File::STREAMING)) - ramFile = newInstance( StreamingArchiveFile ); - else - ramFile = newInstance( RAMFile ); - - ramFile->deleteOnClose(); - if (ramFile->openFromArchive(m_file, fileInfo->m_filename, fileInfo->m_offset, fileInfo->m_size) == FALSE) { - ramFile->close(); - ramFile = nullptr; - return nullptr; - } - - if ((access & File::WRITE) == 0) { - // requesting read only access. Just return the RAM file. - return ramFile; - } - - // whoever is opening this file wants write access, so copy the file to the local disk - // and return that file pointer. - - constexpr size_t bufferSize = 0; - File *localFile = TheLocalFileSystem->openFile(filename, access, bufferSize); - if (localFile != nullptr) { - ramFile->copyDataToFile(localFile); - } - - ramFile->close(); - ramFile = nullptr; - - return localFile; -} - -//============================================================================ -// Win32BIGFile::closeAllFiles -//============================================================================ - -void Win32BIGFile::closeAllFiles() -{ - -} - -//============================================================================ -// Win32BIGFile::getName -//============================================================================ - -AsciiString Win32BIGFile::getName() -{ - return m_name; -} - -//============================================================================ -// Win32BIGFile::getPath -//============================================================================ - -AsciiString Win32BIGFile::getPath() -{ - return m_path; -} - -//============================================================================ -// Win32BIGFile::setSearchPriority -//============================================================================ - -void Win32BIGFile::setSearchPriority( Int new_priority ) -{ - -} - -//============================================================================ -// Win32BIGFile::close -//============================================================================ - -void Win32BIGFile::close() -{ - -} - -//============================================================================ -// Win32BIGFile::getFileInfo -//============================================================================ - -Bool Win32BIGFile::getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const -{ - const ArchivedFileInfo *archivedFileInfo = getArchivedFileInfo(filename); - - if (archivedFileInfo == nullptr) { - return FALSE; - } - - // fill in the size info. Since the size can't be bigger than a JUNK file, the high int will always be 0. - fileInfo->sizeHigh = 0; - fileInfo->sizeLow = archivedFileInfo->m_size; - // the timestamp is taken from the archive file. - fileInfo->timestampHigh = m_fileInfo.timestampHigh; - fileInfo->timestampLow = m_fileInfo.timestampLow; - - return TRUE; -} - diff --git a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp b/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp index 004e393ec02..2159c367728 100644 --- a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp +++ b/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp @@ -38,7 +38,6 @@ #include "Common/Registry.h" #endif -#include "Win32Device/Common/Win32BIGFile.h" #include "Win32Device/Common/Win32BIGFileSystem.h" #include "Utility/endian_compat.h" @@ -138,7 +137,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { fp->seek(0x10, File::START); // read in each directory listing. ArchivedFileInfo fileInfo; - ArchiveFile *archiveFile = NEW Win32BIGFile(filename, AsciiString::TheEmptyString); + ArchiveFile *archiveFile = NEW ArchiveFile(filename, AsciiString::TheEmptyString); Bool corrupt = FALSE; for (Int i = 0; i < numLittleFiles; ++i) { diff --git a/Generals/Code/GameEngineDevice/CMakeLists.txt b/Generals/Code/GameEngineDevice/CMakeLists.txt index dea3ff6c9ae..bedd7c48520 100644 --- a/Generals/Code/GameEngineDevice/CMakeLists.txt +++ b/Generals/Code/GameEngineDevice/CMakeLists.txt @@ -70,7 +70,6 @@ set(GAMEENGINEDEVICE_SRC Include/W3DDevice/GameLogic/W3DGameLogic.h Include/W3DDevice/GameLogic/W3DGhostObject.h Include/W3DDevice/GameLogic/W3DTerrainLogic.h -# Include/Win32Device/Common/Win32BIGFile.h # Include/Win32Device/Common/Win32BIGFileSystem.h Include/Win32Device/Common/Win32GameEngine.h # Include/Win32Device/Common/Win32LocalFile.h @@ -168,7 +167,6 @@ set(GAMEENGINEDEVICE_SRC Source/W3DDevice/GameLogic/W3DGameLogic.cpp Source/W3DDevice/GameLogic/W3DGhostObject.cpp Source/W3DDevice/GameLogic/W3DTerrainLogic.cpp -# Source/Win32Device/Common/Win32BIGFile.cpp # Source/Win32Device/Common/Win32BIGFileSystem.cpp Source/Win32Device/Common/Win32GameEngine.cpp # Source/Win32Device/Common/Win32LocalFile.cpp diff --git a/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt b/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt index 56408e821bd..e8567307646 100644 --- a/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt +++ b/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt @@ -81,7 +81,6 @@ set(GAMEENGINEDEVICE_SRC Include/W3DDevice/GameLogic/W3DGameLogic.h Include/W3DDevice/GameLogic/W3DGhostObject.h Include/W3DDevice/GameLogic/W3DTerrainLogic.h -# Include/Win32Device/Common/Win32BIGFile.h # Include/Win32Device/Common/Win32BIGFileSystem.h Include/Win32Device/Common/Win32GameEngine.h # Include/Win32Device/Common/Win32LocalFile.h @@ -181,7 +180,6 @@ set(GAMEENGINEDEVICE_SRC Source/W3DDevice/GameLogic/W3DGameLogic.cpp Source/W3DDevice/GameLogic/W3DGhostObject.cpp Source/W3DDevice/GameLogic/W3DTerrainLogic.cpp -# Source/Win32Device/Common/Win32BIGFile.cpp # Source/Win32Device/Common/Win32BIGFileSystem.cpp Source/Win32Device/Common/Win32GameEngine.cpp # Source/Win32Device/Common/Win32LocalFile.cpp From 5b1282450bbf6556bcde8c32e7079efa5018ed6a Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Mon, 5 Oct 2026 20:10:57 +0200 Subject: [PATCH 6/8] refactor(archivefilesystem): Merge Win32BIGFileSystem and StdBIGFileSystem into BIGFileSystem (#3505) Both classes are identical apart from their name and go through the local file system for all file access. The one class that remains sits next to ArchiveFileSystem in Core/GameEngine. (cherry picked from commit e4b4d1e9489644ef8d879671c94867ee83dd71ca) --- Core/GameEngine/CMakeLists.txt | 2 + .../Include/Common/BIGFileSystem.h} | 8 +- .../Source/Common/System/BIGFileSystem.cpp} | 42 +-- Core/GameEngineDevice/CMakeLists.txt | 4 - .../StdDevice/Common/StdBIGFileSystem.h | 55 ---- .../StdDevice/Common/StdBIGFileSystem.cpp | 239 ------------------ Core/Tools/Autorun/autorun.cpp | 4 +- Core/Tools/MapCacheBuilder/Source/WinMain.cpp | 5 +- Generals/Code/GameEngineDevice/CMakeLists.txt | 2 - .../Win32Device/Common/Win32GameEngine.h | 4 +- .../Code/Tools/GUIEdit/Source/GUIEdit.cpp | 4 +- .../Tools/WorldBuilder/src/WorldBuilder.cpp | 4 +- .../Code/GameEngineDevice/CMakeLists.txt | 2 - .../Win32Device/Common/Win32GameEngine.h | 4 +- .../Code/Tools/GUIEdit/Source/GUIEdit.cpp | 4 +- .../Tools/WorldBuilder/src/WorldBuilder.cpp | 4 +- 16 files changed, 44 insertions(+), 343 deletions(-) rename Core/{GameEngineDevice/Include/Win32Device/Common/Win32BIGFileSystem.h => GameEngine/Include/Common/BIGFileSystem.h} (91%) rename Core/{GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp => GameEngine/Source/Common/System/BIGFileSystem.cpp} (82%) delete mode 100644 Core/GameEngineDevice/Include/StdDevice/Common/StdBIGFileSystem.h delete mode 100644 Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt index e6aee6da85f..8f5892206e0 100644 --- a/Core/GameEngine/CMakeLists.txt +++ b/Core/GameEngine/CMakeLists.txt @@ -15,6 +15,7 @@ set(GAMEENGINE_SRC # Include/Common/BattleHonors.h # Include/Common/BezFwdIterator.h # Include/Common/BezierSegment.h + Include/Common/BIGFileSystem.h # Include/Common/BitFlags.h # Include/Common/BitFlagsIO.h # Include/Common/BorderColors.h @@ -644,6 +645,7 @@ set(GAMEENGINE_SRC Source/Common/System/ArchiveFile.cpp Source/Common/System/ArchiveFileSystem.cpp Source/Common/System/AsciiString.cpp + Source/Common/System/BIGFileSystem.cpp # Source/Common/System/BuildAssistant.cpp # Source/Common/System/CriticalSection.cpp # Source/Common/System/DataChunk.cpp diff --git a/Core/GameEngineDevice/Include/Win32Device/Common/Win32BIGFileSystem.h b/Core/GameEngine/Include/Common/BIGFileSystem.h similarity index 91% rename from Core/GameEngineDevice/Include/Win32Device/Common/Win32BIGFileSystem.h rename to Core/GameEngine/Include/Common/BIGFileSystem.h index 6819ba90577..602a63e4dd5 100644 --- a/Core/GameEngineDevice/Include/Win32Device/Common/Win32BIGFileSystem.h +++ b/Core/GameEngine/Include/Common/BIGFileSystem.h @@ -22,7 +22,7 @@ // // //////////////////////////////////////////////////////////////////////////////// -//////// Win32BIGFileSystem.h /////////////////////////// +//////// BIGFileSystem.h /////////////////////////// // Bryan Cleveland, August 2002 ///////////////////////////////////////////////////////////// @@ -30,11 +30,11 @@ #include "Common/ArchiveFileSystem.h" -class Win32BIGFileSystem : public ArchiveFileSystem +class BIGFileSystem : public ArchiveFileSystem { public: - Win32BIGFileSystem(); - virtual ~Win32BIGFileSystem() override; + BIGFileSystem(); + virtual ~BIGFileSystem() override; virtual void init() override; virtual void update() override; diff --git a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp b/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp similarity index 82% rename from Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp rename to Core/GameEngine/Source/Common/System/BIGFileSystem.cpp index 2159c367728..6750525f15d 100644 --- a/Core/GameEngineDevice/Source/Win32Device/Common/Win32BIGFileSystem.cpp +++ b/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp @@ -22,13 +22,16 @@ // // //////////////////////////////////////////////////////////////////////////////// -//////// Win32BIGFileSystem.h /////////////////////////// +//////// BIGFileSystem.cpp /////////////////////////// // Bryan Cleveland, August 2002 ///////////////////////////////////////////////////////////// +#include "PreRTS.h" + +#include "Common/BIGFileSystem.h" + #include "Common/AudioAffect.h" #include "Common/ArchiveFile.h" -#include "Common/ArchiveFileSystem.h" #include "Common/file.h" #include "Common/GameAudio.h" #include "Common/GameMemory.h" @@ -38,19 +41,18 @@ #include "Common/Registry.h" #endif -#include "Win32Device/Common/Win32BIGFileSystem.h" #include "Utility/endian_compat.h" static const char *BIGFileIdentifier = "BIGF"; -Win32BIGFileSystem::Win32BIGFileSystem() : ArchiveFileSystem() { +BIGFileSystem::BIGFileSystem() : ArchiveFileSystem() { } -Win32BIGFileSystem::~Win32BIGFileSystem() { +BIGFileSystem::~BIGFileSystem() { } -void Win32BIGFileSystem::init() { +void BIGFileSystem::init() { DEBUG_ASSERTCRASH(TheLocalFileSystem != nullptr, ("TheLocalFileSystem must be initialized before TheArchiveFileSystem.")); if (TheLocalFileSystem == nullptr) { return; @@ -69,16 +71,16 @@ void Win32BIGFileSystem::init() { #endif } -void Win32BIGFileSystem::reset() { +void BIGFileSystem::reset() { } -void Win32BIGFileSystem::update() { +void BIGFileSystem::update() { } -void Win32BIGFileSystem::postProcessLoad() { +void BIGFileSystem::postProcessLoad() { } -ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { +ArchiveFile * BIGFileSystem::openArchiveFile(const Char *filename) { File *fp = TheLocalFileSystem->openFile(filename, File::READ | File::BINARY); AsciiString archiveFileName; archiveFileName = filename; @@ -86,7 +88,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { Int archiveFileSize = 0; Int numLittleFiles = 0; - DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - opening BIG file %s", filename)); + DEBUG_LOG(("BIGFileSystem::openArchiveFile - opening BIG file %s", filename)); if (fp == nullptr) { DEBUG_CRASH(("Could not open archive file %s for parsing", filename)); @@ -112,7 +114,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { return nullptr; } - DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - size of archive file is %d bytes", archiveFileSize)); + DEBUG_LOG(("BIGFileSystem::openArchiveFile - size of archive file is %d bytes", archiveFileSize)); // char t; @@ -126,7 +128,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { } numLittleFiles = betoh(numLittleFiles); - DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - %d are contained in archive", numLittleFiles)); + DEBUG_LOG(("BIGFileSystem::openArchiveFile - %d are contained in archive", numLittleFiles)); // for (Int i = 0; i < 2; ++i) { // t = buffer[i]; // buffer[i] = buffer[(4-i)-1]; @@ -187,7 +189,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { AsciiString debugpath; debugpath = path; debugpath.concat(fileInfo.m_filename); -// DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - adding file %s to archive file %s, file number %d", debugpath.str(), fileInfo->m_archiveFilename.str(), i)); +// DEBUG_LOG(("BIGFileSystem::openArchiveFile - adding file %s to archive file %s, file number %d", debugpath.str(), fileInfo->m_archiveFilename.str(), i)); archiveFile->addFile(path, &fileInfo); } @@ -207,7 +209,7 @@ ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) { return archiveFile; } -void Win32BIGFileSystem::closeArchiveFile(const Char *filename) { +void BIGFileSystem::closeArchiveFile(const Char *filename) { // Need to close the specified big file ArchiveFileMap::iterator it = m_archiveFileMap.find(filename); if (it == m_archiveFileMap.end()) { @@ -228,13 +230,13 @@ void Win32BIGFileSystem::closeArchiveFile(const Char *filename) { m_archiveFileMap.erase(it); } -void Win32BIGFileSystem::closeAllArchiveFiles() { +void BIGFileSystem::closeAllArchiveFiles() { } -void Win32BIGFileSystem::closeAllFiles() { +void BIGFileSystem::closeAllFiles() { } -Bool Win32BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite) { +Bool BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite) { FilenameList filenameList; TheLocalFileSystem->getFileListInDirectory(dir, "", fileMask, filenameList, TRUE); @@ -255,10 +257,10 @@ Bool Win32BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString ArchiveFile *archiveFile = openArchiveFile((*it).str()); if (archiveFile != nullptr) { - DEBUG_LOG(("Win32BIGFileSystem::loadBigFilesFromDirectory - loading %s into the directory tree.", (*it).str())); + DEBUG_LOG(("BIGFileSystem::loadBigFilesFromDirectory - loading %s into the directory tree.", (*it).str())); loadIntoDirectoryTree(archiveFile, overwrite); m_archiveFileMap[(*it)] = archiveFile; - DEBUG_LOG(("Win32BIGFileSystem::loadBigFilesFromDirectory - %s inserted into the archive file map.", (*it).str())); + DEBUG_LOG(("BIGFileSystem::loadBigFilesFromDirectory - %s inserted into the archive file map.", (*it).str())); actuallyAdded = TRUE; } diff --git a/Core/GameEngineDevice/CMakeLists.txt b/Core/GameEngineDevice/CMakeLists.txt index 3315487c387..71933e7c69f 100644 --- a/Core/GameEngineDevice/CMakeLists.txt +++ b/Core/GameEngineDevice/CMakeLists.txt @@ -83,7 +83,6 @@ set(GAMEENGINEDEVICE_SRC # Include/W3DDevice/GameLogic/W3DGameLogic.h # Include/W3DDevice/GameLogic/W3DGhostObject.h # Include/W3DDevice/GameLogic/W3DTerrainLogic.h - Include/Win32Device/Common/Win32BIGFileSystem.h # Include/Win32Device/Common/Win32GameEngine.h Include/Win32Device/Common/Win32LocalFile.h Include/Win32Device/Common/Win32LocalFileSystem.h @@ -185,7 +184,6 @@ set(GAMEENGINEDEVICE_SRC # Source/W3DDevice/GameLogic/W3DGameLogic.cpp # Source/W3DDevice/GameLogic/W3DGhostObject.cpp # Source/W3DDevice/GameLogic/W3DTerrainLogic.cpp - Source/Win32Device/Common/Win32BIGFileSystem.cpp # Source/Win32Device/Common/Win32GameEngine.cpp Source/Win32Device/Common/Win32LocalFile.cpp Source/Win32Device/Common/Win32LocalFileSystem.cpp @@ -198,10 +196,8 @@ set(GAMEENGINEDEVICE_SRC # Add C++ 17 FileSystem implementation for non-VS6 builds if(NOT IS_VS6_BUILD) list(APPEND GAMEENGINEDEVICE_SRC - Include/StdDevice/Common/StdBIGFileSystem.h Include/StdDevice/Common/StdLocalFile.h Include/StdDevice/Common/StdLocalFileSystem.h - Source/StdDevice/Common/StdBIGFileSystem.cpp Source/StdDevice/Common/StdLocalFile.cpp Source/StdDevice/Common/StdLocalFileSystem.cpp ) diff --git a/Core/GameEngineDevice/Include/StdDevice/Common/StdBIGFileSystem.h b/Core/GameEngineDevice/Include/StdDevice/Common/StdBIGFileSystem.h deleted file mode 100644 index b8cb316ab7c..00000000000 --- a/Core/GameEngineDevice/Include/StdDevice/Common/StdBIGFileSystem.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -//////// StdBIGFileSystem.h /////////////////////////// -// Stephan Vedder, April 2025 -///////////////////////////////////////////////////////////// - -#pragma once - -#include "Common/ArchiveFileSystem.h" - -class StdBIGFileSystem : public ArchiveFileSystem -{ -public: - StdBIGFileSystem(); - virtual ~StdBIGFileSystem() override; - - virtual void init() override; - virtual void update() override; - virtual void reset() override; - virtual void postProcessLoad() override; - - // ArchiveFile operations - virtual void closeAllArchiveFiles() override; ///< Close all Archivefiles currently open - - // File operations - virtual ArchiveFile * openArchiveFile(const Char *filename) override; - virtual void closeArchiveFile(const Char *filename) override; - virtual void closeAllFiles() override; ///< Close all files associated with ArchiveFiles - - virtual Bool loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite = FALSE) override; -protected: - -}; diff --git a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp b/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp deleted file mode 100644 index 529f5b03648..00000000000 --- a/Core/GameEngineDevice/Source/StdDevice/Common/StdBIGFileSystem.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** This program is free software: you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program. If not, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -//////// StdBIGFileSystem.h /////////////////////////// -// Stephan Vedder, April 2025 -///////////////////////////////////////////////////////////// - -#include "Common/AudioAffect.h" -#include "Common/ArchiveFile.h" -#include "Common/ArchiveFileSystem.h" -#include "Common/file.h" -#include "Common/GameAudio.h" -#include "Common/GameMemory.h" -#include "Common/LocalFileSystem.h" - -#if RTS_ZEROHOUR -#include "Common/Registry.h" -#endif - -#include "StdDevice/Common/StdBIGFileSystem.h" -#include "Utility/endian_compat.h" - -static const char *BIGFileIdentifier = "BIGF"; - -StdBIGFileSystem::StdBIGFileSystem() : ArchiveFileSystem() { -} - -StdBIGFileSystem::~StdBIGFileSystem() { -} - -void StdBIGFileSystem::init() { - DEBUG_ASSERTCRASH(TheLocalFileSystem != nullptr, ("TheLocalFileSystem must be initialized before TheArchiveFileSystem.")); - if (TheLocalFileSystem == nullptr) { - return; - } - - loadBigFilesFromDirectory("", "*.big"); - -#if RTS_ZEROHOUR - // load original Generals assets - AsciiString installPath; - GetStringFromGeneralsRegistry("", "InstallPath", installPath ); - //@todo this will need to be ramped up to a crash for release - DEBUG_ASSERTCRASH(!installPath.isEmpty(), ("Be 1337! Go install Generals!")); - if (!installPath.isEmpty()) - loadBigFilesFromDirectory(installPath, "*.big"); -#endif -} - -void StdBIGFileSystem::reset() { -} - -void StdBIGFileSystem::update() { -} - -void StdBIGFileSystem::postProcessLoad() { -} - -ArchiveFile * StdBIGFileSystem::openArchiveFile(const Char *filename) { - File *fp = TheLocalFileSystem->openFile(filename, File::READ | File::BINARY); - AsciiString archiveFileName; - archiveFileName = filename; - archiveFileName.toLower(); - Int archiveFileSize = 0; - Int numLittleFiles = 0; - - ArchiveFile *archiveFile = NEW StdBIGFile(filename, AsciiString::TheEmptyString); - - DEBUG_LOG(("StdBIGFileSystem::openArchiveFile - opening BIG file %s", filename)); - - if (fp == nullptr) { - DEBUG_CRASH(("Could not open archive file %s for parsing", filename)); - return nullptr; - } - - AsciiString asciibuf; - char buffer[_MAX_PATH]; - fp->read(buffer, 4); // read the "BIG" at the beginning of the file. - buffer[4] = 0; - if (strcmp(buffer, BIGFileIdentifier) != 0) { - DEBUG_CRASH(("Error reading BIG file identifier in file %s", filename)); - fp->close(); - fp = nullptr; - return nullptr; - } - - // read in the file size. - fp->read(&archiveFileSize, 4); - - DEBUG_LOG(("StdBIGFileSystem::openArchiveFile - size of archive file is %d bytes", archiveFileSize)); - -// char t; - - // read in the number of files contained in this BIG file. - // change the order of the bytes cause the file size is in reverse byte order for some reason. - fp->read(&numLittleFiles, 4); - numLittleFiles = betoh(numLittleFiles); - - DEBUG_LOG(("StdBIGFileSystem::openArchiveFile - %d are contained in archive", numLittleFiles)); -// for (Int i = 0; i < 2; ++i) { -// t = buffer[i]; -// buffer[i] = buffer[(4-i)-1]; -// buffer[(4-i)-1] = t; -// } - - // seek to the beginning of the directory listing. - fp->seek(0x10, File::START); - // read in each directory listing. - ArchivedFileInfo fileInfo; - ArchiveFile *archiveFile = NEW ArchiveFile(filename, AsciiString::TheEmptyString); - - for (Int i = 0; i < numLittleFiles; ++i) { - Int filesize = 0; - Int fileOffset = 0; - fp->read(&fileOffset, 4); - fp->read(&filesize, 4); - - filesize = betoh(filesize); - fileOffset = betoh(fileOffset); - - fileInfo.m_archiveFilename = archiveFileName; - fileInfo.m_offset = fileOffset; - fileInfo.m_size = filesize; - - // read in the path name of the file. - Int pathIndex = -1; - do { - ++pathIndex; - fp->read(buffer + pathIndex, 1); - } while (buffer[pathIndex] != 0); - - Int filenameIndex = pathIndex; - while ((filenameIndex >= 0) && (buffer[filenameIndex] != '\\') && (buffer[filenameIndex] != '/')) { - --filenameIndex; - } - - fileInfo.m_filename = (char *)(buffer + filenameIndex + 1); - fileInfo.m_filename.toLower(); - buffer[filenameIndex + 1] = 0; - - AsciiString path; - path = buffer; - - AsciiString debugpath; - debugpath = path; - debugpath.concat(fileInfo.m_filename); -// DEBUG_LOG(("StdBIGFileSystem::openArchiveFile - adding file %s to archive file %s, file number %d", debugpath.str(), fileInfo->m_archiveFilename.str(), i)); - - archiveFile->addFile(path, &fileInfo); - } - - archiveFile->attachFile(fp); - - // leave fp open as the archive file will be using it. - - return archiveFile; -} - -void StdBIGFileSystem::closeArchiveFile(const Char *filename) { - // Need to close the specified big file - ArchiveFileMap::iterator it = m_archiveFileMap.find(filename); - if (it == m_archiveFileMap.end()) { - return; - } - - if (stricmp(filename, MUSIC_BIG) == 0) { - // Stop the current audio - TheAudio->stopAudio(AudioAffect_Music); - - // No need to turn off other audio, as the lookups will just fail. - } - DEBUG_ASSERTCRASH(stricmp(filename, MUSIC_BIG) == 0, ("Attempting to close Archive file '%s', need to add code to handle its shutdown correctly.", filename)); - - // may need to do some other processing here first. - - delete (it->second); - m_archiveFileMap.erase(it); -} - -void StdBIGFileSystem::closeAllArchiveFiles() { -} - -void StdBIGFileSystem::closeAllFiles() { -} - -Bool StdBIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite) { - - FilenameList filenameList; - TheLocalFileSystem->getFileListInDirectory(dir, "", fileMask, filenameList, TRUE); - - Bool actuallyAdded = FALSE; - FilenameListIter it = filenameList.begin(); - while (it != filenameList.end()) { -#if RTS_ZEROHOUR - // TheSuperHackers @bugfix bobtista 18/11/2025 Skip duplicate INIZH.big in Data\INI to prevent CRC mismatches. - // English, Chinese, and Korean SKUs shipped with two INIZH.big files (one in Run directory, one in Run\Data\INI). - // The DeleteFile cleanup doesn't work on EA App/Origin installs because the folder is not writable, so we skip loading it instead. - if (it->endsWithNoCase("Data\\INI\\INIZH.big") || it->endsWithNoCase("Data/INI/INIZH.big")) { - it++; - continue; - } -#endif - - ArchiveFile *archiveFile = openArchiveFile((*it).str()); - - if (archiveFile != nullptr) { - DEBUG_LOG(("StdBIGFileSystem::loadBigFilesFromDirectory - loading %s into the directory tree.", (*it).str())); - loadIntoDirectoryTree(archiveFile, overwrite); - m_archiveFileMap[(*it)] = archiveFile; - DEBUG_LOG(("StdBIGFileSystem::loadBigFilesFromDirectory - %s inserted into the archive file map.", (*it).str())); - actuallyAdded = TRUE; - } - - it++; - } - - return actuallyAdded; -} diff --git a/Core/Tools/Autorun/autorun.cpp b/Core/Tools/Autorun/autorun.cpp index 2e5a428c2b3..4f3618dcf2a 100644 --- a/Core/Tools/Autorun/autorun.cpp +++ b/Core/Tools/Autorun/autorun.cpp @@ -119,7 +119,7 @@ #include "GameClient/GameText.h" #include "Common/UnicodeString.h" #include "Win32Device/Common/Win32LocalFileSystem.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" +#include "Common/BIGFileSystem.h" #endif //----------------------------------------------------------------------------- @@ -449,7 +449,7 @@ int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpszCmd // create singletons TheFileSystem->init(); TheLocalFileSystem = new Win32LocalFileSystem; - TheArchiveFileSystem = new Win32BIGFileSystem; + TheArchiveFileSystem = new BIGFileSystem; TheGameText = CreateGameTextInterface(); TheGameText->init(); diff --git a/Core/Tools/MapCacheBuilder/Source/WinMain.cpp b/Core/Tools/MapCacheBuilder/Source/WinMain.cpp index ab545a07892..fe7fcf1bc5d 100644 --- a/Core/Tools/MapCacheBuilder/Source/WinMain.cpp +++ b/Core/Tools/MapCacheBuilder/Source/WinMain.cpp @@ -51,8 +51,8 @@ #include "Common/ThingFactory.h" #include "Common/FileSystem.h" +#include "Common/BIGFileSystem.h" #include "Win32Device/Common/Win32LocalFileSystem.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" #include "Common/SubsystemInterface.h" #include "GameClient/MapUtil.h" #include "W3DDevice/Common/W3DModuleFactory.h" @@ -101,7 +101,6 @@ #include #include "Win32Device/GameClient/Win32Mouse.h" #include "Win32Device/Common/Win32LocalFileSystem.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" #include "WWLib/trim.h" @@ -249,7 +248,7 @@ Int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, TheFileSystem = new FileSystem; initSubsystem(TheLocalFileSystem, (LocalFileSystem*)new Win32LocalFileSystem); - initSubsystem(TheArchiveFileSystem, (ArchiveFileSystem*)new Win32BIGFileSystem); + initSubsystem(TheArchiveFileSystem, (ArchiveFileSystem*)new BIGFileSystem); INI ini; initSubsystem(TheWritableGlobalData, new GlobalData(), "Data\\INI\\Default\\GameData.ini", "Data\\INI\\GameData.ini"); initSubsystem(TheGameText, CreateGameTextInterface()); diff --git a/Generals/Code/GameEngineDevice/CMakeLists.txt b/Generals/Code/GameEngineDevice/CMakeLists.txt index bedd7c48520..dbb41d0f7b4 100644 --- a/Generals/Code/GameEngineDevice/CMakeLists.txt +++ b/Generals/Code/GameEngineDevice/CMakeLists.txt @@ -70,7 +70,6 @@ set(GAMEENGINEDEVICE_SRC Include/W3DDevice/GameLogic/W3DGameLogic.h Include/W3DDevice/GameLogic/W3DGhostObject.h Include/W3DDevice/GameLogic/W3DTerrainLogic.h -# Include/Win32Device/Common/Win32BIGFileSystem.h Include/Win32Device/Common/Win32GameEngine.h # Include/Win32Device/Common/Win32LocalFile.h # Include/Win32Device/Common/Win32LocalFileSystem.h @@ -167,7 +166,6 @@ set(GAMEENGINEDEVICE_SRC Source/W3DDevice/GameLogic/W3DGameLogic.cpp Source/W3DDevice/GameLogic/W3DGhostObject.cpp Source/W3DDevice/GameLogic/W3DTerrainLogic.cpp -# Source/Win32Device/Common/Win32BIGFileSystem.cpp Source/Win32Device/Common/Win32GameEngine.cpp # Source/Win32Device/Common/Win32LocalFile.cpp # Source/Win32Device/Common/Win32LocalFileSystem.cpp diff --git a/Generals/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h b/Generals/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h index b17369dc844..01f5b0af14f 100644 --- a/Generals/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h +++ b/Generals/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h @@ -37,7 +37,7 @@ #include "GameLogic/GameLogic.h" #include "GameNetwork/NetworkInterface.h" #include "MilesAudioDevice/MilesAudioManager.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" +#include "Common/BIGFileSystem.h" #include "Win32Device/Common/Win32LocalFileSystem.h" #include "W3DDevice/Common/W3DModuleFactory.h" #include "W3DDevice/GameLogic/W3DGameLogic.h" @@ -93,7 +93,7 @@ inline ModuleFactory *Win32GameEngine::createModuleFactory() { return NEW W3DMod inline ThingFactory *Win32GameEngine::createThingFactory() { return NEW W3DThingFactory; } inline FunctionLexicon *Win32GameEngine::createFunctionLexicon() { return NEW W3DFunctionLexicon; } inline LocalFileSystem *Win32GameEngine::createLocalFileSystem() { return NEW Win32LocalFileSystem; } -inline ArchiveFileSystem *Win32GameEngine::createArchiveFileSystem() { return NEW Win32BIGFileSystem; } +inline ArchiveFileSystem *Win32GameEngine::createArchiveFileSystem() { return NEW BIGFileSystem; } inline ParticleSystemManager* Win32GameEngine::createParticleSystemManager(Bool dummy) { if (dummy) diff --git a/Generals/Code/Tools/GUIEdit/Source/GUIEdit.cpp b/Generals/Code/Tools/GUIEdit/Source/GUIEdit.cpp index 4d18b320cd8..d5c928ff52a 100644 --- a/Generals/Code/Tools/GUIEdit/Source/GUIEdit.cpp +++ b/Generals/Code/Tools/GUIEdit/Source/GUIEdit.cpp @@ -85,7 +85,7 @@ #include "Win32Device/GameClient/Win32Mouse.h" #include "Win32Device/GameClient/Win32DIKeyboard.h" #include "Win32Device/Common/Win32LocalFileSystem.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" +#include "Common/BIGFileSystem.h" #include "resource.h" #include "WinMain.h" @@ -485,7 +485,7 @@ void GUIEdit::init() // create file system TheFileSystem = new FileSystem; TheLocalFileSystem = new Win32LocalFileSystem; - TheArchiveFileSystem = new Win32BIGFileSystem; + TheArchiveFileSystem = new BIGFileSystem; TheFileSystem->init(); //--------------------------------------------------------------------------- diff --git a/Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp b/Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp index b3287235361..9c5421c320d 100644 --- a/Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp @@ -79,7 +79,7 @@ #include #include "Win32Device/GameClient/Win32Mouse.h" #include "Win32Device/Common/Win32LocalFileSystem.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" +#include "Common/BIGFileSystem.h" static SubsystemInterfaceList TheSubsystemListRecord; @@ -316,7 +316,7 @@ BOOL CWorldBuilderApp::InitInstance() TheFileSystem = new FileSystem; initSubsystem(TheLocalFileSystem, (LocalFileSystem*)new Win32LocalFileSystem); - initSubsystem(TheArchiveFileSystem, (ArchiveFileSystem*)new Win32BIGFileSystem); + initSubsystem(TheArchiveFileSystem, (ArchiveFileSystem*)new BIGFileSystem); // Just for kicks, get the HINSTANCE that WOL would need // if we were going to use it, which we aren't. diff --git a/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt b/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt index e8567307646..d251e04bb38 100644 --- a/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt +++ b/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt @@ -81,7 +81,6 @@ set(GAMEENGINEDEVICE_SRC Include/W3DDevice/GameLogic/W3DGameLogic.h Include/W3DDevice/GameLogic/W3DGhostObject.h Include/W3DDevice/GameLogic/W3DTerrainLogic.h -# Include/Win32Device/Common/Win32BIGFileSystem.h Include/Win32Device/Common/Win32GameEngine.h # Include/Win32Device/Common/Win32LocalFile.h # Include/Win32Device/Common/Win32LocalFileSystem.h @@ -180,7 +179,6 @@ set(GAMEENGINEDEVICE_SRC Source/W3DDevice/GameLogic/W3DGameLogic.cpp Source/W3DDevice/GameLogic/W3DGhostObject.cpp Source/W3DDevice/GameLogic/W3DTerrainLogic.cpp -# Source/Win32Device/Common/Win32BIGFileSystem.cpp Source/Win32Device/Common/Win32GameEngine.cpp # Source/Win32Device/Common/Win32LocalFile.cpp # Source/Win32Device/Common/Win32LocalFileSystem.cpp diff --git a/GeneralsMD/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h b/GeneralsMD/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h index 2710cdf4555..e27eb8504c9 100644 --- a/GeneralsMD/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h +++ b/GeneralsMD/Code/GameEngineDevice/Include/Win32Device/Common/Win32GameEngine.h @@ -32,12 +32,12 @@ #pragma once +#include "Common/BIGFileSystem.h" #include "Common/GameEngine.h" #include "GameClient/ParticleSys.h" #include "GameLogic/GameLogic.h" #include "GameNetwork/NetworkInterface.h" #include "MilesAudioDevice/MilesAudioManager.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" #include "Win32Device/Common/Win32LocalFileSystem.h" #include "W3DDevice/Common/W3DModuleFactory.h" #include "W3DDevice/GameLogic/W3DGameLogic.h" @@ -93,7 +93,7 @@ inline ModuleFactory *Win32GameEngine::createModuleFactory() { return NEW W3DMod inline ThingFactory *Win32GameEngine::createThingFactory() { return NEW W3DThingFactory; } inline FunctionLexicon *Win32GameEngine::createFunctionLexicon() { return NEW W3DFunctionLexicon; } inline LocalFileSystem *Win32GameEngine::createLocalFileSystem() { return NEW Win32LocalFileSystem; } -inline ArchiveFileSystem *Win32GameEngine::createArchiveFileSystem() { return NEW Win32BIGFileSystem; } +inline ArchiveFileSystem *Win32GameEngine::createArchiveFileSystem() { return NEW BIGFileSystem; } inline ParticleSystemManager* Win32GameEngine::createParticleSystemManager(Bool dummy) { if (dummy) diff --git a/GeneralsMD/Code/Tools/GUIEdit/Source/GUIEdit.cpp b/GeneralsMD/Code/Tools/GUIEdit/Source/GUIEdit.cpp index 2cbc8ec3ffb..6ecfad34952 100644 --- a/GeneralsMD/Code/Tools/GUIEdit/Source/GUIEdit.cpp +++ b/GeneralsMD/Code/Tools/GUIEdit/Source/GUIEdit.cpp @@ -85,7 +85,7 @@ #include "Win32Device/GameClient/Win32Mouse.h" #include "Win32Device/GameClient/Win32DIKeyboard.h" #include "Win32Device/Common/Win32LocalFileSystem.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" +#include "Common/BIGFileSystem.h" #include "resource.h" #include "WinMain.h" @@ -485,7 +485,7 @@ void GUIEdit::init() // create file system TheFileSystem = new FileSystem; TheLocalFileSystem = new Win32LocalFileSystem; - TheArchiveFileSystem = new Win32BIGFileSystem; + TheArchiveFileSystem = new BIGFileSystem; TheFileSystem->init(); //--------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp index d49589ee0c8..65d2fb82b8f 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp @@ -79,7 +79,7 @@ #include #include "Win32Device/GameClient/Win32Mouse.h" #include "Win32Device/Common/Win32LocalFileSystem.h" -#include "Win32Device/Common/Win32BIGFileSystem.h" +#include "Common/BIGFileSystem.h" static SubsystemInterfaceList TheSubsystemListRecord; @@ -326,7 +326,7 @@ BOOL CWorldBuilderApp::InitInstance() TheFileSystem = new FileSystem; initSubsystem(TheLocalFileSystem, (LocalFileSystem*)new Win32LocalFileSystem); - initSubsystem(TheArchiveFileSystem, (ArchiveFileSystem*)new Win32BIGFileSystem); + initSubsystem(TheArchiveFileSystem, (ArchiveFileSystem*)new BIGFileSystem); // Just for kicks, get the HINSTANCE that WOL would need // if we were going to use it, which we aren't. From b5b3e12b99051e4c64140523e79d1a0a3665072d Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Mon, 5 Oct 2026 20:11:49 +0200 Subject: [PATCH 7/8] refactor(archivefilesystem): Move loadMods to BIGFileSystem and rename loadBigFilesFromDirectory (#3505) loadMods refers to BIG files, which nothing else in ArchiveFileSystem does. It becomes a virtual function that BIGFileSystem implements. loadBigFilesFromDirectory is renamed to loadArchiveFilesFromDirectory, because the base class is not tied to one archive format. (cherry picked from commit f29956197ad5d0e3ebfb44d9a4d2646b4585e5cb) --- .../Include/Common/ArchiveFileSystem.h | 4 +- .../GameEngine/Include/Common/BIGFileSystem.h | 4 +- .../Common/System/ArchiveFileSystem.cpp | 50 ---------------- .../Source/Common/System/BIGFileSystem.cpp | 60 +++++++++++++++++-- 4 files changed, 60 insertions(+), 58 deletions(-) diff --git a/Core/GameEngine/Include/Common/ArchiveFileSystem.h b/Core/GameEngine/Include/Common/ArchiveFileSystem.h index 5583290bce0..ddad61637a6 100644 --- a/Core/GameEngine/Include/Common/ArchiveFileSystem.h +++ b/Core/GameEngine/Include/Common/ArchiveFileSystem.h @@ -141,9 +141,9 @@ class ArchiveFileSystem : public SubsystemInterface void getFileListInDirectory(const AsciiString& currentDirectory, const AsciiString& originalDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const; ///< search the given directory for files matching the searchName (egs. *.ini, *.rep). Possibly search subdirectories. Scans each Archive file. Bool getFileInfo(const AsciiString& filename, FileInfo *fileInfo, FileInstance instance = 0) const; ///< see FileSystem.h - virtual Bool loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite = FALSE) = 0; + virtual Bool loadArchiveFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite = FALSE) = 0; - void loadMods(); + virtual void loadMods() = 0; ArchivedDirectoryInfo* friend_getArchivedDirectoryInfo(const Char* directory); diff --git a/Core/GameEngine/Include/Common/BIGFileSystem.h b/Core/GameEngine/Include/Common/BIGFileSystem.h index 602a63e4dd5..95e20c0ea6c 100644 --- a/Core/GameEngine/Include/Common/BIGFileSystem.h +++ b/Core/GameEngine/Include/Common/BIGFileSystem.h @@ -49,7 +49,9 @@ class BIGFileSystem : public ArchiveFileSystem virtual void closeArchiveFile(const Char *filename) override; virtual void closeAllFiles() override; ///< Close all files associated with ArchiveFiles - virtual Bool loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite = FALSE) override; + virtual Bool loadArchiveFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite = FALSE) override; + + virtual void loadMods() override; protected: }; diff --git a/Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp b/Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp index 17d49e8b372..2322827ef2b 100644 --- a/Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp +++ b/Core/GameEngine/Source/Common/System/ArchiveFileSystem.cpp @@ -51,8 +51,6 @@ #include "Common/AsciiString.h" #include "Common/LocalFileSystem.h" #include "Common/PerfTimer.h" -#include "../NGMP_include.h" -#include "../OnlineServices_Init.h" //---------------------------------------------------------------------------- @@ -231,54 +229,6 @@ void ArchiveFileSystem::loadIntoDirectoryTree(ArchiveFile *archiveFile, Bool ove } } -void ArchiveFileSystem::loadMods() -{ -#if defined(GENERALS_ONLINE) && defined(GENERALS_ONLINE_COMMUNITY_PATCH_CHANGES) - // load community data patch BIG - if (NGMP_OnlineServicesManager::Settings.DataPacks_UseCommunityPatch() - && !TheGlobalData->m_commandLineData.isCommunityDataPatchDisabled()) - { - std::string strBigPath = std::format("{}GeneralsOnlineGameData/500_900_CommunityPatch_CoreINI.big", TheGlobalData->getPath_UserData().str()); - bool bLoaded = false; - if (TheLocalFileSystem->doesFileExist(strBigPath.c_str())) - { - ArchiveFile* archiveFile = openArchiveFile(strBigPath.c_str()); - if (archiveFile != nullptr) - { - // Sorted by filename so the patch respects the addon number order of BIGs in the game folder. - loadIntoDirectoryTree(archiveFile, FALSE, TRUE); - m_archiveFileMap[AsciiString(strBigPath.c_str())] = archiveFile; - bLoaded = true; - } - } - NetworkLog(ELogVerbosity::LOG_RELEASE, "Loaded community patch (%s): %d", strBigPath.c_str(), bLoaded); - } -#endif - - if (TheGlobalData->m_modBIG.isNotEmpty()) - { - ArchiveFile *archiveFile = openArchiveFile(TheGlobalData->m_modBIG.str()); - - if (archiveFile != nullptr) { - DEBUG_LOG(("ArchiveFileSystem::loadMods - loading %s into the directory tree.", TheGlobalData->m_modBIG.str())); - loadIntoDirectoryTree(archiveFile, TRUE); - m_archiveFileMap[TheGlobalData->m_modBIG] = archiveFile; - DEBUG_LOG(("ArchiveFileSystem::loadMods - %s inserted into the archive file map.", TheGlobalData->m_modBIG.str())); - } - else - { - DEBUG_LOG(("ArchiveFileSystem::loadMods - could not openArchiveFile(%s)", TheGlobalData->m_modBIG.str())); - } - } - - if (TheGlobalData->m_modDir.isNotEmpty()) - { - MAYBE_UNUSED Bool ret = loadBigFilesFromDirectory(TheGlobalData->m_modDir, "*.big", TRUE); - (void)ret; - DEBUG_ASSERTLOG(ret, ("loadBigFilesFromDirectory(%s) returned FALSE!", TheGlobalData->m_modDir.str())); - } -} - Bool ArchiveFileSystem::doesFileExist(const Char *filename, FileInstance instance) const { ArchivedDirectoryInfoResult result = const_cast(this)->getArchivedDirectoryInfo(filename); diff --git a/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp b/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp index 6750525f15d..3bd1a29026c 100644 --- a/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp +++ b/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp @@ -42,6 +42,8 @@ #endif #include "Utility/endian_compat.h" +#include "../NGMP_include.h" +#include "../OnlineServices_Init.h" static const char *BIGFileIdentifier = "BIGF"; @@ -58,7 +60,7 @@ void BIGFileSystem::init() { return; } - loadBigFilesFromDirectory("", "*.big"); + loadArchiveFilesFromDirectory("", "*.big"); #if RTS_ZEROHOUR // load original Generals assets @@ -67,7 +69,7 @@ void BIGFileSystem::init() { //@todo this will need to be ramped up to a crash for release DEBUG_ASSERTCRASH(!installPath.isEmpty(), ("Be 1337! Go install Generals!")); if (!installPath.isEmpty()) - loadBigFilesFromDirectory(installPath, "*.big"); + loadArchiveFilesFromDirectory(installPath, "*.big"); #endif } @@ -236,7 +238,7 @@ void BIGFileSystem::closeAllArchiveFiles() { void BIGFileSystem::closeAllFiles() { } -Bool BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite) { +Bool BIGFileSystem::loadArchiveFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite) { FilenameList filenameList; TheLocalFileSystem->getFileListInDirectory(dir, "", fileMask, filenameList, TRUE); @@ -257,10 +259,10 @@ Bool BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileM ArchiveFile *archiveFile = openArchiveFile((*it).str()); if (archiveFile != nullptr) { - DEBUG_LOG(("BIGFileSystem::loadBigFilesFromDirectory - loading %s into the directory tree.", (*it).str())); + DEBUG_LOG(("BIGFileSystem::loadArchiveFilesFromDirectory - loading %s into the directory tree.", (*it).str())); loadIntoDirectoryTree(archiveFile, overwrite); m_archiveFileMap[(*it)] = archiveFile; - DEBUG_LOG(("BIGFileSystem::loadBigFilesFromDirectory - %s inserted into the archive file map.", (*it).str())); + DEBUG_LOG(("BIGFileSystem::loadArchiveFilesFromDirectory - %s inserted into the archive file map.", (*it).str())); actuallyAdded = TRUE; } @@ -269,3 +271,51 @@ Bool BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileM return actuallyAdded; } + +void BIGFileSystem::loadMods() +{ +#if defined(GENERALS_ONLINE) && defined(GENERALS_ONLINE_COMMUNITY_PATCH_CHANGES) + // load community data patch BIG + if (NGMP_OnlineServicesManager::Settings.DataPacks_UseCommunityPatch() + && !TheGlobalData->m_commandLineData.isCommunityDataPatchDisabled()) + { + std::string strBigPath = std::format("{}GeneralsOnlineGameData/500_900_CommunityPatch_CoreINI.big", TheGlobalData->getPath_UserData().str()); + bool bLoaded = false; + if (TheLocalFileSystem->doesFileExist(strBigPath.c_str())) + { + ArchiveFile* archiveFile = openArchiveFile(strBigPath.c_str()); + if (archiveFile != nullptr) + { + // Sorted by filename so the patch respects the addon number order of BIGs in the game folder. + loadIntoDirectoryTree(archiveFile, FALSE, TRUE); + m_archiveFileMap[AsciiString(strBigPath.c_str())] = archiveFile; + bLoaded = true; + } + } + NetworkLog(ELogVerbosity::LOG_RELEASE, "Loaded community patch (%s): %d", strBigPath.c_str(), bLoaded); + } +#endif + + if (TheGlobalData->m_modBIG.isNotEmpty()) + { + ArchiveFile *archiveFile = openArchiveFile(TheGlobalData->m_modBIG.str()); + + if (archiveFile != nullptr) { + DEBUG_LOG(("BIGFileSystem::loadMods - loading %s into the directory tree.", TheGlobalData->m_modBIG.str())); + loadIntoDirectoryTree(archiveFile, TRUE); + m_archiveFileMap[TheGlobalData->m_modBIG] = archiveFile; + DEBUG_LOG(("BIGFileSystem::loadMods - %s inserted into the archive file map.", TheGlobalData->m_modBIG.str())); + } + else + { + DEBUG_LOG(("BIGFileSystem::loadMods - could not openArchiveFile(%s)", TheGlobalData->m_modBIG.str())); + } + } + + if (TheGlobalData->m_modDir.isNotEmpty()) + { + MAYBE_UNUSED Bool ret = loadArchiveFilesFromDirectory(TheGlobalData->m_modDir, "*.big", TRUE); + (void)ret; + DEBUG_ASSERTLOG(ret, ("loadArchiveFilesFromDirectory(%s) returned FALSE!", TheGlobalData->m_modDir.str())); + } +} From 73f827cd4697361b23fb13df31e261a718f5886b Mon Sep 17 00:00:00 2001 From: tintinhamans <5984296+tintinhamans@users.noreply.github.com> Date: Sun, 25 Oct 2026 00:06:41 +0200 Subject: [PATCH 8/8] fix(filesystem): Reject BIG archives cut off before the directory --- .../Source/Common/System/BIGFileSystem.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp b/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp index 3bd1a29026c..dd0943e6336 100644 --- a/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp +++ b/Core/GameEngine/Source/Common/System/BIGFileSystem.cpp @@ -130,6 +130,13 @@ ArchiveFile * BIGFileSystem::openArchiveFile(const Char *filename) { } numLittleFiles = betoh(numLittleFiles); + if (numLittleFiles < 0) { + DEBUG_CRASH(("Invalid BIG file count in file %s", filename)); + fp->close(); + fp = nullptr; + return nullptr; + } + DEBUG_LOG(("BIGFileSystem::openArchiveFile - %d are contained in archive", numLittleFiles)); // for (Int i = 0; i < 2; ++i) { // t = buffer[i]; @@ -137,8 +144,14 @@ ArchiveFile * BIGFileSystem::openArchiveFile(const Char *filename) { // buffer[(4-i)-1] = t; // } - // seek to the beginning of the directory listing. - fp->seek(0x10, File::START); + // read the first entry offset field, which ends the header and starts the directory listing. + Int firstEntryOffset = 0; + if (fp->read(&firstEntryOffset, 4) != 4) { + DEBUG_CRASH(("Error reading BIG header in file %s", filename)); + fp->close(); + fp = nullptr; + return nullptr; + } // read in each directory listing. ArchivedFileInfo fileInfo; ArchiveFile *archiveFile = NEW ArchiveFile(filename, AsciiString::TheEmptyString); @@ -160,7 +173,6 @@ ArchiveFile * BIGFileSystem::openArchiveFile(const Char *filename) { fileInfo.m_size = filesize; // read in the path name of the file. - // the name must terminate within the buffer Int pathIndex = -1; Bool terminated = FALSE; while (++pathIndex < (Int)sizeof(buffer)) {