From 84e78790ab3f3e8883493b18946e97328d921774 Mon Sep 17 00:00:00 2001 From: wwylele Date: Wed, 30 Nov 2016 11:32:09 +0200 Subject: Config: auto-select region and language --- src/core/hle/service/cfg/cfg.cpp | 57 ++++++++++++++++++++++++++++++++++++++-- src/core/hle/service/cfg/cfg.h | 7 +++++ 2 files changed, 62 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/cfg') diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index d554c3f54..5e340f4c8 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -114,6 +114,8 @@ static const std::vector cfg_system_savedata_id = { 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00, }; +static u32 preferred_region_code = 0; + void GetCountryCodeString(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 country_code_id = cmd_buff[1]; @@ -159,11 +161,18 @@ void GetCountryCodeID(Service::Interface* self) { cmd_buff[2] = country_code_id; } +static u32 GetRegionValue() { + if (Settings::values.region_value == Settings::REGION_VALUE_AUTO_SELECT) + return preferred_region_code; + + return Settings::values.region_value; +} + void SecureInfoGetRegion(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = Settings::values.region_value; + cmd_buff[2] = GetRegionValue(); } void GenHashConsoleUnique(Service::Interface* self) { @@ -183,7 +192,7 @@ void GetRegionCanadaUSA(Service::Interface* self) { cmd_buff[1] = RESULT_SUCCESS.raw; u8 canada_or_usa = 1; - if (canada_or_usa == Settings::values.region_value) { + if (canada_or_usa == GetRegionValue()) { cmd_buff[2] = 1; } else { cmd_buff[2] = 0; @@ -313,10 +322,47 @@ static ResultVal GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 fl return MakeResult(pointer); } +/// Checks if the language is available in the chosen region, and returns a proper one +static u8 AdjustLanguageInfoBlock(u32 region, u8 language) { + static const std::array, 7> region_languages{{ + // JPN + {LANGUAGE_JP}, + // USA + {LANGUAGE_EN, LANGUAGE_FR, LANGUAGE_ES, LANGUAGE_PT}, + // EUR + {LANGUAGE_EN, LANGUAGE_FR, LANGUAGE_DE, LANGUAGE_IT, LANGUAGE_ES, LANGUAGE_NL, LANGUAGE_PT, + LANGUAGE_RU}, + // AUS + {LANGUAGE_EN, LANGUAGE_FR, LANGUAGE_DE, LANGUAGE_IT, LANGUAGE_ES, LANGUAGE_NL, LANGUAGE_PT, + LANGUAGE_RU}, + // CHN + {LANGUAGE_ZH}, + // KOR + {LANGUAGE_KO}, + // TWN + {LANGUAGE_TW}, + }}; + const auto& available = region_languages[region]; + if (std::find(available.begin(), available.end(), language) == available.end()) { + return available[0]; + } + return language; +} + ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) { void* pointer; CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag)); memcpy(output, pointer, size); + + // override the language setting if the region setting is auto + if (block_id == LanguageBlockID && + Settings::values.region_value == Settings::REGION_VALUE_AUTO_SELECT) { + u8 language; + memcpy(&language, output, sizeof(u8)); + language = AdjustLanguageInfoBlock(preferred_region_code, language); + memcpy(output, &language, sizeof(u8)); + } + return RESULT_SUCCESS; } @@ -533,10 +579,17 @@ void Init() { AddService(new CFG_U_Interface); LoadConfigNANDSaveFile(); + + preferred_region_code = 0; } void Shutdown() {} +void SetPreferredRegionCode(u32 region_code) { + preferred_region_code = region_code; + LOG_INFO(Service_CFG, "Preferred region code set to %u", preferred_region_code); +} + void SetUsername(const std::u16string& name) { ASSERT(name.size() <= 10); UsernameBlock block{}; diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index fb47c2aa5..618c9647e 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h @@ -282,6 +282,13 @@ void Init(); /// Shutdown the config service void Shutdown(); +/** + * Set the region code preferred by the game so that CFG will adjust to it when the region setting + * is auto. + * @param region_code the preferred region code to set + */ +void SetPreferredRegionCode(u32 region_code); + // Utilities for frontend to set config data. // Note: before calling these functions, LoadConfigNANDSaveFile should be called, // and UpdateConfigNANDSavegame should be called after making changes to config data. -- cgit v1.2.3