Win32BIGFileSystem.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. //////// Win32BIGFileSystem.h ///////////////////////////
  24. // Bryan Cleveland, August 2002
  25. /////////////////////////////////////////////////////////////
  26. #include <winsock2.h>
  27. #include "Common/AudioAffect.h"
  28. #include "Common/ArchiveFile.h"
  29. #include "Common/ArchiveFileSystem.h"
  30. #include "Common/File.h"
  31. #include "Common/GameAudio.h"
  32. #include "Common/GameMemory.h"
  33. #include "Common/LocalFileSystem.h"
  34. #include "Win32Device/Common/Win32BIGFile.h"
  35. #include "Win32Device/Common/Win32BIGFileSystem.h"
  36. #include "Common/registry.h"
  37. #ifdef _INTERNAL
  38. // for occasional debugging...
  39. //#pragma optimize("", off)
  40. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  41. #endif
  42. static const char *BIGFileIdentifier = "BIGF";
  43. Win32BIGFileSystem::Win32BIGFileSystem() : ArchiveFileSystem() {
  44. }
  45. Win32BIGFileSystem::~Win32BIGFileSystem() {
  46. }
  47. void Win32BIGFileSystem::init() {
  48. DEBUG_ASSERTCRASH(TheLocalFileSystem != NULL, ("TheLocalFileSystem must be initialized before TheArchiveFileSystem."));
  49. if (TheLocalFileSystem == NULL) {
  50. return;
  51. }
  52. loadBigFilesFromDirectory("", "*.big");
  53. // load original Generals assets
  54. AsciiString installPath;
  55. GetStringFromGeneralsRegistry("", "InstallPath", installPath );
  56. //@todo this will need to be ramped up to a crash for release
  57. #ifndef _INTERNAL
  58. // had to make this non-internal only, otherwise we can't autobuild
  59. // GeneralsZH...
  60. DEBUG_ASSERTCRASH(installPath != "", ("Be 1337! Go install Generals!"));
  61. #endif
  62. if (installPath!="")
  63. loadBigFilesFromDirectory(installPath, "*.big");
  64. }
  65. void Win32BIGFileSystem::reset() {
  66. }
  67. void Win32BIGFileSystem::update() {
  68. }
  69. void Win32BIGFileSystem::postProcessLoad() {
  70. }
  71. ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) {
  72. File *fp = TheLocalFileSystem->openFile(filename, File::READ | File::BINARY);
  73. AsciiString archiveFileName;
  74. archiveFileName = filename;
  75. archiveFileName.toLower();
  76. Int archiveFileSize = 0;
  77. Int numLittleFiles = 0;
  78. ArchiveFile *archiveFile = NEW Win32BIGFile;
  79. DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - opening BIG file %s\n", filename));
  80. if (fp == NULL) {
  81. DEBUG_CRASH(("Could not open archive file %s for parsing", filename));
  82. return NULL;
  83. }
  84. AsciiString asciibuf;
  85. char buffer[_MAX_PATH];
  86. fp->read(buffer, 4); // read the "BIG" at the beginning of the file.
  87. buffer[4] = 0;
  88. if (strcmp(buffer, BIGFileIdentifier) != 0) {
  89. DEBUG_CRASH(("Error reading BIG file identifier in file %s", filename));
  90. fp->close();
  91. fp = NULL;
  92. return NULL;
  93. }
  94. // read in the file size.
  95. fp->read(&archiveFileSize, 4);
  96. DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - size of archive file is %d bytes\n", archiveFileSize));
  97. // char t;
  98. // read in the number of files contained in this BIG file.
  99. // change the order of the bytes cause the file size is in reverse byte order for some reason.
  100. fp->read(&numLittleFiles, 4);
  101. numLittleFiles = ntohl(numLittleFiles);
  102. DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - %d are contained in archive\n", numLittleFiles));
  103. // for (Int i = 0; i < 2; ++i) {
  104. // t = buffer[i];
  105. // buffer[i] = buffer[(4-i)-1];
  106. // buffer[(4-i)-1] = t;
  107. // }
  108. // seek to the beginning of the directory listing.
  109. fp->seek(0x10, File::START);
  110. // read in each directory listing.
  111. ArchivedFileInfo *fileInfo = NEW ArchivedFileInfo;
  112. for (Int i = 0; i < numLittleFiles; ++i) {
  113. Int filesize = 0;
  114. Int fileOffset = 0;
  115. fp->read(&fileOffset, 4);
  116. fp->read(&filesize, 4);
  117. filesize = ntohl(filesize);
  118. fileOffset = ntohl(fileOffset);
  119. fileInfo->m_archiveFilename = archiveFileName;
  120. fileInfo->m_offset = fileOffset;
  121. fileInfo->m_size = filesize;
  122. // read in the path name of the file.
  123. Int pathIndex = -1;
  124. do {
  125. ++pathIndex;
  126. fp->read(buffer + pathIndex, 1);
  127. } while (buffer[pathIndex] != 0);
  128. Int filenameIndex = pathIndex;
  129. while ((buffer[filenameIndex] != '\\') && (buffer[filenameIndex] != '/') && (filenameIndex >= 0)) {
  130. --filenameIndex;
  131. }
  132. fileInfo->m_filename = (char *)(buffer + filenameIndex + 1);
  133. fileInfo->m_filename.toLower();
  134. buffer[filenameIndex + 1] = 0;
  135. AsciiString path;
  136. path = buffer;
  137. AsciiString debugpath;
  138. debugpath = path;
  139. debugpath.concat(fileInfo->m_filename);
  140. // DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - adding file %s to archive file %s, file number %d\n", debugpath.str(), fileInfo->m_archiveFilename.str(), i));
  141. archiveFile->addFile(path, fileInfo);
  142. }
  143. archiveFile->attachFile(fp);
  144. delete fileInfo;
  145. fileInfo = NULL;
  146. // leave fp open as the archive file will be using it.
  147. return archiveFile;
  148. }
  149. void Win32BIGFileSystem::closeArchiveFile(const Char *filename) {
  150. // Need to close the specified big file
  151. ArchiveFileMap::iterator it = m_archiveFileMap.find(filename);
  152. if (it == m_archiveFileMap.end()) {
  153. return;
  154. }
  155. if (stricmp(filename, MUSIC_BIG) == 0) {
  156. // Stop the current audio
  157. TheAudio->stopAudio(AudioAffect_Music);
  158. // No need to turn off other audio, as the lookups will just fail.
  159. }
  160. DEBUG_ASSERTCRASH(stricmp(filename, MUSIC_BIG) == 0, ("Attempting to close Archive file '%s', need to add code to handle its shutdown correctly.", filename));
  161. // may need to do some other processing here first.
  162. delete (it->second);
  163. m_archiveFileMap.erase(it);
  164. }
  165. void Win32BIGFileSystem::closeAllArchiveFiles() {
  166. }
  167. void Win32BIGFileSystem::closeAllFiles() {
  168. }
  169. Bool Win32BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite) {
  170. FilenameList filenameList;
  171. TheLocalFileSystem->getFileListInDirectory(dir, AsciiString(""), fileMask, filenameList, TRUE);
  172. Bool actuallyAdded = FALSE;
  173. FilenameListIter it = filenameList.begin();
  174. while (it != filenameList.end()) {
  175. ArchiveFile *archiveFile = openArchiveFile((*it).str());
  176. if (archiveFile != NULL) {
  177. DEBUG_LOG(("Win32BIGFileSystem::loadBigFilesFromDirectory - loading %s into the directory tree.\n", (*it).str()));
  178. loadIntoDirectoryTree(archiveFile, *it, overwrite);
  179. m_archiveFileMap[(*it)] = archiveFile;
  180. DEBUG_LOG(("Win32BIGFileSystem::loadBigFilesFromDirectory - %s inserted into the archive file map.\n", (*it).str()));
  181. actuallyAdded = TRUE;
  182. }
  183. it++;
  184. }
  185. return actuallyAdded;
  186. }