loader, cfg: choose region based on language if multiple regions available

master
Weiyi Wang 2018-09-17 11:41:33 +07:00
parent 2ba62ec196
commit 697bc1a9c7
3 changed files with 28 additions and 17 deletions

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <tuple>
#include <cryptopp/osrng.h>
#include <cryptopp/sha.h>
#include "common/file_util.h"
@ -571,7 +572,8 @@ Module::Module() {
Module::~Module() = default;
/// Checks if the language is available in the chosen region, and returns a proper one
static SystemLanguage AdjustLanguageInfoBlock(u32 region, SystemLanguage language) {
static std::tuple<u32 /*region*/, SystemLanguage> AdjustLanguageInfoBlock(
const std::vector<u32>& region_code, SystemLanguage language) {
static const std::array<std::vector<SystemLanguage>, 7> region_languages{{
// JPN
{LANGUAGE_JP},
@ -590,21 +592,28 @@ static SystemLanguage AdjustLanguageInfoBlock(u32 region, SystemLanguage languag
// TWN
{LANGUAGE_TW},
}};
const auto& available = region_languages[region];
if (std::find(available.begin(), available.end(), language) == available.end()) {
return available[0];
// Check if any available region supports the languages
for (u32 region : region_code) {
const auto& available = region_languages[region];
if (std::find(available.begin(), available.end(), language) != available.end()) {
// found a proper region, so return this region - language pair
return {region, language};
}
}
return language;
// The language is not available in any available region, so default to the first region and
// language
u32 default_region = region_code[0];
return {default_region, region_languages[default_region][0]};
}
void Module::SetPreferredRegionCode(u32 region_code) {
preferred_region_code = region_code;
void Module::SetPreferredRegionCodes(const std::vector<u32>& region_codes) {
const SystemLanguage current_language = GetSystemLanguage();
auto [region, adjusted_language] = AdjustLanguageInfoBlock(region_codes, current_language);
preferred_region_code = region;
LOG_INFO(Service_CFG, "Preferred region code set to {}", preferred_region_code);
if (Settings::values.region_value == Settings::REGION_VALUE_AUTO_SELECT) {
const SystemLanguage current_language = GetSystemLanguage();
const SystemLanguage adjusted_language =
AdjustLanguageInfoBlock(region_code, current_language);
if (current_language != adjusted_language) {
LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}",
static_cast<int>(current_language), static_cast<int>(adjusted_language));

@ -7,6 +7,7 @@
#include <array>
#include <memory>
#include <string>
#include <vector>
#include "common/common_types.h"
#include "core/hle/service/fs/archive.h"
@ -298,12 +299,11 @@ public:
u32 GetRegionValue();
/**
* 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
* Set the region codes preferred by the game so that CFG will adjust to it when the region
* setting is auto.
* @param region_codes the preferred region codes to set
*/
void SetPreferredRegionCode(u32 region_code);
void SetPreferredRegionCodes(const std::vector<u32>& region_codes);
// Utilities for frontend to set config data.
// Note: UpdateConfigNANDSavegame should be called after making changes to config data.

@ -8,6 +8,7 @@
#include <cstring>
#include <locale>
#include <memory>
#include <vector>
#include <fmt/format.h>
#include "common/logging/log.h"
#include "common/string_util.h"
@ -136,13 +137,14 @@ void AppLoader_NCCH::ParseRegionLockoutInfo() {
memcpy(&smdh, smdh_buffer.data(), sizeof(SMDH));
u32 region_lockout = smdh.region_lockout;
constexpr u32 REGION_COUNT = 7;
std::vector<u32> regions;
for (u32 region = 0; region < REGION_COUNT; ++region) {
if (region_lockout & 1) {
Service::CFG::GetCurrentModule()->SetPreferredRegionCode(region);
break;
regions.push_back(region);
}
region_lockout >>= 1;
}
Service::CFG::GetCurrentModule()->SetPreferredRegionCodes(regions);
}
}