Annotation of doom/w_wad.c, revision 1.1.1.6

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

unix.superglobalmegacorp.com

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