diff --git a/src/xenia/kernel/xam/xam_locale.cc b/src/xenia/kernel/xam/xam_locale.cc index 26fd37c5d..598bd6798 100644 --- a/src/xenia/kernel/xam/xam_locale.cc +++ b/src/xenia/kernel/xam/xam_locale.cc @@ -649,9 +649,10 @@ dword_result_t XamGetLanguageTypeface_entry(dword_t language, DECLARE_XAM_EXPORT1(XamGetLanguageTypeface, kNone, kImplemented); pointer_result_t XamGetLanguageTypefacePatch_entry(dword_t language) { - return 0; + assert_false(language >= static_cast(XLanguage::kMaxLanguages)); + return kernel_state()->xam_state()->GetLanguageTypefacePatch(language); } -DECLARE_XAM_EXPORT1(XamGetLanguageTypefacePatch, kNone, kStub); +DECLARE_XAM_EXPORT1(XamGetLanguageTypefacePatch, kNone, kSketchy); dword_result_t XamGetCountry_entry() { return kernel_state()->xconfig()->ReadSetting( diff --git a/src/xenia/kernel/xam/xam_state.cc b/src/xenia/kernel/xam/xam_state.cc index 2317e2e0d..b2d1b4567 100644 --- a/src/xenia/kernel/xam/xam_state.cc +++ b/src/xenia/kernel/xam/xam_state.cc @@ -31,6 +31,7 @@ XamState::XamState(Emulator* emulator, KernelState* kernel_state) achievement_manager_ = std::make_unique(); LoadLanguageLocaleFallback(); + LoadLanguageTypefacePatch(); LoadIptvServiceName(); AppManager::RegisterApps(kernel_state, app_manager_.get()); @@ -61,8 +62,53 @@ void XamState::LoadLanguageLocaleFallback() { } } +void XamState::LoadLanguageTypefacePatch() { + const std::array patch_data = { + u"", + u"file://media:/XenonSCLatin.xttp2", + u"file://media:/XenonCLatin.xttp2", + u"file://media:/XenonJKLatin.xttp2", + u"file://media:/XenonSCLatin.xttp1", + u"file://media:/XenonCLatin.xttp1", + u"file://media:/XenonJKLatin.xttp1"}; + + constexpr uint32_t array_start = 0x80D10000; + + if (kernel_state_->memory() + ->LookupHeap(0x80000000) + ->AllocFixed(array_start, 0x168, 0x1000, kMemoryAllocationCommit, + kMemoryProtectRead | kMemoryProtectWrite)) { + char16_t* ptr = + kernel_state_->memory()->TranslateVirtual(array_start); + + for (size_t i = 1; i < patch_data.size(); i++) { + language_type_face_patch_[i] = + kernel_state_->memory()->HostToGuestVirtual(ptr); + ptr += xe::string_util::copy_and_swap_truncating( + ptr, patch_data.at(i), patch_data.at(i).size() + 1) + + 1; + } + } +} + +uint32_t XamState::GetLanguageTypefacePatch(uint32_t language) const { + // checks an out of bounds address to see if either a flag of 0x1000 or 0x2000 + // is set. If first then use xttp1, if other use xttp2, else just return empty + // pointer. for now only usng xttp2 + uint32_t index = 0; + if (language == 17) { // kSChinese + index = 1; + } else if (language == 8) { // kTChinese + index = 2; + } else { + index = 3; + } + + return language_type_face_patch_[index]; +} + void XamState::LoadIptvServiceName() { - constexpr uint32_t address = 0x80D10000; + constexpr uint32_t address = 0x80D20000; if (kernel_state_->memory() ->LookupHeap(0x80000000) diff --git a/src/xenia/kernel/xam/xam_state.h b/src/xenia/kernel/xam/xam_state.h index f07122ca9..5a7659c41 100644 --- a/src/xenia/kernel/xam/xam_state.h +++ b/src/xenia/kernel/xam/xam_state.h @@ -66,6 +66,8 @@ class XamState { return language_fallback_address_[index]; } + uint32_t GetLanguageTypefacePatch(uint32_t language) const; + uint32_t GetIptvNameAddress() const { return iptv_name_address_; } X_DASH_APP_INFO dash_app_info_ = {}; @@ -78,6 +80,7 @@ class XamState { private: void LoadLanguageLocaleFallback(); + void LoadLanguageTypefacePatch(); void LoadIptvServiceName(); KernelState* kernel_state_; @@ -92,6 +95,7 @@ class XamState { // Custom XAM stuff std::array language_fallback_address_{}; + std::array language_type_face_patch_{}; uint32_t iptv_name_address_{}; };