Subversion Repositories Kolibri OS

Rev

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