Subversion Repositories Kolibri OS

Rev

Rev 333 | 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.     printf("open file %s\n\r",filename);
  156.                
  157.     if ( (handle = fopen (filename,"rb")) == NULL)
  158.     {
  159.        printf (" couldn't open %s\n",filename);
  160.        return;
  161.     }
  162.  
  163.     printf (" adding %s\n\r",filename);
  164.     startlump = numlumps;
  165.        
  166.     if (strnicmp (filename+strlen(filename)-3 , "wad", 3 ) )
  167.     {
  168.         // single lump file
  169.         fileinfo = &singleinfo;
  170.         singleinfo.filepos = 0;
  171.         singleinfo.size = FileSize(handle);
  172.         ExtractFileBase (filename, singleinfo.name);
  173.         numlumps++;
  174.     }
  175.     else
  176.     {
  177.          //WAD file
  178.         fread (&header, 1, sizeof(header), handle);
  179.  
  180.         if (strncmp(header.identification,"IWAD",4))
  181.         {
  182.             printf("No IWAD id\n");
  183.             // Homebrew levels?
  184.             if (strncmp(header.identification,"PWAD",4))
  185.             {
  186.                 I_Error ("Wad file %s doesn't have IWAD "
  187.                          "or PWAD id\n", filename);
  188.             }
  189.             printf("WAD magic OK\n");
  190.             // ???modifiedgame = true;          
  191.         }
  192.         header.numlumps = LONG(header.numlumps);
  193.  
  194.         header.infotableofs = LONG(header.infotableofs);
  195.  
  196.         length = header.numlumps*sizeof(filelump_t);
  197.  
  198.         fileinfo = alloca(length);
  199.        
  200.         fseek (handle, header.infotableofs, SEEK_SET);
  201.         fread (fileinfo, 1, length, handle);
  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.     fread (&header, 1, sizeof(header), handle);
  253.    
  254.     lumpcount = LONG(header.numlumps);
  255.     header.infotableofs = LONG(header.infotableofs);
  256.     length = lumpcount*sizeof(filelump_t);
  257.     fileinfo = malloc (length);
  258.     fseek (handle, header.infotableofs, SEEK_SET);
  259.     fread (fileinfo, 1, length, handle);
  260.    
  261.     // Fill in lumpinfo
  262.     lump_p = &lumpinfo[reloadlump];
  263.        
  264.     for (i=reloadlump ;
  265.          i<reloadlump+lumpcount ;
  266.          i++,lump_p++, fileinfo++)
  267.     {
  268.         if (lumpcache[i])
  269.             Z_Free (lumpcache[i]);
  270.  
  271.         lump_p->position = LONG(fileinfo->filepos);
  272.         lump_p->size = LONG(fileinfo->size);
  273.     }
  274.        
  275.     fclose (handle);
  276. }
  277.  
  278. //
  279. // W_InitMultipleFiles
  280. // Pass a null terminated list of files to use.
  281. // All files are optional, but at least one file
  282. //  must be found.
  283. // Files with a .wad extension are idlink files
  284. //  with multiple lumps.
  285. // Other files are single lumps with the base filename
  286. //  for the lump name.
  287. // Lump names can appear multiple times.
  288. // The name searcher looks backwards, so a later file
  289. //  does override all earlier ones.
  290. //
  291. void W_InitMultipleFiles (char** filenames)
  292. {      
  293.     int         size;
  294.    
  295.     // open all the files, load headers, and count lumps
  296.     numlumps = 0;
  297.  
  298.     // will be realloced as lumps are added
  299.     lumpinfo = malloc(16384);      
  300.  
  301.     for ( ; *filenames ; filenames++)
  302.         W_AddFile (*filenames);
  303.  
  304.     if (!numlumps)
  305.         I_Error ("W_InitFiles: no files found");
  306.    
  307.     // set up caching
  308.     size = numlumps * sizeof(*lumpcache);
  309.     lumpcache = malloc (size);
  310.    
  311.     if (!lumpcache)
  312.         I_Error ("Couldn't allocate lumpcache");
  313.  
  314.     memset (lumpcache,0, size);
  315. }
  316.  
  317.  
  318.  
  319.  
  320. //
  321. // W_InitFile
  322. // Just initialize from a single file.
  323. //
  324. void W_InitFile (char* filename)
  325. {
  326.     char*       names[2];
  327.  
  328.     names[0] = filename;
  329.     names[1] = NULL;
  330.     W_InitMultipleFiles (names);
  331. }
  332.  
  333.  
  334.  
  335. //
  336. // W_NumLumps
  337. //
  338. int W_NumLumps (void)
  339. {
  340.     return numlumps;
  341. }
  342.  
  343.  
  344.  
  345. //
  346. // W_CheckNumForName
  347. // Returns -1 if name not found.
  348. //
  349.  
  350. int W_CheckNumForName (char* name)
  351. {
  352.     union {
  353.         char    s[9];
  354.         int     x[2];
  355.        
  356.     } name8;
  357.    
  358.     int         v1;
  359.     int         v2;
  360.     lumpinfo_t* lump_p;
  361.  
  362.     // make the name into two integers for easy compares
  363.     strncpy (name8.s,name,8);
  364.  
  365.     // in case the name was a fill 8 chars
  366.     name8.s[8] = 0;
  367.  
  368.     // case insensitive
  369.     strupr (name8.s);          
  370.  
  371.     v1 = name8.x[0];
  372.     v2 = name8.x[1];
  373.  
  374.  
  375.     // scan backwards so patch lump files take precedence
  376.     lump_p = lumpinfo + numlumps;
  377.  
  378.     while (lump_p-- != lumpinfo)
  379.     {
  380.         if ( *(int *)lump_p->name == v1
  381.              && *(int *)&lump_p->name[4] == v2)
  382.         {
  383.             return lump_p - lumpinfo;
  384.         }
  385.     }
  386.  
  387.     // TFB. Not found.
  388.     return -1;
  389. }
  390.  
  391.  
  392.  
  393.  
  394. //
  395. // W_GetNumForName
  396. // Calls W_CheckNumForName, but bombs out if not found.
  397. //
  398. int W_GetNumForName (char* name)
  399. {
  400.     int i;
  401.  
  402.     i = W_CheckNumForName (name);
  403.    
  404.     if (i == -1)
  405.       I_Error ("W_GetNumForName: %s not found!", name);
  406.      
  407.     return i;
  408. }
  409.  
  410.  
  411. //
  412. // W_LumpLength
  413. // Returns the buffer size needed to load the given lump.
  414. //
  415. int W_LumpLength (int lump)
  416. {
  417.     if (lump >= numlumps)
  418.         I_Error ("W_LumpLength: %i >= numlumps",lump);
  419.  
  420.     return lumpinfo[lump].size;
  421. }
  422.  
  423.  
  424.  
  425. //
  426. // W_ReadLump
  427. // Loads the lump into the given buffer,
  428. //  which must be >= W_LumpLength().
  429. //
  430. void
  431. W_ReadLump
  432. ( int           lump,
  433.   void*         dest )
  434. {
  435.     int         c;
  436.     lumpinfo_t* l;
  437.     FILE        *handle;
  438.     size_t bytes;
  439.        
  440.     if (lump >= numlumps)
  441.         I_Error ("W_ReadLump: %i >= numlumps",lump);
  442.  
  443.     l = lumpinfo+lump;
  444.        
  445.     // ??? I_BeginRead ();
  446.        
  447.     if (l->handle == -1)
  448.     {
  449.         // reloadable file, so use open / read / close
  450.         if ( (handle = fopen (reloadname,"rb")) == NULL)
  451.             I_Error ("W_ReadLump: couldn't open %s",reloadname);
  452.     }
  453.     else
  454.         handle = (FILE *)l->handle;
  455.                
  456.     fseek (handle, l->position, SEEK_SET);
  457.     c = fread (dest, 1, l->size, handle);
  458.     if (c < l->size)
  459.         I_Error ("W_ReadLump: only read %i of %i on lump %i",
  460.                  c,l->size,lump);      
  461.  
  462.     if (l->handle == -1)
  463.         fclose (handle);
  464.                
  465.     // ??? I_EndRead ();
  466. }
  467.  
  468.  
  469.  
  470.  
  471. //
  472. // W_CacheLumpNum
  473. //
  474. void*
  475. W_CacheLumpNum
  476. ( int           lump,
  477.   int           tag )
  478. {
  479.     byte*       ptr;
  480.  
  481.     if ((unsigned)lump >= (unsigned)numlumps)
  482.         I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
  483.                
  484.     if (!lumpcache[lump])
  485.     {
  486.         // read the lump in
  487.        
  488.         //printf ("cache miss on lump %i\n",lump);
  489.         ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
  490.         W_ReadLump (lump, lumpcache[lump]);
  491.     }
  492.     else
  493.     {
  494.         //printf ("cache hit on lump %i\n",lump);
  495.         Z_ChangeTag (lumpcache[lump],tag);
  496.     }
  497.        
  498.     return lumpcache[lump];
  499. }
  500.  
  501.  
  502.  
  503. //
  504. // W_CacheLumpName
  505. //
  506. void*
  507. W_CacheLumpName
  508. ( char*         name,
  509.   int           tag )
  510. {
  511.     return W_CacheLumpNum (W_GetNumForName(name), tag);
  512. }
  513.  
  514. #if 0
  515.  
  516. //
  517. // W_Profile
  518. //
  519. int             info[2500][10];
  520. int             profilecount;
  521.  
  522. void W_Profile (void)
  523. {
  524.     int         i;
  525.     memblock_t* block;
  526.     void*       ptr;
  527.     char        ch;
  528.     FILE*       f;
  529.     int         j;
  530.     char        name[9];
  531.        
  532.        
  533.     for (i=0 ; i<numlumps ; i++)
  534.     {  
  535.         ptr = lumpcache[i];
  536.         if (!ptr)
  537.         {
  538.             ch = ' ';
  539.             continue;
  540.         }
  541.         else
  542.         {
  543.             block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
  544.             if (block->tag < PU_PURGELEVEL)
  545.                 ch = 'S';
  546.             else
  547.                 ch = 'P';
  548.         }
  549.         info[i][profilecount] = ch;
  550.     }
  551.     profilecount++;
  552.        
  553.     f = fopen ("waddump.txt","w");
  554.     name[8] = 0;
  555.  
  556.     for (i=0 ; i<numlumps ; i++)
  557.     {
  558.         memcpy (name,lumpinfo[i].name,8);
  559.  
  560.         for (j=0 ; j<8 ; j++)
  561.             if (!name[j])
  562.                 break;
  563.  
  564.         for ( ; j<8 ; j++)
  565.             name[j] = ' ';
  566.  
  567.         //printf ("%s ",name);
  568.  
  569.         for (j=0 ; j<profilecount ; j++)
  570.             fprintf (f,"    %c",info[i][j]);
  571.  
  572.         //printf ("\n");
  573.     }
  574.     fclose (f);
  575. }
  576.  
  577. #endif
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.