Check that the country setting is valid for selected region (#847)

* Check that the country setting is valid for selected region

* `SystemSaveGame.checkCountryCompatibility` -> `SystemSaveGame.getCountryCompatibility`

* SettingsFragmentPresenter.kt: Moved `checkCountryCompatibility` definition out of `addSystemSettings`

* SettingsFragmentPresenter.kt: Renamed `compat` value to `compatFlags` for better readability

* configure_system.ui: Corrected indentation

---------

Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
This commit is contained in:
PabloMK7
2025-03-29 22:50:00 +01:00
committed by GitHub
parent eda2d6f9fa
commit 5c7622100b
16 changed files with 528 additions and 177 deletions

View File

@@ -86,30 +86,227 @@ static constexpr u16 C(const char code[2]) {
}
static const std::array<u16, 187> country_codes = {{
0, C("JP"), 0, 0, 0, 0, 0, 0, // 0-7
C("AI"), C("AG"), C("AR"), C("AW"), C("BS"), C("BB"), C("BZ"), C("BO"), // 8-15
C("BR"), C("VG"), C("CA"), C("KY"), C("CL"), C("CO"), C("CR"), C("DM"), // 16-23
C("DO"), C("EC"), C("SV"), C("GF"), C("GD"), C("GP"), C("GT"), C("GY"), // 24-31
C("HT"), C("HN"), C("JM"), C("MQ"), C("MX"), C("MS"), C("AN"), C("NI"), // 32-39
C("PA"), C("PY"), C("PE"), C("KN"), C("LC"), C("VC"), C("SR"), C("TT"), // 40-47
C("TC"), C("US"), C("UY"), C("VI"), C("VE"), 0, 0, 0, // 48-55
0, 0, 0, 0, 0, 0, 0, 0, // 56-63
C("AL"), C("AU"), C("AT"), C("BE"), C("BA"), C("BW"), C("BG"), C("HR"), // 64-71
C("CY"), C("CZ"), C("DK"), C("EE"), C("FI"), C("FR"), C("DE"), C("GR"), // 72-79
C("HU"), C("IS"), C("IE"), C("IT"), C("LV"), C("LS"), C("LI"), C("LT"), // 80-87
C("LU"), C("MK"), C("MT"), C("ME"), C("MZ"), C("NA"), C("NL"), C("NZ"), // 88-95
C("NO"), C("PL"), C("PT"), C("RO"), C("RU"), C("RS"), C("SK"), C("SI"), // 96-103
C("ZA"), C("ES"), C("SZ"), C("SE"), C("CH"), C("TR"), C("GB"), C("ZM"), // 104-111
C("ZW"), C("AZ"), C("MR"), C("ML"), C("NE"), C("TD"), C("SD"), C("ER"), // 112-119
C("DJ"), C("SO"), C("AD"), C("GI"), C("GG"), C("IM"), C("JE"), C("MC"), // 120-127
C("TW"), 0, 0, 0, 0, 0, 0, 0, // 128-135
C("KR"), 0, 0, 0, 0, 0, 0, 0, // 136-143
C("HK"), C("MO"), 0, 0, 0, 0, 0, 0, // 144-151
C("ID"), C("SG"), C("TH"), C("PH"), C("MY"), 0, 0, 0, // 152-159
C("CN"), 0, 0, 0, 0, 0, 0, 0, // 160-167
C("AE"), C("IN"), C("EG"), C("OM"), C("QA"), C("KW"), C("SA"), C("SY"), // 168-175
C("BH"), C("JO"), 0, 0, 0, 0, 0, 0, // 176-183
C("SM"), C("VA"), C("BM"), // 184-186
// 0-7 Japan
0,
C("JP"),
0,
0,
0,
0,
0,
0,
// 8-15 America
C("AI"),
C("AG"),
C("AR"),
C("AW"),
C("BS"),
C("BB"),
C("BZ"),
C("BO"),
// 16-23 America
C("BR"),
C("VG"),
C("CA"),
C("KY"),
C("CL"),
C("CO"),
C("CR"),
C("DM"),
// 24-31 America
C("DO"),
C("EC"),
C("SV"),
C("GF"),
C("GD"),
C("GP"),
C("GT"),
C("GY"),
// 32-39 America
C("HT"),
C("HN"),
C("JM"),
C("MQ"),
C("MX"),
C("MS"),
C("AN"),
C("NI"),
// 40-47 America
C("PA"),
C("PY"),
C("PE"),
C("KN"),
C("LC"),
C("VC"),
C("SR"),
C("TT"),
// 48-55 America
C("TC"),
C("US"),
C("UY"),
C("VI"),
C("VE"),
0,
0,
0,
// 56-63 Invalid
0,
0,
0,
0,
0,
0,
0,
0,
// 64-71 Europe
C("AL"),
C("AU"),
C("AT"),
C("BE"),
C("BA"),
C("BW"),
C("BG"),
C("HR"),
// 72-79 Europe
C("CY"),
C("CZ"),
C("DK"),
C("EE"),
C("FI"),
C("FR"),
C("DE"),
C("GR"),
// 80-87 Europe
C("HU"),
C("IS"),
C("IE"),
C("IT"),
C("LV"),
C("LS"),
C("LI"),
C("LT"),
// 88-95 Europe
C("LU"),
C("MK"),
C("MT"),
C("ME"),
C("MZ"),
C("NA"),
C("NL"),
C("NZ"),
// 96-103 Europe
C("NO"),
C("PL"),
C("PT"),
C("RO"),
C("RU"),
C("RS"),
C("SK"),
C("SI"),
// 104-111 Europe
C("ZA"),
C("ES"),
C("SZ"),
C("SE"),
C("CH"),
C("TR"),
C("GB"),
C("ZM"),
// 112-119 Europe
C("ZW"),
C("AZ"),
C("MR"),
C("ML"),
C("NE"),
C("TD"),
C("SD"),
C("ER"),
// 120-127 Europe
C("DJ"),
C("SO"),
C("AD"),
C("GI"),
C("GG"),
C("IM"),
C("JE"),
C("MC"),
// 128-135 Taiwan
C("TW"),
0,
0,
0,
0,
0,
0,
0,
// 136-143 Korea
C("KR"),
0,
0,
0,
0,
0,
0,
0,
// 144-151 China? (Hong Kong & Macao)
C("HK"),
C("MO"),
0,
0,
0,
0,
0,
0,
// 152-159 Southeast Asia
C("ID"),
C("SG"), // USA
C("TH"),
C("PH"),
C("MY"), // USA
0,
0,
0,
// 160-167 China
C("CN"),
0,
0,
0,
0,
0,
0,
0,
// 168-175 Middle East
C("AE"), // USA
C("IN"), // EUR
C("EG"),
C("OM"),
C("QA"),
C("KW"),
C("SA"), // USA
C("SY"),
// 176-183 Middle East
C("BH"),
C("JO"),
0,
0,
0,
0,
0,
0,
// 184-186 European Microstates
C("SM"),
C("VA"),
C("BM"),
}};
// Based on PKHeX's lists of subregions at
@@ -218,6 +415,29 @@ u32 Module::GetRegionValue(bool from_secure_info) {
return Settings::values.region_value.GetValue();
}
bool Module::IsValidRegionCountry(u32 region, u8 country_code) {
switch (region) {
case 0: // JPN
return country_code == 1;
case 1: // USA
return (country_code >= 8 && country_code <= 52) || country_code == 153 ||
country_code == 156 || country_code == 168 || country_code == 174;
case 2: // EUR
case 3: // AUS
return (country_code >= 64 && country_code <= 127) ||
(country_code >= 184 && country_code <= 186) || country_code == 169;
case 4: // CHN
return country_code == 144 || country_code == 145 || country_code == 160;
case 5: // KOR
return country_code == 136;
case 6: // TWN
return country_code == 128;
default:
break;
}
return false;
}
void Module::Interface::GetRegion(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);

View File

@@ -486,6 +486,8 @@ private:
public:
u32 GetRegionValue(bool from_secure_info);
static bool IsValidRegionCountry(u32 region, u8 country_code);
// Utilities for frontend to set config data.
// Note: UpdateConfigNANDSavegame should be called after making changes to config data.

View File

@@ -408,6 +408,7 @@ ResultStatus Apploader_Artic::Load(std::shared_ptr<Kernel::Process>& process) {
return ResultStatus::ErrorArtic;
}
auto cfg = system.ServiceManager().GetService<Service::CFG::CFG_U>("cfg:u");
// Request console unique data
for (int i = 0; i < 6; i++) {
std::string path;
@@ -471,7 +472,6 @@ ResultStatus Apploader_Artic::Load(std::shared_ptr<Kernel::Process>& process) {
memcpy(&console_id, resp_buff->first, sizeof(u64));
memcpy(&random_id, reinterpret_cast<u8*>(resp_buff->first) + sizeof(u64),
sizeof(u32));
auto cfg = system.ServiceManager().GetService<Service::CFG::CFG_U>("cfg:u");
if (cfg.get()) {
auto cfg_module = cfg->GetModule();
cfg_module->SetConsoleUniqueId(random_id, console_id);
@@ -480,7 +480,6 @@ ResultStatus Apploader_Artic::Load(std::shared_ptr<Kernel::Process>& process) {
} else if (i == 5) {
std::array<u8, 6> mac;
memcpy(mac.data(), resp_buff->first, mac.size());
auto cfg = system.ServiceManager().GetService<Service::CFG::CFG_U>("cfg:u");
if (cfg.get()) {
auto cfg_module = cfg->GetModule();
cfg_module->GetMacAddress() = Service::CFG::MacToString(mac);
@@ -494,10 +493,25 @@ ResultStatus Apploader_Artic::Load(std::shared_ptr<Kernel::Process>& process) {
if (!HW::UniqueData::GetCTCert().IsValid() || !HW::UniqueData::GetMovableSed().IsValid() ||
!HW::UniqueData::GetSecureInfoA().IsValid() ||
!HW::UniqueData::GetLocalFriendCodeSeedB().IsValid()) {
LOG_CRITICAL(Loader, "Some console unique data is invalid, aborting...");
client->LogOnServer(Network::ArticBaseCommon::LogOnServerType::LOG_ERROR,
"Some console unique data is invalid.\n Aborting...");
return ResultStatus::ErrorArtic;
}
if (cfg.get()) {
auto cfg_module = cfg->GetModule();
if (!Service::CFG::Module::IsValidRegionCountry(cfg_module->GetRegionValue(true),
cfg_module->GetCountryCode())) {
// Report mismatch to server.
client->LogOnServer(
Network::ArticBaseCommon::LogOnServerType::LOG_ERROR,
"The country configuration does not match\n the console region. "
"Please select a valid\n country from the emulation settings.");
return ResultStatus::ErrorArtic;
}
cfg_module->SetSystemSetupNeeded(false);
}
// Set deliver arg so that System Settings goes to the update screen directly
auto apt = Service::APT::GetModule(system);
Service::APT::DeliverArg arg;