W3DFileSystem.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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. // 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_UNKNOWN = 0,
  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. /** Sets the file name, and finds the GDI asset if present. */
  100. //-------------------------------------------------------------------------------------------------
  101. char const * GameFileClass::Set_Name( char const *filename )
  102. {
  103. if( Is_Open() )
  104. Close();
  105. // save the filename
  106. strncpy( m_filename, filename, _MAX_PATH );
  107. char name[_MAX_PATH];
  108. const Int EXT_LEN = 32;
  109. char extension[EXT_LEN];
  110. extension[0] = 0;
  111. strcpy(name, filename);
  112. Int i = strlen(name);
  113. i--;
  114. Int extLen = 1;
  115. while(i>0 && extLen < EXT_LEN) {
  116. if (name[i] == '.') {
  117. strcpy(extension, name+i);
  118. name[i] = 0;
  119. break;
  120. }
  121. i--;
  122. extLen++;
  123. }
  124. Int j = 0;
  125. // Strip out spaces.
  126. for (i=0; name[i]; i++) {
  127. if (name[i] != ' ') {
  128. name[j] = name[i];
  129. j++;
  130. }
  131. }
  132. name[j] = 0;
  133. // test the extension to recognize a few key file types
  134. GameFileType fileType = FILE_TYPE_UNKNOWN;
  135. if( stricmp( extension, ".w3d" ) == 0 )
  136. fileType = FILE_TYPE_W3D;
  137. else if( stricmp( extension, ".tga" ) == 0 )
  138. fileType = FILE_TYPE_TGA;
  139. else if( stricmp( extension, ".dds" ) == 0 )
  140. fileType = FILE_TYPE_DDS;
  141. // all .w3d files are in W3D_DIR_PATH, all .tga files are in TGA_DIR_PATH
  142. if( fileType == FILE_TYPE_W3D )
  143. {
  144. strcpy( m_filePath, W3D_DIR_PATH );
  145. strcat( m_filePath, filename );
  146. } // end if
  147. else if( isImageFileType(fileType) )
  148. {
  149. strcpy( m_filePath, TGA_DIR_PATH );
  150. strcat( m_filePath, filename );
  151. } // end else if
  152. else
  153. strcpy( m_filePath, filename );
  154. // see if the file exists
  155. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  156. // maintain legacy compatibility directories for now
  157. #ifdef MAINTAIN_LEGACY_FILES
  158. if( m_fileExists == FALSE )
  159. {
  160. if( fileType == FILE_TYPE_W3D )
  161. {
  162. strcpy( m_filePath, LEGACY_W3D_DIR_PATH );
  163. strcat( m_filePath, filename );
  164. } // end if
  165. else if( isImageFileType(fileType) )
  166. {
  167. strcpy( m_filePath, LEGACY_TGA_DIR_PATH );
  168. strcat( m_filePath, filename );
  169. } // end else if
  170. // see if the file exists
  171. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  172. } // end if
  173. #endif
  174. // if file is still not found, try the test art folders
  175. #ifdef LOAD_TEST_ASSETS
  176. if( m_fileExists == FALSE )
  177. {
  178. if( fileType == FILE_TYPE_W3D )
  179. {
  180. strcpy( m_filePath, TEST_W3D_DIR_PATH );
  181. strcat( m_filePath, filename );
  182. } // end if
  183. else if( isImageFileType(fileType) )
  184. {
  185. strcpy( m_filePath, TEST_TGA_DIR_PATH );
  186. strcat( m_filePath, filename );
  187. } // end else if
  188. // see if the file exists
  189. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  190. } // end if
  191. #endif
  192. // We allow the user to load their own images for various assets (like the control bar)
  193. if( m_fileExists == FALSE && TheGlobalData)
  194. {
  195. if( fileType == FILE_TYPE_W3D )
  196. {
  197. sprintf(m_filePath,USER_W3D_DIR_PATH, TheGlobalData->getPath_UserData().str());
  198. //strcpy( m_filePath, USER_W3D_DIR_PATH );
  199. strcat( m_filePath, filename );
  200. } // end if
  201. if( isImageFileType(fileType) )
  202. {
  203. sprintf(m_filePath,USER_TGA_DIR_PATH, TheGlobalData->getPath_UserData().str());
  204. //strcpy( m_filePath, USER_TGA_DIR_PATH );
  205. strcat( m_filePath, filename );
  206. } // end else if
  207. // see if the file exists
  208. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  209. } // end if
  210. // We Need to be able to "temporarily copy over the map preview for whichever directory it came from
  211. if( m_fileExists == FALSE && TheGlobalData)
  212. {
  213. if( fileType == FILE_TYPE_TGA ) // just TGA, since we don't dds previews
  214. {
  215. sprintf(m_filePath,MAP_PREVIEW_DIR_PATH, TheGlobalData->getPath_UserData().str());
  216. //strcpy( m_filePath, USER_TGA_DIR_PATH );
  217. strcat( m_filePath, filename );
  218. } // end else if
  219. // see if the file exists
  220. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  221. } // end if
  222. // We need to be able to grab images from a localization dir, because Art has a fetish for baked-in text. Munkee.
  223. if( m_fileExists == FALSE )
  224. {
  225. if( isImageFileType(fileType) )
  226. {
  227. static const char *localizedPathFormat = "Data/%s/Art/Textures/";
  228. sprintf(m_filePath,localizedPathFormat, GetRegistryLanguage().str());
  229. strcat( m_filePath, filename );
  230. } // end else if
  231. // see if the file exists
  232. m_fileExists = TheFileSystem->doesFileExist( m_filePath );
  233. } // end if
  234. return m_filename;
  235. }
  236. //-------------------------------------------------------------------------------------------------
  237. /** If we found a gdi asset, the file is available. */
  238. //-------------------------------------------------------------------------------------------------
  239. bool GameFileClass::Is_Available( int forced )
  240. {
  241. // not maintaining any GDF compatibility, all files should be where the m_filePath says
  242. return m_fileExists;
  243. }
  244. //-------------------------------------------------------------------------------------------------
  245. /** Is the file open. */
  246. //-------------------------------------------------------------------------------------------------
  247. bool GameFileClass::Is_Open(void) const
  248. {
  249. return m_theFile != NULL;
  250. }
  251. //-------------------------------------------------------------------------------------------------
  252. /** Open the named file. */
  253. //-------------------------------------------------------------------------------------------------
  254. int GameFileClass::Open(char const *filename, int rights)
  255. {
  256. Set_Name(filename);
  257. if (Is_Available(false)) {
  258. return(Open(rights));
  259. }
  260. return(false);
  261. }
  262. //-------------------------------------------------------------------------------------------------
  263. /** Open the file using the current file name. */
  264. //-------------------------------------------------------------------------------------------------
  265. int GameFileClass::Open(int rights)
  266. {
  267. if( rights != READ )
  268. {
  269. return(false);
  270. }
  271. // just open up the file in m_filePath
  272. m_theFile = TheFileSystem->openFile( m_filePath, File::READ | File::BINARY );
  273. return (m_theFile != NULL);
  274. }
  275. //-------------------------------------------------------------------------------------------------
  276. /** Read. */
  277. //-------------------------------------------------------------------------------------------------
  278. int GameFileClass::Read(void *buffer, int len)
  279. {
  280. if (m_theFile) {
  281. return m_theFile->read(buffer, len);
  282. }
  283. return(0);
  284. }
  285. //-------------------------------------------------------------------------------------------------
  286. /** Seek. */
  287. //-------------------------------------------------------------------------------------------------
  288. int GameFileClass::Seek(int pos, int dir)
  289. {
  290. File::seekMode mode = File::CURRENT;
  291. switch (dir) {
  292. default:
  293. case SEEK_CUR: mode = File::CURRENT; break;
  294. case SEEK_SET: mode = File::START; break;
  295. case SEEK_END: mode = File::END; break;
  296. }
  297. if (m_theFile) {
  298. return m_theFile->seek(pos, mode);
  299. }
  300. return 0xFFFFFFFF;
  301. }
  302. //-------------------------------------------------------------------------------------------------
  303. /** Size. */
  304. //-------------------------------------------------------------------------------------------------
  305. int GameFileClass::Size(void)
  306. {
  307. if (m_theFile) {
  308. return m_theFile->size();
  309. }
  310. return 0xFFFFFFFF;
  311. }
  312. //-------------------------------------------------------------------------------------------------
  313. /** Write. */
  314. //-------------------------------------------------------------------------------------------------
  315. int GameFileClass::Write(void const *buffer, Int len)
  316. {
  317. #ifdef _DEBUG
  318. #endif
  319. return(0);
  320. }
  321. //-------------------------------------------------------------------------------------------------
  322. /** Close. */
  323. //-------------------------------------------------------------------------------------------------
  324. void GameFileClass::Close(void)
  325. {
  326. if (m_theFile) {
  327. m_theFile->close();
  328. m_theFile = NULL;
  329. }
  330. }
  331. ///////////////////////////////////////////////////////////////////////////////////////////////////
  332. // W3DFileSystem Class ////////////////////////////////////////////////////////////////////////////
  333. ///////////////////////////////////////////////////////////////////////////////////////////////////
  334. extern W3DFileSystem *TheW3DFileSystem = NULL;
  335. //-------------------------------------------------------------------------------------------------
  336. /** Constructor. Creating an instance of this class overrices the default
  337. W3D file factory. */
  338. //-------------------------------------------------------------------------------------------------
  339. W3DFileSystem::W3DFileSystem(void)
  340. {
  341. _TheFileFactory = this; // override the w3d file factory.
  342. }
  343. //-------------------------------------------------------------------------------------------------
  344. /** Destructor. This removes the W3D file factory, so shouldn't be done until
  345. after W3D is shutdown. */
  346. //-------------------------------------------------------------------------------------------------
  347. W3DFileSystem::~W3DFileSystem(void)
  348. {
  349. _TheFileFactory = NULL; // remove the w3d file factory.
  350. }
  351. //-------------------------------------------------------------------------------------------------
  352. /** Gets a file with the specified filename. */
  353. //-------------------------------------------------------------------------------------------------
  354. FileClass * W3DFileSystem::Get_File( char const *filename )
  355. {
  356. return NEW GameFileClass( filename ); // poolify
  357. }
  358. //-------------------------------------------------------------------------------------------------
  359. /** Releases a file returned by Get_File. */
  360. //-------------------------------------------------------------------------------------------------
  361. void W3DFileSystem::Return_File( FileClass *file )
  362. {
  363. delete file;
  364. }