Core/SystemTimers: Refactor to class, move to System.

This commit is contained in:
Admiral H. Curtiss 2024-01-04 23:07:50 +01:00
parent 9c91b5edca
commit 07c035e659
No known key found for this signature in database
GPG Key ID: F051B4C4044F33FB
35 changed files with 258 additions and 185 deletions

View File

@ -257,7 +257,8 @@ void Interpreter::WriteControlRegister(u16 val)
val &= ~CR_INIT;
val |= CR_INIT_CODE;
// Number obtained from real hardware on a Wii, but it's not perfectly consistent
state.control_reg_init_code_clear_time = SystemTimers::GetFakeTimeBase() + 130;
state.control_reg_init_code_clear_time =
Core::System::GetInstance().GetSystemTimers().GetFakeTimeBase() + 130;
}
// update cr
@ -269,10 +270,11 @@ u16 Interpreter::ReadControlRegister()
auto& state = m_dsp_core.DSPState();
if ((state.control_reg & CR_INIT_CODE) != 0)
{
if (SystemTimers::GetFakeTimeBase() >= state.control_reg_init_code_clear_time)
auto& system = Core::System::GetInstance();
if (system.GetSystemTimers().GetFakeTimeBase() >= state.control_reg_init_code_clear_time)
state.control_reg &= ~CR_INIT_CODE;
else
Core::System::GetInstance().GetCoreTiming().ForceExceptionCheck(50); // Keep checking
system.GetCoreTiming().ForceExceptionCheck(50); // Keep checking
}
return state.control_reg;
}

View File

@ -410,8 +410,9 @@ FifoPlayer& FifoPlayer::GetInstance()
void FifoPlayer::WriteFrame(const FifoFrameInfo& frame, const AnalyzedFrameInfo& info)
{
// Core timing information
auto& vi = Core::System::GetInstance().GetVideoInterface();
m_CyclesPerFrame = static_cast<u64>(SystemTimers::GetTicksPerSecond()) *
auto& system = Core::System::GetInstance();
auto& vi = system.GetVideoInterface();
m_CyclesPerFrame = static_cast<u64>(system.GetSystemTimers().GetTicksPerSecond()) *
vi.GetTargetRefreshRateDenominator() / vi.GetTargetRefreshRateNumerator();
m_ElapsedCycles = 0;
m_FrameFifoSize = static_cast<u32>(frame.fifoData.size());

View File

@ -184,7 +184,7 @@ void AudioInterfaceManager::SetAISSampleRate(SampleRate sample_rate)
m_ais_sample_rate_divisor = Get48KHzSampleRateDivisor();
}
m_cpu_cycles_per_sample = static_cast<u64>(SystemTimers::GetTicksPerSecond()) *
m_cpu_cycles_per_sample = static_cast<u64>(m_system.GetSystemTimers().GetTicksPerSecond()) *
m_ais_sample_rate_divisor / Mixer::FIXED_SAMPLE_RATE_DIVIDEND;
SoundStream* sound_stream = m_system.GetSoundStream();
sound_stream->GetMixer()->SetStreamInputSampleRateDivisor(m_ais_sample_rate_divisor);

View File

@ -55,7 +55,7 @@ u32 DSPHLE::DSP_UpdateRate()
{
// AX HLE uses 3ms (Wii) or 5ms (GC) timing period
// But to be sure, just update the HLE every ms.
return SystemTimers::GetTicksPerSecond() / 1000;
return Core::System::GetInstance().GetSystemTimers().GetTicksPerSecond() / 1000;
}
void DSPHLE::SendMailToDSP(u32 mail)
@ -221,7 +221,8 @@ u16 DSPHLE::DSP_WriteControlRegister(u16 value)
SetUCode(UCODE_INIT_AUDIO_SYSTEM);
temp.DSPInitCode = 1;
// Number obtained from real hardware on a Wii, but it's not perfectly consistent
m_control_reg_init_code_clear_time = SystemTimers::GetFakeTimeBase() + 130;
m_control_reg_init_code_clear_time =
Core::System::GetInstance().GetSystemTimers().GetFakeTimeBase() + 130;
}
m_dsp_control.Hex = temp.Hex;
@ -232,10 +233,11 @@ u16 DSPHLE::DSP_ReadControlRegister()
{
if (m_dsp_control.DSPInitCode != 0)
{
if (SystemTimers::GetFakeTimeBase() >= m_control_reg_init_code_clear_time)
auto& system = Core::System::GetInstance();
if (system.GetSystemTimers().GetFakeTimeBase() >= m_control_reg_init_code_clear_time)
m_dsp_control.DSPInitCode = 0;
else
Core::System::GetInstance().GetCoreTiming().ForceExceptionCheck(50); // Keep checking
system.GetCoreTiming().ForceExceptionCheck(50); // Keep checking
}
return m_dsp_control.Hex;
}

View File

