home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 25 / amigaformatcd25.iso / websites / amidoom / adoom_src-0.7.lha / ADoom_src / w_wad.c < prev    next >
C/C++ Source or Header  |  1997-12-26  |  11KB  |  596 lines

  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.  
  24.  
  25. static const char
  26. rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $";
  27.  
  28.  
  29. #ifdef NORMALUNIX
  30. #ifndef __SASC
  31. #include <ctype.h>
  32. #include <sys/types.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include <malloc.h>
  36. #include <fcntl.h>
  37. #include <sys/stat.h>
  38. #include <alloca.h>
  39. #define O_BINARY        0
  40. #else
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45. #include <stat.h>
  46. #endif
  47. #endif
  48.  
  49. #include "doomtype.h"
  50. #include "m_swap.h"
  51. #include "i_system.h"
  52. #include "z_zone.h"
  53.  
  54. #ifdef __GNUG__
  55. #pragma implementation "w_wad.h"
  56. #endif
  57. #include "w_wad.h"
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64. //
  65. // GLOBALS
  66. //
  67.  
  68. // Location of each lump on disk.
  69. lumpinfo_t*        lumpinfo;        
  70. int            numlumps;
  71.  
  72. void**            lumpcache;
  73.  
  74.  
  75. #ifndef __SASC
  76. #define strcmpi    strcasecmp
  77.  
  78. void strupr (char* s)
  79. {
  80.     while (*s) { *s = toupper(*s); s++; }
  81. }
  82. #endif
  83.  
  84. int filelength (int handle) 
  85.     struct stat    *fileinfo;
  86.     int size;
  87.     
  88.     if ((fileinfo = malloc (sizeof(struct stat))) == NULL ||
  89.         fstat (handle,fileinfo) == -1)
  90.     I_Error ("Error fstating");
  91.     size = fileinfo->st_size;
  92.     free (fileinfo);
  93.  
  94.     return size;
  95. }
  96.  
  97.  
  98. void
  99. ExtractFileBase
  100. ( char*        path,
  101.   char*        dest )
  102. {
  103.     char*    src;
  104.     int        length;
  105.  
  106.     src = path + strlen(path) - 1;
  107.     
  108.     // back up until a \ or the start
  109.     while (src != path
  110.        && *(src-1) != '\\'
  111.        && *(src-1) != '/')
  112.     {
  113.     src--;
  114.     }
  115.     
  116.     // copy up to eight characters
  117.     memset (dest,0,8);
  118.     length = 0;
  119.     
  120.     while (*src && *src != '.')
  121.     {
  122.     if (++length == 9)
  123.         I_Error ("Filename base of %s >8 chars",path);
  124.  
  125.     *dest++ = toupper((int)*src++);
  126.     }
  127. }
  128.  
  129.  
  130.  
  131.  
  132.  
  133. //
  134. // LUMP BASED ROUTINES.
  135. //
  136.  
  137. //
  138. // W_AddFile
  139. // All files are optional, but at least one file must be
  140. //  found (PWAD, if all required lumps are present).
  141. // Files with a .wad extension are wadlink files
  142. //  with multiple lumps.
  143. // Other files are single lumps with the base filename
  144. //  for the lump name.
  145. //
  146. // If filename starts with a tilde, the file is handled
  147. //  specially to allow map reloads.
  148. // But: the reload feature is a fragile hack...
  149.  
  150. int            reloadlump;
  151. char*            reloadname;
  152.  
  153.  
  154. void W_AddFile (char *filename)
  155. {
  156.     wadinfo_t        header;
  157.     lumpinfo_t*        lump_p;
  158.     unsigned        i;
  159.     FILE        *handle;
  160.     int            length;
  161.     int            startlump;
  162.     filelump_t*        fileinfo = NULL;
  163.     filelump_t        singleinfo;
  164.     FILE        *storehandle;
  165.     
  166.     // open the file and add to directory
  167.  
  168.     // handle reload indicator.
  169.     if (filename[0] == '~')
  170.     {
  171.     filename++;
  172.     reloadname = filename;
  173.     reloadlump = numlumps;
  174.     }
  175.         
  176.     if ( (handle = fopen (filename,"r")) == NULL)
  177.     {
  178.     printf (" couldn't open %s\n",filename);
  179.     return;
  180.     }
  181.  
  182.     printf (" adding %s\n",filename);
  183.     startlump = numlumps;
  184.     
  185.     if (strcmpi (filename+strlen(filename)-3 , "wad" ) )
  186.     {
  187.     // single lump file
  188.     fileinfo = &singleinfo;
  189.     singleinfo.filepos = 0;
  190.     singleinfo.size = LONG(filelength(fileno(handle)));
  191.     ExtractFileBase (filename, singleinfo.name);
  192.     numlumps++;
  193.     }
  194.     else 
  195.     {
  196.     // WAD file
  197.     fread (&header, 1, sizeof(header), handle);
  198.     if (strncmp(header.identification,"IWAD",4))
  199.     {
  200.         // Homebrew levels?
  201.         if (strncmp(header.identification,"PWAD",4))
  202.         {
  203.         I_Error ("Wad file %s doesn't have IWAD "
  204.              "or PWAD id\n", filename);
  205.         }
  206.         
  207.         // ???modifiedgame = true;        
  208.     }
  209.     header.numlumps = LONG(header.numlumps);
  210.     header.infotableofs = LONG(header.infotableofs);
  211.     length = header.numlumps*sizeof(filelump_t);
  212.     fileinfo = malloc (length);
  213.     fseek (handle, header.infotableofs, SEEK_SET);
  214.     fread (fileinfo, 1, length, handle);
  215.     numlumps += header.numlumps;
  216.     }
  217.  
  218.     
  219.     // Fill in lumpinfo
  220.     lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
  221.  
  222.     if (!lumpinfo)
  223.     I_Error ("Couldn't realloc lumpinfo");
  224.  
  225.     lump_p = &lumpinfo[startlump];
  226.     
  227.     storehandle = reloadname ? NULL : handle;
  228.     
  229.     for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++)
  230.     {
  231.     lump_p->handle = storehandle;
  232.     lump_p->position = LONG(fileinfo->filepos);
  233.     lump_p->size = LONG(fileinfo->size);
  234.     strncpy (lump_p->name, fileinfo->name, 8);
  235.     }
  236.     
  237.     if (reloadname)
  238.     fclose (handle);
  239.     if (fileinfo != NULL)
  240.         free (fileinfo);
  241. }
  242.  
  243.  
  244.  
  245.  
  246. //
  247. // W_Reload
  248. // Flushes any of the reloadable lumps in memory
  249. //  and reloads the directory.
  250. //
  251. void W_Reload (void)
  252. {
  253.     wadinfo_t        header;
  254.     int            lumpcount;
  255.     lumpinfo_t*        lump_p;
  256.     unsigned        i;
  257.     FILE        *handle;
  258.     int            length;
  259.     filelump_t*        fileinfo = NULL;
  260.     
  261.     if (!reloadname)
  262.     return;
  263.         
  264.     if ( (handle = fopen (reloadname,"r")) == NULL)
  265.     I_Error ("W_Reload: couldn't open %s",reloadname);
  266.  
  267.     fread (&header, 1, sizeof(header), handle);
  268.     lumpcount = LONG(header.numlumps);
  269.     header.infotableofs = LONG(header.infotableofs);
  270.     length = lumpcount*sizeof(filelump_t);
  271.     fileinfo = malloc (length);
  272.     fseek (handle, header.infotableofs, SEEK_SET);
  273.     fread (fileinfo, 1, length, handle);
  274.     
  275.     // Fill in lumpinfo
  276.     lump_p = &lumpinfo[reloadlump];
  277.     
  278.     for (i=reloadlump ;
  279.      i<reloadlump+lumpcount ;
  280.      i++,lump_p++, fileinfo++)
  281.     {
  282.     if (lumpcache[i])
  283.         Z_Free (lumpcache[i]);
  284.  
  285.     lump_p->position = LONG(fileinfo->filepos);
  286.     lump_p->size = LONG(fileinfo->size);
  287.     }
  288.     
  289.     fclose (handle);
  290.     if (fileinfo != NULL)
  291.        free (fileinfo);
  292. }
  293.  
  294.  
  295.  
  296. //
  297. // W_InitMultipleFiles
  298. // Pass a null terminated list of files to use.
  299. // All files are optional, but at least one file
  300. //  must be found.
  301. // Files with a .wad extension are idlink files
  302. //  with multiple lumps.
  303. // Other files are single lumps with the base filename
  304. //  for the lump name.
  305. // Lump names can appear multiple times.
  306. // The name searcher looks backwards, so a later file
  307. //  does override all earlier ones.
  308. //
  309. void W_InitMultipleFiles (char** filenames)
  310. {    
  311.     int        size;
  312.     
  313.     // open all the files, load headers, and count lumps
  314.     numlumps = 0;
  315.  
  316.     // will be realloced as lumps are added
  317.     lumpinfo = malloc(1);    
  318.  
  319.     for ( ; *filenames ; filenames++)
  320.     W_AddFile (*filenames);
  321.  
  322.     if (!numlumps)
  323.     I_Error ("W_InitFiles: no files found");
  324.     
  325.     // set up caching
  326.     size = numlumps * sizeof(*lumpcache);
  327.     lumpcache = malloc (size);
  328.     
  329.     if (!lumpcache)
  330.     I_Error ("Couldn't allocate lumpcache");
  331.  
  332.     memset (lumpcache,0, size);
  333. }
  334.  
  335.  
  336.  
  337.  
  338. //
  339. // W_InitFile
  340. // Just initialize from a single file.
  341. //
  342. void W_InitFile (char* filename)
  343. {
  344.     char*    names[2];
  345.  
  346.     names[0] = filename;
  347.     names[1] = NULL;
  348.     W_InitMultipleFiles (names);
  349. }
  350.  
  351.  
  352.  
  353. //
  354. // W_NumLumps
  355. //
  356. int W_NumLumps (void)
  357. {
  358.     return numlumps;
  359. }
  360.  
  361.  
  362.  
  363. //
  364. // W_CheckNumForName
  365. // Returns -1 if name not found.
  366. //
  367.  
  368. int W_CheckNumForName (char* name)
  369. {
  370.     union {
  371.     char    s[9];
  372.     int    x[2];
  373.     
  374.     } name8;
  375.     
  376.     int        v1;
  377.     int        v2;
  378.     lumpinfo_t*    lump_p;
  379.  
  380.     // make the name into two integers for easy compares
  381.     strncpy (name8.s,name,8);
  382.  
  383.     // in case the name was a fill 8 chars
  384.     name8.s[8] = 0;
  385.  
  386.     // case insensitive
  387.     strupr (name8.s);        
  388.  
  389.     v1 = name8.x[0];
  390.     v2 = name8.x[1];
  391.  
  392.  
  393.     // scan backwards so patch lump files take precedence
  394.     lump_p = lumpinfo + numlumps;
  395.  
  396.     while (lump_p-- != lumpinfo)
  397.     {
  398.     if ( *(int *)lump_p->name == v1
  399.          && *(int *)&lump_p->name[4] == v2)
  400.     {
  401.         return lump_p - lumpinfo;
  402.     }
  403.     }
  404.  
  405.     // TFB. Not found.
  406.     return -1;
  407. }
  408.  
  409.  
  410.  
  411.  
  412. //
  413. // W_GetNumForName
  414. // Calls W_CheckNumForName, but bombs out if not found.
  415. //
  416. int W_GetNumForName (char* name)
  417. {
  418.     int    i;
  419.  
  420.     i = W_CheckNumForName (name);
  421.     
  422.     if (i == -1)
  423.       I_Error ("W_GetNumForName: %s not found!", name);
  424.       
  425.     return i;
  426. }
  427.  
  428.  
  429. //
  430. // W_LumpLength
  431. // Returns the buffer size needed to load the given lump.
  432. //
  433. int W_LumpLength (int lump)
  434. {
  435.     if (lump >= numlumps)
  436.     I_Error ("W_LumpLength: %i >= numlumps",lump);
  437.  
  438.     return lumpinfo[lump].size;
  439. }
  440.  
  441.  
  442.  
  443. //
  444. // W_ReadLump
  445. // Loads the lump into the given buffer,
  446. //  which must be >= W_LumpLength().
  447. //
  448. void
  449. W_ReadLump
  450. ( int        lump,
  451.   void*        dest )
  452. {
  453.     int        c;
  454.     lumpinfo_t*    l;
  455.     FILE    *handle;
  456.     
  457.     if (lump >= numlumps)
  458.     I_Error ("W_ReadLump: %i >= numlumps",lump);
  459.  
  460.     l = lumpinfo+lump;
  461.     
  462.     // ??? I_BeginRead ();
  463.     
  464.     if (l->handle == NULL)
  465.     {
  466.     // reloadable file, so use open / read / close
  467.     if ( (handle = fopen (reloadname,"r")) == NULL)
  468.         I_Error ("W_ReadLump: couldn't open %s",reloadname);
  469.     }
  470.     else
  471.     handle = l->handle;
  472.         
  473.     fseek (handle, l->position, SEEK_SET);
  474.     c = fread (dest, 1, l->size, handle);
  475.  
  476.     if (c < l->size)
  477.     I_Error ("W_ReadLump: only read %i of %i on lump %i",
  478.          c,l->size,lump);    
  479.  
  480.     if (l->handle == NULL)
  481.     fclose (handle);
  482.         
  483.     // ??? I_EndRead ();
  484. }
  485.  
  486.  
  487.  
  488.  
  489. //
  490. // W_CacheLumpNum
  491. //
  492. void*
  493. W_CacheLumpNum
  494. ( int        lump,
  495.   int        tag )
  496. {
  497.     byte*    ptr;
  498.  
  499.     if ((unsigned)lump >= numlumps)
  500.     I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
  501.         
  502.     if (!lumpcache[lump])
  503.     {
  504.     // read the lump in
  505.     
  506.     //printf ("cache miss on lump %i\n",lump);
  507.     ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
  508.     W_ReadLump (lump, lumpcache[lump]);
  509.     }
  510.     else
  511.     {
  512.     //printf ("cache hit on lump %i\n",lump);
  513.     Z_ChangeTag (lumpcache[lump],tag);
  514.     }
  515.     
  516.     return lumpcache[lump];
  517. }
  518.  
  519.  
  520.  
  521. //
  522. // W_CacheLumpName
  523. //
  524. void*
  525. W_CacheLumpName
  526. ( char*        name,
  527.   int        tag )
  528. {
  529.     return W_CacheLumpNum (W_GetNumForName(name), tag);
  530. }
  531.  
  532.  
  533. //
  534. // W_Profile
  535. //
  536. int        info[2500][10];
  537. int        profilecount;
  538.  
  539. void W_Profile (void)
  540. {
  541.     int        i;
  542.     memblock_t*    block;
  543.     void*    ptr;
  544.     char    ch;
  545.     FILE*    f;
  546.     int        j;
  547.     char    name[9];
  548.     
  549.     
  550.     for (i=0 ; i<numlumps ; i++)
  551.     {    
  552.     ptr = lumpcache[i];
  553.     if (!ptr)
  554.     {
  555.         ch = ' ';
  556.         continue;
  557.     }
  558.     else
  559.     {
  560.         block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
  561.         if (block->tag < PU_PURGELEVEL)
  562.         ch = 'S';
  563.         else
  564.         ch = 'P';
  565.     }
  566.     info[i][profilecount] = ch;
  567.     }
  568.     profilecount++;
  569.     
  570.     f = fopen ("waddump.txt","w");
  571.     name[8] = 0;
  572.  
  573.     for (i=0 ; i<numlumps ; i++)
  574.     {
  575.     memcpy (name,lumpinfo[i].name,8);
  576.  
  577.     for (j=0 ; j<8 ; j++)
  578.         if (!name[j])
  579.         break;
  580.  
  581.     for ( ; j<8 ; j++)
  582.         name[j] = ' ';
  583.  
  584.     fprintf (f,"%s ",name);
  585.  
  586.     for (j=0 ; j<profilecount ; j++)
  587.         fprintf (f,"    %c",info[i][j]);
  588.  
  589.     fprintf (f,"\n");
  590.     }
  591.     fclose (f);
  592. }
  593.  
  594.  
  595.