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

View File

@ -410,8 +410,9 @@ FifoPlayer& FifoPlayer::GetInstance()
void FifoPlayer::WriteFrame(const FifoFrameInfo& frame, const AnalyzedFrameInfo& info) void FifoPlayer::WriteFrame(const FifoFrameInfo& frame, const AnalyzedFrameInfo& info)
{ {
// Core timing information // Core timing information
auto& vi = Core::System::GetInstance().GetVideoInterface(); auto& system = Core::System::GetInstance();
m_CyclesPerFrame = static_cast<u64>(SystemTimers::GetTicksPerSecond()) * auto& vi = system.GetVideoInterface();
m_CyclesPerFrame = static_cast<u64>(system.GetSystemTimers().GetTicksPerSecond()) *
vi.GetTargetRefreshRateDenominator() / vi.GetTargetRefreshRateNumerator(); vi.GetTargetRefreshRateDenominator() / vi.GetTargetRefreshRateNumerator();
m_ElapsedCycles = 0; m_ElapsedCycles = 0;
m_FrameFifoSize = static_cast<u32>(frame.fifoData.size()); 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_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; m_ais_sample_rate_divisor / Mixer::FIXED_SAMPLE_RATE_DIVIDEND;
SoundStream* sound_stream = m_system.GetSoundStream(); SoundStream* sound_stream = m_system.GetSoundStream();
sound_stream->GetMixer()->SetStreamInputSampleRateDivisor(m_ais_sample_rate_divisor); 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 // AX HLE uses 3ms (Wii) or 5ms (GC) timing period
// But to be sure, just update the HLE every ms. // 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) void DSPHLE::SendMailToDSP(u32 mail)
@ -221,7 +221,8 @@ u16 DSPHLE::DSP_WriteControlRegister(u16 value)
SetUCode(UCODE_INIT_AUDIO_SYSTEM); SetUCode(UCODE_INIT_AUDIO_SYSTEM);
temp.DSPInitCode = 1; temp.DSPInitCode = 1;
// Number obtained from real hardware on a Wii, but it's not perfectly consistent // 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; m_dsp_control.Hex = temp.Hex;
@ -232,10 +233,11 @@ u16 DSPHLE::DSP_ReadControlRegister()
{ {
if (m_dsp_control.DSPInitCode != 0) 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; m_dsp_control.DSPInitCode = 0;
else else
Core::System::GetInstance().GetCoreTiming().ForceExceptionCheck(50); // Keep checking system.GetCoreTiming().ForceExceptionCheck(50); // Keep checking
} }
return m_dsp_control.Hex; 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. // 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 / StreamADPCM::SAMPLES_PER_BLOCK * sample_rate_divisor /
Mixer::FIXED_SAMPLE_RATE_DIVIDEND; Mixer::FIXED_SAMPLE_RATE_DIVIDEND;
ticks_to_dtk -= cycles_late; ticks_to_dtk -= cycles_late;
@ -474,7 +474,8 @@ void DVDInterface::ChangeDisc(const std::string& new_path)
EjectDisc(EjectCause::User); EjectDisc(EjectCause::User);
m_disc_path_to_insert = new_path; 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); Movie::SignalDiscChange(new_path);
for (size_t i = 0; i < m_auto_disc_change_paths.size(); ++i) 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.GetDVDThread().IsInsertedDiscRunning() && !m_auto_disc_change_paths.empty())
{ {
m_system.GetCoreTiming().ScheduleEvent( 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); OSD::AddMessage("Changing discs automatically...", OSD::Duration::NORMAL);
} }
else if (force_eject) 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 // TODO: Needs testing to determine if MINIMUM_COMMAND_LATENCY_US is accurate for this
m_system.GetCoreTiming().ScheduleEvent( 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)); 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 // TODO: Needs testing to determine if MINIMUM_COMMAND_LATENCY_US is accurate for this
m_system.GetCoreTiming().ScheduleEvent( 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)); 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 // TODO: Needs testing to determine if MINIMUM_COMMAND_LATENCY_US is accurate for this
const DIInterruptType interrupt_type = DIInterruptType::DEINT; const DIInterruptType interrupt_type = DIInterruptType::DEINT;
m_system.GetCoreTiming().ScheduleEvent( 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)); 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(); auto& core_timing = m_system.GetCoreTiming();
const u64 current_time = core_timing.GetTicks(); 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(); auto& dvd_thread = m_system.GetDVDThread();
const bool wii_disc = dvd_thread.GetDiscType() == DiscIO::Platform::WiiDisc; 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); length, output_address);
s64 ticks_until_completion = 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 buffered_blocks = 0;
u32 unbuffered_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={}, " "Schedule reads: ECC blocks unbuffered={}, buffered={}, "
"ticks={}, time={} us", "ticks={}, time={} us",
unbuffered_blocks, buffered_blocks, ticks_until_completion, unbuffered_blocks, buffered_blocks, ticks_until_completion,
ticks_until_completion * 1000000 / SystemTimers::GetTicksPerSecond()); ticks_until_completion * 1000000 / m_system.GetSystemTimers().GetTicksPerSecond());
} }
} // namespace DVD } // namespace DVD