@ -234,7 +234,7 @@ void DVDInterface::DTKStreamingCallback(DIInterruptType interrupt_type,
}
// Read the next chunk of audio data asynchronously.
s64 ticks_to_dtk = SystemTimers::GetTicksPerSecond() * s64(m_pending_blocks) *
s64 ticks_to_dtk = m_system.GetSystemTimers().GetTicksPerSecond() * s64(m_pending_blocks) *
StreamADPCM::SAMPLES_PER_BLOCK * sample_rate_divisor /
Mixer::FIXED_SAMPLE_RATE_DIVIDEND;
ticks_to_dtk -= cycles_late;
@ -474,7 +474,8 @@ void DVDInterface::ChangeDisc(const std::string& new_path)
EjectDisc(EjectCause::User);
m_disc_path_to_insert = new_path;
m_system.GetCoreTiming().ScheduleEvent(SystemTimers::GetTicksPerSecond(), m_insert_disc);
m_system.GetCoreTiming().ScheduleEvent(m_system.GetSystemTimers().GetTicksPerSecond(),
m_insert_disc);
Movie::SignalDiscChange(new_path);
for (size_t i = 0; i < m_auto_disc_change_paths.size(); ++i)
@ -1090,7 +1091,7 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
m_system.GetDVDThread().IsInsertedDiscRunning() && !m_auto_disc_change_paths.empty())
{
m_system.GetCoreTiming().ScheduleEvent(
force_eject ? 0 : SystemTimers::GetTicksPerSecond() / 2, m_auto_change_disc);
force_eject ? 0 : m_system.GetSystemTimers().GetTicksPerSecond() / 2, m_auto_change_disc);
OSD::AddMessage("Changing discs automatically...", OSD::Duration::NORMAL);
}
else if (force_eject)
@ -1181,7 +1182,7 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
{
// TODO: Needs testing to determine if MINIMUM_COMMAND_LATENCY_US is accurate for this
m_system.GetCoreTiming().ScheduleEvent(
MINIMUM_COMMAND_LATENCY_US * (SystemTimers::GetTicksPerSecond() / 1000000),
MINIMUM_COMMAND_LATENCY_US * (m_system.GetSystemTimers().GetTicksPerSecond() / 1000000),
m_finish_executing_command, PackFinishExecutingCommandUserdata(reply_type, interrupt_type));
}
}
@ -1202,7 +1203,7 @@ void DVDInterface::PerformDecryptingRead(u32 position, u32 length, u32 output_ad
{
// TODO: Needs testing to determine if MINIMUM_COMMAND_LATENCY_US is accurate for this
m_system.GetCoreTiming().ScheduleEvent(
MINIMUM_COMMAND_LATENCY_US * (SystemTimers::GetTicksPerSecond() / 1000000),
MINIMUM_COMMAND_LATENCY_US * (m_system.GetSystemTimers().GetTicksPerSecond() / 1000000),
m_finish_executing_command, PackFinishExecutingCommandUserdata(reply_type, interrupt_type));
}
}
@ -1219,7 +1220,7 @@ void DVDInterface::ForceOutOfBoundsRead(ReplyType reply_type)
// TODO: Needs testing to determine if MINIMUM_COMMAND_LATENCY_US is accurate for this
const DIInterruptType interrupt_type = DIInterruptType::DEINT;
m_system.GetCoreTiming().ScheduleEvent(
MINIMUM_COMMAND_LATENCY_US * (SystemTimers::GetTicksPerSecond() / 1000000),
MINIMUM_COMMAND_LATENCY_US * (m_system.GetSystemTimers().GetTicksPerSecond() / 1000000),
m_finish_executing_command, PackFinishExecutingCommandUserdata(reply_type, interrupt_type));
}
@ -1321,7 +1322,7 @@ void DVDInterface::ScheduleReads(u64 offset, u32 length, const DiscIO::Partition
auto& core_timing = m_system.GetCoreTiming();
const u64 current_time = core_timing.GetTicks();
const u32 ticks_per_second = SystemTimers::GetTicksPerSecond();
const u32 ticks_per_second = m_system.GetSystemTimers().GetTicksPerSecond();
auto& dvd_thread = m_system.GetDVDThread();
const bool wii_disc = dvd_thread.GetDiscType() == DiscIO::Platform::WiiDisc;
@ -1400,7 +1401,7 @@ void DVDInterface::ScheduleReads(u64 offset, u32 length, const DiscIO::Partition
length, output_address);
s64 ticks_until_completion =
READ_COMMAND_LATENCY_US * (SystemTimers::GetTicksPerSecond() / 1000000);
READ_COMMAND_LATENCY_US * (m_system.GetSystemTimers().GetTicksPerSecond() / 1000000);
u32 buffered_blocks = 0;
u32 unbuffered_blocks = 0;
@ -1528,7 +1529,7 @@ void DVDInterface::ScheduleReads(u64 offset, u32 length, const DiscIO::Partition
"Schedule reads: ECC blocks unbuffered={}, buffered={}, "
"ticks={}, time={} us",
unbuffered_blocks, buffered_blocks, ticks_until_completion,
ticks_until_completion * 1000000 / SystemTimers::GetTicksPerSecond());
ticks_until_completion * 1000000 / m_system.GetSystemTimers().GetTicksPerSecond());
}
} // namespace DVD

View File

@ -301,7 +301,7 @@ void DVDThread::FinishRead(u64 id, s64 cycles_late)
request.realtime_done_us - request.realtime_started_us,
Common::Timer::NowUs() - request.realtime_started_us,
(m_system.GetCoreTiming().GetTicks() - request.time_started_ticks) /
(SystemTimers::GetTicksPerSecond() / 1000000));
(m_system.GetSystemTimers().GetTicksPerSecond() / 1000000));
auto& dvd_interface = m_system.GetDVDInterface();
DVD::DIInterruptType interrupt;

View File

@ -208,9 +208,9 @@ void ExpansionInterfaceManager::ChangeDevice(u8 channel, u8 device_num, EXIDevic
core_timing.ScheduleEvent(0, m_event_type_change_device,
((u64)channel << 32) | ((u64)EXIDeviceType::None << 16) | device_num,
from_thread);
core_timing.ScheduleEvent(SystemTimers::GetTicksPerSecond(), m_event_type_change_device,
((u64)channel << 32) | ((u64)device_type << 16) | device_num,
from_thread);
core_timing.ScheduleEvent(
m_system.GetSystemTimers().GetTicksPerSecond(), m_event_type_change_device,
((u64)channel << 32) | ((u64)device_type << 16) | device_num, from_thread);
}
CEXIChannel* ExpansionInterfaceManager::GetChannel(u32 index)

View File

@ -411,19 +411,20 @@ u32 CEXIIPL::GetEmulatedTime(Core::System& system, u32 epoch)
ltime = Movie::GetRecordingStartTime();
// let's keep time moving forward, regardless of what it starts at
ltime += system.GetCoreTiming().GetTicks() / SystemTimers::GetTicksPerSecond();
ltime += system.GetCoreTiming().GetTicks() / system.GetSystemTimers().GetTicksPerSecond();
}
else if (NetPlay::IsNetPlayRunning())
{
ltime = NetPlay_GetEmulatedTime();
// let's keep time moving forward, regardless of what it starts at
ltime += system.GetCoreTiming().GetTicks() / SystemTimers::GetTicksPerSecond();
ltime += system.GetCoreTiming().GetTicks() / system.GetSystemTimers().GetTicksPerSecond();
}
else
{
ASSERT(!Core::WantsDeterminism());
ltime = Common::Timer::GetLocalTimeSinceJan1970() - SystemTimers::GetLocalTimeRTCOffset();
ltime = Common::Timer::GetLocalTimeSinceJan1970() -
system.GetSystemTimers().GetLocalTimeRTCOffset();
}
return static_cast<u32>(ltime) - epoch;

View File

