w_wad.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code 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. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. #include <ctype.h>
  23. #include <sys/types.h>
  24. #include <string.h>
  25. #include <fcntl.h>
  26. #include <sys/stat.h>
  27. #include <vector>
  28. #include "doomtype.h"
  29. #include "m_swap.h"
  30. #include "i_system.h"
  31. #include "z_zone.h"
  32. #include "idlib/precompiled.h"
  33. #ifdef __GNUG__
  34. #pragma implementation "w_wad.h"
  35. #endif
  36. #include "w_wad.h"
  37. //
  38. // GLOBALS
  39. //
  40. lumpinfo_t* lumpinfo = NULL;
  41. int numlumps;
  42. void** lumpcache;
  43. int filelength (FILE* handle)
  44. {
  45. // DHM - not used :: development tool (loading single lump not in a WAD file)
  46. return 0;
  47. }
  48. void
  49. ExtractFileBase
  50. ( const char* path,
  51. char* dest )
  52. {
  53. const char* src;
  54. int length;
  55. src = path + strlen(path) - 1;
  56. // back up until a \ or the start
  57. while (src != path
  58. && *(src-1) != '\\'
  59. && *(src-1) != '/')
  60. {
  61. src--;
  62. }
  63. // copy up to eight characters
  64. memset (dest,0,8);
  65. length = 0;
  66. while (*src && *src != '.')
  67. {
  68. if (++length == 9)
  69. I_Error ("Filename base of %s >8 chars",path);
  70. *dest++ = toupper((int)*src++);
  71. }
  72. }
  73. //
  74. // LUMP BASED ROUTINES.
  75. //
  76. //
  77. // W_AddFile
  78. // All files are optional, but at least one file must be
  79. // found (PWAD, if all required lumps are present).
  80. // Files with a .wad extension are wadlink files
  81. // with multiple lumps.
  82. // Other files are single lumps with the base filename
  83. // for the lump name.
  84. //
  85. // If filename starts with a tilde, the file is handled
  86. // specially to allow map reloads.
  87. // But: the reload feature is a fragile hack...
  88. const char* reloadname;
  89. void W_AddFile ( const char *filename)
  90. {
  91. wadinfo_t header;
  92. lumpinfo_t* lump_p;
  93. int i;
  94. idFile * handle;
  95. int length;
  96. int startlump;
  97. std::vector<filelump_t> fileinfo( 1 );
  98. // open the file and add to directory
  99. if ( (handle = fileSystem->OpenFileRead(filename)) == 0)
  100. {
  101. I_Printf (" couldn't open %s\n",filename);
  102. return;
  103. }
  104. I_Printf (" adding %s\n",filename);
  105. startlump = numlumps;
  106. if ( idStr::Icmp( filename+strlen(filename)-3 , "wad" ) )
  107. {
  108. // single lump file
  109. fileinfo[0].filepos = 0;
  110. fileinfo[0].size = 0;
  111. ExtractFileBase (filename, fileinfo[0].name);
  112. numlumps++;
  113. }
  114. else
  115. {
  116. // WAD file
  117. handle->Read( &header, sizeof( header ) );
  118. if ( idStr::Cmpn( header.identification,"IWAD",4 ) )
  119. {
  120. // Homebrew levels?
  121. if ( idStr::Cmpn( header.identification, "PWAD", 4 ) )
  122. {
  123. I_Error ("Wad file %s doesn't have IWAD "
  124. "or PWAD id\n", filename);
  125. }
  126. // ???modifiedgame = true;
  127. }
  128. header.numlumps = LONG(header.numlumps);
  129. header.infotableofs = LONG(header.infotableofs);
  130. length = header.numlumps*sizeof(filelump_t);
  131. fileinfo.resize(header.numlumps);
  132. handle->Seek( header.infotableofs, FS_SEEK_SET );
  133. handle->Read( &fileinfo[0], length );
  134. numlumps += header.numlumps;
  135. }
  136. // Fill in lumpinfo
  137. if (lumpinfo == NULL) {
  138. lumpinfo = (lumpinfo_t*)malloc( numlumps*sizeof(lumpinfo_t) );
  139. } else {
  140. lumpinfo = (lumpinfo_t*)realloc( lumpinfo, numlumps*sizeof(lumpinfo_t) );
  141. }
  142. if (!lumpinfo)
  143. I_Error ("Couldn't realloc lumpinfo");
  144. lump_p = &lumpinfo[startlump];
  145. ::g->wadFileHandles[ ::g->numWadFiles++ ] = handle;
  146. filelump_t * filelumpPointer = &fileinfo[0];
  147. for (i=startlump ; i<numlumps ; i++,lump_p++, filelumpPointer++)
  148. {
  149. lump_p->handle = handle;
  150. lump_p->position = LONG(filelumpPointer->filepos);
  151. lump_p->size = LONG(filelumpPointer->size);
  152. strncpy (lump_p->name, filelumpPointer->name, 8);
  153. }
  154. }
  155. //
  156. // W_Reload
  157. // Flushes any of the reloadable lumps in memory
  158. // and reloads the directory.
  159. //
  160. void W_Reload (void)
  161. {
  162. // DHM - unused development tool
  163. }
  164. //
  165. // W_FreeLumps
  166. // Frees all lump data
  167. //
  168. void W_FreeLumps() {
  169. if ( lumpcache != NULL ) {
  170. for ( int i = 0; i < numlumps; i++ ) {
  171. if ( lumpcache[i] ) {
  172. Z_Free( lumpcache[i] );
  173. }
  174. }
  175. Z_Free( lumpcache );
  176. lumpcache = NULL;
  177. }
  178. if ( lumpinfo != NULL ) {
  179. free( lumpinfo );
  180. lumpinfo = NULL;
  181. numlumps = 0;
  182. }
  183. }
  184. //
  185. // W_FreeWadFiles
  186. // Free this list of wad files so that a new list can be created
  187. //
  188. void W_FreeWadFiles() {
  189. for (int i = 0 ; i < MAXWADFILES ; i++) {
  190. wadfiles[i] = NULL;
  191. if ( ::g->wadFileHandles[i] ) {
  192. delete ::g->wadFileHandles[i];
  193. }
  194. ::g->wadFileHandles[i] = NULL;
  195. }
  196. ::g->numWadFiles = 0;
  197. extraWad = 0;
  198. }
  199. //
  200. // W_InitMultipleFiles
  201. // Pass a null terminated list of files to use.
  202. // All files are optional, but at least one file
  203. // must be found.
  204. // Files with a .wad extension are idlink files
  205. // with multiple lumps.
  206. // Other files are single lumps with the base filename
  207. // for the lump name.
  208. // Lump names can appear multiple times.
  209. // The name searcher looks backwards, so a later file
  210. // does override all earlier ones.
  211. //
  212. void W_InitMultipleFiles (const char** filenames)
  213. {
  214. int size;
  215. if (lumpinfo == NULL)
  216. {
  217. // open all the files, load headers, and count lumps
  218. numlumps = 0;
  219. // will be realloced as lumps are added
  220. lumpinfo = NULL;
  221. for ( ; *filenames ; filenames++)
  222. {
  223. W_AddFile (*filenames);
  224. }
  225. if (!numlumps)
  226. I_Error ("W_InitMultipleFiles: no files found");
  227. // set up caching
  228. size = numlumps * sizeof(*lumpcache);
  229. lumpcache = (void**)DoomLib::Z_Malloc(size, PU_STATIC_SHARED, 0 );
  230. if (!lumpcache)
  231. I_Error ("Couldn't allocate lumpcache");
  232. memset (lumpcache,0, size);
  233. } else {
  234. // set up caching
  235. size = numlumps * sizeof(*lumpcache);
  236. lumpcache = (void**)DoomLib::Z_Malloc(size, PU_STATIC_SHARED, 0 );
  237. if (!lumpcache)
  238. I_Error ("Couldn't allocate lumpcache");
  239. memset (lumpcache,0, size);
  240. }
  241. }
  242. void W_Shutdown( void ) {
  243. /*
  244. for (int i = 0 ; i < MAXWADFILES ; i++) {
  245. if ( ::g->wadFileHandles[i] ) {
  246. doomFiles->FClose( ::g->wadFileHandles[i] );
  247. }
  248. }
  249. if ( lumpinfo != NULL ) {
  250. free( lumpinfo );
  251. lumpinfo = NULL;
  252. }
  253. */
  254. W_FreeLumps();
  255. W_FreeWadFiles();
  256. }
  257. //
  258. // W_NumLumps
  259. //
  260. int W_NumLumps (void)
  261. {
  262. return numlumps;
  263. }
  264. //
  265. // W_CheckNumForName
  266. // Returns -1 if name not found.
  267. //
  268. int W_CheckNumForName (const char* name)
  269. {
  270. const int NameLength = 9;
  271. union {
  272. char s[NameLength];
  273. int x[2];
  274. } name8;
  275. int v1;
  276. int v2;
  277. lumpinfo_t* lump_p;
  278. // make the name into two integers for easy compares
  279. strncpy (name8.s,name, NameLength - 1);
  280. // in case the name was a fill 8 chars
  281. name8.s[NameLength - 1] = 0;
  282. // case insensitive
  283. for ( int i = 0; i < NameLength; ++i ) {
  284. name8.s[i] = toupper( name8.s[i] );
  285. }
  286. v1 = name8.x[0];
  287. v2 = name8.x[1];
  288. // scan backwards so patch lump files take precedence
  289. lump_p = lumpinfo + numlumps;
  290. while (lump_p-- != lumpinfo)
  291. {
  292. if ( *(int *)lump_p->name == v1
  293. && *(int *)&lump_p->name[4] == v2)
  294. {
  295. return lump_p - lumpinfo;
  296. }
  297. }
  298. // TFB. Not found.
  299. return -1;
  300. }
  301. //
  302. // W_GetNumForName
  303. // Calls W_CheckNumForName, but bombs out if not found.
  304. //
  305. int W_GetNumForName ( const char* name)
  306. {
  307. int i;
  308. i = W_CheckNumForName ( name);
  309. if (i == -1)
  310. I_Error ("W_GetNumForName: %s not found!", name);
  311. return i;
  312. }
  313. //
  314. // W_LumpLength
  315. // Returns the buffer size needed to load the given lump.
  316. //
  317. int W_LumpLength (int lump)
  318. {
  319. if (lump >= numlumps)
  320. I_Error ("W_LumpLength: %i >= numlumps",lump);
  321. return lumpinfo[lump].size;
  322. }
  323. //
  324. // W_ReadLump
  325. // Loads the lump into the given buffer,
  326. // which must be >= W_LumpLength().
  327. //
  328. void
  329. W_ReadLump
  330. ( int lump,
  331. void* dest )
  332. {
  333. int c;
  334. lumpinfo_t* l;
  335. idFile * handle;
  336. if (lump >= numlumps)
  337. I_Error ("W_ReadLump: %i >= numlumps",lump);
  338. l = lumpinfo+lump;
  339. handle = l->handle;
  340. handle->Seek( l->position, FS_SEEK_SET );
  341. c = handle->Read( dest, l->size );
  342. if (c < l->size)
  343. I_Error ("W_ReadLump: only read %i of %i on lump %i", c,l->size,lump);
  344. }
  345. //
  346. // W_CacheLumpNum
  347. //
  348. void*
  349. W_CacheLumpNum
  350. ( int lump,
  351. int tag )
  352. {
  353. #ifdef RANGECHECK
  354. if (lump >= numlumps)
  355. I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
  356. #endif
  357. if (!lumpcache[lump])
  358. {
  359. byte* ptr;
  360. // read the lump in
  361. //I_Printf ("cache miss on lump %i\n",lump);
  362. ptr = (byte*)DoomLib::Z_Malloc(W_LumpLength (lump), tag, &lumpcache[lump]);
  363. W_ReadLump (lump, lumpcache[lump]);
  364. }
  365. return lumpcache[lump];
  366. }
  367. //
  368. // W_CacheLumpName
  369. //
  370. void*
  371. W_CacheLumpName
  372. ( const char* name,
  373. int tag )
  374. {
  375. return W_CacheLumpNum (W_GetNumForName(name), tag);
  376. }
  377. void W_Profile (void)
  378. {
  379. }