diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index 525f7165f2..74ad817bf4 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -250,6 +250,8 @@ void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata if(tsLast) tsLast->next = ne; tsLast = ne; + + SetDowncount(ne->type, cyclesIntoFuture); } // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread @@ -260,6 +262,7 @@ void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) { std::lock_guard lk(externalEventSection); event_types[event_type].callback(userdata, 0); + SetDowncount(event_type, 0); } else ScheduleEvent_Threadsafe(0, event_type, userdata); @@ -413,6 +416,21 @@ void SetMaximumSlice(int maximumSliceLength) maxSliceLength = maximumSliceLength; } +void SetDowncount(int event_type, int cycles) +{ + if (event_types[event_type].name == "SetToken") + return; + + if (cycles == 0) + cycles = 100; // External Exception latency. Paper Mario TTYD freezes in fight scenes if this is zero. + + if (downcount > cycles) + { + slicelength -= (downcount - cycles); // Account for cycles already executed by adjusting the slicelength + downcount = cycles; + } +} + void ResetSliceLength() { maxSliceLength = MAX_SLICE_LENGTH; diff --git a/Source/Core/Core/Src/CoreTiming.h b/Source/Core/Core/Src/CoreTiming.h index db8dcecfc1..88c9de5948 100644 --- a/Source/Core/Core/Src/CoreTiming.h +++ b/Source/Core/Core/Src/CoreTiming.h @@ -92,6 +92,8 @@ void SetFakeTBStartValue(u64 val); u64 GetFakeTBStartTicks(); void SetFakeTBStartTicks(u64 val); +void SetDowncount(int event_type, int cycles); + extern int downcount; extern int slicelength; diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp index 4b2eaba1e0..71b4591bf7 100644 --- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp @@ -144,7 +144,7 @@ void Init() isHiWatermarkActive = false; isLoWatermarkActive = false; - et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper); + et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper); } void Read16(u16& _rReturnValue, const u32 _Address)