@ -532,7 +532,7 @@ void CEXIMemoryCard::DMARead(u32 addr, u32 size)
// Schedule transfer complete later based on read speed
m_system.GetCoreTiming().ScheduleEvent(
size * (SystemTimers::GetTicksPerSecond() / MC_TRANSFER_RATE_READ),
size * (m_system.GetSystemTimers().GetTicksPerSecond() / MC_TRANSFER_RATE_READ),
s_et_transfer_complete[m_card_slot], static_cast<u64>(m_card_slot));
}
@ -550,7 +550,7 @@ void CEXIMemoryCard::DMAWrite(u32 addr, u32 size)
// Schedule transfer complete later based on write speed
m_system.GetCoreTiming().ScheduleEvent(
size * (SystemTimers::GetTicksPerSecond() / MC_TRANSFER_RATE_WRITE),
size * (m_system.GetSystemTimers().GetTicksPerSecond() / MC_TRANSFER_RATE_WRITE),
s_et_transfer_complete[m_card_slot], static_cast<u64>(m_card_slot));
}
} // namespace ExpansionInterface

View File

@ -264,7 +264,7 @@ void CEXIMic::SetCS(int cs)
void CEXIMic::UpdateNextInterruptTicks()
{
int diff = (SystemTimers::GetTicksPerSecond() / sample_rate) * buff_size_samples;
int diff = (m_system.GetSystemTimers().GetTicksPerSecond() / sample_rate) * buff_size_samples;
next_int_ticks = m_system.GetCoreTiming().GetTicks() + diff;
m_system.GetExpansionInterface().ScheduleUpdateInterrupts(CoreTiming::FromThread::CPU, diff);
}

View File

