From d3aedf5df19d080e43b4d921b5de40f52e5b3849 Mon Sep 17 00:00:00 2001 From: Andrew James Date: Sat, 8 Jan 2022 19:15:39 +1100 Subject: [PATCH] Split loading of MPQs to handle translations and voice packs (#3922) --- Source/diablo.cpp | 9 ++++++++- Source/init.cpp | 43 +++++++++++++++++++++---------------------- Source/init.h | 5 +++-- Source/options.cpp | 2 +- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index e752d037e..f3f780d4f 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1629,10 +1629,17 @@ int DiabloMain(int argc, char **argv) DiabloParseFlags(argc, argv); InitKeymapActions(); - init_archives(); + // Need to ensure devilutionx.mpq (and fonts.mpq if available) are loaded before attempting to read translation settings + LoadCoreArchives(); was_archives_init = true; + // Read settings including translation next. This will use the presence of fonts.mpq and look for assets in devilutionx.mpq LoadOptions(); + // Then look for a voice pack file based on the selected translation + LoadLanguageArchive(); + + // Finally load game data + LoadGameArchives(); DiabloInit(); diff --git a/Source/init.cpp b/Source/init.cpp index 5609acbef..48bd090a6 100644 --- a/Source/init.cpp +++ b/Source/init.cpp @@ -60,13 +60,13 @@ std::optional font_mpq; namespace { -std::optional LoadMPQ(const std::vector &paths, const char *mpqName) +std::optional LoadMPQ(const std::vector &paths, string_view mpqName) { std::optional archive; std::string mpqAbsPath; std::int32_t error = 0; for (const auto &path : paths) { - mpqAbsPath = path + mpqName; + mpqAbsPath = path + mpqName.data(); if ((archive = MpqArchive::Open(mpqAbsPath.c_str(), error))) { LogVerbose(" Found: {} in {}", mpqName, path); paths::SetMpqDir(path); @@ -125,18 +125,6 @@ std::vector GetMPQSearchPaths() return paths; } -void init_language_archives(const std::vector &paths) -{ - string_view code = *sgOptions.Language.code; - if (code != "en") { - char langMpqName[10] = {}; - CopyUtf8(langMpqName, code.data(), sizeof(langMpqName)); - - strncat(langMpqName, ".mpq", sizeof(langMpqName) - strlen(langMpqName) - 1); - lang_mpq = LoadMPQ(paths, langMpqName); - } -} - } // namespace void init_cleanup() @@ -160,7 +148,7 @@ void init_cleanup() NetClose(); } -void init_archives() +void LoadCoreArchives() { auto paths = GetMPQSearchPaths(); @@ -169,8 +157,25 @@ void init_archives() devilutionx_mpq = LoadMPQ(paths, "devilutionx.mpq"); #endif font_mpq = LoadMPQ(paths, "fonts.mpq"); // Extra fonts +} - init_language_archives(paths); +void LoadLanguageArchive() +{ + lang_mpq = std::nullopt; + + string_view code = *sgOptions.Language.code; + if (code != "en") { + std::string langMpqName { code }; + langMpqName.append(".mpq"); + + auto paths = GetMPQSearchPaths(); + lang_mpq = LoadMPQ(paths, langMpqName); + } +} + +void LoadGameArchives() +{ + auto paths = GetMPQSearchPaths(); diabdat_mpq = LoadMPQ(paths, "DIABDAT.MPQ"); if (!diabdat_mpq) { @@ -212,12 +217,6 @@ void init_archives() } } -void init_language_archives() -{ - lang_mpq = std::nullopt; - init_language_archives(GetMPQSearchPaths()); -} - void init_create_window() { if (!SpawnWindow(PROJECT_NAME)) diff --git a/Source/init.h b/Source/init.h index 8a5fb660f..908380344 100644 --- a/Source/init.h +++ b/Source/init.h @@ -30,8 +30,9 @@ extern std::optional lang_mpq; extern std::optional devilutionx_mpq; void init_cleanup(); -void init_archives(); -void init_language_archives(); +void LoadCoreArchives(); +void LoadLanguageArchive(); +void LoadGameArchives(); void init_create_window(); void MainWndProc(uint32_t Msg); WNDPROC SetWindowProc(WNDPROC NewProc); diff --git a/Source/options.cpp b/Source/options.cpp index 46bf04d40..bb795bb24 100644 --- a/Source/options.cpp +++ b/Source/options.cpp @@ -271,7 +271,7 @@ void OptionShowFPSChanged() void OptionLanguageCodeChanged() { LanguageInitialize(); - init_language_archives(); + LoadLanguageArchive(); } void OptionGameModeChanged()