diff options
Diffstat (limited to 'src/hexen/w_wad.c')
-rw-r--r-- | src/hexen/w_wad.c | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/src/hexen/w_wad.c b/src/hexen/w_wad.c new file mode 100644 index 00000000..50b2ac92 --- /dev/null +++ b/src/hexen/w_wad.c @@ -0,0 +1,596 @@ + +//************************************************************************** +//** +//** w_wad.c : Heretic 2 : Raven Software, Corp. +//** +//** $RCSfile: w_wad.c,v $ +//** $Revision: 1.6 $ +//** $Date: 95/10/06 20:56:47 $ +//** $Author: cjr $ +//** +//************************************************************************** + +// HEADER FILES ------------------------------------------------------------ + +#ifdef NeXT +#include <libc.h> +#include <ctype.h> +#else +#include <malloc.h> +#include <io.h> +#include <fcntl.h> +#include <sys/stat.h> +#endif +#include "h2def.h" + +// MACROS ------------------------------------------------------------------ + +#ifdef NeXT +// NeXT doesn't need a binary flag in open call +#define O_BINARY 0 +#define strcmpi strcasecmp +#endif + +// TYPES ------------------------------------------------------------------- + +typedef struct +{ + char identification[4]; + int numlumps; + int infotableofs; +} wadinfo_t; + +typedef struct +{ + int filepos; + int size; + char name[8]; +} filelump_t; + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +lumpinfo_t *lumpinfo; +int numlumps; +void **lumpcache; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static lumpinfo_t *PrimaryLumpInfo; +static int PrimaryNumLumps; +static void **PrimaryLumpCache; +static lumpinfo_t *AuxiliaryLumpInfo; +static int AuxiliaryNumLumps; +static void **AuxiliaryLumpCache; +static int AuxiliaryHandle = 0; +boolean AuxiliaryOpened = false; + +// CODE -------------------------------------------------------------------- + +#ifdef NeXT +//========================================================================== +// +// strupr +// +//========================================================================== + +void strupr(char *s) +{ + while(*s) + *s++ = toupper(*s); +} + +//========================================================================== +// +// filelength +// +//========================================================================== + +int filelength(int handle) +{ + struct stat fileinfo; + + if(fstat(handle, &fileinfo) == -1) + { + I_Error("Error fstating"); + } + return fileinfo.st_size; +} +#endif + +//========================================================================== +// +// W_AddFile +// +// Files with a .wad extension are wadlink files with multiple lumps, +// other files are single lumps with the base filename for the lump name. +// +//========================================================================== + +void W_AddFile(char *filename) +{ + wadinfo_t header; + lumpinfo_t *lump_p; + unsigned i; + int handle, length; + int startlump; + filelump_t *fileinfo, singleinfo; + filelump_t *freeFileInfo; + + if((handle = open(filename, O_RDONLY|O_BINARY)) == -1) + { // Didn't find file + return; + } + startlump = numlumps; + if(strcmpi(filename+strlen(filename)-3, "wad")) + { // Single lump file + fileinfo = &singleinfo; + freeFileInfo = NULL; + singleinfo.filepos = 0; + singleinfo.size = LONG(filelength(handle)); + M_ExtractFileBase(filename, singleinfo.name); + numlumps++; + } + else + { // WAD file + read(handle, &header, sizeof(header)); + if(strncmp(header.identification, "IWAD", 4)) + { + if(strncmp(header.identification, "PWAD", 4)) + { // Bad file id + I_Error("Wad file %s doesn't have IWAD or PWAD id\n", + filename); + } + } + header.numlumps = LONG(header.numlumps); + header.infotableofs = LONG(header.infotableofs); + length = header.numlumps*sizeof(filelump_t); +// fileinfo = alloca(length); + if(!(fileinfo = malloc(length))) + { + I_Error("W_AddFile: fileinfo malloc failed\n"); + } + freeFileInfo = fileinfo; + lseek(handle, header.infotableofs, SEEK_SET); + read(handle, fileinfo, length); + 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]; + for(i = startlump; i < numlumps; i++, lump_p++, fileinfo++) + { + lump_p->handle = handle; + lump_p->position = LONG(fileinfo->filepos); + lump_p->size = LONG(fileinfo->size); + strncpy(lump_p->name, fileinfo->name, 8); + } + if(freeFileInfo) + { + free(freeFileInfo); + } +} + +//========================================================================== +// +// W_InitMultipleFiles +// +// Pass a null terminated list of files to use. All files are optional, +// but at least one file must be found. Lump names can appear multiple +// times. The name searcher looks backwards, so a later file can +// override an earlier one. +// +//========================================================================== + +void W_InitMultipleFiles(char **filenames) +{ + int size; + + // Open all the files, load headers, and count lumps + numlumps = 0; + lumpinfo = malloc(1); // Will be realloced as lumps are added + + for(; *filenames; filenames++) + { + W_AddFile(*filenames); + } + if(!numlumps) + { + I_Error("W_InitMultipleFiles: 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); + + PrimaryLumpInfo = lumpinfo; + PrimaryLumpCache = lumpcache; + PrimaryNumLumps = numlumps; +} + +//========================================================================== +// +// W_InitFile +// +// Initialize the primary from a single file. +// +//========================================================================== + +void W_InitFile(char *filename) +{ + char *names[2]; + + names[0] = filename; + names[1] = NULL; + W_InitMultipleFiles(names); +} + +//========================================================================== +// +// W_OpenAuxiliary +// +//========================================================================== + +void W_OpenAuxiliary(char *filename) +{ + int i; + int size; + wadinfo_t header; + int handle; + int length; + filelump_t *fileinfo; + filelump_t *sourceLump; + lumpinfo_t *destLump; + + if(AuxiliaryOpened) + { + W_CloseAuxiliary(); + } + if((handle = open(filename, O_RDONLY|O_BINARY)) == -1) + { + I_Error("W_OpenAuxiliary: %s not found.", filename); + return; + } + AuxiliaryHandle = handle; + read(handle, &header, sizeof(header)); + if(strncmp(header.identification, "IWAD", 4)) + { + if(strncmp(header.identification, "PWAD", 4)) + { // Bad file id + I_Error("Wad file %s doesn't have IWAD or PWAD id\n", + filename); + } + } + header.numlumps = LONG(header.numlumps); + header.infotableofs = LONG(header.infotableofs); + length = header.numlumps*sizeof(filelump_t); + fileinfo = Z_Malloc(length, PU_STATIC, 0); + lseek(handle, header.infotableofs, SEEK_SET); + read(handle, fileinfo, length); + numlumps = header.numlumps; + + // Init the auxiliary lumpinfo array + lumpinfo = Z_Malloc(numlumps*sizeof(lumpinfo_t), PU_STATIC, 0); + sourceLump = fileinfo; + destLump = lumpinfo; + for(i = 0; i < numlumps; i++, destLump++, sourceLump++) + { + destLump->handle = handle; + destLump->position = LONG(sourceLump->filepos); + destLump->size = LONG(sourceLump->size); + strncpy(destLump->name, sourceLump->name, 8); + } + Z_Free(fileinfo); + + // Allocate the auxiliary lumpcache array + size = numlumps*sizeof(*lumpcache); + lumpcache = Z_Malloc(size, PU_STATIC, 0); + memset(lumpcache, 0, size); + + AuxiliaryLumpInfo = lumpinfo; + AuxiliaryLumpCache = lumpcache; + AuxiliaryNumLumps = numlumps; + AuxiliaryOpened = true; +} + +//========================================================================== +// +// W_CloseAuxiliary +// +//========================================================================== + +void W_CloseAuxiliary(void) +{ + int i; + + if(AuxiliaryOpened) + { + W_UseAuxiliary(); + for(i = 0; i < numlumps; i++) + { + if(lumpcache[i]) + { + Z_Free(lumpcache[i]); + } + } + Z_Free(AuxiliaryLumpInfo); + Z_Free(AuxiliaryLumpCache); + W_CloseAuxiliaryFile(); + AuxiliaryOpened = false; + } + W_UsePrimary(); +} + +//========================================================================== +// +// W_CloseAuxiliaryFile +// +// WARNING: W_CloseAuxiliary() must be called before any further +// auxiliary lump processing. +// +//========================================================================== + +void W_CloseAuxiliaryFile(void) +{ + if(AuxiliaryHandle) + { + close(AuxiliaryHandle); + AuxiliaryHandle = 0; + } +} + +//========================================================================== +// +// W_UsePrimary +// +//========================================================================== + +void W_UsePrimary(void) +{ + lumpinfo = PrimaryLumpInfo; + numlumps = PrimaryNumLumps; + lumpcache = PrimaryLumpCache; +} + +//========================================================================== +// +// W_UseAuxiliary +// +//========================================================================== + +void W_UseAuxiliary(void) +{ + if(AuxiliaryOpened == false) + { + I_Error("W_UseAuxiliary: WAD not opened."); + } + lumpinfo = AuxiliaryLumpInfo; + numlumps = AuxiliaryNumLumps; + lumpcache = AuxiliaryLumpCache; +} + +//========================================================================== +// +// W_NumLumps +// +//========================================================================== + +int W_NumLumps(void) +{ + return numlumps; +} + +//========================================================================== +// +// W_CheckNumForName +// +// Returns -1 if name not found. +// +//========================================================================== + +int W_CheckNumForName(char *name) +{ + char name8[9]; + int v1, v2; + lumpinfo_t *lump_p; + + // Make the name into two integers for easy compares + strncpy(name8, name, 8); + name8[8] = 0; // in case the name was a full 8 chars + strupr(name8); // case insensitive + v1 = *(int *)name8; + v2 = *(int *)&name8[4]; + + // 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; + } + } + 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) + { + return i; + } + I_Error("W_GetNumForName: %s not found!", name); + return -1; +} + +//========================================================================== +// +// 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; + + if(lump >= numlumps) + { + I_Error("W_ReadLump: %i >= numlumps", lump); + } + l = lumpinfo+lump; + //I_BeginRead(); + lseek(l->handle, l->position, SEEK_SET); + c = read(l->handle, dest, l->size); + if(c < l->size) + { + I_Error("W_ReadLump: only read %i of %i on lump %i", + c, l->size, lump); + } + //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]) + { // Need to read the lump in + ptr = Z_Malloc(W_LumpLength(lump), tag, &lumpcache[lump]); + W_ReadLump(lump, lumpcache[lump]); + } + else + { + 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 +// +//========================================================================== + +// Ripped out for Heretic +/* +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); +} +*/ |