Subversion Repositories Kolibri OS

Rev

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