Subversion Repositories Kolibri OS

Rev

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