diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index 5577fba8c8..dc6a48aa7f 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -45,6 +45,7 @@ const Info MAIN_ACCURATE_CPU_CACHE{{System::Main, "Core", "AccurateCPUCach const Info MAIN_DSP_HLE{{System::Main, "Core", "DSPHLE"}, true}; const Info MAIN_MAX_FALLBACK{{System::Main, "Core", "MaxFallback"}, 100}; const Info MAIN_TIMING_VARIANCE{{System::Main, "Core", "TimingVariance"}, 40}; +const Info MAIN_CORRECT_TIME_DRIFT{{System::Main, "Core", "CorrectTimeDrift"}, false}; const Info MAIN_CPU_THREAD{{System::Main, "Core", "CPUThread"}, true}; const Info MAIN_SYNC_ON_SKIP_IDLE{{System::Main, "Core", "SyncOnSkipIdle"}, true}; const Info MAIN_DEFAULT_ISO{{System::Main, "Core", "DefaultISO"}, ""}; diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index 4e3ad8830f..f732d68645 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -63,6 +63,7 @@ extern const Info MAIN_ACCURATE_CPU_CACHE; extern const Info MAIN_DSP_HLE; extern const Info MAIN_MAX_FALLBACK; extern const Info MAIN_TIMING_VARIANCE; +extern const Info MAIN_CORRECT_TIME_DRIFT; extern const Info MAIN_CPU_THREAD; extern const Info MAIN_SYNC_ON_SKIP_IDLE; extern const Info MAIN_DEFAULT_ISO; diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp index f4c7d13fc0..261fa454fd 100644 --- a/Source/Core/Core/CoreTiming.cpp +++ b/Source/Core/Core/CoreTiming.cpp @@ -105,10 +105,20 @@ void CoreTimingManager::Init() m_last_oc_factor = m_config_oc_factor; m_globals.last_OC_factor_inverted = m_config_oc_inv_factor; + + m_on_state_changed_handle = Core::AddOnStateChangedCallback([this](Core::State state) { + if (state == Core::State::Running) + { + // We don't want Throttle to attempt catch-up for all the time lost while paused. + ResetThrottle(GetTicks()); + } + }); } void CoreTimingManager::Shutdown() { + Core::RemoveOnStateChangedCallback(&m_on_state_changed_handle); + std::lock_guard lk(m_ts_write_lock); MoveEvents(); ClearPendingEvents(); @@ -131,6 +141,8 @@ void CoreTimingManager::RefreshConfig() m_max_variance = std::chrono::duration_cast
(DT_ms(Config::Get(Config::MAIN_TIMING_VARIANCE))); + m_correct_time_drift = Config::Get(Config::MAIN_CORRECT_TIME_DRIFT); + if (AchievementManager::GetInstance().IsHardcoreModeActive() && Config::Get(Config::MAIN_EMULATION_SPEED) < 1.0f && Config::Get(Config::MAIN_EMULATION_SPEED) > 0.0f) @@ -428,7 +440,9 @@ void CoreTimingManager::Throttle(const s64 target_cycle) const TimePoint time = Clock::now(); const TimePoint min_target = time - m_max_fallback; - if (target_time < min_target) + + // "Correct Time Drift" setting prevents timing relaxing. + if (!m_correct_time_drift && target_time < min_target) { // Core is running too slow.. i.e. CPU bottleneck. const DT adjustment = min_target - target_time; diff --git a/Source/Core/Core/CoreTiming.h b/Source/Core/Core/CoreTiming.h index ae0dccd38c..8761a45c95 100644 --- a/Source/Core/Core/CoreTiming.h +++ b/Source/Core/Core/CoreTiming.h @@ -211,6 +211,7 @@ private: DT m_max_fallback = {}; DT m_max_variance = {}; + bool m_correct_time_drift = false; double m_emulation_speed = 1.0; bool IsSpeedUnlimited() const; @@ -225,6 +226,8 @@ private: std::atomic_bool m_use_precision_timer = false; Common::PrecisionTimer m_precision_cpu_timer; Common::PrecisionTimer m_precision_gpu_timer; + + int m_on_state_changed_handle; }; } // namespace CoreTiming diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp index 31e73a5b34..d9746b8579 100644 --- a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp +++ b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp @@ -89,6 +89,18 @@ void AdvancedPane::CreateLayout() "needed.

If unsure, leave this unchecked.")); cpu_options_group_layout->addWidget(m_accurate_cpu_cache_checkbox); + auto* const timing_group = new QGroupBox(tr("Timing")); + main_layout->addWidget(timing_group); + auto* timing_group_layout = new QVBoxLayout{timing_group}; + auto* const correct_time_drift = + new ConfigBool{tr("Correct Time Drift"), Config::MAIN_CORRECT_TIME_DRIFT}; + correct_time_drift->SetDescription( + tr("Allow the emulated console to run fast after stutters," + "
pursuing accurate overall elapsed time unless paused or speed-adjusted." + "

This may be useful for internet play." + "

If unsure, leave this unchecked.")); + timing_group_layout->addWidget(correct_time_drift); + auto* clock_override = new QGroupBox(tr("Clock Override")); auto* clock_override_layout = new QVBoxLayout(); clock_override->setLayout(clock_override_layout);