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