Annotation of doom/w_wad.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.