View File

@ -301,7 +301,7 @@ void DVDThread::FinishRead(u64 id, s64 cycles_late)
request.realtime_done_us - request.realtime_started_us, request.realtime_done_us - request.realtime_started_us,
Common::Timer::NowUs() - request.realtime_started_us, Common::Timer::NowUs() - request.realtime_started_us,
(m_system.GetCoreTiming().GetTicks() - request.time_started_ticks) / (m_system.GetCoreTiming().GetTicks() - request.time_started_ticks) /
(SystemTimers::GetTicksPerSecond() / 1000000)); (m_system.GetSystemTimers().GetTicksPerSecond() / 1000000));
auto& dvd_interface = m_system.GetDVDInterface(); auto& dvd_interface = m_system.GetDVDInterface();
DVD::DIInterruptType interrupt; 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, core_timing.ScheduleEvent(0, m_event_type_change_device,
((u64)channel << 32) | ((u64)EXIDeviceType::None << 16) | device_num, ((u64)channel << 32) | ((u64)EXIDeviceType::None << 16) | device_num,
from_thread); from_thread);
core_timing.ScheduleEvent(SystemTimers::GetTicksPerSecond(), m_event_type_change_device, core_timing.ScheduleEvent(
((u64)channel << 32) | ((u64)device_type << 16) | device_num, m_system.GetSystemTimers().GetTicksPerSecond(), m_event_type_change_device,
from_thread); ((u64)channel << 32) | ((u64)device_type << 16) | device_num, from_thread);
} }
CEXIChannel* ExpansionInterfaceManager::GetChannel(u32 index) CEXIChannel* ExpansionInterfaceManager::GetChannel(u32 index)

View File

@ -411,19 +411,20 @@ u32 CEXIIPL::GetEmulatedTime(Core::System& system, u32 epoch)
ltime = Movie::GetRecordingStartTime(); ltime = Movie::GetRecordingStartTime();
// let's keep time moving forward, regardless of what it starts at // 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()) else if (NetPlay::IsNetPlayRunning())
{ {
ltime = NetPlay_GetEmulatedTime(); ltime = NetPlay_GetEmulatedTime();
// let's keep time moving forward, regardless of what it starts at // 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 else
{ {
ASSERT(!Core::WantsDeterminism()); ASSERT(!Core::WantsDeterminism());
ltime = Common::Timer::GetLocalTimeSinceJan1970() - SystemTimers::GetLocalTimeRTCOffset(); ltime = Common::Timer::GetLocalTimeSinceJan1970() -
system.GetSystemTimers().GetLocalTimeRTCOffset();
} }
return static_cast<u32>(ltime) - epoch; 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 // Schedule transfer complete later based on read speed
m_system.GetCoreTiming().ScheduleEvent( 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)); 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 // Schedule transfer complete later based on write speed
m_system.GetCoreTiming().ScheduleEvent( 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)); s_et_transfer_complete[m_card_slot], static_cast<u64>(m_card_slot));
} }
} // namespace ExpansionInterface } // namespace ExpansionInterface

