diff --git a/.editorconfig b/.editorconfig index 6baba88588a..959e97e84ea 100644 --- a/.editorconfig +++ b/.editorconfig @@ -83,3 +83,6 @@ end_of_line = lf [Dockerfile] end_of_line = lf + +[ASSETS_VERSION] +end_of_line = lf diff --git a/CMake/Assets.cmake b/CMake/Assets.cmake index c9e52fbcfa3..cab76d3a84f 100644 --- a/CMake/Assets.cmake +++ b/CMake/Assets.cmake @@ -41,6 +41,7 @@ if (Gettext_FOUND) endif() set(devilutionx_assets + ASSETS_VERSION arena/church.dun arena/circle_of_death.dun arena/hell.dun diff --git a/Source/diablo.cpp b/Source/diablo.cpp index fa1809aef8c..8a2ed108e91 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1145,7 +1145,7 @@ void CheckArchivesUpToDate() #ifdef UNPACKED_MPQS const bool devilutionxMpqOutOfDate = false; #else - const bool devilutionxMpqOutOfDate = devilutionx_mpq && (!devilutionx_mpq->HasFile("data\\charbg.clx") || devilutionx_mpq->HasFile("fonts\\12-00.bin")); + const bool devilutionxMpqOutOfDate = IsDevilutionXMpqOutOfDate(); #endif const bool fontsMpqOutOfDate = AreExtraFontsOutOfDate(); diff --git a/Source/init.cpp b/Source/init.cpp index 1e145b78f85..1e6488d58f7 100644 --- a/Source/init.cpp +++ b/Source/init.cpp @@ -77,6 +77,7 @@ std::optional font_mpq; namespace { +constexpr char DevilutionXMpqVersion[] = "1\n"; constexpr char ExtraFontsVersion[] = "1\n"; #ifdef UNPACKED_MPQS @@ -174,22 +175,44 @@ std::vector GetMPQSearchPaths() return paths; } -bool CheckExtraFontsVersion(AssetRef &&ref) +bool AssetContentsEq(AssetRef &&ref, std::string_view expected) { const size_t size = ref.size(); AssetHandle handle = OpenAsset(std::move(ref), false); - if (!handle.ok()) - return true; + if (!handle.ok()) return false; + std::unique_ptr contents { new char[size] }; + if (!handle.read(contents.get(), size)) return false; + return std::string_view { contents.get(), size } == expected; +} - std::unique_ptr version_contents { new char[size] }; - if (!handle.read(version_contents.get(), size)) - return true; +bool CheckDevilutionXMpqVersion(AssetRef &&ref) +{ + return !AssetContentsEq(std::move(ref), DevilutionXMpqVersion); +} - return std::string_view { version_contents.get(), size } != ExtraFontsVersion; +bool CheckExtraFontsVersion(AssetRef &&ref) +{ + return !AssetContentsEq(std::move(ref), ExtraFontsVersion); } } // namespace +#ifndef UNPACKED_MPQS +bool IsDevilutionXMpqOutOfDate(MpqArchive &archive) +{ + const char filename[] = "ASSETS_VERSION"; + const MpqFileHash fileHash = CalculateMpqFileHash(filename); + uint32_t fileNumber; + if (!archive.GetFileNumber(fileHash, fileNumber)) + return true; + AssetRef ref; + ref.archive = &archive; + ref.fileNumber = fileNumber; + ref.filename = filename; + return CheckDevilutionXMpqVersion(std::move(ref)); +} +#endif + #ifdef UNPACKED_MPQS bool AreExtraFontsOutOfDate(const std::string &path) { diff --git a/Source/init.h b/Source/init.h index d5c9921c439..e8ce7b43795 100644 --- a/Source/init.h +++ b/Source/init.h @@ -99,6 +99,19 @@ inline bool AreExtraFontsOutOfDate() #endif } +#ifndef UNPACKED_MPQS +bool IsDevilutionXMpqOutOfDate(MpqArchive &archive); +#endif + +inline bool IsDevilutionXMpqOutOfDate() +{ +#ifdef UNPACKED_MPQS + return false; +#else + return !devilutionx_mpq.has_value() || IsDevilutionXMpqOutOfDate(*devilutionx_mpq); +#endif +} + void init_cleanup(); void LoadCoreArchives(); void LoadLanguageArchive(); diff --git a/assets/ASSETS_VERSION b/assets/ASSETS_VERSION new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/assets/ASSETS_VERSION @@ -0,0 +1 @@ +1