diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp index 50747cf59a..e2ab497e86 100644 --- a/Source/Core/Core/CoreTiming.cpp +++ b/Source/Core/Core/CoreTiming.cpp @@ -129,6 +129,11 @@ void Init() g_slice_length = MAX_SLICE_LENGTH; g_global_timer = 0; s_idled_cycles = 0; + + // The time between CoreTiming being intialized and the first call to Advance() is considered + // the slice boundary between slice -1 and slice 0. Dispatcher loops must call Advance() before + // executing the first PPC cycle of each slice to prepare the slice length and downcount for + // that slice. s_is_global_timer_sane = true; s_ev_lost = RegisterEvent("_lost_event", &EmptyTimedCallback); diff --git a/Source/Core/Core/CoreTiming.h b/Source/Core/Core/CoreTiming.h index 4f209c97bd..28263be94c 100644 --- a/Source/Core/Core/CoreTiming.h +++ b/Source/Core/Core/CoreTiming.h @@ -31,6 +31,8 @@ extern u64 g_fake_TB_start_ticks; extern int g_slice_length; extern float g_last_OC_factor_inverted; +// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is +// required to end slice -1 and start slice 0 before the first cycle of code is executed. void Init(); void Shutdown(); @@ -60,12 +62,22 @@ enum class FromThread }; // userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from savestates. +// After the first Advance, the slice lengths and the downcount will be reduced whenever an event +// is scheduled earlier than the current values (when scheduled from the CPU Thread only). +// Scheduling from a callback will not update the downcount until the Advance() completes. void ScheduleEvent(s64 cycles_into_future, EventType* event_type, u64 userdata = 0, FromThread from = FromThread::CPU); // We only permit one event of each type in the queue at a time. void RemoveEvent(EventType* event_type); void RemoveAllEvents(EventType* event_type); + +// Advance must be called at the beginning of dispatcher loops, not the end. Advance() ends +// the previous timing slice and begins the next one, you must Advance from the previous +// slice to the current one before executing any cycles. CoreTiming starts in slice -1 so an +// Advance() is required to initialize the slice length before the first cycle of emulated +// instructions is executed. +// NOTE: Advance updates the PowerPC downcount and performs a PPC external exception check. void Advance(); void MoveEvents();