diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index ff2f5ec93..1b28b1fa8 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -319,6 +319,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/resourcefiles/file_grp.cpp b/src/resourcefiles/file_grp.cpp index ea4de71e5..2f1ef227e 100644 --- a/src/resourcefiles/file_grp.cpp +++ b/src/resourcefiles/file_grp.cpp @@ -121,7 +121,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/resourcefiles/file_pak.cpp b/src/resourcefiles/file_pak.cpp index 29b021f18..10bb816d6 100644 --- a/src/resourcefiles/file_pak.cpp +++ b/src/resourcefiles/file_pak.cpp @@ -114,7 +114,7 @@ bool FPakFile::Open(bool quiet) Lumps[i].LumpSize = LittleLong(fileinfo[i].filelen); Lumps[i].CheckEmbedded(); } - + GenerateHash(); return true; } diff --git a/src/resourcefiles/file_rff.cpp b/src/resourcefiles/file_rff.cpp index 6843904c0..8c1069512 100644 --- a/src/resourcefiles/file_rff.cpp +++ b/src/resourcefiles/file_rff.cpp @@ -185,6 +185,7 @@ bool FRFFFile::Open(bool quiet) } } delete[] lumps; + GenerateHash(); return true; } diff --git a/src/resourcefiles/file_wad.cpp b/src/resourcefiles/file_wad.cpp index cdff63408..7c0afef36 100644 --- a/src/resourcefiles/file_wad.cpp +++ b/src/resourcefiles/file_wad.cpp @@ -206,6 +206,7 @@ bool FWadFile::Open(bool quiet) } delete[] fileinfo; + GenerateHash(); // Do this before the lump processing below. if (!quiet) { diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 04430384e..6f57b019d 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/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/resourcefiles/resourcefile.cpp b/src/resourcefiles/resourcefile.cpp index 02271a65b..79da7d7b0 100644 --- a/src/resourcefiles/resourcefile.cpp +++ b/src/resourcefiles/resourcefile.cpp @@ -42,6 +42,7 @@ #include "gi.h" #include "doomstat.h" #include "w_zip.h" +#include "md5.h" //========================================================================== @@ -347,6 +348,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/resourcefiles/resourcefile.h b/src/resourcefiles/resourcefile.h index 9ad2e43cf..05d5e39fa 100644 --- a/src/resourcefiles/resourcefile.h +++ b/src/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: