TimingEvents: Swap to 64-bit global ticks
This commit is contained in:
parent
7d80cabf9f
commit
1546b28f46
|
@ -316,7 +316,7 @@ static ModeRegister s_mode = {};
|
|||
static u8 s_interrupt_enable_register = INTERRUPT_REGISTER_MASK;
|
||||
static u8 s_interrupt_flag_register = 0;
|
||||
static u8 s_pending_async_interrupt = 0;
|
||||
static u32 s_last_interrupt_time = 0;
|
||||
static GlobalTicks s_last_interrupt_time = 0;
|
||||
|
||||
static CDImage::Position s_setloc_position = {};
|
||||
static CDImage::LBA s_requested_lba{};
|
||||
|
@ -324,7 +324,7 @@ static CDImage::LBA s_current_lba{}; // this is the hold position
|
|||
static CDImage::LBA s_seek_start_lba{};
|
||||
static CDImage::LBA s_seek_end_lba{};
|
||||
static CDImage::LBA s_physical_lba{}; // current position of the disc with respect to time
|
||||
static u32 s_physical_lba_update_tick = 0;
|
||||
static GlobalTicks s_physical_lba_update_tick = 0;
|
||||
static u32 s_physical_lba_update_carry = 0;
|
||||
static bool s_setloc_pending = false;
|
||||
static bool s_read_after_seek = false;
|
||||
|
@ -484,7 +484,7 @@ void CDROM::Reset()
|
|||
s_mode.read_raw_sector = true;
|
||||
s_interrupt_enable_register = INTERRUPT_REGISTER_MASK;
|
||||
s_interrupt_flag_register = 0;
|
||||
s_last_interrupt_time = System::GetGlobalTickCounter() - MINIMUM_INTERRUPT_DELAY;
|
||||
s_last_interrupt_time = TimingEvents::GetGlobalTickCounter() - MINIMUM_INTERRUPT_DELAY;
|
||||
ClearAsyncInterrupt();
|
||||
s_setloc_position = {};
|
||||
s_seek_start_lba = 0;
|
||||
|
@ -605,14 +605,14 @@ bool CDROM::DoState(StateWrapper& sw)
|
|||
|
||||
sw.Do(&s_interrupt_enable_register);
|
||||
sw.Do(&s_interrupt_flag_register);
|
||||
sw.DoEx(&s_last_interrupt_time, 57, System::GetGlobalTickCounter() - MINIMUM_INTERRUPT_DELAY);
|
||||
//sw.DoEx(&s_last_interrupt_time, 57, TimingEvents::GetGlobalTickCounter() - MINIMUM_INTERRUPT_DELAY);// TODO: FIXME
|
||||
sw.Do(&s_pending_async_interrupt);
|
||||
sw.DoPOD(&s_setloc_position);
|
||||
sw.Do(&s_current_lba);
|
||||
sw.Do(&s_seek_start_lba);
|
||||
sw.Do(&s_seek_end_lba);
|
||||
sw.DoEx(&s_physical_lba, 49, s_current_lba);
|
||||
sw.DoEx(&s_physical_lba_update_tick, 49, static_cast<u32>(0));
|
||||
//sw.DoEx(&s_physical_lba_update_tick, 49, static_cast<u32>(0)); // TODO FIXME
|
||||
sw.DoEx(&s_physical_lba_update_carry, 54, static_cast<u32>(0));
|
||||
sw.Do(&s_setloc_pending);
|
||||
sw.Do(&s_read_after_seek);
|
||||
|
@ -1097,7 +1097,7 @@ bool CDROM::HasPendingAsyncInterrupt()
|
|||
void CDROM::SetInterrupt(Interrupt interrupt)
|
||||
{
|
||||
s_interrupt_flag_register = static_cast<u8>(interrupt);
|
||||
s_last_interrupt_time = System::GetGlobalTickCounter();
|
||||
s_last_interrupt_time = TimingEvents::GetGlobalTickCounter();
|
||||
UpdateInterruptRequest();
|
||||
}
|
||||
|
||||
|
@ -1138,7 +1138,7 @@ void CDROM::QueueDeliverAsyncInterrupt()
|
|||
return;
|
||||
|
||||
// underflows here are okay
|
||||
const u32 diff = System::GetGlobalTickCounter() - s_last_interrupt_time;
|
||||
const GlobalTicks diff = TimingEvents::GetGlobalTickCounter() - s_last_interrupt_time;
|
||||
if (diff >= MINIMUM_INTERRUPT_DELAY)
|
||||
{
|
||||
DeliverAsyncInterrupt(nullptr, 0, 0);
|
||||
|
@ -2442,13 +2442,13 @@ void CDROM::UpdatePositionWhileSeeking()
|
|||
|
||||
s_current_lba = current_lba;
|
||||
s_physical_lba = current_lba;
|
||||
s_physical_lba_update_tick = System::GetGlobalTickCounter();
|
||||
s_physical_lba_update_tick = TimingEvents::GetGlobalTickCounter();
|
||||
s_physical_lba_update_carry = 0;
|
||||
}
|
||||
|
||||
void CDROM::UpdatePhysicalPosition(bool update_logical)
|
||||
{
|
||||
const u32 ticks = System::GetGlobalTickCounter();
|
||||
const u32 ticks = TimingEvents::GetGlobalTickCounter();
|
||||
if (IsSeeking() || IsReadingOrPlaying() || !IsMotorOn())
|
||||
{
|
||||
// If we're seeking+reading the first sector (no stat bits set), we need to return the set/current lba, not the last
|
||||
|
@ -2539,7 +2539,7 @@ void CDROM::SetHoldPosition(CDImage::LBA lba, bool update_subq)
|
|||
|
||||
s_current_lba = lba;
|
||||
s_physical_lba = lba;
|
||||
s_physical_lba_update_tick = System::GetGlobalTickCounter();
|
||||
s_physical_lba_update_tick = TimingEvents::GetGlobalTickCounter();
|
||||
s_physical_lba_update_carry = 0;
|
||||
}
|
||||
|
||||
|
@ -2607,7 +2607,7 @@ bool CDROM::CompleteSeek()
|
|||
}
|
||||
|
||||
s_physical_lba = s_current_lba;
|
||||
s_physical_lba_update_tick = System::GetGlobalTickCounter();
|
||||
s_physical_lba_update_tick = TimingEvents::GetGlobalTickCounter();
|
||||
s_physical_lba_update_carry = 0;
|
||||
return seek_okay;
|
||||
}
|
||||
|
@ -2783,7 +2783,7 @@ void CDROM::DoSectorRead()
|
|||
|
||||
s_current_lba = s_reader.GetLastReadSector();
|
||||
s_physical_lba = s_current_lba;
|
||||
s_physical_lba_update_tick = System::GetGlobalTickCounter();
|
||||
s_physical_lba_update_tick = TimingEvents::GetGlobalTickCounter();
|
||||
s_physical_lba_update_carry = 0;
|
||||
|
||||
s_secondary_status.SetReadingBits(s_drive_state == DriveState::Playing);
|
||||
|
|
|
@ -888,7 +888,7 @@ void CPU::CodeCache::LogCurrentState()
|
|||
"tick=%u dc=%u/%u pc=%08X at=%08X v0=%08X v1=%08X a0=%08X a1=%08X a2=%08X a3=%08X t0=%08X t1=%08X t2=%08X t3=%08X "
|
||||
"t4=%08X t5=%08X t6=%08X t7=%08X s0=%08X s1=%08X s2=%08X s3=%08X s4=%08X s5=%08X s6=%08X s7=%08X t8=%08X t9=%08X "
|
||||
"k0=%08X k1=%08X gp=%08X sp=%08X fp=%08X ra=%08X hi=%08X lo=%08X ldr=%s ldv=%08X cause=%08X sr=%08X gte=%08X\n",
|
||||
System::GetGlobalTickCounter(), g_state.pending_ticks, g_state.downcount, g_state.pc, regs.at, regs.v0, regs.v1,
|
||||
TimingEvents::GetGlobalTickCounter(), g_state.pending_ticks, g_state.downcount, g_state.pc, regs.at, regs.v0, regs.v1,
|
||||
regs.a0, regs.a1, regs.a2, regs.a3, regs.t0, regs.t1, regs.t2, regs.t3, regs.t4, regs.t5, regs.t6, regs.t7, regs.s0,
|
||||
regs.s1, regs.s2, regs.s3, regs.s4, regs.s5, regs.s6, regs.s7, regs.t8, regs.t9, regs.k0, regs.k1, regs.gp, regs.sp,
|
||||
regs.fp, regs.ra, regs.hi, regs.lo,
|
||||
|
|
|
@ -213,7 +213,7 @@ static System::FrameTimeHistory s_frame_time_history;
|
|||
static u32 s_frame_time_history_pos = 0;
|
||||
static u32 s_last_frame_number = 0;
|
||||
static u32 s_last_internal_frame_number = 0;
|
||||
static u32 s_last_global_tick_counter = 0;
|
||||
static GlobalTicks s_last_global_tick_counter = 0;
|
||||
static u64 s_last_cpu_time = 0;
|
||||
static u64 s_last_sw_time = 0;
|
||||
static u32 s_presents_since_last_update = 0;
|
||||
|
@ -403,11 +403,6 @@ void System::UpdateOverclock()
|
|||
UpdateThrottlePeriod();
|
||||
}
|
||||
|
||||
u32 System::GetGlobalTickCounter()
|
||||
{
|
||||
return TimingEvents::GetGlobalTickCounter() + CPU::GetPendingTicks();
|
||||
}
|
||||
|
||||
u32 System::GetFrameNumber()
|
||||
{
|
||||
return s_frame_number;
|
||||
|
@ -2611,7 +2606,7 @@ void System::UpdatePerformanceCounters()
|
|||
|
||||
const u32 frames_run = s_frame_number - s_last_frame_number;
|
||||
const float frames_runf = static_cast<float>(frames_run);
|
||||
const u32 global_tick_counter = GetGlobalTickCounter();
|
||||
const GlobalTicks global_tick_counter = TimingEvents::GetGlobalTickCounter();
|
||||
|
||||
// TODO: Make the math here less rubbish
|
||||
const double pct_divider =
|
||||
|
@ -2672,7 +2667,7 @@ void System::ResetPerformanceCounters()
|
|||
{
|
||||
s_last_frame_number = s_frame_number;
|
||||
s_last_internal_frame_number = s_internal_frame_number;
|
||||
s_last_global_tick_counter = GetGlobalTickCounter();
|
||||
s_last_global_tick_counter = TimingEvents::GetGlobalTickCounter();
|
||||
s_last_cpu_time = s_cpu_thread_handle ? s_cpu_thread_handle.GetCPUTime() : 0;
|
||||
if (const Threading::Thread* sw_thread = g_gpu->GetSWThread(); sw_thread)
|
||||
s_last_sw_time = sw_thread->GetCPUTime();
|
||||
|
|
|
@ -195,7 +195,6 @@ void UpdateOverclock();
|
|||
/// direct execution to this executable.
|
||||
bool InjectEXEFromBuffer(const void* buffer, u32 buffer_size, bool patch_loader = true);
|
||||
|
||||
u32 GetGlobalTickCounter();
|
||||
u32 GetFrameNumber();
|
||||
u32 GetInternalFrameNumber();
|
||||
void IncrementInternalFrameNumber();
|
||||
|
|
|
@ -16,16 +16,16 @@ static TimingEvent* s_active_events_head;
|
|||
static TimingEvent* s_active_events_tail;
|
||||
static TimingEvent* s_current_event = nullptr;
|
||||
static u32 s_active_event_count = 0;
|
||||
static u32 s_global_tick_counter = 0;
|
||||
static u32 s_event_run_tick_counter = 0;
|
||||
static GlobalTicks s_global_tick_counter = 0;
|
||||
static GlobalTicks s_event_run_tick_counter = 0;
|
||||
static bool s_frame_done = false;
|
||||
|
||||
u32 GetGlobalTickCounter()
|
||||
GlobalTicks GetGlobalTickCounter()
|
||||
{
|
||||
return s_global_tick_counter;
|
||||
return s_global_tick_counter + CPU::GetPendingTicks();
|
||||
}
|
||||
|
||||
u32 GetEventRunTickCounter()
|
||||
GlobalTicks GetEventRunTickCounter()
|
||||
{
|
||||
return s_event_run_tick_counter;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ void Initialize()
|
|||
void Reset()
|
||||
{
|
||||
s_global_tick_counter = 0;
|
||||
s_event_run_tick_counter = 0;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
|
@ -58,7 +59,8 @@ std::unique_ptr<TimingEvent> CreateTimingEvent(std::string name, TickCount perio
|
|||
|
||||
void UpdateCPUDowncount()
|
||||
{
|
||||
const u32 event_downcount = s_active_events_head->GetDowncount();
|
||||
DebugAssert(s_active_events_head->GetNextRunTime() >= s_global_tick_counter);
|
||||
const u32 event_downcount = static_cast<u32>(s_active_events_head->GetNextRunTime() - s_global_tick_counter);
|
||||
CPU::g_state.downcount = CPU::HasPendingInterrupt() ? 0 : event_downcount;
|
||||
}
|
||||
|
||||
|
@ -69,13 +71,13 @@ TimingEvent** GetHeadEventPtr()
|
|||
|
||||
static void SortEvent(TimingEvent* event)
|
||||
{
|
||||
const TickCount event_downcount = event->m_downcount;
|
||||
const GlobalTicks event_runtime = event->GetNextRunTime();
|
||||
|
||||
if (event->prev && event->prev->m_downcount > event_downcount)
|
||||
if (event->prev && event->prev->GetNextRunTime() > event_runtime)
|
||||
{
|
||||
// move backwards
|
||||
TimingEvent* current = event->prev;
|
||||
while (current && current->m_downcount > event_downcount)
|
||||
while (current && current->GetNextRunTime() > event_runtime)
|
||||
current = current->prev;
|
||||
|
||||
// unlink
|
||||
|
@ -111,11 +113,11 @@ static void SortEvent(TimingEvent* event)
|
|||
UpdateCPUDowncount();
|
||||
}
|
||||
}
|
||||
else if (event->next && event_downcount > event->next->m_downcount)
|
||||
else if (event->next && event_runtime > event->next->GetNextRunTime())
|
||||
{
|
||||
// move forwards
|
||||
TimingEvent* current = event->next;
|
||||
while (current && event_downcount > current->m_downcount)
|
||||
while (current && event_runtime > current->GetNextRunTime())
|
||||
current = current->next;
|
||||
|
||||
// unlink
|
||||
|
@ -168,9 +170,10 @@ static void AddActiveEvent(TimingEvent* event)
|
|||
DebugAssert(!event->prev && !event->next);
|
||||
s_active_event_count++;
|
||||
|
||||
const GlobalTicks event_runtime = event->GetNextRunTime();
|
||||
TimingEvent* current = nullptr;
|
||||
TimingEvent* next = s_active_events_head;
|
||||
while (next && event->m_downcount > next->m_downcount)
|
||||
while (next && event_runtime > next->GetNextRunTime())
|
||||
{
|
||||
current = next;
|
||||
next = next->next;
|
||||
|
@ -231,7 +234,7 @@ static void RemoveActiveEvent(TimingEvent* event)
|
|||
else
|
||||
{
|
||||
s_active_events_head = event->next;
|
||||
if (s_active_events_head)
|
||||
if (s_active_events_head && !s_current_event)
|
||||
UpdateCPUDowncount();
|
||||
}
|
||||
|
||||
|
@ -295,45 +298,37 @@ void RunEvents()
|
|||
if (CPU::HasPendingInterrupt())
|
||||
CPU::DispatchInterrupt();
|
||||
|
||||
TickCount pending_ticks = CPU::GetPendingTicks();
|
||||
if (pending_ticks >= s_active_events_head->GetDowncount())
|
||||
// TODO: Get rid of pending completely...
|
||||
const GlobalTicks new_global_ticks = s_global_tick_counter + static_cast<GlobalTicks>(CPU::GetPendingTicks());
|
||||
if (new_global_ticks >= s_active_events_head->m_next_run_time)
|
||||
{
|
||||
CPU::ResetPendingTicks();
|
||||
s_event_run_tick_counter = s_global_tick_counter + static_cast<u32>(pending_ticks);
|
||||
s_event_run_tick_counter = new_global_ticks; // TODO: Might be wrong... should move below?but then it'd ping-pong.
|
||||
|
||||
do
|
||||
{
|
||||
const TickCount time = std::min(pending_ticks, s_active_events_head->GetDowncount());
|
||||
s_global_tick_counter += static_cast<u32>(time);
|
||||
pending_ticks -= time;
|
||||
|
||||
// Apply downcount to all events.
|
||||
// This will result in a negative downcount for those events which are late.
|
||||
for (TimingEvent* event = s_active_events_head; event; event = event->next)
|
||||
{
|
||||
event->m_downcount -= time;
|
||||
event->m_time_since_last_run += time;
|
||||
}
|
||||
s_global_tick_counter = std::min(new_global_ticks, s_active_events_head->m_next_run_time);
|
||||
|
||||
// Now we can actually run the callbacks.
|
||||
while (s_active_events_head->m_downcount <= 0)
|
||||
TimingEvent* event;
|
||||
while (s_global_tick_counter >= (event = s_active_events_head)->m_next_run_time)
|
||||
{
|
||||
// move it to the end, since that'll likely be its new position
|
||||
TimingEvent* event = s_active_events_head;
|
||||
s_current_event = event;
|
||||
|
||||
// Factor late time into the time for the next invocation.
|
||||
const TickCount ticks_late = -event->m_downcount;
|
||||
const TickCount ticks_to_execute = event->m_time_since_last_run;
|
||||
event->m_downcount += event->m_interval;
|
||||
event->m_time_since_last_run = 0;
|
||||
const TickCount ticks_late =
|
||||
static_cast<TickCount>(s_global_tick_counter - s_active_events_head->m_next_run_time);
|
||||
const TickCount ticks_to_execute =
|
||||
static_cast<TickCount>(s_global_tick_counter - s_active_events_head->m_last_run_time);
|
||||
s_active_events_head->m_next_run_time += static_cast<GlobalTicks>(event->m_interval);
|
||||
s_active_events_head->m_last_run_time = s_global_tick_counter;
|
||||
|
||||
// The cycles_late is only an indicator, it doesn't modify the cycles to execute.
|
||||
event->m_callback(event->m_callback_param, ticks_to_execute, ticks_late);
|
||||
if (event->m_active)
|
||||
SortEvent(event);
|
||||
}
|
||||
} while (pending_ticks > 0);
|
||||
} while (new_global_ticks > s_event_run_tick_counter);
|
||||
|
||||
s_current_event = nullptr;
|
||||
}
|
||||
|
@ -379,8 +374,9 @@ bool DoState(StateWrapper& sw)
|
|||
}
|
||||
|
||||
// Using reschedule is safe here since we call sort afterwards.
|
||||
event->m_downcount = downcount;
|
||||
event->m_time_since_last_run = time_since_last_run;
|
||||
Panic("Fixme");
|
||||
//event->m_downcount = downcount;
|
||||
//event->m_time_since_last_run = time_since_last_run;
|
||||
event->m_period = period;
|
||||
event->m_interval = interval;
|
||||
}
|
||||
|
@ -402,8 +398,8 @@ bool DoState(StateWrapper& sw)
|
|||
for (TimingEvent* event = s_active_events_head; event; event = event->next)
|
||||
{
|
||||
sw.Do(&event->m_name);
|
||||
sw.Do(&event->m_downcount);
|
||||
sw.Do(&event->m_time_since_last_run);
|
||||
//sw.Do(&event->m_downcount);
|
||||
//sw.Do(&event->m_time_since_last_run);
|
||||
sw.Do(&event->m_period);
|
||||
sw.Do(&event->m_interval);
|
||||
}
|
||||
|
@ -418,7 +414,7 @@ bool DoState(StateWrapper& sw)
|
|||
|
||||
TimingEvent::TimingEvent(std::string name, TickCount period, TickCount interval, TimingEventCallback callback,
|
||||
void* callback_param)
|
||||
: m_callback(callback), m_callback_param(callback_param), m_downcount(interval), m_time_since_last_run(0),
|
||||
: m_callback(callback), m_callback_param(callback_param), m_next_run_time(TimingEvents::GetGlobalTickCounter() + static_cast<GlobalTicks>(interval)), m_last_run_time(TimingEvents::GetGlobalTickCounter()),
|
||||
m_period(period), m_interval(interval), m_name(std::move(name))
|
||||
{
|
||||
}
|
||||
|
@ -429,16 +425,6 @@ TimingEvent::~TimingEvent()
|
|||
TimingEvents::RemoveActiveEvent(this);
|
||||
}
|
||||
|
||||
TickCount TimingEvent::GetTicksSinceLastExecution() const
|
||||
{
|
||||
return CPU::GetPendingTicks() + m_time_since_last_run;
|
||||
}
|
||||
|
||||
TickCount TimingEvent::GetTicksUntilNextExecution() const
|
||||
{
|
||||
return std::max(m_downcount - CPU::GetPendingTicks(), static_cast<TickCount>(0));
|
||||
}
|
||||
|
||||
void TimingEvent::Delay(TickCount ticks)
|
||||
{
|
||||
if (!m_active)
|
||||
|
@ -447,7 +433,7 @@ void TimingEvent::Delay(TickCount ticks)
|
|||
return;
|
||||
}
|
||||
|
||||
m_downcount += ticks;
|
||||
m_next_run_time += static_cast<GlobalTicks>(ticks);
|
||||
|
||||
DebugAssert(TimingEvents::s_current_event != this);
|
||||
TimingEvents::SortEvent(this);
|
||||
|
@ -457,13 +443,13 @@ void TimingEvent::Delay(TickCount ticks)
|
|||
|
||||
void TimingEvent::Schedule(TickCount ticks)
|
||||
{
|
||||
const TickCount pending_ticks = CPU::GetPendingTicks();
|
||||
m_downcount = pending_ticks + ticks;
|
||||
const GlobalTicks current_ticks = TimingEvents::GetGlobalTickCounter();
|
||||
m_next_run_time = current_ticks + static_cast<GlobalTicks>(ticks);
|
||||
|
||||
if (!m_active)
|
||||
{
|
||||
// Event is going active, so we want it to only execute ticks from the current timestamp.
|
||||
m_time_since_last_run = -pending_ticks;
|
||||
m_last_run_time = current_ticks;
|
||||
m_active = true;
|
||||
TimingEvents::AddActiveEvent(this);
|
||||
}
|
||||
|
@ -498,8 +484,9 @@ void TimingEvent::Reset()
|
|||
if (!m_active)
|
||||
return;
|
||||
|
||||
m_downcount = m_interval;
|
||||
m_time_since_last_run = 0;
|
||||
const GlobalTicks current_ticks = TimingEvents::GetGlobalTickCounter();
|
||||
m_next_run_time = current_ticks + static_cast<GlobalTicks>(m_interval);
|
||||
m_last_run_time = current_ticks;
|
||||
if (TimingEvents::s_current_event != this)
|
||||
{
|
||||
TimingEvents::SortEvent(this);
|
||||
|
@ -513,13 +500,15 @@ void TimingEvent::InvokeEarly(bool force /* = false */)
|
|||
if (!m_active)
|
||||
return;
|
||||
|
||||
const TickCount pending_ticks = CPU::GetPendingTicks();
|
||||
const TickCount ticks_to_execute = m_time_since_last_run + pending_ticks;
|
||||
const GlobalTicks current_ticks = TimingEvents::GetGlobalTickCounter();
|
||||
DebugAssert(current_ticks >= m_last_run_time);
|
||||
|
||||
const TickCount ticks_to_execute = static_cast<TickCount>(current_ticks - m_last_run_time);
|
||||
if ((!force && ticks_to_execute < m_period) || ticks_to_execute <= 0)
|
||||
return;
|
||||
|
||||
m_downcount = pending_ticks + m_interval;
|
||||
m_time_since_last_run -= ticks_to_execute;
|
||||
m_next_run_time = current_ticks + static_cast<GlobalTicks>(m_interval);
|
||||
m_last_run_time = current_ticks;
|
||||
m_callback(m_callback_param, ticks_to_execute, 0);
|
||||
|
||||
// Since we've changed the downcount, we need to re-sort the events.
|
||||
|
@ -534,10 +523,9 @@ void TimingEvent::Activate()
|
|||
if (m_active)
|
||||
return;
|
||||
|
||||
// leave the downcount intact
|
||||
const TickCount pending_ticks = CPU::GetPendingTicks();
|
||||
m_downcount += pending_ticks;
|
||||
m_time_since_last_run -= pending_ticks;
|
||||
const GlobalTicks current_ticks = TimingEvents::GetGlobalTickCounter();
|
||||
m_next_run_time = current_ticks + static_cast<GlobalTicks>(m_interval);
|
||||
m_last_run_time = current_ticks;
|
||||
|
||||
m_active = true;
|
||||
TimingEvents::AddActiveEvent(this);
|
||||
|
@ -548,10 +536,6 @@ void TimingEvent::Deactivate()
|
|||
if (!m_active)
|
||||
return;
|
||||
|
||||
const TickCount pending_ticks = CPU::GetPendingTicks();
|
||||
m_downcount -= pending_ticks;
|
||||
m_time_since_last_run += pending_ticks;
|
||||
|
||||
m_active = false;
|
||||
TimingEvents::RemoveActiveEvent(this);
|
||||
}
|
||||
|
|
|
@ -11,9 +11,37 @@
|
|||
|
||||
class StateWrapper;
|
||||
|
||||
class TimingEvent;
|
||||
|
||||
// Event callback type. Second parameter is the number of cycles the event was executed "late".
|
||||
using TimingEventCallback = void (*)(void* param, TickCount ticks, TickCount ticks_late);
|
||||
|
||||
namespace TimingEvents {
|
||||
|
||||
GlobalTicks GetGlobalTickCounter();
|
||||
GlobalTicks GetEventRunTickCounter();
|
||||
|
||||
void Initialize();
|
||||
void Reset();
|
||||
void Shutdown();
|
||||
|
||||
/// Creates a new event.
|
||||
std::unique_ptr<TimingEvent> CreateTimingEvent(std::string name, TickCount period, TickCount interval,
|
||||
TimingEventCallback callback, void* callback_param, bool activate);
|
||||
|
||||
/// Serialization.
|
||||
bool DoState(StateWrapper& sw);
|
||||
|
||||
bool IsRunningEvents();
|
||||
void SetFrameDone();
|
||||
void RunEvents();
|
||||
|
||||
void UpdateCPUDowncount();
|
||||
|
||||
TimingEvent** GetHeadEventPtr();
|
||||
|
||||
} // namespace TimingEvents
|
||||
|
||||
class TimingEvent
|
||||
{
|
||||
public:
|
||||
|
@ -27,11 +55,18 @@ public:
|
|||
// Returns the number of ticks between each event.
|
||||
ALWAYS_INLINE TickCount GetPeriod() const { return m_period; }
|
||||
ALWAYS_INLINE TickCount GetInterval() const { return m_interval; }
|
||||
ALWAYS_INLINE TickCount GetDowncount() const { return m_downcount; }
|
||||
ALWAYS_INLINE GlobalTicks GetNextRunTime() const { return m_next_run_time; }
|
||||
ALWAYS_INLINE GlobalTicks GetLastRunTime() const { return m_last_run_time; }
|
||||
|
||||
// Includes pending time.
|
||||
TickCount GetTicksSinceLastExecution() const;
|
||||
TickCount GetTicksUntilNextExecution() const;
|
||||
ALWAYS_INLINE TickCount GetTicksSinceLastExecution() const
|
||||
{
|
||||
return static_cast<TickCount>(TimingEvents::GetGlobalTickCounter() - m_last_run_time);
|
||||
}
|
||||
ALWAYS_INLINE TickCount GetTicksUntilNextExecution() const
|
||||
{
|
||||
return static_cast<TickCount>(m_next_run_time - TimingEvents::GetGlobalTickCounter());
|
||||
}
|
||||
|
||||
// Adds ticks to current execution.
|
||||
void Delay(TickCount ticks);
|
||||
|
@ -69,37 +104,11 @@ public:
|
|||
TimingEventCallback m_callback;
|
||||
void* m_callback_param;
|
||||
|
||||
TickCount m_downcount;
|
||||
TickCount m_time_since_last_run;
|
||||
GlobalTicks m_next_run_time;
|
||||
GlobalTicks m_last_run_time;
|
||||
TickCount m_period;
|
||||
TickCount m_interval;
|
||||
bool m_active = false;
|
||||
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
namespace TimingEvents {
|
||||
|
||||
u32 GetGlobalTickCounter();
|
||||
u32 GetEventRunTickCounter();
|
||||
|
||||
void Initialize();
|
||||
void Reset();
|
||||
void Shutdown();
|
||||
|
||||
/// Creates a new event.
|
||||
std::unique_ptr<TimingEvent> CreateTimingEvent(std::string name, TickCount period, TickCount interval,
|
||||
TimingEventCallback callback, void* callback_param, bool activate);
|
||||
|
||||
/// Serialization.
|
||||
bool DoState(StateWrapper& sw);
|
||||
|
||||
bool IsRunningEvents();
|
||||
void SetFrameDone();
|
||||
void RunEvents();
|
||||
|
||||
void UpdateCPUDowncount();
|
||||
|
||||
TimingEvent** GetHeadEventPtr();
|
||||
|
||||
} // namespace TimingEvents
|
|
@ -20,7 +20,8 @@ enum class MemoryAccessSize : u32
|
|||
Word
|
||||
};
|
||||
|
||||
using TickCount = s32;
|
||||
using TickCount = s32; // TODO: Make u32
|
||||
using GlobalTicks = u64;
|
||||
|
||||
enum class ConsoleRegion
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue