diff --git a/src/gamedata/resourcefiles/file_7z.cpp b/src/gamedata/resourcefiles/file_7z.cpp index 01bd043efc..27b5963413 100644 --- a/src/gamedata/resourcefiles/file_7z.cpp +++ b/src/gamedata/resourcefiles/file_7z.cpp @@ -316,6 +316,7 @@ bool F7ZFile::Open(bool quiet) if (!quiet && !batchrun) Printf(", %d lumps\n", NumLumps); + GenerateHash(); PostProcessArchive(&Lumps[0], sizeof(F7ZLump)); return true; } diff --git a/src/gamedata/resourcefiles/file_grp.cpp b/src/gamedata/resourcefiles/file_grp.cpp index 9364901772..81657a3c5d 100644 --- a/src/gamedata/resourcefiles/file_grp.cpp +++ b/src/gamedata/resourcefiles/file_grp.cpp @@ -120,7 +120,7 @@ bool FGrpFile::Open(bool quiet) Lumps[i].LumpNameSetup(fileinfo[i].NameWithZero); } if (!quiet && !batchrun) Printf(", %d lumps\n", NumLumps); - + GenerateHash(); delete[] fileinfo; return true; } diff --git a/src/gamedata/resourcefiles/file_pak.cpp b/src/gamedata/resourcefiles/file_pak.cpp index d69c5673d5..2b4d396586 100644 --- a/src/gamedata/resourcefiles/file_pak.cpp +++ b/src/gamedata/resourcefiles/file_pak.cpp @@ -113,7 +113,7 @@ bool FPakFile::Open(bool quiet) Lumps[i].LumpSize = LittleLong(fileinfo[i].filelen); Lumps[i].CheckEmbedded(); } - + GenerateHash(); return true; } diff --git a/src/gamedata/resourcefiles/file_rff.cpp b/src/gamedata/resourcefiles/file_rff.cpp index 056379c7b0..35402c3add 100644 --- a/src/gamedata/resourcefiles/file_rff.cpp +++ b/src/gamedata/resourcefiles/file_rff.cpp @@ -184,6 +184,7 @@ bool FRFFFile::Open(bool quiet) } } delete[] lumps; + GenerateHash(); return true; } diff --git a/src/gamedata/resourcefiles/file_wad.cpp b/src/gamedata/resourcefiles/file_wad.cpp index f6db35f14a..169cd975d7 100644 --- a/src/gamedata/resourcefiles/file_wad.cpp +++ b/src/gamedata/resourcefiles/file_wad.cpp @@ -203,6 +203,7 @@ bool FWadFile::Open(bool quiet) } delete[] fileinfo; + GenerateHash(); // Do this before the lump processing below. if (!quiet) { diff --git a/src/gamedata/resourcefiles/file_zip.cpp b/src/gamedata/resourcefiles/file_zip.cpp index 8ee031ae0b..d661a8158f 100644 --- a/src/gamedata/resourcefiles/file_zip.cpp +++ b/src/gamedata/resourcefiles/file_zip.cpp @@ -363,6 +363,7 @@ bool FZipFile::Open(bool quiet) if (!quiet && !batchrun) Printf(TEXTCOLOR_NORMAL ", %d lumps\n", NumLumps); + GenerateHash(); PostProcessArchive(&Lumps[0], sizeof(FZipLump)); return true; } diff --git a/src/gamedata/resourcefiles/resourcefile.cpp b/src/gamedata/resourcefiles/resourcefile.cpp index 68a17058c4..d934c98f22 100644 --- a/src/gamedata/resourcefiles/resourcefile.cpp +++ b/src/gamedata/resourcefiles/resourcefile.cpp @@ -41,6 +41,7 @@ #include "gi.h" #include "doomstat.h" #include "doomtype.h" +#include "md5.h" //========================================================================== @@ -353,6 +354,39 @@ int lumpcmp(const void * a, const void * b) return rec1->FullName.CompareNoCase(rec2->FullName); } +//========================================================================== +// +// FResourceFile :: GenerateHash +// +// Generates a hash identifier for use in file identification. +// Potential uses are mod-wide compatibility settings or localization add-ons. +// This only hashes the lump directory but not the actual content +// +//========================================================================== + +void FResourceFile::GenerateHash() +{ + // hash the lump directory after sorting + + Hash.Format(("%08X-%04X-"), (unsigned)Reader.GetLength(), NumLumps); + + MD5Context md5; + + uint8_t digest[16]; + for(uint32_t i = 0; i < NumLumps; i++) + { + auto lump = GetLump(i); + md5.Update((const uint8_t*)lump->Name, strlen(lump->Name) + 1); // +1 to hash the terminating 0 as well. + md5.Update((const uint8_t*)lump->FullName.GetChars(), lump->FullName.Len() + 1); + md5.Update((const uint8_t*)&lump->LumpSize, 4); + } + md5.Final(digest); + for (auto c : digest) + { + Hash.AppendFormat("%02X", c); + } +} + //========================================================================== // // FResourceFile :: PostProcessArchive diff --git a/src/gamedata/resourcefiles/resourcefile.h b/src/gamedata/resourcefiles/resourcefile.h index 4903441bde..65e0ef3f1f 100644 --- a/src/gamedata/resourcefiles/resourcefile.h +++ b/src/gamedata/resourcefiles/resourcefile.h @@ -85,11 +85,13 @@ public: FString FileName; protected: uint32_t NumLumps; + FString Hash; FResourceFile(const char *filename); FResourceFile(const char *filename, FileReader &r); // for archives that can contain directories + void GenerateHash(); void PostProcessArchive(void *lumps, size_t lumpsize); private: