mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-28 01:49:33 -06:00
Core: Add VBI Frequency Override
This feature allows overriding the frequency of the Vertical Blank Interrupt. For many games, this means that their gameplay speed will change without affecting audio, which would be useful by itself (e.g. grinding in RPGs). However, there are games that use delta time for their game logic, which allows them to be played at >60 FPS at the same gameplay speed! Some games aren't dynamic though, and require a patch to adjust their game speed variable.
This commit is contained in:
@ -100,6 +100,12 @@ enum class BooleanSetting(
|
|||||||
"OverclockEnable",
|
"OverclockEnable",
|
||||||
false
|
false
|
||||||
),
|
),
|
||||||
|
MAIN_VI_OVERCLOCK_ENABLE(
|
||||||
|
Settings.FILE_DOLPHIN,
|
||||||
|
Settings.SECTION_INI_CORE,
|
||||||
|
"VIOverclockEnable",
|
||||||
|
false
|
||||||
|
),
|
||||||
MAIN_RAM_OVERRIDE_ENABLE(
|
MAIN_RAM_OVERRIDE_ENABLE(
|
||||||
Settings.FILE_DOLPHIN,
|
Settings.FILE_DOLPHIN,
|
||||||
Settings.SECTION_INI_CORE,
|
Settings.SECTION_INI_CORE,
|
||||||
|
@ -11,6 +11,7 @@ enum class FloatSetting(
|
|||||||
// These entries have the same names and order as in C++, just for consistency.
|
// 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_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_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);
|
GFX_CC_GAME_GAMMA(Settings.FILE_GFX, Settings.SECTION_GFX_COLOR_CORRECTION, "GameGamma", 2.35f);
|
||||||
|
|
||||||
override val isOverridden: Boolean
|
override val isOverridden: Boolean
|
||||||
|
@ -1027,6 +1027,27 @@ class SettingsFragmentPresenter(
|
|||||||
false
|
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,
|
||||||
|
500f,
|
||||||
|
"%",
|
||||||
|
1f,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val mem1Size = ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM1_SIZE)
|
val mem1Size = ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM1_SIZE)
|
||||||
val mem2Size = ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM2_SIZE)
|
val mem2Size = ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM2_SIZE)
|
||||||
|
@ -376,7 +376,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="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="clock_override">Clock Override</string>
|
||||||
<string name="overclock_enable">Override Emulated CPU Clock Speed</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">On games that have an unstable frame rate despite full emulation speed, higher values can improve their performance, requiring a powerful device. Lower values reduce the emulated console\'s performance, but improve the emulation speed.</string>
|
||||||
<string name="overclock_title">Emulated CPU Clock Speed</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="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>
|
<string name="memory_override">Memory Override</string>
|
||||||
@ -385,6 +385,10 @@
|
|||||||
<string name="main_mem1_size">MEM1 Size</string>
|
<string name="main_mem1_size">MEM1 Size</string>
|
||||||
<string name="main_mem2_size">MEM2 Size</string>
|
<string name="main_mem2_size">MEM2 Size</string>
|
||||||
<string name="gpu_options">GPU Options</string>
|
<string name="gpu_options">GPU Options</string>
|
||||||
|
<string name="vi_overclock_enable">Override VBI Frequency</string>
|
||||||
|
<string name="vi_overclock_enable_description">Makes games run at a different frame rate, making the emulation less demanding when lowered, or improving smoothness when increased. This may affect gameplay speed, as it is often tied to the frame rate.</string>
|
||||||
|
<string name="vi_overclock_title">VBI Frequency</string>
|
||||||
|
<string name="vi_overclock_title_description">Adjusts the VBI frequency rate if \"Override VBI Frequency\" is enabled.\nAlso adjusts the emulated CPU\'s clock speed, to keep it relatively the same.</string>
|
||||||
<string name="synchronize_gpu_thread">Synchronize GPU Thread</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="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>
|
<string name="custom_rtc_options">Custom RTC Options</string>
|
||||||
|
@ -222,6 +222,8 @@ const Info<bool> MAIN_PRECISION_FRAME_TIMING{{System::Main, "Core", "PrecisionFr
|
|||||||
DEFAULT_PRECISION_FRAME_TIMING};
|
DEFAULT_PRECISION_FRAME_TIMING};
|
||||||
const Info<float> MAIN_OVERCLOCK{{System::Main, "Core", "Overclock"}, 1.0f};
|
const Info<float> MAIN_OVERCLOCK{{System::Main, "Core", "Overclock"}, 1.0f};
|
||||||
const Info<bool> MAIN_OVERCLOCK_ENABLE{{System::Main, "Core", "OverclockEnable"}, false};
|
const Info<bool> MAIN_OVERCLOCK_ENABLE{{System::Main, "Core", "OverclockEnable"}, false};
|
||||||
|
const Info<float> MAIN_VI_OVERCLOCK{{System::Main, "Core", "VIOverclock"}, 1.0f};
|
||||||
|
const Info<bool> MAIN_VI_OVERCLOCK_ENABLE{{System::Main, "Core", "VIOverclockEnable"}, false};
|
||||||
const Info<bool> MAIN_RAM_OVERRIDE_ENABLE{{System::Main, "Core", "RAMOverrideEnable"}, 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_MEM1_SIZE{{System::Main, "Core", "MEM1Size"}, Memory::MEM1_SIZE_RETAIL};
|
||||||
const Info<u32> MAIN_MEM2_SIZE{{System::Main, "Core", "MEM2Size"}, Memory::MEM2_SIZE_RETAIL};
|
const Info<u32> MAIN_MEM2_SIZE{{System::Main, "Core", "MEM2Size"}, Memory::MEM2_SIZE_RETAIL};
|
||||||
|
@ -128,6 +128,8 @@ extern const Info<float> MAIN_EMULATION_SPEED;
|
|||||||
extern const Info<bool> MAIN_PRECISION_FRAME_TIMING;
|
extern const Info<bool> MAIN_PRECISION_FRAME_TIMING;
|
||||||
extern const Info<float> MAIN_OVERCLOCK;
|
extern const Info<float> MAIN_OVERCLOCK;
|
||||||
extern const Info<bool> MAIN_OVERCLOCK_ENABLE;
|
extern const Info<bool> MAIN_OVERCLOCK_ENABLE;
|
||||||
|
extern const Info<float> MAIN_VI_OVERCLOCK;
|
||||||
|
extern const Info<bool> MAIN_VI_OVERCLOCK_ENABLE;
|
||||||
extern const Info<bool> MAIN_RAM_OVERRIDE_ENABLE;
|
extern const Info<bool> MAIN_RAM_OVERRIDE_ENABLE;
|
||||||
extern const Info<u32> MAIN_MEM1_SIZE;
|
extern const Info<u32> MAIN_MEM1_SIZE;
|
||||||
extern const Info<u32> MAIN_MEM2_SIZE;
|
extern const Info<u32> MAIN_MEM2_SIZE;
|
||||||
|
@ -42,6 +42,8 @@ public:
|
|||||||
layer->Set(Config::MAIN_DSP_HLE, m_settings.dsp_hle);
|
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_ENABLE, m_settings.oc_enable);
|
||||||
layer->Set(Config::MAIN_OVERCLOCK, m_settings.oc_factor);
|
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)
|
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
|
||||||
layer->Set(Config::GetInfoForEXIDevice(slot), m_settings.exi_device[slot]);
|
layer->Set(Config::GetInfoForEXIDevice(slot), m_settings.exi_device[slot]);
|
||||||
layer->Set(Config::MAIN_MEMORY_CARD_SIZE, m_settings.memcard_size_override);
|
layer->Set(Config::MAIN_MEMORY_CARD_SIZE, m_settings.memcard_size_override);
|
||||||
|
@ -119,7 +119,9 @@ void CoreTimingManager::Shutdown()
|
|||||||
void CoreTimingManager::RefreshConfig()
|
void CoreTimingManager::RefreshConfig()
|
||||||
{
|
{
|
||||||
m_config_oc_factor =
|
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_oc_inv_factor = 1.0f / m_config_oc_factor;
|
||||||
m_config_sync_on_skip_idle = Config::Get(Config::MAIN_SYNC_ON_SKIP_IDLE);
|
m_config_sync_on_skip_idle = Config::Get(Config::MAIN_SYNC_ON_SKIP_IDLE);
|
||||||
|
|
||||||
@ -482,6 +484,11 @@ bool CoreTimingManager::GetVISkip() const
|
|||||||
return m_throttle_disable_vi_int && g_ActiveConfig.bVISkip && !Core::WantsDeterminism();
|
return m_throttle_disable_vi_int && g_ActiveConfig.bVISkip && !Core::WantsDeterminism();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CoreTimingManager::GetOverclock() const
|
||||||
|
{
|
||||||
|
return m_config_oc_factor;
|
||||||
|
}
|
||||||
|
|
||||||
bool CoreTimingManager::UseSyncOnSkipIdle() const
|
bool CoreTimingManager::UseSyncOnSkipIdle() const
|
||||||
{
|
{
|
||||||
return m_config_sync_on_skip_idle;
|
return m_config_sync_on_skip_idle;
|
||||||
|
@ -165,6 +165,8 @@ public:
|
|||||||
// Used by VideoInterface
|
// Used by VideoInterface
|
||||||
bool GetVISkip() const;
|
bool GetVISkip() const;
|
||||||
|
|
||||||
|
float GetOverclock() const;
|
||||||
|
|
||||||
bool UseSyncOnSkipIdle() const;
|
bool UseSyncOnSkipIdle() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -365,6 +365,8 @@ void DolphinAnalytics::MakePerGameBuilder()
|
|||||||
builder.AddData("cfg-audio-backend", Config::Get(Config::MAIN_AUDIO_BACKEND));
|
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-enable", Config::Get(Config::MAIN_OVERCLOCK_ENABLE));
|
||||||
builder.AddData("cfg-oc-factor", Config::Get(Config::MAIN_OVERCLOCK));
|
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));
|
builder.AddData("cfg-render-to-main", Config::Get(Config::MAIN_RENDER_TO_MAIN));
|
||||||
if (g_video_backend)
|
if (g_video_backend)
|
||||||
{
|
{
|
||||||
|
@ -13,8 +13,10 @@
|
|||||||
#include "Common/Config/Config.h"
|
#include "Common/Config/Config.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
|
||||||
|
#include "VideoCommon/OnScreenDisplay.h"
|
||||||
#include "VideoCommon/PerformanceMetrics.h"
|
#include "VideoCommon/PerformanceMetrics.h"
|
||||||
|
|
||||||
|
#include "Core/AchievementManager.h"
|
||||||
#include "Core/Config/GraphicsSettings.h"
|
#include "Core/Config/GraphicsSettings.h"
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
#include "Core/Config/SYSCONFSettings.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{{
|
static constexpr std::array<u32, 2> CLOCK_FREQUENCIES{{
|
||||||
27000000,
|
27000000,
|
||||||
@ -173,6 +178,22 @@ void VideoInterfaceManager::Preset(bool _bNTSC)
|
|||||||
void VideoInterfaceManager::Init()
|
void VideoInterfaceManager::Init()
|
||||||
{
|
{
|
||||||
Preset(true);
|
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 frequency is 100% in Hardcore Mode");
|
||||||
|
}
|
||||||
|
UpdateRefreshRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
void VideoInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
@ -488,7 +509,8 @@ float VideoInterfaceManager::GetAspectRatio() const
|
|||||||
float vertical_period = tick_length * GetTicksPerField();
|
float vertical_period = tick_length * GetTicksPerField();
|
||||||
float horizontal_period = tick_length * GetTicksPerHalfLine() * 2;
|
float horizontal_period = tick_length * GetTicksPerHalfLine() * 2;
|
||||||
float vertical_active_area = active_lines * horizontal_period;
|
float vertical_active_area = active_lines * horizontal_period;
|
||||||
float horizontal_active_area = tick_length * GetTicksPerSample() * active_width_samples;
|
float horizontal_active_area =
|
||||||
|
tick_length * GetTicksPerSample() * active_width_samples / m_config_vi_oc_factor;
|
||||||
|
|
||||||
// We are approximating the horizontal/vertical flyback transformers that control the
|
// We are approximating the horizontal/vertical flyback transformers that control the
|
||||||
// position of the electron beam on the screen. Our flyback transformers create a
|
// position of the electron beam on the screen. Our flyback transformers create a
|
||||||
@ -707,7 +729,11 @@ void VideoInterfaceManager::UpdateParameters()
|
|||||||
m_vblank_timing_even.PRB - odd_even_psb_diff;
|
m_vblank_timing_even.PRB - odd_even_psb_diff;
|
||||||
m_even_field_last_hl = m_even_field_first_hl + acv_hl - 1;
|
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_numerator = m_system.GetSystemTimers().GetTicksPerSecond() * 2;
|
||||||
m_target_refresh_rate_denominator = GetTicksPerEvenField() + GetTicksPerOddField();
|
m_target_refresh_rate_denominator = GetTicksPerEvenField() + GetTicksPerOddField();
|
||||||
m_target_refresh_rate =
|
m_target_refresh_rate =
|
||||||
@ -736,7 +762,7 @@ u32 VideoInterfaceManager::GetTicksPerSample() const
|
|||||||
|
|
||||||
u32 VideoInterfaceManager::GetTicksPerHalfLine() const
|
u32 VideoInterfaceManager::GetTicksPerHalfLine() const
|
||||||
{
|
{
|
||||||
return GetTicksPerSample() * m_h_timing_0.HLW;
|
return GetTicksPerSample() * m_h_timing_0.HLW / m_config_vi_oc_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 VideoInterfaceManager::GetTicksPerField() const
|
u32 VideoInterfaceManager::GetTicksPerField() const
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/Config/Config.h"
|
||||||
|
|
||||||
enum class FieldType;
|
enum class FieldType;
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
@ -407,6 +408,9 @@ private:
|
|||||||
void BeginField(FieldType field, u64 ticks);
|
void BeginField(FieldType field, u64 ticks);
|
||||||
void EndField(FieldType field, u64 ticks);
|
void EndField(FieldType field, u64 ticks);
|
||||||
|
|
||||||
|
void RefreshConfig();
|
||||||
|
void UpdateRefreshRate();
|
||||||
|
|
||||||
// Registers listed in order:
|
// Registers listed in order:
|
||||||
UVIVerticalTimingRegister m_vertical_timing_register;
|
UVIVerticalTimingRegister m_vertical_timing_register;
|
||||||
UVIDisplayControlRegister m_display_control_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_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
|
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;
|
Core::System& m_system;
|
||||||
};
|
};
|
||||||
} // namespace VideoInterface
|
} // namespace VideoInterface
|
||||||
|
@ -68,9 +68,7 @@ IPCReply GetCPUSpeed(Core::System& system, const IOCtlVRequest& request)
|
|||||||
return IPCReply(IPC_EINVAL);
|
return IPCReply(IPC_EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool overclock_enabled = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
|
const bool oc = system.GetCoreTiming().GetOverclock();
|
||||||
const float oc = overclock_enabled ? Config::Get(Config::MAIN_OVERCLOCK) : 1.0f;
|
|
||||||
|
|
||||||
const u32 core_clock = u32(float(system.GetSystemTimers().GetTicksPerSecond()) * oc);
|
const u32 core_clock = u32(float(system.GetSystemTimers().GetTicksPerSecond()) * oc);
|
||||||
|
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
@ -862,6 +862,8 @@ void NetPlayClient::OnStartGame(sf::Packet& packet)
|
|||||||
packet >> m_net_settings.allow_sd_writes;
|
packet >> m_net_settings.allow_sd_writes;
|
||||||
packet >> m_net_settings.oc_enable;
|
packet >> m_net_settings.oc_enable;
|
||||||
packet >> m_net_settings.oc_factor;
|
packet >> m_net_settings.oc_factor;
|
||||||
|
packet >> m_net_settings.vi_oc_enable;
|
||||||
|
packet >> m_net_settings.vi_oc_factor;
|
||||||
|
|
||||||
for (auto slot : ExpansionInterface::SLOTS)
|
for (auto slot : ExpansionInterface::SLOTS)
|
||||||
packet >> m_net_settings.exi_device[slot];
|
packet >> m_net_settings.exi_device[slot];
|
||||||
|
@ -47,6 +47,8 @@ struct NetSettings
|
|||||||
bool allow_sd_writes = false;
|
bool allow_sd_writes = false;
|
||||||
bool oc_enable = false;
|
bool oc_enable = false;
|
||||||
float oc_factor = 0;
|
float oc_factor = 0;
|
||||||
|
bool vi_oc_enable = false;
|
||||||
|
float vi_oc_factor = 0;
|
||||||
Common::EnumMap<ExpansionInterface::EXIDeviceType, ExpansionInterface::MAX_SLOT> exi_device{};
|
Common::EnumMap<ExpansionInterface::EXIDeviceType, ExpansionInterface::MAX_SLOT> exi_device{};
|
||||||
int memcard_size_override = -1;
|
int memcard_size_override = -1;
|
||||||
|
|
||||||
|
@ -1376,6 +1376,8 @@ bool NetPlayServer::SetupNetSettings()
|
|||||||
settings.allow_sd_writes = Config::Get(Config::MAIN_ALLOW_SD_WRITES);
|
settings.allow_sd_writes = Config::Get(Config::MAIN_ALLOW_SD_WRITES);
|
||||||
settings.oc_enable = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
|
settings.oc_enable = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
|
||||||
settings.oc_factor = Config::Get(Config::MAIN_OVERCLOCK);
|
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)
|
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
|
||||||
{
|
{
|
||||||
@ -1603,6 +1605,8 @@ bool NetPlayServer::StartGame()
|
|||||||
spac << m_settings.allow_sd_writes;
|
spac << m_settings.allow_sd_writes;
|
||||||
spac << m_settings.oc_enable;
|
spac << m_settings.oc_enable;
|
||||||
spac << m_settings.oc_factor;
|
spac << m_settings.oc_factor;
|
||||||
|
spac << m_settings.vi_oc_enable;
|
||||||
|
spac << m_settings.vi_oc_factor;
|
||||||
|
|
||||||
for (auto slot : ExpansionInterface::SLOTS)
|
for (auto slot : ExpansionInterface::SLOTS)
|
||||||
spac << static_cast<int>(m_settings.exi_device[slot]);
|
spac << static_cast<int>(m_settings.exi_device[slot]);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
|
#include "Core/HW/VideoInterface.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
|
||||||
@ -111,14 +112,47 @@ void AdvancedPane::CreateLayout()
|
|||||||
|
|
||||||
m_cpu_clock_override_checkbox->SetDescription(
|
m_cpu_clock_override_checkbox->SetDescription(
|
||||||
tr("Adjusts the emulated CPU's clock rate.<br><br>"
|
tr("Adjusts the emulated CPU's clock rate.<br><br>"
|
||||||
"Higher values may make variable-framerate games run at a higher framerate, "
|
"On games that have an unstable frame rate despite full emulation speed, "
|
||||||
"at the expense of performance. Lower values may activate a game's "
|
"higher values can improve their performance, requiring a powerful device. "
|
||||||
"internal frameskip, potentially improving performance.<br><br>"
|
"Lower values reduce the emulated console's performance, but improve the "
|
||||||
"<b>WARNING</b>: Changing this from the default (100%) can and will "
|
"emulation speed.<br><br>"
|
||||||
|
"WARNING: Changing this from the default (100%) can and will "
|
||||||
"break games and cause glitches. Do so at your own risk. "
|
"break games and cause glitches. Do so at your own risk. "
|
||||||
"Please do not report bugs that occur with a non-default clock."
|
"Please do not report bugs that occur with a non-default clock."
|
||||||
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>"));
|
"<br><br><dolphin_emphasis>If unsure, leave this unchecked.</dolphin_emphasis>"));
|
||||||
|
|
||||||
|
auto* vi_rate_override = new QGroupBox(tr("VBI Frequency 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_OVERCLOCK_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 VBI frequency. Also adjusts the emulated CPU's "
|
||||||
|
"clock rate, to keep it relatively the same.<br><br>"
|
||||||
|
"Makes games run at a different frame rate, making the emulation less "
|
||||||
|
"demanding when lowered, or improving smoothness when increased. This may "
|
||||||
|
"affect gameplay 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 = new QGroupBox(tr("Memory Override"));
|
||||||
auto* ram_override_layout = new QVBoxLayout();
|
auto* ram_override_layout = new QVBoxLayout();
|
||||||
ram_override->setLayout(ram_override_layout);
|
ram_override->setLayout(ram_override_layout);
|
||||||
@ -199,6 +233,18 @@ void AdvancedPane::ConnectLayout()
|
|||||||
Update();
|
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_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();
|
||||||
|
});
|
||||||
|
|
||||||
connect(m_mem1_override_slider, &QSlider::valueChanged, [this](int slider_value) {
|
connect(m_mem1_override_slider, &QSlider::valueChanged, [this](int slider_value) {
|
||||||
const u32 mem1_size = m_mem1_override_slider->value() * 0x100000;
|
const u32 mem1_size = m_mem1_override_slider->value() * 0x100000;
|
||||||
Config::SetBaseOrCurrent(Config::MAIN_MEM1_SIZE, mem1_size);
|
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 is_uninitialized = Core::IsUninitialized(Core::System::GetInstance());
|
||||||
const bool enable_cpu_clock_override_widgets = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
|
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_OVERCLOCK_ENABLE);
|
||||||
const bool enable_ram_override_widgets = Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE);
|
const bool enable_ram_override_widgets = Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE);
|
||||||
const bool enable_custom_rtc_widgets =
|
const bool enable_custom_rtc_widgets =
|
||||||
Config::Get(Config::MAIN_CUSTOM_RTC_ENABLE) && is_uninitialized;
|
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));
|
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_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_OVERCLOCK) * 100.f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vi_rate_override_slider_label->setText([] {
|
||||||
|
int percent = static_cast<int>(std::round(Config::Get(Config::MAIN_VI_OVERCLOCK) * 100.f));
|
||||||
|
float vps =
|
||||||
|
static_cast<float>(Core::System::GetInstance().GetVideoInterface().GetTargetRefreshRate());
|
||||||
|
if (vps == 0.0f || !Config::Get(Config::MAIN_VI_OVERCLOCK_ENABLE))
|
||||||
|
vps = 59.94f * 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);
|
m_ram_override_checkbox->setEnabled(is_uninitialized);
|
||||||
SignalBlocking(m_ram_override_checkbox)->setChecked(enable_ram_override_widgets);
|
SignalBlocking(m_ram_override_checkbox)->setChecked(enable_ram_override_widgets);
|
||||||
|
|
||||||
|
@ -39,6 +39,10 @@ private:
|
|||||||
QSlider* m_cpu_clock_override_slider;
|
QSlider* m_cpu_clock_override_slider;
|
||||||
QLabel* m_cpu_clock_override_slider_label;
|
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;
|
ConfigBool* m_custom_rtc_checkbox;
|
||||||
QDateTimeEdit* m_custom_rtc_datetime;
|
QDateTimeEdit* m_custom_rtc_datetime;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user