Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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