|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.