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 156d6ccd4c..82e82f0d18 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 2af2202599..9c5ca9e362 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
@@ -1010,6 +1010,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 aacc57a3be..90917e68de 100644
--- a/Source/Android/app/src/main/res/values/strings.xml
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -370,7 +370,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 framerate 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 physics ignore the framerate.
Emulated CPU Clock Speed
Adjusts the emulated CPU\'s clock rate if \"Override Emulated CPU Clock Speed\" is enabled.
Memory Override
@@ -379,6 +379,10 @@
MEM1 Size
MEM2 Size
GPU Options
+ Override VBI Clock Speed
+ Makes the game run at a different framerate without impacting audio, making the emulation less demanding when lowered, or improving smoothness when increased. Because many games\' physics ignore the framerate, this may affect game speed.
+ Emulated VBI Clock Speed
+ Adjusts the emulated VBI clock rate if \"Override VBI Clock Speed\" 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 c9cd0333a9..efa2d6fd11 100644
--- a/Source/Core/Core/Config/MainSettings.cpp
+++ b/Source/Core/Core/Config/MainSettings.cpp
@@ -208,6 +208,8 @@ const Info MAIN_DISABLE_ICACHE{{System::Main, "Core", "DisableICache"}, fa
const Info MAIN_EMULATION_SPEED{{System::Main, "Core", "EmulationSpeed"}, 1.0f};
const Info MAIN_OVERCLOCK{{System::Main, "Core", "Overclock"}, 1.0f};
const Info MAIN_OVERCLOCK_ENABLE{{System::Main, "Core", "OverclockEnable"}, false};
+const Info MAIN_VI_OVERCLOCK{{System::Main, "Core", "VIOverclock"}, 1.0f};
+const Info MAIN_VI_OVERCLOCK_ENABLE{{System::Main, "Core", "VIOverclockEnable"}, 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 b6e8f966c7..4f8f72f7c2 100644
--- a/Source/Core/Core/Config/MainSettings.h
+++ b/Source/Core/Core/Config/MainSettings.h
@@ -125,6 +125,8 @@ extern const Info MAIN_DISABLE_ICACHE;
extern const Info MAIN_EMULATION_SPEED;
extern const Info MAIN_OVERCLOCK;
extern const Info MAIN_OVERCLOCK_ENABLE;
+extern const Info MAIN_VI_OVERCLOCK;
+extern const Info MAIN_VI_OVERCLOCK_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 75b1bda454..48c9668f9d 100644
--- a/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp
+++ b/Source/Core/Core/ConfigLoaders/NetPlayConfigLoader.cpp
@@ -38,6 +38,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_OVERCLOCK_ENABLE, m_settings.vi_oc_enable);
+ layer->Set(Config::MAIN_VI_OVERCLOCK, m_settings.vi_oc_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 549c455a3f..ffd197f2e2 100644
--- a/Source/Core/Core/CoreTiming.cpp
+++ b/Source/Core/Core/CoreTiming.cpp
@@ -118,7 +118,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_OVERCLOCK_ENABLE) ? Config::Get(Config::MAIN_VI_OVERCLOCK) :
+ 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);
@@ -422,6 +424,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 b76e898e70..98d35ad242 100644
--- a/Source/Core/Core/CoreTiming.h
+++ b/Source/Core/Core/CoreTiming.h
@@ -162,6 +162,7 @@ public:
TimePoint GetCPUTimePoint(s64 cyclesLate) const; // Used by Dolphin Analytics
bool GetVISkip() const; // Used By VideoInterface
+ float GetOverclock() const;
bool UseSyncOnSkipIdle() const;
diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp
index 5f54420013..53ce3d8941 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-oc-enable", Config::Get(Config::MAIN_VI_OVERCLOCK_ENABLE));
+ builder.AddData("cfg-vi-oc-factor", Config::Get(Config::MAIN_VI_OVERCLOCK));
builder.AddData("cfg-render-to-main", Config::Get(Config::MAIN_RENDER_TO_MAIN));
if (g_video_backend)
{
diff --git a/Source/Core/Core/HW/SystemTimers.cpp b/Source/Core/Core/HW/SystemTimers.cpp
index 022b94bf4d..95bbf5dcc2 100644
--- a/Source/Core/Core/HW/SystemTimers.cpp
+++ b/Source/Core/Core/HW/SystemTimers.cpp
@@ -140,7 +140,7 @@ void SystemTimersManager::VICallback(Core::System& system, u64 userdata, s64 cyc
auto& core_timing = system.GetCoreTiming();
auto& vi = system.GetVideoInterface();
vi.Update(core_timing.GetTicks() - cycles_late);
- core_timing.ScheduleEvent(vi.GetTicksPerHalfLine() - cycles_late,
+ core_timing.ScheduleEvent(vi.GetTicksPerViCallback() - cycles_late,
system.GetSystemTimers().m_event_type_vi);
}
@@ -296,7 +296,7 @@ void SystemTimersManager::Init()
core_timing.ScheduleEvent(0, m_event_type_perf_tracker);
core_timing.ScheduleEvent(0, m_event_type_gpu_sleeper);
- core_timing.ScheduleEvent(vi.GetTicksPerHalfLine(), m_event_type_vi);
+ core_timing.ScheduleEvent(vi.GetTicksPerViCallback(), m_event_type_vi);
core_timing.ScheduleEvent(0, m_event_type_dsp);
const int audio_dma_callback_period = GetAudioDMACallbackPeriod(
diff --git a/Source/Core/Core/HW/VideoInterface.cpp b/Source/Core/Core/HW/VideoInterface.cpp
index be197f4915..2241ef2698 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,21 @@ 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_oc_factor =
+ Config::Get(Config::MAIN_VI_OVERCLOCK_ENABLE) ? Config::Get(Config::MAIN_VI_OVERCLOCK) : 1.0f;
+ if (AchievementManager::GetInstance().IsHardcoreModeActive() && m_config_vi_oc_factor < 1.0f)
+ {
+ Config::SetCurrent(Config::MAIN_VI_OVERCLOCK, 1.0f);
+ m_config_vi_oc_factor = 1.0f;
+ OSD::AddMessage("Minimum VBI overclock is 100% in Hardcore Mode");
+ }
}
void VideoInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
@@ -731,6 +751,11 @@ u32 VideoInterfaceManager::GetTicksPerField() const
return GetTicksPerEvenField();
}
+u32 VideoInterfaceManager::GetTicksPerViCallback() const
+{
+ return static_cast(GetTicksPerHalfLine() / m_config_vi_oc_factor);
+}
+
void VideoInterfaceManager::LogField(FieldType field, u32 xfb_address) const
{
static constexpr std::array field_type_names{{"Odd", "Even"}};
diff --git a/Source/Core/Core/HW/VideoInterface.h b/Source/Core/Core/HW/VideoInterface.h
index 8bb1e23405..5560b51308 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;
@@ -387,6 +388,7 @@ public:
u32 GetTicksPerSample() const;
u32 GetTicksPerHalfLine() const;
u32 GetTicksPerField() const;
+ u32 GetTicksPerViCallback() const;
// Get the aspect ratio of VI's active area (rarely matching pure 4:3).
// This function only deals with standard aspect ratios. For widescreen aspect ratios, multiply
@@ -407,6 +409,8 @@ private:
void BeginField(FieldType field, u64 ticks);
void EndField(FieldType field, u64 ticks);
+ void RefreshConfig();
+
// 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_oc_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/NetPlayProto.h b/Source/Core/Core/NetPlayProto.h
index a20aee39ce..0e7879c4f4 100644
--- a/Source/Core/Core/NetPlayProto.h
+++ b/Source/Core/Core/NetPlayProto.h
@@ -46,6 +46,8 @@ struct NetSettings
bool allow_sd_writes = false;
bool oc_enable = false;
float oc_factor = 0;
+ bool vi_oc_enable = false;
+ float vi_oc_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 0044ce903e..3d0be26f18 100644
--- a/Source/Core/Core/NetPlayServer.cpp
+++ b/Source/Core/Core/NetPlayServer.cpp
@@ -1369,6 +1369,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_oc_enable = Config::Get(Config::MAIN_VI_OVERCLOCK_ENABLE);
+ settings.vi_oc_factor = Config::Get(Config::MAIN_VI_OVERCLOCK);
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
{
diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp
index e15b8f2325..5f9a048fc9 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"
@@ -107,17 +108,49 @@ void AdvancedPane::CreateLayout()
m_cpu_clock_override_slider_label = new QLabel();
cpu_clock_override_slider_layout->addWidget(m_cpu_clock_override_slider_label);
- auto* cpu_clock_override_description =
- new QLabel(tr("Adjusts the emulated CPU's clock rate.\n\n"
- "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.\n\n"
- "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."));
+ auto* cpu_clock_override_description = new QLabel(tr(
+ "Adjusts the emulated CPU's clock rate.\n\n"
+ "Higher values can make games run at a higher framerate 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 physics ignore the "
+ "framerate.\n\n"
+ "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."));
cpu_clock_override_description->setWordWrap(true);
clock_override_layout->addWidget(cpu_clock_override_description);
+ auto* vi_clock_override = new QGroupBox(tr("VBI Clock Override"));
+ auto* vi_clock_override_layout = new QVBoxLayout();
+ vi_clock_override->setLayout(vi_clock_override_layout);
+ main_layout->addWidget(vi_clock_override);
+
+ m_vi_clock_override_checkbox = new QCheckBox(tr("Enable VBI Overclocking"));
+ vi_clock_override_layout->addWidget(m_vi_clock_override_checkbox);
+
+ auto* vi_clock_override_slider_layout = new QHBoxLayout();
+ vi_clock_override_slider_layout->setContentsMargins(0, 0, 0, 0);
+ vi_clock_override_layout->addLayout(vi_clock_override_slider_layout);
+
+ m_vi_clock_override_slider = new QSlider(Qt::Horizontal);
+ m_vi_clock_override_slider->setRange(1, 400);
+ vi_clock_override_slider_layout->addWidget(m_vi_clock_override_slider);
+
+ m_vi_clock_override_slider_label = new QLabel();
+ vi_clock_override_slider_layout->addWidget(m_vi_clock_override_slider_label);
+
+ auto* vi_clock_override_description = new QLabel(
+ tr("Adjusts the emulated VBI clock rate. Also adjusts the emulated CPU's clock rate, to "
+ "keep it relatively the same.\n\n"
+ "Makes the game run at a different framerate without impacting audio, making the "
+ "emulation less demanding when lowered, or improving smoothness when increased. Because "
+ "many games' physics ignore the framerate, this may affect game speed.\n\n"
+ "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."));
+ vi_clock_override_description->setWordWrap(true);
+ vi_clock_override_layout->addWidget(vi_clock_override_description);
+
auto* ram_override = new QGroupBox(tr("Memory Override"));
auto* ram_override_layout = new QVBoxLayout();
ram_override->setLayout(ram_override_layout);
@@ -203,6 +236,19 @@ void AdvancedPane::ConnectLayout()
Update();
});
+ m_vi_clock_override_checkbox->setChecked(Config::Get(Config::MAIN_VI_OVERCLOCK_ENABLE));
+ connect(m_vi_clock_override_checkbox, &QCheckBox::toggled, [this](bool enable_clock_override) {
+ Config::SetBaseOrCurrent(Config::MAIN_VI_OVERCLOCK_ENABLE, enable_clock_override);
+ Update();
+ });
+
+ connect(m_vi_clock_override_slider, &QSlider::valueChanged, [this](int oc_factor) {
+ const float factor = m_vi_clock_override_slider->value() / 100.f;
+ Config::SetBaseOrCurrent(Config::MAIN_VI_OVERCLOCK, 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();
@@ -236,6 +282,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_clock_override_widgets = Config::Get(Config::MAIN_VI_OVERCLOCK_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;
@@ -278,6 +325,31 @@ 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_OVERCLOCK_ENABLE) !=
+ Config::LayerType::Base);
+ m_vi_clock_override_checkbox->setFont(vi_bf);
+ m_vi_clock_override_checkbox->setChecked(enable_vi_clock_override_widgets);
+
+ m_vi_clock_override_slider->setEnabled(enable_vi_clock_override_widgets);
+ m_vi_clock_override_slider_label->setEnabled(enable_vi_clock_override_widgets);
+
+ {
+ const QSignalBlocker blocker(m_vi_clock_override_slider);
+ m_vi_clock_override_slider->setValue(
+ static_cast(std::round(Config::Get(Config::MAIN_VI_OVERCLOCK) * 100.f)));
+ }
+
+ m_vi_clock_override_slider_label->setText([] {
+ int percent = static_cast(std::round(Config::Get(Config::MAIN_VI_OVERCLOCK) * 100.f));
+ float core_vps =
+ static_cast(Core::System::GetInstance().GetVideoInterface().GetTargetRefreshRate());
+ if (core_vps == 0.0f)
+ core_vps = 59.94f;
+ float vps = static_cast(core_vps * Config::Get(Config::MAIN_VI_OVERCLOCK));
+ 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 1607c1b3c0..6f701c6cb3 100644
--- a/Source/Core/DolphinQt/Settings/AdvancedPane.h
+++ b/Source/Core/DolphinQt/Settings/AdvancedPane.h
@@ -40,6 +40,11 @@ private:
QLabel* m_cpu_clock_override_slider_label;
QLabel* m_cpu_clock_override_description;
+ QCheckBox* m_vi_clock_override_checkbox;
+ QSlider* m_vi_clock_override_slider;
+ QLabel* m_vi_clock_override_slider_label;
+ QLabel* m_vi_clock_override_description;
+
QCheckBox* m_custom_rtc_checkbox;
QDateTimeEdit* m_custom_rtc_datetime;