diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 011aada5ee..92fec9575b 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -387,7 +387,7 @@ bool BootCore(std::unique_ptr boot, const WindowSystemInfo& wsi) g_SRAM_netplay_initialized = false; } - // Override out-of-region languages to prevent games from crashing or behaving oddly + // Override out-of-region languages/countries to prevent games from crashing or behaving oddly if (!StartUp.bOverrideRegionSettings) { const int gc_language = @@ -399,6 +399,26 @@ bool BootCore(std::unique_ptr boot, const WindowSystemInfo& wsi) const u32 wii_language = static_cast(StartUp.GetLanguageAdjustedForRegion(true, StartUp.m_region)); Config::SetCurrent(Config::SYSCONF_LANGUAGE, wii_language); + + const u8 country_code = static_cast(Config::Get(Config::SYSCONF_COUNTRY)); + if (StartUp.m_region != DiscIO::SysConfCountryToRegion(country_code)) + { + switch (StartUp.m_region) + { + case DiscIO::Region::NTSC_J: + Config::SetCurrent(Config::SYSCONF_COUNTRY, 0x01); // Japan + break; + case DiscIO::Region::NTSC_U: + Config::SetCurrent(Config::SYSCONF_COUNTRY, 0x31); // United States + break; + case DiscIO::Region::PAL: + Config::SetCurrent(Config::SYSCONF_COUNTRY, 0x6c); // Switzerland + break; + case DiscIO::Region::NTSC_K: + Config::SetCurrent(Config::SYSCONF_COUNTRY, 0x88); // South Korea + break; + } + } } } diff --git a/Source/Core/Core/Config/SYSCONFSettings.cpp b/Source/Core/Core/Config/SYSCONFSettings.cpp index 636c84e525..a9eb811e24 100644 --- a/Source/Core/Core/Config/SYSCONFSettings.cpp +++ b/Source/Core/Core/Config/SYSCONFSettings.cpp @@ -10,6 +10,7 @@ namespace Config const ConfigInfo SYSCONF_SCREENSAVER{{System::SYSCONF, "IPL", "SSV"}, false}; const ConfigInfo SYSCONF_LANGUAGE{{System::SYSCONF, "IPL", "LNG"}, 0x01}; +const ConfigInfo SYSCONF_COUNTRY{{System::SYSCONF, "IPL", "SADR"}, 0x6c}; const ConfigInfo SYSCONF_WIDESCREEN{{System::SYSCONF, "IPL", "AR"}, true}; const ConfigInfo SYSCONF_PROGRESSIVE_SCAN{{System::SYSCONF, "IPL", "PGS"}, true}; const ConfigInfo SYSCONF_PAL60{{System::SYSCONF, "IPL", "E60"}, 0x01}; @@ -21,9 +22,10 @@ const ConfigInfo SYSCONF_SENSOR_BAR_SENSITIVITY{{System::SYSCONF, "BT", "SE const ConfigInfo SYSCONF_SPEAKER_VOLUME{{System::SYSCONF, "BT", "SPKV"}, 0x58}; const ConfigInfo SYSCONF_WIIMOTE_MOTOR{{System::SYSCONF, "BT", "MOT"}, true}; -const std::array SYSCONF_SETTINGS{ +const std::array SYSCONF_SETTINGS{ {{SYSCONF_SCREENSAVER, SysConf::Entry::Type::Byte}, {SYSCONF_LANGUAGE, SysConf::Entry::Type::Byte}, + {SYSCONF_COUNTRY, SysConf::Entry::Type::BigArray}, {SYSCONF_WIDESCREEN, SysConf::Entry::Type::Byte}, {SYSCONF_PROGRESSIVE_SCAN, SysConf::Entry::Type::Byte}, {SYSCONF_PAL60, SysConf::Entry::Type::Byte}, diff --git a/Source/Core/Core/Config/SYSCONFSettings.h b/Source/Core/Core/Config/SYSCONFSettings.h index 2d1dd78e12..1c6d8cd5f7 100644 --- a/Source/Core/Core/Config/SYSCONFSettings.h +++ b/Source/Core/Core/Config/SYSCONFSettings.h @@ -18,6 +18,7 @@ namespace Config extern const ConfigInfo SYSCONF_SCREENSAVER; extern const ConfigInfo SYSCONF_LANGUAGE; +extern const ConfigInfo SYSCONF_COUNTRY; extern const ConfigInfo SYSCONF_WIDESCREEN; extern const ConfigInfo SYSCONF_PROGRESSIVE_SCAN; extern const ConfigInfo SYSCONF_PAL60; @@ -35,6 +36,6 @@ struct SYSCONFSetting SysConf::Entry::Type type; }; -extern const std::array SYSCONF_SETTINGS; +extern const std::array SYSCONF_SETTINGS; } // namespace Config diff --git a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp index 5cfd42e7bc..4422a096a5 100644 --- a/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp @@ -4,6 +4,7 @@ #include "Core/ConfigLoaders/BaseConfigLoader.h" +#include #include #include #include @@ -43,9 +44,22 @@ void SaveToSYSCONF(Config::LayerType layer) const std::string key = info.location.section + "." + info.location.key; if (setting.type == SysConf::Entry::Type::Long) + { sysconf.SetData(key, setting.type, Config::Get(layer, info)); + } else if (setting.type == SysConf::Entry::Type::Byte) + { sysconf.SetData(key, setting.type, static_cast(Config::Get(layer, info))); + } + else if (setting.type == SysConf::Entry::Type::BigArray) + { + // Somewhat hacky support for IPL.SADR. The setting only stores the + // first 4 bytes even thought the SYSCONF entry is much bigger. + SysConf::Entry* entry = sysconf.GetOrAddEntry(key, setting.type); + if (entry->bytes.size() < 0x1007 + 1) + entry->bytes.resize(0x1007 + 1); + *reinterpret_cast(entry->bytes.data()) = Config::Get(layer, info); + } }, setting.config_info); } @@ -167,9 +181,26 @@ private: [&](auto& info) { const std::string key = info.location.section + "." + info.location.key; if (setting.type == SysConf::Entry::Type::Long) + { layer->Set(info.location, sysconf.GetData(key, info.default_value)); + } else if (setting.type == SysConf::Entry::Type::Byte) + { layer->Set(info.location, sysconf.GetData(key, info.default_value)); + } + else if (setting.type == SysConf::Entry::Type::BigArray) + { + // Somewhat hacky support for IPL.SADR. The setting only stores the + // first 4 bytes even thought the SYSCONF entry is much bigger. + u32 value = info.default_value; + SysConf::Entry* entry = sysconf.GetEntry(key); + if (entry) + { + std::memcpy(&value, entry->bytes.data(), + std::min(entry->bytes.size(), sizeof(u32))); + } + layer->Set(info.location, value); + } }, setting.config_info); } diff --git a/Source/Core/DiscIO/Enums.cpp b/Source/Core/DiscIO/Enums.cpp index f7069c0012..6847b4e44a 100644 --- a/Source/Core/DiscIO/Enums.cpp +++ b/Source/Core/DiscIO/Enums.cpp @@ -145,6 +145,29 @@ Country TypicalCountryForRegion(Region region) } } +Region SysConfCountryToRegion(u8 country_code) +{ + if (country_code == 0) + return Region::Unknown; + + if (country_code < 0x08) // Japan + return Region::NTSC_J; + + if (country_code < 0x40) // Americas + return Region::NTSC_U; + + if (country_code < 0x80) // Europe, Oceania, parts of Africa + return Region::PAL; + + if (country_code < 0xa8) // Southeast Asia + return country_code == 0x88 ? Region::NTSC_K : Region::NTSC_J; + + if (country_code < 0xc0) // Middle East + return Region::NTSC_U; + + return Region::Unknown; +} + Region CountryCodeToRegion(u8 country_code, Platform platform, Region expected_region, std::optional revision) { diff --git a/Source/Core/DiscIO/Enums.h b/Source/Core/DiscIO/Enums.h index 9b1425a14b..14940d92a8 100644 --- a/Source/Core/DiscIO/Enums.h +++ b/Source/Core/DiscIO/Enums.h @@ -77,6 +77,7 @@ bool IsWii(Platform volume_type); bool IsNTSC(Region region); Country TypicalCountryForRegion(Region region); +Region SysConfCountryToRegion(u8 country_code); // Avoid using this function if you can. Country codes aren't always reliable region indicators. Region CountryCodeToRegion(u8 country_code, Platform platform, Region expected_region = Region::Unknown,