View File

@ -264,7 +264,7 @@ void CEXIMic::SetCS(int cs)
void CEXIMic::UpdateNextInterruptTicks() 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; next_int_ticks = m_system.GetCoreTiming().GetTicks() + diff;
m_system.GetExpansionInterface().ScheduleUpdateInterrupts(CoreTiming::FromThread::CPU, 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) if (static_cast<s64>(gc_ticks - m_last_gc_ticks) <= 0)
return; return;
const u64 gc_frequency = SystemTimers::GetTicksPerSecond(); const u64 gc_frequency = ::Core::System::GetInstance().GetSystemTimers().GetTicksPerSecond();
const u32 core_frequency = GetCoreFrequency(m_core); const u32 core_frequency = GetCoreFrequency(m_core);
mTimingSchedule(m_core->timing, &m_event, mTimingSchedule(m_core->timing, &m_event,

View File

@ -34,7 +34,7 @@ namespace HW
void Init(Core::System& system, const Sram* override_sram) void Init(Core::System& system, const Sram* override_sram)
{ {
system.GetCoreTiming().Init(); system.GetCoreTiming().Init();
SystemTimers::PreInit(); system.GetSystemTimers().PreInit();
State::Init(); State::Init();
@ -52,7 +52,7 @@ void Init(Core::System& system, const Sram* override_sram)
system.GetDVDInterface().Init(); system.GetDVDInterface().Init();
system.GetGPFifo().Init(); system.GetGPFifo().Init();
system.GetCPU().Init(Config::Get(Config::MAIN_CPU_CORE)); system.GetCPU().Init(Config::Get(Config::MAIN_CPU_CORE));
SystemTimers::Init(); system.GetSystemTimers().Init();
if (SConfig::GetInstance().bWii) if (SConfig::GetInstance().bWii)
{ {
@ -67,7 +67,7 @@ void Shutdown(Core::System& system)
IOS::HLE::Shutdown(); // Depends on Memory IOS::HLE::Shutdown(); // Depends on Memory
IOS::Shutdown(); IOS::Shutdown();
SystemTimers::Shutdown(); system.GetSystemTimers().Shutdown();
system.GetCPU().Shutdown(); system.GetCPU().Shutdown();
system.GetDVDInterface().Shutdown(); system.GetDVDInterface().Shutdown();
system.GetDSP().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_toggle_reset_button, true, CoreTiming::FromThread::ANY);
core_timing.ScheduleEvent(0, m_event_type_ios_notify_reset_button, 0, core_timing.ScheduleEvent(0, m_event_type_ios_notify_reset_button, 0,
CoreTiming::FromThread::ANY); CoreTiming::FromThread::ANY);
core_timing.ScheduleEvent(SystemTimers::GetTicksPerSecond() / 2, m_event_type_toggle_reset_button, core_timing.ScheduleEvent(m_system.GetSystemTimers().GetTicksPerSecond() / 2,
false, CoreTiming::FromThread::ANY); m_event_type_toggle_reset_button, false, CoreTiming::FromThread::ANY);
} }
void ProcessorInterfaceManager::PowerButton_Tap() 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. // Prevent additional device changes on this channel for one second.
m_channel[channel].has_recent_device_change = true; 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); m_event_type_change_device, channel);
} }

View File

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

View File

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

View File

