|
@@ -115,6 +115,8 @@ static const std::vector<u8> cfg_system_savedata_id = {
|
|
|
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+static u32 preferred_region_code = 0;
|
|
|
|
|
+
|
|
|
void GetCountryCodeString(Service::Interface* self) {
|
|
void GetCountryCodeString(Service::Interface* self) {
|
|
|
u32* cmd_buff = Kernel::GetCommandBuffer();
|
|
u32* cmd_buff = Kernel::GetCommandBuffer();
|
|
|
u32 country_code_id = cmd_buff[1];
|
|
u32 country_code_id = cmd_buff[1];
|
|
@@ -160,11 +162,18 @@ void GetCountryCodeID(Service::Interface* self) {
|
|
|
cmd_buff[2] = country_code_id;
|
|
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) {
|
|
void SecureInfoGetRegion(Service::Interface* self) {
|
|
|
u32* cmd_buff = Kernel::GetCommandBuffer();
|
|
u32* cmd_buff = Kernel::GetCommandBuffer();
|
|
|
|
|
|
|
|
cmd_buff[1] = RESULT_SUCCESS.raw;
|
|
cmd_buff[1] = RESULT_SUCCESS.raw;
|
|
|
- cmd_buff[2] = Settings::values.region_value;
|
|
|
|
|
|
|
+ cmd_buff[2] = GetRegionValue();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void GenHashConsoleUnique(Service::Interface* self) {
|
|
void GenHashConsoleUnique(Service::Interface* self) {
|
|
@@ -184,7 +193,7 @@ void GetRegionCanadaUSA(Service::Interface* self) {
|
|
|
cmd_buff[1] = RESULT_SUCCESS.raw;
|
|
cmd_buff[1] = RESULT_SUCCESS.raw;
|
|
|
|
|
|
|
|
u8 canada_or_usa = 1;
|
|
u8 canada_or_usa = 1;
|
|
|
- if (canada_or_usa == Settings::values.region_value) {
|
|
|
|
|
|
|
+ if (canada_or_usa == GetRegionValue()) {
|
|
|
cmd_buff[2] = 1;
|
|
cmd_buff[2] = 1;
|
|
|
} else {
|
|
} else {
|
|
|
cmd_buff[2] = 0;
|
|
cmd_buff[2] = 0;
|
|
@@ -314,10 +323,47 @@ static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 fl
|
|
|
return MakeResult<void*>(pointer);
|
|
return MakeResult<void*>(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<std::vector<u8>, 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) {
|
|
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) {
|
|
|
void* pointer;
|
|
void* pointer;
|
|
|
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
|
|
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
|
|
|
memcpy(output, pointer, size);
|
|
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;
|
|
return RESULT_SUCCESS;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -535,10 +581,17 @@ void Init() {
|
|
|
AddService(new CFG_U);
|
|
AddService(new CFG_U);
|
|
|
|
|
|
|
|
LoadConfigNANDSaveFile();
|
|
LoadConfigNANDSaveFile();
|
|
|
|
|
+
|
|
|
|
|
+ preferred_region_code = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Shutdown() {}
|
|
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) {
|
|
void SetUsername(const std::u16string& name) {
|
|
|
ASSERT(name.size() <= 10);
|
|
ASSERT(name.size() <= 10);
|
|
|
UsernameBlock block{};
|
|
UsernameBlock block{};
|