W3DFileSystem.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  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. // FILE: W3DFileSystem.cpp ////////////////////////////////////////////////////////////////////////
  24. //
  25. // W3D implementation of a file factory. This replaces the W3D file factory,
  26. // and uses GDI assets, so that
  27. // W3D files and targa files are loaded using the GDI file interface.
  28. // Note - this only servers up read only files.
  29. //
  30. // Author: John Ahlquist, Sept 2001
  31. // Colin Day, November 2001
  32. //
  33. ///////////////////////////////////////////////////////////////////////////////////////////////////
  34. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  35. // for now we maintain old legacy files
  36. // #define MAINTAIN_LEGACY_FILES
  37. #include "Common/Debug.h"
  38. #include "Common/File.h"
  39. #include "Common/FileSystem.h"
  40. #include "Common/GlobalData.h"
  41. #include "Common/MapObject.h"
  42. #include "Common/Registry.h"
  43. #include "W3DDevice/GameClient/W3DFileSystem.h"
  44. // DEFINES ////////////////////////////////////////////////////////////////////////////////////////
  45. #include <io.h>
  46. //-------------------------------------------------------------------------------------------------
  47. /** Game file access. At present this allows us to access test assets, assets from
  48. * legacy GDI assets, and the current flat directory access for textures, models etc */
  49. //-------------------------------------------------------------------------------------------------
  50. //-------------------------------------------------------------------------------------------------
  51. //-------------------------------------------------------------------------------------------------
  52. typedef enum
  53. {
  54. FILE_TYPE_COMPLETELY_UNKNOWN = 0, // MBL 08.15.2002 - compile error with FILE_TYPE_UNKNOWN, is constant
  55. FILE_TYPE_W3D,
  56. FILE_TYPE_TGA,
  57. FILE_TYPE_DDS,
  58. } GameFileType;
  59. //-------------------------------------------------------------------------------------------------
  60. //-------------------------------------------------------------------------------------------------
  61. GameFileClass::GameFileClass( char const *filename )
  62. {
  63. m_fileExists = FALSE;
  64. m_theFile = NULL;
  65. m_filePath[ 0 ] = 0;
  66. m_filename[0] = 0;
  67. if( filename )
  68. Set_Name( filename );
  69. }
  70. //-------------------------------------------------------------------------------------------------
  71. //-------------------------------------------------------------------------------------------------
  72. GameFileClass::GameFileClass( void )
  73. {
  74. m_fileExists = FALSE;
  75. m_theFile = NULL;
  76. m_filePath[ 0 ] = 0;
  77. m_filename[ 0 ] = 0;
  78. }
  79. //-------------------------------------------------------------------------------------------------
  80. //-------------------------------------------------------------------------------------------------
  81. GameFileClass::~GameFileClass()
  82. {
  83. Close();
  84. }
  85. //-------------------------------------------------------------------------------------------------
  86. /** Gets the file name */
  87. //-------------------------------------------------------------------------------------------------
  88. char const * GameFileClass::File_Name( void ) const
  89. {
  90. return m_filename;
  91. }
  92. //-------------------------------------------------------------------------------------------------
  93. //-------------------------------------------------------------------------------------------------
  94. inline static Bool isImageFileType( GameFileType fileType )
  95. {
  96. return (fileType == FILE_TYPE_TGA || fileType == FILE_TYPE_DDS);
  97. }
  98. //-------------------------------------------------------------------------------------------------
  99. /**
  100. Sets the file name, and finds the GDI asset if present.
  101. Well, that is the worst comment ever for the most important function there is.
  102. Everything comes through this. This builds the directory and tests for the file
  103. in several different places.
  104. First we look in Language subfolders so that our Perforce build can handle files that have
  105. been localized but were in Generals.
  106. Then we do the normal TheFileSystem lookup. In there it does LocalFile (Art/Textures) then it does
  107. big files (which internally are also Art/Textures).
  108. Finally we try UserData.
  109. */
  110. //-------------------------------------------------------------------------------------------------
  111. char const * GameFileClass::Set_Name( char const *filename )
  112. {
  113. if( Is_Open() )
  114. Close();
  115. // save the filename
  116. strncpy( m_filename, filename, _MAX_PATH );
  117. char name[_MAX_PATH];
  118. const Int EXT_LEN = 32;
  119. char extension[EXT_LEN];
  120. extension[0] = 0;
  121. strcpy(name, filename);
  122. Int i = strlen(name);
  123. i--;
  124. Int extLen = 1;
  125. while(i>0 && extLen < EXT_LEN) {
  126. if (name[i] == '.') {
  127. strcpy(extension, name+i);
  128. name[i] = 0;
  129. break;
  130. }
  131. i--;
  132. extLen++;
  133. }
  134. Int j = 0;
  135. // Strip out spaces.
  136. for (i=0; name[i]; i++) {
  137. if (name[i] != ' ') {
  138. name[j] = name[i];
  139. j++;
  140. }
  141. }
  142. name[j] = 0;
  143. // test the extension to recognize a few key file types
  144. GameFileType fileType = FILE_TYPE_COMPLETELY_UNKNOWN; // MBL FILE_TYPE_UNKNOWN change due to compile error
  145. if( stricmp( extension, ".w3d" ) == 0 )
  146. fileType = FILE_TYPE_W3D;
  147. else if( stricmp( extension, ".tga" ) == 0 )
  148. fileType = FILE_TYPE_TGA;
  149. else if( stricmp( extension, ".dds" ) == 0 )
  150. fileType = FILE_TYPE_DDS;
  151. // We need to be able to grab w3d's from a localization dir, since Germany hates exploding people units.
  152. if( fileType == FILE_TYPE_W3D )
  153. {
  154. static const char *localizedPathFormat = "Data/%s/Art/W3D/";
  155. sprintf(m_filePath,localizedPathFormat, GetRegistryLanguage().str());
  156. strcat( m_filePath, filename );
  157. } // end if
  158. // We need to be able to grab images from a localization dir, because Art has a fetish for baked-in text. Munkee.
  159. if( isImageFileType(fileType) )
  160. {
  161. static const char *localizedPathFormat = "Data/%s/Art/Textures/";
  162. sprintf(m_filePath,localizedPathFormat, GetRegistryLanguage().str());
  163. strcat( m_filePath, filename );
  164. } // end else if
  165. // see if the file exists
  166. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  167. // Now try the main lookup of hitting local files and big files
  168. if( m_fileExists == FALSE )
  169. {
  170. // all .w3d files are in W3D_DIR_PATH, all .tga files are in TGA_DIR_PATH
  171. if( fileType == FILE_TYPE_W3D )
  172. {
  173. strcpy( m_filePath, W3D_DIR_PATH );
  174. strcat( m_filePath, filename );
  175. } // end if
  176. else if( isImageFileType(fileType) )
  177. {
  178. strcpy( m_filePath, TGA_DIR_PATH );
  179. strcat( m_filePath, filename );
  180. } // end else if
  181. else
  182. strcpy( m_filePath, filename );
  183. // see if the file exists
  184. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  185. }
  186. // maintain legacy compatibility directories for now
  187. #ifdef MAINTAIN_LEGACY_FILES
  188. if( m_fileExists == FALSE )
  189. {
  190. if( fileType == FILE_TYPE_W3D )
  191. {
  192. strcpy( m_filePath, LEGACY_W3D_DIR_PATH );
  193. strcat( m_filePath, filename );
  194. } // end if
  195. else if( isImageFileType(fileType) )
  196. {
  197. strcpy( m_filePath, LEGACY_TGA_DIR_PATH );
  198. strcat( m_filePath, filename );
  199. } // end else if
  200. // see if the file exists
  201. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  202. } // end if
  203. #endif
  204. // if file is still not found, try the test art folders
  205. #ifdef LOAD_TEST_ASSETS
  206. if( m_fileExists == FALSE )
  207. {
  208. if( fileType == FILE_TYPE_W3D )
  209. {
  210. strcpy( m_filePath, TEST_W3D_DIR_PATH );
  211. strcat( m_filePath, filename );
  212. } // end if
  213. else if( isImageFileType(fileType) )
  214. {
  215. strcpy( m_filePath, TEST_TGA_DIR_PATH );
  216. strcat( m_filePath, filename );
  217. } // end else if
  218. // see if the file exists
  219. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  220. } // end if
  221. #endif
  222. // We allow the user to load their own images for various assets (like the control bar)
  223. if( m_fileExists == FALSE && TheGlobalData)
  224. {
  225. if( fileType == FILE_TYPE_W3D )
  226. {
  227. sprintf(m_filePath,USER_W3D_DIR_PATH, TheGlobalData->getPath_UserData().str());
  228. //strcpy( m_filePath, USER_W3D_DIR_PATH );
  229. strcat( m_filePath, filename );
  230. } // end if
  231. if( isImageFileType(fileType) )
  232. {
  233. sprintf(m_filePath,USER_TGA_DIR_PATH, TheGlobalData->getPath_UserData().str());
  234. //strcpy( m_filePath, USER_TGA_DIR_PATH );
  235. strcat( m_filePath, filename );
  236. } // end else if
  237. // see if the file exists
  238. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  239. } // end if
  240. // We Need to be able to "temporarily copy over the map preview for whichever directory it came from
  241. if( m_fileExists == FALSE && TheGlobalData)
  242. {
  243. if( fileType == FILE_TYPE_TGA ) // just TGA, since we don't dds previews
  244. {
  245. sprintf(m_filePath,MAP_PREVIEW_DIR_PATH, TheGlobalData->getPath_UserData().str());
  246. //strcpy( m_filePath, USER_TGA_DIR_PATH );
  247. strcat( m_filePath, filename );
  248. } // end else if
  249. // see if the file exists
  250. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  251. } // end if
  252. return m_filename;
  253. }
  254. //-------------------------------------------------------------------------------------------------
  255. /** If we found a gdi asset, the file is available. */
  256. //-------------------------------------------------------------------------------------------------
  257. bool GameFileClass::Is_Available( int forced )
  258. {
  259. // not maintaining any GDF compatibility, all files should be where the m_filePath says
  260. return m_fileExists;
  261. }
  262. //-------------------------------------------------------------------------------------------------
  263. /** Is the file open. */
  264. //-------------------------------------------------------------------------------------------------
  265. bool GameFileClass::Is_Open(void) const
  266. {
  267. return m_theFile != NULL;
  268. }
  269. //-------------------------------------------------------------------------------------------------
  270. /** Open the named file. */
  271. //-------------------------------------------------------------------------------------------------
  272. int GameFileClass::Open(char const *filename, int rights)
  273. {
  274. Set_Name(filename);
  275. if (Is_Available(false)) {
  276. return(Open(rights));
  277. }
  278. return(false);
  279. }
  280. //-------------------------------------------------------------------------------------------------
  281. /** Open the file using the current file name. */
  282. //-------------------------------------------------------------------------------------------------
  283. int GameFileClass::Open(int rights)
  284. {
  285. if( rights != READ )
  286. {
  287. return(false);
  288. }
  289. // just open up the file in m_filePath
  290. m_theFile = TheFileSystem->openFile( m_filePath, File::READ | File::BINARY );
  291. return (m_theFile != NULL);
  292. }
  293. //-------------------------------------------------------------------------------------------------
  294. /** Read. */
  295. //-------------------------------------------------------------------------------------------------
  296. int GameFileClass::Read(void *buffer, int len)
  297. {
  298. if (m_theFile) {
  299. return m_theFile->read(buffer, len);
  300. }
  301. return(0);
  302. }
  303. //-------------------------------------------------------------------------------------------------
  304. /** Seek. */
  305. //-------------------------------------------------------------------------------------------------
  306. int GameFileClass::Seek(int pos, int dir)
  307. {
  308. File::seekMode mode = File::CURRENT;
  309. switch (dir) {
  310. default:
  311. case SEEK_CUR: mode = File::CURRENT; break;
  312. case SEEK_SET: mode = File::START; break;
  313. case SEEK_END: mode = File::END; break;
  314. }
  315. if (m_theFile) {
  316. return m_theFile->seek(pos, mode);
  317. }
  318. return 0xFFFFFFFF;
  319. }
  320. //-------------------------------------------------------------------------------------------------
  321. /** Size. */
  322. //-------------------------------------------------------------------------------------------------
  323. int GameFileClass::Size(void)
  324. {
  325. if (m_theFile) {
  326. return m_theFile->size();
  327. }
  328. return 0xFFFFFFFF;
  329. }
  330. //-------------------------------------------------------------------------------------------------
  331. /** Write. */
  332. //-------------------------------------------------------------------------------------------------
  333. int GameFileClass::Write(void const *buffer, Int len)
  334. {
  335. #ifdef _DEBUG
  336. #endif
  337. return(0);
  338. }
  339. //-------------------------------------------------------------------------------------------------
  340. /** Close. */
  341. //-------------------------------------------------------------------------------------------------
  342. void GameFileClass::Close(void)
  343. {
  344. if (m_theFile) {
  345. m_theFile->close();
  346. m_theFile = NULL;
  347. }
  348. }
  349. ///////////////////////////////////////////////////////////////////////////////////////////////////
  350. // W3DFileSystem Class ////////////////////////////////////////////////////////////////////////////
  351. ///////////////////////////////////////////////////////////////////////////////////////////////////
  352. extern W3DFileSystem *TheW3DFileSystem = NULL;
  353. //-------------------------------------------------------------------------------------------------
  354. /** Constructor. Creating an instance of this class overrices the default
  355. W3D file factory. */
  356. //-------------------------------------------------------------------------------------------------
  357. W3DFileSystem::W3DFileSystem(void)
  358. {
  359. _TheFileFactory = this; // override the w3d file factory.
  360. }
  361. //-------------------------------------------------------------------------------------------------
  362. /** Destructor. This removes the W3D file factory, so shouldn't be done until
  363. after W3D is shutdown. */
  364. //-------------------------------------------------------------------------------------------------
  365. W3DFileSystem::~W3DFileSystem(void)
  366. {
  367. _TheFileFactory = NULL; // remove the w3d file factory.
  368. }
  369. //-------------------------------------------------------------------------------------------------
  370. /** Gets a file with the specified filename. */
  371. //-------------------------------------------------------------------------------------------------
  372. FileClass * W3DFileSystem::Get_File( char const *filename )
  373. {
  374. return NEW GameFileClass( filename ); // poolify
  375. }
  376. //-------------------------------------------------------------------------------------------------
  377. /** Releases a file returned by Get_File. */
  378. //-------------------------------------------------------------------------------------------------
  379. void W3DFileSystem::Return_File( FileClass *file )
  380. {
  381. delete file;
  382. }