Win32BIGFileSystem.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. ** Command & Conquer Generals(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. #ifdef _INTERNAL
  37. // for occasional debugging...
  38. //#pragma optimize("", off)
  39. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  40. #endif
  41. static const char *BIGFileIdentifier = "BIGF";
  42. Win32BIGFileSystem::Win32BIGFileSystem() : ArchiveFileSystem() {
  43. }
  44. Win32BIGFileSystem::~Win32BIGFileSystem() {
  45. }
  46. void Win32BIGFileSystem::init() {
  47. DEBUG_ASSERTCRASH(TheLocalFileSystem != NULL, ("TheLocalFileSystem must be initialized before TheArchiveFileSystem."));
  48. if (TheLocalFileSystem == NULL) {
  49. return;
  50. }
  51. loadBigFilesFromDirectory("", "*.big");
  52. }
  53. void Win32BIGFileSystem::reset() {
  54. }
  55. void Win32BIGFileSystem::update() {
  56. }
  57. void Win32BIGFileSystem::postProcessLoad() {
  58. }
  59. ArchiveFile * Win32BIGFileSystem::openArchiveFile(const Char *filename) {
  60. File *fp = TheLocalFileSystem->openFile(filename, File::READ | File::BINARY);
  61. AsciiString archiveFileName;
  62. archiveFileName = filename;
  63. archiveFileName.toLower();
  64. Int archiveFileSize = 0;
  65. Int numLittleFiles = 0;
  66. ArchiveFile *archiveFile = NEW Win32BIGFile;
  67. DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - opening BIG file %s\n", filename));
  68. if (fp == NULL) {
  69. DEBUG_CRASH(("Could not open archive file %s for parsing", filename));
  70. return NULL;
  71. }
  72. AsciiString asciibuf;
  73. char buffer[_MAX_PATH];
  74. fp->read(buffer, 4); // read the "BIG" at the beginning of the file.
  75. buffer[4] = 0;
  76. if (strcmp(buffer, BIGFileIdentifier) != 0) {
  77. DEBUG_CRASH(("Error reading BIG file identifier in file %s", filename));
  78. fp->close();
  79. fp = NULL;
  80. return NULL;
  81. }
  82. // read in the file size.
  83. fp->read(&archiveFileSize, 4);
  84. DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - size of archive file is %d bytes\n", archiveFileSize));
  85. // char t;
  86. // read in the number of files contained in this BIG file.
  87. // change the order of the bytes cause the file size is in reverse byte order for some reason.
  88. fp->read(&numLittleFiles, 4);
  89. numLittleFiles = ntohl(numLittleFiles);
  90. DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - %d are contained in archive\n", numLittleFiles));
  91. // for (Int i = 0; i < 2; ++i) {
  92. // t = buffer[i];
  93. // buffer[i] = buffer[(4-i)-1];
  94. // buffer[(4-i)-1] = t;
  95. // }
  96. // seek to the beginning of the directory listing.
  97. fp->seek(0x10, File::START);
  98. // read in each directory listing.
  99. ArchivedFileInfo *fileInfo = NEW ArchivedFileInfo;
  100. for (Int i = 0; i < numLittleFiles; ++i) {
  101. Int filesize = 0;
  102. Int fileOffset = 0;
  103. fp->read(&fileOffset, 4);
  104. fp->read(&filesize, 4);
  105. filesize = ntohl(filesize);
  106. fileOffset = ntohl(fileOffset);
  107. fileInfo->m_archiveFilename = archiveFileName;
  108. fileInfo->m_offset = fileOffset;
  109. fileInfo->m_size = filesize;
  110. // read in the path name of the file.
  111. Int pathIndex = -1;
  112. do {
  113. ++pathIndex;
  114. fp->read(buffer + pathIndex, 1);
  115. } while (buffer[pathIndex] != 0);
  116. Int filenameIndex = pathIndex;
  117. while ((buffer[filenameIndex] != '\\') && (buffer[filenameIndex] != '/') && (filenameIndex >= 0)) {
  118. --filenameIndex;
  119. }
  120. fileInfo->m_filename = (char *)(buffer + filenameIndex + 1);
  121. fileInfo->m_filename.toLower();
  122. buffer[filenameIndex + 1] = 0;
  123. AsciiString path;
  124. path = buffer;
  125. AsciiString debugpath;
  126. debugpath = path;
  127. debugpath.concat(fileInfo->m_filename);
  128. // DEBUG_LOG(("Win32BIGFileSystem::openArchiveFile - adding file %s to archive file %s, file number %d\n", debugpath.str(), fileInfo->m_archiveFilename.str(), i));
  129. archiveFile->addFile(path, fileInfo);
  130. }
  131. archiveFile->attachFile(fp);
  132. delete fileInfo;
  133. fileInfo = NULL;
  134. // leave fp open as the archive file will be using it.
  135. return archiveFile;
  136. }
  137. void Win32BIGFileSystem::closeArchiveFile(const Char *filename) {
  138. // Need to close the specified big file
  139. ArchiveFileMap::iterator it = m_archiveFileMap.find(filename);
  140. if (it == m_archiveFileMap.end()) {
  141. return;
  142. }
  143. if (stricmp(filename, MUSIC_BIG) == 0) {
  144. // Stop the current audio
  145. TheAudio->stopAudio(AudioAffect_Music);
  146. // No need to turn off other audio, as the lookups will just fail.
  147. }
  148. DEBUG_ASSERTCRASH(stricmp(filename, MUSIC_BIG) == 0, ("Attempting to close Archive file '%s', need to add code to handle its shutdown correctly.", filename));
  149. // may need to do some other processing here first.
  150. delete (it->second);
  151. m_archiveFileMap.erase(it);
  152. }
  153. void Win32BIGFileSystem::closeAllArchiveFiles() {
  154. }
  155. void Win32BIGFileSystem::closeAllFiles() {
  156. }
  157. Bool Win32BIGFileSystem::loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite) {
  158. FilenameList filenameList;
  159. TheLocalFileSystem->getFileListInDirectory(dir, AsciiString(""), fileMask, filenameList, TRUE);
  160. Bool actuallyAdded = FALSE;
  161. FilenameListIter it = filenameList.begin();
  162. while (it != filenameList.end()) {
  163. ArchiveFile *archiveFile = openArchiveFile((*it).str());
  164. if (archiveFile != NULL) {
  165. DEBUG_LOG(("Win32BIGFileSystem::loadBigFilesFromDirectory - loading %s into the directory tree.\n", (*it).str()));
  166. loadIntoDirectoryTree(archiveFile, *it, overwrite);
  167. m_archiveFileMap[(*it)] = archiveFile;
  168. DEBUG_LOG(("Win32BIGFileSystem::loadBigFilesFromDirectory - %s inserted into the archive file map.\n", (*it).str()));
  169. actuallyAdded = TRUE;
  170. }
  171. it++;
  172. }
  173. return actuallyAdded;
  174. }