From 31aa855a51be2184d405eb63d689aa94c4dd6608 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 13 Sep 2019 12:29:17 +0200 Subject: [PATCH] - generate a hash identifier for each loaded resource file. This is not useful by itself but can be used for adding new features later, e.g. mod-wide compatibility settings or file specific lump replacement or injection. --- src/gamedata/resourcefiles/file_7z.cpp | 1 + src/gamedata/resourcefiles/file_grp.cpp | 2 +- src/gamedata/resourcefiles/file_pak.cpp | 2 +- src/gamedata/resourcefiles/file_rff.cpp | 1 + src/gamedata/resourcefiles/file_wad.cpp | 1 + src/gamedata/resourcefiles/file_zip.cpp | 1 + src/gamedata/resourcefiles/resourcefile.cpp | 34 +++++++++++++++++++++ src/gamedata/resourcefiles/resourcefile.h | 2 ++ 8 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/gamedata/resourcefiles/file_7z.cpp b/src/gamedata/resourcefiles/file_7z.cpp index 01bd043ef..27b596341 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 936490177..81657a3c5 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 d69c5673d..2b4d39658 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 056379c7b..35402c3ad 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 f6db35f14..169cd975d 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 8ee031ae0..d661a8158 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 68a17058c..d934c98f2 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 4903441bd..65e0ef3f1 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: