1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
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.
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
20 // Handles WAD file header, directory, lump I/O.
22 //-----------------------------------------------------------------------------
26 rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $";
31 #include <sys/types.h>
53 // Location of each lump on disk.
60 #define strcmpi strcasecmp
64 while (*s) { *s = toupper(*s); s++; }
67 int filelength (int handle)
70 I_Error ("PORTME w_wad.c filelength");
75 if (fstat (handle,&fileinfo) == -1)
76 I_Error ("Error fstating");
78 return fileinfo.st_size;
91 src = path + strlen(path) - 1;
93 // back up until a \ or the start
101 // copy up to eight characters
105 while (*src && *src != '.')
108 I_Error ("Filename base of %s >8 chars",path);
110 *dest++ = toupper((int)*src++);
119 // LUMP BASED ROUTINES.
124 // All files are optional, but at least one file must be
125 // found (PWAD, if all required lumps are present).
126 // Files with a .wad extension are wadlink files
127 // with multiple lumps.
128 // Other files are single lumps with the base filename
129 // for the lump name.
131 // If filename starts with a tilde, the file is handled
132 // specially to allow map reloads.
133 // But: the reload feature is a fragile hack...
139 void W_AddFile (char *filename)
147 filelump_t* fileinfo;
148 filelump_t singleinfo;
150 void *freefileinfo = nil;
152 // open the file and add to directory
154 // handle reload indicator.
155 if (filename[0] == '~')
158 reloadname = filename;
159 reloadlump = numlumps;
162 if ( (handle = I_Open(filename)) == -1 )
164 printf (" couldn't open %s\n",filename);
168 printf (" adding %s\n",filename);
169 startlump = numlumps;
171 if (cistrcmp (filename+strlen(filename)-3 , "wad" ) )
174 fileinfo = &singleinfo;
175 singleinfo.filepos = 0;
176 singleinfo.size = LONG(filelength(handle));
177 ExtractFileBase (filename, singleinfo.name);
183 I_Read (handle, &header, sizeof(header));
184 if (strncmp(header.identification,"IWAD",4))
187 if (strncmp(header.identification,"PWAD",4))
189 I_Error ("Wad file %s doesn't have IWAD "
190 "or PWAD id\n", filename);
193 // ???modifiedgame = true;
195 header.numlumps = LONG(header.numlumps);
196 header.infotableofs = LONG(header.infotableofs);
197 length = header.numlumps*sizeof(filelump_t);
198 fileinfo = malloc (length); freefileinfo=fileinfo;
199 I_Seek (handle, header.infotableofs);
200 I_Read (handle, fileinfo, length);
201 numlumps += header.numlumps;
206 lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
209 I_Error ("Couldn't realloc lumpinfo");
211 lump_p = &lumpinfo[startlump];
213 storehandle = reloadname ? -1 : handle;
215 for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++)
217 lump_p->handle = storehandle;
218 lump_p->position = LONG(fileinfo->filepos);
219 lump_p->size = LONG(fileinfo->size);
220 strncpy (lump_p->name, fileinfo->name, 8);
235 // Flushes any of the reloadable lumps in memory
236 // and reloads the directory.
246 filelump_t* fileinfo;
251 if ( (handle = I_Open (reloadname)) == -1)
252 I_Error ("W_Reload: couldn't open %s",reloadname);
254 I_Read (handle, &header, sizeof(header));
255 lumpcount = LONG(header.numlumps);
256 header.infotableofs = LONG(header.infotableofs);
257 length = lumpcount*sizeof(filelump_t);
258 fileinfo = malloc (length);
259 I_Seek (handle, header.infotableofs);
260 I_Read (handle, fileinfo, length);
263 lump_p = &lumpinfo[reloadlump];
266 i<reloadlump+lumpcount ;
267 i++,lump_p++, fileinfo++)
270 Z_Free (lumpcache[i]);
272 lump_p->position = LONG(fileinfo->filepos);
273 lump_p->size = LONG(fileinfo->size);
283 // W_InitMultipleFiles
284 // Pass a null terminated list of files to use.
285 // All files are optional, but at least one file
287 // Files with a .wad extension are idlink files
288 // with multiple lumps.
289 // Other files are single lumps with the base filename
290 // for the lump name.
291 // Lump names can appear multiple times.
292 // The name searcher looks backwards, so a later file
293 // does override all earlier ones.
295 void W_InitMultipleFiles (char** filenames)
299 // open all the files, load headers, and count lumps
302 // will be realloced as lumps are added
303 lumpinfo = malloc(1);
305 for ( ; *filenames ; filenames++)
306 W_AddFile (*filenames);
309 I_Error ("W_InitFiles: no files found");
312 size = numlumps * sizeof(*lumpcache);
313 lumpcache = malloc (size);
316 I_Error ("Couldn't allocate lumpcache");
318 memset (lumpcache,0, size);
326 // Just initialize from a single file.
328 void W_InitFile (char* filename)
334 W_InitMultipleFiles (names);
342 int W_NumLumps (void)
351 // Returns -1 if name not found.
354 int W_CheckNumForName (char* name)
366 // make the name into two integers for easy compares
367 strncpy (name8.s,name,8);
369 // in case the name was a fill 8 chars
379 // scan backwards so patch lump files take precedence
380 lump_p = lumpinfo + numlumps;
382 while (lump_p-- != lumpinfo)
384 if ( *(int *)lump_p->name == v1
385 && *(int *)&lump_p->name[4] == v2)
387 return lump_p - lumpinfo;
400 // Calls W_CheckNumForName, but bombs out if not found.
402 int W_GetNumForName (char* name)
406 i = W_CheckNumForName (name);
409 I_Error ("W_GetNumForName: %s not found!", name);
417 // Returns the buffer size needed to load the given lump.
419 int W_LumpLength (int lump)
421 if (lump >= numlumps)
422 I_Error ("W_LumpLength: %i >= numlumps",lump);
424 return lumpinfo[lump].size;
431 // Loads the lump into the given buffer,
432 // which must be >= W_LumpLength().
443 if (lump >= numlumps)
444 I_Error ("W_ReadLump: %i >= numlumps",lump);
448 // ??? I_BeginRead ();
452 // reloadable file, so use open / read / close
453 if ( (handle = I_Open (reloadname)) == -1)
454 I_Error ("W_ReadLump: couldn't open %s",reloadname);
459 I_Seek (handle, l->position);
460 c = I_Read (handle, dest, l->size);
463 I_Error ("W_ReadLump: only read %i of %i on lump %i",
483 if ((unsigned)lump >= numlumps)
484 I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
486 if (!lumpcache[lump])
490 //printf ("cache miss on lump %i\n",lump);
491 Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
492 W_ReadLump (lump, lumpcache[lump]);
496 //printf ("cache hit on lump %i\n",lump);
497 Z_ChangeTag (lumpcache[lump],tag);
500 return lumpcache[lump];
513 return W_CacheLumpNum (W_GetNumForName(name), tag);
523 void W_Profile (void)
534 for (i=0 ; i<numlumps ; i++)
543 block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
544 if (block->tag < PU_PURGELEVEL)
549 info[i][profilecount] = ch;
553 f = fopen ("waddump.txt","w");
556 for (i=0 ; i<numlumps ; i++)
558 memcpy (name,lumpinfo[i].name,8);
560 for (j=0 ; j<8 ; j++)
567 fprintf (f,"%s ",name);
569 for (j=0 ; j<profilecount ; j++)
570 fprintf (f," %c",info[i][j]);