w_wad.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:11k
源码类别:

射击游戏

开发平台:

Visual C++

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. // Handles WAD file header, directory, lump I/O.
  21. //
  22. //-----------------------------------------------------------------------------
  23. static const char
  24. rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $";
  25. #ifdef NORMALUNIX
  26. #include <ctype.h>
  27. #include <sys/types.h>
  28. #include <string.h>
  29. #include <unistd.h>
  30. #include <malloc.h>
  31. #include <fcntl.h>
  32. #include <sys/stat.h>
  33. #include <alloca.h>
  34. #define O_BINARY 0
  35. #else
  36.    #include <stdio.h>
  37.    #include <stdlib.h>
  38.    #include <io.h>
  39.    #include <malloc.h>
  40.    #include <string.h>
  41.    #include <sys/types.h>
  42.    #include <sys/stat.h>
  43.    #include <fcntl.h>
  44. #endif
  45. #include "doomtype.h"
  46. #include "m_swap.h"
  47. #include "i_system.h"
  48. #include "z_zone.h"
  49. #ifdef __GNUG__
  50. #pragma implementation "w_wad.h"
  51. #endif
  52. #include "w_wad.h"
  53. char MsgText[256];
  54. void WriteDebug(char *);
  55. //
  56. // GLOBALS
  57. //
  58. // Location of each lump on disk.
  59. lumpinfo_t* lumpinfo;
  60. int numlumps;
  61. void** lumpcache;
  62. //#define strcmpi strcasecmp // This is a redefinition of a standard 'C' function -- not necessary...
  63. //void strupr (char* s)
  64. //{
  65. //    while (*s) { *s = toupper(*s); s++; }
  66. //}
  67. /* This is a redefinition of a standard 'C' function -- not necessary...
  68. int filelength (int handle) 
  69.     struct stat fileinfo;
  70.     
  71.     if (fstat (handle,&fileinfo) == -1)
  72. I_Error ("Error fstating");
  73.     return fileinfo.st_size;
  74. }
  75. */
  76. void
  77. ExtractFileBase
  78. ( char* path,
  79.   char* dest )
  80. {
  81.     char* src;
  82.     int length;
  83.     src = path + strlen(path) - 1;
  84.     
  85.     // back up until a  or the start
  86.     while (src != path
  87.    && *(src-1) != '\'
  88.    && *(src-1) != '/')
  89.     {
  90. src--;
  91.     }
  92.     
  93.     // copy up to eight characters
  94.     memset (dest,0,8);
  95.     length = 0;
  96.     
  97.     while (*src && *src != '.')
  98.     {
  99. if (++length == 9)
  100.     I_Error ("Filename base of %s >8 chars",path);
  101. *dest++ = toupper((int)*src++);
  102.     }
  103. }
  104. //
  105. // LUMP BASED ROUTINES.
  106. //
  107. //
  108. // W_AddFile
  109. // All files are optional, but at least one file must be
  110. //  found (PWAD, if all required lumps are present).
  111. // Files with a .wad extension are wadlink files
  112. //  with multiple lumps.
  113. // Other files are single lumps with the base filename
  114. //  for the lump name.
  115. //
  116. // If filename starts with a tilde, the file is handled
  117. //  specially to allow map reloads.
  118. // But: the reload feature is a fragile hack...
  119. int reloadlump;
  120. char* reloadname;
  121. void W_AddFile (char *filename)
  122. {
  123.     wadinfo_t header;
  124.     lumpinfo_t* lump_p;
  125.     unsigned i;
  126.     int handle;
  127.     int length;
  128.     int startlump;
  129.     filelump_t* fileinfo;
  130.     filelump_t singleinfo;
  131.     int storehandle;
  132.     
  133.     // open the file and add to directory
  134.     // handle reload indicator.
  135.     if (filename[0] == '~')
  136.     {
  137. filename++;
  138. reloadname = filename;
  139. reloadlump = numlumps;
  140.     }
  141.     if ( (handle = open (filename,O_RDONLY | O_BINARY)) == -1)
  142.     {
  143. printf (" couldn't open %sn",filename);
  144. return;
  145.     }
  146.     sprintf (MsgText," adding %sn",filename);
  147.     WriteDebug(MsgText);
  148.     startlump = numlumps;
  149.     if (strcmpi (filename+strlen(filename)-3 , "wad" ) )
  150.     {
  151. // single lump file
  152. fileinfo = &singleinfo;
  153. singleinfo.filepos = 0;
  154. singleinfo.size = LONG(filelength(handle));
  155. ExtractFileBase (filename, singleinfo.name);
  156. numlumps++;
  157.     }
  158.     else 
  159.     {
  160. // WAD file
  161. read (handle, &header, sizeof(header));
  162. if (strncmp(header.identification,"IWAD",4))
  163. {
  164.     // Homebrew levels?
  165.     if (strncmp(header.identification,"PWAD",4))
  166.     {
  167. I_Error ("Wad file %s doesn't have IWAD "
  168.  "or PWAD idn", filename);
  169.     }
  170.     
  171.     // ???modifiedgame = true;
  172. }
  173. header.numlumps = LONG(header.numlumps);
  174. header.infotableofs = LONG(header.infotableofs);
  175. length = header.numlumps*sizeof(filelump_t);
  176. fileinfo = alloca (length);
  177. lseek (handle, header.infotableofs, SEEK_SET);
  178. read (handle, fileinfo, length);
  179. numlumps += header.numlumps;
  180.     }
  181.     
  182.     // Fill in lumpinfo
  183.     lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
  184.     if (!lumpinfo)
  185. I_Error ("Couldn't realloc lumpinfo");
  186.     lump_p = &lumpinfo[startlump];
  187.     storehandle = reloadname ? -1 : handle;
  188.     for (i=startlump ; (int)i<numlumps ; i++,lump_p++, fileinfo++)
  189.     {
  190. lump_p->handle = storehandle;
  191. lump_p->position = LONG(fileinfo->filepos);
  192. lump_p->size = LONG(fileinfo->size);
  193. strncpy (lump_p->name, fileinfo->name, 8);
  194.     }
  195.     if (reloadname)
  196. close (handle);
  197. }
  198. //
  199. // W_Reload
  200. // Flushes any of the reloadable lumps in memory
  201. //  and reloads the directory.
  202. //
  203. void W_Reload (void)
  204. {
  205.     wadinfo_t header;
  206.     int lumpcount;
  207.     lumpinfo_t* lump_p;
  208.     unsigned i;
  209.     int handle;
  210.     int length;
  211.     filelump_t* fileinfo;
  212.     if (!reloadname)
  213. return;
  214.     if ( (handle = open (reloadname,O_RDONLY | O_BINARY)) == -1)
  215. I_Error ("W_Reload: couldn't open %s",reloadname);
  216.     read (handle, &header, sizeof(header));
  217.     lumpcount = LONG(header.numlumps);
  218.     header.infotableofs = LONG(header.infotableofs);
  219.     length = lumpcount*sizeof(filelump_t);
  220.     fileinfo = alloca (length);
  221.     lseek (handle, header.infotableofs, SEEK_SET);
  222.     read (handle, fileinfo, length);
  223.     
  224.     // Fill in lumpinfo
  225.     lump_p = &lumpinfo[reloadlump];
  226.     for (i=reloadlump ;
  227.  (int)i<reloadlump+lumpcount ;
  228.  i++,lump_p++, fileinfo++)
  229.     {
  230. if (lumpcache[i])
  231.     Z_Free (lumpcache[i]);
  232. lump_p->position = LONG(fileinfo->filepos);
  233. lump_p->size = LONG(fileinfo->size);
  234.     }
  235.     close (handle);
  236. }
  237. //
  238. // W_InitMultipleFiles
  239. // Pass a null terminated list of files to use.
  240. // All files are optional, but at least one file
  241. //  must be found.
  242. // Files with a .wad extension are idlink files
  243. //  with multiple lumps.
  244. // Other files are single lumps with the base filename
  245. //  for the lump name.
  246. // Lump names can appear multiple times.
  247. // The name searcher looks backwards, so a later file
  248. //  does override all earlier ones.
  249. //
  250. void W_InitMultipleFiles (char** filenames)
  251. {
  252.     int size;
  253.     
  254.     // open all the files, load headers, and count lumps
  255.     numlumps = 0;
  256.     // will be realloced as lumps are added
  257.     lumpinfo = malloc(1);
  258.     for ( ; *filenames ; filenames++)
  259. W_AddFile (*filenames);
  260.     if (!numlumps)
  261. I_Error ("W_InitFiles: no files found");
  262.     
  263.     // set up caching
  264.     size = numlumps * sizeof(*lumpcache);
  265.     lumpcache = malloc (size);
  266.     
  267.     if (!lumpcache)
  268. I_Error ("Couldn't allocate lumpcache");
  269.     memset (lumpcache,0, size);
  270. }
  271. //
  272. // W_InitFile
  273. // Just initialize from a single file.
  274. //
  275. void W_InitFile (char* filename)
  276. {
  277.     char* names[2];
  278.     names[0] = filename;
  279.     names[1] = NULL;
  280.     W_InitMultipleFiles (names);
  281. }
  282. //
  283. // W_NumLumps
  284. //
  285. int W_NumLumps (void)
  286. {
  287.     return numlumps;
  288. }
  289. //
  290. // W_CheckNumForName
  291. // Returns -1 if name not found.
  292. //
  293. int W_CheckNumForName (char* name)
  294. {
  295.     union {
  296. char s[9];
  297. int x[2];
  298.     } name8;
  299.     
  300.     int v1;
  301.     int v2;
  302.     lumpinfo_t* lump_p;
  303.     // make the name into two integers for easy compares
  304.     strncpy (name8.s,name,8);
  305.     // in case the name was a full 8 chars
  306.     name8.s[8] = 0;
  307.     // case insensitive
  308.     strupr (name8.s);
  309.     v1 = name8.x[0];
  310.     v2 = name8.x[1];
  311.     // scan backwards so patch lump files take precedence
  312.     lump_p = lumpinfo + numlumps;
  313.     while (lump_p-- != lumpinfo)
  314.     {
  315. if ( *(int *)lump_p->name == v1
  316.      && *(int *)&lump_p->name[4] == v2)
  317. {
  318.     return lump_p - lumpinfo;
  319. }
  320.     }
  321.     // TFB. Not found.
  322.     return -1;
  323. }
  324. //
  325. // W_GetNumForName
  326. // Calls W_CheckNumForName, but bombs out if not found.
  327. //
  328. int W_GetNumForName (char* name)
  329. {
  330.     int i;
  331.     i = W_CheckNumForName (name);
  332.     
  333.     if (i == -1)
  334.       I_Error ("W_GetNumForName: %s not found!", name);
  335.       
  336.     return i;
  337. }
  338. //
  339. // W_LumpLength
  340. // Returns the buffer size needed to load the given lump.
  341. //
  342. int W_LumpLength (int lump)
  343. {
  344.     if (lump >= numlumps)
  345. I_Error ("W_LumpLength: %i >= numlumps",lump);
  346.     return lumpinfo[lump].size;
  347. }
  348. //
  349. // W_ReadLump
  350. // Loads the lump into the given buffer,
  351. //  which must be >= W_LumpLength().
  352. //
  353. void
  354. W_ReadLump
  355. ( int lump,
  356.   void* dest )
  357. {
  358.     int c;
  359.     lumpinfo_t* l;
  360.     int handle;
  361.     if (lump >= numlumps)
  362. I_Error ("W_ReadLump: %i >= numlumps",lump);
  363.     l = lumpinfo+lump;
  364.     // ??? I_BeginRead ();
  365.     if (l->handle == -1)
  366.     {
  367. // reloadable file, so use open / read / close
  368. if ( (handle = open (reloadname,O_RDONLY | O_BINARY)) == -1)
  369.     I_Error ("W_ReadLump: couldn't open %s",reloadname);
  370.     }
  371.     else
  372. handle = l->handle;
  373.     lseek (handle, l->position, SEEK_SET);
  374.     c = read (handle, dest, l->size);
  375.     if (c < l->size)
  376. I_Error ("W_ReadLump: only read %i of %i on lump %i",
  377.  c,l->size,lump);
  378.     if (l->handle == -1)
  379. close (handle);
  380.     // ??? I_EndRead ();
  381. }
  382. //
  383. // W_CacheLumpNum
  384. //
  385. void*
  386. W_CacheLumpNum
  387. ( int lump,
  388.   int tag )
  389. {
  390.     byte* ptr;
  391.     if ((unsigned)lump >= (unsigned)numlumps)
  392. I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
  393.     if (!lumpcache[lump])
  394.     {
  395. // read the lump in
  396. //printf ("cache miss on lump %in",lump);
  397. ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
  398. W_ReadLump (lump, lumpcache[lump]);
  399.     }
  400.     else
  401.     {
  402. //printf ("cache hit on lump %in",lump);
  403. Z_ChangeTag (lumpcache[lump],tag);
  404.     }
  405.     return lumpcache[lump];
  406. }
  407. //
  408. // W_CacheLumpName
  409. //
  410. void*
  411. W_CacheLumpName
  412. ( char* name,
  413.   int tag )
  414. {
  415.  int LumpNum;
  416.  LumpNum = W_GetNumForName(name);
  417.  if (LumpNum >= 0)
  418.     return W_CacheLumpNum(LumpNum, tag);
  419.  else
  420.     return NULL;
  421. }
  422. //
  423. // W_Profile
  424. //
  425. int info[2500][10];
  426. int profilecount;
  427. void W_Profile (void)
  428. {
  429.     int i;
  430.     memblock_t* block;
  431.     void* ptr;
  432.     char ch;
  433.     FILE* f;
  434.     int j;
  435.     char name[9];
  436.     for (i=0 ; i<numlumps ; i++)
  437.     {
  438. ptr = lumpcache[i];
  439. if (!ptr)
  440. {
  441.     ch = ' ';
  442.     continue;
  443. }
  444. else
  445. {
  446.     block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
  447.     if (block->tag < PU_PURGELEVEL)
  448. ch = 'S';
  449.     else
  450. ch = 'P';
  451. }
  452. info[i][profilecount] = ch;
  453.     }
  454.     profilecount++;
  455.     f = fopen ("waddump.txt","w");
  456.     name[8] = 0;
  457.     for (i=0 ; i<numlumps ; i++)
  458.     {
  459. memcpy (name,lumpinfo[i].name,8);
  460. for (j=0 ; j<8 ; j++)
  461.     if (!name[j])
  462. break;
  463. for ( ; j<8 ; j++)
  464.     name[j] = ' ';
  465. fprintf (f,"%s ",name);
  466. for (j=0 ; j<profilecount ; j++)
  467.     fprintf (f,"    %c",info[i][j]);
  468. fprintf (f,"n");
  469.     }
  470.     fclose (f);
  471. }