@ -24,7 +24,7 @@ namespace SerialInterface
{ {
static s64 GetSyncInterval() 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) 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) if (m_last_button_combo != COMBO_NONE)
{ {
const u64 current_time = m_system.GetCoreTiming().GetTicks(); 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) 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 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. // 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 // splits up the cycle budget in case lle is used
// for hle, just gives all of the slice to hle // for hle, just gives all of the slice to hle
auto& dsp = system.GetDSP(); auto& dsp = system.GetDSP();
dsp.UpdateDSPSlice(static_cast<int>(dsp.GetDSPEmulator()->DSP_UpdateRate() - cyclesLate)); dsp.UpdateDSPSlice(static_cast<int>(dsp.GetDSPEmulator()->DSP_UpdateRate() - cycles_late));
system.GetCoreTiming().ScheduleEvent(dsp.GetDSPEmulator()->DSP_UpdateRate() - cyclesLate, et_DSP); 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 // System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
auto& system = Core::System::GetInstance(); return static_cast<u64>(cpu_core_clock) * aid_sample_rate_divisor /
return static_cast<u64>(s_cpu_core_clock) * system.GetAudioInterface().GetAIDSampleRateDivisor() /
(Mixer::FIXED_SAMPLE_RATE_DIVIDEND * 4 / 32); (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.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) if (SConfig::GetInstance().bWii)
{ {
IOS::HLE::GetIOS()->UpdateDevices(); 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(); auto& core_timing = system.GetCoreTiming();
system.GetFifo().GpuMaySleep(); system.GetFifo().GpuMaySleep();
// We want to call GpuMaySleep at about 1000hz so // We want to call GpuMaySleep at about 1000hz so
// that the thread can sleep while not doing anything. // 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(); 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. // 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 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. // 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& core_timing = system.GetCoreTiming();
auto& vi = system.GetVideoInterface(); auto& vi = system.GetVideoInterface();
vi.Update(core_timing.GetTicks() - cyclesLate); vi.Update(core_timing.GetTicks() - cycles_late);
core_timing.ScheduleEvent(vi.GetTicksPerHalfLine() - cyclesLate, et_VI); 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(); auto& ppc_state = system.GetPPCState();
ppc_state.spr[SPR_DEC] = 0xFFFFFFFF; ppc_state.spr[SPR_DEC] = 0xFFFFFFFF;
ppc_state.Exceptions |= EXCEPTION_DECREMENTER; 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 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. // 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; cycles_pruned += next_schedule;
} }
system.GetCoreTiming().ScheduleEvent(next_schedule, et_PatchEngine, cycles_pruned); system.GetCoreTiming().ScheduleEvent(
} next_schedule, system.GetSystemTimers().m_event_type_patch_engine, cycles_pruned);
} // namespace
u32 GetTicksPerSecond()
{
return s_cpu_core_clock;
} }
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]; u32 decValue = ppc_state.spr[SPR_DEC];
core_timing.RemoveEvent(et_Dec); core_timing.RemoveEvent(m_event_type_decrementer);
if ((decValue & 0x80000000) == 0) if ((decValue & 0x80000000) == 0)
{ {
core_timing.SetFakeDecStartTicks(core_timing.GetTicks()); core_timing.SetFakeDecStartTicks(core_timing.GetTicks());
core_timing.SetFakeDecStartValue(decValue); 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(); const auto& core_timing = m_system.GetCoreTiming();
auto& core_timing = system.GetCoreTiming();
return (core_timing.GetFakeDecStartValue() - return (core_timing.GetFakeDecStartValue() -
(u32)((core_timing.GetTicks() - core_timing.GetFakeDecStartTicks()) / TIMER_RATIO)); (u32)((core_timing.GetTicks() - core_timing.GetFakeDecStartTicks()) / TIMER_RATIO));
} }
void TimeBaseSet() void SystemTimersManager::TimeBaseSet()
{ {
auto& system = Core::System::GetInstance(); auto& core_timing = m_system.GetCoreTiming();
auto& core_timing = system.GetCoreTiming();
core_timing.SetFakeTBStartTicks(core_timing.GetTicks()); 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(); const auto& core_timing = m_system.GetCoreTiming();
auto& core_timing = system.GetCoreTiming();
return core_timing.GetFakeTBStartValue() + return core_timing.GetFakeTBStartValue() +
((core_timing.GetTicks() - core_timing.GetFakeTBStartTicks()) / TIMER_RATIO); ((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(); return g_perf_metrics.GetMaxSpeed();
} }
// split from Init to break a circular dependency between VideoInterface::Init and // split from Init to break a circular dependency between VideoInterface::Init and
// SystemTimers::Init // SystemTimers::Init
void PreInit() void SystemTimersManager::PreInit()
{ {
ChangePPCClock(SConfig::GetInstance().bWii ? Mode::Wii : Mode::GC); 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) if (mode == Mode::Wii)
s_cpu_core_clock = 729000000u; m_cpu_core_clock = 729000000u;
else else
s_cpu_core_clock = 486000000u; m_cpu_core_clock = 486000000u;
Core::System::GetInstance().GetCoreTiming().AdjustEventQueueTimes(s_cpu_core_clock, m_system.GetCoreTiming().AdjustEventQueueTimes(m_cpu_core_clock, previous_clock);
previous_clock);
} }
void Init() void SystemTimersManager::Init()
{ {
if (SConfig::GetInstance().bWii) if (SConfig::GetInstance().bWii)
{ {
@ -270,55 +262,58 @@ void Init()
// Now the 1500 is a pure assumption // Now the 1500 is a pure assumption
// We need to figure out the real frequency though // We need to figure out the real frequency though
const int freq = 1500; const int freq = 1500;
s_ipc_hle_period = GetTicksPerSecond() / freq; m_ipc_hle_period = GetTicksPerSecond() / freq;
} }
Common::Timer::IncreaseResolution(); Common::Timer::IncreaseResolution();
// store and convert localtime at boot to timebase ticks // store and convert localtime at boot to timebase ticks
if (Config::Get(Config::MAIN_CUSTOM_RTC_ENABLE)) 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); Common::Timer::GetLocalTimeSinceJan1970() - Config::Get(Config::MAIN_CUSTOM_RTC_VALUE);
} }
auto& system = Core::System::GetInstance(); auto& core_timing = m_system.GetCoreTiming();
auto& core_timing = system.GetCoreTiming(); auto& vi = m_system.GetVideoInterface();
auto& vi = 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( 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.SetFakeTBStartTicks(core_timing.GetTicks());
core_timing.SetFakeDecStartValue(0xFFFFFFFF); core_timing.SetFakeDecStartValue(0xFFFFFFFF);
core_timing.SetFakeDecStartTicks(core_timing.GetTicks()); core_timing.SetFakeDecStartTicks(core_timing.GetTicks());
et_Dec = core_timing.RegisterEvent("DecCallback", DecrementerCallback); m_event_type_decrementer = core_timing.RegisterEvent("DecCallback", DecrementerCallback);
et_VI = core_timing.RegisterEvent("VICallback", VICallback); m_event_type_vi = core_timing.RegisterEvent("VICallback", VICallback);
et_DSP = core_timing.RegisterEvent("DSPCallback", DSPCallback); m_event_type_dsp = core_timing.RegisterEvent("DSPCallback", DSPCallback);
et_AudioDMA = core_timing.RegisterEvent("AudioDMACallback", AudioDMACallback); m_event_type_audio_dma = core_timing.RegisterEvent("AudioDMACallback", AudioDMACallback);
et_IPC_HLE = core_timing.RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback); m_event_type_ipc_hle =
et_GPU_sleeper = core_timing.RegisterEvent("GPUSleeper", GPUSleepCallback); core_timing.RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
et_perf_tracker = core_timing.RegisterEvent("PerfTracker", PerfTrackerCallback); m_event_type_gpu_sleeper = core_timing.RegisterEvent("GPUSleeper", GPUSleepCallback);
et_PatchEngine = core_timing.RegisterEvent("PatchEngine", PatchEngineCallback); 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, m_event_type_perf_tracker);
core_timing.ScheduleEvent(0, et_GPU_sleeper); core_timing.ScheduleEvent(0, m_event_type_gpu_sleeper);
core_timing.ScheduleEvent(vi.GetTicksPerHalfLine(), et_VI); core_timing.ScheduleEvent(vi.GetTicksPerHalfLine(), m_event_type_vi);
core_timing.ScheduleEvent(0, et_DSP); core_timing.ScheduleEvent(0, m_event_type_dsp);
core_timing.ScheduleEvent(GetAudioDMACallbackPeriod(), et_AudioDMA);
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) 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(); Common::Timer::RestoreResolution();
s_localtime_rtc_offset = 0; m_localtime_rtc_offset = 0;
} }
} // namespace SystemTimers } // namespace SystemTimers

