This commit is contained in:
SuperSamus 2025-04-23 23:49:14 -05:00 committed by GitHub
commit a915b34d5c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 175 additions and 12 deletions

View file

@ -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,

View file

@ -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

View file

@ -1023,6 +1023,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)

View file

@ -374,7 +374,7 @@
<string name="enable_cpu_cache_description">Enables emulation of the CPU write-back cache. Enabling will have a significant impact on performance. This should be left disabled unless absolutely needed.</string>
<string name="clock_override">Clock Override</string>
<string name="overclock_enable">Override Emulated CPU Clock Speed</string>
<string name="overclock_enable_description">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.</string>
<string name="overclock_enable_description">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.</string>
<string name="overclock_title">Emulated CPU Clock Speed</string>
<string name="overclock_title_description">Adjusts the emulated CPU\'s clock rate if \"Override Emulated CPU Clock Speed\" is enabled.</string>
<string name="memory_override">Memory Override</string>
@ -383,6 +383,10 @@
<string name="main_mem1_size">MEM1 Size</string>
<string name="main_mem2_size">MEM2 Size</string>
<string name="gpu_options">GPU Options</string>
<string name="vi_frequency_enable">Override VBI Frequency</string>
<string name="vi_frequency_enable_description">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.</string>
<string name="vi_frequency_title">Emulated VBI Clock Speed</string>
<string name="vi_frequency_title_description">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.</string>
<string name="synchronize_gpu_thread">Synchronize GPU Thread</string>
<string name="synchronize_gpu_thread_description">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!</string>
<string name="custom_rtc_options">Custom RTC Options</string>

View file

@ -222,6 +222,8 @@ const Info<bool> MAIN_PRECISION_FRAME_TIMING{{System::Main, "Core", "PrecisionFr
DEFAULT_PRECISION_FRAME_TIMING};
const Info<float> MAIN_OVERCLOCK{{System::Main, "Core", "Overclock"}, 1.0f};
const Info<bool> MAIN_OVERCLOCK_ENABLE{{System::Main, "Core", "OverclockEnable"}, false};
const Info<float> MAIN_VI_FREQUENCY{{System::Main, "Core", "VIFrequency"}, 1.0f};
const Info<bool> MAIN_VI_FREQUENCY_ENABLE{{System::Main, "Core", "VIFrequencyEnable"}, false};
const Info<bool> MAIN_RAM_OVERRIDE_ENABLE{{System::Main, "Core", "RAMOverrideEnable"}, false};
const Info<u32> MAIN_MEM1_SIZE{{System::Main, "Core", "MEM1Size"}, Memory::MEM1_SIZE_RETAIL};
const Info<u32> MAIN_MEM2_SIZE{{System::Main, "Core", "MEM2Size"}, Memory::MEM2_SIZE_RETAIL};

View file

@ -128,6 +128,8 @@ extern const Info<float> MAIN_EMULATION_SPEED;
extern const Info<bool> MAIN_PRECISION_FRAME_TIMING;
extern const Info<float> MAIN_OVERCLOCK;
extern const Info<bool> MAIN_OVERCLOCK_ENABLE;
extern const Info<float> MAIN_VI_FREQUENCY;
extern const Info<bool> MAIN_VI_FREQUENCY_ENABLE;
extern const Info<bool> MAIN_RAM_OVERRIDE_ENABLE;
extern const Info<u32> MAIN_MEM1_SIZE;
extern const Info<u32> MAIN_MEM2_SIZE;

View file

@ -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);

View file

@ -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;

View file

@ -165,6 +165,8 @@ public:
// Used by VideoInterface
bool GetVISkip() const;
float GetOverclock() const;
bool UseSyncOnSkipIdle() const;
private:

View file

@ -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)
{

View file

@ -125,7 +125,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);
}
@ -279,7 +279,7 @@ void SystemTimersManager::Init()
m_event_type_patch_engine = core_timing.RegisterEvent("PatchEngine", PatchEngineCallback);
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(

View file

@ -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<u32, 2> 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_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");
}
}
void VideoInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
@ -744,6 +764,11 @@ u32 VideoInterfaceManager::GetTicksPerField() const
return GetTicksPerEvenField();
}
u32 VideoInterfaceManager::GetTicksPerViCallback() const
{
return static_cast<u32>(GetTicksPerHalfLine() / m_config_vi_freq_factor);
}
void VideoInterfaceManager::LogField(FieldType field, u32 xfb_address) const
{
static constexpr std::array<const char*, 2> field_type_names{{"Odd", "Even"}};

View file

@ -7,6 +7,7 @@
#include <memory>
#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_freq_factor = 0.0f;
Config::ConfigChangedCallbackID m_config_changed_callback_id;
Core::System& m_system;
};
} // namespace VideoInterface

View file

@ -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();

View file

@ -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];

View file

@ -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<ExpansionInterface::EXIDeviceType, ExpansionInterface::MAX_SLOT> exi_device{};
int memcard_size_override = -1;

View file

@ -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<int>(m_settings.exi_device[slot]);

View file

@ -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.<br><br>"
"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.<br><br>"
"<b>WARNING</b>: 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.<br><br>"
"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."
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>"));
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.<br><br>"
"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.<br><br>"
"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."
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>"));
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,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_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<int>(std::round(Config::Get(Config::MAIN_VI_FREQUENCY) * 100.f)));
}
m_vi_rate_override_slider_label->setText([] {
int percent = static_cast<int>(std::round(Config::Get(Config::MAIN_VI_FREQUENCY) * 100.f));
float core_vps =
static_cast<float>(Core::System::GetInstance().GetVideoInterface().GetTargetRefreshRate());
if (core_vps == 0.0f)
core_vps = 59.94f;
float vps = static_cast<float>(core_vps * 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);

View file

@ -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;