diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java index f150d44ff3..0b90325035 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java @@ -218,6 +218,7 @@ public final class SettingsFragmentPresenter Setting overclock = null; Setting speedLimit = null; Setting audioStretch = null; + Setting overrideRegionSettings = null; Setting autoDiscChange = null; Setting analytics = null; Setting enableSaveState; @@ -231,6 +232,7 @@ public final class SettingsFragmentPresenter overclock = coreSection.getSetting(SettingsFile.KEY_OVERCLOCK_PERCENT); speedLimit = coreSection.getSetting(SettingsFile.KEY_SPEED_LIMIT); audioStretch = coreSection.getSetting(SettingsFile.KEY_AUDIO_STRETCH); + overrideRegionSettings = coreSection.getSetting(SettingsFile.KEY_OVERRIDE_REGION_SETTINGS); autoDiscChange = coreSection.getSetting(SettingsFile.KEY_AUTO_DISC_CHANGE); analytics = analyticsSection.getSetting(SettingsFile.KEY_ANALYTICS_ENABLED); enableSaveState = coreSection.getSetting(SettingsFile.KEY_ENABLE_SAVE_STATES); @@ -271,6 +273,9 @@ public final class SettingsFragmentPresenter R.string.speed_limit, 0, 200, "%", 100, speedLimit)); sl.add(new CheckBoxSetting(SettingsFile.KEY_AUDIO_STRETCH, Settings.SECTION_INI_CORE, R.string.audio_stretch, R.string.audio_stretch_description, false, audioStretch)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_OVERRIDE_REGION_SETTINGS, + Settings.SECTION_INI_CORE, R.string.override_region_settings, 0, false, + overrideRegionSettings)); sl.add(new CheckBoxSetting(SettingsFile.KEY_AUTO_DISC_CHANGE, Settings.SECTION_INI_CORE, R.string.auto_disc_change, 0, false, autoDiscChange)); sl.add(new CheckBoxSetting(SettingsFile.KEY_ENABLE_SAVE_STATES, Settings.SECTION_INI_CORE, @@ -306,22 +311,17 @@ public final class SettingsFragmentPresenter private void addGameCubeSettings(ArrayList sl) { Setting systemLanguage = null; - Setting overrideGCLanguage = null; Setting slotADevice = null; Setting slotBDevice = null; SettingSection coreSection = mSettings.getSection(Settings.SECTION_INI_CORE); systemLanguage = coreSection.getSetting(SettingsFile.KEY_GAME_CUBE_LANGUAGE); - overrideGCLanguage = coreSection.getSetting(SettingsFile.KEY_OVERRIDE_GAME_CUBE_LANGUAGE); slotADevice = coreSection.getSetting(SettingsFile.KEY_SLOT_A_DEVICE); slotBDevice = coreSection.getSetting(SettingsFile.KEY_SLOT_B_DEVICE); sl.add(new SingleChoiceSetting(SettingsFile.KEY_GAME_CUBE_LANGUAGE, Settings.SECTION_INI_CORE, R.string.gamecube_system_language, 0, R.array.gameCubeSystemLanguageEntries, R.array.gameCubeSystemLanguageValues, 0, systemLanguage)); - sl.add(new CheckBoxSetting(SettingsFile.KEY_OVERRIDE_GAME_CUBE_LANGUAGE, - Settings.SECTION_INI_CORE, R.string.override_gamecube_language, 0, false, - overrideGCLanguage)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_SLOT_A_DEVICE, Settings.SECTION_INI_CORE, R.string.slot_a_device, 0, R.array.slotDeviceEntries, R.array.slotDeviceValues, 8, slotADevice)); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java index 54640a3710..aac139266f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java @@ -48,7 +48,7 @@ public final class SettingsFile public static final String KEY_AUDIO_STRETCH = "AudioStretch"; public static final String KEY_AUTO_DISC_CHANGE = "AutoDiscChange"; public static final String KEY_GAME_CUBE_LANGUAGE = "SelectedLanguage"; - public static final String KEY_OVERRIDE_GAME_CUBE_LANGUAGE = "OverrideGCLang"; + public static final String KEY_OVERRIDE_REGION_SETTINGS = "OverrideRegionSettings"; public static final String KEY_SLOT_A_DEVICE = "SlotA"; public static final String KEY_SLOT_B_DEVICE = "SlotB"; public static final String KEY_ENABLE_SAVE_STATES = "EnableSaveStates"; diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index c74d6aebf3..a853a9f705 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -126,7 +126,6 @@ WARNING: Changing this from the default (100%) WILL break games and cause glitches. Please do not report bugs that occur with a non-default clock. GameCube System Language - Override Language on NTSC games GameCube Slot A Device GameCube Slot B Device Wii @@ -136,6 +135,7 @@ Enable sound output through the speaker on a real Wiimote (DolphinBar required). Audio Stretching Stretches audio to reduce stuttering. Increases latency. + Allow Mismatched Region Settings Change Discs Automatically Enable Savestates WARNING: Savestates may not be compatible with future versions of Dolphin and can make it impossible to create normal saves in some cases. Never use savestates as the only way of saving your progress. diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index f62882e773..92fec9575b 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -356,7 +356,7 @@ bool BootCore(std::unique_ptr boot, const WindowSystemInfo& wsi) StartUp.bCopyWiiSaveNetplay = netplay_settings.m_CopyWiiSave; StartUp.cpu_core = netplay_settings.m_CPUcore; StartUp.SelectedLanguage = netplay_settings.m_SelectedLanguage; - StartUp.bOverrideGCLanguage = netplay_settings.m_OverrideGCLanguage; + StartUp.bOverrideRegionSettings = netplay_settings.m_OverrideRegionSettings; StartUp.m_DSPEnableJIT = netplay_settings.m_DSPEnableJIT; StartUp.m_OCEnable = netplay_settings.m_OCEnable; StartUp.m_OCFactor = netplay_settings.m_OCFactor; @@ -387,19 +387,44 @@ bool BootCore(std::unique_ptr boot, const WindowSystemInfo& wsi) g_SRAM_netplay_initialized = false; } - const bool ntsc = DiscIO::IsNTSC(StartUp.m_region); - - // Apply overrides - // Some NTSC GameCube games such as Baten Kaitos react strangely to - // language settings that would be invalid on an NTSC system - if (!StartUp.bOverrideGCLanguage && ntsc) + // Override out-of-region languages/countries to prevent games from crashing or behaving oddly + if (!StartUp.bOverrideRegionSettings) { - StartUp.SelectedLanguage = 0; + const int gc_language = + static_cast(StartUp.GetLanguageAdjustedForRegion(false, StartUp.m_region)); + StartUp.SelectedLanguage = gc_language - (gc_language > 0); + + if (StartUp.bWii) + { + 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; + } + } + } } // Some NTSC Wii games such as Doc Louis's Punch-Out!! and // 1942 (Virtual Console) crash if the PAL60 option is enabled - if (StartUp.bWii && ntsc) + if (StartUp.bWii && DiscIO::IsNTSC(StartUp.m_region)) Config::SetCurrent(Config::SYSCONF_PAL60, false); // Ensure any new settings are written to the SYSCONF diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index 4176500314..55739e0c38 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -28,7 +28,8 @@ const ConfigInfo MAIN_SYNC_ON_SKIP_IDLE{{System::Main, "Core", "SyncOnSkip const ConfigInfo MAIN_DEFAULT_ISO{{System::Main, "Core", "DefaultISO"}, ""}; const ConfigInfo MAIN_ENABLE_CHEATS{{System::Main, "Core", "EnableCheats"}, false}; const ConfigInfo MAIN_GC_LANGUAGE{{System::Main, "Core", "SelectedLanguage"}, 0}; -const ConfigInfo MAIN_OVERRIDE_GC_LANGUAGE{{System::Main, "Core", "OverrideGCLang"}, false}; +const ConfigInfo MAIN_OVERRIDE_REGION_SETTINGS{ + {System::Main, "Core", "OverrideRegionSettings"}, false}; const ConfigInfo MAIN_DPL2_DECODER{{System::Main, "Core", "DPL2Decoder"}, false}; const ConfigInfo MAIN_AUDIO_LATENCY{{System::Main, "Core", "AudioLatency"}, 20}; const ConfigInfo MAIN_AUDIO_STRETCH{{System::Main, "Core", "AudioStretch"}, false}; diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index f0726b550f..88d10d101d 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -30,7 +30,7 @@ extern const ConfigInfo MAIN_SYNC_ON_SKIP_IDLE; extern const ConfigInfo MAIN_DEFAULT_ISO; extern const ConfigInfo MAIN_ENABLE_CHEATS; extern const ConfigInfo MAIN_GC_LANGUAGE; -extern const ConfigInfo MAIN_OVERRIDE_GC_LANGUAGE; +extern const ConfigInfo MAIN_OVERRIDE_REGION_SETTINGS; extern const ConfigInfo MAIN_DPL2_DECODER; extern const ConfigInfo MAIN_AUDIO_LATENCY; extern const ConfigInfo MAIN_AUDIO_STRETCH; 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/Core/ConfigLoaders/NetPlayConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp index c101cad865..c15dbb0c18 100644 --- a/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp +++ b/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp @@ -29,7 +29,7 @@ public: layer->Set(Config::MAIN_CPU_THREAD, m_settings.m_CPUthread); layer->Set(Config::MAIN_CPU_CORE, m_settings.m_CPUcore); layer->Set(Config::MAIN_GC_LANGUAGE, m_settings.m_SelectedLanguage); - layer->Set(Config::MAIN_OVERRIDE_GC_LANGUAGE, m_settings.m_OverrideGCLanguage); + layer->Set(Config::MAIN_OVERRIDE_REGION_SETTINGS, m_settings.m_OverrideRegionSettings); layer->Set(Config::MAIN_DSP_HLE, m_settings.m_DSPHLE); layer->Set(Config::MAIN_OVERCLOCK_ENABLE, m_settings.m_OCEnable); layer->Set(Config::MAIN_OVERCLOCK, m_settings.m_OCFactor); diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index e1a1eb6ef9..3ef072a955 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -211,7 +211,7 @@ void SConfig::SaveCoreSettings(IniFile& ini) core->Set("AccurateNaNs", bAccurateNaNs); core->Set("EnableCheats", bEnableCheats); core->Set("SelectedLanguage", SelectedLanguage); - core->Set("OverrideGCLang", bOverrideGCLanguage); + core->Set("OverrideRegionSettings", bOverrideRegionSettings); core->Set("DPL2Decoder", bDPL2Decoder); core->Set("AudioLatency", iLatency); core->Set("AudioStretch", m_audio_stretch); @@ -486,7 +486,7 @@ void SConfig::LoadCoreSettings(IniFile& ini) core->Get("SyncOnSkipIdle", &bSyncGPUOnSkipIdleHack, true); core->Get("EnableCheats", &bEnableCheats, false); core->Get("SelectedLanguage", &SelectedLanguage, 0); - core->Get("OverrideGCLang", &bOverrideGCLanguage, false); + core->Get("OverrideRegionSettings", &bOverrideRegionSettings, false); core->Get("DPL2Decoder", &bDPL2Decoder, false); core->Get("AudioLatency", &iLatency, 20); core->Get("AudioStretch", &m_audio_stretch, false); @@ -650,7 +650,7 @@ void SConfig::LoadJitDebugSettings(IniFile& ini) void SConfig::ResetRunningGameMetadata() { - SetRunningGameMetadata("00000000", "", 0, 0, DiscIO::Country::Unknown); + SetRunningGameMetadata("00000000", "", 0, 0, DiscIO::Region::Unknown); } void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume, @@ -660,13 +660,13 @@ void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume, { SetRunningGameMetadata(volume.GetGameID(), volume.GetGameTDBID(), volume.GetTitleID().value_or(0), volume.GetRevision().value_or(0), - volume.GetCountry()); + volume.GetRegion()); } else { SetRunningGameMetadata(volume.GetGameID(partition), volume.GetGameTDBID(), volume.GetTitleID(partition).value_or(0), - volume.GetRevision(partition).value_or(0), volume.GetCountry()); + volume.GetRevision(partition).value_or(0), volume.GetRegion()); } } @@ -682,15 +682,13 @@ void SConfig::SetRunningGameMetadata(const IOS::ES::TMDReader& tmd, DiscIO::Plat !DVDInterface::UpdateRunningGameMetadata(tmd_title_id)) { // If not launching a disc game, just read everything from the TMD. - const DiscIO::Country country = DiscIO::CountryCodeToCountry( - static_cast(tmd_title_id), platform, tmd.GetRegion(), tmd.GetTitleVersion()); SetRunningGameMetadata(tmd.GetGameID(), tmd.GetGameTDBID(), tmd_title_id, tmd.GetTitleVersion(), - country); + tmd.GetRegion()); } } void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::string& gametdb_id, - u64 title_id, u16 revision, DiscIO::Country country) + u64 title_id, u16 revision, DiscIO::Region region) { const bool was_changed = m_game_id != game_id || m_gametdb_id != gametdb_id || m_title_id != title_id || m_revision != revision; @@ -723,9 +721,7 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::stri } const Core::TitleDatabase title_database; - const DiscIO::Language language = !bWii && country == DiscIO::Country::Japan ? - DiscIO::Language::Japanese : - GetCurrentLanguage(bWii); + const DiscIO::Language language = GetLanguageAdjustedForRegion(bWii, region); m_title_description = title_database.Describe(m_gametdb_id, language); NOTICE_LOG(CORE, "Active title: %s", m_title_description.c_str()); Host_TitleChanged(); @@ -782,7 +778,7 @@ void SConfig::LoadDefaults() bFastDiscSpeed = false; bEnableMemcardSdWriting = true; SelectedLanguage = 0; - bOverrideGCLanguage = false; + bOverrideRegionSettings = false; bWii = false; bDPL2Decoder = false; iLatency = 20; @@ -995,6 +991,40 @@ DiscIO::Language SConfig::GetCurrentLanguage(bool wii) const return language; } +DiscIO::Language SConfig::GetLanguageAdjustedForRegion(bool wii, DiscIO::Region region) const +{ + const DiscIO::Language language = GetCurrentLanguage(wii); + + if (!wii && region == DiscIO::Region::NTSC_K) + region = DiscIO::Region::NTSC_J; // NTSC-K only exists on Wii, so use a fallback + + if (!wii && region == DiscIO::Region::NTSC_J && language == DiscIO::Language::English) + return DiscIO::Language::Japanese; // English and Japanese both use the value 0 in GC SRAM + + if (!bOverrideRegionSettings) + { + if (region == DiscIO::Region::NTSC_J) + return DiscIO::Language::Japanese; + + if (region == DiscIO::Region::NTSC_U && language != DiscIO::Language::English && + (!wii || (language != DiscIO::Language::French && language != DiscIO::Language::Spanish))) + { + return DiscIO::Language::English; + } + + if (region == DiscIO::Region::PAL && + (language < DiscIO::Language::English || language > DiscIO::Language::Dutch)) + { + return DiscIO::Language::English; + } + + if (region == DiscIO::Region::NTSC_K) + return DiscIO::Language::Korean; + } + + return language; +} + IniFile SConfig::LoadDefaultGameIni() const { return LoadDefaultGameIni(GetGameID(), m_revision); diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index d50a9b2223..e9e9d43bef 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -18,7 +18,6 @@ class IniFile; namespace DiscIO { -enum class Country; enum class Language; enum class Platform; enum class Region; @@ -141,7 +140,7 @@ struct SConfig float fSyncGpuOverclock; int SelectedLanguage = 0; - bool bOverrideGCLanguage = false; + bool bOverrideRegionSettings = false; bool bWii = false; bool m_is_mios = false; @@ -212,6 +211,7 @@ struct SConfig bool SetPathsAndGameMetadata(const BootParameters& boot); static DiscIO::Region GetFallbackRegion(); DiscIO::Language GetCurrentLanguage(bool wii) const; + DiscIO::Language GetLanguageAdjustedForRegion(bool wii, DiscIO::Region region) const; IniFile LoadDefaultGameIni() const; IniFile LoadLocalGameIni() const; @@ -365,7 +365,7 @@ private: void LoadJitDebugSettings(IniFile& ini); void SetRunningGameMetadata(const std::string& game_id, const std::string& gametdb_id, - u64 title_id, u16 revision, DiscIO::Country country); + u64 title_id, u16 revision, DiscIO::Region region); static SConfig* m_Instance; diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 40b4f1703a..f7849fc547 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -631,7 +631,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) packet >> m_net_settings.m_EnableCheats; packet >> m_net_settings.m_SelectedLanguage; - packet >> m_net_settings.m_OverrideGCLanguage; + packet >> m_net_settings.m_OverrideRegionSettings; packet >> m_net_settings.m_ProgressiveScan; packet >> m_net_settings.m_PAL60; packet >> m_net_settings.m_DSPEnableJIT; diff --git a/Source/Core/Core/NetPlayProto.h b/Source/Core/Core/NetPlayProto.h index 1b94f4614b..cb8760c730 100644 --- a/Source/Core/Core/NetPlayProto.h +++ b/Source/Core/Core/NetPlayProto.h @@ -26,7 +26,7 @@ struct NetSettings PowerPC::CPUCore m_CPUcore; bool m_EnableCheats; int m_SelectedLanguage; - bool m_OverrideGCLanguage; + bool m_OverrideRegionSettings; bool m_ProgressiveScan; bool m_PAL60; bool m_DSPHLE; diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index 1169740ec2..329c58b49f 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -1279,7 +1279,7 @@ bool NetPlayServer::StartGame() spac << static_cast>(m_settings.m_CPUcore); spac << m_settings.m_EnableCheats; spac << m_settings.m_SelectedLanguage; - spac << m_settings.m_OverrideGCLanguage; + spac << m_settings.m_OverrideRegionSettings; spac << m_settings.m_ProgressiveScan; spac << m_settings.m_PAL60; spac << m_settings.m_DSPEnableJIT; 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, diff --git a/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp b/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp index 69d01a94a4..2c64f31d6e 100644 --- a/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp +++ b/Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp @@ -443,7 +443,7 @@ void NetPlayDialog::OnStart() settings.m_CPUcore = Config::Get(Config::MAIN_CPU_CORE); settings.m_EnableCheats = Config::Get(Config::MAIN_ENABLE_CHEATS); settings.m_SelectedLanguage = Config::Get(Config::MAIN_GC_LANGUAGE); - settings.m_OverrideGCLanguage = Config::Get(Config::MAIN_OVERRIDE_GC_LANGUAGE); + settings.m_OverrideRegionSettings = Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS); settings.m_ProgressiveScan = Config::Get(Config::SYSCONF_PROGRESSIVE_SCAN); settings.m_PAL60 = Config::Get(Config::SYSCONF_PAL60); settings.m_DSPHLE = Config::Get(Config::MAIN_DSP_HLE); diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.cpp b/Source/Core/DolphinQt/Settings/GameCubePane.cpp index 95e94e8287..b0cfab9999 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.cpp +++ b/Source/Core/DolphinQt/Settings/GameCubePane.cpp @@ -56,7 +56,6 @@ void GameCubePane::CreateWidgets() ipl_box->setLayout(ipl_layout); m_skip_main_menu = new QCheckBox(tr("Skip Main Menu"), ipl_box); - m_override_language_ntsc = new QCheckBox(tr("Override Language on NTSC Games"), ipl_box); m_language_combo = new QComboBox(ipl_box); m_language_combo->setCurrentIndex(-1); @@ -71,7 +70,6 @@ void GameCubePane::CreateWidgets() ipl_layout->addWidget(m_skip_main_menu, 0, 0); ipl_layout->addWidget(new QLabel(tr("System Language:")), 1, 0); ipl_layout->addWidget(m_language_combo, 1, 1); - ipl_layout->addWidget(m_override_language_ntsc, 2, 0); // Device Settings QGroupBox* device_box = new QGroupBox(tr("Device Settings"), this); @@ -134,7 +132,6 @@ void GameCubePane::ConnectWidgets() connect(m_skip_main_menu, &QCheckBox::stateChanged, this, &GameCubePane::SaveSettings); connect(m_language_combo, QOverload::of(&QComboBox::currentIndexChanged), this, &GameCubePane::SaveSettings); - connect(m_override_language_ntsc, &QCheckBox::stateChanged, this, &GameCubePane::SaveSettings); // Device Settings for (int i = 0; i < SLOT_COUNT; i++) @@ -302,7 +299,6 @@ void GameCubePane::LoadSettings() // IPL Settings m_skip_main_menu->setChecked(params.bHLE_BS2); m_language_combo->setCurrentIndex(m_language_combo->findData(params.SelectedLanguage)); - m_override_language_ntsc->setChecked(params.bOverrideGCLanguage); bool have_menu = false; @@ -343,9 +339,6 @@ void GameCubePane::SaveSettings() Config::SetBaseOrCurrent(Config::MAIN_SKIP_IPL, m_skip_main_menu->isChecked()); params.SelectedLanguage = m_language_combo->currentData().toInt(); Config::SetBaseOrCurrent(Config::MAIN_GC_LANGUAGE, m_language_combo->currentData().toInt()); - params.bOverrideGCLanguage = m_override_language_ntsc->isChecked(); - Config::SetBaseOrCurrent(Config::MAIN_OVERRIDE_GC_LANGUAGE, - m_override_language_ntsc->isChecked()); for (int i = 0; i < SLOT_COUNT; i++) { diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.h b/Source/Core/DolphinQt/Settings/GameCubePane.h index 3b4df87a89..554670904b 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.h +++ b/Source/Core/DolphinQt/Settings/GameCubePane.h @@ -27,7 +27,6 @@ private: void OnConfigPressed(int slot); QCheckBox* m_skip_main_menu; - QCheckBox* m_override_language_ntsc; QComboBox* m_language_combo; QPushButton* m_slot_buttons[3]; diff --git a/Source/Core/DolphinQt/Settings/GeneralPane.cpp b/Source/Core/DolphinQt/Settings/GeneralPane.cpp index 77d51571b5..2bed590f8b 100644 --- a/Source/Core/DolphinQt/Settings/GeneralPane.cpp +++ b/Source/Core/DolphinQt/Settings/GeneralPane.cpp @@ -84,6 +84,7 @@ void GeneralPane::OnEmulationStateChanged(Core::State state) m_checkbox_dualcore->setEnabled(!running); m_checkbox_cheats->setEnabled(!running); + m_checkbox_override_region_settings->setEnabled(!running); #ifdef USE_DISCORD_PRESENCE m_checkbox_discord_presence->setEnabled(!running); #endif @@ -96,6 +97,8 @@ void GeneralPane::ConnectLayout() { connect(m_checkbox_dualcore, &QCheckBox::toggled, this, &GeneralPane::OnSaveConfig); connect(m_checkbox_cheats, &QCheckBox::toggled, this, &GeneralPane::OnSaveConfig); + connect(m_checkbox_override_region_settings, &QCheckBox::stateChanged, this, + &GeneralPane::OnSaveConfig); connect(m_checkbox_auto_disc_change, &QCheckBox::toggled, this, &GeneralPane::OnSaveConfig); #ifdef USE_DISCORD_PRESENCE connect(m_checkbox_discord_presence, &QCheckBox::toggled, this, &GeneralPane::OnSaveConfig); @@ -138,6 +141,9 @@ void GeneralPane::CreateBasic() m_checkbox_cheats = new QCheckBox(tr("Enable Cheats")); basic_group_layout->addWidget(m_checkbox_cheats); + m_checkbox_override_region_settings = new QCheckBox(tr("Allow Mismatched Region Settings")); + basic_group_layout->addWidget(m_checkbox_override_region_settings); + m_checkbox_auto_disc_change = new QCheckBox(tr("Change Discs Automatically")); basic_group_layout->addWidget(m_checkbox_auto_disc_change); @@ -243,6 +249,7 @@ void GeneralPane::LoadConfig() #endif m_checkbox_dualcore->setChecked(SConfig::GetInstance().bCPUThread); m_checkbox_cheats->setChecked(Settings::Instance().GetCheatsEnabled()); + m_checkbox_override_region_settings->setChecked(SConfig::GetInstance().bOverrideRegionSettings); m_checkbox_auto_disc_change->setChecked(Config::Get(Config::MAIN_AUTO_DISC_CHANGE)); #ifdef USE_DISCORD_PRESENCE m_checkbox_discord_presence->setChecked(Config::Get(Config::MAIN_USE_DISCORD_PRESENCE)); @@ -305,6 +312,9 @@ void GeneralPane::OnSaveConfig() settings.bCPUThread = m_checkbox_dualcore->isChecked(); Config::SetBaseOrCurrent(Config::MAIN_CPU_THREAD, m_checkbox_dualcore->isChecked()); Settings::Instance().SetCheatsEnabled(m_checkbox_cheats->isChecked()); + settings.bOverrideRegionSettings = m_checkbox_override_region_settings->isChecked(); + Config::SetBaseOrCurrent(Config::MAIN_OVERRIDE_REGION_SETTINGS, + m_checkbox_override_region_settings->isChecked()); Config::SetBase(Config::MAIN_AUTO_DISC_CHANGE, m_checkbox_auto_disc_change->isChecked()); Config::SetBaseOrCurrent(Config::MAIN_ENABLE_CHEATS, m_checkbox_cheats->isChecked()); settings.m_EmulationSpeed = m_combobox_speedlimit->currentIndex() * 0.1f; diff --git a/Source/Core/DolphinQt/Settings/GeneralPane.h b/Source/Core/DolphinQt/Settings/GeneralPane.h index 9ae0d48893..6aa9fc1e1a 100644 --- a/Source/Core/DolphinQt/Settings/GeneralPane.h +++ b/Source/Core/DolphinQt/Settings/GeneralPane.h @@ -44,6 +44,7 @@ private: QComboBox* m_combobox_update_track; QCheckBox* m_checkbox_dualcore; QCheckBox* m_checkbox_cheats; + QCheckBox* m_checkbox_override_region_settings; QCheckBox* m_checkbox_auto_disc_change; #ifdef USE_DISCORD_PRESENCE QCheckBox* m_checkbox_discord_presence; diff --git a/Source/Core/UICommon/GameFile.cpp b/Source/Core/UICommon/GameFile.cpp index 5431face3a..89d38e24f5 100644 --- a/Source/Core/UICommon/GameFile.cpp +++ b/Source/Core/UICommon/GameFile.cpp @@ -61,15 +61,12 @@ bool UseGameCovers() DiscIO::Language GameFile::GetConfigLanguage() const { - if (m_platform == DiscIO::Platform::GameCubeDisc && m_country == DiscIO::Country::Japan) - return DiscIO::Language::Japanese; - #ifdef ANDROID // TODO: Make the Android app load the config at app start instead of emulation start // so that we can access the user's preference here return DiscIO::Language::English; #else - return SConfig::GetInstance().GetCurrentLanguage(DiscIO::IsWii(m_platform)); + return SConfig::GetInstance().GetLanguageAdjustedForRegion(DiscIO::IsWii(m_platform), m_region); #endif }