From db5aec019ca08dc04f57866118a9afb67d038357 Mon Sep 17 00:00:00 2001 From: Vincent Cunningham Date: Sat, 28 Nov 2020 15:09:37 -0500 Subject: [PATCH] Add Fallback Region to configuration menu Fallback Region A user-selected fallback to use instead of the default PAL This is used for unknown region or region free titles to give them the ability to force region to use. This replaces the current fallback region of PAL. This can be useful if a user is trying to play a region free tilte that is originally NTSC and expects to be run at NTSC speeds. This may be done when a user attempts to dump a WAD of their own without understanding the settings they have chosen, or could be an intentional decision by a developer of a ROM hack that can be injected into a Virtual Console WAD. Remove using System Menu region being checked in GetFallbackRegion Use DiscIO::Region instead of std::String for fallback Add explanation text for Fallback Region --- Source/Core/Core/Config/MainSettings.cpp | 3 + Source/Core/Core/Config/MainSettings.h | 2 + .../Core/ConfigLoaders/IsSettingSaveable.cpp | 3 +- Source/Core/Core/ConfigManager.cpp | 14 +--- Source/Core/DolphinQt/Settings.cpp | 15 ++++ Source/Core/DolphinQt/Settings.h | 7 ++ .../Core/DolphinQt/Settings/GeneralPane.cpp | 79 +++++++++++++++++++ Source/Core/DolphinQt/Settings/GeneralPane.h | 2 + 8 files changed, 112 insertions(+), 13 deletions(-) diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index 6715a2a877..e350bb4e62 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -12,6 +12,7 @@ #include "Core/HW/Memmap.h" #include "Core/HW/SI/SI_Device.h" #include "Core/PowerPC/PowerPC.h" +#include "DiscIO/Enums.h" #include "VideoCommon/VideoBackendBase.h" namespace Config @@ -106,6 +107,8 @@ const Info MAIN_PERF_MAP_DIR{{System::Main, "Core", "PerfMapDir"}, const Info MAIN_CUSTOM_RTC_ENABLE{{System::Main, "Core", "EnableCustomRTC"}, false}; // Default to seconds between 1.1.1970 and 1.1.2000 const Info MAIN_CUSTOM_RTC_VALUE{{System::Main, "Core", "CustomRTCValue"}, 946684800}; +const Info MAIN_FALLBACK_REGION{{System::Main, "Core", "FallbackRegion"}, + DiscIO::Region::NTSC_J}; const Info MAIN_AUTO_DISC_CHANGE{{System::Main, "Core", "AutoDiscChange"}, false}; const Info MAIN_ALLOW_SD_WRITES{{System::Main, "Core", "WiiSDCardAllowWrites"}, true}; const Info MAIN_ENABLE_SAVESTATES{{System::Main, "Core", "EnableSaveStates"}, false}; diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index ddd6cac340..8b568039e0 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -7,6 +7,7 @@ #include #include "Common/Config/Config.h" +#include "DiscIO/Enums.h" namespace PowerPC { @@ -88,6 +89,7 @@ extern const Info MAIN_CUSTOM_RTC_VALUE; extern const Info MAIN_AUTO_DISC_CHANGE; extern const Info MAIN_ALLOW_SD_WRITES; extern const Info MAIN_ENABLE_SAVESTATES; +extern const Info MAIN_FALLBACK_REGION; // Main.DSP diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index 3cc47f6b97..e1e581031f 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -33,7 +33,7 @@ bool IsSettingSaveable(const Config::Location& config_location) } } - static constexpr std::array s_setting_saveable = { + static constexpr std::array s_setting_saveable = { // Main.Core &Config::MAIN_DEFAULT_ISO.location, @@ -48,6 +48,7 @@ bool IsSettingSaveable(const Config::Location& config_location) &Config::MAIN_MEM2_SIZE.location, &Config::MAIN_GFX_BACKEND.location, &Config::MAIN_ENABLE_SAVESTATES.location, + &Config::MAIN_FALLBACK_REGION.location, // Main.Interface diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index ddd81b9497..d68c215998 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -31,6 +31,7 @@ #include "Core/Analytics.h" #include "Core/Boot/Boot.h" #include "Core/CommonTitles.h" +#include "Core/Config/MainSettings.h" #include "Core/Config/SYSCONFSettings.h" #include "Core/ConfigLoaders/GameConfigLoader.h" #include "Core/Core.h" @@ -929,18 +930,7 @@ bool SConfig::SetPathsAndGameMetadata(const BootParameters& boot) DiscIO::Region SConfig::GetFallbackRegion() { - // Fall back to the system menu region, if possible. - IOS::HLE::Kernel ios; - const IOS::ES::TMDReader system_menu_tmd = ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU); - if (system_menu_tmd.IsValid()) - { - const DiscIO::Region region = system_menu_tmd.GetRegion(); - if (region != DiscIO::Region::Unknown) - return region; - } - - // Fall back to PAL. - return DiscIO::Region::PAL; + return Config::Get(Config::MAIN_FALLBACK_REGION); } DiscIO::Language SConfig::GetCurrentLanguage(bool wii) const diff --git a/Source/Core/DolphinQt/Settings.cpp b/Source/Core/DolphinQt/Settings.cpp index c7c156bfd5..ce2b5a7e47 100644 --- a/Source/Core/DolphinQt/Settings.cpp +++ b/Source/Core/DolphinQt/Settings.cpp @@ -508,6 +508,21 @@ QString Settings::GetAutoUpdateTrack() const return QString::fromStdString(SConfig::GetInstance().m_auto_update_track); } +void Settings::SetFallbackRegion(const DiscIO::Region& region) +{ + if (region == GetFallbackRegion()) + return; + + Config::SetBase(Config::MAIN_FALLBACK_REGION, region); + + emit FallbackRegionChanged(region); +} + +DiscIO::Region Settings::GetFallbackRegion() const +{ + return Config::Get(Config::MAIN_FALLBACK_REGION); +} + void Settings::SetAnalyticsEnabled(bool enabled) { if (enabled == IsAnalyticsEnabled()) diff --git a/Source/Core/DolphinQt/Settings.h b/Source/Core/DolphinQt/Settings.h index 2e493feddd..63396c3e76 100644 --- a/Source/Core/DolphinQt/Settings.h +++ b/Source/Core/DolphinQt/Settings.h @@ -10,6 +10,8 @@ #include #include +#include "DiscIO/Enums.h" + namespace Core { enum class State; @@ -139,6 +141,10 @@ public: QString GetAutoUpdateTrack() const; void SetAutoUpdateTrack(const QString& mode); + // Fallback Region + DiscIO::Region GetFallbackRegion() const; + void SetFallbackRegion(const DiscIO::Region& region); + // Analytics bool IsAnalyticsEnabled() const; void SetAnalyticsEnabled(bool enabled); @@ -177,6 +183,7 @@ signals: void DebugModeToggled(bool enabled); void DebugFontChanged(QFont font); void AutoUpdateTrackChanged(const QString& mode); + void FallbackRegionChanged(const DiscIO::Region& region); void AnalyticsToggled(bool enabled); void DevicesChanged(); void SDCardInsertionChanged(bool inserted); diff --git a/Source/Core/DolphinQt/Settings/GeneralPane.cpp b/Source/Core/DolphinQt/Settings/GeneralPane.cpp index 24370daa77..62ca50469f 100644 --- a/Source/Core/DolphinQt/Settings/GeneralPane.cpp +++ b/Source/Core/DolphinQt/Settings/GeneralPane.cpp @@ -41,6 +41,11 @@ constexpr const char* AUTO_UPDATE_STABLE_STRING = "stable"; constexpr const char* AUTO_UPDATE_BETA_STRING = "beta"; constexpr const char* AUTO_UPDATE_DEV_STRING = "dev"; +constexpr int FALLBACK_REGION_NTSCJ_INDEX = 0; +constexpr int FALLBACK_REGION_NTSCU_INDEX = 1; +constexpr int FALLBACK_REGION_PAL_INDEX = 2; +constexpr int FALLBACK_REGION_NTSCK_INDEX = 3; + GeneralPane::GeneralPane(QWidget* parent) : QWidget(parent) { CreateLayout(); @@ -63,6 +68,8 @@ void GeneralPane::CreateLayout() if (AutoUpdateChecker::SystemSupportsAutoUpdates()) CreateAutoUpdate(); + CreateFallbackRegion(); + #if defined(USE_ANALYTICS) && USE_ANALYTICS CreateAnalytics(); #endif @@ -81,6 +88,7 @@ void GeneralPane::OnEmulationStateChanged(Core::State state) #ifdef USE_DISCORD_PRESENCE m_checkbox_discord_presence->setEnabled(!running); #endif + m_combobox_fallback_region->setEnabled(!running); } void GeneralPane::ConnectLayout() @@ -106,6 +114,10 @@ void GeneralPane::ConnectLayout() connect(m_combobox_speedlimit, qOverload(&QComboBox::currentIndexChanged), [this]() { OnSaveConfig(); }); + connect(m_combobox_fallback_region, qOverload(&QComboBox::currentIndexChanged), this, + &GeneralPane::OnSaveConfig); + connect(&Settings::Instance(), &Settings::FallbackRegionChanged, this, &GeneralPane::LoadConfig); + #if defined(USE_ANALYTICS) && USE_ANALYTICS connect(&Settings::Instance(), &Settings::AnalyticsToggled, this, &GeneralPane::LoadConfig); connect(m_checkbox_enable_analytics, &QCheckBox::toggled, this, &GeneralPane::OnSaveConfig); @@ -179,6 +191,33 @@ void GeneralPane::CreateAutoUpdate() m_combobox_update_track->addItem(option); } +void GeneralPane::CreateFallbackRegion() +{ + auto* fallback_region_group = new QGroupBox(tr("Fallback Region")); + auto* layout = new QVBoxLayout; + fallback_region_group->setLayout(layout); + m_main_layout->addWidget(fallback_region_group); + + m_combobox_fallback_region = new QComboBox(this); + + auto* form_widget = new QWidget; + auto* form_layout = new QFormLayout; + form_widget->setLayout(form_layout); + form_layout->setAlignment(Qt::AlignLeft | Qt::AlignTop); + form_layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); + form_layout->addRow(tr("Fallback Region:"), m_combobox_fallback_region); + layout->addWidget(form_widget); + + auto* fallback_region_description = + new QLabel(tr("Dolphin will use this for titles whose region cannot be determined " + "automatically.")); + fallback_region_description->setWordWrap(true); + layout->addWidget(fallback_region_description); + + for (const QString& option : {tr("NTSC-J"), tr("NTSC-U"), tr("PAL"), tr("NTSC-K")}) + m_combobox_fallback_region->addItem(option); +} + #if defined(USE_ANALYTICS) && USE_ANALYTICS void GeneralPane::CreateAnalytics() { @@ -224,6 +263,19 @@ void GeneralPane::LoadConfig() if (selection < m_combobox_speedlimit->count()) m_combobox_speedlimit->setCurrentIndex(selection); m_checkbox_dualcore->setChecked(SConfig::GetInstance().bCPUThread); + + const auto fallback = Settings::Instance().GetFallbackRegion(); + + if (fallback == DiscIO::Region::NTSC_J) + m_combobox_fallback_region->setCurrentIndex(FALLBACK_REGION_NTSCJ_INDEX); + else if (fallback == DiscIO::Region::NTSC_U) + m_combobox_fallback_region->setCurrentIndex(FALLBACK_REGION_NTSCU_INDEX); + else if (fallback == DiscIO::Region::PAL) + m_combobox_fallback_region->setCurrentIndex(FALLBACK_REGION_PAL_INDEX); + else if (fallback == DiscIO::Region::NTSC_K) + m_combobox_fallback_region->setCurrentIndex(FALLBACK_REGION_NTSCK_INDEX); + else + m_combobox_fallback_region->setCurrentIndex(FALLBACK_REGION_NTSCJ_INDEX); } static QString UpdateTrackFromIndex(int index) @@ -249,6 +301,31 @@ static QString UpdateTrackFromIndex(int index) return value; } +static DiscIO::Region UpdateFallbackRegionFromIndex(int index) +{ + DiscIO::Region value = DiscIO::Region::Unknown; + + switch (index) + { + case FALLBACK_REGION_NTSCJ_INDEX: + value = DiscIO::Region::NTSC_J; + break; + case FALLBACK_REGION_NTSCU_INDEX: + value = DiscIO::Region::NTSC_U; + break; + case FALLBACK_REGION_PAL_INDEX: + value = DiscIO::Region::PAL; + break; + case FALLBACK_REGION_NTSCK_INDEX: + value = DiscIO::Region::NTSC_K; + break; + default: + value = DiscIO::Region::NTSC_J; + } + + return value; +} + void GeneralPane::OnSaveConfig() { Config::ConfigChangeCallbackGuard config_guard; @@ -277,6 +354,8 @@ void GeneralPane::OnSaveConfig() 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; + Settings::Instance().SetFallbackRegion( + UpdateFallbackRegionFromIndex(m_combobox_fallback_region->currentIndex())); settings.SaveSettings(); } diff --git a/Source/Core/DolphinQt/Settings/GeneralPane.h b/Source/Core/DolphinQt/Settings/GeneralPane.h index 8106672bcd..79f5cc3861 100644 --- a/Source/Core/DolphinQt/Settings/GeneralPane.h +++ b/Source/Core/DolphinQt/Settings/GeneralPane.h @@ -30,6 +30,7 @@ private: void ConnectLayout(); void CreateBasic(); void CreateAutoUpdate(); + void CreateFallbackRegion(); void LoadConfig(); void OnSaveConfig(); @@ -39,6 +40,7 @@ private: QVBoxLayout* m_main_layout; QComboBox* m_combobox_speedlimit; QComboBox* m_combobox_update_track; + QComboBox* m_combobox_fallback_region; QCheckBox* m_checkbox_dualcore; QCheckBox* m_checkbox_cheats; QCheckBox* m_checkbox_override_region_settings;