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)) {