0,0 → 1,580 |
// Emacs style mode select -*- C++ -*- |
//----------------------------------------------------------------------------- |
// |
// $Id:$ |
// |
// Copyright (C) 1993-1996 by id Software, Inc. |
// |
// This source is available for distribution and/or modification |
// only under the terms of the DOOM Source Code License as |
// published by id Software. All rights reserved. |
// |
// The source is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License |
// for more details. |
// |
// $Log:$ |
// |
// DESCRIPTION: |
// Handles WAD file header, directory, lump I/O. |
// |
//----------------------------------------------------------------------------- |
|
|
static const char |
rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $"; |
|
|
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <ctype.h> |
|
#include "m_swap.h" |
#include "doomtype.h" |
#include "i_system.h" |
#include "z_zone.h" |
#include "w_wad.h" |
|
#include <malloc.h> |
|
|
// |
// GLOBALS |
// |
|
// Location of each lump on disk. |
lumpinfo_t* lumpinfo; |
int numlumps; |
|
void** lumpcache; |
|
|
int filelength (FILE *handle) |
{ |
unsigned long pos, size; |
|
pos = ftell(handle); |
fseek(handle, 0, SEEK_END); |
size = ftell(handle); |
fseek(handle, pos, SEEK_SET); |
return (int)size; |
} |
|
|
void |
ExtractFileBase |
( char* path, |
char* dest ) |
{ |
char* src; |
int length; |
|
src = path + strlen(path) - 1; |
|
// back up until a \ or the start |
while (src != path |
&& *(src-1) != '\\' |
&& *(src-1) != '/') |
{ |
src--; |
} |
|
// copy up to eight characters |
memset (dest,0,8); |
length = 0; |
|
while (*src && *src != '.') |
{ |
if (++length == 9) |
I_Error ("Filename base of %s >8 chars",path); |
|
*dest++ = toupper((int)*src++); |
} |
} |
|
|
|
|
|
// |
// LUMP BASED ROUTINES. |
// |
|
// |
// W_AddFile |
// All files are optional, but at least one file must be |
// found (PWAD, if all required lumps are present). |
// Files with a .wad extension are wadlink files |
// with multiple lumps. |
// Other files are single lumps with the base filename |
// for the lump name. |
// |
// If filename starts with a tilde, the file is handled |
// specially to allow map reloads. |
// But: the reload feature is a fragile hack... |
|
#ifdef __BEOS__ |
#ifdef __GNUC__ |
extern void *alloca(int); |
#else |
#include <alloca.h> |
#endif |
#endif /* __BEOS__ */ |
|
int reloadlump; |
char* reloadname; |
|
|
void W_AddFile (char *filename) |
{ |
wadinfo_t header; |
lumpinfo_t* lump_p; |
unsigned i; |
FILE *handle; |
int length; |
int startlump; |
filelump_t* fileinfo; |
filelump_t singleinfo; |
int storehandle; |
|
// open the file and add to directory |
|
// handle reload indicator. |
if (filename[0] == '~') |
{ |
filename++; |
reloadname = filename; |
reloadlump = numlumps; |
} |
|
if ( (handle = fopen (filename,"rb")) == NULL) |
{ |
printf (" couldn't open %s\n",filename); |
return; |
} |
|
printf (" adding %s\n",filename); |
startlump = numlumps; |
|
if (I_strncasecmp (filename+strlen(filename)-3 , "wad", 3 ) ) |
{ |
// single lump file |
fileinfo = &singleinfo; |
singleinfo.filepos = 0; |
singleinfo.size = LONG(filelength(handle)); |
ExtractFileBase (filename, singleinfo.name); |
numlumps++; |
} |
else |
{ |
//WAD file |
printf("f1 at %x,%u\n",&header,handle); |
fread (&header, 1, sizeof(header), handle); |
printf("f2\n"); |
if (strncmp(header.identification,"IWAD",4)) |
{ |
printf("No IWAD id\n"); |
// Homebrew levels? |
if (strncmp(header.identification,"PWAD",4)) |
{ |
I_Error ("Wad file %s doesn't have IWAD " |
"or PWAD id\n", filename); |
} |
// printf("WAD magic OK\n"); |
// ???modifiedgame = true; |
} |
printf("after checking hdr\n"); |
header.numlumps = LONG(header.numlumps); |
printf("%u lumps in WAD\n",header.numlumps); |
header.infotableofs = LONG(header.infotableofs); |
printf("infor table at %x\n",header.infotableofs); |
length = header.numlumps*sizeof(filelump_t); |
printf("length %u\n",length); |
fileinfo = alloca(length); |
|
printf("seeking to info table\n"); |
fseek (handle, header.infotableofs, SEEK_SET); |
printf("f3\n"); |
fread (fileinfo, 1, length, handle); |
printf("f4\n"); |
numlumps += header.numlumps; |
} |
|
|
// Fill in lumpinfo |
lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t)); |
|
if (!lumpinfo) |
I_Error ("Couldn't realloc lumpinfo"); |
|
lump_p = &lumpinfo[startlump]; |
|
storehandle = reloadname ? -1 : (int)handle; |
|
for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++) |
{ |
lump_p->handle = storehandle; |
lump_p->position = LONG(fileinfo->filepos); |
lump_p->size = LONG(fileinfo->size); |
strncpy (lump_p->name, fileinfo->name, 8); |
} |
|
if (reloadname) |
fclose (handle); |
} |
|
|
|
|
// |
// W_Reload |
// Flushes any of the reloadable lumps in memory |
// and reloads the directory. |
// |
void W_Reload (void) |
{ |
wadinfo_t header; |
int lumpcount; |
lumpinfo_t* lump_p; |
unsigned i; |
FILE *handle; |
int length; |
filelump_t* fileinfo; |
|
if (!reloadname) |
return; |
|
if ( (handle = fopen (reloadname,"rb")) == NULL) |
I_Error ("W_Reload: couldn't open %s",reloadname); |
|
printf("f5\n"); |
fread (&header, 1, sizeof(header), handle); |
printf("f6\n"); |
lumpcount = LONG(header.numlumps); |
header.infotableofs = LONG(header.infotableofs); |
length = lumpcount*sizeof(filelump_t); |
fileinfo = malloc (length); |
fseek (handle, header.infotableofs, SEEK_SET); |
printf("f7\n"); |
fread (fileinfo, 1, length, handle); |
printf("f8\n"); |
|
// Fill in lumpinfo |
lump_p = &lumpinfo[reloadlump]; |
|
for (i=reloadlump ; |
i<reloadlump+lumpcount ; |
i++,lump_p++, fileinfo++) |
{ |
if (lumpcache[i]) |
Z_Free (lumpcache[i]); |
|
lump_p->position = LONG(fileinfo->filepos); |
lump_p->size = LONG(fileinfo->size); |
} |
|
fclose (handle); |
} |
|
|
|
// |
// W_InitMultipleFiles |
// Pass a null terminated list of files to use. |
// All files are optional, but at least one file |
// must be found. |
// Files with a .wad extension are idlink files |
// with multiple lumps. |
// Other files are single lumps with the base filename |
// for the lump name. |
// Lump names can appear multiple times. |
// The name searcher looks backwards, so a later file |
// does override all earlier ones. |
// |
void W_InitMultipleFiles (char** filenames) |
{ |
int size; |
|
// open all the files, load headers, and count lumps |
numlumps = 0; |
|
// will be realloced as lumps are added |
lumpinfo = malloc(1); |
|
for ( ; *filenames ; filenames++) |
W_AddFile (*filenames); |
|
if (!numlumps) |
I_Error ("W_InitFiles: no files found"); |
|
// set up caching |
size = numlumps * sizeof(*lumpcache); |
lumpcache = malloc (size); |
|
if (!lumpcache) |
I_Error ("Couldn't allocate lumpcache"); |
|
memset (lumpcache,0, size); |
} |
|
|
|
|
// |
// W_InitFile |
// Just initialize from a single file. |
// |
void W_InitFile (char* filename) |
{ |
char* names[2]; |
|
names[0] = filename; |
names[1] = NULL; |
W_InitMultipleFiles (names); |
} |
|
|
|
// |
// W_NumLumps |
// |
int W_NumLumps (void) |
{ |
return numlumps; |
} |
|
|
|
// |
// W_CheckNumForName |
// Returns -1 if name not found. |
// |
|
int W_CheckNumForName (char* name) |
{ |
union { |
char s[9]; |
int x[2]; |
|
} name8; |
|
int v1; |
int v2; |
lumpinfo_t* lump_p; |
|
// make the name into two integers for easy compares |
strncpy (name8.s,name,8); |
|
// in case the name was a fill 8 chars |
name8.s[8] = 0; |
|
// case insensitive |
strupr (name8.s); |
|
v1 = name8.x[0]; |
v2 = name8.x[1]; |
|
|
// scan backwards so patch lump files take precedence |
lump_p = lumpinfo + numlumps; |
|
while (lump_p-- != lumpinfo) |
{ |
if ( *(int *)lump_p->name == v1 |
&& *(int *)&lump_p->name[4] == v2) |
{ |
return lump_p - lumpinfo; |
} |
} |
|
// TFB. Not found. |
return -1; |
} |
|
|
|
|
// |
// W_GetNumForName |
// Calls W_CheckNumForName, but bombs out if not found. |
// |
int W_GetNumForName (char* name) |
{ |
int i; |
|
i = W_CheckNumForName (name); |
|
if (i == -1) |
I_Error ("W_GetNumForName: %s not found!", name); |
|
return i; |
} |
|
|
// |
// W_LumpLength |
// Returns the buffer size needed to load the given lump. |
// |
int W_LumpLength (int lump) |
{ |
if (lump >= numlumps) |
I_Error ("W_LumpLength: %i >= numlumps",lump); |
|
return lumpinfo[lump].size; |
} |
|
|
|
// |
// W_ReadLump |
// Loads the lump into the given buffer, |
// which must be >= W_LumpLength(). |
// |
void |
W_ReadLump |
( int lump, |
void* dest ) |
{ |
int c; |
lumpinfo_t* l; |
FILE *handle; |
|
if (lump >= numlumps) |
I_Error ("W_ReadLump: %i >= numlumps",lump); |
|
l = lumpinfo+lump; |
|
// ??? I_BeginRead (); |
|
if (l->handle == -1) |
{ |
// reloadable file, so use open / read / close |
if ( (handle = fopen (reloadname,"rb")) == NULL) |
I_Error ("W_ReadLump: couldn't open %s",reloadname); |
} |
else |
handle = (FILE *)l->handle; |
|
fseek (handle, l->position, SEEK_SET); |
c = fread (dest, 1, l->size, handle); |
if (c < l->size) |
I_Error ("W_ReadLump: only read %i of %i on lump %i", |
c,l->size,lump); |
|
if (l->handle == -1) |
fclose (handle); |
|
// ??? I_EndRead (); |
} |
|
|
|
|
// |
// W_CacheLumpNum |
// |
void* |
W_CacheLumpNum |
( int lump, |
int tag ) |
{ |
byte* ptr; |
|
if ((unsigned)lump >= numlumps) |
I_Error ("W_CacheLumpNum: %i >= numlumps",lump); |
|
if (!lumpcache[lump]) |
{ |
// read the lump in |
|
//printf ("cache miss on lump %i\n",lump); |
ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]); |
W_ReadLump (lump, lumpcache[lump]); |
} |
else |
{ |
//printf ("cache hit on lump %i\n",lump); |
Z_ChangeTag (lumpcache[lump],tag); |
} |
|
return lumpcache[lump]; |
} |
|
|
|
// |
// W_CacheLumpName |
// |
void* |
W_CacheLumpName |
( char* name, |
int tag ) |
{ |
return W_CacheLumpNum (W_GetNumForName(name), tag); |
} |
|
|
// |
// W_Profile |
// |
int info[2500][10]; |
int profilecount; |
|
void W_Profile (void) |
{ |
int i; |
memblock_t* block; |
void* ptr; |
char ch; |
FILE* f; |
int j; |
char name[9]; |
|
|
for (i=0 ; i<numlumps ; i++) |
{ |
ptr = lumpcache[i]; |
if (!ptr) |
{ |
ch = ' '; |
continue; |
} |
else |
{ |
block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); |
if (block->tag < PU_PURGELEVEL) |
ch = 'S'; |
else |
ch = 'P'; |
} |
info[i][profilecount] = ch; |
} |
profilecount++; |
|
f = fopen ("waddump.txt","w"); |
name[8] = 0; |
|
for (i=0 ; i<numlumps ; i++) |
{ |
memcpy (name,lumpinfo[i].name,8); |
|
for (j=0 ; j<8 ; j++) |
if (!name[j]) |
break; |
|
for ( ; j<8 ; j++) |
name[j] = ' '; |
|
fprintf (f,"%s ",name); |
|
for (j=0 ; j<profilecount ; j++) |
fprintf (f," %c",info[i][j]); |
|
fprintf (f,"\n"); |
} |
fclose (f); |
} |
|
|