diff --git a/src/common/utility/cmdlib.cpp b/src/common/utility/cmdlib.cpp index 3eb07adc966..2b14df6539d 100644 --- a/src/common/utility/cmdlib.cpp +++ b/src/common/utility/cmdlib.cpp @@ -36,6 +36,8 @@ #include "cmdlib.h" #include "findfile.h" +#include "files.h" +#include "md5.h" #include #include @@ -1032,3 +1034,36 @@ FString M_ZLibError(int zerr) return errs[-zerr - 1]; } } + +void md5Update(FileReader& file, MD5Context& md5, unsigned len) +{ + uint8_t readbuf[8192]; + unsigned t; + + while (len > 0) + { + t = std::min(len, sizeof(readbuf)); + len -= t; + t = (long)file.Read(readbuf, t); + md5.Update(readbuf, t); + } +} + + +//========================================================================== +// +// uppercoppy +// +// [RH] Copy up to 8 chars, upper-casing them in the process +//========================================================================== + +void uppercopy(char* to, const char* from) +{ + int i; + + for (i = 0; i < 8 && from[i]; i++) + to[i] = toupper(from[i]); + for (; i < 8; i++) + to[i] = 0; +} + diff --git a/src/common/utility/cmdlib.h b/src/common/utility/cmdlib.h index 75cb5a012d3..c3ea527f2df 100644 --- a/src/common/utility/cmdlib.h +++ b/src/common/utility/cmdlib.h @@ -84,4 +84,10 @@ inline int32_t Scale(int32_t a, int32_t b, int32_t c) return (int32_t)(((int64_t)a * b) / c); } +class FileReader; +struct MD5Context; + +void md5Update(FileReader& file, MD5Context& md5, unsigned len); +void uppercopy(char* to, const char* from); + #endif diff --git a/src/console/c_cmds.cpp b/src/console/c_cmds.cpp index cc1b3bb7c85..87d38aa9f48 100644 --- a/src/console/c_cmds.cpp +++ b/src/console/c_cmds.cpp @@ -848,7 +848,7 @@ CCMD (wdir) Printf ("usage: wdir \n"); return; } - int wadnum = fileSystem.CheckIfWadLoaded (argv[1]); + int wadnum = fileSystem.CheckIfResourceFileLoaded (argv[1]); if (wadnum < 0) { Printf ("%s must be loaded to view its directory.\n", argv[1]); diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 5906fbfcd9f..699812f97bd 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -270,11 +270,10 @@ FIWadManager::FIWadManager(const char *firstfn, const char *optfn) { FileSystem check; TArray fns; - TArray deletes; fns.Push(firstfn); if (optfn) fns.Push(optfn); - check.InitMultipleFiles(fns, deletes, true); + check.InitMultipleFiles(fns, true); if (check.GetNumLumps() > 0) { int num = check.CheckNumForName("IWADINFO"); diff --git a/src/d_main.cpp b/src/d_main.cpp index 6ad33e0e949..91dce01e487 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -103,6 +103,7 @@ #include "s_music.h" #include "swrenderer/r_swcolormaps.h" #include "findfile.h" +#include "md5.h" EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Int, vr_mode) @@ -2018,11 +2019,10 @@ static FString ParseGameInfo(TArray &pwads, const char *fn, const char static FString CheckGameInfo(TArray & pwads) { - TArray deletes; FileSystem check; // Open the entire list as a temporary file system and look for a GAMEINFO lump. The last one will automatically win. - check.InitMultipleFiles(pwads, deletes, true); + check.InitMultipleFiles(pwads, true); if (check.GetNumLumps() > 0) { int num = check.CheckNumForName("GAMEINFO"); @@ -2030,7 +2030,7 @@ static FString CheckGameInfo(TArray & pwads) { // Found one! auto data = check.ReadLumpIntoArray(num); - auto wadname = check.GetWadName(check.GetLumpFile(num)); + auto wadname = check.GetResourceFileName(check.GetLumpFile(num)); return ParseGameInfo(pwads, wadname, (const char*)data.Data(), data.Size()); } } @@ -2321,6 +2321,336 @@ static void NewFailure () I_FatalError ("Failed to allocate memory from system heap"); } + +//========================================================================== +// +// RenameSprites +// +// Renames sprites in IWADs so that unique actors can have unique sprites, +// making it possible to import any actor from any game into any other +// game without jumping through hoops to resolve duplicate sprite names. +// You just need to know what the sprite's new name is. +// +//========================================================================== + +static void RenameSprites(FileSystem &fileSystem, const TArray& deletelumps) +{ + bool renameAll; + bool MNTRZfound = false; + const char* altbigfont = gameinfo.gametype == GAME_Strife ? "SBIGFONT" : (gameinfo.gametype & GAME_Raven) ? "HBIGFONT" : "DBIGFONT"; + + static const uint32_t HereticRenames[] = + { MAKE_ID('H','E','A','D'), MAKE_ID('L','I','C','H'), // Ironlich + }; + + static const uint32_t HexenRenames[] = + { MAKE_ID('B','A','R','L'), MAKE_ID('Z','B','A','R'), // ZBarrel + MAKE_ID('A','R','M','1'), MAKE_ID('A','R','_','1'), // MeshArmor + MAKE_ID('A','R','M','2'), MAKE_ID('A','R','_','2'), // FalconShield + MAKE_ID('A','R','M','3'), MAKE_ID('A','R','_','3'), // PlatinumHelm + MAKE_ID('A','R','M','4'), MAKE_ID('A','R','_','4'), // AmuletOfWarding + MAKE_ID('S','U','I','T'), MAKE_ID('Z','S','U','I'), // ZSuitOfArmor and ZArmorChunk + MAKE_ID('T','R','E','1'), MAKE_ID('Z','T','R','E'), // ZTree and ZTreeDead + MAKE_ID('T','R','E','2'), MAKE_ID('T','R','E','S'), // ZTreeSwamp150 + MAKE_ID('C','A','N','D'), MAKE_ID('B','C','A','N'), // ZBlueCandle + MAKE_ID('R','O','C','K'), MAKE_ID('R','O','K','K'), // rocks and dirt in a_debris.cpp + MAKE_ID('W','A','T','R'), MAKE_ID('H','W','A','T'), // Strife also has WATR + MAKE_ID('G','I','B','S'), MAKE_ID('P','O','L','5'), // RealGibs + MAKE_ID('E','G','G','M'), MAKE_ID('P','R','K','M'), // PorkFX + MAKE_ID('I','N','V','U'), MAKE_ID('D','E','F','N'), // Icon of the Defender + }; + + static const uint32_t StrifeRenames[] = + { MAKE_ID('M','I','S','L'), MAKE_ID('S','M','I','S'), // lots of places + MAKE_ID('A','R','M','1'), MAKE_ID('A','R','M','3'), // MetalArmor + MAKE_ID('A','R','M','2'), MAKE_ID('A','R','M','4'), // LeatherArmor + MAKE_ID('P','M','A','P'), MAKE_ID('S','M','A','P'), // StrifeMap + MAKE_ID('T','L','M','P'), MAKE_ID('T','E','C','H'), // TechLampSilver and TechLampBrass + MAKE_ID('T','R','E','1'), MAKE_ID('T','R','E','T'), // TreeStub + MAKE_ID('B','A','R','1'), MAKE_ID('B','A','R','C'), // BarricadeColumn + MAKE_ID('S','H','T','2'), MAKE_ID('M','P','U','F'), // MaulerPuff + MAKE_ID('B','A','R','L'), MAKE_ID('B','B','A','R'), // StrifeBurningBarrel + MAKE_ID('T','R','C','H'), MAKE_ID('T','R','H','L'), // SmallTorchLit + MAKE_ID('S','H','R','D'), MAKE_ID('S','H','A','R'), // glass shards + MAKE_ID('B','L','S','T'), MAKE_ID('M','A','U','L'), // Mauler + MAKE_ID('L','O','G','G'), MAKE_ID('L','O','G','W'), // StickInWater + MAKE_ID('V','A','S','E'), MAKE_ID('V','A','Z','E'), // Pot and Pitcher + MAKE_ID('C','N','D','L'), MAKE_ID('K','N','D','L'), // Candle + MAKE_ID('P','O','T','1'), MAKE_ID('M','P','O','T'), // MetalPot + MAKE_ID('S','P','I','D'), MAKE_ID('S','T','L','K'), // Stalker + }; + + const uint32_t* renames; + int numrenames; + + switch (gameinfo.gametype) + { + case GAME_Doom: + default: + // Doom's sprites don't get renamed. + renames = nullptr; + numrenames = 0; + break; + + case GAME_Heretic: + renames = HereticRenames; + numrenames = sizeof(HereticRenames) / 8; + break; + + case GAME_Hexen: + renames = HexenRenames; + numrenames = sizeof(HexenRenames) / 8; + break; + + case GAME_Strife: + renames = StrifeRenames; + numrenames = sizeof(StrifeRenames) / 8; + break; + } + + unsigned NumFiles = fileSystem.GetNumLumps(); + + for (uint32_t i = 0; i < NumFiles; i++) + { + // check for full Minotaur animations. If this is not found + // some frames need to be renamed. + if (fileSystem.GetLumpNamespace(i) == ns_sprites) + { + auto& shortName = fileSystem.GetShortName(i); + if (shortName.dword == MAKE_ID('M', 'N', 'T', 'R') && shortName.String[4] == 'Z') + { + MNTRZfound = true; + break; + } + } + } + + renameAll = !!Args->CheckParm("-oldsprites") || nospriterename; + + for (uint32_t i = 0; i < NumFiles; i++) + { + auto& shortName = fileSystem.GetShortName(i); + if (fileSystem.GetLumpNamespace(i) == ns_sprites) + { + // Only sprites in the IWAD normally get renamed + if (renameAll || fileSystem.GetLumpFile(i) == fileSystem.GetIwadNum()) + { + for (int j = 0; j < numrenames; ++j) + { + if (shortName.dword == renames[j * 2]) + { + shortName.dword = renames[j * 2 + 1]; + } + } + if (gameinfo.gametype == GAME_Hexen) + { + if (fileSystem.CheckLumpName(i, "ARTIINVU")) + { + shortName.String[4] = 'D'; shortName.String[5] = 'E'; + shortName.String[6] = 'F'; shortName.String[7] = 'N'; + } + } + } + + if (!MNTRZfound) + { + if (shortName.dword == MAKE_ID('M', 'N', 'T', 'R')) + { + for (size_t fi : {4, 6}) + { + if (shortName.String[fi] >= 'F' && shortName.String[fi] <= 'K') + { + shortName.String[fi] += 'U' - 'F'; + } + } + } + } + + // When not playing Doom rename all BLOD sprites to BLUD so that + // the same blood states can be used everywhere + if (!(gameinfo.gametype & GAME_DoomChex)) + { + if (shortName.dword == MAKE_ID('B', 'L', 'O', 'D')) + { + shortName.dword = MAKE_ID('B', 'L', 'U', 'D'); + } + } + } + else if (fileSystem.GetLumpNamespace(i) == ns_global) + { + int fn = fileSystem.GetLumpFile(i); + if (fn >= fileSystem.GetIwadNum() && fn <= fileSystem.GetMaxIwadNum() && deletelumps.Find(shortName.String) < deletelumps.Size()) + { + shortName.String[0] = 0; // Lump must be deleted from directory. + } + // Rename the game specific big font lumps so that the font manager does not have to do problematic special checks for them. + else if (!strcmp(shortName.String, altbigfont)) + { + strcpy(shortName.String, "BIGFONT"); + } + } + } +} + +//========================================================================== +// +// RenameNerve +// +// Renames map headers and map name pictures in nerve.wad so as to load it +// alongside Doom II and offer both episodes without causing conflicts. +// MD5 checksum for NERVE.WAD: 967d5ae23daf45196212ae1b605da3b0 (3,819,855) +// MD5 checksum for Unity version of NERVE.WAD: 4214c47651b63ee2257b1c2490a518c9 (3,821,966) +// +//========================================================================== +void RenameNerve(FileSystem& fileSystem) +{ + if (gameinfo.gametype != GAME_Doom) + return; + + const int numnerveversions = 2; + + bool found = false; + uint8_t cksum[16]; + static const uint8_t nerve[numnerveversions][16] = { + { 0x96, 0x7d, 0x5a, 0xe2, 0x3d, 0xaf, 0x45, 0x19, + 0x62, 0x12, 0xae, 0x1b, 0x60, 0x5d, 0xa3, 0xb0 }, + { 0x42, 0x14, 0xc4, 0x76, 0x51, 0xb6, 0x3e, 0xe2, + 0x25, 0x7b, 0x1c, 0x24, 0x90, 0xa5, 0x18, 0xc9 } + }; + size_t nervesize[numnerveversions] = { 3819855, 3821966 }; // NERVE.WAD's file size + int w = fileSystem.GetIwadNum(); + while (++w < fileSystem.GetNumWads()) + { + auto fr = fileSystem.GetFileReader(w); + int isizecheck = -1; + if (fr == NULL) + { + continue; + } + for (int icheck = 0; icheck < numnerveversions; icheck++) + if (fr->GetLength() == (long)nervesize[icheck]) + isizecheck = icheck; + if (isizecheck == -1) + { + // Skip MD5 computation when there is a + // cheaper way to know this is not the file + continue; + } + fr->Seek(0, FileReader::SeekSet); + MD5Context md5; + md5Update(*fr, md5, (unsigned)fr->GetLength()); + md5.Final(cksum); + if (memcmp(nerve[isizecheck], cksum, 16) == 0) + { + found = true; + break; + } + } + + if (!found) + return; + + for (int i = fileSystem.GetFirstLump(w); i <= fileSystem.GetLastLump(w); i++) + { + auto& shortName = fileSystem.GetShortName(i); + // Only rename the maps from NERVE.WAD + if (shortName.dword == MAKE_ID('C', 'W', 'I', 'L')) + { + shortName.String[0] = 'N'; + } + else if (shortName.dword == MAKE_ID('M', 'A', 'P', '0')) + { + shortName.String[6] = shortName.String[4]; + shortName.String[5] = '0'; + shortName.String[4] = 'L'; + shortName.dword = MAKE_ID('L', 'E', 'V', 'E'); + } + } +} + +//========================================================================== +// +// FixMacHexen +// +// Discard all extra lumps in Mac version of Hexen IWAD (demo or full) +// to avoid any issues caused by names of these lumps, including: +// * Wrong height of small font +// * Broken life bar of mage class +// +//========================================================================== + +void FixMacHexen(FileSystem& fileSystem) +{ + if (GAME_Hexen != gameinfo.gametype) + { + return; + } + + FileReader* reader = fileSystem.GetFileReader(fileSystem.GetIwadNum()); + auto iwadSize = reader->GetLength(); + + static const long DEMO_SIZE = 13596228; + static const long BETA_SIZE = 13749984; + static const long FULL_SIZE = 21078584; + + if (DEMO_SIZE != iwadSize + && BETA_SIZE != iwadSize + && FULL_SIZE != iwadSize) + { + return; + } + + reader->Seek(0, FileReader::SeekSet); + + uint8_t checksum[16]; + MD5Context md5; + + md5Update(*reader, md5, (unsigned)iwadSize); + md5.Final(checksum); + + static const uint8_t HEXEN_DEMO_MD5[16] = + { + 0x92, 0x5f, 0x9f, 0x50, 0x00, 0xe1, 0x7d, 0xc8, + 0x4b, 0x0a, 0x6a, 0x3b, 0xed, 0x3a, 0x6f, 0x31 + }; + + static const uint8_t HEXEN_BETA_MD5[16] = + { + 0x2a, 0xf1, 0xb2, 0x7c, 0xd1, 0x1f, 0xb1, 0x59, + 0xe6, 0x08, 0x47, 0x2a, 0x1b, 0x53, 0xe4, 0x0e + }; + + static const uint8_t HEXEN_FULL_MD5[16] = + { + 0xb6, 0x81, 0x40, 0xa7, 0x96, 0xf6, 0xfd, 0x7f, + 0x3a, 0x5d, 0x32, 0x26, 0xa3, 0x2b, 0x93, 0xbe + }; + + const bool isBeta = 0 == memcmp(HEXEN_BETA_MD5, checksum, sizeof checksum); + + if (!isBeta + && 0 != memcmp(HEXEN_DEMO_MD5, checksum, sizeof checksum) + && 0 != memcmp(HEXEN_FULL_MD5, checksum, sizeof checksum)) + { + return; + } + + static const int EXTRA_LUMPS = 299; + + // Hexen Beta is very similar to Demo but it has MAP41: Maze at the end of the WAD + // So keep this map if it's present but discard all extra lumps + + const int lastLump = fileSystem.GetLastLump(fileSystem.GetIwadNum()) - (isBeta ? 12 : 0); + assert(fileSystem.GetFirstLump(fileSystem.GetIwadNum()) + 299 < lastLump); + + for (int i = lastLump - EXTRA_LUMPS + 1; i <= lastLump; ++i) + { + auto& shortName = fileSystem.GetShortName(i); + shortName.String[0] = '\0'; + } +} + + //========================================================================== // // D_DoomMain @@ -2504,7 +2834,14 @@ static int D_DoomMain_Internal (void) static const char* reserved[] = { "mapinfo", "zmapinfo", "gameinfo", "sndinfo", "sbarinfo", "menudef", "gldefs", "animdefs", "decorate", "zscript", "maps/" }; for (auto p : reserved) lfi.requiredPrefixes.Push(p); - fileSystem.InitMultipleFiles (allwads, iwad_info->DeleteLumps, false, &lfi); + lfi.postprocessFunc = [&]() + { + RenameNerve(fileSystem); + RenameSprites(fileSystem, iwad_info->DeleteLumps); + FixMacHexen(fileSystem); + }; + + fileSystem.InitMultipleFiles (allwads, false, &lfi); allwads.Clear(); allwads.ShrinkToFit(); SetMapxxFlag(); diff --git a/src/g_dumpinfo.cpp b/src/g_dumpinfo.cpp index 60aa9bd904a..7a25d7f17bc 100644 --- a/src/g_dumpinfo.cpp +++ b/src/g_dumpinfo.cpp @@ -156,7 +156,7 @@ CCMD (mapchecksum) else { map->GetChecksum(cksum); - const char *wadname = fileSystem.GetWadName(fileSystem.GetLumpFile(map->lumpnum)); + const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetLumpFile(map->lumpnum)); delete map; for (size_t j = 0; j < sizeof(cksum); ++j) { @@ -367,7 +367,7 @@ CCMD(listmaps) if (map != NULL) { Printf("%s: '%s' (%s)\n", info->MapName.GetChars(), info->LookupLevelName().GetChars(), - fileSystem.GetWadName(fileSystem.GetLumpFile(map->lumpnum))); + fileSystem.GetResourceFileName(fileSystem.GetLumpFile(map->lumpnum))); delete map; } } diff --git a/src/g_game.cpp b/src/g_game.cpp index 89ef8fc529f..978a7de0a68 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1765,7 +1765,7 @@ static bool CheckSingleWad (const char *name, bool &printRequires, bool printwar { return true; } - if (fileSystem.CheckIfWadLoaded (name) < 0) + if (fileSystem.CheckIfResourceFileLoaded (name) < 0) { if (printwarn) { @@ -2129,13 +2129,13 @@ static void PutSaveWads (FSerializer &arc) const char *name; // Name of IWAD - name = fileSystem.GetWadName (fileSystem.GetIwadNum()); + name = fileSystem.GetResourceFileName (fileSystem.GetIwadNum()); arc.AddString("Game WAD", name); // Name of wad the map resides in if (fileSystem.GetLumpFile (primaryLevel->lumpnum) > fileSystem.GetIwadNum()) { - name = fileSystem.GetWadName (fileSystem.GetLumpFile (primaryLevel->lumpnum)); + name = fileSystem.GetResourceFileName (fileSystem.GetLumpFile (primaryLevel->lumpnum)); arc.AddString("Map WAD", name); } } @@ -2776,7 +2776,7 @@ void G_DoPlayDemo (void) demolump = fileSystem.CheckNumForFullName (defdemoname, true); if (demolump >= 0) { - int demolen = fileSystem.LumpLength (demolump); + int demolen = fileSystem.FileLength (demolump); demobuffer = (uint8_t *)M_Malloc(demolen); fileSystem.ReadLump (demolump, demobuffer); } diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index 5ff75572158..6de740775da 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -519,7 +519,7 @@ void SBarInfo::ParseSBarInfo(int lump) else if (fileSystem.GetLumpFile(baselump) > 0) { I_FatalError("File %s is overriding core lump sbarinfo/%s.txt.", - fileSystem.GetWadFullName(fileSystem.GetLumpFile(baselump)), sc.String); + fileSystem.GetResourceFileFullName(fileSystem.GetLumpFile(baselump)), sc.String); } ParseSBarInfo(baselump); } diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 416c20385fb..a082e295564 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -2490,7 +2490,7 @@ bool D_LoadDehLump(int lumpnum) auto ls = LumpFileNum; LumpFileNum = fileSystem.GetLumpFile(lumpnum); - PatchSize = fileSystem.LumpLength(lumpnum); + PatchSize = fileSystem.FileLength(lumpnum); PatchName = fileSystem.GetLumpFullPath(lumpnum); PatchFile = new char[PatchSize + 1]; diff --git a/src/gamedata/fonts/singlelumpfont.cpp b/src/gamedata/fonts/singlelumpfont.cpp index 2995c83e28d..083fb50db01 100644 --- a/src/gamedata/fonts/singlelumpfont.cpp +++ b/src/gamedata/fonts/singlelumpfont.cpp @@ -125,7 +125,7 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump) FontName = name; - FMemLump data1 = fileSystem.ReadLump (lump); + FileData data1 = fileSystem.ReadLump (lump); const uint8_t *data = (const uint8_t *)data1.GetMem(); if (data[0] == 0xE1 && data[1] == 0xE6 && data[2] == 0xD5 && data[3] == 0x1A) @@ -539,7 +539,7 @@ int FSingleLumpFont::BMFCompare(const void *a, const void *b) void FSingleLumpFont::CheckFON1Chars (double *luminosity) { - FMemLump memLump = fileSystem.ReadLump(Lump); + FileData memLump = fileSystem.ReadLump(Lump); const uint8_t* data = (const uint8_t*) memLump.GetMem(); uint8_t used[256], reverse[256]; diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index bb6223e3fec..1c5bd50a25d 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -856,7 +856,7 @@ void FMapInfoParser::ParseCluster() { // Check if this comes from either Hexen.wad or Hexdd.wad and if so, map to the string table. int fileno = fileSystem.GetLumpFile(lump); - auto fn = fileSystem.GetWadName(fileno); + auto fn = fileSystem.GetResourceFileName(fileno); if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, clusterinfo->ExitText.GetChars()); @@ -1987,7 +1987,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) { // Try to localize Hexen's map names. This does not use the above feature to allow these names to be unique. int fileno = fileSystem.GetLumpFile(sc.LumpNum); - auto fn = fileSystem.GetWadName(fileno); + auto fn = fileSystem.GetResourceFileName(fileno); if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, levelinfo->MapName.GetChars()); @@ -2217,7 +2217,7 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i if (fileSystem.GetLumpFile(sc.LumpNum) == 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetWadFullName(fileSystem.GetLumpFile(inclump)), sc.String); + fileSystem.GetResourceFileFullName(fileSystem.GetLumpFile(inclump)), sc.String); } } FScanner saved_sc = sc; @@ -2410,7 +2410,7 @@ void G_ParseMapInfo (FString basemapinfo) if (fileSystem.GetLumpFile(baselump) > 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetWadFullName(fileSystem.GetLumpFile(baselump)), basemapinfo.GetChars()); + fileSystem.GetResourceFileName(fileSystem.GetLumpFile(baselump)), basemapinfo.GetChars()); } parse.ParseMapInfo(baselump, gamedefaults, defaultinfo); } diff --git a/src/gamedata/keysections.cpp b/src/gamedata/keysections.cpp index 32d458853e6..7ddf90bb887 100644 --- a/src/gamedata/keysections.cpp +++ b/src/gamedata/keysections.cpp @@ -162,8 +162,8 @@ void D_LoadWadSettings () while ((lump = fileSystem.FindLump ("KEYCONF", &lastlump)) != -1) { - FMemLump data = fileSystem.ReadLump (lump); - const char *eof = (char *)data.GetMem() + fileSystem.LumpLength (lump); + FileData data = fileSystem.ReadLump (lump); + const char *eof = (char *)data.GetMem() + fileSystem.FileLength (lump); const char *conf = (char *)data.GetMem(); while (conf < eof) diff --git a/src/gamedata/resourcefiles/file_wad.cpp b/src/gamedata/resourcefiles/file_wad.cpp index f813c324825..e4caa50b5c6 100644 --- a/src/gamedata/resourcefiles/file_wad.cpp +++ b/src/gamedata/resourcefiles/file_wad.cpp @@ -39,6 +39,22 @@ #include "w_wad.h" #include "engineerrors.h" + +struct wadinfo_t +{ + // Should be "IWAD" or "PWAD". + uint32_t Magic; + uint32_t NumLumps; + uint32_t InfoTableOfs; +}; + +struct wadlump_t +{ + uint32_t FilePos; + uint32_t Size; + char Name[8]; +}; + //========================================================================== // // Wad Lump (with console doom LZSS support) diff --git a/src/gamedata/resourcefiles/resourcefile.cpp b/src/gamedata/resourcefiles/resourcefile.cpp index 03485380f0e..08919cee7d4 100644 --- a/src/gamedata/resourcefiles/resourcefile.cpp +++ b/src/gamedata/resourcefiles/resourcefile.cpp @@ -685,19 +685,4 @@ int FExternalLump::FillCache() } -bool FMemoryFile::Open(bool quiet, LumpFilterInfo*) -{ - FString name(ExtractFileBase(FileName)); - FString fname(ExtractFileBase(FileName, true)); - - Lumps.Resize(1); - Lumps[0].LumpNameSetup(fname); - Lumps[0].Owner = this; - Lumps[0].Position = 0; - Lumps[0].LumpSize = (int)Reader.GetLength(); - Lumps[0].Flags = 0; - NumLumps = 1; - return true; -} - diff --git a/src/gamedata/resourcefiles/resourcefile.h b/src/gamedata/resourcefiles/resourcefile.h index 7bc7aeae6bc..e54ed0bf504 100644 --- a/src/gamedata/resourcefiles/resourcefile.h +++ b/src/gamedata/resourcefiles/resourcefile.h @@ -13,6 +13,7 @@ struct LumpFilterInfo // The following are for checking if the root directory of a zip can be removed. TArray reservedFolders; TArray requiredPrefixes; + std::function postprocessFunc; }; class FResourceFile; @@ -86,11 +87,11 @@ struct FResourceLump friend class FWadFile; // this still needs direct access. int LumpSize; + int RefCount; protected: - FString FullName; // only valid for files loaded from a non-wad archive + FString FullName; public: uint8_t Flags; - int8_t RefCount; char * Cache; FResourceFile * Owner; @@ -199,20 +200,25 @@ struct FExternalLump : public FResourceLump }; -struct FMemoryFile : public FUncompressedFile +struct FMemoryLump : public FResourceLump { - FMemoryFile(const char *_filename, const void *sdata, int length) - : FUncompressedFile(_filename) + FMemoryLump(const void* data, int length) { - Reader.OpenMemoryArray(sdata, length); + RefCount = INT_MAX / 2; + LumpSize = length; + Cache = new char[length]; + memcpy(Cache, data, length); } - bool Open(bool quiet, LumpFilterInfo* filter); - - + virtual int FillCache() override + { + RefCount = INT_MAX / 2; // Make sure it never counts down to 0 by resetting it to something high each time it is used. + return 1; + } }; + #endif diff --git a/src/gamedata/statistics.cpp b/src/gamedata/statistics.cpp index be09d601607..578982369fe 100644 --- a/src/gamedata/statistics.cpp +++ b/src/gamedata/statistics.cpp @@ -459,7 +459,7 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level) wad = fileSystem.GetLumpFile(map->lumpnum); delete map; } - const char * name = fileSystem.GetWadName(wad); + const char * name = fileSystem.GetResourceFileName(wad); FString section = ExtractFileBase(name) + "." + StartEpisode->mEpisodeMap; section.ToUpper(); diff --git a/src/gamedata/textures/anim_switches.cpp b/src/gamedata/textures/anim_switches.cpp index 3fd04c658c1..a899af2d0ea 100644 --- a/src/gamedata/textures/anim_switches.cpp +++ b/src/gamedata/textures/anim_switches.cpp @@ -64,7 +64,7 @@ void FTextureManager::InitSwitchList () if (lump != -1) { - FMemLump lumpdata = fileSystem.ReadLump (lump); + FileData lumpdata = fileSystem.ReadLump (lump); const char *alphSwitchList = (const char *)lumpdata.GetMem(); const char *list_p; FSwitchDef *def1, *def2; diff --git a/src/gamedata/textures/animations.cpp b/src/gamedata/textures/animations.cpp index 6191c802f08..477a5c4baf8 100644 --- a/src/gamedata/textures/animations.cpp +++ b/src/gamedata/textures/animations.cpp @@ -182,8 +182,8 @@ void FTextureManager::InitAnimated (void) int lumpnum = fileSystem.CheckNumForName ("ANIMATED"); if (lumpnum != -1) { - FMemLump animatedlump = fileSystem.ReadLump (lumpnum); - int animatedlen = fileSystem.LumpLength(lumpnum); + FileData animatedlump = fileSystem.ReadLump (lumpnum); + int animatedlen = fileSystem.FileLength(lumpnum); const uint8_t *animdefs = (const uint8_t *)animatedlump.GetMem(); const uint8_t *anim_p; FTextureID pic1, pic2; diff --git a/src/gamedata/textures/formats/automaptexture.cpp b/src/gamedata/textures/formats/automaptexture.cpp index e68de73d7cd..fbb46ed896b 100644 --- a/src/gamedata/textures/formats/automaptexture.cpp +++ b/src/gamedata/textures/formats/automaptexture.cpp @@ -81,7 +81,7 @@ FAutomapTexture::FAutomapTexture (int lumpnum) : FImageSource(lumpnum) { Width = 320; - Height = uint16_t(fileSystem.LumpLength(lumpnum) / 320); + Height = uint16_t(fileSystem.FileLength(lumpnum) / 320); bUseGamePalette = true; } @@ -94,7 +94,7 @@ FAutomapTexture::FAutomapTexture (int lumpnum) TArray FAutomapTexture::CreatePalettedPixels(int conversion) { int x, y; - FMemLump data = fileSystem.ReadLump (SourceLump); + FileData data = fileSystem.ReadLump (SourceLump); const uint8_t *indata = (const uint8_t *)data.GetMem(); TArray Pixels(Width * Height, true); diff --git a/src/gamedata/textures/formats/buildtexture.cpp b/src/gamedata/textures/formats/buildtexture.cpp index 4ca84499d48..4de856681c9 100644 --- a/src/gamedata/textures/formats/buildtexture.cpp +++ b/src/gamedata/textures/formats/buildtexture.cpp @@ -238,12 +238,12 @@ static int CountTiles (const void *tiles) static int BuildPaletteTranslation(int lump) { - if (fileSystem.LumpLength(lump) < 768) + if (fileSystem.FileLength(lump) < 768) { return false; } - FMemLump data = fileSystem.ReadLump(lump); + FileData data = fileSystem.ReadLump(lump); const uint8_t *ipal = (const uint8_t *)data.GetMem(); FRemapTable opal; @@ -316,7 +316,7 @@ void FTextureManager::InitBuildTiles() if (fileSystem.CheckNumForFullName(name) != i) continue; // This palette is hidden by a later one. Do not process FString base = ExtractFileBase(name, true); base.ToLower(); - if (base.Compare("palette.dat") == 0 && fileSystem.LumpLength(i) >= 768) // must be a valid palette, i.e. at least 256 colors. + if (base.Compare("palette.dat") == 0 && fileSystem.FileLength(i) >= 768) // must be a valid palette, i.e. at least 256 colors. { FString path = ExtractFilePath(name); if (path.IsNotEmpty() && path.Back() != '/') path += '/'; @@ -336,7 +336,7 @@ void FTextureManager::InitBuildTiles() BuildTileData.Reserve(1); auto &artdata = BuildTileData.Last(); - artdata.Resize(fileSystem.LumpLength(lumpnum)); + artdata.Resize(fileSystem.FileLength(lumpnum)); fileSystem.ReadLump(lumpnum, &artdata[0]); if ((numtiles = CountTiles(&artdata[0])) > 0) diff --git a/src/gamedata/textures/formats/flattexture.cpp b/src/gamedata/textures/formats/flattexture.cpp index d081a7603a9..5eb3e077ec7 100644 --- a/src/gamedata/textures/formats/flattexture.cpp +++ b/src/gamedata/textures/formats/flattexture.cpp @@ -79,7 +79,7 @@ FFlatTexture::FFlatTexture (int lumpnum) int area; int bits; - area = fileSystem.LumpLength (lumpnum); + area = fileSystem.FileLength (lumpnum); switch (area) { diff --git a/src/gamedata/textures/formats/imgztexture.cpp b/src/gamedata/textures/formats/imgztexture.cpp index bc1985354e8..c9c11681592 100644 --- a/src/gamedata/textures/formats/imgztexture.cpp +++ b/src/gamedata/textures/formats/imgztexture.cpp @@ -122,7 +122,7 @@ FIMGZTexture::FIMGZTexture (int lumpnum, uint16_t w, uint16_t h, int16_t l, int1 TArray FIMGZTexture::CreatePalettedPixels(int conversion) { - FMemLump lump = fileSystem.ReadLump (SourceLump); + FileData lump = fileSystem.ReadLump (SourceLump); const ImageHeader *imgz = (const ImageHeader *)lump.GetMem(); const uint8_t *data = (const uint8_t *)&imgz[1]; diff --git a/src/gamedata/textures/formats/patchtexture.cpp b/src/gamedata/textures/formats/patchtexture.cpp index 2b46e333863..6b1d83b7b2f 100644 --- a/src/gamedata/textures/formats/patchtexture.cpp +++ b/src/gamedata/textures/formats/patchtexture.cpp @@ -170,10 +170,10 @@ TArray FPatchTexture::CreatePalettedPixels(int conversion) const column_t *maxcol; int x; - FMemLump lump = fileSystem.ReadLump (SourceLump); + FileData lump = fileSystem.ReadLump (SourceLump); const patch_t *patch = (const patch_t *)lump.GetMem(); - maxcol = (const column_t *)((const uint8_t *)patch + fileSystem.LumpLength (SourceLump) - 3); + maxcol = (const column_t *)((const uint8_t *)patch + fileSystem.FileLength (SourceLump) - 3); remap = ImageHelpers::GetRemap(conversion == luminance, isalpha); // Special case for skies @@ -275,12 +275,12 @@ int FPatchTexture::CopyPixels(FBitmap *bmp, int conversion) void FPatchTexture::DetectBadPatches () { // The patch must look like it is large enough for the rules to apply to avoid using this on truly empty patches. - if (fileSystem.LumpLength(SourceLump) < Width * Height / 2) return; + if (fileSystem.FileLength(SourceLump) < Width * Height / 2) return; // Check if this patch is likely to be a problem. // It must be 256 pixels tall, and all its columns must have exactly // one post, where each post has a supposed length of 0. - FMemLump lump = fileSystem.ReadLump (SourceLump); + FileData lump = fileSystem.ReadLump (SourceLump); const patch_t *realpatch = (patch_t *)lump.GetMem(); const uint32_t *cofs = realpatch->columnofs; int x, x2 = LittleShort(realpatch->width); diff --git a/src/gamedata/textures/formats/rawpagetexture.cpp b/src/gamedata/textures/formats/rawpagetexture.cpp index 0f2f6641910..449b52a0c39 100644 --- a/src/gamedata/textures/formats/rawpagetexture.cpp +++ b/src/gamedata/textures/formats/rawpagetexture.cpp @@ -162,7 +162,7 @@ FRawPageTexture::FRawPageTexture (int lumpnum) if (Name.CompareNoCase("E2END") == 0 && gameinfo.gametype == GAME_Heretic) { mPaletteLump = fileSystem.CheckNumForName("E2PAL"); - if (fileSystem.LumpLength(mPaletteLump) < 768) mPaletteLump = -1; + if (fileSystem.FileLength(mPaletteLump) < 768) mPaletteLump = -1; } else bUseGamePalette = true; } @@ -175,7 +175,7 @@ FRawPageTexture::FRawPageTexture (int lumpnum) TArray FRawPageTexture::CreatePalettedPixels(int conversion) { - FMemLump lump = fileSystem.ReadLump (SourceLump); + FileData lump = fileSystem.ReadLump (SourceLump); const uint8_t *source = (const uint8_t *)lump.GetMem(); const uint8_t *source_p = source; uint8_t *dest_p; @@ -207,8 +207,8 @@ int FRawPageTexture::CopyPixels(FBitmap *bmp, int conversion) if (mPaletteLump < 0) return FImageSource::CopyPixels(bmp, conversion); else { - FMemLump lump = fileSystem.ReadLump(SourceLump); - FMemLump plump = fileSystem.ReadLump(mPaletteLump); + FileData lump = fileSystem.ReadLump(SourceLump); + FileData plump = fileSystem.ReadLump(mPaletteLump); const uint8_t *source = (const uint8_t *)lump.GetMem(); const uint8_t *psource = (const uint8_t *)plump.GetMem(); PalEntry paldata[256]; diff --git a/src/gamedata/textures/multipatchtexturebuilder.cpp b/src/gamedata/textures/multipatchtexturebuilder.cpp index 22eeda4b827..48a76a2b0c6 100644 --- a/src/gamedata/textures/multipatchtexturebuilder.cpp +++ b/src/gamedata/textures/multipatchtexturebuilder.cpp @@ -294,7 +294,7 @@ void FMultipatchTextureBuilder::AddTexturesLump(const void *lumpdata, int lumpsi } // Check whether the amount of names reported is correct. - int lumplength = fileSystem.LumpLength(patcheslump); + int lumplength = fileSystem.FileLength(patcheslump); if (numpatches > uint32_t((lumplength - 4) / 8)) { Printf("PNAMES lump is shorter than required (%u entries reported but only %d bytes (%d entries) long\n", @@ -406,13 +406,13 @@ void FMultipatchTextureBuilder::AddTexturesLumps(int lump1, int lump2, int patch if (lump1 >= 0) { - FMemLump texdir = fileSystem.ReadLump(lump1); - AddTexturesLump(texdir.GetMem(), fileSystem.LumpLength(lump1), lump1, patcheslump, firstdup, true); + FileData texdir = fileSystem.ReadLump(lump1); + AddTexturesLump(texdir.GetMem(), fileSystem.FileLength(lump1), lump1, patcheslump, firstdup, true); } if (lump2 >= 0) { - FMemLump texdir = fileSystem.ReadLump(lump2); - AddTexturesLump(texdir.GetMem(), fileSystem.LumpLength(lump2), lump2, patcheslump, firstdup, false); + FileData texdir = fileSystem.ReadLump(lump2); + AddTexturesLump(texdir.GetMem(), fileSystem.FileLength(lump2), lump2, patcheslump, firstdup, false); } } diff --git a/src/gamedata/textures/texturemanager.cpp b/src/gamedata/textures/texturemanager.cpp index 27b3d3f77c6..0109108982b 100644 --- a/src/gamedata/textures/texturemanager.cpp +++ b/src/gamedata/textures/texturemanager.cpp @@ -607,7 +607,7 @@ void FTextureManager::AddGroup(int wadnum, int ns, ETextureType usetype) } StartScreen->Progress(); } - else if (ns == ns_flats && fileSystem.GetLumpFlags(firsttx) & LUMPF_MAYBEFLAT) + else if (ns == ns_flats && fileSystem.GetFileFlags(firsttx) & LUMPF_MAYBEFLAT) { if (fileSystem.CheckNumForName (Name, ns) < firsttx) { @@ -963,7 +963,7 @@ void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &b if (ns == ns_global) { // In Zips all graphics must be in a separate namespace. - if (fileSystem.GetLumpFlags(i) & LUMPF_FULLPATH) continue; + if (fileSystem.GetFileFlags(i) & LUMPF_FULLPATH) continue; // Ignore lumps with empty names. if (fileSystem.CheckLumpName(i, "")) continue; @@ -1366,7 +1366,7 @@ int FTextureManager::GuesstimateNumTextures () break; default: - if (fileSystem.GetLumpFlags(i) & LUMPF_MAYBEFLAT) numtex++; + if (fileSystem.GetFileFlags(i) & LUMPF_MAYBEFLAT) numtex++; break; } @@ -1547,7 +1547,7 @@ void FTextureManager::GenerateGlobalBrightmapFromColormap() int lump = fileSystem.CheckNumForName("COLORMAP"); if (lump == -1) lump = fileSystem.CheckNumForName("COLORMAP", ns_colormaps); if (lump == -1) return; - FMemLump cmap = fileSystem.ReadLump(lump); + FileData cmap = fileSystem.ReadLump(lump); uint8_t palbuffer[768]; ReadPalette(fileSystem.GetNumForName("PLAYPAL"), palbuffer); diff --git a/src/gamedata/w_wad.cpp b/src/gamedata/w_wad.cpp index 9edfa4107d0..9d04c916835 100644 --- a/src/gamedata/w_wad.cpp +++ b/src/gamedata/w_wad.cpp @@ -1,9 +1,9 @@ /* -** w_wad.cpp +** filesystem.cpp ** **--------------------------------------------------------------------------- ** Copyright 1998-2009 Randy Heit -** Copyright 2005-2009 Christoph Oelckers +** Copyright 2005-2020 Christoph Oelckers ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -51,24 +51,11 @@ #include "resourcefiles/resourcefile.h" #include "md5.h" #include "doomstat.h" -#include "vm.h" // MACROS ------------------------------------------------------------------ #define NULL_INDEX (0xffffffff) -// -// WADFILE I/O related stuff. -// - -union LumpShortName -{ - char String[9]; - - uint32_t dword; // These are for accessing the first 4 or 8 chars of - uint64_t qword; // Name as a unit without breaking strict aliasing rules -}; - struct FileSystem::LumpRecord { @@ -172,9 +159,6 @@ struct FileSystem::LumpRecord } }; -// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- -extern bool nospriterename; - // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -185,44 +169,11 @@ static void PrintLastError (); FileSystem fileSystem; -// PRIVATE DATA DEFINITIONS ------------------------------------------------ - // CODE -------------------------------------------------------------------- -void md5Update(FileReader& file, MD5Context &md5, unsigned len) -{ - uint8_t readbuf[8192]; - unsigned t; - - while (len > 0) - { - t = std::min(len, sizeof(readbuf)); - len -= t; - t = (long)file.Read(readbuf, t); - md5.Update(readbuf, t); - } -} - - -//========================================================================== -// -// uppercoppy -// -// [RH] Copy up to 8 chars, upper-casing them in the process -//========================================================================== - -void uppercopy (char *to, const char *from) -{ - int i; - - for (i = 0; i < 8 && from[i]; i++) - to[i] = toupper (from[i]); - for (; i < 8; i++) - to[i] = 0; -} - -FileSystem::FileSystem () +FileSystem::FileSystem() { + // This is needed to initialize the LumpRecord array, which depends on data only available here. } FileSystem::~FileSystem () @@ -232,11 +183,15 @@ FileSystem::~FileSystem () void FileSystem::DeleteAll () { - LumpInfo.Clear(); - NumLumps = 0; + Hashes.Clear(); + NumEntries = 0; - // we must count backward to ensure that embedded WADs are deleted before - // the ones that contain their data. + // explicitly delete all manually added lumps. + for (auto &frec : FileInfo) + { + if (frec.wadnum == -1) delete frec.lump; + } + FileInfo.Clear(); for (int i = Files.Size() - 1; i >= 0; --i) { delete Files[i]; @@ -246,7 +201,7 @@ void FileSystem::DeleteAll () //========================================================================== // -// W_InitMultipleFiles +// 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 @@ -258,12 +213,11 @@ void FileSystem::DeleteAll () void FileSystem::InitSingleFile(const char* filename, bool quiet) { TArray filenames; - TArray deletes; filenames.Push(filename); - InitMultipleFiles(filenames, deletes, true); + InitMultipleFiles(filenames, true); } -void FileSystem::InitMultipleFiles (TArray &filenames, const TArray &deletelumps, bool quiet, LumpFilterInfo* filter) +void FileSystem::InitMultipleFiles (TArray &filenames, bool quiet, LumpFilterInfo* filter) { int numfiles; @@ -273,7 +227,7 @@ void FileSystem::InitMultipleFiles (TArray &filenames, const TArray &filenames, const TArraypostprocessFunc) filter->postprocessFunc(); // [RH] Set up hash table - Hashes.Resize(6 * NumLumps); - FirstLumpIndex = &Hashes[0]; - NextLumpIndex = &Hashes[NumLumps]; - FirstLumpIndex_FullName = &Hashes[NumLumps*2]; - NextLumpIndex_FullName = &Hashes[NumLumps*3]; - FirstLumpIndex_NoExt = &Hashes[NumLumps*4]; - NextLumpIndex_NoExt = &Hashes[NumLumps*5]; InitHashChains (); - LumpInfo.ShrinkToFit(); - Files.ShrinkToFit(); +} + +//========================================================================== +// +// AddLump +// +// Adds a given lump to the directory. Does not perform rehashing +// +//========================================================================== + +void FileSystem::AddLump(FResourceLump *lump) +{ + FileSystem::LumpRecord *lumprec = &FileInfo[FileInfo.Reserve(1)]; + lumprec->SetFromLump(-1, lump); } //----------------------------------------------------------------------- @@ -315,15 +272,31 @@ void FileSystem::InitMultipleFiles (TArray &filenames, const TArraySetFromLump(-1, lump); - return LumpInfo.Size()-1; // later + AddLump(lump); + return FileInfo.Size() - 1; // later } //========================================================================== // -// W_AddFile +// AddFromBuffer +// +// Adds an in-memory resource to the virtual directory +// +//========================================================================== + +int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags) +{ + FStringf fullname("%s.%s", name, type); + auto newlump = new FMemoryLump(data, size); + newlump->LumpNameSetup(fullname); + AddLump(newlump); + FileInfo.Last().resourceId = id; + return FileInfo.Size()-1; +} + +//========================================================================== +// +// 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. @@ -331,13 +304,13 @@ int FileSystem::AddExternalFile(const char *filename) // [RH] Removed reload hack //========================================================================== -void FileSystem::AddFile (const char *filename, FileReader *wadr, bool quiet, LumpFilterInfo* filter) +void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, LumpFilterInfo* filter) { int startlump; bool isdir = false; - FileReader wadreader; + FileReader filereader; - if (wadr == nullptr) + if (filer == nullptr) { // Does this exist? If so, is it a directory? if (!DirEntryExists(filename, &isdir)) @@ -352,7 +325,7 @@ void FileSystem::AddFile (const char *filename, FileReader *wadr, bool quiet, Lu if (!isdir) { - if (!wadreader.OpenFile(filename)) + if (!filereader.OpenFile(filename)) { // Didn't find file if (!quiet) { @@ -363,15 +336,15 @@ void FileSystem::AddFile (const char *filename, FileReader *wadr, bool quiet, Lu } } } - else wadreader = std::move(*wadr); + else filereader = std::move(*filer); if (!batchrun && !quiet) Printf (" adding %s", filename); - startlump = NumLumps; + startlump = NumEntries; FResourceFile *resfile; if (!isdir) - resfile = FResourceFile::OpenResourceFile(filename, wadreader, quiet, false, filter); + resfile = FResourceFile::OpenResourceFile(filename, filereader, quiet, false, filter); else resfile = FResourceFile::OpenDirectory(filename, quiet, filter); @@ -379,13 +352,13 @@ void FileSystem::AddFile (const char *filename, FileReader *wadr, bool quiet, Lu { if (!quiet && !batchrun) Printf(", %d lumps\n", resfile->LumpCount()); - uint32_t lumpstart = LumpInfo.Size(); + uint32_t lumpstart = FileInfo.Size(); resfile->SetFirstLump(lumpstart); for (uint32_t i=0; i < resfile->LumpCount(); i++) { FResourceLump *lump = resfile->GetLump(i); - FileSystem::LumpRecord *lump_p = &LumpInfo[LumpInfo.Reserve(1)]; + FileSystem::LumpRecord *lump_p = &FileInfo[FileInfo.Reserve(1)]; lump_p->SetFromLump(Files.Size(), lump); } @@ -409,11 +382,11 @@ void FileSystem::AddFile (const char *filename, FileReader *wadr, bool quiet, Lu char cksumout[33]; memset(cksumout, 0, sizeof(cksumout)); - if (wadreader.isOpen()) + if (filereader.isOpen()) { MD5Context md5; - wadreader.Seek(0, FileReader::SeekSet); - md5Update(wadreader, md5, (unsigned)wadreader.GetLength()); + filereader.Seek(0, FileReader::SeekSet); + md5Update(filereader, md5, (unsigned)filereader.GetLength()); md5.Final(cksum); for (size_t j = 0; j < sizeof(cksum); ++j) @@ -421,7 +394,7 @@ void FileSystem::AddFile (const char *filename, FileReader *wadr, bool quiet, Lu sprintf(cksumout + (j * 2), "%02X", cksum[j]); } - fprintf(hashfile, "file: %s, hash: %s, size: %d\n", filename, cksumout, (int)wadreader.GetLength()); + fprintf(hashfile, "file: %s, hash: %s, size: %d\n", filename, cksumout, (int)filereader.GetLength()); } else @@ -453,16 +426,16 @@ void FileSystem::AddFile (const char *filename, FileReader *wadr, bool quiet, Lu //========================================================================== // -// W_CheckIfWadLoaded +// CheckIfResourceFileLoaded // -// Returns true if the specified wad is loaded, false otherwise. -// If a fully-qualified path is specified, then the wad must match exactly. -// Otherwise, any wad with that name will work, whatever its path. -// Returns the wads index if found, or -1 if not. +// Returns true if the specified file is loaded, false otherwise. +// If a fully-qualified path is specified, then the file must match exactly. +// Otherwise, any file with that name will work, whatever its path. +// Returns the file's index if found, or -1 if not. // //========================================================================== -int FileSystem::CheckIfWadLoaded (const char *name) +int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept { unsigned int i; @@ -470,7 +443,7 @@ int FileSystem::CheckIfWadLoaded (const char *name) { for (i = 0; i < Files.Size(); ++i) { - if (stricmp (GetWadFullName (i), name) == 0) + if (stricmp (GetResourceFileFullName (i), name) == 0) { return i; } @@ -480,7 +453,8 @@ int FileSystem::CheckIfWadLoaded (const char *name) { for (i = 0; i < Files.Size(); ++i) { - if (stricmp (GetWadName (i), name) == 0) + auto pth = ExtractFileBase(GetResourceFileName(i), true); + if (stricmp (pth.GetChars(), name) == 0) { return i; } @@ -491,19 +465,7 @@ int FileSystem::CheckIfWadLoaded (const char *name) //========================================================================== // -// W_NumLumps -// -//========================================================================== - -DEFINE_ACTION_FUNCTION(_Wads, GetNumLumps) -{ - PARAM_PROLOGUE; - ACTION_RETURN_INT(fileSystem.GetNumLumps()); -} - -//========================================================================== -// -// W_CheckNumForName +// CheckNumForName // // Returns -1 if name not found. The version with a third parameter will // look exclusively in the specified wad for the lump. @@ -534,14 +496,14 @@ int FileSystem::CheckNumForName (const char *name, int space) } uppercopy (uname, name); - i = FirstLumpIndex[LumpNameHash (uname) % NumLumps]; + i = FirstLumpIndex[LumpNameHash (uname) % NumEntries]; while (i != NULL_INDEX) { - if (LumpInfo[i].shortName.qword == qname) + if (FileInfo[i].shortName.qword == qname) { - auto &lump = LumpInfo[i]; + auto &lump = FileInfo[i]; if (lump.Namespace == space) break; // If the lump is from one of the special namespaces exclusive to Zips // the check has to be done differently: @@ -572,14 +534,14 @@ int FileSystem::CheckNumForName (const char *name, int space, int wadnum, bool e } uppercopy (uname, name); - i = FirstLumpIndex[LumpNameHash (uname) % NumLumps]; + i = FirstLumpIndex[LumpNameHash (uname) % NumEntries]; // If exact is true if will only find lumps in the same WAD, otherwise // also those in earlier WADs. while (i != NULL_INDEX && - (LumpInfo[i].shortName.qword != qname || LumpInfo[i].Namespace != space || - (exact? (LumpInfo[i].wadnum != wadnum) : (LumpInfo[i].wadnum > wadnum)) )) + (FileInfo[i].shortName.qword != qname || FileInfo[i].Namespace != space || + (exact? (FileInfo[i].wadnum != wadnum) : (FileInfo[i].wadnum > wadnum)) )) { i = NextLumpIndex[i]; } @@ -587,20 +549,11 @@ int FileSystem::CheckNumForName (const char *name, int space, int wadnum, bool e return i != NULL_INDEX ? i : -1; } -DEFINE_ACTION_FUNCTION(_Wads, CheckNumForName) -{ - PARAM_PROLOGUE; - PARAM_STRING(name); - PARAM_INT(ns); - PARAM_INT(wadnum); - PARAM_BOOL(exact); - ACTION_RETURN_INT(fileSystem.CheckNumForName(name, ns, wadnum, exact)); -} //========================================================================== // -// W_GetNumForName +// GetNumForName // -// Calls W_CheckNumForName, but bombs out if not found. +// Calls CheckNumForName, but bombs out if not found. // //========================================================================== @@ -619,7 +572,7 @@ int FileSystem::GetNumForName (const char *name, int space) //========================================================================== // -// W_CheckNumForFullName +// CheckNumForFullName // // Same as above but looks for a fully qualified name from a .zip // These don't care about namespaces though because those are part @@ -635,18 +588,19 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names { return -1; } + if (*name == '/') name++; // ignore leading slashes in file names. uint32_t *fli = ignoreext ? FirstLumpIndex_NoExt : FirstLumpIndex_FullName; uint32_t *nli = ignoreext ? NextLumpIndex_NoExt : NextLumpIndex_FullName; auto len = strlen(name); - for (i = fli[MakeKey(name) % NumLumps]; i != NULL_INDEX; i = nli[i]) + for (i = fli[MakeKey(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) { - if (strnicmp(name, LumpInfo[i].longName, len)) continue; - if (LumpInfo[i].longName[len] == 0) break; // this is a full match - if (ignoreext && LumpInfo[i].longName[len] == '.') + if (strnicmp(name, FileInfo[i].longName, len)) continue; + if (FileInfo[i].longName[len] == 0) break; // this is a full match + if (ignoreext && FileInfo[i].longName[len] == '.') { // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? - if (strpbrk(LumpInfo[i].longName.GetChars() + len + 1, "./") == nullptr) break; + if (strpbrk(FileInfo[i].longName.GetChars() + len + 1, "./") == nullptr) break; } } @@ -659,13 +613,6 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names return -1; } -DEFINE_ACTION_FUNCTION(_Wads, CheckNumForFullName) -{ - PARAM_PROLOGUE; - PARAM_STRING(name); - ACTION_RETURN_INT(fileSystem.CheckNumForFullName(name)); -} - int FileSystem::CheckNumForFullName (const char *name, int wadnum) { uint32_t i; @@ -675,10 +622,10 @@ int FileSystem::CheckNumForFullName (const char *name, int wadnum) return CheckNumForFullName (name); } - i = FirstLumpIndex_FullName[MakeKey (name) % NumLumps]; + i = FirstLumpIndex_FullName[MakeKey (name) % NumEntries]; while (i != NULL_INDEX && - (stricmp(name, LumpInfo[i].longName) || LumpInfo[i].wadnum != wadnum)) + (stricmp(name, FileInfo[i].longName) || FileInfo[i].wadnum != wadnum)) { i = NextLumpIndex_FullName[i]; } @@ -688,9 +635,9 @@ int FileSystem::CheckNumForFullName (const char *name, int wadnum) //========================================================================== // -// W_GetNumForFullName +// GetNumForFullName // -// Calls W_CheckNumForFullName, but bombs out if not found. +// Calls CheckNumForFullName, but bombs out if not found. // //========================================================================== @@ -706,6 +653,98 @@ int FileSystem::GetNumForFullName (const char *name) return i; } +//========================================================================== +// +// FindFile +// +// Looks up a file by name, either eith or without path and extension +// +//========================================================================== + +int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts, int count) +{ + uint32_t i; + + if (name == NULL) + { + return -1; + } + if (*name == '/') name++; // ignore leading slashes in file names. + uint32_t* fli = FirstLumpIndex_NoExt; + uint32_t* nli = NextLumpIndex_NoExt; + auto len = strlen(name); + + for (i = fli[MakeKey(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) + { + if (strnicmp(name, FileInfo[i].longName, len)) continue; + if (FileInfo[i].longName[len] != '.') continue; // we are looking for extensions but this file doesn't have one. + + auto cp = FileInfo[i].longName.GetChars() + len + 1; + // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? + if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry. + + for (int j = 0; j < count; j++) + { + if (!stricmp(cp, exts[j])) return i; // found a match + } + } + return -1; +} + +//========================================================================== +// +// FindResource +// +// Looks for content based on Blood resource IDs. +// +//========================================================================== + +int FileSystem::FindResource (int resid, const char *type, int filenum) const noexcept +{ + uint32_t i; + + if (type == NULL) + { + return -1; + } + FName lname(type, true); + if (lname == NAME_None) return -1; + + uint32_t* fli = FirstLumpIndex_ResId; + uint32_t* nli = NextLumpIndex_ResId; + + for (i = fli[resid % NumEntries]; i != NULL_INDEX; i = nli[i]) + { + if (filenum > 0 && FileInfo[i].wadnum != filenum) continue; + if (FileInfo[i].resourceId != resid) continue; + auto extp = strrchr(FileInfo[i].longName, '.'); + if (!extp) continue; + if (!stricmp(extp + 1, type)) return i; + } + return -1; +} + +//========================================================================== +// +// GetResource +// +// Calls GetResource, but bombs out if not found. +// +//========================================================================== + +int FileSystem::GetResource (int resid, const char *type, int filenum) const +{ + int i; + + i = FindResource (resid, type, filenum); + + if (i == -1) + { + I_Error("GetResource: %d of type %s not found!", resid, type); + } + return i; +} + //========================================================================== // // link a texture with a given lump @@ -714,9 +753,9 @@ int FileSystem::GetNumForFullName (const char *name) void FileSystem::SetLinkedTexture(int lump, FTexture *tex) { - if ((size_t)lump < NumLumps) + if ((size_t)lump < NumEntries) { - LumpInfo[lump].linkedTexture = tex; + FileInfo[lump].linkedTexture = tex; } } @@ -728,69 +767,67 @@ void FileSystem::SetLinkedTexture(int lump, FTexture *tex) FTexture *FileSystem::GetLinkedTexture(int lump) { - if ((size_t)lump < NumLumps) + if ((size_t)lump < NumEntries) { - return LumpInfo[lump].linkedTexture; + return FileInfo[lump].linkedTexture; } return NULL; } //========================================================================== // -// W_LumpLength +// FileLength // // Returns the buffer size needed to load the given lump. // //========================================================================== -int FileSystem::LumpLength (int lump) const +int FileSystem::FileLength (int lump) const { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) { - I_Error ("W_LumpLength: %i >= NumLumps",lump); + return -1; } - - return LumpInfo[lump].lump->LumpSize; + return FileInfo[lump].lump->LumpSize; } //========================================================================== // -// GetLumpOffset +// GetFileOffset // // Returns the offset from the beginning of the file to the lump. // Returns -1 if the lump is compressed or can't be read directly // //========================================================================== -int FileSystem::GetLumpOffset (int lump) +int FileSystem::GetFileOffset (int lump) { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) { - I_Error ("GetLumpOffset: %i >= NumLumps",lump); + return -1; } - - return LumpInfo[lump].lump->GetFileOffset(); + return FileInfo[lump].lump->GetFileOffset(); } //========================================================================== // -// GetLumpOffset +// // //========================================================================== -int FileSystem::GetLumpFlags (int lump) +int FileSystem::GetFileFlags (int lump) { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) { return 0; } - return LumpInfo[lump].lump->Flags; + return FileInfo[lump].lump->Flags; } //========================================================================== // -// W_LumpNameHash +// LumpNameHash // // NOTE: s should already be uppercase, in contrast to the BOOM version. // @@ -815,7 +852,7 @@ uint32_t FileSystem::LumpNameHash (const char *s) //========================================================================== // -// W_InitHashChains +// InitHashChains // // Prepares the lumpinfos for hashing. // (Hey! This looks suspiciously like something from Boom! :-) @@ -826,362 +863,63 @@ void FileSystem::InitHashChains (void) { unsigned int i, j; + Hashes.Resize(8 * NumEntries); // Mark all buckets as empty - memset (FirstLumpIndex, 255, NumLumps*sizeof(FirstLumpIndex[0])); - memset (NextLumpIndex, 255, NumLumps*sizeof(NextLumpIndex[0])); - memset (FirstLumpIndex_FullName, 255, NumLumps*sizeof(FirstLumpIndex_FullName[0])); - memset (NextLumpIndex_FullName, 255, NumLumps*sizeof(NextLumpIndex_FullName[0])); - memset(FirstLumpIndex_NoExt, 255, NumLumps * sizeof(FirstLumpIndex_NoExt[0])); - memset(NextLumpIndex_NoExt, 255, NumLumps * sizeof(NextLumpIndex_NoExt[0])); + memset(Hashes.Data(), -1, Hashes.Size() * sizeof(Hashes[0])); + FirstLumpIndex = &Hashes[0]; + NextLumpIndex = &Hashes[NumEntries]; + FirstLumpIndex_FullName = &Hashes[NumEntries * 2]; + NextLumpIndex_FullName = &Hashes[NumEntries * 3]; + FirstLumpIndex_NoExt = &Hashes[NumEntries * 4]; + NextLumpIndex_NoExt = &Hashes[NumEntries * 5]; + FirstLumpIndex_ResId = &Hashes[NumEntries * 6]; + NextLumpIndex_ResId = &Hashes[NumEntries * 7]; + // Now set up the chains - for (i = 0; i < (unsigned)NumLumps; i++) + for (i = 0; i < (unsigned)NumEntries; i++) { - j = LumpNameHash (LumpInfo[i].shortName.String) % NumLumps; + j = LumpNameHash (FileInfo[i].shortName.String) % NumEntries; NextLumpIndex[i] = FirstLumpIndex[j]; FirstLumpIndex[j] = i; // Do the same for the full paths - if (LumpInfo[i].longName.IsNotEmpty()) + if (FileInfo[i].longName.IsNotEmpty()) { - j = MakeKey(LumpInfo[i].longName) % NumLumps; + j = MakeKey(FileInfo[i].longName) % NumEntries; NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j]; FirstLumpIndex_FullName[j] = i; - FString nameNoExt = LumpInfo[i].longName; + FString nameNoExt = FileInfo[i].longName; auto dot = nameNoExt.LastIndexOf('.'); auto slash = nameNoExt.LastIndexOf('/'); if (dot > slash) nameNoExt.Truncate(dot); - j = MakeKey(nameNoExt) % NumLumps; + j = MakeKey(nameNoExt) % NumEntries; NextLumpIndex_NoExt[i] = FirstLumpIndex_NoExt[j]; FirstLumpIndex_NoExt[j] = i; - } - } -} + j = FileInfo[i].resourceId % NumEntries; + NextLumpIndex_ResId[i] = FirstLumpIndex_ResId[j]; + FirstLumpIndex_ResId[j] = i; -//========================================================================== -// -// RenameSprites -// -// Renames sprites in IWADs so that unique actors can have unique sprites, -// making it possible to import any actor from any game into any other -// game without jumping through hoops to resolve duplicate sprite names. -// You just need to know what the sprite's new name is. -// -//========================================================================== - -void FileSystem::RenameSprites (const TArray &deletelumps) -{ - bool renameAll; - bool MNTRZfound = false; - const char *altbigfont = gameinfo.gametype == GAME_Strife? "SBIGFONT" : (gameinfo.gametype & GAME_Raven)? "HBIGFONT" : "DBIGFONT"; - - static const uint32_t HereticRenames[] = - { MAKE_ID('H','E','A','D'), MAKE_ID('L','I','C','H'), // Ironlich - }; - - static const uint32_t HexenRenames[] = - { MAKE_ID('B','A','R','L'), MAKE_ID('Z','B','A','R'), // ZBarrel - MAKE_ID('A','R','M','1'), MAKE_ID('A','R','_','1'), // MeshArmor - MAKE_ID('A','R','M','2'), MAKE_ID('A','R','_','2'), // FalconShield - MAKE_ID('A','R','M','3'), MAKE_ID('A','R','_','3'), // PlatinumHelm - MAKE_ID('A','R','M','4'), MAKE_ID('A','R','_','4'), // AmuletOfWarding - MAKE_ID('S','U','I','T'), MAKE_ID('Z','S','U','I'), // ZSuitOfArmor and ZArmorChunk - MAKE_ID('T','R','E','1'), MAKE_ID('Z','T','R','E'), // ZTree and ZTreeDead - MAKE_ID('T','R','E','2'), MAKE_ID('T','R','E','S'), // ZTreeSwamp150 - MAKE_ID('C','A','N','D'), MAKE_ID('B','C','A','N'), // ZBlueCandle - MAKE_ID('R','O','C','K'), MAKE_ID('R','O','K','K'), // rocks and dirt in a_debris.cpp - MAKE_ID('W','A','T','R'), MAKE_ID('H','W','A','T'), // Strife also has WATR - MAKE_ID('G','I','B','S'), MAKE_ID('P','O','L','5'), // RealGibs - MAKE_ID('E','G','G','M'), MAKE_ID('P','R','K','M'), // PorkFX - MAKE_ID('I','N','V','U'), MAKE_ID('D','E','F','N'), // Icon of the Defender - }; - - static const uint32_t StrifeRenames[] = - { MAKE_ID('M','I','S','L'), MAKE_ID('S','M','I','S'), // lots of places - MAKE_ID('A','R','M','1'), MAKE_ID('A','R','M','3'), // MetalArmor - MAKE_ID('A','R','M','2'), MAKE_ID('A','R','M','4'), // LeatherArmor - MAKE_ID('P','M','A','P'), MAKE_ID('S','M','A','P'), // StrifeMap - MAKE_ID('T','L','M','P'), MAKE_ID('T','E','C','H'), // TechLampSilver and TechLampBrass - MAKE_ID('T','R','E','1'), MAKE_ID('T','R','E','T'), // TreeStub - MAKE_ID('B','A','R','1'), MAKE_ID('B','A','R','C'), // BarricadeColumn - MAKE_ID('S','H','T','2'), MAKE_ID('M','P','U','F'), // MaulerPuff - MAKE_ID('B','A','R','L'), MAKE_ID('B','B','A','R'), // StrifeBurningBarrel - MAKE_ID('T','R','C','H'), MAKE_ID('T','R','H','L'), // SmallTorchLit - MAKE_ID('S','H','R','D'), MAKE_ID('S','H','A','R'), // glass shards - MAKE_ID('B','L','S','T'), MAKE_ID('M','A','U','L'), // Mauler - MAKE_ID('L','O','G','G'), MAKE_ID('L','O','G','W'), // StickInWater - MAKE_ID('V','A','S','E'), MAKE_ID('V','A','Z','E'), // Pot and Pitcher - MAKE_ID('C','N','D','L'), MAKE_ID('K','N','D','L'), // Candle - MAKE_ID('P','O','T','1'), MAKE_ID('M','P','O','T'), // MetalPot - MAKE_ID('S','P','I','D'), MAKE_ID('S','T','L','K'), // Stalker - }; - - const uint32_t *renames; - int numrenames; - - switch (gameinfo.gametype) - { - case GAME_Doom: - default: - // Doom's sprites don't get renamed. - renames = nullptr; - numrenames = 0; - break; - - case GAME_Heretic: - renames = HereticRenames; - numrenames = sizeof(HereticRenames)/8; - break; - - case GAME_Hexen: - renames = HexenRenames; - numrenames = sizeof(HexenRenames)/8; - break; - - case GAME_Strife: - renames = StrifeRenames; - numrenames = sizeof(StrifeRenames)/8; - break; - } - - - for (uint32_t i=0; i< LumpInfo.Size(); i++) - { - // check for full Minotaur animations. If this is not found - // some frames need to be renamed. - if (LumpInfo[i].Namespace == ns_sprites) - { - if (LumpInfo[i].shortName.dword == MAKE_ID('M', 'N', 'T', 'R') && LumpInfo[i].shortName.String[4] == 'Z' ) - { - MNTRZfound = true; - break; - } - } - } - - renameAll = !!Args->CheckParm ("-oldsprites") || nospriterename; - - for (uint32_t i = 0; i < LumpInfo.Size(); i++) - { - if (LumpInfo[i].Namespace == ns_sprites) - { - // Only sprites in the IWAD normally get renamed - if (renameAll || LumpInfo[i].wadnum == GetIwadNum()) - { - for (int j = 0; j < numrenames; ++j) - { - if (LumpInfo[i].shortName.dword == renames[j*2]) - { - LumpInfo[i].shortName.dword = renames[j*2+1]; - } - } - if (gameinfo.gametype == GAME_Hexen) - { - if (CheckLumpName(i, "ARTIINVU")) - { - LumpInfo[i].shortName.String[4] = 'D'; LumpInfo[i].shortName.String[5] = 'E'; - LumpInfo[i].shortName.String[6] = 'F'; LumpInfo[i].shortName.String[7] = 'N'; - } - } - } - - if (!MNTRZfound) - { - if (LumpInfo[i].shortName.dword == MAKE_ID('M', 'N', 'T', 'R')) - { - for (size_t fi : {4, 6}) - { - if (LumpInfo[i].shortName.String[fi] >= 'F' && LumpInfo[i].shortName.String[fi] <= 'K') - { - LumpInfo[i].shortName.String[fi] += 'U' - 'F'; - } - } - } - } - - // When not playing Doom rename all BLOD sprites to BLUD so that - // the same blood states can be used everywhere - if (!(gameinfo.gametype & GAME_DoomChex)) - { - if (LumpInfo[i].shortName.dword == MAKE_ID('B', 'L', 'O', 'D')) - { - LumpInfo[i].shortName.dword = MAKE_ID('B', 'L', 'U', 'D'); - } - } - } - else if (LumpInfo[i].Namespace == ns_global) - { - if (LumpInfo[i].wadnum >= GetIwadNum() && LumpInfo[i].wadnum <= GetMaxIwadNum() && deletelumps.Find(LumpInfo[i].shortName.String) < deletelumps.Size()) - { - LumpInfo[i].shortName.String[0] = 0; // Lump must be deleted from directory. - } - // Rename the game specific big font lumps so that the font manager does not have to do problematic special checks for them. - else if (!strcmp(LumpInfo[i].shortName.String, altbigfont)) - { - strcpy(LumpInfo[i].shortName.String, "BIGFONT"); - } - } - } -} - -//========================================================================== -// -// RenameNerve -// -// Renames map headers and map name pictures in nerve.wad so as to load it -// alongside Doom II and offer both episodes without causing conflicts. -// MD5 checksum for NERVE.WAD: 967d5ae23daf45196212ae1b605da3b0 (3,819,855) -// MD5 checksum for Unity version of NERVE.WAD: 4214c47651b63ee2257b1c2490a518c9 (3,821,966) -// -//========================================================================== -void FileSystem::RenameNerve () -{ - if (gameinfo.gametype != GAME_Doom) - return; - - const int numnerveversions = 2; - - bool found = false; - uint8_t cksum[16]; - static const uint8_t nerve[numnerveversions][16] = { - { 0x96, 0x7d, 0x5a, 0xe2, 0x3d, 0xaf, 0x45, 0x19, - 0x62, 0x12, 0xae, 0x1b, 0x60, 0x5d, 0xa3, 0xb0 }, - { 0x42, 0x14, 0xc4, 0x76, 0x51, 0xb6, 0x3e, 0xe2, - 0x25, 0x7b, 0x1c, 0x24, 0x90, 0xa5, 0x18, 0xc9 } - }; - size_t nervesize[numnerveversions] = { 3819855, 3821966 } ; // NERVE.WAD's file size - int w = GetIwadNum(); - while (++w < GetNumWads()) - { - auto fr = GetFileReader(w); - int isizecheck = -1; - if (fr == NULL) - { - continue; - } - for (int icheck = 0; icheck < numnerveversions; icheck++) - if (fr->GetLength() == (long)nervesize[icheck]) - isizecheck = icheck; - if (isizecheck == -1) - { - // Skip MD5 computation when there is a - // cheaper way to know this is not the file - continue; - } - fr->Seek(0, FileReader::SeekSet); - MD5Context md5; - md5Update(*fr, md5, (unsigned)fr->GetLength()); - md5.Final(cksum); - if (memcmp(nerve[isizecheck], cksum, 16) == 0) - { - found = true; - break; - } - } - - if (!found) - return; - - for (int i = GetFirstLump(w); i <= GetLastLump(w); i++) - { - // Only rename the maps from NERVE.WAD - assert(LumpInfo[i].wadnum == w); - if (LumpInfo[i].shortName.dword == MAKE_ID('C', 'W', 'I', 'L')) - { - LumpInfo[i].shortName.String[0] = 'N'; - } - else if (LumpInfo[i].shortName.dword == MAKE_ID('M', 'A', 'P', '0')) - { - LumpInfo[i].shortName.String[6] = LumpInfo[i].shortName.String[4]; - LumpInfo[i].shortName.String[5] = '0'; - LumpInfo[i].shortName.String[4] = 'L'; - LumpInfo[i].shortName.dword = MAKE_ID('L', 'E', 'V', 'E'); } } + FileInfo.ShrinkToFit(); + Files.ShrinkToFit(); } //========================================================================== // -// FixMacHexen -// -// Discard all extra lumps in Mac version of Hexen IWAD (demo or full) -// to avoid any issues caused by names of these lumps, including: -// * Wrong height of small font -// * Broken life bar of mage class +// may only be called before the hash chains are set up. // //========================================================================== -void FileSystem::FixMacHexen() +LumpShortName& FileSystem::GetShortName(int i) { - if (GAME_Hexen != gameinfo.gametype) - { - return; - } - - FileReader *reader = GetFileReader(GetIwadNum()); - auto iwadSize = reader->GetLength(); - - static const long DEMO_SIZE = 13596228; - static const long BETA_SIZE = 13749984; - static const long FULL_SIZE = 21078584; - - if ( DEMO_SIZE != iwadSize - && BETA_SIZE != iwadSize - && FULL_SIZE != iwadSize) - { - return; - } - - reader->Seek(0, FileReader::SeekSet); - - uint8_t checksum[16]; - MD5Context md5; - - md5Update(*reader, md5, (unsigned)iwadSize); - md5.Final(checksum); - - static const uint8_t HEXEN_DEMO_MD5[16] = - { - 0x92, 0x5f, 0x9f, 0x50, 0x00, 0xe1, 0x7d, 0xc8, - 0x4b, 0x0a, 0x6a, 0x3b, 0xed, 0x3a, 0x6f, 0x31 - }; - - static const uint8_t HEXEN_BETA_MD5[16] = - { - 0x2a, 0xf1, 0xb2, 0x7c, 0xd1, 0x1f, 0xb1, 0x59, - 0xe6, 0x08, 0x47, 0x2a, 0x1b, 0x53, 0xe4, 0x0e - }; - - static const uint8_t HEXEN_FULL_MD5[16] = - { - 0xb6, 0x81, 0x40, 0xa7, 0x96, 0xf6, 0xfd, 0x7f, - 0x3a, 0x5d, 0x32, 0x26, 0xa3, 0x2b, 0x93, 0xbe - }; - - const bool isBeta = 0 == memcmp(HEXEN_BETA_MD5, checksum, sizeof checksum); - - if ( !isBeta - && 0 != memcmp(HEXEN_DEMO_MD5, checksum, sizeof checksum) - && 0 != memcmp(HEXEN_FULL_MD5, checksum, sizeof checksum)) - { - return; - } - - static const int EXTRA_LUMPS = 299; - - // Hexen Beta is very similar to Demo but it has MAP41: Maze at the end of the WAD - // So keep this map if it's present but discard all extra lumps - - const int lastLump = GetLastLump(GetIwadNum()) - (isBeta ? 12 : 0); - assert(GetFirstLump(GetIwadNum()) + 299 < lastLump); - - for (int i = lastLump - EXTRA_LUMPS + 1; i <= lastLump; ++i) - { - LumpInfo[i].shortName.String[0] = '\0'; - } + if (Hashes.Size()) I_FatalError("Attempt to modify file system"); // This may ONLY be called in the RenameSprites callback. + if ((unsigned)i >= NumEntries) I_Error("GetShortName: Invalid index"); + return FileInfo[i].shortName; } //========================================================================== @@ -1202,18 +940,18 @@ static FResourceLump placeholderLump; void FileSystem::MoveLumpsInFolder(const char *path) { auto len = strlen(path); - auto wadnum = LumpInfo.Last().wadnum; + auto wadnum = FileInfo.Last().wadnum; unsigned i; - for (i = 0; i < LumpInfo.Size(); i++) + for (i = 0; i < FileInfo.Size(); i++) { - auto& li = LumpInfo[i]; + auto& li = FileInfo[i]; if (li.wadnum >= GetIwadNum()) break; if (li.longName.Left(len).CompareNoCase(path) == 0) { - LumpInfo.Push(li); + FileInfo.Push(li); li.lump = &placeholderLump; // Make the old entry point to something empty. We cannot delete the lump record here because it'd require adjustment of all indices in the list. - auto &ln = LumpInfo.Last(); + auto &ln = FileInfo.Last(); ln.lump->LumpNameSetup(ln.longName.Mid(len)); ln.SetFromLump(wadnum, ln.lump); } @@ -1241,32 +979,22 @@ int FileSystem::FindLump (const char *name, int *lastlump, bool anyns) uppercopy (name8, name); assert(lastlump != NULL && *lastlump >= 0); - lump_p = &LumpInfo[*lastlump]; - while (lump_p < &LumpInfo[NumLumps]) + lump_p = &FileInfo[*lastlump]; + while (lump_p < &FileInfo[NumEntries]) { if ((anyns || lump_p->Namespace == ns_global) && lump_p->shortName.qword == qname) { - int lump = int(lump_p - &LumpInfo[0]); + int lump = int(lump_p - &FileInfo[0]); *lastlump = lump + 1; return lump; } lump_p++; } - *lastlump = NumLumps; + *lastlump = NumEntries; return -1; } -DEFINE_ACTION_FUNCTION(_Wads, FindLump) -{ - PARAM_PROLOGUE; - PARAM_STRING(name); - PARAM_INT(startlump); - PARAM_INT(ns); - const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumLumps(); - ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLump(name, &startlump, 0 != ns) : -1); -} - //========================================================================== // // W_FindLumpMulti @@ -1281,8 +1009,8 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in LumpRecord *lump_p; assert(lastlump != NULL && *lastlump >= 0); - lump_p = &LumpInfo[*lastlump]; - while (lump_p < &LumpInfo[NumLumps]) + lump_p = &FileInfo[*lastlump]; + while (lump_p < &FileInfo[NumEntries]) { if (anyns || lump_p->Namespace == ns_global) { @@ -1291,7 +1019,7 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in { if (!strnicmp(*name, lump_p->shortName.String, 8)) { - int lump = int(lump_p - &LumpInfo[0]); + int lump = int(lump_p - &FileInfo[0]); *lastlump = lump + 1; if (nameindex != NULL) *nameindex = int(name - names); return lump; @@ -1301,7 +1029,7 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in lump_p++; } - *lastlump = NumLumps; + *lastlump = NumEntries; return -1; } @@ -1313,10 +1041,10 @@ int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, in bool FileSystem::CheckLumpName (int lump, const char *name) { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) return false; - return !strnicmp (LumpInfo[lump].shortName.String, name, 8); + return !strnicmp (FileInfo[lump].shortName.String, name, 8); } //========================================================================== @@ -1327,39 +1055,30 @@ bool FileSystem::CheckLumpName (int lump, const char *name) void FileSystem::GetLumpName (char *to, int lump) const { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) *to = 0; else - uppercopy (to, LumpInfo[lump].shortName.String); + uppercopy (to, FileInfo[lump].shortName.String); } const char* FileSystem::GetLumpName(int lump) const { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) return nullptr; else - return LumpInfo[lump].shortName.String; + return FileInfo[lump].shortName.String; } void FileSystem::GetLumpName(FString &to, int lump) const { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) to = FString(); else { - to = LumpInfo[lump].shortName.String; + to = FileInfo[lump].shortName.String; to.ToUpper(); } } -DEFINE_ACTION_FUNCTION(_Wads, GetLumpName) -{ - PARAM_PROLOGUE; - PARAM_INT(lump); - FString lumpname; - fileSystem.GetLumpName(lumpname, lump); - ACTION_RETURN_STRING(lumpname); -} - //========================================================================== // // FileSystem :: GetLumpFullName @@ -1370,22 +1089,15 @@ DEFINE_ACTION_FUNCTION(_Wads, GetLumpName) const char *FileSystem::GetLumpFullName (int lump, bool returnshort) const { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) return NULL; - else if (LumpInfo[lump].longName.IsNotEmpty()) - return LumpInfo[lump].longName; + else if (FileInfo[lump].longName.IsNotEmpty()) + return FileInfo[lump].longName; else if (returnshort) - return LumpInfo[lump].shortName.String; + return FileInfo[lump].shortName.String; else return nullptr; } -DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullName) -{ - PARAM_PROLOGUE; - PARAM_INT(lump); - ACTION_RETURN_STRING(fileSystem.GetLumpFullName(lump)); -} - //========================================================================== // // FileSystem :: GetLumpFullPath @@ -1398,9 +1110,9 @@ FString FileSystem::GetLumpFullPath(int lump) const { FString foo; - if ((size_t) lump < NumLumps) + if ((size_t) lump < NumEntries) { - foo << GetWadName(LumpInfo[lump].wadnum) << ':' << GetLumpFullName(lump); + foo << GetResourceFileName(FileInfo[lump].wadnum) << ':' << GetLumpFullName(lump); } return foo; } @@ -1413,17 +1125,10 @@ FString FileSystem::GetLumpFullPath(int lump) const int FileSystem::GetLumpNamespace (int lump) const { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) return ns_global; else - return LumpInfo[lump].Namespace; -} - -DEFINE_ACTION_FUNCTION(_Wads, GetLumpNamespace) -{ - PARAM_PROLOGUE; - PARAM_INT(lump); - ACTION_RETURN_INT(fileSystem.GetLumpNamespace(lump)); + return FileInfo[lump].Namespace; } //========================================================================== @@ -1438,10 +1143,10 @@ DEFINE_ACTION_FUNCTION(_Wads, GetLumpNamespace) int FileSystem::GetLumpIndexNum(int lump) const { - if ((size_t)lump >= NumLumps) + if ((size_t)lump >= NumEntries) return 0; else - return LumpInfo[lump].resourceId; + return FileInfo[lump].resourceId; } //========================================================================== @@ -1452,9 +1157,9 @@ int FileSystem::GetLumpIndexNum(int lump) const int FileSystem::GetLumpFile (int lump) const { - if ((size_t)lump >= LumpInfo.Size()) + if ((size_t)lump >= FileInfo.Size()) return -1; - return LumpInfo[lump].wadnum; + return FileInfo[lump].wadnum; } //========================================================================== @@ -1465,9 +1170,9 @@ int FileSystem::GetLumpFile (int lump) const FResourceLump *FileSystem::GetLumpRecord(int lump) const { - if ((size_t)lump >= LumpInfo.Size()) + if ((size_t)lump >= FileInfo.Size()) return nullptr; - return LumpInfo[lump].lump; + return FileInfo[lump].lump; } //========================================================================== @@ -1494,14 +1199,14 @@ unsigned FileSystem::GetLumpsInFolder(const char *inpath, TArray &r path.ToLower(); if (path[path.Len() - 1] != '/') path += '/'; result.Clear(); - for (unsigned i = 0; i < LumpInfo.Size(); i++) + for (unsigned i = 0; i < FileInfo.Size(); i++) { - if (LumpInfo[i].longName.IndexOf(path) == 0) + if (FileInfo[i].longName.IndexOf(path) == 0) { // Only if it hasn't been replaced. - if ((unsigned)fileSystem.CheckNumForFullName(LumpInfo[i].longName) == i) + if ((unsigned)fileSystem.CheckNumForFullName(FileInfo[i].longName) == i) { - result.Push({ LumpInfo[i].longName.GetChars(), i }); + result.Push({ FileInfo[i].longName.GetChars(), i }); } } } @@ -1580,17 +1285,9 @@ TArray FileSystem::ReadLumpIntoArray(int lump, int pad) // //========================================================================== -FMemLump FileSystem::ReadLump (int lump) -{ - return FMemLump(FString(ELumpNum(lump))); -} - -DEFINE_ACTION_FUNCTION(_Wads, ReadLump) +FileData FileSystem::ReadLump (int lump) { - PARAM_PROLOGUE; - PARAM_INT(lump); - const bool isLumpValid = lump >= 0 && lump < fileSystem.GetNumLumps(); - ACTION_RETURN_STRING(isLumpValid ? fileSystem.ReadLump(lump).GetString() : FString()); + return FileData(FString(ELumpNum(lump))); } //========================================================================== @@ -1604,12 +1301,12 @@ DEFINE_ACTION_FUNCTION(_Wads, ReadLump) FileReader FileSystem::OpenLumpReader(int lump) { - if ((unsigned)lump >= (unsigned)LumpInfo.Size()) + if ((unsigned)lump >= (unsigned)FileInfo.Size()) { - I_Error("W_OpenLumpNum: %u >= NumLumps", lump); + I_Error("W_OpenLumpNum: %u >= NumEntries", lump); } - auto rl = LumpInfo[lump].lump; + auto rl = FileInfo[lump].lump; auto rd = rl->GetReader(); if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !(rl->Flags & LUMPF_COMPRESSED)) @@ -1623,18 +1320,18 @@ FileReader FileSystem::OpenLumpReader(int lump) FileReader FileSystem::ReopenLumpReader(int lump, bool alwayscache) { - if ((unsigned)lump >= (unsigned)LumpInfo.Size()) + if ((unsigned)lump >= (unsigned)FileInfo.Size()) { - I_Error("ReopenLumpReader: %u >= NumLumps", lump); + I_Error("ReopenLumpReader: %u >= NumEntries", lump); } - auto rl = LumpInfo[lump].lump; + auto rl = FileInfo[lump].lump; auto rd = rl->GetReader(); if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !alwayscache && !(rl->Flags & LUMPF_COMPRESSED)) { int fileno = fileSystem.GetLumpFile(lump); - const char *filename = fileSystem.GetWadFullName(fileno); + const char *filename = fileSystem.GetResourceFileName(fileno); FileReader fr; if (fr.OpenFile(filename, rl->GetFileOffset(), rl->LumpSize)) { @@ -1671,7 +1368,7 @@ FileReader *FileSystem::GetFileReader(int wadnum) // //========================================================================== -const char *FileSystem::GetWadName (int wadnum) const +const char *FileSystem::GetResourceFileName (int wadnum) const noexcept { const char *name, *slash; @@ -1739,7 +1436,7 @@ int FileSystem::GetLumpCount (int wadnum) const // //========================================================================== -const char *FileSystem::GetWadFullName (int wadnum) const +const char *FileSystem::GetResourceFileFullName (int wadnum) const noexcept { if ((unsigned int)wadnum >= Files.Size()) { @@ -1750,29 +1447,29 @@ const char *FileSystem::GetWadFullName (int wadnum) const } -// FMemLump ----------------------------------------------------------------- +// FileData ----------------------------------------------------------------- -FMemLump::FMemLump () +FileData::FileData () { } -FMemLump::FMemLump (const FMemLump ©) +FileData::FileData (const FileData ©) { Block = copy.Block; } -FMemLump &FMemLump::operator = (const FMemLump ©) +FileData &FileData::operator = (const FileData ©) { Block = copy.Block; return *this; } -FMemLump::FMemLump (const FString &source) +FileData::FileData (const FString &source) : Block (source) { } -FMemLump::~FMemLump () +FileData::~FileData () { } diff --git a/src/gamedata/w_wad.h b/src/gamedata/w_wad.h index a64a9efd9ba..21f88d9a5d8 100644 --- a/src/gamedata/w_wad.h +++ b/src/gamedata/w_wad.h @@ -12,6 +12,7 @@ #include "files.h" #include "doomdef.h" #include "tarray.h" +#include "cmdlib.h" #include "zstring.h" #include "resourcefiles/resourcefile.h" @@ -19,43 +20,30 @@ class FResourceFile; struct FResourceLump; class FTexture; -struct wadinfo_t +union LumpShortName { - // Should be "IWAD" or "PWAD". - uint32_t Magic; - uint32_t NumLumps; - uint32_t InfoTableOfs; -}; + char String[9]; -struct wadlump_t -{ - uint32_t FilePos; - uint32_t Size; - char Name[8]; + uint32_t dword; // These are for accessing the first 4 or 8 chars of + uint64_t qword; // Name as a unit without breaking strict aliasing rules }; -#define IWAD_ID MAKE_ID('I','W','A','D') -#define PWAD_ID MAKE_ID('P','W','A','D') - - -// [RH] Copy an 8-char string and uppercase it. -void uppercopy (char *to, const char *from); // A lump in memory. -class FMemLump +class FileData { public: - FMemLump (); + FileData (); - FMemLump (const FMemLump ©); - FMemLump &operator= (const FMemLump ©); - ~FMemLump (); + FileData (const FileData ©); + FileData &operator= (const FileData ©); + ~FileData (); void *GetMem () { return Block.Len() == 0 ? NULL : (void *)Block.GetChars(); } size_t GetSize () { return Block.Len(); } FString GetString () { return Block; } private: - FMemLump (const FString &source); + FileData (const FString &source); FString Block; @@ -82,12 +70,12 @@ class FileSystem void SetMaxIwadNum(int x) { MaxIwadIndex = x; } void InitSingleFile(const char *filename, bool quiet = false); - void InitMultipleFiles (TArray &filenames, const TArray &deletelumps, bool quiet = false, LumpFilterInfo* filter = nullptr); + void InitMultipleFiles (TArray &filenames, bool quiet = false, LumpFilterInfo* filter = nullptr); void AddFile (const char *filename, FileReader *wadinfo, bool quiet, LumpFilterInfo* filter); - int CheckIfWadLoaded (const char *name); + int CheckIfResourceFileLoaded (const char *name) noexcept; - const char *GetWadName (int wadnum) const; - const char *GetWadFullName (int wadnum) const; + const char *GetResourceFileName (int filenum) const noexcept; + const char *GetResourceFileFullName (int wadnum) const noexcept; int GetFirstLump(int wadnum) const; int GetLastLump(int wadnum) const; @@ -109,6 +97,11 @@ class FileSystem int CheckNumForFullName (const char *name, bool trynormal = false, int namespc = ns_global, bool ignoreext = false); int CheckNumForFullName (const char *name, int wadfile); int GetNumForFullName (const char *name); + int FindFile(const char* name) + { + return CheckNumForFullName(name); + } + LumpShortName& GetShortName(int i); // may only be called before the hash chains are set up. inline int CheckNumForFullName(const FString &name, bool trynormal = false, int namespc = ns_global) { return CheckNumForFullName(name.GetChars(), trynormal, namespc); } inline int CheckNumForFullName (const FString &name, int wadfile) { return CheckNumForFullName(name.GetChars(), wadfile); } @@ -119,9 +112,9 @@ class FileSystem void ReadLump (int lump, void *dest); - TArray ReadLumpIntoArray(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FMemLump isn't writable!) - FMemLump ReadLump (int lump); - FMemLump ReadLump (const char *name) { return ReadLump (GetNumForName (name)); } + TArray ReadLumpIntoArray(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!) + FileData ReadLump (int lump); + FileData ReadLump (const char *name) { return ReadLump (GetNumForName (name)); } FileReader OpenLumpReader(int lump); // opens a reader that redirects to the containing file's one. FileReader ReopenLumpReader(int lump, bool alwayscache = false); // opens an independent reader. @@ -130,11 +123,16 @@ class FileSystem int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names bool CheckLumpName (int lump, const char *name); // [RH] True if lump's name == name + int FindFileWithExtensions(const char* name, const char* const* exts, int count); + int FindResource(int resid, const char* type, int filenum) const noexcept; + int GetResource(int resid, const char* type, int filenum) const; + + static uint32_t LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name - int LumpLength (int lump) const; - int GetLumpOffset (int lump); // [RH] Returns offset of lump in the wadfile - int GetLumpFlags (int lump); // Return the flags for this lump + int FileLength (int lump) const; + int GetFileOffset (int lump); // [RH] Returns offset of lump in the wadfile + int GetFileFlags (int lump); // Return the flags for this lump void GetLumpName (char *to, int lump) const; // [RH] Copies the lump name to to using uppercopy void GetLumpName (FString &to, int lump) const; const char* GetLumpName(int lump) const; @@ -149,7 +147,7 @@ class FileSystem int GetNumLumps() const { - return NumLumps; + return NumEntries; } int GetNumWads() const @@ -157,14 +155,18 @@ class FileSystem return Files.Size(); } + void AddLump(FResourceLump* lump); int AddExternalFile(const char *filename); + int AddFromBuffer(const char* name, const char* type, char* data, int size, int id, int flags); + FileReader* GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD + void InitHashChains(); protected: struct LumpRecord; TArray Files; - TArray LumpInfo; + TArray FileInfo; TArray Hashes; // one allocation for all hash lists. uint32_t *FirstLumpIndex; // [RH] Hashing stuff moved out of lumpinfo structure @@ -176,22 +178,19 @@ class FileSystem uint32_t *FirstLumpIndex_NoExt; // The same information for fully qualified paths from .zips uint32_t *NextLumpIndex_NoExt; - uint32_t NumLumps = 0; // Not necessarily the same as LumpInfo.Size() + uint32_t* FirstLumpIndex_ResId; // The same information for fully qualified paths from .zips + uint32_t* NextLumpIndex_ResId; + + uint32_t NumEntries = 0; // Not necessarily the same as FileInfo.Size() uint32_t NumWads; int IwadIndex = -1; int MaxIwadIndex = -1; - void InitHashChains (); // [RH] Set up the lumpinfo hashing - private: - void RenameSprites(const TArray &deletelumps); - void RenameNerve(); - void FixMacHexen(); void DeleteAll(); void MoveLumpsInFolder(const char *); - FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD }; extern FileSystem fileSystem; diff --git a/src/intermission/intermission_parse.cpp b/src/intermission/intermission_parse.cpp index 5348d39d476..dba03f78125 100644 --- a/src/intermission/intermission_parse.cpp +++ b/src/intermission/intermission_parse.cpp @@ -307,7 +307,7 @@ bool FIntermissionActionTextscreen::ParseKey(FScanner &sc) { // Check if this comes from either Hexen.wad or Hexdd.wad and if so, map to the string table. int fileno = fileSystem.GetLumpFile(lump); - auto fn = fileSystem.GetWadName(fileno); + auto fn = fileSystem.GetResourceFileName(fileno); if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, sc.String); diff --git a/src/maploader/glnodes.cpp b/src/maploader/glnodes.cpp index 84b82075ce5..0b3cb852a60 100644 --- a/src/maploader/glnodes.cpp +++ b/src/maploader/glnodes.cpp @@ -752,7 +752,7 @@ static int FindGLNodesInWAD(int labellump) { if (fileSystem.GetLumpFile(lump)==wadfile) { - FMemLump mem = fileSystem.ReadLump(lump); + FileData mem = fileSystem.ReadLump(lump); if (MatchHeader(fileSystem.GetLumpFullName(labellump), (const char *)mem.GetMem())) return lump; } } @@ -858,7 +858,7 @@ bool MapLoader::LoadGLNodes(MapData * map) bool mapinwad = map->InWad; FResourceFile * f_gwa = map->resource; - const char * name = fileSystem.GetWadFullName(lumpfile); + const char * name = fileSystem.GetResourceFileFullName(lumpfile); if (mapinwad) { diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index d6ae3ed6157..3122b9fbedd 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -1158,7 +1158,7 @@ void MapLoader::LoadSectors (MapData *map, FMissingTextureTracker &missingtex) template bool MapLoader::LoadNodes (MapData * map) { - FMemLump data; + FileData data; int j; int k; nodetype *mn; @@ -2151,7 +2151,7 @@ void MapLoader::ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec sd->SetTexture(side_t::mid, FNullTextureID()); } else if ((lumpnum = fileSystem.CheckNumForName (msd->midtexture)) > 0 && - fileSystem.LumpLength (lumpnum) == 65536) + fileSystem.FileLength (lumpnum) == 65536) { *alpha = (short)DetermineTranslucency (lumpnum); sd->SetTexture(side_t::mid, FNullTextureID()); diff --git a/src/maploader/strifedialogue.cpp b/src/maploader/strifedialogue.cpp index 2b071efd207..b651f6a953b 100644 --- a/src/maploader/strifedialogue.cpp +++ b/src/maploader/strifedialogue.cpp @@ -155,10 +155,10 @@ bool MapLoader::LoadScriptFile (const char *name, bool include, int type) FileReader lump = fileSystem.ReopenLumpReader (lumpnum); auto fn = fileSystem.GetLumpFile(lumpnum); - auto wadname = fileSystem.GetWadName(fn); + auto wadname = fileSystem.GetResourceFileName(fn); if (stricmp(wadname, "STRIFE0.WAD") && stricmp(wadname, "STRIFE1.WAD") && stricmp(wadname, "SVE.WAD")) name = nullptr; // Only localize IWAD content. - bool res = LoadScriptFile(name, lumpnum, lump, fileSystem.LumpLength(lumpnum), include, type); + bool res = LoadScriptFile(name, lumpnum, lump, fileSystem.FileLength(lumpnum), include, type); return res; } diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index 5a7771e4d6c..c8c6cee7c26 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -204,7 +204,7 @@ void FSavegameManager::ReadSaveStrings() // old, incompatible savegame. List as not usable. oldVer = true; } - else if (iwad.CompareNoCase(fileSystem.GetWadName(fileSystem.GetIwadNum())) == 0) + else if (iwad.CompareNoCase(fileSystem.GetResourceFileName(fileSystem.GetIwadNum())) == 0) { missing = !G_CheckSaveGameWads(arc, false); } diff --git a/src/p_openmap.cpp b/src/p_openmap.cpp index 1a826c5a3aa..abb47a32407 100644 --- a/src/p_openmap.cpp +++ b/src/p_openmap.cpp @@ -40,8 +40,11 @@ #include "w_wad.h" #include "md5.h" #include "g_levellocals.h" +#include "cmdlib.h" + +#define IWAD_ID MAKE_ID('I','W','A','D') +#define PWAD_ID MAKE_ID('P','W','A','D') -void md5Update(FileReader& file, MD5Context& md5, unsigned len); inline bool P_IsBuildMap(MapData *map) { diff --git a/src/playsim/fragglescript/t_load.cpp b/src/playsim/fragglescript/t_load.cpp index 12a65530a31..a1b1bbb1ae9 100644 --- a/src/playsim/fragglescript/t_load.cpp +++ b/src/playsim/fragglescript/t_load.cpp @@ -223,7 +223,7 @@ bool FScriptLoader::ParseInfo(MapData * map) // Try a global FS lump int lumpnum=fileSystem.CheckNumForName("FSGLOBAL"); if (lumpnum<0) return false; - lumpsize=fileSystem.LumpLength(lumpnum); + lumpsize=fileSystem.FileLength(lumpnum); if (lumpsize==0) return false; fsglobal=true; lump=new char[lumpsize+3]; diff --git a/src/playsim/fragglescript/t_prepro.cpp b/src/playsim/fragglescript/t_prepro.cpp index 8841ab7f8b4..6f739c335ba 100644 --- a/src/playsim/fragglescript/t_prepro.cpp +++ b/src/playsim/fragglescript/t_prepro.cpp @@ -417,7 +417,7 @@ void DFsScript::ParseInclude(FLevelLocals *Level, char *lumpname) return; } - int lumplen=fileSystem.LumpLength(lumpnum); + int lumplen=fileSystem.FileLength(lumpnum); lump=new char[lumplen+10]; fileSystem.ReadLump(lumpnum,lump); diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 5b6d6996b46..fe3f43eb416 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -2224,7 +2224,7 @@ bool FBehavior::Init(FLevelLocals *Level, int lumpnum, FileReader * fr, int len, // 2. Corrupt modules won't be reported when a level is being loaded if this function quits before // adding it to the list. - if (fr == NULL) len = fileSystem.LumpLength (lumpnum); + if (fr == NULL) len = fileSystem.FileLength (lumpnum); @@ -2318,7 +2318,7 @@ bool FBehavior::Init(FLevelLocals *Level, int lumpnum, FileReader * fr, int len, if ((Level->flags2 & LEVEL2_HEXENHACK) && gameinfo.gametype == GAME_Hexen && lumpnum == -1 && reallumpnum > 0) { int fileno = fileSystem.GetLumpFile(reallumpnum); - const char * filename = fileSystem.GetWadName(fileno); + const char * filename = fileSystem.GetResourceFileName(fileno); if (!stricmp(filename, "HEXEN.WAD") || !stricmp(filename, "HEXDD.WAD")) { ShouldLocalize = true; diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index b65fc87fc36..d2206c7c4de 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -392,7 +392,7 @@ void player_t::SetLogNumber (int num) if (lumpnum != -1) { auto fn = fileSystem.GetLumpFile(lumpnum); - auto wadname = fileSystem.GetWadName(fn); + auto wadname = fileSystem.GetResourceFileName(fn); if (!stricmp(wadname, "STRIFE0.WAD") || !stricmp(wadname, "STRIFE1.WAD") || !stricmp(wadname, "SVE.WAD")) { // If this is an original IWAD text, try looking up its lower priority string version first. diff --git a/src/posix/sdl/i_main.cpp b/src/posix/sdl/i_main.cpp index 942761d9736..bac53e3131f 100644 --- a/src/posix/sdl/i_main.cpp +++ b/src/posix/sdl/i_main.cpp @@ -115,7 +115,7 @@ static int DoomSpecificInfo (char *buffer, char *end) } p += snprintf(buffer + p, size - p, "\n"); - for (i = 0; (arg = fileSystem.GetWadName(i)) != NULL; ++i) + for (i = 0; (arg = fileSystem.GetResourceFileName(i)) != NULL; ++i) { p += snprintf(buffer + p, size - p, "\nWad %d: %s", i, arg); } diff --git a/src/r_data/colormaps.cpp b/src/r_data/colormaps.cpp index cd6c6539524..885dcd1641b 100644 --- a/src/r_data/colormaps.cpp +++ b/src/r_data/colormaps.cpp @@ -242,7 +242,7 @@ void R_InitColormaps (bool allowCustomColormap) for (unsigned j = 1; j < fakecmaps.Size(); j++) { - if (fileSystem.LumpLength (fakecmaps[j].lump) >= 256) + if (fileSystem.FileLength (fakecmaps[j].lump) >= 256) { int k, r, g, b; auto lump = fileSystem.OpenLumpReader (fakecmaps[j].lump); diff --git a/src/r_data/models/models.cpp b/src/r_data/models/models.cpp index 38e78b3ee81..910ed083698 100644 --- a/src/r_data/models/models.cpp +++ b/src/r_data/models/models.cpp @@ -407,8 +407,8 @@ static unsigned FindModel(const char * path, const char * modelfile) if (!Models[i]->mFileName.CompareNoCase(fullname)) return i; } - int len = fileSystem.LumpLength(lump); - FMemLump lumpd = fileSystem.ReadLump(lump); + int len = fileSystem.FileLength(lump); + FileData lumpd = fileSystem.ReadLump(lump); char * buffer = (char*)lumpd.GetMem(); if ( (size_t)fullname.LastIndexOf("_d.3d") == fullname.Len()-5 ) diff --git a/src/r_data/models/models_md2.cpp b/src/r_data/models/models_md2.cpp index 381b33fd836..1192ec08f77 100644 --- a/src/r_data/models/models_md2.cpp +++ b/src/r_data/models/models_md2.cpp @@ -170,7 +170,7 @@ bool FDMDModel::Load(const char * path, int lumpnum, const char * buffer, int le void FDMDModel::LoadGeometry() { static int axis[3] = { VX, VY, VZ }; - FMemLump lumpdata = fileSystem.ReadLump(mLumpNum); + FileData lumpdata = fileSystem.ReadLump(mLumpNum); const char *buffer = (const char *)lumpdata.GetMem(); texCoords = new FTexCoord[info.numTexCoords]; memcpy(texCoords, buffer + info.offsetTexCoords, info.numTexCoords * sizeof(FTexCoord)); @@ -496,7 +496,7 @@ void FMD2Model::LoadGeometry() { static int axis[3] = { VX, VY, VZ }; uint8_t *md2_frames; - FMemLump lumpdata = fileSystem.ReadLump(mLumpNum); + FileData lumpdata = fileSystem.ReadLump(mLumpNum); const char *buffer = (const char *)lumpdata.GetMem(); texCoords = new FTexCoord[info.numTexCoords]; diff --git a/src/r_data/models/models_md3.cpp b/src/r_data/models/models_md3.cpp index 2096e8d82ae..571e85b974c 100644 --- a/src/r_data/models/models_md3.cpp +++ b/src/r_data/models/models_md3.cpp @@ -185,7 +185,7 @@ bool FMD3Model::Load(const char * path, int lumpnum, const char * buffer, int le void FMD3Model::LoadGeometry() { - FMemLump lumpdata = fileSystem.ReadLump(mLumpNum); + FileData lumpdata = fileSystem.ReadLump(mLumpNum); const char *buffer = (const char *)lumpdata.GetMem(); md3_header_t * hdr = (md3_header_t *)buffer; md3_surface_t * surf = (md3_surface_t*)(buffer + LittleLong(hdr->Ofs_Surfaces)); diff --git a/src/r_data/models/models_ue1.cpp b/src/r_data/models/models_ue1.cpp index 0fa5c8d17f2..a36dda73ec5 100644 --- a/src/r_data/models/models_ue1.cpp +++ b/src/r_data/models/models_ue1.cpp @@ -62,7 +62,7 @@ bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int void FUE1Model::LoadGeometry() { - FMemLump lump, lump2; + FileData lump, lump2; const char *buffer, *buffer2; lump = fileSystem.ReadLump(mDataLump); buffer = (char*)lump.GetMem(); diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 10e15e449e8..16381e8a788 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -490,7 +490,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerC bases = s; basev = v; - if (colorset != NULL && colorset->Lump >= 0 && fileSystem.LumpLength(colorset->Lump) < 256) + if (colorset != NULL && colorset->Lump >= 0 && fileSystem.FileLength(colorset->Lump) < 256) { // Bad table length. Ignore it. colorset = NULL; } @@ -511,7 +511,7 @@ static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerC } else { - FMemLump translump = fileSystem.ReadLump(colorset->Lump); + FileData translump = fileSystem.ReadLump(colorset->Lump); const uint8_t *trans = (const uint8_t *)translump.GetMem(); for (i = start; i <= end; ++i) { diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index 925cfab113f..b26be338e18 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -949,7 +949,7 @@ CCMD (skins) static void R_CreateSkinTranslation (const char *palname) { - FMemLump lump = fileSystem.ReadLump (palname); + FileData lump = fileSystem.ReadLump (palname); const uint8_t *otherPal = (uint8_t *)lump.GetMem(); for (int i = 0; i < 256; ++i) diff --git a/src/r_data/v_palette.cpp b/src/r_data/v_palette.cpp index 9c1c2b6501d..f5818a9ceb5 100644 --- a/src/r_data/v_palette.cpp +++ b/src/r_data/v_palette.cpp @@ -284,7 +284,7 @@ int ReadPalette(int lumpnum, uint8_t *buffer) { return 0; } - FMemLump lump = fileSystem.ReadLump(lumpnum); + FileData lump = fileSystem.ReadLump(lumpnum); uint8_t *lumpmem = (uint8_t*)lump.GetMem(); memset(buffer, 0, 768); diff --git a/src/r_data/voxels.cpp b/src/r_data/voxels.cpp index 69bbe70e879..9f372bf75ca 100644 --- a/src/r_data/voxels.cpp +++ b/src/r_data/voxels.cpp @@ -178,7 +178,7 @@ FVoxel *R_LoadKVX(int lumpnum) int mip, maxmipsize; int i, j, n; - FMemLump lump = fileSystem.ReadLump(lumpnum); // FMemLump adds an extra 0 byte to the end. + FileData lump = fileSystem.ReadLump(lumpnum); // FileData adds an extra 0 byte to the end. uint8_t *rawvoxel = (uint8_t *)lump.GetMem(); int voxelsize = (int)(lump.GetSize()-1); diff --git a/src/rendering/gl/shaders/gl_shader.cpp b/src/rendering/gl/shaders/gl_shader.cpp index 55207964305..a821e347f1e 100644 --- a/src/rendering/gl/shaders/gl_shader.cpp +++ b/src/rendering/gl/shaders/gl_shader.cpp @@ -333,11 +333,11 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump, 0); if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump); - FMemLump vp_data = fileSystem.ReadLump(vp_lump); + FileData vp_data = fileSystem.ReadLump(vp_lump); int fp_lump = fileSystem.CheckNumForFullName(frag_prog_lump, 0); if (fp_lump == -1) I_Error("Unable to load '%s'", frag_prog_lump); - FMemLump fp_data = fileSystem.ReadLump(fp_lump); + FileData fp_data = fileSystem.ReadLump(fp_lump); @@ -385,7 +385,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * { int pp_lump = fileSystem.CheckNumForFullName(proc_prog_lump); if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump); - FMemLump pp_data = fileSystem.ReadLump(pp_lump); + FileData pp_data = fileSystem.ReadLump(pp_lump); if (pp_data.GetString().IndexOf("ProcessMaterial") < 0) { @@ -394,7 +394,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * // add ProcessMaterial function that calls the older ProcessTexel function int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat.fp"); - FMemLump pl_data = fileSystem.ReadLump(pl_lump); + FileData pl_data = fileSystem.ReadLump(pl_lump); fp_comb << "\n" << pl_data.GetString().GetChars(); if (pp_data.GetString().IndexOf("ProcessTexel") < 0) @@ -420,7 +420,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * { int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultlight.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultlight.fp"); - FMemLump pl_data = fileSystem.ReadLump(pl_lump); + FileData pl_data = fileSystem.ReadLump(pl_lump); fp_comb << "\n" << pl_data.GetString().GetChars(); } } @@ -435,7 +435,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * { int pp_lump = fileSystem.CheckNumForFullName(light_fragprog, 0); if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog); - FMemLump pp_data = fileSystem.ReadLump(pp_lump); + FileData pp_data = fileSystem.ReadLump(pp_lump); fp_comb << pp_data.GetString().GetChars() << "\n"; } diff --git a/src/rendering/swrenderer/r_swcolormaps.cpp b/src/rendering/swrenderer/r_swcolormaps.cpp index 565bc908e8e..c57e34684fc 100644 --- a/src/rendering/swrenderer/r_swcolormaps.cpp +++ b/src/rendering/swrenderer/r_swcolormaps.cpp @@ -424,7 +424,7 @@ static void InitBoomColormaps () remap[0] = 0; for (j = 1; j < fakecmaps.Size(); j++) { - if (fileSystem.LumpLength (fakecmaps[j].lump) >= (NUMCOLORMAPS+1)*256) + if (fileSystem.FileLength (fakecmaps[j].lump) >= (NUMCOLORMAPS+1)*256) { int k, r; auto lump = fileSystem.OpenLumpReader (fakecmaps[j].lump); diff --git a/src/rendering/v_video.cpp b/src/rendering/v_video.cpp index 85010676bf5..84b0c402803 100644 --- a/src/rendering/v_video.cpp +++ b/src/rendering/v_video.cpp @@ -380,7 +380,7 @@ int V_GetColorFromString (const uint32_t *palette, const char *cstr, FScriptPosi FString V_GetColorStringByName (const char *name, FScriptPosition *sc) { - FMemLump rgbNames; + FileData rgbNames; char *rgbEnd; char *rgb, *endp; int rgblump; @@ -399,7 +399,7 @@ FString V_GetColorStringByName (const char *name, FScriptPosition *sc) rgbNames = fileSystem.ReadLump (rgblump); rgb = (char *)rgbNames.GetMem(); - rgbEnd = rgb + fileSystem.LumpLength (rgblump); + rgbEnd = rgb + fileSystem.FileLength (rgblump); step = 0; namelen = strlen (name); diff --git a/src/rendering/vulkan/shaders/vk_shader.cpp b/src/rendering/vulkan/shaders/vk_shader.cpp index d5499ac8eb4..ddf4f93a948 100644 --- a/src/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/rendering/vulkan/shaders/vk_shader.cpp @@ -347,7 +347,7 @@ FString VkShaderManager::LoadPublicShaderLump(const char *lumpname) { int lump = fileSystem.CheckNumForFullName(lumpname); if (lump == -1) I_Error("Unable to load '%s'", lumpname); - FMemLump data = fileSystem.ReadLump(lump); + FileData data = fileSystem.ReadLump(lump); return data.GetString(); } @@ -355,6 +355,6 @@ FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname) { int lump = fileSystem.CheckNumForFullName(lumpname, 0); if (lump == -1) I_Error("Unable to load '%s'", lumpname); - FMemLump data = fileSystem.ReadLump(lump); + FileData data = fileSystem.ReadLump(lump); return data.GetString(); } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 6435a415580..d043f6591c1 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -1276,7 +1276,7 @@ void ParseDecorate (FScanner &sc, PNamespace *ns) if (includefile != 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetWadFullName(includefile), sc.String); + fileSystem.GetResourceFileFullName(includefile), sc.String); } } FScanner newscanner; diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 304c4e857f9..17f45618766 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -3141,6 +3141,85 @@ DEFINE_ACTION_FUNCTION_NATIVE(_AltHUD, GetLatency, Net_GetLatency) return numret; } +//========================================================================== +// +// file system +// +//========================================================================== + +//========================================================================== +// +// W_NumLumps +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(_Wads, GetNumLumps) +{ + PARAM_PROLOGUE; + ACTION_RETURN_INT(fileSystem.GetNumLumps()); +} + +DEFINE_ACTION_FUNCTION(_Wads, CheckNumForName) +{ + PARAM_PROLOGUE; + PARAM_STRING(name); + PARAM_INT(ns); + PARAM_INT(wadnum); + PARAM_BOOL(exact); + ACTION_RETURN_INT(fileSystem.CheckNumForName(name, ns, wadnum, exact)); +} + +DEFINE_ACTION_FUNCTION(_Wads, CheckNumForFullName) +{ + PARAM_PROLOGUE; + PARAM_STRING(name); + ACTION_RETURN_INT(fileSystem.CheckNumForFullName(name)); +} + +DEFINE_ACTION_FUNCTION(_Wads, FindLump) +{ + PARAM_PROLOGUE; + PARAM_STRING(name); + PARAM_INT(startlump); + PARAM_INT(ns); + const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumLumps(); + ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLump(name, &startlump, 0 != ns) : -1); +} + +DEFINE_ACTION_FUNCTION(_Wads, GetLumpName) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + FString lumpname; + fileSystem.GetLumpName(lumpname, lump); + ACTION_RETURN_STRING(lumpname); +} + +DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullName) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_STRING(fileSystem.GetLumpFullName(lump)); +} + +DEFINE_ACTION_FUNCTION(_Wads, GetLumpNamespace) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + ACTION_RETURN_INT(fileSystem.GetLumpNamespace(lump)); +} + +DEFINE_ACTION_FUNCTION(_Wads, ReadLump) +{ + PARAM_PROLOGUE; + PARAM_INT(lump); + const bool isLumpValid = lump >= 0 && lump < fileSystem.GetNumLumps(); + ACTION_RETURN_STRING(isLumpValid ? fileSystem.ReadLump(lump).GetString() : FString()); +} + + + + //========================================================================== // // diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 6ecadccf226..6ff20a64ac2 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -426,7 +426,7 @@ static void DoParse(int lumpnum) if (fileno == 0 && fileno2 != 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetWadFullName(fileSystem.GetLumpFile(lumpnum)), Includes[i].GetChars()); + fileSystem.GetResourceFileFullName(fileSystem.GetLumpFile(lumpnum)), Includes[i].GetChars()); } ParseSingleFile(nullptr, nullptr, lumpnum, parser, state); diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index 606effc64d8..3b874387199 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -191,7 +191,7 @@ static void SetupWgOpn() { return; } - FMemLump data = fileSystem.ReadLump(lump); + FileData data = fileSystem.ReadLump(lump); ZMusic_SetWgOpn(data.GetMem(), (uint32_t)data.GetSize()); } @@ -202,7 +202,7 @@ static void SetupDMXGUS() { return; } - FMemLump data = fileSystem.ReadLump(lump); + FileData data = fileSystem.ReadLump(lump); ZMusic_SetDmxGus(data.GetMem(), (uint32_t)data.GetSize()); } diff --git a/src/sound/s_music.cpp b/src/sound/s_music.cpp index bd4b773f23d..bedc0610929 100644 --- a/src/sound/s_music.cpp +++ b/src/sound/s_music.cpp @@ -441,7 +441,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) } if (handle == nullptr) { - if (fileSystem.LumpLength (lumpnum) == 0) + if (fileSystem.FileLength (lumpnum) == 0) { return false; } diff --git a/src/utility/sc_man.cpp b/src/utility/sc_man.cpp index f62c972d8fe..6595677ae7b 100644 --- a/src/utility/sc_man.cpp +++ b/src/utility/sc_man.cpp @@ -279,7 +279,7 @@ void FScanner :: OpenLumpNum (int lump) { Close (); { - FMemLump mem = fileSystem.ReadLump(lump); + FileData mem = fileSystem.ReadLump(lump); ScriptBuffer = mem.GetString(); } ScriptName = fileSystem.GetLumpFullPath(lump); diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 29c594fbe82..a5a0246befe 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1016,7 +1016,7 @@ void DoomSpecificInfo (char *buffer, size_t bufflen) FString cmdline(GetCommandLineW()); buffer += mysnprintf (buffer, buffend - buffer, "\r\nCommand line: %s\r\n", cmdline.GetChars() ); - for (i = 0; (arg = fileSystem.GetWadName (i)) != NULL; ++i) + for (i = 0; (arg = fileSystem.GetResourceFileName (i)) != NULL; ++i) { buffer += mysnprintf (buffer, buffend - buffer, "\r\nWad %d: %s", i, arg); } diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index c50ae2e397b..00f13591ca0 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -526,7 +526,7 @@ int RunEndoom() bool blinking = false, blinkstate = false; int i; - if (endoom_lump < 0 || fileSystem.LumpLength (endoom_lump) != 4000) + if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000) { return 0; } diff --git a/src/win32/st_start_util.cpp b/src/win32/st_start_util.cpp index 01f57d84ab3..750d4cac70e 100644 --- a/src/win32/st_start_util.cpp +++ b/src/win32/st_start_util.cpp @@ -413,9 +413,9 @@ FHexenStartupScreen::FHexenStartupScreen(int max_progress, long& hr) int notch_lump = fileSystem.CheckNumForName("NOTCH"); hr = -1; - if (startup_lump < 0 || fileSystem.LumpLength(startup_lump) != 153648 || !ST_Util_CreateStartupWindow() || - netnotch_lump < 0 || fileSystem.LumpLength(netnotch_lump) != ST_NETNOTCH_WIDTH / 2 * ST_NETNOTCH_HEIGHT || - notch_lump < 0 || fileSystem.LumpLength(notch_lump) != ST_NOTCH_WIDTH / 2 * ST_NOTCH_HEIGHT) + if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 153648 || !ST_Util_CreateStartupWindow() || + netnotch_lump < 0 || fileSystem.FileLength(netnotch_lump) != ST_NETNOTCH_WIDTH / 2 * ST_NETNOTCH_HEIGHT || + notch_lump < 0 || fileSystem.FileLength(notch_lump) != ST_NOTCH_WIDTH / 2 * ST_NOTCH_HEIGHT) { NetNotchBits = NotchBits = NULL; return; @@ -579,7 +579,7 @@ FHereticStartupScreen::FHereticStartupScreen(int max_progress, long& hr) uint8_t* font; hr = -1; - if (loading_lump < 0 || fileSystem.LumpLength(loading_lump) != 4000 || !ST_Util_CreateStartupWindow()) + if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000 || !ST_Util_CreateStartupWindow()) { return; } @@ -722,7 +722,7 @@ FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, long& hr) StartupPics[i] = NULL; } - if (startup_lump < 0 || fileSystem.LumpLength(startup_lump) != 64000 || !ST_Util_CreateStartupWindow()) + if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 64000 || !ST_Util_CreateStartupWindow()) { return; } @@ -742,7 +742,7 @@ FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, long& hr) int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]); int lumplen; - if (lumpnum >= 0 && (lumplen = fileSystem.LumpLength(lumpnum)) == StrifeStartupPicSizes[i]) + if (lumpnum >= 0 && (lumplen = fileSystem.FileLength(lumpnum)) == StrifeStartupPicSizes[i]) { auto lumpr = fileSystem.OpenLumpReader(lumpnum); StartupPics[i] = new uint8_t[lumplen]; @@ -1061,7 +1061,7 @@ uint8_t* ST_Util_LoadFont(const char* filename) { // font not found return NULL; } - lumplen = fileSystem.LumpLength(lumpnum); + lumplen = fileSystem.FileLength(lumpnum); height = lumplen / 256; if (height * 256 != lumplen) { // font is a bad size