ffile.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. //---------------------------------------------------------------------------
  2. //
  3. // ffile.cpp - This file contains the class functions for FastFile
  4. //
  5. //---------------------------------------------------------------------------//
  6. // Copyright (C) Microsoft Corporation. All rights reserved. //
  7. //===========================================================================//
  8. //---------------------------------------------------------------------------
  9. // Include files
  10. #ifndef FFILE_H
  11. #include "ffile.h"
  12. #endif
  13. #ifndef UTILITIES_H
  14. #include "utilities.h"
  15. #endif
  16. #include "lz.h"
  17. #include "zlib.h"
  18. #include <windows.h>
  19. #include <string.h>
  20. #include <gameos.hpp>
  21. MemoryPtr LZPacketBuffer = NULL;
  22. unsigned long LZPacketBufferSize = 512000;
  23. extern char CDInstallPath[];
  24. void EnterWindowMode();
  25. void EnterFullScreenMode();
  26. void __stdcall ExitGameOS();
  27. char FileMissingString[512];
  28. char CDMissingString[1024];
  29. char MissingTitleString[256];
  30. //---------------------------------------------------------------------------
  31. // class FastFile member functions
  32. //---------------------------------------------------------------------------
  33. void *FastFile::operator new (size_t mySize)
  34. {
  35. void *result = NULL;
  36. result = malloc(mySize);
  37. return(result);
  38. }
  39. //---------------------------------------------------------------------------
  40. void FastFile::operator delete (void *us)
  41. {
  42. ::free(us);
  43. }
  44. //---------------------------------------------------------------------------
  45. FastFile::FastFile (void)
  46. {
  47. files = NULL;
  48. numFiles = 0;
  49. fileName = NULL;
  50. handle = NULL;
  51. length = 0;
  52. logicalPosition = 0;
  53. useLZCompress = false;
  54. }
  55. //---------------------------------------------------------------------------
  56. FastFile::~FastFile (void)
  57. {
  58. close();
  59. if (LZPacketBuffer)
  60. {
  61. free(LZPacketBuffer);
  62. LZPacketBuffer = NULL;
  63. }
  64. }
  65. //---------------------------------------------------------------------------
  66. long FastFile::open (char* fName)
  67. {
  68. //-------------------------------------------------------------
  69. long fNameLength = strlen(fName);
  70. fileName = new char [fNameLength+1];
  71. if (!fileName)
  72. return(NO_RAM_FOR_FILENAME);
  73. strncpy(fileName,fName,fNameLength+1);
  74. handle = fopen(fileName,"r");
  75. if (handle != NULL)
  76. {
  77. logicalPosition = 0;
  78. fileSize(); //Sets Length
  79. }
  80. else
  81. {
  82. //Check on CD. They may not have been installed.
  83. char actualPath[2048];
  84. strcpy(actualPath,CDInstallPath);
  85. strcat(actualPath,fileName);
  86. handle = fopen(actualPath,"r");
  87. if (handle == NULL)
  88. {
  89. //OPEN Error. Maybe the CD is missing?
  90. bool openFailed = false;
  91. bool alreadyFullScreen = (Environment.fullScreen != 0);
  92. while (handle == NULL)
  93. {
  94. openFailed = true;
  95. EnterWindowMode();
  96. char data[2048];
  97. sprintf(data,FileMissingString,fileName,CDMissingString);
  98. DWORD result1 = MessageBox(NULL,data,MissingTitleString,MB_OKCANCEL | MB_ICONWARNING);
  99. if (result1 == IDCANCEL)
  100. {
  101. ExitGameOS();
  102. return (2); //File not found. Never returns though!
  103. }
  104. handle = fopen(actualPath,"r");
  105. }
  106. if (openFailed && (Environment.fullScreen == 0) && alreadyFullScreen)
  107. EnterFullScreenMode();
  108. }
  109. else
  110. {
  111. logicalPosition = 0;
  112. fileSize(); //Sets Length
  113. }
  114. }
  115. //---------------------------------------------
  116. //-- Read in ALL of the file names and offsets
  117. logicalPosition = fseek(handle,0,SEEK_SET);
  118. //---------------------------------------------
  119. //-- First Long is Version Number of FastFile
  120. unsigned long result = 0;
  121. unsigned long version = 0;
  122. result = fread((&version),1,sizeof(long),handle);
  123. logicalPosition += sizeof(long);
  124. if (result != sizeof(long))
  125. {
  126. long lastError = errno;
  127. return lastError;
  128. }
  129. if (version != FASTFILE_VERSION && version != FASTFILE_VERSION_LZ)
  130. return FASTFILE_VERSION;
  131. if (version == FASTFILE_VERSION_LZ)
  132. useLZCompress = true;
  133. //---------------------------------------------
  134. //-- Second Long is number of filenames present.
  135. result = fread((&numFiles),1,sizeof(long),handle);
  136. logicalPosition += sizeof(long);
  137. if (result != sizeof(long))
  138. {
  139. long lastError = errno;
  140. return lastError;
  141. }
  142. files = (FILE_HANDLE*)malloc(sizeof(FILE_HANDLE) * numFiles);
  143. for (long i=0;i<numFiles;i++)
  144. {
  145. files[i].pfe = (FILEENTRY *)malloc(sizeof(FILEENTRY));
  146. memset(files[i].pfe,0,sizeof(FILEENTRY));
  147. unsigned long result = 0;
  148. result = fread(files[i].pfe,1,sizeof(FILEENTRY),handle);
  149. files[i].inuse = FALSE;
  150. files[i].pos = 0;
  151. }
  152. return (result);
  153. }
  154. //---------------------------------------------------------------------------
  155. void FastFile::close (void)
  156. {
  157. //------------------------------------------------------------------------
  158. // The actual stored filename is also in the parent. Everyone else just has
  159. // pointer and, as such, only the parent frees the memory.
  160. if (fileName)
  161. delete [] fileName; // this was free, which didn't match the new allocation.
  162. // neither new nor free were overridden. Should they have been?
  163. fileName = NULL;
  164. length = 0;
  165. if (isOpen())
  166. {
  167. fclose(handle);
  168. handle = NULL;
  169. }
  170. //---------------------------------------------
  171. //-- First Long is number of filenames present.
  172. for (long i=0;i<numFiles;i++)
  173. {
  174. free(files[i].pfe);
  175. }
  176. free(files);
  177. files = NULL;
  178. numFiles = 0;
  179. }
  180. //---------------------------------------------------------------------------
  181. long FastFile::openFast (DWORD hash, char *fName)
  182. {
  183. //------------------------------------------------------------------
  184. //-- In order to use this, the file name must be part of the index.
  185. for (long i=0;i<numFiles;i++)
  186. {
  187. if ((hash == files[i].pfe->hash) && (stricmp(files[i].pfe->name,fName) == 0))
  188. {
  189. files[i].inuse = TRUE;
  190. files[i].pos = 0;
  191. return i;
  192. }
  193. }
  194. return -1;
  195. }
  196. //---------------------------------------------------------------------------
  197. void FastFile::closeFast (long fastFileHandle)
  198. {
  199. if ((fastFileHandle >= 0) && (fastFileHandle < numFiles) && files[fastFileHandle].inuse)
  200. {
  201. files[fastFileHandle].inuse = FALSE;
  202. files[fastFileHandle].pos = 0;
  203. }
  204. }
  205. //---------------------------------------------------------------------------
  206. long FastFile::seekFast (long fastFileHandle, long off, long how)
  207. {
  208. if ((fastFileHandle >= 0) && (fastFileHandle < numFiles) && files[fastFileHandle].inuse)
  209. {
  210. switch (how)
  211. {
  212. case SEEK_SET:
  213. if (off > files[fastFileHandle].pfe->size)
  214. {
  215. return READ_PAST_EOF_ERR;
  216. }
  217. break;
  218. case SEEK_END:
  219. if ((abs(off) > files[fastFileHandle].pfe->size) || (off > 0))
  220. {
  221. return READ_PAST_EOF_ERR;
  222. }
  223. break;
  224. case SEEK_CUR:
  225. if (off+files[fastFileHandle].pos > files[fastFileHandle].pfe->size)
  226. {
  227. return READ_PAST_EOF_ERR;
  228. }
  229. break;
  230. }
  231. long newPosition = 0;
  232. switch (how)
  233. {
  234. case SEEK_SET:
  235. newPosition = off;
  236. break;
  237. case SEEK_END:
  238. newPosition = files[fastFileHandle].pfe->size;
  239. newPosition += off;
  240. break;
  241. case SEEK_CUR:
  242. newPosition = off+files[fastFileHandle].pos;
  243. break;
  244. }
  245. if (newPosition == -1)
  246. {
  247. return (INVALID_SEEK_ERR);
  248. }
  249. files[fastFileHandle].pos = newPosition;
  250. //-----------------------------------
  251. //-- Now macro seek the entire file.
  252. if (fseek(handle,files[fastFileHandle].pos + files[fastFileHandle].pfe->offset,SEEK_SET) == 0)
  253. logicalPosition = ftell(handle);
  254. return (files[fastFileHandle].pos);
  255. }
  256. return (FILE_NOT_OPEN);
  257. }
  258. //---------------------------------------------------------------------------
  259. long FastFile::readFast (long fastFileHandle, void *bfr, long size)
  260. {
  261. size;
  262. long result = 0;
  263. if ((fastFileHandle >= 0) && (fastFileHandle < numFiles) && files[fastFileHandle].inuse)
  264. {
  265. logicalPosition = fseek(handle,files[fastFileHandle].pos + files[fastFileHandle].pfe->offset,SEEK_SET);
  266. //ALL files in the fast file are now zLib compressed. NO EXCEPTIONS!!
  267. // This fixes a bug where the zLib Compressed version is the same length
  268. // as the raw version. Yikes but this is rare. Finally happened though!
  269. // -fs
  270. /*
  271. if (files[fastFileHandle].pfe->size == files[fastFileHandle].pfe->realSize)
  272. {
  273. result = fread(bfr,1,size,handle);
  274. logicalPosition += size;
  275. if (result != size)
  276. {
  277. long lastError = errno;
  278. return lastError;
  279. }
  280. }
  281. else //File is NOW zLib Compressed. Read In Appropriately
  282. */
  283. {
  284. if (!LZPacketBuffer)
  285. {
  286. LZPacketBuffer = (MemoryPtr)malloc(LZPacketBufferSize);
  287. if (!LZPacketBuffer)
  288. return 0;
  289. }
  290. if ((long)LZPacketBufferSize < files[fastFileHandle].pfe->size)
  291. {
  292. LZPacketBufferSize = files[fastFileHandle].pfe->size;
  293. free(LZPacketBuffer);
  294. LZPacketBuffer = (MemoryPtr)malloc(LZPacketBufferSize);
  295. if (!LZPacketBuffer)
  296. return 0;
  297. }
  298. if (LZPacketBuffer)
  299. {
  300. result = fread(LZPacketBuffer,1,files[fastFileHandle].pfe->size,handle);
  301. logicalPosition += files[fastFileHandle].pfe->size;
  302. if (result != files[fastFileHandle].pfe->size)
  303. {
  304. //READ Error. Maybe the CD is missing?
  305. bool openFailed = false;
  306. bool alreadyFullScreen = (Environment.fullScreen != 0);
  307. while (result != files[fastFileHandle].pfe->size)
  308. {
  309. openFailed = true;
  310. EnterWindowMode();
  311. char data[2048];
  312. sprintf(data,FileMissingString,fileName,CDMissingString);
  313. DWORD result1 = MessageBox(NULL,data,MissingTitleString,MB_OKCANCEL | MB_ICONWARNING);
  314. if (result1 == IDCANCEL)
  315. {
  316. ExitGameOS();
  317. return (2); //File not found. Never returns though!
  318. }
  319. logicalPosition = fseek(handle,files[fastFileHandle].pos + files[fastFileHandle].pfe->offset,SEEK_SET);
  320. result = fread(LZPacketBuffer,1,files[fastFileHandle].pfe->size,handle);
  321. logicalPosition += files[fastFileHandle].pfe->size;
  322. }
  323. if (openFailed && (Environment.fullScreen == 0) && alreadyFullScreen)
  324. EnterFullScreenMode();
  325. }
  326. //--------------------------------------------------------
  327. //USED to LZ Compress here. It is NOW zLib Compression.
  328. // We should not try to use old fastfiles becuase version check above should fail when trying to open!!
  329. unsigned long decompLength = 0;
  330. if (useLZCompress)
  331. {
  332. decompLength = LZDecomp((MemoryPtr)bfr,LZPacketBuffer,files[fastFileHandle].pfe->size);
  333. }
  334. else
  335. {
  336. decompLength = files[fastFileHandle].pfe->realSize;
  337. long error = uncompress((MemoryPtr)bfr,&decompLength,LZPacketBuffer,files[fastFileHandle].pfe->size);
  338. if (error != Z_OK)
  339. STOP(("Error %d UnCompressing File %s from FastFile %s",error,files[fastFileHandle].pfe->name,fileName));
  340. }
  341. if ((long)decompLength != files[fastFileHandle].pfe->realSize)
  342. result = 0;
  343. else
  344. result = decompLength;
  345. }
  346. }
  347. return result;
  348. }
  349. return FILE_NOT_OPEN;
  350. }
  351. //---------------------------------------------------------------------------
  352. // This function pulls the raw compressed data out of the file and sticks it in the buffer
  353. // passed in. This way, we can load the textures directly from file to RAM and not
  354. // have to decompress them!!
  355. long FastFile::readFastRAW (long fastFileHandle, void *bfr, long size)
  356. {
  357. size;
  358. long result = 0;
  359. if ((fastFileHandle >= 0) && (fastFileHandle < numFiles) && files[fastFileHandle].inuse)
  360. {
  361. logicalPosition = fseek(handle,files[fastFileHandle].pos + files[fastFileHandle].pfe->offset,SEEK_SET);
  362. if (size >= files[fastFileHandle].pfe->size)
  363. {
  364. result = fread(bfr,1,files[fastFileHandle].pfe->size,handle);
  365. logicalPosition += files[fastFileHandle].pfe->size;
  366. }
  367. if (result != files[fastFileHandle].pfe->size)
  368. {
  369. //READ Error. Maybe the CD is missing?
  370. bool openFailed = false;
  371. bool alreadyFullScreen = (Environment.fullScreen != 0);
  372. while (result != files[fastFileHandle].pfe->size)
  373. {
  374. openFailed = true;
  375. EnterWindowMode();
  376. char data[2048];
  377. sprintf(data,FileMissingString,fileName,CDMissingString);
  378. DWORD result1 = MessageBox(NULL,data,MissingTitleString,MB_OKCANCEL | MB_ICONWARNING);
  379. if (result1 == IDCANCEL)
  380. {
  381. ExitGameOS();
  382. return (2); //File not found. Never returns though!
  383. }
  384. logicalPosition = fseek(handle,files[fastFileHandle].pos + files[fastFileHandle].pfe->offset,SEEK_SET);
  385. result = fread(bfr,1,files[fastFileHandle].pfe->size,handle);
  386. logicalPosition += files[fastFileHandle].pfe->size;
  387. }
  388. if (openFailed && (Environment.fullScreen == 0) && alreadyFullScreen)
  389. EnterFullScreenMode();
  390. }
  391. return result;
  392. }
  393. return FILE_NOT_OPEN;
  394. }
  395. //---------------------------------------------------------------------------
  396. long FastFile::tellFast (long fastFileHandle)
  397. {
  398. if ((fastFileHandle >= 0) && (fastFileHandle < numFiles) && files[fastFileHandle].inuse)
  399. return files[fastFileHandle].pos;
  400. return -1;
  401. }
  402. //---------------------------------------------------------------------------
  403. long FastFile::sizeFast (long fastFileHandle)
  404. {
  405. if ((fastFileHandle >= 0) && (fastFileHandle < numFiles) && files[fastFileHandle].inuse)
  406. return files[fastFileHandle].pfe->realSize;
  407. return -1;
  408. }
  409. //---------------------------------------------------------------------------
  410. long FastFile::lzSizeFast (long fastFileHandle)
  411. {
  412. if ((fastFileHandle >= 0) && (fastFileHandle < numFiles) && files[fastFileHandle].inuse)
  413. return files[fastFileHandle].pfe->size;
  414. return -1;
  415. }
  416. //---------------------------------------------------------------------------
  417. //
  418. // Edit Log
  419. //
  420. //
  421. //---------------------------------------------------------------------------