From aef5df6628d1eeafce7426ef5feaee27792e5b33 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 17 Aug 2006 22:10:50 +0000 Subject: [PATCH] - Did some minor reorganization of code in r_data.cpp (mostly to make handling of textures easier in GZDoom.) - Did some preparations to allow loading folders on the HD into the lump directory. SVN r298 (trunk) --- docs/rh-log.txt | 6 ++ src/p_setup.cpp | 14 +++- src/r_data.cpp | 150 +++++++++++++++++++-------------------- src/r_data.h | 2 + src/r_defs.h | 1 + src/r_jpeg.h | 29 ++++++++ src/w_wad.cpp | 182 +++++++++++++++++++++++++++++++++--------------- src/w_wad.h | 9 ++- zdoom.vcproj | 4 ++ 9 files changed, 262 insertions(+), 135 deletions(-) create mode 100644 src/r_jpeg.h diff --git a/docs/rh-log.txt b/docs/rh-log.txt index fd79dfb3c4..3e12189d9c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,10 @@ August 17, 2006 (Changes by Graf Zahl) +- Added a check to the map loader to check whether the map label + is in the same WAD as the following lump. +- Did some minor reorganization of code in r_data.cpp (mostly to make + handling of textures easier in GZDoom.) +- Did some preparations to allow loading folders on the HD into the lump + directory. - Took MF2_WINDTHRUST off AMorphedMonster. This is something that should not be a default setting. - Moved a_artiegg.cpp to g_shared and renamed it to a_morph.cpp to better reflect diff --git a/src/p_setup.cpp b/src/p_setup.cpp index f7a340c9c5..c5ecb0e227 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -271,7 +271,19 @@ MapData *P_OpenMapData(const char * mapname) if (lump_name > lump_wad && lump_name > lump_map && lump_name != -1) { - map->file = Wads.GetFileReader(Wads.GetLumpFile (lump_name)); + int lumpfile=Wads.GetLumpFile(lump_name); + int nextfile=Wads.GetLumpFile(lump_name+1); + + if (lumpfile != nextfile) + { + // The following lump is from a different file so whatever this is, + // it is not a multi-lump Doom level. + return map; + } + + // This case can only happen if the lump is inside a real WAD file. + // As such any special handling for other types of lumps is skipped. + map->file = Wads.GetFileReader(lumpfile); map->CloseOnDestruct = false; map->lumpnum = lump_name; diff --git a/src/r_data.cpp b/src/r_data.cpp index 9266ade7aa..8614d106eb 100644 --- a/src/r_data.cpp +++ b/src/r_data.cpp @@ -37,10 +37,8 @@ #include #include #include -extern "C" -{ -#include -} + +#include "r_jpeg.h" #include "i_system.h" #include "m_alloc.h" @@ -235,9 +233,10 @@ int FTextureManager::AddTexture (FTexture *texture) return trans; } + // Examines the lump contents to decide what type of texture to create, -// creates the texture, and adds it to the manager. -int FTextureManager::CreateTexture (int lumpnum, int usetype) +// and creates the texture. +FTexture * FTextureManager::DoCreateTexture (int lumpnum, int usetype) { FTexture *out = NULL; enum { t_patch, t_raw, t_imgz, t_png } type = t_patch; @@ -252,7 +251,7 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype) // 13 is the minimum length of anything valid (i.e a 1x1 pixel Doom patch.) if (lumpnum < 0 || Wads.LumpLength(lumpnum)<13) { - return -1; + return NULL; } else { @@ -272,11 +271,11 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype) // first 4 bytes match, but later bytes don't, we assume it's // a corrupt PNG.) data.Read (first4bytes.b, 4); - if (first4bytes.dw != MAKE_ID(13,10,26,10)) return -1; + if (first4bytes.dw != MAKE_ID(13,10,26,10)) return NULL; data.Read (first4bytes.b, 4); - if (first4bytes.dw != MAKE_ID(0,0,0,13)) return -1; + if (first4bytes.dw != MAKE_ID(0,0,0,13)) return NULL; data.Read (first4bytes.b, 4); - if (first4bytes.dw != MAKE_ID('I','H','D','R')) return -1; + if (first4bytes.dw != MAKE_ID('I','H','D','R')) return NULL; // The PNG looks valid so far. Check the IHDR to make sure it's a // type of PNG we support. @@ -285,15 +284,15 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype) if (compression != 0 || filter != 0 || interlace > 1) { - return -1; + return NULL; } if (!((1 << colortype) & 0x5D)) { - return -1; + return NULL; } if (!((1 << bitdepth) & 0x116)) { - return -1; + return NULL; } // Just for completeness, make sure the PNG has something more than an @@ -305,7 +304,7 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype) data.Read (first4bytes.b, 4); if (first4bytes.dw == MAKE_ID('I','E','N','D')) { - return -1; + return NULL; } } @@ -323,25 +322,25 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype) { if (data.Read (first4bytes.w, 2) != 2) { - return -1; + return NULL; } data.Seek (BigShort(first4bytes.w[0]) - 2, SEEK_CUR); if (data.Read (first4bytes.b + 2, 2) != 2 || first4bytes.b[2] != 0xFF) { - return -1; + return NULL; } } if (data.Read (first4bytes.b, 3) != 3) { - return -1; + return NULL; } if (BigShort (first4bytes.w[0]) <5) { - return -1; + return NULL; } if (data.Read (first4bytes.b, 4) != 4) { - return -1; + return NULL; } type = t_png; out = new FJPEGTexture (lumpnum, BigShort(first4bytes.w[1]), BigShort(first4bytes.w[0])); @@ -349,7 +348,7 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype) else if (usetype == FTexture::TEX_Flat) { // allow PNGs as flats but not Doom patches. - return -1; + return NULL; } else if ((gameinfo.flags & GI_PAGESARERAW) && data.GetLength() == 64000) { @@ -438,8 +437,16 @@ int FTextureManager::CreateTexture (int lumpnum, int usetype) { out->UseType = usetype; } - return AddTexture (out); } + return out; +} + +// Calls DoCreateTexture and adds the texture to the manager. +int FTextureManager::CreateTexture (int lumpnum, int usetype) +{ + FTexture *out = DoCreateTexture(lumpnum, usetype); + + if (out != NULL) return AddTexture (out); return -1; } @@ -2138,75 +2145,68 @@ void FPNGTexture::MakeTexture () } } -struct FLumpSourceMgr : public jpeg_source_mgr +FLumpSourceMgr::FLumpSourceMgr (FileReader *lump, j_decompress_ptr cinfo) +: Lump (lump) { - FWadLump &Lump; - JOCTET Buffer[4096]; - bool StartOfFile; + cinfo->src = this; + init_source = InitSource; + fill_input_buffer = FillInputBuffer; + skip_input_data = SkipInputData; + resync_to_restart = jpeg_resync_to_restart; + term_source = TermSource; + bytes_in_buffer = 0; + next_input_byte = NULL; +} - FLumpSourceMgr (FWadLump &lump, j_decompress_ptr cinfo) - : Lump (lump) +void FLumpSourceMgr::InitSource (j_decompress_ptr cinfo) +{ + ((FLumpSourceMgr *)(cinfo->src))->StartOfFile = true; +} + +boolean FLumpSourceMgr::FillInputBuffer (j_decompress_ptr cinfo) +{ + FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src); + long nbytes = me->Lump->Read (me->Buffer, sizeof(me->Buffer)); + + if (nbytes <= 0) { - cinfo->src = this; - init_source = InitSource; - fill_input_buffer = FillInputBuffer; - skip_input_data = SkipInputData; - resync_to_restart = jpeg_resync_to_restart; - term_source = TermSource; - bytes_in_buffer = 0; - next_input_byte = NULL; + me->Buffer[0] = (JOCTET)0xFF; + me->Buffer[1] = (JOCTET)JPEG_EOI; + nbytes = 2; } + me->next_input_byte = me->Buffer; + me->bytes_in_buffer = nbytes; + me->StartOfFile = false; + return TRUE; +} - static void InitSource (j_decompress_ptr cinfo) +void FLumpSourceMgr::SkipInputData (j_decompress_ptr cinfo, long num_bytes) +{ + FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src); + if (num_bytes <= (long)me->bytes_in_buffer) { - ((FLumpSourceMgr *)(cinfo->src))->StartOfFile = true; + me->bytes_in_buffer -= num_bytes; + me->next_input_byte += num_bytes; } - - static boolean FillInputBuffer (j_decompress_ptr cinfo) + else { - FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src); - long nbytes = me->Lump.Read (me->Buffer, sizeof(me->Buffer)); - - if (nbytes <= 0) - { - me->Buffer[0] = (JOCTET)0xFF; - me->Buffer[1] = (JOCTET)JPEG_EOI; - nbytes = 2; - } - me->next_input_byte = me->Buffer; - me->bytes_in_buffer = nbytes; - me->StartOfFile = false; - return TRUE; + num_bytes -= (long)me->bytes_in_buffer; + me->Lump->Seek (num_bytes, SEEK_CUR); + FillInputBuffer (cinfo); } +} - static void SkipInputData (j_decompress_ptr cinfo, long num_bytes) - { - FLumpSourceMgr *me = (FLumpSourceMgr *)(cinfo->src); - if (num_bytes <= (long)me->bytes_in_buffer) - { - me->bytes_in_buffer -= num_bytes; - me->next_input_byte += num_bytes; - } - else - { - num_bytes -= (long)me->bytes_in_buffer; - me->Lump.Seek (num_bytes, SEEK_CUR); - FillInputBuffer (cinfo); - } - } +void FLumpSourceMgr::TermSource (j_decompress_ptr cinfo) +{ +} - static void TermSource (j_decompress_ptr cinfo) - { - } -}; - -static void JPEG_ErrorExit (j_common_ptr cinfo) +void JPEG_ErrorExit (j_common_ptr cinfo) { (*cinfo->err->output_message) (cinfo); throw -1; } -static void JPEG_OutputMessage (j_common_ptr cinfo) +void JPEG_OutputMessage (j_common_ptr cinfo) { char buffer[JMSG_LENGTH_MAX]; @@ -2299,7 +2299,7 @@ void FJPEGTexture::MakeTexture () jpeg_create_decompress(&cinfo); try { - FLumpSourceMgr sourcemgr(lump, &cinfo); + FLumpSourceMgr sourcemgr(&lump, &cinfo); jpeg_read_header(&cinfo, TRUE); if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || diff --git a/src/r_data.h b/src/r_data.h index 45795d1517..975d70fe4d 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -29,6 +29,7 @@ #include "v_video.h" + // A texture that doesn't really exist class FDummyTexture : public FTexture { @@ -210,6 +211,7 @@ protected: }; + // A JPEG image class FJPEGTexture : public FTexture { diff --git a/src/r_defs.h b/src/r_defs.h index 992641cac7..72f8cd5729 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -731,6 +731,7 @@ public: void AddTiles (void *tileFile); void AddExtraTextures (); // Adds patches in the ns_newtextures namespace + static FTexture *DoCreateTexture (int lumpnum, int usetype=FTexture::TEX_Any); int CreateTexture (int lumpnum, int usetype=FTexture::TEX_Any); // Also calls AddTexture int AddTexture (FTexture *texture); int AddPatch (const char *patchname, int namespc=0); diff --git a/src/r_jpeg.h b/src/r_jpeg.h new file mode 100644 index 0000000000..923e265a5c --- /dev/null +++ b/src/r_jpeg.h @@ -0,0 +1,29 @@ +#ifndef __R_JPEG_H +#define __R_JPEG_H + +extern "C" +{ +#include +} +#include "files.h" + + +struct FLumpSourceMgr : public jpeg_source_mgr +{ + FileReader *Lump; + JOCTET Buffer[4096]; + bool StartOfFile; + + FLumpSourceMgr (FileReader *lump, j_decompress_ptr cinfo); + static void InitSource (j_decompress_ptr cinfo); + static boolean FillInputBuffer (j_decompress_ptr cinfo); + static void SkipInputData (j_decompress_ptr cinfo, long num_bytes); + static void TermSource (j_decompress_ptr cinfo); +}; + + +void JPEG_ErrorExit (j_common_ptr cinfo); +void JPEG_OutputMessage (j_common_ptr cinfo); + + +#endif \ No newline at end of file diff --git a/src/w_wad.cpp b/src/w_wad.cpp index b955fe50f9..0d2a982ea0 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -100,6 +100,7 @@ enum LUMPF_COMPRESSED = 2, // Zip-compressed LUMPF_ZIPFILE = 4, // Inside a Zip file - used to enforce use of special directories insize Zips LUMPF_NEEDFILESTART = 8, // Still need to process local file header to find file start inside a zip + LUMPF_EXTERNAL = 16, // Lump is from an external file that won't be kept open permanently }; class FWadCollection::WadFileRecord : public FileReader @@ -161,7 +162,7 @@ void uppercopy (char *to, const char *from) FWadCollection::FWadCollection () : FirstLumpIndex(NULL), NextLumpIndex(NULL), FirstLumpIndex_FullName(NULL), NextLumpIndex_FullName(NULL), - LumpInfo(NULL), Wads(NULL), NumLumps(0), NumWads(0) + NumLumps(0) { } @@ -187,27 +188,20 @@ FWadCollection::~FWadCollection () delete[] NextLumpIndex_FullName; NextLumpIndex_FullName = NULL; } - if (LumpInfo != NULL) + for (DWORD i = 0; i < LumpInfo.Size(); ++i) { - for (DWORD i = 0; i < NumLumps; ++i) + if (LumpInfo[i].fullname != NULL) { - if (LumpInfo[i].fullname != NULL) - { - delete[] LumpInfo[i].fullname; - } + delete[] LumpInfo[i].fullname; } - free (LumpInfo); - LumpInfo = NULL; } - if (Wads != NULL) + LumpInfo.Clear(); + + for (DWORD i = 0; i < Wads.Size(); ++i) { - for (DWORD i = 0; i < NumWads; ++i) - { - delete Wads[i]; - } - free (Wads); - Wads = NULL; + delete Wads[i]; } + Wads.Clear(); } //========================================================================== @@ -227,9 +221,9 @@ void FWadCollection::InitMultipleFiles (wadlist_t **filenames) // open all the files, load headers, and count lumps numfiles = 0; - NumWads = 0; + Wads.Clear(); + LumpInfo.Clear(); NumLumps = 0; - LumpInfo = NULL; // will be realloced as lumps are added while (*filenames) { @@ -276,6 +270,28 @@ void FWadCollection::InitMultipleFiles (wadlist_t **filenames) InitHashChains (); } +//----------------------------------------------------------------------- +// +// Adds an external file to the lump list but not to the hash chains +// It's just a simple means to assign a lump number to some file so that +// the texture manager can read from it. +// +//----------------------------------------------------------------------- + +int FWadCollection::AddExternalFile(const char *filename) +{ + LumpRecord lump; + + lump.fullname = copystring(filename); + lump.name[0]=0; + lump.wadnum=-1; + lump.flags = LUMPF_EXTERNAL; + lump.position = 0; + lump.namespc = ns_global; + lump.compressedsize = 0; + return LumpInfo.Push(lump); +} + #define BUFREADCOMMENT (0x400) //----------------------------------------------------------------------- @@ -421,7 +437,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt BloodCrypt (lumps, header.rff.DirOfs, header.rff.NumLumps * sizeof(rfflump_t)); NumLumps += header.rff.NumLumps; - LumpInfo = (LumpRecord *)M_Realloc (LumpInfo, NumLumps*sizeof(LumpRecord)); + LumpInfo.Resize(NumLumps); lump_p = &LumpInfo[startlump]; for (i = 0, rff_p = lumps; i < header.rff.NumLumps; ++i, ++rff_p) @@ -443,7 +459,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt uppercopy (lump_p->name, rff_p->Name); lump_p->name[8] = 0; - lump_p->wadnum = (WORD)NumWads; + lump_p->wadnum = (WORD)Wads.Size(); lump_p->position = LittleLong(rff_p->FilePos); lump_p->size = LittleLong(rff_p->Size); lump_p->flags = (rff_p->Flags & 0x10) >> 4; @@ -475,12 +491,12 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt pos = sizeof(grpinfo_t) + header.grp.NumLumps * sizeof(grplump_t); NumLumps += header.grp.NumLumps; - LumpInfo = (LumpRecord *)M_Realloc (LumpInfo, NumLumps*sizeof(LumpRecord)); + LumpInfo.Resize(NumLumps); lump_p = &LumpInfo[startlump]; for (i = 0, grp_p = lumps; i < header.grp.NumLumps; ++i, ++grp_p) { - lump_p->wadnum = (WORD)NumWads; + lump_p->wadnum = (WORD)Wads.Size(); lump_p->position = pos; lump_p->size = LittleLong(grp_p->Size); pos += lump_p->size; @@ -521,7 +537,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt } NumLumps += LittleShort(info.wEntryCount); - LumpInfo = (LumpRecord *)M_Realloc (LumpInfo, NumLumps*sizeof(LumpRecord)); + LumpInfo.Resize(NumLumps); lump_p = &LumpInfo[startlump]; // Load the entire central directory. Too bad that this contains variable length entries... @@ -617,7 +633,7 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt memset(lump_p->name, 0, 8); } - lump_p->wadnum = (WORD)NumWads; + lump_p->wadnum = (WORD)Wads.Size(); lump_p->flags = LittleShort(zip_fh->wCompression) == Z_DEFLATED? LUMPF_COMPRESSED|LUMPF_ZIPFILE : LUMPF_ZIPFILE; lump_p->compressedsize = LittleLong(zip_fh->dwCompressedSize); @@ -642,10 +658,10 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt } // Resize the lump record array to its actual size NumLumps -= skipped; - LumpInfo = (LumpRecord *)M_Realloc (LumpInfo, NumLumps*sizeof(LumpRecord)); + LumpInfo.Resize(NumLumps); // Entries in Zips are sorted alphabetically. - qsort(LumpInfo + startlump, NumLumps - startlump, sizeof(LumpRecord), lumpcmp); + qsort(&LumpInfo[startlump], NumLumps - startlump, sizeof(LumpRecord), lumpcmp); } else { // This is just a single lump file @@ -664,14 +680,14 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt header.magic[0] != ZIP_ID && (header.magic[0] != GRP_ID_0 || header.magic[1] != GRP_ID_1 || header.magic[2] != GRP_ID_2)) { - LumpInfo = (LumpRecord *)M_Realloc (LumpInfo, NumLumps*sizeof(LumpRecord)); + LumpInfo.Resize(NumLumps); lump_p = &LumpInfo[startlump]; for (i = startlump; i < (unsigned)NumLumps; i++, lump_p++, fileinfo++) { // [RH] Convert name to uppercase during copy uppercopy (lump_p->name, fileinfo->Name); lump_p->name[8] = 0; - lump_p->wadnum = (WORD)NumWads; + lump_p->wadnum = (WORD)Wads.Size(); lump_p->position = LittleLong(fileinfo->FilePos); lump_p->size = LittleLong(fileinfo->Size); lump_p->namespc = ns_global; @@ -690,11 +706,10 @@ void FWadCollection::AddFile (const char *filename, const char * data, int lengt wadinfo->FirstLump = startlump; wadinfo->LastLump = NumLumps - 1; - Wads = (WadFileRecord **)M_Realloc (Wads, (++NumWads)*sizeof(WadFileRecord*)); - Wads[NumWads-1] = wadinfo; + Wads.Push(wadinfo); // [RH] Put the Strife Teaser voices into the voices namespace - if (NumWads == IWAD_FILENUM+1 && gameinfo.gametype == GAME_Strife && gameinfo.flags & GI_SHAREWARE) + if (Wads.Size() == IWAD_FILENUM+1 && gameinfo.gametype == GAME_Strife && gameinfo.flags & GI_SHAREWARE) { FindStrifeTeaserVoices (); } @@ -759,7 +774,7 @@ int FWadCollection::CheckIfWadLoaded (const char *name) if (strrchr (name, '/') != NULL) { - for (i = 0; i < NumWads; ++i) + for (i = 0; i < Wads.Size(); ++i) { if (stricmp (GetWadFullName (i), name) == 0) { @@ -769,7 +784,7 @@ int FWadCollection::CheckIfWadLoaded (const char *name) } else { - for (i = 0; i < NumWads; ++i) + for (i = 0; i < Wads.Size(); ++i) { if (stricmp (GetWadName (i), name) == 0) { @@ -1066,7 +1081,7 @@ bool FWadCollection::IsMarker (const FWadCollection::LumpRecord *lump, const cha { // If the previous lump was of the form FF_END and this one is // of the form F_END, ignore this as a marker - if (marker[2] == 'E' && lump > LumpInfo) + if (marker[2] == 'E' && lump > &LumpInfo[0]) { if ((lump - 1)->name[0] == *marker && strncmp ((lump - 1)->name + 1, marker, 7) == 0) @@ -1204,7 +1219,7 @@ void FWadCollection::ScanForFlatHack (int startlump) } } ++NumLumps; - LumpInfo = (LumpRecord *)M_Realloc (LumpInfo, NumLumps*sizeof(LumpRecord)); + LumpInfo.Resize(NumLumps); for (; i > j; --i) { LumpInfo[i+1] = LumpInfo[i]; @@ -1384,7 +1399,7 @@ int FWadCollection::MergeLumps (const char *start, const char *end, int space) } else // Check if this is the start of a block - if (IsMarker (LumpInfo + i, ustart)) + if (IsMarker (&LumpInfo[i], ustart)) { insideBlock = true; markerpos = i; @@ -1415,7 +1430,7 @@ int FWadCollection::MergeLumps (const char *start, const char *end, int space) insideBlock = false; LumpInfo[oldlumps++] = LumpInfo[i]; } - else if (IsMarker (LumpInfo + i, uend)) + else if (IsMarker (&LumpInfo[i], uend)) { // It is the end of a block. We'll add the end marker once // we've processed everything. @@ -1434,10 +1449,9 @@ int FWadCollection::MergeLumps (const char *start, const char *end, int space) if (newlumps) { - if (size_t(oldlumps + newlumps) >= NumLumps) - LumpInfo = (LumpRecord *)M_Realloc (LumpInfo, (oldlumps + newlumps + 1) * sizeof(LumpRecord) ); + LumpInfo.Resize(oldlumps+newlumps+1); - memcpy (LumpInfo + oldlumps, newlumpinfos, sizeof(LumpRecord) * newlumps); + memcpy (&LumpInfo[oldlumps], newlumpinfos, sizeof(LumpRecord) * newlumps); markerpos = oldlumps; NumLumps = oldlumps + newlumps; @@ -1502,13 +1516,13 @@ int FWadCollection::FindLump (const char *name, int *lastlump, bool anyns) uppercopy (name8, name); - lump_p = LumpInfo + *lastlump; - while (lump_p < LumpInfo + NumLumps) + lump_p = &LumpInfo[*lastlump]; + while (lump_p < &LumpInfo[NumLumps]) { if ((anyns || lump_p->namespc == ns_global) && *(__int64 *)&lump_p->name == *(__int64 *)&name8) { - int lump = lump_p - LumpInfo; + int lump = lump_p - &LumpInfo[0]; *lastlump = lump + 1; return lump; } @@ -1587,7 +1601,7 @@ int FWadCollection::GetLumpNamespace (int lump) const int FWadCollection::GetLumpFile (int lump) const { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= LumpInfo.Size()) return -1; return LumpInfo[lump].wadnum; } @@ -1675,20 +1689,20 @@ FWadLump FWadCollection::OpenLumpNum (int lump) LumpRecord *l; WadFileRecord *wad; - if ((unsigned)lump >= (unsigned)NumLumps) + if ((unsigned)lump >= (unsigned)LumpInfo.Size()) { I_Error ("W_MapLumpNum: %u >= NumLumps",lump); } l = &LumpInfo[lump]; - wad = Wads[l->wadnum]; + wad = l->wadnum >= 0? Wads[l->wadnum] : NULL; if (l->flags & LUMPF_NEEDFILESTART) { SetLumpAddress(l); } - wad->Seek (l->position, SEEK_SET); + if (wad != NULL) wad->Seek (l->position, SEEK_SET); if (l->flags & LUMPF_COMPRESSED) { @@ -1699,12 +1713,39 @@ FWadLump FWadCollection::OpenLumpNum (int lump) frz.Read(buffer, l->size); return FWadLump(buffer, l->size, true); } + else if (l->flags & LUMPF_EXTERNAL) + { + FILE * f; + if (wad != NULL) // The WadRecord in this case is just a means to store a path + { + FString name; + + name.Format("%s/%s", wad->Name, l->fullname); + f = fopen(name, "rb"); + } + else + { + f = fopen(l->fullname, "rb"); + } + // This is an external file that cannot be kept open so we have to read + // the complete contents into a memory buffer first + if (f != NULL) + { + char * buffer = new char[l->size+1]; // the last byte is used as a reference counter + buffer[l->size] = 0; + fread(buffer, 1, l->size, f); + fclose(f); + return FWadLump(buffer, l->size, true); + } + // The file got deleted or worse. At least return something. + Printf("%s: Unable to open file\n", l->fullname); + return FWadLump("", 1, false); + } else if (wad->MemoryData != NULL) { // A lump from an embedded WAD // Handling this here creates less overhead than trying // to do it inside the FWadLump class. - return FWadLump((char*)wad->MemoryData + l->position, l->size, false); } else @@ -1730,13 +1771,13 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump) WadFileRecord *wad; FILE *f; - if ((unsigned)lump >= (unsigned)NumLumps) + if ((unsigned)lump >= (unsigned)LumpInfo.Size()) { I_Error ("W_MapLumpNum: %u >= NumLumps",lump); } l = &LumpInfo[lump]; - wad = Wads[l->wadnum]; + wad = l->wadnum >= 0? Wads[l->wadnum] : NULL; if (l->flags & LUMPF_NEEDFILESTART) { @@ -1754,6 +1795,34 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump) wad->Seek(address, SEEK_SET); return new FWadLump(buffer, l->size, true); //... but restore the file pointer afterward! } + else if (l->flags & LUMPF_EXTERNAL) + { + FILE * f; + if (wad != NULL) // The WadRecord in this case is just a means to store a path + { + FString name; + + name.Format("%s/%s", wad->Name, l->fullname); + f = fopen(name, "rb"); + } + else + { + f = fopen(l->fullname, "rb"); + } + // This is an external file that cannot be kept open so we have to read + // the complete contents into a memory buffer first + if (f != NULL) + { + char * buffer = new char[l->size+1]; // the last byte is used as a reference counter + buffer[l->size] = 0; + fread(buffer, 1, l->size, f); + fclose(f); + return new FWadLump(buffer, l->size, true); + } + // The file got deleted or worse. At least return something. + Printf("%s: Unable to open file\n", l->fullname); + return new FWadLump("", 1, false); + } else if (wad->MemoryData!=NULL) { // A lump from an embedded WAD @@ -1782,12 +1851,13 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump) // GetFileReader // // Retrieves the FileReader object to access the given WAD +// Careful: This is only useful for real WAD files! // //========================================================================== FileReader *FWadCollection::GetFileReader(int wadnum) { - if ((DWORD)wadnum >= NumWads) + if ((DWORD)wadnum >= Wads.Size()) { return NULL; } @@ -1806,7 +1876,7 @@ const char *FWadCollection::GetWadName (int wadnum) const { const char *name, *slash; - if ((DWORD)wadnum >= NumWads) + if ((DWORD)wadnum >= Wads.Size()) { return NULL; } @@ -1826,7 +1896,7 @@ const char *FWadCollection::GetWadName (int wadnum) const const char *FWadCollection::GetWadFullName (int wadnum) const { - if ((unsigned int)wadnum >= NumWads) + if ((unsigned int)wadnum >= Wads.Size()) { return NULL; } @@ -1854,7 +1924,7 @@ bool FWadCollection::IsUncompressedFile(int lump) const LumpRecord * l = &LumpInfo[lump]; - if (l->flags & LUMPF_COMPRESSED) return false; + if (l->flags & (LUMPF_COMPRESSED|LUMPF_EXTERNAL)) return false; else if (Wads[l->wadnum]->MemoryData!=NULL) return false; else return true; } @@ -1893,7 +1963,7 @@ void FWadCollection::SkinHack (int baselump) { bool skinned = false; bool hasmap = false; - size_t i; + DWORD i; for (i = baselump; i < NumLumps; i++) { @@ -1908,7 +1978,7 @@ void FWadCollection::SkinHack (int baselump) if (!skinned) { skinned = true; - size_t j; + DWORD j; for (j = baselump; j < NumLumps; j++) { diff --git a/src/w_wad.h b/src/w_wad.h index 04e3690e21..35a9e11c98 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -25,6 +25,7 @@ #include "files.h" #include "doomdef.h" +#include "tarray.h" // [RH] Compare wad header as ints instead of chars #define IWAD_ID MAKE_ID('I','W','A','D') @@ -209,6 +210,8 @@ public: int GetNumLumps () const; + int AddExternalFile(const char *filename); + protected: class WadFileRecord; struct LumpRecord; @@ -220,9 +223,9 @@ protected: WORD *NextLumpIndex_FullName; - LumpRecord *LumpInfo; - WadFileRecord **Wads; - DWORD NumLumps; + TArray LumpInfo; + TArrayWads; + DWORD NumLumps; // Not necessarily the same as LumpInfo.Size() DWORD NumWads; void SkinHack (int baselump); diff --git a/zdoom.vcproj b/zdoom.vcproj index c54d8a6651..c1780ed668 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -9433,6 +9433,10 @@ RelativePath=".\src\r_draw.h" > + +