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