diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt
index afe48b86d7..d074c16fff 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt
@@ -100,6 +100,12 @@ enum class BooleanSetting(
"OverclockEnable",
false
),
+ MAIN_VI_OVERCLOCK_ENABLE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "VIOverclockEnable",
+ false
+ ),
MAIN_RAM_OVERRIDE_ENABLE(
Settings.FILE_DOLPHIN,
Settings.SECTION_INI_CORE,
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.kt
index ec5bda11cc..d6e6be05c4 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.kt
@@ -11,6 +11,7 @@ enum class FloatSetting(
// These entries have the same names and order as in C++, just for consistency.
MAIN_EMULATION_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EmulationSpeed", 1.0f),
MAIN_OVERCLOCK(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Overclock", 1.0f),
+ MAIN_VI_OVERCLOCK(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "VIOverclock", 1.0f),
GFX_CC_GAME_GAMMA(Settings.FILE_GFX, Settings.SECTION_GFX_COLOR_CORRECTION, "GameGamma", 2.35f);
override val isOverridden: Boolean
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
index e0aa32e15c..657fdb9256 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -1031,6 +1031,27 @@ class SettingsFragmentPresenter(
false
)
)
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_VI_OVERCLOCK_ENABLE,
+ R.string.vi_overclock_enable,
+ R.string.vi_overclock_enable_description
+ )
+ )
+ sl.add(
+ PercentSliderSetting(
+ context,
+ FloatSetting.MAIN_VI_OVERCLOCK,
+ R.string.vi_overclock_title,
+ R.string.vi_overclock_title_description,
+ 0f,
+ 400f,
+ "%",
+ 1f,
+ false
+ )
+ )
val mem1Size = ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM1_SIZE)
val mem2Size = ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM2_SIZE)
diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml
index 22cd5c4a34..09b65952c8 100644
--- a/Source/Android/app/src/main/res/values/strings.xml
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -376,7 +376,7 @@
Enables emulation of the CPU write-back cache. Enabling will have a significant impact on performance. This should be left disabled unless absolutely needed.
Clock Override
Override Emulated CPU Clock Speed
- Higher values can make variable-framerate games run at a higher framerate, requiring a powerful device. Lower values make games run at a lower framerate, increasing emulation speed, but reducing the emulated console\'s performance.
+ Higher values can make games run at a higher frame rate if they lagged on original hardware, requiring a powerful device. Lower values improve performance by causing lag, but will slow down the game (without affecting audio) if its speed is tied to the frame rate.
Emulated CPU Clock Speed
Adjusts the emulated CPU\'s clock rate if \"Override Emulated CPU Clock Speed\" is enabled.
Memory Override
@@ -385,6 +385,10 @@
MEM1 Size
MEM2 Size
GPU Options
+ Override VBI Frequency
+ Makes the game run at a different frame rate without impacting audio, making the emulation less demanding when lowered, or improving smoothness when increased. This may affect game speed, as it is often tied to the frame rate.
+ Emulated VBI Clock Speed
+ Adjusts the emulated VBI frequency rate if \"Override VBI Frequency\" is enabled.\nAlso adjusts the emulated CPU\'s clock rate, to keep it relatively the same.
Synchronize GPU Thread
Synchronizing the GPU thread reduces the risk of games crashing or becoming unstable with dual core enabled, but can also reduce the performance gain of dual core. If unsure, select \"On Idle Skipping\". Selecting \"Never\" is risky and not recommended!
Custom RTC Options
diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp
index 9f4d1cce17..74e6b1e0a2 100644
--- a/Source/Core/Core/Config/MainSettings.cpp
+++ b/Source/Core/Core/Config/MainSettings.cpp
@@ -222,6 +222,8 @@ const Info MAIN_PRECISION_FRAME_TIMING{{System::Main, "Core", "PrecisionFr
DEFAULT_PRECISION_FRAME_TIMING};
const Info MAIN_OVERCLOCK{{System::Main, "Core", "Overclock"}, 1.0f};
const Info MAIN_OVERCLOCK_ENABLE{{System::Main, "Core", "OverclockEnable"}, false};
+const Info MAIN_VI_FREQUENCY{{System::Main, "Core", "VIFrequency"}, 1.0f};
+const Info MAIN_VI_FREQUENCY_ENABLE{{System::Main, "Core", "VIFrequencyEnable"}, false};
const Info MAIN_RAM_OVERRIDE_ENABLE{{System::Main, "Core", "RAMOverrideEnable"}, false};
const Info MAIN_MEM1_SIZE{{System::Main, "Core", "MEM1Size"}, Memory::MEM1_SIZE_RETAIL};
const Info MAIN_MEM2_SIZE{{System::Main, "Core", "MEM2Size"}, Memory::MEM2_SIZE_RETAIL};
diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h
index 28a044d253..4f54bcc021 100644
--- a/Source/Core/Core/Config/MainSettings.h
+++ b/Source/Core/Core/Config/MainSettings.h
@@ -128,6 +128,8 @@ extern const Info MAIN_EMULATION_SPEED;
extern const Info MAIN_PRECISION_FRAME_TIMING;
extern const Info MAIN_OVERCLOCK;
extern const Info MAIN_OVERCLOCK_ENABLE;
+extern const Info MAIN_VI_FREQUENCY;
+extern const Info MAIN_VI_FREQUENCY_ENABLE;
extern const Info MAIN_RAM_OVERRIDE_ENABLE;
extern const Info MAIN_MEM1_SIZE;
extern const Info MAIN_MEM2_SIZE;
diff --git a/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp b/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp
index 5f772fd0e3..5ff33e2541 100644
--- a/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp
+++ b/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp
@@ -42,6 +42,8 @@ public:
layer->Set(Config::MAIN_DSP_HLE, m_settings.dsp_hle);
layer->Set(Config::MAIN_OVERCLOCK_ENABLE, m_settings.oc_enable);
layer->Set(Config::MAIN_OVERCLOCK, m_settings.oc_factor);
+ layer->Set(Config::MAIN_VI_FREQUENCY_ENABLE, m_settings.vi_freq_enable);
+ layer->Set(Config::MAIN_VI_FREQUENCY, m_settings.vi_freq_factor);
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
layer->Set(Config::GetInfoForEXIDevice(slot), m_settings.exi_device[slot]);
layer->Set(Config::MAIN_MEMORY_CARD_SIZE, m_settings.memcard_size_override);
diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp
index 82d0db9f7c..9bc5995ce4 100644
--- a/Source/Core/Core/CoreTiming.cpp
+++ b/Source/Core/Core/CoreTiming.cpp
@@ -117,7 +117,9 @@ void CoreTimingManager::Shutdown()
void CoreTimingManager::RefreshConfig()
{
m_config_oc_factor =
- Config::Get(Config::MAIN_OVERCLOCK_ENABLE) ? Config::Get(Config::MAIN_OVERCLOCK) : 1.0f;
+ (Config::Get(Config::MAIN_OVERCLOCK_ENABLE) ? Config::Get(Config::MAIN_OVERCLOCK) : 1.0f) *
+ (Config::Get(Config::MAIN_VI_FREQUENCY_ENABLE) ? Config::Get(Config::MAIN_VI_FREQUENCY) :
+ 1.0f);
m_config_oc_inv_factor = 1.0f / m_config_oc_factor;
m_config_sync_on_skip_idle = Config::Get(Config::MAIN_SYNC_ON_SKIP_IDLE);
@@ -444,6 +446,11 @@ bool CoreTimingManager::GetVISkip() const
return m_throttle_disable_vi_int && g_ActiveConfig.bVISkip && !Core::WantsDeterminism();
}
+float CoreTimingManager::GetOverclock() const
+{
+ return m_config_oc_factor;
+}
+
bool CoreTimingManager::UseSyncOnSkipIdle() const
{
return m_config_sync_on_skip_idle;
diff --git a/Source/Core/Core/CoreTiming.h b/Source/Core/Core/CoreTiming.h
index 3ffa5d897f..e3bdc1dafb 100644
--- a/Source/Core/Core/CoreTiming.h
+++ b/Source/Core/Core/CoreTiming.h
@@ -165,6 +165,8 @@ public:
// Used by VideoInterface
bool GetVISkip() const;
+ float GetOverclock() const;
+
bool UseSyncOnSkipIdle() const;
private:
diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp
index 5613e3fea4..970c2bf74e 100644
--- a/Source/Core/Core/DolphinAnalytics.cpp
+++ b/Source/Core/Core/DolphinAnalytics.cpp
@@ -365,6 +365,8 @@ void DolphinAnalytics::MakePerGameBuilder()
builder.AddData("cfg-audio-backend", Config::Get(Config::MAIN_AUDIO_BACKEND));
builder.AddData("cfg-oc-enable", Config::Get(Config::MAIN_OVERCLOCK_ENABLE));
builder.AddData("cfg-oc-factor", Config::Get(Config::MAIN_OVERCLOCK));
+ builder.AddData("cfg-vi-freq-enable", Config::Get(Config::MAIN_VI_FREQUENCY_ENABLE));
+ builder.AddData("cfg-vi-freq-factor", Config::Get(Config::MAIN_VI_FREQUENCY));
builder.AddData("cfg-render-to-main", Config::Get(Config::MAIN_RENDER_TO_MAIN));
if (g_video_backend)
{
diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp
index b03a8c5988..79f9796236 100644
--- a/Source/Core/Core/HW/VideoInterface.cpp
+++ b/Source/Core/Core/HW/VideoInterface.cpp
@@ -13,8 +13,10 @@
#include "Common/Config/Config.h"
#include "Common/Logging/Log.h"
+#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/PerformanceMetrics.h"
+#include "Core/AchievementManager.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/SYSCONFSettings.h"
@@ -41,7 +43,10 @@ VideoInterfaceManager::VideoInterfaceManager(Core::System& system) : m_system(sy
{
}
-VideoInterfaceManager::~VideoInterfaceManager() = default;
+VideoInterfaceManager::~VideoInterfaceManager()
+{
+ Config::RemoveConfigChangedCallback(m_config_changed_callback_id);
+}
static constexpr std::array CLOCK_FREQUENCIES{{
27000000,
@@ -173,6 +178,22 @@ void VideoInterfaceManager::Preset(bool _bNTSC)
void VideoInterfaceManager::Init()
{
Preset(true);
+
+ m_config_changed_callback_id = Config::AddConfigChangedCallback([this] { RefreshConfig(); });
+ RefreshConfig();
+}
+
+void VideoInterfaceManager::RefreshConfig()
+{
+ m_config_vi_freq_factor =
+ Config::Get(Config::MAIN_VI_FREQUENCY_ENABLE) ? Config::Get(Config::MAIN_VI_FREQUENCY) : 1.0f;
+ if (AchievementManager::GetInstance().IsHardcoreModeActive() && m_config_vi_freq_factor < 1.0f)
+ {
+ Config::SetCurrent(Config::MAIN_VI_FREQUENCY, 1.0f);
+ m_config_vi_freq_factor = 1.0f;
+ OSD::AddMessage("Minimum VBI frequency is 100% in Hardcore Mode");
+ }
+ UpdateRefreshRate();
}
void VideoInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
@@ -707,7 +728,11 @@ void VideoInterfaceManager::UpdateParameters()
m_vblank_timing_even.PRB - odd_even_psb_diff;
m_even_field_last_hl = m_even_field_first_hl + acv_hl - 1;
- // Refresh rate:
+ UpdateRefreshRate();
+}
+
+void VideoInterfaceManager::UpdateRefreshRate()
+{
m_target_refresh_rate_numerator = m_system.GetSystemTimers().GetTicksPerSecond() * 2;
m_target_refresh_rate_denominator = GetTicksPerEvenField() + GetTicksPerOddField();
m_target_refresh_rate =
@@ -729,9 +754,10 @@ u32 VideoInterfaceManager::GetTargetRefreshRateDenominator() const
return m_target_refresh_rate_denominator;
}
-u32 VideoInterfaceManager::GetTicksPerSample() const
+double VideoInterfaceManager::GetTicksPerSample() const
{
- return 2 * m_system.GetSystemTimers().GetTicksPerSecond() / CLOCK_FREQUENCIES[m_clock & 1];
+ return 2 * m_system.GetSystemTimers().GetTicksPerSecond() / CLOCK_FREQUENCIES[m_clock & 1] /
+ m_config_vi_freq_factor;
}
u32 VideoInterfaceManager::GetTicksPerHalfLine() const
diff --git a/Source/Core/Core/HW/VideoInterface.h b/Source/Core/Core/HW/VideoInterface.h
index 8bb1e23405..cb2ce6a28a 100644
--- a/Source/Core/Core/HW/VideoInterface.h
+++ b/Source/Core/Core/HW/VideoInterface.h
@@ -7,6 +7,7 @@
#include
#include "Common/CommonTypes.h"
+#include "Common/Config/Config.h"
enum class FieldType;
class PointerWrap;
@@ -384,7 +385,7 @@ public:
u32 GetTargetRefreshRateNumerator() const;
u32 GetTargetRefreshRateDenominator() const;
- u32 GetTicksPerSample() const;
+ double GetTicksPerSample() const;
u32 GetTicksPerHalfLine() const;
u32 GetTicksPerField() const;
@@ -407,6 +408,9 @@ private:
void BeginField(FieldType field, u64 ticks);
void EndField(FieldType field, u64 ticks);
+ void RefreshConfig();
+ void UpdateRefreshRate();
+
// Registers listed in order:
UVIVerticalTimingRegister m_vertical_timing_register;
UVIDisplayControlRegister m_display_control_register;
@@ -447,6 +451,9 @@ private:
u32 m_even_field_last_hl = 0; // index last halfline of the even field
u32 m_odd_field_last_hl = 0; // index last halfline of the odd field
+ float m_config_vi_freq_factor = 0.0f;
+
+ Config::ConfigChangedCallbackID m_config_changed_callback_id;
Core::System& m_system;
};
} // namespace VideoInterface
diff --git a/Source/Core/Core/IOS/DolphinDevice.cpp b/Source/Core/Core/IOS/DolphinDevice.cpp
index 944bec41b2..c240b922b7 100644
--- a/Source/Core/Core/IOS/DolphinDevice.cpp
+++ b/Source/Core/Core/IOS/DolphinDevice.cpp
@@ -68,9 +68,7 @@ IPCReply GetCPUSpeed(Core::System& system, const IOCtlVRequest& request)
return IPCReply(IPC_EINVAL);
}
- const bool overclock_enabled = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
- const float oc = overclock_enabled ? Config::Get(Config::MAIN_OVERCLOCK) : 1.0f;
-
+ const bool oc = system.GetCoreTiming().GetOverclock();
const u32 core_clock = u32(float(system.GetSystemTimers().GetTicksPerSecond()) * oc);
auto& memory = system.GetMemory();
diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp
index aee89cbc1c..10e0839288 100644
--- a/Source/Core/Core/NetPlayClient.cpp
+++ b/Source/Core/Core/NetPlayClient.cpp
@@ -862,6 +862,8 @@ void NetPlayClient::OnStartGame(sf::Packet& packet)
packet >> m_net_settings.allow_sd_writes;
packet >> m_net_settings.oc_enable;
packet >> m_net_settings.oc_factor;
+ packet >> m_net_settings.vi_freq_enable;
+ packet >> m_net_settings.vi_freq_factor;
for (auto slot : ExpansionInterface::SLOTS)
packet >> m_net_settings.exi_device[slot];
diff --git a/Source/Core/Core/NetPlayProto.h b/Source/Core/Core/NetPlayProto.h
index c97d04c2b2..4d7ca9fed9 100644
--- a/Source/Core/Core/NetPlayProto.h
+++ b/Source/Core/Core/NetPlayProto.h
@@ -47,6 +47,8 @@ struct NetSettings
bool allow_sd_writes = false;
bool oc_enable = false;
float oc_factor = 0;
+ bool vi_freq_enable = false;
+ float vi_freq_factor = 0;
Common::EnumMap exi_device{};
int memcard_size_override = -1;
diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp
index 4cff258e9b..9f04a41cba 100644
--- a/Source/Core/Core/NetPlayServer.cpp
+++ b/Source/Core/Core/NetPlayServer.cpp
@@ -1376,6 +1376,8 @@ bool NetPlayServer::SetupNetSettings()
settings.allow_sd_writes = Config::Get(Config::MAIN_ALLOW_SD_WRITES);
settings.oc_enable = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
settings.oc_factor = Config::Get(Config::MAIN_OVERCLOCK);
+ settings.vi_freq_enable = Config::Get(Config::MAIN_VI_FREQUENCY_ENABLE);
+ settings.vi_freq_factor = Config::Get(Config::MAIN_VI_FREQUENCY);
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
{
@@ -1603,6 +1605,8 @@ bool NetPlayServer::StartGame()
spac << m_settings.allow_sd_writes;
spac << m_settings.oc_enable;
spac << m_settings.oc_factor;
+ spac << m_settings.vi_freq_enable;
+ spac << m_settings.vi_freq_factor;
for (auto slot : ExpansionInterface::SLOTS)
spac << static_cast(m_settings.exi_device[slot]);
diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp
index 917e7e898c..f577eb87eb 100644
--- a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp
+++ b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp
@@ -20,6 +20,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/SystemTimers.h"
+#include "Core/HW/VideoInterface.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
@@ -111,14 +112,47 @@ void AdvancedPane::CreateLayout()
m_cpu_clock_override_checkbox->SetDescription(
tr("Adjusts the emulated CPU's clock rate.
"
- "Higher values may make variable-framerate games run at a higher framerate, "
- "at the expense of performance. Lower values may activate a game's "
- "internal frameskip, potentially improving performance.
"
- "WARNING: Changing this from the default (100%) can and will "
+ "Higher values can make games run at a higher frame rate if they "
+ "lagged on original hardware at the expense of performance. Lower "
+ "values improve performance by causing lag, but will slow down "
+ "the game (without affecting audio) if its speed is tied to the frame rate.
"
+ "WARNING: Changing this from the default (100%) can and will "
"break games and cause glitches. Do so at your own risk. "
"Please do not report bugs that occur with a non-default clock."
"
If unsure, leave this unchecked."));
+ auto* vi_rate_override = new QGroupBox(tr("VBI Clock Override"));
+ auto* vi_rate_override_layout = new QVBoxLayout();
+ vi_rate_override->setLayout(vi_rate_override_layout);
+ main_layout->addWidget(vi_rate_override);
+
+ m_vi_rate_override_checkbox =
+ new ConfigBool(tr("Enable VBI Frequency Override"), Config::MAIN_VI_FREQUENCY_ENABLE);
+ vi_rate_override_layout->addWidget(m_vi_rate_override_checkbox);
+ connect(m_vi_rate_override_checkbox, &QCheckBox::toggled, this, &AdvancedPane::Update);
+
+ auto* vi_rate_override_slider_layout = new QHBoxLayout();
+ vi_rate_override_slider_layout->setContentsMargins(0, 0, 0, 0);
+ vi_rate_override_layout->addLayout(vi_rate_override_slider_layout);
+
+ m_vi_rate_override_slider = new QSlider(Qt::Horizontal);
+ m_vi_rate_override_slider->setRange(1, 500);
+ vi_rate_override_slider_layout->addWidget(m_vi_rate_override_slider);
+
+ m_vi_rate_override_slider_label = new QLabel();
+ vi_rate_override_slider_layout->addWidget(m_vi_rate_override_slider_label);
+
+ m_vi_rate_override_checkbox->SetDescription(
+ tr("Adjusts the emulated VBI frequency. Also adjusts the emulated CPU's "
+ "clock rate, to keep it relatively the same.
"
+ "Makes the game run at a different frame rate without impacting audio, making the "
+ "emulation less demanding when lowered, or improving smoothness when increased. This may "
+ "affect game speed, as it is often tied to the frame rate.
"
+ "WARNING: Changing this from the default (100%) can and will "
+ "break games and cause glitches. Do so at your own risk. "
+ "Please do not report bugs that occur with a non-default frequency."
+ "
If unsure, leave this unchecked."));
+
auto* ram_override = new QGroupBox(tr("Memory Override"));
auto* ram_override_layout = new QVBoxLayout();
ram_override->setLayout(ram_override_layout);
@@ -199,6 +233,18 @@ void AdvancedPane::ConnectLayout()
Update();
});
+ connect(m_vi_rate_override_slider, &QSlider::valueChanged, [this](int oc_factor) {
+ const float factor = m_vi_rate_override_slider->value() / 100.f;
+ Config::SetBaseOrCurrent(Config::MAIN_VI_FREQUENCY, factor);
+ Update();
+ });
+
+ m_ram_override_checkbox->setChecked(Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE));
+ connect(m_ram_override_checkbox, &QCheckBox::toggled, [this](bool enable_ram_override) {
+ Config::SetBaseOrCurrent(Config::MAIN_RAM_OVERRIDE_ENABLE, enable_ram_override);
+ Update();
+ });
+
connect(m_mem1_override_slider, &QSlider::valueChanged, [this](int slider_value) {
const u32 mem1_size = m_mem1_override_slider->value() * 0x100000;
Config::SetBaseOrCurrent(Config::MAIN_MEM1_SIZE, mem1_size);
@@ -222,6 +268,7 @@ void AdvancedPane::Update()
{
const bool is_uninitialized = Core::IsUninitialized(Core::System::GetInstance());
const bool enable_cpu_clock_override_widgets = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
+ const bool enable_vi_rate_override_widgets = Config::Get(Config::MAIN_VI_FREQUENCY_ENABLE);
const bool enable_ram_override_widgets = Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE);
const bool enable_custom_rtc_widgets =
Config::Get(Config::MAIN_CUSTOM_RTC_ENABLE) && is_uninitialized;
@@ -264,6 +311,30 @@ void AdvancedPane::Update()
return tr("%1% (%2 MHz)").arg(QString::number(percent), QString::number(clock));
}());
+ QFont vi_bf = font();
+ vi_bf.setBold(Config::GetActiveLayerForConfig(Config::MAIN_VI_FREQUENCY_ENABLE) !=
+ Config::LayerType::Base);
+ m_vi_rate_override_checkbox->setFont(vi_bf);
+ m_vi_rate_override_checkbox->setChecked(enable_vi_rate_override_widgets);
+
+ m_vi_rate_override_slider->setEnabled(enable_vi_rate_override_widgets);
+ m_vi_rate_override_slider_label->setEnabled(enable_vi_rate_override_widgets);
+
+ {
+ const QSignalBlocker blocker(m_vi_rate_override_slider);
+ m_vi_rate_override_slider->setValue(
+ static_cast(std::round(Config::Get(Config::MAIN_VI_FREQUENCY) * 100.f)));
+ }
+
+ m_vi_rate_override_slider_label->setText([] {
+ int percent = static_cast(std::round(Config::Get(Config::MAIN_VI_FREQUENCY) * 100.f));
+ float vps =
+ static_cast(Core::System::GetInstance().GetVideoInterface().GetTargetRefreshRate());
+ if (vps == 0.0f || !Config::Get(Config::MAIN_VI_FREQUENCY_ENABLE))
+ vps = 59.94f * Config::Get(Config::MAIN_VI_FREQUENCY);
+ return tr("%1% (%2 VPS)").arg(QString::number(percent), QString::number(vps, 'f', 2));
+ }());
+
m_ram_override_checkbox->setEnabled(is_uninitialized);
SignalBlocking(m_ram_override_checkbox)->setChecked(enable_ram_override_widgets);
diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.h b/Source/Core/DolphinQt/Settings/AdvancedPane.h
index ff449aca65..6493e71a73 100644
--- a/Source/Core/DolphinQt/Settings/AdvancedPane.h
+++ b/Source/Core/DolphinQt/Settings/AdvancedPane.h
@@ -39,6 +39,10 @@ private:
QSlider* m_cpu_clock_override_slider;
QLabel* m_cpu_clock_override_slider_label;
+ ConfigBool* m_vi_rate_override_checkbox;
+ QSlider* m_vi_rate_override_slider;
+ QLabel* m_vi_rate_override_slider_label;
+
ConfigBool* m_custom_rtc_checkbox;
QDateTimeEdit* m_custom_rtc_datetime;