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++; }
75 sysfatal("dirfstat: %r");
78 return l; /* lump file lenghts in doom are ints */
90 src = path + strlen(path) - 1;
92 // back up until a \ or the start
100 // copy up to eight characters
104 while (*src && *src != '.')
107 I_Error ("Filename base of %s >8 chars",path);
109 *dest++ = toupper((int)*src++);
118 // LUMP BASED ROUTINES.
123 // All files are optional, but at least one file must be
124 // found (PWAD, if all required lumps are present).
125 // Files with a .wad extension are wadlink files
126 // with multiple lumps.
127 // Other files are single lumps with the base filename
128 // for the lump name.
130 // If filename starts with a tilde, the file is handled
131 // specially to allow map reloads.
132 // But: the reload feature is a fragile hack...
138 void W_AddFile (char *filename)
146 filelump_t* fileinfo;
147 filelump_t singleinfo;
149 void *freefileinfo = nil;
151 // open the file and add to directory
153 // handle reload indicator.
154 if (filename[0] == '~')
157 reloadname = filename;
158 reloadlump = numlumps;
161 if ( (handle = I_Open(filename)) == -1 )
163 printf (" couldn't open %s\n",filename);
167 printf (" adding %s\n",filename);
168 startlump = numlumps;
170 if (cistrcmp (filename+strlen(filename)-3 , "wad" ) )
173 fileinfo = &singleinfo;
174 singleinfo.filepos = 0;
175 singleinfo.size = LONG(filelength(handle));
176 ExtractFileBase (filename, singleinfo.name);
182 I_Read (handle, &header, sizeof(header));
183 if (strncmp(header.identification,"IWAD",4))
186 if (strncmp(header.identification,"PWAD",4))
188 I_Error ("Wad file %s doesn't have IWAD "
189 "or PWAD id\n", filename);
192 // ???modifiedgame = true;
194 header.numlumps = LONG(header.numlumps);
195 header.infotableofs = LONG(header.infotableofs);
196 length = header.numlumps*sizeof(filelump_t);
197 fileinfo = malloc (length); freefileinfo=fileinfo;
198 I_Seek (handle, header.infotableofs);
199 I_Read (handle, fileinfo, length);
200 numlumps += header.numlumps;
205 lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
208 I_Error ("Couldn't realloc lumpinfo");
210 lump_p = &lumpinfo[startlump];
212 storehandle = reloadname ? -1 : handle;
214 for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++)
216 lump_p->handle = storehandle;
217 lump_p->position = LONG(fileinfo->filepos);
218 lump_p->size = LONG(fileinfo->size);
219 strncpy (lump_p->name, fileinfo->name, 8);
234 // Flushes any of the reloadable lumps in memory
235 // and reloads the directory.
245 filelump_t* fileinfo;
250 if ( (handle = I_Open (reloadname)) == -1)
251 I_Error ("W_Reload: couldn't open %s",reloadname);
253 I_Read (handle, &header, sizeof(header));
254 lumpcount = LONG(header.numlumps);
255 header.infotableofs = LONG(header.infotableofs);
256 length = lumpcount*sizeof(filelump_t);
257 fileinfo = malloc (length);
258 I_Seek (handle, header.infotableofs);
259 I_Read (handle, fileinfo, length);
262 lump_p = &lumpinfo[reloadlump];
265 i<reloadlump+lumpcount ;
266 i++,lump_p++, fileinfo++)
269 Z_Free (lumpcache[i]);
271 lump_p->position = LONG(fileinfo->filepos);
272 lump_p->size = LONG(fileinfo->size);
282 // W_InitMultipleFiles
283 // Pass a null terminated list of files to use.
284 // All files are optional, but at least one file
286 // Files with a .wad extension are idlink files
287 // with multiple lumps.
288 // Other files are single lumps with the base filename
289 // for the lump name.
290 // Lump names can appear multiple times.
291 // The name searcher looks backwards, so a later file
292 // does override all earlier ones.
294 void W_InitMultipleFiles (char** filenames)
298 // open all the files, load headers, and count lumps
301 // will be realloced as lumps are added
302 lumpinfo = malloc(1);
304 for ( ; *filenames ; filenames++)
305 W_AddFile (*filenames);
308 I_Error ("W_InitFiles: no files found");
311 size = numlumps * sizeof(*lumpcache);
312 lumpcache = malloc (size);
315 I_Error ("Couldn't allocate lumpcache");
317 memset (lumpcache,0, size);
325 // Just initialize from a single file.
327 void W_InitFile (char* filename)
333 W_InitMultipleFiles (names);
341 int W_NumLumps (void)
350 // Returns -1 if name not found.
353 int W_CheckNumForName (char* name)
365 // make the name into two integers for easy compares
366 strncpy (name8.s,name,8);
368 // in case the name was a fill 8 chars
378 // scan backwards so patch lump files take precedence
379 lump_p = lumpinfo + numlumps;
381 while (lump_p-- != lumpinfo)
383 if ( *(int *)lump_p->name == v1
384 && *(int *)&lump_p->name[4] == v2)
386 return lump_p - lumpinfo;
399 // Calls W_CheckNumForName, but bombs out if not found.
401 int W_GetNumForName (char* name)
405 i = W_CheckNumForName (name);
408 I_Error ("W_GetNumForName: %s not found!", name);
416 // Returns the buffer size needed to load the given lump.
418 int W_LumpLength (int lump)
420 if (lump >= numlumps)
421 I_Error ("W_LumpLength: %i >= numlumps",lump);
423 return lumpinfo[lump].size;
430 // Loads the lump into the given buffer,
431 // which must be >= W_LumpLength().
442 if (lump >= numlumps)
443 I_Error ("W_ReadLump: %i >= numlumps",lump);
447 // ??? I_BeginRead ();
451 // reloadable file, so use open / read / close
452 if ( (handle = I_Open (reloadname)) == -1)
453 I_Error ("W_ReadLump: couldn't open %s",reloadname);
458 I_Seek (handle, l->position);
459 c = I_Read (handle, dest, l->size);
462 I_Error ("W_ReadLump: only read %i of %i on lump %i",
482 if ((unsigned)lump >= numlumps)
483 I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
485 if (!lumpcache[lump])
489 //printf ("cache miss on lump %i\n",lump);
490 Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
491 W_ReadLump (lump, lumpcache[lump]);
495 //printf ("cache hit on lump %i\n",lump);
496 Z_ChangeTag (lumpcache[lump],tag);
499 return lumpcache[lump];
512 return W_CacheLumpNum (W_GetNumForName(name), tag);
522 void W_Profile (void)
533 for (i=0 ; i<numlumps ; i++)
542 block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
543 if (block->tag < PU_PURGELEVEL)
548 info[i][profilecount] = ch;
552 f = fopen ("waddump.txt","w");
555 for (i=0 ; i<numlumps ; i++)
557 memcpy (name,lumpinfo[i].name,8);
559 for (j=0 ; j<8 ; j++)
566 fprintf (f,"%s ",name);
568 for (j=0 ; j<profilecount ; j++)
569 fprintf (f," %c",info[i][j]);