|
|
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.5 ! 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.5 ! root 69: /*void strupr (char* s)
1.1 root 70: {
1.1.1.4 root 71: while (*s) { *s = toupper(*s); s++; }
1.1.1.5 ! root 72: }*/
1.1 root 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.