From ce19d948f0b0845836c137aa92d0f160261b3d6b Mon Sep 17 00:00:00 2001 From: emoose Date: Thu, 22 Apr 2021 01:27:12 +0100 Subject: [PATCH] [Base] Move XdbfLocale to xbox.h as XLanguage, let STFS headers use it Renamed to XLanguage because AFAIK locale on Xbox is a different concept involving countries, this enum only involves languages though. --- src/xenia/emulator.cc | 2 +- src/xenia/kernel/util/xdbf_utils.cc | 14 +++---- src/xenia/kernel/util/xdbf_utils.h | 20 ++-------- src/xenia/kernel/xam/xam_info.cc | 11 ++--- src/xenia/vfs/devices/stfs_container_device.h | 40 +++++++++++++------ src/xenia/xbox.h | 21 ++++++++++ 6 files changed, 65 insertions(+), 43 deletions(-) diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index b1f504b59..4ee98cc24 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -714,7 +714,7 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path, module->memory()->TranslateVirtual(resource_data), resource_size); if (db.is_valid()) { // TODO(gibbed): get title respective to user locale. - title_name_ = db.title(kernel::util::XdbfLocale::kEnglish); + title_name_ = db.title(XLanguage::kEnglish); if (title_name_.empty()) { // If English title is unavailable, get the title in default locale. title_name_ = db.title(); diff --git a/src/xenia/kernel/util/xdbf_utils.cc b/src/xenia/kernel/util/xdbf_utils.cc index c2ed6880d..4e8c83ea3 100644 --- a/src/xenia/kernel/util/xdbf_utils.cc +++ b/src/xenia/kernel/util/xdbf_utils.cc @@ -55,10 +55,10 @@ XdbfBlock XdbfWrapper::GetEntry(XdbfSection section, uint64_t id) const { return {0}; } -std::string XdbfWrapper::GetStringTableEntry(XdbfLocale locale, +std::string XdbfWrapper::GetStringTableEntry(XLanguage language, uint16_t string_id) const { auto language_block = - GetEntry(XdbfSection::kStringTable, static_cast(locale)); + GetEntry(XdbfSection::kStringTable, static_cast(language)); if (!language_block) { return ""; } @@ -88,22 +88,22 @@ XdbfBlock XdbfGameData::icon() const { return GetEntry(XdbfSection::kImage, kXdbfIdTitle); } -XdbfLocale XdbfGameData::default_language() const { +XLanguage XdbfGameData::default_language() const { auto block = GetEntry(XdbfSection::kMetadata, kXdbfIdXstc); if (!block.buffer) { - return XdbfLocale::kEnglish; + return XLanguage::kEnglish; } auto xstc = reinterpret_cast(block.buffer); assert_true(xstc->magic == kXdbfMagicXstc); - return static_cast(static_cast(xstc->default_language)); + return static_cast(static_cast(xstc->default_language)); } std::string XdbfGameData::title() const { return GetStringTableEntry(default_language(), kXdbfIdTitle); } -std::string XdbfGameData::title(XdbfLocale locale) const { - return GetStringTableEntry(locale, kXdbfIdTitle); +std::string XdbfGameData::title(XLanguage language) const { + return GetStringTableEntry(language, kXdbfIdTitle); } } // namespace util diff --git a/src/xenia/kernel/util/xdbf_utils.h b/src/xenia/kernel/util/xdbf_utils.h index 50893788f..ff05a5b1b 100644 --- a/src/xenia/kernel/util/xdbf_utils.h +++ b/src/xenia/kernel/util/xdbf_utils.h @@ -14,6 +14,7 @@ #include #include "xenia/base/memory.h" +#include "xenia/xbox.h" namespace xe { namespace kernel { @@ -28,19 +29,6 @@ enum class XdbfSection : uint16_t { kStringTable = 0x0003, }; -// Found by dumping the kSectionStringTable sections of various games: -enum class XdbfLocale : uint32_t { - kUnknown = 0, - kEnglish = 1, - kJapanese = 2, - kGerman = 3, - kFrench = 4, - kSpanish = 5, - kItalian = 6, - kKorean = 7, - kChinese = 8, -}; - struct XdbfBlock { const uint8_t* buffer; size_t size; @@ -63,7 +51,7 @@ class XdbfWrapper { // Gets a string from the string table in the given language. // Returns the empty string if the entry is not found. - std::string GetStringTableEntry(XdbfLocale locale, uint16_t string_id) const; + std::string GetStringTableEntry(XLanguage language, uint16_t string_id) const; protected: #pragma pack(push, 1) @@ -133,12 +121,12 @@ class XdbfGameData : public XdbfWrapper { XdbfBlock icon() const; // The game's default language. - XdbfLocale default_language() const; + XLanguage default_language() const; // The game's title in its default language. std::string title() const; - std::string title(XdbfLocale locale) const; + std::string title(XLanguage language) const; }; } // namespace util diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index 438b8a8d0..f697ff658 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -28,9 +28,6 @@ namespace xe { namespace kernel { namespace xam { -constexpr uint32_t X_LANGUAGE_ENGLISH = 1; -constexpr uint32_t X_LANGUAGE_JAPANESE = 2; - dword_result_t XamFeatureEnabled(dword_t unk) { return 0; } DECLARE_XAM_EXPORT1(XamFeatureEnabled, kNone, kStub); @@ -208,19 +205,19 @@ dword_result_t XGetGameRegion() { return xeXGetGameRegion(); } DECLARE_XAM_EXPORT1(XGetGameRegion, kNone, kStub); dword_result_t XGetLanguage() { - uint32_t desired_language = X_LANGUAGE_ENGLISH; + auto desired_language = XLanguage::kEnglish; // Switch the language based on game region. // TODO(benvanik): pull from xex header. uint32_t game_region = XEX_REGION_NTSCU; if (game_region & XEX_REGION_NTSCU) { - desired_language = X_LANGUAGE_ENGLISH; + desired_language = XLanguage::kEnglish; } else if (game_region & XEX_REGION_NTSCJ) { - desired_language = X_LANGUAGE_JAPANESE; + desired_language = XLanguage::kJapanese; } // Add more overrides? - return desired_language; + return uint32_t(desired_language); } DECLARE_XAM_EXPORT1(XGetLanguage, kNone, kImplemented); diff --git a/src/xenia/vfs/devices/stfs_container_device.h b/src/xenia/vfs/devices/stfs_container_device.h index e435d142f..a7ecda6d2 100644 --- a/src/xenia/vfs/devices/stfs_container_device.h +++ b/src/xenia/vfs/devices/stfs_container_device.h @@ -268,11 +268,13 @@ XEPACKEDSTRUCT(XContentMetadata, { char16_t description_ex_chars[kNumLanguagesV2 - kNumLanguagesV1][128]; }; - std::u16string display_name(uint32_t lang_id) const { - lang_id--; + std::u16string display_name(XLanguage language) const { + uint32_t lang_id = uint32_t(language) - 1; + if (lang_id >= kNumLanguagesV2) { assert_always(); - lang_id = 0; // no room for this lang, read from english slot.. + // no room for this lang, read from english slot.. + lang_id = uint32_t(XLanguage::kEnglish) - 1; } const be* str = 0; @@ -284,17 +286,21 @@ XEPACKEDSTRUCT(XContentMetadata, { } if (!str) { + // Invalid language ID? + assert_always(); return u""; } return load_and_swap(str); } - std::u16string description(uint32_t lang_id) const { - lang_id--; + std::u16string description(XLanguage language) const { + uint32_t lang_id = uint32_t(language) - 1; + if (lang_id >= kNumLanguagesV2) { assert_always(); - lang_id = 0; // no room for this lang, read from english slot.. + // no room for this lang, read from english slot.. + lang_id = uint32_t(XLanguage::kEnglish) - 1; } const be* str = 0; @@ -306,6 +312,8 @@ XEPACKEDSTRUCT(XContentMetadata, { } if (!str) { + // Invalid language ID? + assert_always(); return u""; } @@ -320,11 +328,13 @@ XEPACKEDSTRUCT(XContentMetadata, { return load_and_swap(title_name_raw); } - bool set_display_name(uint32_t lang_id, const std::u16string_view value) { - lang_id--; + bool set_display_name(XLanguage language, const std::u16string_view value) { + uint32_t lang_id = uint32_t(language) - 1; + if (lang_id >= kNumLanguagesV2) { assert_always(); - lang_id = 0; // no room for this lang, store in english slot.. + // no room for this lang, store in english slot.. + lang_id = uint32_t(XLanguage::kEnglish) - 1; } char16_t* str = 0; @@ -336,6 +346,8 @@ XEPACKEDSTRUCT(XContentMetadata, { } if (!str) { + // Invalid language ID? + assert_always(); return false; } @@ -344,11 +356,13 @@ XEPACKEDSTRUCT(XContentMetadata, { return true; } - bool set_description(uint32_t lang_id, const std::u16string_view value) { - lang_id--; + bool set_description(XLanguage language, const std::u16string_view value) { + uint32_t lang_id = uint32_t(language) - 1; + if (lang_id >= kNumLanguagesV2) { assert_always(); - lang_id = 0; // no room for this lang, store in english slot.. + // no room for this lang, store in english slot.. + lang_id = uint32_t(XLanguage::kEnglish) - 1; } char16_t* str = 0; @@ -360,6 +374,8 @@ XEPACKEDSTRUCT(XContentMetadata, { } if (!str) { + // Invalid language ID? + assert_always(); return false; } diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 2080b236c..bdf6e3f38 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -323,6 +323,27 @@ static_assert_size(X_EXCEPTION_RECORD, 0x50); #pragma pack(pop) +// Found by dumping the kSectionStringTable sections of various games: +// and the language list at +// https://free60project.github.io/wiki/Profile_Account/ +enum class XLanguage : uint32_t { + kInvalid = 0, + kEnglish = 1, + kJapanese = 2, + kGerman = 3, + kFrench = 4, + kSpanish = 5, + kItalian = 6, + kKorean = 7, + kTChinese = 8, + kPortuguese = 9, + kSChinese = 10, + kPolish = 11, + kRussian = 12, + // STFS headers can't support any more languages than these + kMaxLanguages = 13 +}; + } // namespace xe // clang-format on