diff options
| author | Aneesh Maganti <28660350+aminoa@users.noreply.github.com> | 2025-02-10 15:28:32 -0500 |
|---|---|---|
| committer | Admiral H. Curtiss <pikachu025@gmail.com> | 2025-02-16 23:15:12 +0100 |
| commit | fffb499da2fdde53e1ff25e17f2f718cd608167f (patch) | |
| tree | 007fd7dd4e761db3ffc70f2ffece0d1369f2cd43 | |
| parent | 3c44fe592b8db19bf7be5f5e1cb45e5cb0062950 (diff) | |
Core/HW: Add time tracking thread in CPU manager
Introduce method to track the time played for a game via time differences and TimePlayed methods. Threads are synchronized via Common::Event.
| -rw-r--r-- | Source/Core/Core/HW/CPU.cpp | 54 | ||||
| -rw-r--r-- | Source/Core/Core/HW/CPU.h | 4 |
2 files changed, 58 insertions, 0 deletions
diff --git a/Source/Core/Core/HW/CPU.cpp b/Source/Core/Core/HW/CPU.cpp index 1eae912476..487a33c6ff 100644 --- a/Source/Core/Core/HW/CPU.cpp +++ b/Source/Core/Core/HW/CPU.cpp @@ -10,12 +10,16 @@ #include "AudioCommon/AudioCommon.h" #include "Common/CommonTypes.h" #include "Common/Event.h" +#include "Common/Timer.h" #include "Core/CPUThreadConfigCallback.h" +#include "Core/Config/MainSettings.h" +#include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/Host.h" #include "Core/PowerPC/GDBStub.h" #include "Core/PowerPC/PowerPC.h" #include "Core/System.h" +#include "Core/TimePlayed.h" #include "VideoCommon/Fifo.h" namespace CPU @@ -63,6 +67,41 @@ void CPUManager::ExecutePendingJobs(std::unique_lock<std::mutex>& state_lock) } } +void CPUManager::StartTimePlayedTimer() +{ + // Steady clock for greater accuracy of timing + std::chrono::steady_clock timer; + auto prev_time = timer.now(); + + while (true) + { + const std::string game_id = SConfig::GetInstance().GetGameID(); + TimePlayed time_played(game_id); + auto curr_time = timer.now(); + + // Check that emulation is not paused + // If the emulation is paused, wait for SetStepping() to reactivate + if (m_state == State::Running) + { + const auto diff_time = + std::chrono::duration_cast<std::chrono::milliseconds>(curr_time - prev_time); + time_played.AddTime(diff_time); + } + else if (m_state == State::Stepping) + { + m_time_played_finish_sync.Wait(); + curr_time = timer.now(); + } + + prev_time = curr_time; + + if (m_state == State::PowerDown) + return; + + m_time_played_finish_sync.WaitFor(std::chrono::seconds(30)); + } +} + void CPUManager::Run() { auto& power_pc = m_system.GetPowerPC(); @@ -71,6 +110,13 @@ void CPUManager::Run() // We can't rely on PowerPC::Init doing it, since it's called from EmuThread. PowerPC::RoundingModeUpdated(power_pc.GetPPCState()); + // Start a separate time tracker thread + std::thread timing; + if (Config::Get(Config::MAIN_TIME_TRACKING)) + { + timing = std::thread(&CPUManager::StartTimePlayedTimer, this); + } + std::unique_lock state_lock(m_state_change_lock); while (m_state != State::PowerDown) { @@ -165,6 +211,13 @@ void CPUManager::Run() break; } } + + if (timing.joinable()) + { + m_time_played_finish_sync.Set(); + timing.join(); + } + state_lock.unlock(); Host_UpdateDisasmDialog(); } @@ -266,6 +319,7 @@ void CPUManager::SetStepping(bool stepping) else if (SetStateLocked(State::Running)) { m_state_cpu_cvar.notify_one(); + m_time_played_finish_sync.Set(); RunAdjacentSystems(true); } } diff --git a/Source/Core/Core/HW/CPU.h b/Source/Core/Core/HW/CPU.h index 57e8a31a29..b73471136d 100644 --- a/Source/Core/Core/HW/CPU.h +++ b/Source/Core/Core/HW/CPU.h @@ -8,6 +8,8 @@ #include <mutex> #include <queue> +#include "Common/Event.h" + namespace Common { class Event; @@ -102,6 +104,7 @@ public: private: void FlushStepSyncEventLocked(); void ExecutePendingJobs(std::unique_lock<std::mutex>& state_lock); + void StartTimePlayedTimer(); void RunAdjacentSystems(bool running); bool SetStateLocked(State s); @@ -133,6 +136,7 @@ private: bool m_state_cpu_step_instruction = false; Common::Event* m_state_cpu_step_instruction_sync = nullptr; std::queue<std::function<void()>> m_pending_jobs; + Common::Event m_time_played_finish_sync; Core::System& m_system; }; |
