// 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 /*#ifdef NORMALUNIX #include #include #include #include #include #include #include #include #define O_BINARY 0 #endif*/ #include "os.h" #include "cgdoom.h" #include "cgdoom-alloc.h" #include "doomtype.h" #include "m_swap.h" #include "i_system.h" #include "z_zone.h" #ifdef __GNUG__ #pragma implementation "w_wad.h" #endif #include "w_wad.h" // // GLOBALS // // Location of each lump on disk. lumpinfo_t* lumpinfo; static int numlumps = 0; void** lumpcache = NULL; // // 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... // THAT'S WHY RELOADABLE FILE SUPPORT WAS REMOVED, YOU FUCKERS! STOP USING CRAPPY HACKS! static int W_AddFile () { wadinfo_t header; lumpinfo_t* lump_p; int i; int length; int startlump; filelump_t* fileinfo; filelump_t* fileinfo_mem; startlump = numlumps; Flash_ReadFile(&header, sizeof(header),0); if (strncmp(header.identification,"IWAD",4)) { // Homebrew levels? if (strncmp(header.identification,"PWAD",4)) return 0; // CX port //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 = fileinfo_mem = CGD_malloc(length); Flash_ReadFile(fileinfo, length,header.infotableofs); numlumps += header.numlumps; // Fill in lumpinfo (when handling multiples files, should realloc) lumpinfo = (lumpinfo_t *)Z_Malloc (numlumps*sizeof(lumpinfo_t), PU_STATIC, 0); lump_p = &lumpinfo[startlump]; for (i=startlump ; ihandle = handle; //Originally, this was storehandle... hopefully this won't break anything... lump_p->position = LONG(fileinfo->filepos); lump_p->size = LONG(fileinfo->size); memset(lump_p->name,0,8);//hack strncpy (lump_p->name, fileinfo->name, 8); } free(fileinfo_mem); return 1; // CX port } // // 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. // int W_InitMultipleFiles(void) { int previous_numlumps = numlumps; // open all the files, load headers, and count lumps numlumps = 0; /* CGDoom: Loading multiples files hasn't been tested for a long time and may not work due to the allocation of lumpcache */ // will be realloced as lumps are added lumpinfo = NULL; if(!W_AddFile ()) { return 0; // CX port } if (!numlumps) { I_Error ("W_InitFiles: no files found"); } // set up caching printf ("numlumps = %i \n",numlumps); if (lumpcache != NULL && numlumps <= previous_numlumps) { /* Don't realloc when not needed */ } else { lumpcache = (void **)CGD_PRAM_Zalloc(numlumps * sizeof(*lumpcache)); } if (!lumpcache) { I_Error ("Couldn't allocate lumpcache"); } return 1; // CX port } // // W_NumLumps // int W_NumLumps (void) { return numlumps; } // // W_CheckNumForName // Returns -1 if name not found. // int W_CheckNumForName (const char* name) { lumpinfo_t* lump_p; // scan backwards so patch lump files take precedence lump_p = lumpinfo + numlumps; while(lump_p-- != lumpinfo) { if(strnicmp(name,lump_p->name,8)==0 ) { return lump_p - lumpinfo; } } // TFB. Not found. return -1; } // // W_GetNumForName // Calls W_CheckNumForName, but bombs out if not found. // int W_GetNumForName (const 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; if (lump >= numlumps) { I_Error ("W_ReadLump: %i >= numlumps",lump); } l = lumpinfo+lump; c = Flash_ReadFile(dest, l->size,l->position); /*printf("W_ReadLump(%i,...) in progress... \n",lump); printf("l->handle = %i \n",(int)l->handle); printf("l->size = %i \n",l->size); printf("l->position = %i \n",l->position); printf("c= %i \n",c);*/ if (c < l->size) { I_Error ("W_ReadLump: only read %i of %i on lump %i", c,l->size,lump); } } void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash) { int c = 0; if (lump >= numlumps) { I_Error ("W_ReadLump: %i >= numlumps",lump); } if(iEnableFlash) { c = FindInFlash((const void **)&lumpcache[lump], lumpinfo[lump].size, lumpinfo[lump].position); } int full = (c == lumpinfo[lump].size); int aligned = (((uintptr_t)lumpcache[lump] & 1) == 0); if(CGD_Options.TrustUnalignedLumps) aligned = 1; /* Record statistics on loading unaligned but full lumps */ if(full && !aligned) { CGD_Stats.UnalignedLumpsLoaded++; CGD_Stats.UnalignedLumpsLoadedTotal += lumpinfo[lump].size; } /* Allocate only if the lump spans several fragments, or is misaligned; otherwise, returns the cached Flash address, which is just as good as what the heap would provide. */ if(!full || !aligned) { CGD_Stats.LumpsLoaded++; CGD_Stats.LumpsLoadedTotal += lumpinfo[lump].size; prof_enter(CGD_Perf.LumpLoading); if(!aligned) prof_enter(CGD_Perf.UnalignedLumpLoading); Z_Malloc (lumpinfo[lump].size, tag, &lumpcache[lump]); W_ReadLump (lump, lumpcache[lump]); if(!aligned) prof_leave(CGD_Perf.UnalignedLumpLoading); prof_leave(CGD_Perf.LumpLoading); } else { CGD_Stats.LumpsReferenced++; CGD_Stats.LumpsReferencedTotal += lumpinfo[lump].size; } return lumpcache[lump]; } // // W_CacheLumpNum // static void* W_CacheLumpNumCommon( int lump, int tag,int iEnableFlash) { if (lump >= numlumps) { I_Error ("W_CacheLumpNum: %i >= numlumps (%i)",lump,numlumps); } if (!lumpcache[lump]) { W_ReadLumpWithZ_Malloc(lump,tag,iEnableFlash); } else { Z_ChangeTag (lumpcache[lump],tag); } if(lumpcache[lump] == NULL) I_Error ("W_CacheLumpNumCommon: Loading lump %d failed (%p)", lump, lumpcache[lump]); return lumpcache[lump]; } //#define USE_FLASH 0 void *W_CacheLumpNumVolatile (int lump, int tag) { return W_CacheLumpNumCommon(lump,tag,0); } const void* W_CacheLumpNumConst (int lump, int tag) { return W_CacheLumpNumCommon(lump,tag,1); } /*void* W_CacheLumpNum(int lump, int tag) { return W_CacheLumpNumCommon(lump,tag,USE_FLASH); }*/ const patch_t* W_CacheLumpNumPatch(int lump, int tag) { return (patch_t*) W_CacheLumpNumCommon(lump,tag,1); } // // W_CacheLumpName // void* W_CacheLumpNameVolatile (const char* name, int tag) { return W_CacheLumpNumCommon(W_GetNumForName(name),tag,0); } /*void* W_CacheLumpName (const char* name, int tag) { return W_CacheLumpNumCommon(W_GetNumForName(name),tag,USE_FLASH); }*/ const void* W_CacheLumpNameConst (const char* name, int tag) { return W_CacheLumpNumCommon(W_GetNumForName(name),tag,1); } const patch_t *W_CacheLumpNamePatch(const char* name, int tag) { return (patch_t *)W_CacheLumpNumCommon(W_GetNumForName(name),tag,1); }