W_WAD.C 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. //**************************************************************************
  2. //**
  3. //** w_wad.c : Heretic 2 : Raven Software, Corp.
  4. //**
  5. //** $RCSfile: w_wad.c,v $
  6. //** $Revision: 1.6 $
  7. //** $Date: 95/10/06 20:56:47 $
  8. //** $Author: cjr $
  9. //**
  10. //**************************************************************************
  11. // HEADER FILES ------------------------------------------------------------
  12. #ifdef NeXT
  13. #include <libc.h>
  14. #include <ctype.h>
  15. #else
  16. #include <malloc.h>
  17. #include <io.h>
  18. #include <fcntl.h>
  19. #include <sys/stat.h>
  20. #endif
  21. #include "h2def.h"
  22. // MACROS ------------------------------------------------------------------
  23. #ifdef NeXT
  24. // NeXT doesn't need a binary flag in open call
  25. #define O_BINARY 0
  26. #define strcmpi strcasecmp
  27. #endif
  28. // TYPES -------------------------------------------------------------------
  29. typedef struct
  30. {
  31. char identification[4];
  32. int numlumps;
  33. int infotableofs;
  34. } wadinfo_t;
  35. typedef struct
  36. {
  37. int filepos;
  38. int size;
  39. char name[8];
  40. } filelump_t;
  41. // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
  42. // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
  43. // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
  44. // EXTERNAL DATA DECLARATIONS ----------------------------------------------
  45. // PUBLIC DATA DEFINITIONS -------------------------------------------------
  46. lumpinfo_t *lumpinfo;
  47. int numlumps;
  48. void **lumpcache;
  49. // PRIVATE DATA DEFINITIONS ------------------------------------------------
  50. static lumpinfo_t *PrimaryLumpInfo;
  51. static int PrimaryNumLumps;
  52. static void **PrimaryLumpCache;
  53. static lumpinfo_t *AuxiliaryLumpInfo;
  54. static int AuxiliaryNumLumps;
  55. static void **AuxiliaryLumpCache;
  56. static int AuxiliaryHandle = 0;
  57. boolean AuxiliaryOpened = false;
  58. // CODE --------------------------------------------------------------------
  59. #ifdef NeXT
  60. //==========================================================================
  61. //
  62. // strupr
  63. //
  64. //==========================================================================
  65. void strupr(char *s)
  66. {
  67. while(*s)
  68. *s++ = toupper(*s);
  69. }
  70. //==========================================================================
  71. //
  72. // filelength
  73. //
  74. //==========================================================================
  75. int filelength(int handle)
  76. {
  77. struct stat fileinfo;
  78. if(fstat(handle, &fileinfo) == -1)
  79. {
  80. I_Error("Error fstating");
  81. }
  82. return fileinfo.st_size;
  83. }
  84. #endif
  85. //==========================================================================
  86. //
  87. // W_AddFile
  88. //
  89. // Files with a .wad extension are wadlink files with multiple lumps,
  90. // other files are single lumps with the base filename for the lump name.
  91. //
  92. //==========================================================================
  93. void W_AddFile(char *filename)
  94. {
  95. wadinfo_t header;
  96. lumpinfo_t *lump_p;
  97. unsigned i;
  98. int handle, length;
  99. int startlump;
  100. filelump_t *fileinfo, singleinfo;
  101. filelump_t *freeFileInfo;
  102. if((handle = open(filename, O_RDONLY|O_BINARY)) == -1)
  103. { // Didn't find file
  104. return;
  105. }
  106. startlump = numlumps;
  107. if(strcmpi(filename+strlen(filename)-3, "wad"))
  108. { // Single lump file
  109. fileinfo = &singleinfo;
  110. freeFileInfo = NULL;
  111. singleinfo.filepos = 0;
  112. singleinfo.size = LONG(filelength(handle));
  113. M_ExtractFileBase(filename, singleinfo.name);
  114. numlumps++;
  115. }
  116. else
  117. { // WAD file
  118. read(handle, &header, sizeof(header));
  119. if(strncmp(header.identification, "IWAD", 4))
  120. {
  121. if(strncmp(header.identification, "PWAD", 4))
  122. { // Bad file id
  123. I_Error("Wad file %s doesn't have IWAD or PWAD id\n",
  124. filename);
  125. }
  126. }
  127. header.numlumps = LONG(header.numlumps);
  128. header.infotableofs = LONG(header.infotableofs);
  129. length = header.numlumps*sizeof(filelump_t);
  130. // fileinfo = alloca(length);
  131. if(!(fileinfo = malloc(length)))
  132. {
  133. I_Error("W_AddFile: fileinfo malloc failed\n");
  134. }
  135. freeFileInfo = fileinfo;
  136. lseek(handle, header.infotableofs, SEEK_SET);
  137. read(handle, fileinfo, length);
  138. numlumps += header.numlumps;
  139. }
  140. // Fill in lumpinfo
  141. lumpinfo = realloc(lumpinfo, numlumps*sizeof(lumpinfo_t));
  142. if(!lumpinfo)
  143. {
  144. I_Error("Couldn't realloc lumpinfo");
  145. }
  146. lump_p = &lumpinfo[startlump];
  147. for(i = startlump; i < numlumps; i++, lump_p++, fileinfo++)
  148. {
  149. lump_p->handle = handle;
  150. lump_p->position = LONG(fileinfo->filepos);
  151. lump_p->size = LONG(fileinfo->size);
  152. strncpy(lump_p->name, fileinfo->name, 8);
  153. }
  154. if(freeFileInfo)
  155. {
  156. free(freeFileInfo);
  157. }
  158. }
  159. //==========================================================================
  160. //
  161. // W_InitMultipleFiles
  162. //
  163. // Pass a null terminated list of files to use. All files are optional,
  164. // but at least one file must be found. Lump names can appear multiple
  165. // times. The name searcher looks backwards, so a later file can
  166. // override an earlier one.
  167. //
  168. //==========================================================================
  169. void W_InitMultipleFiles(char **filenames)
  170. {
  171. int size;
  172. // Open all the files, load headers, and count lumps
  173. numlumps = 0;
  174. lumpinfo = malloc(1); // Will be realloced as lumps are added
  175. for(; *filenames; filenames++)
  176. {
  177. W_AddFile(*filenames);
  178. }
  179. if(!numlumps)
  180. {
  181. I_Error("W_InitMultipleFiles: no files found");
  182. }
  183. // Set up caching
  184. size = numlumps*sizeof(*lumpcache);
  185. lumpcache = malloc(size);
  186. if(!lumpcache)
  187. {
  188. I_Error("Couldn't allocate lumpcache");
  189. }
  190. memset(lumpcache, 0, size);
  191. PrimaryLumpInfo = lumpinfo;
  192. PrimaryLumpCache = lumpcache;
  193. PrimaryNumLumps = numlumps;
  194. }
  195. //==========================================================================
  196. //
  197. // W_InitFile
  198. //
  199. // Initialize the primary from a single file.
  200. //
  201. //==========================================================================
  202. void W_InitFile(char *filename)
  203. {
  204. char *names[2];
  205. names[0] = filename;
  206. names[1] = NULL;
  207. W_InitMultipleFiles(names);
  208. }
  209. //==========================================================================
  210. //
  211. // W_OpenAuxiliary
  212. //
  213. //==========================================================================
  214. void W_OpenAuxiliary(char *filename)
  215. {
  216. int i;
  217. int size;
  218. wadinfo_t header;
  219. int handle;
  220. int length;
  221. filelump_t *fileinfo;
  222. filelump_t *sourceLump;
  223. lumpinfo_t *destLump;
  224. if(AuxiliaryOpened)
  225. {
  226. W_CloseAuxiliary();
  227. }
  228. if((handle = open(filename, O_RDONLY|O_BINARY)) == -1)
  229. {
  230. I_Error("W_OpenAuxiliary: %s not found.", filename);
  231. return;
  232. }
  233. AuxiliaryHandle = handle;
  234. read(handle, &header, sizeof(header));
  235. if(strncmp(header.identification, "IWAD", 4))
  236. {
  237. if(strncmp(header.identification, "PWAD", 4))
  238. { // Bad file id
  239. I_Error("Wad file %s doesn't have IWAD or PWAD id\n",
  240. filename);
  241. }
  242. }
  243. header.numlumps = LONG(header.numlumps);
  244. header.infotableofs = LONG(header.infotableofs);
  245. length = header.numlumps*sizeof(filelump_t);
  246. fileinfo = Z_Malloc(length, PU_STATIC, 0);
  247. lseek(handle, header.infotableofs, SEEK_SET);
  248. read(handle, fileinfo, length);
  249. numlumps = header.numlumps;
  250. // Init the auxiliary lumpinfo array
  251. lumpinfo = Z_Malloc(numlumps*sizeof(lumpinfo_t), PU_STATIC, 0);
  252. sourceLump = fileinfo;
  253. destLump = lumpinfo;
  254. for(i = 0; i < numlumps; i++, destLump++, sourceLump++)
  255. {
  256. destLump->handle = handle;
  257. destLump->position = LONG(sourceLump->filepos);
  258. destLump->size = LONG(sourceLump->size);
  259. strncpy(destLump->name, sourceLump->name, 8);
  260. }
  261. Z_Free(fileinfo);
  262. // Allocate the auxiliary lumpcache array
  263. size = numlumps*sizeof(*lumpcache);
  264. lumpcache = Z_Malloc(size, PU_STATIC, 0);
  265. memset(lumpcache, 0, size);
  266. AuxiliaryLumpInfo = lumpinfo;
  267. AuxiliaryLumpCache = lumpcache;
  268. AuxiliaryNumLumps = numlumps;
  269. AuxiliaryOpened = true;
  270. }
  271. //==========================================================================
  272. //
  273. // W_CloseAuxiliary
  274. //
  275. //==========================================================================
  276. void W_CloseAuxiliary(void)
  277. {
  278. int i;
  279. if(AuxiliaryOpened)
  280. {
  281. W_UseAuxiliary();
  282. for(i = 0; i < numlumps; i++)
  283. {
  284. if(lumpcache[i])
  285. {
  286. Z_Free(lumpcache[i]);
  287. }
  288. }
  289. Z_Free(AuxiliaryLumpInfo);
  290. Z_Free(AuxiliaryLumpCache);
  291. W_CloseAuxiliaryFile();
  292. AuxiliaryOpened = false;
  293. }
  294. W_UsePrimary();
  295. }
  296. //==========================================================================
  297. //
  298. // W_CloseAuxiliaryFile
  299. //
  300. // WARNING: W_CloseAuxiliary() must be called before any further
  301. // auxiliary lump processing.
  302. //
  303. //==========================================================================
  304. void W_CloseAuxiliaryFile(void)
  305. {
  306. if(AuxiliaryHandle)
  307. {
  308. close(AuxiliaryHandle);
  309. AuxiliaryHandle = 0;
  310. }
  311. }
  312. //==========================================================================
  313. //
  314. // W_UsePrimary
  315. //
  316. //==========================================================================
  317. void W_UsePrimary(void)
  318. {
  319. lumpinfo = PrimaryLumpInfo;
  320. numlumps = PrimaryNumLumps;
  321. lumpcache = PrimaryLumpCache;
  322. }
  323. //==========================================================================
  324. //
  325. // W_UseAuxiliary
  326. //
  327. //==========================================================================
  328. void W_UseAuxiliary(void)
  329. {
  330. if(AuxiliaryOpened == false)
  331. {
  332. I_Error("W_UseAuxiliary: WAD not opened.");
  333. }
  334. lumpinfo = AuxiliaryLumpInfo;
  335. numlumps = AuxiliaryNumLumps;
  336. lumpcache = AuxiliaryLumpCache;
  337. }
  338. //==========================================================================
  339. //
  340. // W_NumLumps
  341. //
  342. //==========================================================================
  343. int W_NumLumps(void)
  344. {
  345. return numlumps;
  346. }
  347. //==========================================================================
  348. //
  349. // W_CheckNumForName
  350. //
  351. // Returns -1 if name not found.
  352. //
  353. //==========================================================================
  354. int W_CheckNumForName(char *name)
  355. {
  356. char name8[9];
  357. int v1, v2;
  358. lumpinfo_t *lump_p;
  359. // Make the name into two integers for easy compares
  360. strncpy(name8, name, 8);
  361. name8[8] = 0; // in case the name was a full 8 chars
  362. strupr(name8); // case insensitive
  363. v1 = *(int *)name8;
  364. v2 = *(int *)&name8[4];
  365. // Scan backwards so patch lump files take precedence
  366. lump_p = lumpinfo+numlumps;
  367. while(lump_p-- != lumpinfo)
  368. {
  369. if(*(int *)lump_p->name == v1 && *(int *)&lump_p->name[4] == v2)
  370. {
  371. return lump_p-lumpinfo;
  372. }
  373. }
  374. return -1;
  375. }
  376. //==========================================================================
  377. //
  378. // W_GetNumForName
  379. //
  380. // Calls W_CheckNumForName, but bombs out if not found.
  381. //
  382. //==========================================================================
  383. int W_GetNumForName (char *name)
  384. {
  385. int i;
  386. i = W_CheckNumForName(name);
  387. if(i != -1)
  388. {
  389. return i;
  390. }
  391. I_Error("W_GetNumForName: %s not found!", name);
  392. return -1;
  393. }
  394. //==========================================================================
  395. //
  396. // W_LumpLength
  397. //
  398. // Returns the buffer size needed to load the given lump.
  399. //
  400. //==========================================================================
  401. int W_LumpLength(int lump)
  402. {
  403. if(lump >= numlumps)
  404. {
  405. I_Error("W_LumpLength: %i >= numlumps", lump);
  406. }
  407. return lumpinfo[lump].size;
  408. }
  409. //==========================================================================
  410. //
  411. // W_ReadLump
  412. //
  413. // Loads the lump into the given buffer, which must be >= W_LumpLength().
  414. //
  415. //==========================================================================
  416. void W_ReadLump(int lump, void *dest)
  417. {
  418. int c;
  419. lumpinfo_t *l;
  420. if(lump >= numlumps)
  421. {
  422. I_Error("W_ReadLump: %i >= numlumps", lump);
  423. }
  424. l = lumpinfo+lump;
  425. //I_BeginRead();
  426. lseek(l->handle, l->position, SEEK_SET);
  427. c = read(l->handle, dest, l->size);
  428. if(c < l->size)
  429. {
  430. I_Error("W_ReadLump: only read %i of %i on lump %i",
  431. c, l->size, lump);
  432. }
  433. //I_EndRead();
  434. }
  435. //==========================================================================
  436. //
  437. // W_CacheLumpNum
  438. //
  439. //==========================================================================
  440. void *W_CacheLumpNum(int lump, int tag)
  441. {
  442. byte *ptr;
  443. if((unsigned)lump >= numlumps)
  444. {
  445. I_Error("W_CacheLumpNum: %i >= numlumps", lump);
  446. }
  447. if(!lumpcache[lump])
  448. { // Need to read the lump in
  449. ptr = Z_Malloc(W_LumpLength(lump), tag, &lumpcache[lump]);
  450. W_ReadLump(lump, lumpcache[lump]);
  451. }
  452. else
  453. {
  454. Z_ChangeTag(lumpcache[lump], tag);
  455. }
  456. return lumpcache[lump];
  457. }
  458. //==========================================================================
  459. //
  460. // W_CacheLumpName
  461. //
  462. //==========================================================================
  463. void *W_CacheLumpName(char *name, int tag)
  464. {
  465. return W_CacheLumpNum(W_GetNumForName(name), tag);
  466. }
  467. //==========================================================================
  468. //
  469. // W_Profile
  470. //
  471. //==========================================================================
  472. // Ripped out for Heretic
  473. /*
  474. int info[2500][10];
  475. int profilecount;
  476. void W_Profile (void)
  477. {
  478. int i;
  479. memblock_t *block;
  480. void *ptr;
  481. char ch;
  482. FILE *f;
  483. int j;
  484. char name[9];
  485. for (i=0 ; i<numlumps ; i++)
  486. {
  487. ptr = lumpcache[i];
  488. if (!ptr)
  489. {
  490. ch = ' ';
  491. continue;
  492. }
  493. else
  494. {
  495. block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
  496. if (block->tag < PU_PURGELEVEL)
  497. ch = 'S';
  498. else
  499. ch = 'P';
  500. }
  501. info[i][profilecount] = ch;
  502. }
  503. profilecount++;
  504. f = fopen ("waddump.txt","w");
  505. name[8] = 0;
  506. for (i=0 ; i<numlumps ; i++)
  507. {
  508. memcpy (name,lumpinfo[i].name,8);
  509. for (j=0 ; j<8 ; j++)
  510. if (!name[j])
  511. break;
  512. for ( ; j<8 ; j++)
  513. name[j] = ' ';
  514. fprintf (f,"%s ",name);
  515. for (j=0 ; j<profilecount ; j++)
  516. fprintf (f," %c",info[i][j]);
  517. fprintf (f,"\n");
  518. }
  519. fclose (f);
  520. }
  521. */