diff --git a/pcsx2/IopCounters.cpp b/pcsx2/IopCounters.cpp index bcbca5468a..d29b8ea880 100644 --- a/pcsx2/IopCounters.cpp +++ b/pcsx2/IopCounters.cpp @@ -438,8 +438,6 @@ void psxRcntUpdate() { int i; - psxRegs.iopNextEventCycle = psxRegs.cycle + 32; - psxNextCounter = 0x7fffffff; psxNextsCounter = psxRegs.cycle; diff --git a/pcsx2/R3000A.cpp b/pcsx2/R3000A.cpp index 832b0e26e6..65678c7d06 100644 --- a/pcsx2/R3000A.cpp +++ b/pcsx2/R3000A.cpp @@ -42,6 +42,8 @@ u32 g_psxHasConstReg, g_psxFlushedConstReg; // is true, even if it's already running ahead a bit. bool iopEventAction = false; +static constexpr uint iopWaitCycles = 384; // Keep inline with EE wait cycle max. + bool iopEventTestIsActive = false; alignas(16) psxRegisters psxRegs; @@ -140,13 +142,13 @@ __fi void PSX_INT( IopEventId n, s32 ecycle ) psxSetNextBranchDelta(ecycle); - if (psxRegs.iopCycleEE < 0) + const s32 iopDelta = (psxRegs.iopNextEventCycle - psxRegs.cycle) * 8; + + if (psxRegs.iopCycleEE < iopDelta) { // The EE called this int, so inform it to branch as needed: - // fixme - this doesn't take into account EE/IOP sync (the IOP may be running - // ahead or behind the EE as per the EEsCycles value) - const s32 iopDelta = (psxRegs.iopNextEventCycle - psxRegs.cycle) * 8; - cpuSetNextEventDelta(iopDelta); + + cpuSetNextEventDelta(iopDelta - psxRegs.iopCycleEE); } } @@ -209,6 +211,8 @@ static __fi void _psxTestInterrupts() __ri void iopEventTest() { + psxRegs.iopNextEventCycle = psxRegs.cycle + iopWaitCycles; + if (psxTestCycle(psxNextsCounter, psxNextCounter)) { psxRcntUpdate(); @@ -218,7 +222,8 @@ __ri void iopEventTest() { // start the next branch at the next counter event by default // the interrupt code below will assign nearer branches if needed. - psxRegs.iopNextEventCycle = psxNextsCounter + psxNextCounter; + if (psxNextCounter < (psxRegs.iopNextEventCycle - psxNextsCounter)) + psxRegs.iopNextEventCycle = psxNextsCounter + psxNextCounter; } if (psxRegs.interrupt) diff --git a/pcsx2/R3000A.h b/pcsx2/R3000A.h index f932bf2f2e..af4a3dc0e0 100644 --- a/pcsx2/R3000A.h +++ b/pcsx2/R3000A.h @@ -119,7 +119,7 @@ struct psxRegisters { // cycles can be accounted for later. s32 iopBreak; - // tracks the IOP's current sync status with the EE. When it dips below zero, + // Tracks current number of cycles IOP can run in EE cycles. When it dips below zero, // control is returned to the EE. s32 iopCycleEE; diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index ed04ad308f..b046b75528 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -51,7 +51,7 @@ alignas(16) fpuRegisters fpuRegs; alignas(16) tlbs tlb[48]; R5900cpu *Cpu = NULL; -static const uint eeWaitCycles = 3072; +static constexpr uint eeWaitCycles = 3072; bool eeEventTestIsActive = false; EE_intProcessStatus eeRunInterruptScan = INT_NOT_RUNNING; @@ -453,7 +453,9 @@ __fi void _cpuEventTest_Shared() // ---- Schedule Next Event Test -------------- - if (EEsCycle > 192) + const int nextIopEventDeta = ((psxRegs.iopNextEventCycle - psxRegs.cycle) * 8); + // 8 or more cycles behind and there's an event scheduled + if (EEsCycle >= nextIopEventDeta) { // EE's running way ahead of the IOP still, so we should branch quickly to give the // IOP extra timeslices in short order. @@ -463,8 +465,7 @@ __fi void _cpuEventTest_Shared() } else { - // The IOP could be running ahead/behind of us, so adjust the iop's next branch by its - // relative position to the EE (via EEsCycle) + // Otherwise IOP is caught up/not doing anything so we can wait for the next event. cpuSetNextEventDelta(((psxRegs.iopNextEventCycle - psxRegs.cycle) * 8) - EEsCycle); }