@ -568,7 +568,7 @@ void Core::RunUntil(u64 gc_ticks)
if (static_cast<s64>(gc_ticks - m_last_gc_ticks) <= 0)
return;
const u64 gc_frequency = SystemTimers::GetTicksPerSecond();
const u64 gc_frequency = ::Core::System::GetInstance().GetSystemTimers().GetTicksPerSecond();
const u32 core_frequency = GetCoreFrequency(m_core);
mTimingSchedule(m_core->timing, &m_event,

View File

@ -34,7 +34,7 @@ namespace HW
void Init(Core::System& system, const Sram* override_sram)
{
system.GetCoreTiming().Init();
SystemTimers::PreInit();
system.GetSystemTimers().PreInit();
State::Init();
@ -52,7 +52,7 @@ void Init(Core::System& system, const Sram* override_sram)
system.GetDVDInterface().Init();
system.GetGPFifo().Init();
system.GetCPU().Init(Config::Get(Config::MAIN_CPU_CORE));
SystemTimers::Init();
system.GetSystemTimers().Init();
if (SConfig::GetInstance().bWii)
{
@ -67,7 +67,7 @@ void Shutdown(Core::System& system)
IOS::HLE::Shutdown(); // Depends on Memory
IOS::Shutdown();
SystemTimers::Shutdown();
system.GetSystemTimers().Shutdown();
system.GetCPU().Shutdown();
system.GetDVDInterface().Shutdown();
system.GetDSP().Shutdown();

View File

@ -262,8 +262,8 @@ void ProcessorInterfaceManager::ResetButton_Tap()
core_timing.ScheduleEvent(0, m_event_type_toggle_reset_button, true, CoreTiming::FromThread::ANY);
core_timing.ScheduleEvent(0, m_event_type_ios_notify_reset_button, 0,
CoreTiming::FromThread::ANY);
core_timing.ScheduleEvent(SystemTimers::GetTicksPerSecond() / 2, m_event_type_toggle_reset_button,
false, CoreTiming::FromThread::ANY);
core_timing.ScheduleEvent(m_system.GetSystemTimers().GetTicksPerSecond() / 2,
m_event_type_toggle_reset_button, false, CoreTiming::FromThread::ANY);
}
void ProcessorInterfaceManager::PowerButton_Tap()

View File

@ -525,7 +525,7 @@ void SerialInterfaceManager::ChangeDeviceDeterministic(SIDevices device, int cha
// Prevent additional device changes on this channel for one second.
m_channel[channel].has_recent_device_change = true;
m_system.GetCoreTiming().ScheduleEvent(SystemTimers::GetTicksPerSecond(),
m_system.GetCoreTiming().ScheduleEvent(m_system.GetSystemTimers().GetTicksPerSecond(),
m_event_type_change_device, channel);
}

View File

@ -25,6 +25,7 @@
#include "Core/HW/SI/SI_DeviceKeyboard.h"
#include "Core/HW/SI/SI_DeviceNull.h"
#include "Core/HW/SystemTimers.h"
#include "Core/System.h"
namespace SerialInterface
{
@ -142,10 +143,10 @@ int SIDevice_GetGBATransferTime(EBufferCommands cmd)
}
}
u64 cycles =
(gba_bytes_transferred * 8 * SystemTimers::GetTicksPerSecond() / GBA_BITS_PER_SECOND) +
(gc_bytes_transferred * 8 * SystemTimers::GetTicksPerSecond() / GC_BITS_PER_SECOND) +
(stop_bits_ns * SystemTimers::GetTicksPerSecond() / 1000000000LL);
const u32 ticks_per_second = Core::System::GetInstance().GetSystemTimers().GetTicksPerSecond();
const u64 cycles = (gba_bytes_transferred * 8 * ticks_per_second / GBA_BITS_PER_SECOND) +
(gc_bytes_transferred * 8 * ticks_per_second / GC_BITS_PER_SECOND) +
(stop_bits_ns * ticks_per_second / 1000000000LL);
return static_cast<int>(cycles);
}

View File

@ -154,14 +154,14 @@ void GBASockServer::ClockSync(Core::System& system)
{
s_num_connected++;
m_last_time_slice = core_timing.GetTicks();
time_slice = (u32)(SystemTimers::GetTicksPerSecond() / 60);
time_slice = (u32)(system.GetSystemTimers().GetTicksPerSecond() / 60);
}
else
{
time_slice = (u32)(core_timing.GetTicks() - m_last_time_slice);
}
time_slice = (u32)((u64)time_slice * 16777216 / SystemTimers::GetTicksPerSecond());
time_slice = (u32)((u64)time_slice * 16777216 / system.GetSystemTimers().GetTicksPerSecond());
m_last_time_slice = core_timing.GetTicks();
char bytes[4] = {0, 0, 0, 0};
bytes[0] = (time_slice >> 24) & 0xff;

View File

@ -24,7 +24,7 @@ namespace SerialInterface
{
static s64 GetSyncInterval()
{
return SystemTimers::GetTicksPerSecond() / 1000;
return Core::System::GetInstance().GetSystemTimers().GetTicksPerSecond() / 1000;
}
CSIDevice_GBAEmu::CSIDevice_GBAEmu(Core::System& system, SIDevices device, int device_number)

View File

@ -264,7 +264,8 @@ CSIDevice_GCController::HandleButtonCombos(const GCPadStatus& pad_status)
if (m_last_button_combo != COMBO_NONE)
{
const u64 current_time = m_system.GetCoreTiming().GetTicks();
if (u32(current_time - m_timer_button_combo_start) > SystemTimers::GetTicksPerSecond() * 3)
const u32 ticks_per_second = m_system.GetSystemTimers().GetTicksPerSecond();
if (u32(current_time - m_timer_button_combo_start) > ticks_per_second * 3)
{
if (m_last_button_combo == COMBO_RESET)
{

View File

@ -71,97 +71,88 @@ IPC_HLE_PERIOD: For the Wii Remote this is the call schedule:
namespace SystemTimers
{
namespace
{
CoreTiming::EventType* et_Dec;
CoreTiming::EventType* et_VI;
CoreTiming::EventType* et_AudioDMA;
CoreTiming::EventType* et_DSP;
CoreTiming::EventType* et_IPC_HLE;
CoreTiming::EventType* et_GPU_sleeper;
CoreTiming::EventType* et_perf_tracker;
// PatchEngine updates every 1/60th of a second by default
CoreTiming::EventType* et_PatchEngine;
u32 s_cpu_core_clock = 486000000u; // 486 mhz (its not 485, stop bugging me!)
// This is completely arbitrary. If we find that we need lower latency,
// we can just increase this number.
int s_ipc_hle_period;
// Custom RTC
s64 s_localtime_rtc_offset = 0;
// DSP/CPU timeslicing.
void DSPCallback(Core::System& system, u64 userdata, s64 cyclesLate)
void SystemTimersManager::DSPCallback(Core::System& system, u64 userdata, s64 cycles_late)
{
// splits up the cycle budget in case lle is used
// for hle, just gives all of the slice to hle
auto& dsp = system.GetDSP();
dsp.UpdateDSPSlice(static_cast<int>(dsp.GetDSPEmulator()->DSP_UpdateRate() - cyclesLate));
system.GetCoreTiming().ScheduleEvent(dsp.GetDSPEmulator()->DSP_UpdateRate() - cyclesLate, et_DSP);
dsp.UpdateDSPSlice(static_cast<int>(dsp.GetDSPEmulator()->DSP_UpdateRate() - cycles_late));
system.GetCoreTiming().ScheduleEvent(dsp.GetDSPEmulator()->DSP_UpdateRate() - cycles_late,
system.GetSystemTimers().m_event_type_dsp);
}
int GetAudioDMACallbackPeriod()
static int GetAudioDMACallbackPeriod(u32 cpu_core_clock, u32 aid_sample_rate_divisor)
{
// System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
auto& system = Core::System::GetInstance();
return static_cast<u64>(s_cpu_core_clock) * system.GetAudioInterface().GetAIDSampleRateDivisor() /
return static_cast<u64>(cpu_core_clock) * aid_sample_rate_divisor /
(Mixer::FIXED_SAMPLE_RATE_DIVIDEND * 4 / 32);
}
void AudioDMACallback(Core::System& system, u64 userdata, s64 cyclesLate)
void SystemTimersManager::AudioDMACallback(Core::System& system, u64 userdata, s64 cycles_late)
{
system.GetDSP().UpdateAudioDMA(); // Push audio to speakers.
system.GetCoreTiming().ScheduleEvent(GetAudioDMACallbackPeriod() - cyclesLate, et_AudioDMA);
auto& system_timers = system.GetSystemTimers();
const int callback_period = GetAudioDMACallbackPeriod(
system_timers.m_cpu_core_clock, system.GetAudioInterface().GetAIDSampleRateDivisor());
system.GetCoreTiming().ScheduleEvent(callback_period - cycles_late,
system_timers.m_event_type_audio_dma);
}
void IPC_HLE_UpdateCallback(Core::System& system, u64 userdata, s64 cyclesLate)
void SystemTimersManager::IPC_HLE_UpdateCallback(Core::System& system, u64 userdata,
s64 cycles_late)
{
if (SConfig::GetInstance().bWii)
{
IOS::HLE::GetIOS()->UpdateDevices();
system.GetCoreTiming().ScheduleEvent(s_ipc_hle_period - cyclesLate, et_IPC_HLE);
auto& system_timers = system.GetSystemTimers();
system.GetCoreTiming().ScheduleEvent(system_timers.m_ipc_hle_period - cycles_late,
system_timers.m_event_type_ipc_hle);
}
}
void GPUSleepCallback(Core::System& system, u64 userdata, s64 cyclesLate)
void SystemTimersManager::GPUSleepCallback(Core::System& system, u64 userdata, s64 cycles_late)
{
auto& core_timing = system.GetCoreTiming();
system.GetFifo().GpuMaySleep();
// We want to call GpuMaySleep at about 1000hz so
// that the thread can sleep while not doing anything.
core_timing.ScheduleEvent(GetTicksPerSecond() / 1000 - cyclesLate, et_GPU_sleeper);
auto& system_timers = system.GetSystemTimers();
core_timing.ScheduleEvent(system_timers.GetTicksPerSecond() / 1000 - cycles_late,
system_timers.m_event_type_gpu_sleeper);
}
void PerfTrackerCallback(Core::System& system, u64 userdata, s64 cyclesLate)
void SystemTimersManager::PerfTrackerCallback(Core::System& system, u64 userdata, s64 cycles_late)
{
auto& core_timing = system.GetCoreTiming();
g_perf_metrics.CountPerformanceMarker(system, cyclesLate);
g_perf_metrics.CountPerformanceMarker(system, cycles_late);
// Call this performance tracker again in 1/100th of a second.
// The tracker stores 256 values so this will let us summarize the last 2.56 seconds.
// The performance metrics require this to be called at 100hz for the speed% is correct.
core_timing.ScheduleEvent(GetTicksPerSecond() / 100 - cyclesLate, et_perf_tracker);
auto& system_timers = system.GetSystemTimers();
core_timing.ScheduleEvent(system_timers.GetTicksPerSecond() / 100 - cycles_late,
system_timers.m_event_type_perf_tracker);
}
void VICallback(Core::System& system, u64 userdata, s64 cyclesLate)
void SystemTimersManager::VICallback(Core::System& system, u64 userdata, s64 cycles_late)
{
auto& core_timing = system.GetCoreTiming();
auto& vi = system.GetVideoInterface();
vi.Update(core_timing.GetTicks() - cyclesLate);
core_timing.ScheduleEvent(vi.GetTicksPerHalfLine() - cyclesLate, et_VI);
vi.Update(core_timing.GetTicks() - cycles_late);
core_timing.ScheduleEvent(vi.GetTicksPerHalfLine() - cycles_late,
system.GetSystemTimers().m_event_type_vi);
}
void DecrementerCallback(Core::System& system, u64 userdata, s64 cyclesLate)
void SystemTimersManager::DecrementerCallback(Core::System& system, u64 userdata, s64 cycles_late)
{
auto& ppc_state = system.GetPPCState();
ppc_state.spr[SPR_DEC] = 0xFFFFFFFF;
ppc_state.Exceptions |= EXCEPTION_DECREMENTER;
}
void PatchEngineCallback(Core::System& system, u64 userdata, s64 cycles_late)
void SystemTimersManager::PatchEngineCallback(Core::System& system, u64 userdata, s64 cycles_late)
{
// We have 2 periods, a 1000 cycle error period and the VI period.
// We have to carefully combine these together so that we stay on the VI period without drifting.
@ -183,86 +174,87 @@ void PatchEngineCallback(Core::System& system, u64 userdata, s64 cycles_late)
cycles_pruned += next_schedule;
}
system.GetCoreTiming().ScheduleEvent(next_schedule, et_PatchEngine, cycles_pruned);
}
} // namespace
u32 GetTicksPerSecond()
{
return s_cpu_core_clock;
system.GetCoreTiming().ScheduleEvent(
next_schedule, system.GetSystemTimers().m_event_type_patch_engine, cycles_pruned);
}
void DecrementerSet()
SystemTimersManager::SystemTimersManager(Core::System& system) : m_system(system)
{
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
auto& ppc_state = system.GetPPCState();
}
SystemTimersManager::~SystemTimersManager() = default;
u32 SystemTimersManager::GetTicksPerSecond() const
{
return m_cpu_core_clock;
}
void SystemTimersManager::DecrementerSet()
{
auto& core_timing = m_system.GetCoreTiming();
auto& ppc_state = m_system.GetPPCState();
u32 decValue = ppc_state.spr[SPR_DEC];
core_timing.RemoveEvent(et_Dec);
core_timing.RemoveEvent(m_event_type_decrementer);
if ((decValue & 0x80000000) == 0)
{
core_timing.SetFakeDecStartTicks(core_timing.GetTicks());
core_timing.SetFakeDecStartValue(decValue);
core_timing.ScheduleEvent(decValue * TIMER_RATIO, et_Dec);
core_timing.ScheduleEvent(decValue * TIMER_RATIO, m_event_type_decrementer);
}
}
u32 GetFakeDecrementer()
u32 SystemTimersManager::GetFakeDecrementer() const
{
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
const auto& core_timing = m_system.GetCoreTiming();
return (core_timing.GetFakeDecStartValue() -
(u32)((core_timing.GetTicks() - core_timing.GetFakeDecStartTicks()) / TIMER_RATIO));
}
void TimeBaseSet()
void SystemTimersManager::TimeBaseSet()
{
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
auto& core_timing = m_system.GetCoreTiming();
core_timing.SetFakeTBStartTicks(core_timing.GetTicks());
core_timing.SetFakeTBStartValue(system.GetPowerPC().ReadFullTimeBaseValue());
core_timing.SetFakeTBStartValue(m_system.GetPowerPC().ReadFullTimeBaseValue());
}
u64 GetFakeTimeBase()
u64 SystemTimersManager::GetFakeTimeBase() const
{
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
const auto& core_timing = m_system.GetCoreTiming();
return core_timing.GetFakeTBStartValue() +
((core_timing.GetTicks() - core_timing.GetFakeTBStartTicks()) / TIMER_RATIO);
}
s64 GetLocalTimeRTCOffset()
s64 SystemTimersManager::GetLocalTimeRTCOffset() const
{
return s_localtime_rtc_offset;
return m_localtime_rtc_offset;
}
double GetEstimatedEmulationPerformance()
double SystemTimersManager::GetEstimatedEmulationPerformance() const
{
return g_perf_metrics.GetMaxSpeed();
}
// split from Init to break a circular dependency between VideoInterface::Init and
// SystemTimers::Init
void PreInit()
void SystemTimersManager::PreInit()
{
ChangePPCClock(SConfig::GetInstance().bWii ? Mode::Wii : Mode::GC);
}
void ChangePPCClock(Mode mode)
void SystemTimersManager::ChangePPCClock(Mode mode)
{
const u32 previous_clock = s_cpu_core_clock;
const u32 previous_clock = m_cpu_core_clock;
if (mode == Mode::Wii)
s_cpu_core_clock = 729000000u;
m_cpu_core_clock = 729000000u;
else
s_cpu_core_clock = 486000000u;
Core::System::GetInstance().GetCoreTiming().AdjustEventQueueTimes(s_cpu_core_clock,
previous_clock);
m_cpu_core_clock = 486000000u;
m_system.GetCoreTiming().AdjustEventQueueTimes(m_cpu_core_clock, previous_clock);
}
void Init()
void SystemTimersManager::Init()
{
if (SConfig::GetInstance().bWii)
{
@ -270,55 +262,58 @@ void Init()
// Now the 1500 is a pure assumption
// We need to figure out the real frequency though
const int freq = 1500;
s_ipc_hle_period = GetTicksPerSecond() / freq;
m_ipc_hle_period = GetTicksPerSecond() / freq;
}
Common::Timer::IncreaseResolution();
// store and convert localtime at boot to timebase ticks
if (Config::Get(Config::MAIN_CUSTOM_RTC_ENABLE))
{
s_localtime_rtc_offset =
m_localtime_rtc_offset =
Common::Timer::GetLocalTimeSinceJan1970() - Config::Get(Config::MAIN_CUSTOM_RTC_VALUE);
}
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
auto& vi = system.GetVideoInterface();
auto& core_timing = m_system.GetCoreTiming();
auto& vi = m_system.GetVideoInterface();
core_timing.SetFakeTBStartValue(static_cast<u64>(s_cpu_core_clock / TIMER_RATIO) *
core_timing.SetFakeTBStartValue(static_cast<u64>(m_cpu_core_clock / TIMER_RATIO) *
static_cast<u64>(ExpansionInterface::CEXIIPL::GetEmulatedTime(
system, ExpansionInterface::CEXIIPL::GC_EPOCH)));
m_system, ExpansionInterface::CEXIIPL::GC_EPOCH)));
core_timing.SetFakeTBStartTicks(core_timing.GetTicks());
core_timing.SetFakeDecStartValue(0xFFFFFFFF);
core_timing.SetFakeDecStartTicks(core_timing.GetTicks());
et_Dec = core_timing.RegisterEvent("DecCallback", DecrementerCallback);
et_VI = core_timing.RegisterEvent("VICallback", VICallback);
et_DSP = core_timing.RegisterEvent("DSPCallback", DSPCallback);
et_AudioDMA = core_timing.RegisterEvent("AudioDMACallback", AudioDMACallback);
et_IPC_HLE = core_timing.RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
et_GPU_sleeper = core_timing.RegisterEvent("GPUSleeper", GPUSleepCallback);
et_perf_tracker = core_timing.RegisterEvent("PerfTracker", PerfTrackerCallback);
et_PatchEngine = core_timing.RegisterEvent("PatchEngine", PatchEngineCallback);
m_event_type_decrementer = core_timing.RegisterEvent("DecCallback", DecrementerCallback);
m_event_type_vi = core_timing.RegisterEvent("VICallback", VICallback);
m_event_type_dsp = core_timing.RegisterEvent("DSPCallback", DSPCallback);
m_event_type_audio_dma = core_timing.RegisterEvent("AudioDMACallback", AudioDMACallback);
m_event_type_ipc_hle =
core_timing.RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
m_event_type_gpu_sleeper = core_timing.RegisterEvent("GPUSleeper", GPUSleepCallback);
m_event_type_perf_tracker = core_timing.RegisterEvent("PerfTracker", PerfTrackerCallback);
m_event_type_patch_engine = core_timing.RegisterEvent("PatchEngine", PatchEngineCallback);
core_timing.ScheduleEvent(0, et_perf_tracker);
core_timing.ScheduleEvent(0, et_GPU_sleeper);
core_timing.ScheduleEvent(vi.GetTicksPerHalfLine(), et_VI);
core_timing.ScheduleEvent(0, et_DSP);
core_timing.ScheduleEvent(GetAudioDMACallbackPeriod(), et_AudioDMA);
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(0, m_event_type_dsp);
core_timing.ScheduleEvent(vi.GetTicksPerField(), et_PatchEngine);
const int audio_dma_callback_period = GetAudioDMACallbackPeriod(
m_cpu_core_clock, m_system.GetAudioInterface().GetAIDSampleRateDivisor());
core_timing.ScheduleEvent(audio_dma_callback_period, m_event_type_audio_dma);
core_timing.ScheduleEvent(vi.GetTicksPerField(), m_event_type_patch_engine);
if (SConfig::GetInstance().bWii)
core_timing.ScheduleEvent(s_ipc_hle_period, et_IPC_HLE);
core_timing.ScheduleEvent(m_ipc_hle_period, m_event_type_ipc_hle);
}
void Shutdown()
void SystemTimersManager::Shutdown()
{
Common::Timer::RestoreResolution();
s_localtime_rtc_offset = 0;
m_localtime_rtc_offset = 0;
}
} // namespace SystemTimers

View File

@ -5,6 +5,15 @@
#include "Common/CommonTypes.h"
namespace Core
{
class System;
}
namespace CoreTiming
{
struct EventType;
}
namespace SystemTimers
{
/*
@ -47,29 +56,70 @@ enum class Mode
Wii,
};
u32 GetTicksPerSecond();
void PreInit();
void Init();
void Shutdown();
void ChangePPCClock(Mode mode);
class SystemTimersManager
{
public:
explicit SystemTimersManager(Core::System& system);
SystemTimersManager(const SystemTimersManager& other) = delete;
SystemTimersManager(SystemTimersManager&& other) = delete;
SystemTimersManager& operator=(const SystemTimersManager& other) = delete;
SystemTimersManager& operator=(SystemTimersManager&& other) = delete;
~SystemTimersManager();
// Notify timing system that somebody wrote to the decrementer
void DecrementerSet();
u32 GetFakeDecrementer();
u32 GetTicksPerSecond() const;
void PreInit();
void Init();
void Shutdown();
void ChangePPCClock(Mode mode);
void TimeBaseSet();
u64 GetFakeTimeBase();
// Custom RTC
s64 GetLocalTimeRTCOffset();
// Notify timing system that somebody wrote to the decrementer
void DecrementerSet();
u32 GetFakeDecrementer() const;
// Returns an estimate of how fast/slow the emulation is running (excluding throttling induced sleep
// time). The estimate is computed over the last 1s of emulated time. Example values:
//
// - 0.5: the emulator is running at 50% speed (falling behind).
// - 1.0: the emulator is running at 100% speed.
// - 2.0: the emulator is running at 200% speed (or 100% speed but sleeping half of the time).
double GetEstimatedEmulationPerformance();
void TimeBaseSet();
u64 GetFakeTimeBase() const;
// Custom RTC
s64 GetLocalTimeRTCOffset() const;
// Returns an estimate of how fast/slow the emulation is running (excluding throttling induced
// sleep time). The estimate is computed over the last 1s of emulated time. Example values:
//
// - 0.5: the emulator is running at 50% speed (falling behind).
// - 1.0: the emulator is running at 100% speed.
// - 2.0: the emulator is running at 200% speed (or 100% speed but sleeping half of the time).
double GetEstimatedEmulationPerformance() const;
private:
static void DSPCallback(Core::System& system, u64 userdata, s64 cycles_late);
static void AudioDMACallback(Core::System& system, u64 userdata, s64 cycles_late);
static void IPC_HLE_UpdateCallback(Core::System& system, u64 userdata, s64 cycles_late);
static void GPUSleepCallback(Core::System& system, u64 userdata, s64 cycles_late);
static void PerfTrackerCallback(Core::System& system, u64 userdata, s64 cycles_late);
static void VICallback(Core::System& system, u64 userdata, s64 cycles_late);
static void DecrementerCallback(Core::System& system, u64 userdata, s64 cycles_late);
static void PatchEngineCallback(Core::System& system, u64 userdata, s64 cycles_late);
Core::System& m_system;
u32 m_cpu_core_clock = 486000000u; // 486 mhz
// This is completely arbitrary. If we find that we need lower latency,
// we can just increase this number.
int m_ipc_hle_period = 0;
// Custom RTC
s64 m_localtime_rtc_offset = 0;
CoreTiming::EventType* m_event_type_decrementer = nullptr;
CoreTiming::EventType* m_event_type_vi = nullptr;
CoreTiming::EventType* m_event_type_audio_dma = nullptr;
CoreTiming::EventType* m_event_type_dsp = nullptr;
CoreTiming::EventType* m_event_type_ipc_hle = nullptr;
CoreTiming::EventType* m_event_type_gpu_sleeper = nullptr;
CoreTiming::EventType* m_event_type_perf_tracker = nullptr;
// PatchEngine updates every 1/60th of a second by default
CoreTiming::EventType* m_event_type_patch_engine = nullptr;
};
} // namespace SystemTimers
inline namespace SystemTimersLiterals

View File

@ -484,7 +484,7 @@ float VideoInterfaceManager::GetAspectRatio() const
int active_width_samples = (m_h_timing_0.HLW + m_h_timing_1.HBS640 - m_h_timing_1.HBE640);
// 2. TVs are analog and don't have pixels. So we convert to seconds.
float tick_length = (1.0f / SystemTimers::GetTicksPerSecond());
float tick_length = (1.0f / m_system.GetSystemTimers().GetTicksPerSecond());
float vertical_period = tick_length * GetTicksPerField();
float horizontal_period = tick_length * GetTicksPerHalfLine() * 2;
float vertical_active_area = active_lines * horizontal_period;
@ -695,7 +695,7 @@ void VideoInterfaceManager::UpdateParameters()
m_even_field_first_hl = equ_hl + m_vblank_timing_even.PRB + GetHalfLinesPerOddField();
m_even_field_last_hl = m_even_field_first_hl + acv_hl - 1;
m_target_refresh_rate_numerator = SystemTimers::GetTicksPerSecond() * 2;
m_target_refresh_rate_numerator = m_system.GetSystemTimers().GetTicksPerSecond() * 2;
m_target_refresh_rate_denominator = GetTicksPerEvenField() + GetTicksPerOddField();
m_target_refresh_rate =
static_cast<double>(m_target_refresh_rate_numerator) / m_target_refresh_rate_denominator;
@ -718,7 +718,7 @@ u32 VideoInterfaceManager::GetTargetRefreshRateDenominator() const
u32 VideoInterfaceManager::GetTicksPerSample() const
{
return 2 * SystemTimers::GetTicksPerSecond() / CLOCK_FREQUENCIES[m_clock & 1];
return 2 * m_system.GetSystemTimers().GetTicksPerSecond() / CLOCK_FREQUENCIES[m_clock & 1];
}
u32 VideoInterfaceManager::GetTicksPerHalfLine() const

View File

@ -71,7 +71,7 @@ IPCReply GetCPUSpeed(Core::System& system, const IOCtlVRequest& request)
const bool overclock_enabled = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
const float oc = overclock_enabled ? Config::Get(Config::MAIN_OVERCLOCK) : 1.0f;
const u32 core_clock = u32(float(SystemTimers::GetTicksPerSecond()) * oc);
const u32 core_clock = u32(float(system.GetSystemTimers().GetTicksPerSecond()) * oc);
auto& memory = system.GetMemory();
memory.Write_U32(core_clock, request.io_vectors[0].address);

View File

@ -50,7 +50,7 @@ static void ReinitHardware(Core::System& system)
dsp.GetDSPEmulator()->Initialize(SConfig::GetInstance().bWii,
Config::Get(Config::MAIN_DSP_THREAD));
SystemTimers::ChangePPCClock(SystemTimers::Mode::GC);
system.GetSystemTimers().ChangePPCClock(SystemTimers::Mode::GC);
}
constexpr u32 ADDRESS_INIT_SEMAPHORE = 0x30f8;

View File

@ -346,7 +346,7 @@ void BluetoothEmuDevice::Update()
for (auto& wiimote : m_wiimotes)
wiimote->Update();
const u64 interval = SystemTimers::GetTicksPerSecond() / Wiimote::UPDATE_FREQ;
const u64 interval = GetSystem().GetSystemTimers().GetTicksPerSecond() / Wiimote::UPDATE_FREQ;
const u64 now = GetSystem().GetCoreTiming().GetTicks();
if (now - m_last_ticks > interval)

View File

@ -40,7 +40,7 @@ void TransferCommand::OnTransferComplete(s32 return_value) const
void TransferCommand::ScheduleTransferCompletion(s32 return_value, u32 expected_time_us) const
{
auto ticks = SystemTimers::GetTicksPerSecond();
auto ticks = m_ios.GetSystem().GetSystemTimers().GetTicksPerSecond();
s64 cycles_in_future = static_cast<s64>((static_cast<u64>(ticks) * expected_time_us) / 1'000'000);
m_ios.EnqueueIPCReply(ios_request, return_value, cycles_in_future, CoreTiming::FromThread::ANY);
}

View File

@ -2522,7 +2522,7 @@ void NetPlayClient::SendTimeBase()
if (netplay_client->m_timebase_frame % 60 == 0)
{
const sf::Uint64 timebase = SystemTimers::GetFakeTimeBase();
const sf::Uint64 timebase = Core::System::GetInstance().GetSystemTimers().GetFakeTimeBase();
sf::Packet packet;
packet << MessageID::TimeBase;

View File

@ -245,13 +245,14 @@ void Interpreter::mfspr(Interpreter& interpreter, UGeckoInstruction inst)
case SPR_DEC:
if ((ppc_state.spr[index] & 0x80000000) == 0) // We are still decrementing
{
ppc_state.spr[index] = SystemTimers::GetFakeDecrementer();
ppc_state.spr[index] = interpreter.m_system.GetSystemTimers().GetFakeDecrementer();
}
break;
case SPR_TL:
case SPR_TU:
interpreter.m_system.GetPowerPC().WriteFullTimeBaseValue(SystemTimers::GetFakeTimeBase());
interpreter.m_system.GetPowerPC().WriteFullTimeBaseValue(
interpreter.m_system.GetSystemTimers().GetFakeTimeBase());
break;
case SPR_WPAR:
@ -326,12 +327,12 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
case SPR_TL_W:
TL(ppc_state) = ppc_state.gpr[inst.RD];
SystemTimers::TimeBaseSet();
interpreter.m_system.GetSystemTimers().TimeBaseSet();
break;
case SPR_TU_W:
TU(ppc_state) = ppc_state.gpr[inst.RD];
SystemTimers::TimeBaseSet();
interpreter.m_system.GetSystemTimers().TimeBaseSet();
break;
case SPR_PVR:
@ -433,7 +434,7 @@ void Interpreter::mtspr(Interpreter& interpreter, UGeckoInstruction inst)
INFO_LOG_FMT(POWERPC, "Software triggered Decrementer exception");
ppc_state.Exceptions |= EXCEPTION_DECREMENTER;
}
SystemTimers::DecrementerSet();
interpreter.m_system.GetSystemTimers().DecrementerSet();
break;
// Page table base etc

View File

@ -199,14 +199,15 @@ void PowerPCManager::ResetRegisters()
mmu.DBATUpdated();
mmu.IBATUpdated();
auto& system_timers = m_system.GetSystemTimers();
TL(m_ppc_state) = 0;
TU(m_ppc_state) = 0;
SystemTimers::TimeBaseSet();
system_timers.TimeBaseSet();
// MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :}
m_ppc_state.msr.Hex = 0;
m_ppc_state.spr[SPR_DEC] = 0xFFFFFFFF;
SystemTimers::DecrementerSet();
system_timers.DecrementerSet();
RoundingModeUpdated(m_ppc_state);
RecalculateAllFeatureFlags(m_ppc_state);

View File

@ -21,6 +21,7 @@
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/Sram.h"
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/PowerPC/Interpreter/Interpreter.h"
#include "Core/PowerPC/JitInterface.h"
@ -46,7 +47,7 @@ struct System::Impl
m_expansion_interface(system), m_fifo{system}, m_gp_fifo(system),
m_memory(system), m_pixel_engine{system}, m_power_pc(system),
m_mmu(system, m_memory, m_power_pc), m_processor_interface(system),
m_serial_interface(system), m_video_interface(system),
m_serial_interface(system), m_system_timers(system), m_video_interface(system),
m_interpreter(system, m_power_pc.GetPPCState(), m_mmu), m_jit_interface(system)
{
}
@ -78,6 +79,7 @@ struct System::Impl
ProcessorInterface::ProcessorInterfaceManager m_processor_interface;
SerialInterface::SerialInterfaceManager m_serial_interface;
Sram m_sram;
SystemTimers::SystemTimersManager m_system_timers;
VertexShaderManager m_vertex_shader_manager;
XFStateManager m_xf_state_manager;
VideoInterface::VideoInterfaceManager m_video_interface;
@ -259,6 +261,11 @@ Sram& System::GetSRAM() const
return m_impl->m_sram;
}
SystemTimers::SystemTimersManager& System::GetSystemTimers() const
{
return m_impl->m_system_timers;
}
VertexShaderManager& System::GetVertexShaderManager() const
{
return m_impl->m_vertex_shader_manager;

View File

@ -86,6 +86,10 @@ namespace SerialInterface
{
class SerialInterfaceManager;
};
namespace SystemTimers
{
class SystemTimersManager;
}
namespace VideoCommon
{
class CustomAssetLoader;
@ -155,6 +159,7 @@ public:
ProcessorInterface::ProcessorInterfaceManager& GetProcessorInterface() const;
SerialInterface::SerialInterfaceManager& GetSerialInterface() const;
Sram& GetSRAM() const;
SystemTimers::SystemTimersManager& GetSystemTimers() const;
VertexShaderManager& GetVertexShaderManager() const;
XFStateManager& GetXFStateManager() const;
VideoInterface::VideoInterfaceManager& GetVideoInterface() const;

View File

@ -21,6 +21,7 @@
#include "Core/Core.h"
#include "Core/HW/SystemTimers.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
@ -275,7 +276,8 @@ void AdvancedPane::Update()
}
m_cpu_clock_override_slider_label->setText([] {
int core_clock = SystemTimers::GetTicksPerSecond() / std::pow(10, 6);
int core_clock =
Core::System::GetInstance().GetSystemTimers().GetTicksPerSecond() / std::pow(10, 6);
int percent = static_cast<int>(std::round(Config::Get(Config::MAIN_OVERCLOCK) * 100.f));
int clock = static_cast<int>(std::round(Config::Get(Config::MAIN_OVERCLOCK) * core_clock));
return tr("%1% (%2 MHz)").arg(QString::number(percent), QString::number(clock));

View File

@ -436,7 +436,7 @@ void Init()
{
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
if ((core_timing.GetTicks() - s_last_init) < SystemTimers::GetTicksPerSecond())
if ((core_timing.GetTicks() - s_last_init) < system.GetSystemTimers().GetTicksPerSecond())
return;
s_last_init = core_timing.GetTicks();

View File

@ -356,9 +356,10 @@ void FFMpegFrameDump::AddFrame(const FrameData& frame)
return;
// Calculate presentation timestamp from ticks since start.
const s64 pts = av_rescale_q(frame.state.ticks - m_context->start_ticks,
AVRational{1, int(SystemTimers::GetTicksPerSecond())},
m_context->codec->time_base);
const s64 pts = av_rescale_q(
frame.state.ticks - m_context->start_ticks,
AVRational{1, int(Core::System::GetInstance().GetSystemTimers().GetTicksPerSecond())},
m_context->codec->time_base);
if (!IsFirstFrameInCurrentFile())
{

View File

@ -10,6 +10,7 @@
#include "Core/DolphinAnalytics.h"
#include "Core/HW/SystemTimers.h"
#include "Core/System.h"
#include "VideoCommon/BPFunctions.h"
#include "VideoCommon/VideoCommon.h"
@ -24,7 +25,8 @@ static Common::EventHook s_before_frame_event =
static Common::EventHook s_after_frame_event = AfterFrameEvent::Register(
[] {
DolphinAnalytics::PerformanceSample perf_sample;
perf_sample.speed_ratio = SystemTimers::GetEstimatedEmulationPerformance();
perf_sample.speed_ratio =
Core::System::GetInstance().GetSystemTimers().GetEstimatedEmulationPerformance();
perf_sample.num_prims = g_stats.this_frame.num_prims + g_stats.this_frame.num_dl_prims;
perf_sample.num_draw_calls = g_stats.this_frame.num_draw_calls;
DolphinAnalytics::Instance().ReportPerformanceInfo(std::move(perf_sample));

View File

@ -546,7 +546,7 @@ void VertexManagerBase::Flush()
if (g_ActiveConfig.bGraphicMods)
{
const double seconds_elapsed =
static_cast<double>(m_ticks_elapsed) / SystemTimers::GetTicksPerSecond();
static_cast<double>(m_ticks_elapsed) / system.GetSystemTimers().GetTicksPerSecond();
pixel_shader_manager.constants.time_ms = seconds_elapsed * 1000;
}