View File

@ -5,6 +5,15 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
namespace Core
{
class System;
}
namespace CoreTiming
{
struct EventType;
}
namespace SystemTimers namespace SystemTimers
{ {
/* /*
@ -47,29 +56,70 @@ enum class Mode
Wii, Wii,
}; };
u32 GetTicksPerSecond(); class SystemTimersManager
void PreInit(); {
void Init(); public:
void Shutdown(); explicit SystemTimersManager(Core::System& system);
void ChangePPCClock(Mode mode); 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 u32 GetTicksPerSecond() const;
void DecrementerSet(); void PreInit();
u32 GetFakeDecrementer(); void Init();
void Shutdown();
void ChangePPCClock(Mode mode);
void TimeBaseSet(); // Notify timing system that somebody wrote to the decrementer
u64 GetFakeTimeBase(); void DecrementerSet();
// Custom RTC u32 GetFakeDecrementer() const;
s64 GetLocalTimeRTCOffset();
// Returns an estimate of how fast/slow the emulation is running (excluding throttling induced sleep void TimeBaseSet();
// time). The estimate is computed over the last 1s of emulated time. Example values: u64 GetFakeTimeBase() const;
// // Custom RTC
// - 0.5: the emulator is running at 50% speed (falling behind). s64 GetLocalTimeRTCOffset() const;
// - 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();
// 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 } // namespace SystemTimers
inline namespace SystemTimersLiterals 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); 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. // 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 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;
@ -695,7 +695,7 @@ void VideoInterfaceManager::UpdateParameters()
m_even_field_first_hl = equ_hl + m_vblank_timing_even.PRB + GetHalfLinesPerOddField(); 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_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_denominator = GetTicksPerEvenField() + GetTicksPerOddField();
m_target_refresh_rate = m_target_refresh_rate =
static_cast<double>(m_target_refresh_rate_numerator) / m_target_refresh_rate_denominator; 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 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 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 bool overclock_enabled = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
const float oc = overclock_enabled ? Config::Get(Config::MAIN_OVERCLOCK) : 1.0f; 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(); auto& memory = system.GetMemory();
memory.Write_U32(core_clock, request.io_vectors[0].address); 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, dsp.GetDSPEmulator()->Initialize(SConfig::GetInstance().bWii,
Config::Get(Config::MAIN_DSP_THREAD)); Config::Get(Config::MAIN_DSP_THREAD));
SystemTimers::ChangePPCClock(SystemTimers::Mode::GC); system.GetSystemTimers().ChangePPCClock(SystemTimers::Mode::GC);
} }
constexpr u32 ADDRESS_INIT_SEMAPHORE = 0x30f8; constexpr u32 ADDRESS_INIT_SEMAPHORE = 0x30f8;

View File

@ -346,7 +346,7 @@ void BluetoothEmuDevice::Update()
for (auto& wiimote : m_wiimotes) for (auto& wiimote : m_wiimotes)
wiimote->Update(); 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(); const u64 now = GetSystem().GetCoreTiming().GetTicks();
if (now - m_last_ticks > interval) 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 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); 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); 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) 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; sf::Packet packet;
packet << MessageID::TimeBase; packet << MessageID::TimeBase;

View File

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

View File

@ -199,14 +199,15 @@ void PowerPCManager::ResetRegisters()
mmu.DBATUpdated(); mmu.DBATUpdated();
mmu.IBATUpdated(); mmu.IBATUpdated();
auto& system_timers = m_system.GetSystemTimers();
TL(m_ppc_state) = 0; TL(m_ppc_state) = 0;
TU(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 :} // 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.msr.Hex = 0;
m_ppc_state.spr[SPR_DEC] = 0xFFFFFFFF; m_ppc_state.spr[SPR_DEC] = 0xFFFFFFFF;
SystemTimers::DecrementerSet(); system_timers.DecrementerSet();
RoundingModeUpdated(m_ppc_state); RoundingModeUpdated(m_ppc_state);
RecalculateAllFeatureFlags(m_ppc_state); RecalculateAllFeatureFlags(m_ppc_state);

View File

@ -21,6 +21,7 @@
#include "Core/HW/ProcessorInterface.h" #include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SI/SI.h" #include "Core/HW/SI/SI.h"
#include "Core/HW/Sram.h" #include "Core/HW/Sram.h"
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h" #include "Core/HW/VideoInterface.h"
#include "Core/PowerPC/Interpreter/Interpreter.h" #include "Core/PowerPC/Interpreter/Interpreter.h"
#include "Core/PowerPC/JitInterface.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_expansion_interface(system), m_fifo{system}, m_gp_fifo(system),
m_memory(system), m_pixel_engine{system}, m_power_pc(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_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) 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; ProcessorInterface::ProcessorInterfaceManager m_processor_interface;
SerialInterface::SerialInterfaceManager m_serial_interface; SerialInterface::SerialInterfaceManager m_serial_interface;
Sram m_sram; Sram m_sram;
SystemTimers::SystemTimersManager m_system_timers;
VertexShaderManager m_vertex_shader_manager; VertexShaderManager m_vertex_shader_manager;
XFStateManager m_xf_state_manager; XFStateManager m_xf_state_manager;
VideoInterface::VideoInterfaceManager m_video_interface; VideoInterface::VideoInterfaceManager m_video_interface;
@ -259,6 +261,11 @@ Sram& System::GetSRAM() const
return m_impl->m_sram; return m_impl->m_sram;
} }
SystemTimers::SystemTimersManager& System::GetSystemTimers() const
{
return m_impl->m_system_timers;
}
VertexShaderManager& System::GetVertexShaderManager() const VertexShaderManager& System::GetVertexShaderManager() const
{ {
return m_impl->m_vertex_shader_manager; return m_impl->m_vertex_shader_manager;

View File

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

View File

@ -21,6 +21,7 @@
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/HW/SystemTimers.h" #include "Core/HW/SystemTimers.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "DolphinQt/Config/ConfigControls/ConfigBool.h" #include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include "DolphinQt/QtUtils/SignalBlocking.h" #include "DolphinQt/QtUtils/SignalBlocking.h"
@ -275,7 +276,8 @@ void AdvancedPane::Update()
} }
m_cpu_clock_override_slider_label->setText([] { 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 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)); 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)); 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& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming(); 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; return;
s_last_init = core_timing.GetTicks(); s_last_init = core_timing.GetTicks();

View File

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

View File

@ -10,6 +10,7 @@
#include "Core/DolphinAnalytics.h" #include "Core/DolphinAnalytics.h"
#include "Core/HW/SystemTimers.h" #include "Core/HW/SystemTimers.h"
#include "Core/System.h"
#include "VideoCommon/BPFunctions.h" #include "VideoCommon/BPFunctions.h"
#include "VideoCommon/VideoCommon.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( static Common::EventHook s_after_frame_event = AfterFrameEvent::Register(
[] { [] {
DolphinAnalytics::PerformanceSample perf_sample; 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_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; perf_sample.num_draw_calls = g_stats.this_frame.num_draw_calls;
DolphinAnalytics::Instance().ReportPerformanceInfo(std::move(perf_sample)); DolphinAnalytics::Instance().ReportPerformanceInfo(std::move(perf_sample));

View File

@ -546,7 +546,7 @@ void VertexManagerBase::Flush()
if (g_ActiveConfig.bGraphicMods) if (g_ActiveConfig.bGraphicMods)
{ {
const double seconds_elapsed = 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; pixel_shader_manager.constants.time_ms = seconds_elapsed * 1000;
} }