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