diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index 05ca7bc39f..173f2a922c 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -21,9 +21,7 @@ #include "VMManager.h" #include "VUmicro.h" -extern u8 psxhblankgate; static const uint EECNT_FUTURE_TARGET = 0x10000000; -static int gates = 0; uint g_FrameCount = 0; @@ -75,7 +73,7 @@ static __fi void _rcntSet(int cntidx) const Counter& counter = counters[cntidx]; // Stopped or special hsync gate? - if (!counter.mode.IsCounting || (counter.mode.ClockSource == 0x3)) + if (!rcntCanCount(cntidx) || (counter.mode.ClockSource == 0x3)) return; if (!counter.mode.TargetInterrupt && !counter.mode.OverflowInterrupt) @@ -232,7 +230,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 sca { hBlank /= 2; hRender /= 2; - } + } //TODO: Carry fixed-point math all the way through the entire vsync and hsync counting processes, and continually apply rounding //as needed for each scheduled v/hsync related event. Much better to handle than this messed state. @@ -512,8 +510,7 @@ static __fi void VSyncStart(u32 sCycle) // Memcard IO detection - Uses a tick system to determine when memcards are no longer being written. MemcardBusy::Decrement(); - if (gates) - rcntStartGate(true, sCycle); // Counters Start Gate code + rcntStartGate(true, sCycle); // Counters Start Gate code // INTC - VB Blank Start Hack -- // Hack fix! This corrects a freezeup in Granda 2 where it decides to spin @@ -570,8 +567,7 @@ static __fi void VSyncEnd(u32 sCycle) hwIntcIrq(INTC_VBLANK_E); // HW Irq psxVBlankEnd(); // psxCounters vBlank End - if (gates) - rcntEndGate(true, sCycle); // Counters End Gate Code + rcntEndGate(true, sCycle); // Counters End Gate Code // FolderMemoryCard needs information on how much time has passed since the last write // Call it every 60 frames @@ -597,13 +593,14 @@ __fi void rcntUpdate_hScanline() //iopEventAction = 1; if (hsyncCounter.Mode == MODE_HBLANK) { //HBLANK Start + + rcntStartGate(false, hsyncCounter.sCycle + hsyncCounter.CycleT); + psxHBlankStart(); + // Setup the hRender's start and end cycle information: hsyncCounter.sCycle += vSyncInfo.hBlank; // start (absolute cycle value) hsyncCounter.CycleT = vSyncInfo.hRender; // endpoint (delta from start value) hsyncCounter.Mode = MODE_HRENDER; - - rcntStartGate(false, hsyncCounter.sCycle); - psxCheckStartGate16(0); } else { //HBLANK END / HRENDER Begin @@ -614,16 +611,15 @@ __fi void rcntUpdate_hScanline() gsIrq(); } + rcntEndGate(false, hsyncCounter.sCycle + hsyncCounter.CycleT); + + psxHBlankEnd(); + // set up the hblank's start and end cycle information: hsyncCounter.sCycle += vSyncInfo.hRender; // start (absolute cycle value) hsyncCounter.CycleT = vSyncInfo.hBlank; // endpoint (delta from start value) hsyncCounter.Mode = MODE_HBLANK; - if (gates) - rcntEndGate(false, hsyncCounter.sCycle); - if (psxhblankgate) - psxCheckEndGate16(0); - #ifdef VSYNC_DEBUG hsc++; #endif @@ -637,11 +633,11 @@ __fi void rcntUpdate_vSync() if (vsyncCounter.Mode == MODE_VSYNC) { + VSyncEnd(vsyncCounter.sCycle + vsyncCounter.CycleT); + vsyncCounter.sCycle += vSyncInfo.Blank; vsyncCounter.CycleT = vSyncInfo.Render; - vsyncCounter.Mode = MODE_VRENDER; - - VSyncEnd(vsyncCounter.sCycle); + vsyncCounter.Mode = MODE_VRENDER; // VSYNC END - Render begin } else if (vsyncCounter.Mode == MODE_GSBLANK) // GS CSR Swap and interrupt { @@ -651,8 +647,10 @@ __fi void rcntUpdate_vSync() // Don't set the start cycle, makes it easier to calculate the correct Vsync End time vsyncCounter.CycleT = vSyncInfo.Blank; } - else // VSYNC end / VRENDER begin + else // VSYNC Start { + VSyncStart(vsyncCounter.sCycle + vsyncCounter.CycleT); + vsyncCounter.sCycle += vSyncInfo.Render; vsyncCounter.CycleT = vSyncInfo.GSBlank; vsyncCounter.Mode = MODE_GSBLANK; @@ -660,8 +658,6 @@ __fi void rcntUpdate_vSync() // Accumulate hsync rounding errors: hsyncCounter.sCycle += vSyncInfo.hSyncError; - VSyncStart(vsyncCounter.sCycle); - #ifdef VSYNC_DEBUG vblankinc++; if (vblankinc > 1) @@ -717,7 +713,20 @@ static __fi void _cpuTestOverflow(int i) } -// forceinline note: this method is called from two locations, but one +__fi bool rcntCanCount(int i) +{ + if (!counters[i].mode.IsCounting) + return false; + + if (!counters[i].mode.EnableGate) + return true; + + // If we're in gate mode, we can only count if it's not both gated and counting on HBLANK or GateMode is not 0 (Count only when low) or the signal is low. + return ((counters[i].mode.GateSource == 0 && counters[i].mode.ClockSource != 3 && (hsyncCounter.Mode == MODE_HRENDER || counters[i].mode.GateMode != 0)) || + (counters[i].mode.GateSource == 1 && (vsyncCounter.Mode == MODE_VRENDER || counters[i].mode.GateMode != 0))); +} + + // forceinline note: this method is called from two locations, but one // of them is the interpreter, which doesn't count. ;) So might as // well forceinline it! __fi void rcntUpdate() @@ -730,12 +739,7 @@ __fi void rcntUpdate() for (int i = 0; i <= 3; i++) { - // We want to count gated counters (except the hblank which exclude below, and are - // counted by the hblank timer instead) - - //if ( gates & (1<> 1; + + if (cntidx == 2 || cntidx == 4 || cntidx == 5) + { + // Gates being enabled on these counters forces it to disable the counter if being on or off depends on a gate being on or off. + return (gateMode & 1); + } + + const bool blanking = cntidx == 0 ? hBlanking : vBlanking; + + // Stop counting if Gate mode 0 (only count when rendering) and blanking or Gate mode 2 (only count when blanking) when not blanking + if ((gateMode == 0 && blanking == true) || (gateMode == 2 && blanking == false)) + return false; + + // All other cases allow counting. + return true; +} + static void _rcntSet(int cntidx) { u64 overflowCap = (cntidx >= 3) ? 0x100000000ULL : 0x10000; @@ -83,7 +111,7 @@ static void _rcntSet(int cntidx) // that into account. Adding the difference from that cycle count to the current one // will do the trick! - if (counter.mode & IOPCNT_STOPPED || counter.rate == PSXHBLANK) + if (counter.rate == PSXHBLANK || !psxRcntCanCount(cntidx)) return; if (!(counter.mode & (IOPCNT_INT_TARGET | IOPCNT_INT_OVERFLOW))) @@ -256,6 +284,9 @@ Gate: TM_GATE_ON_Clear_OFF_Start 101 TM_GATE_ON_Start 111 + = means counting + - means not counting + V-blank ----+ +----------------------------+ +------ | | | | | | | | @@ -266,19 +297,19 @@ Gate: TM_GATE_ON_Count: - <---->0==========================><---->0===== + <---->===========================><---->====== TM_GATE_ON_ClearStart: - 0====>0================================>0===== + =====>0================================>0===== TM_GATE_ON_Clear_OFF_Start: - 0====><-------------------------->0====><----- + 0====>0-------------------------->0====>0----- TM_GATE_ON_Start: - <---->0==========================>============ + <---->===========================>============ */ static void _psxCheckStartGate(int i) @@ -288,30 +319,32 @@ static void _psxCheckStartGate(int i) switch ((psxCounters[i].mode & 0x6) >> 1) { - case 0x0: // GATE_ON_count - stop count on gate start: + case 0x0: // GATE_ON_count - count while gate signal is low (RENDER) // get the current count at the time of stoppage: psxCounters[i].count = (i < 3) ? psxRcntRcount16(i) : psxRcntRcount32(i); - psxCounters[i].mode |= IOPCNT_STOPPED; - return; - case 0x1: // GATE_ON_ClearStart - count normally with resets after every end gate - // do nothing - All counting will be done on a need-to-count basis. - return; - - case 0x2: // GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end - psxCounters[i].count = 0; + // Not strictly necessary. psxCounters[i].sCycleT = psxRegs.cycle; - psxCounters[i].mode &= ~IOPCNT_STOPPED; break; - case 0x3: //GATE_ON_Start - start and count normally on gate end (no restarts or stops or clears) + case 0x1: // GATE_ON_ClearStart - Counts constantly, clears on Blank END // do nothing! - return; + break; + + case 0x2: // GATE_ON_Clear_OFF_Start - Counts only when Blanking, clears on both ends, starts counting on next Blank Start. + psxCounters[i].mode &= ~IOPCNT_STOPPED; + psxCounters[i].count = 0; + psxCounters[i].target &= ~IOPCNT_FUTURE_TARGET; + psxCounters[i].sCycleT = psxRegs.cycle; + break; + + case 0x3: //GATE_ON_Start - Starts counting when the next Blank Ends, no clear. + // do nothing! + break; } - _rcntSet(i); } static void _psxCheckEndGate(int i) @@ -319,105 +352,94 @@ static void _psxCheckEndGate(int i) if (!(psxCounters[i].mode & IOPCNT_ENABLE_GATE)) return; // Ignore Gate + // NOTE: Starting and stopping of modes 0 and 2 are checked in psxRcntCanCount(), only need to update the start cycle and counts. switch ((psxCounters[i].mode & 0x6) >> 1) { - case 0x0: // GATE_ON_count - reset and start counting - case 0x1: // GATE_ON_ClearStart - count normally with resets after every end gate - psxCounters[i].count = 0; + case 0x0: // GATE_ON_count - count while gate signal is low (RENDER) psxCounters[i].sCycleT = psxRegs.cycle; - psxCounters[i].mode &= ~IOPCNT_STOPPED; break; - case 0x2: // GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end - psxCounters[i].count = (i < 3) ? psxRcntRcount16(i) : psxRcntRcount32(i); - psxCounters[i].mode |= IOPCNT_STOPPED; - return; // do not set the counter + case 0x1: // GATE_ON_ClearStart - Counts constantly, clears on Blank END + psxCounters[i].count = 0; + psxCounters[i].target &= ~IOPCNT_FUTURE_TARGET; + break; - case 0x3: // GATE_ON_Start - start and count normally (no restarts or stops or clears) + case 0x2: // GATE_ON_Clear_OFF_Start - Counts only when Blanking, clears on both ends, starts counting on next Blank Start. + // No point in updating the count, since we're gonna clear it. + psxCounters[i].count = 0; + psxCounters[i].target &= ~IOPCNT_FUTURE_TARGET; + psxCounters[i].sCycleT = psxRegs.cycle; + break; // do not set the counter + + case 0x3: // GATE_ON_Start - Starts counting when the next Blank Ends, no clear. if (psxCounters[i].mode & IOPCNT_STOPPED) { - psxCounters[i].count = 0; psxCounters[i].sCycleT = psxRegs.cycle; psxCounters[i].mode &= ~IOPCNT_STOPPED; } break; } - _rcntSet(i); } -void psxCheckStartGate16(int i) +void psxHBlankStart() { - pxAssert(i < 3); - - if (i == 0) // hSync counting + // AlternateSource/scanline counters for Gates 1 and 3. + // We count them here so that they stay nicely synced with the EE's hsync. + if ((psxCounters[1].rate == PSXHBLANK) && psxRcntCanCount(1)) { - // AlternateSource/scanline counters for Gates 1 and 3. - // We count them here so that they stay nicely synced with the EE's hsync. - - const u32 altSourceCheck = IOPCNT_ALT_SOURCE | IOPCNT_ENABLE_GATE; - const u32 stoppedGateCheck = (IOPCNT_STOPPED | altSourceCheck); - - // count if alt source is enabled and either: - // * the gate is enabled and not stopped. - // * the gate is disabled. - - if ((psxCounters[1].mode & altSourceCheck) == IOPCNT_ALT_SOURCE || - (psxCounters[1].mode & stoppedGateCheck) == altSourceCheck) - { - psxCounters[1].count++; - _rcntTestOverflow(1); - _rcntTestTarget(1); - } - - if ((psxCounters[3].mode & altSourceCheck) == IOPCNT_ALT_SOURCE || - (psxCounters[3].mode & stoppedGateCheck) == altSourceCheck) - { - psxCounters[3].count++; - _rcntTestOverflow(3); - _rcntTestTarget(3); - } + psxCounters[1].count++; + _rcntTestOverflow(1); + _rcntTestTarget(1); } - _psxCheckStartGate(i); + if ((psxCounters[3].rate == PSXHBLANK) && psxRcntCanCount(3)) + { + psxCounters[3].count++; + _rcntTestOverflow(3); + _rcntTestTarget(3); + } + + _psxCheckStartGate(0); + + hBlanking = true; + + _rcntSet(0); } -void psxCheckEndGate16(int i) +void psxHBlankEnd() { - pxAssert(i < 3); - _psxCheckEndGate(i); -} + _psxCheckEndGate(0); -static void psxCheckStartGate32(int i) -{ - // 32 bit gate is called for gate 3 only. Ever. - pxAssert(i == 3); - _psxCheckStartGate(i); -} + hBlanking = false; -static void psxCheckEndGate32(int i) -{ - pxAssert(i == 3); - _psxCheckEndGate(i); + _rcntSet(0); } - void psxVBlankStart() { cdvdVsync(); iopIntcIrq(0); - if (psxvblankgate & (1 << 1)) - psxCheckStartGate16(1); - if (psxvblankgate & (1 << 3)) - psxCheckStartGate32(3); + + _psxCheckStartGate(1); + _psxCheckStartGate(3); + + vBlanking = true; + + _rcntSet(1); + _rcntSet(3); } void psxVBlankEnd() { iopIntcIrq(11); - if (psxvblankgate & (1 << 1)) - psxCheckEndGate16(1); - if (psxvblankgate & (1 << 3)) - psxCheckEndGate32(3); + + _psxCheckEndGate(1); + _psxCheckEndGate(3); + + vBlanking = false; + + _rcntSet(1); + _rcntSet(3); } void psxRcntUpdate() @@ -427,13 +449,13 @@ void psxRcntUpdate() psxNextCounter = 0x7fffffff; psxNextsCounter = psxRegs.cycle; - for (i = 0; i <= 5; i++) + for (i = 0; i < 6; i++) { // don't count disabled or hblank counters... // We can't check the ALTSOURCE flag because the PSXCLOCK source *should* // be counted here. - if (psxCounters[i].mode & IOPCNT_STOPPED) + if (!psxRcntCanCount(i)) continue; if ((psxCounters[i].mode & IOPCNT_INT_REPEAT) && !(psxCounters[i].mode & IOPCNT_INT_TOGGLE)) @@ -448,39 +470,20 @@ void psxRcntUpdate() { const u32 change = (psxRegs.cycle - psxCounters[i].sCycleT) / psxCounters[i].rate; - if (change <= 0) - continue; - - psxCounters[i].count += change; - psxCounters[i].sCycleT += change * psxCounters[i].rate; + if (change > 0) + { + psxCounters[i].count += change; + psxCounters[i].sCycleT += change * psxCounters[i].rate; + } } else { psxCounters[i].count += psxRegs.cycle - psxCounters[i].sCycleT; psxCounters[i].sCycleT = psxRegs.cycle; } - } - - // Do target/overflow testing - // Optimization Note: This approach is very sound. Please do not try to unroll it - // as the size of the Test functions will cause code cache clutter and slowness. - - for (i = 0; i < 6; i++) - { - // don't do target/oveflow checks for hblankers. Those - // checks are done when the counters are updated. - if (psxCounters[i].rate == PSXHBLANK) - continue; - if (psxCounters[i].mode & IOPCNT_STOPPED) - continue; _rcntTestOverflow(i); _rcntTestTarget(i); - - // perform second target test because if we overflowed above it's possible we - // already shot past our target if it was very near zero. - - //if( psxCounters[i].count >= psxCounters[i].target ) _rcntTestTarget( i ); } const u32 spu2_delta = (psxRegs.cycle - lClocks) % 768; @@ -615,11 +618,6 @@ __fi void psxRcntWmode16(int index, u32 value) break; jNO_DEFAULT; } - - if ((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1) - { - counter.mode |= IOPCNT_STOPPED; - } } else { @@ -629,26 +627,22 @@ __fi void psxRcntWmode16(int index, u32 value) if (value & IOPCNT_ALT_SOURCE) counter.rate = (index == 0) ? PSXPIXEL : PSXHBLANK; + if (counter.rate == PSXPIXEL) + Console.Warning("PSX Pixel clock set to time 0, sync may be incorrect"); + if (counter.mode & IOPCNT_ENABLE_GATE) { - // gated counters are added up as per the h/vblank timers. - // (the PIXEL alt source becomes a vsync gate) - counter.mode |= IOPCNT_STOPPED; + // If set to gate mode 3, the counting starts at the end of the next blank depending on which counter. + if ((counter.mode & IOPCNT_MODE_GATE) == 0x4 && !psxRcntCanCount(index)) + counter.mode |= IOPCNT_STOPPED; + else if ((counter.mode & IOPCNT_MODE_GATE) == 0x6) + counter.mode |= IOPCNT_STOPPED; + PSXCNT_LOG("IOP Counter[%d] Gate Check set, value = 0x%04X", index, value); - if (index == 0) - psxhblankgate |= 1; // fixme: these gate flags should be one var >_< - else - psxvblankgate |= 1 << 1; - } - else - { - if (index == 0) - psxhblankgate &= ~1; - else - psxvblankgate &= ~(1 << 1); } } + // Current counter *always* resets on mode write. counter.count = 0; counter.sCycleT = psxRegs.cycle; @@ -703,11 +697,10 @@ __fi void psxRcntWmode32(int index, u32 value) if (counter.mode & IOPCNT_ENABLE_GATE) { PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value); - counter.mode |= IOPCNT_STOPPED; - psxvblankgate |= 1 << 3; + // If set to gate mode 2 or 3, the counting starts at the start and end of the next blank respectively depending on which counter. + if ((counter.mode & IOPCNT_MODE_GATE) > 0x2) + counter.mode |= IOPCNT_STOPPED; } - else - psxvblankgate &= ~(1 << 3); } else { @@ -726,15 +719,9 @@ __fi void psxRcntWmode32(int index, u32 value) counter.rate = 256; break; } - - // Need to set a rate and target - if ((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1) - { - Console.WriteLn("Gate set on IOP Counter %d, disabling", index); - counter.mode |= IOPCNT_STOPPED; - } } + // Current counter *always* resets on mode write. counter.count = 0; counter.sCycleT = psxRegs.cycle; counter.target &= 0xffffffff; @@ -755,7 +742,7 @@ void psxRcntWtarget16(int index, u32 value) psxCounters[index].mode |= IOPCNT_INT_REQ; // Interrupt flag reset to high } - if (!(psxCounters[index].mode & IOPCNT_STOPPED) && + if (psxRcntCanCount(index) && (psxCounters[index].rate != PSXHBLANK)) { // Re-adjust the sCycleT to match where the counter is currently @@ -789,7 +776,7 @@ void psxRcntWtarget32(int index, u32 value) psxCounters[index].mode |= IOPCNT_INT_REQ; // Interrupt flag reset to high } - if (!(psxCounters[index].mode & IOPCNT_STOPPED) && + if (psxRcntCanCount(index) && (psxCounters[index].rate != PSXHBLANK)) { // Re-adjust the sCycleT to match where the counter is currently @@ -819,14 +806,15 @@ u16 psxRcntRcount16(int index) // Don't count HBLANK timers // Don't count stopped gates either. - - if (!(psxCounters[index].mode & IOPCNT_STOPPED) && - (psxCounters[index].rate != PSXHBLANK)) + const bool canCount = psxRcntCanCount(index); + if ((psxCounters[index].rate != PSXHBLANK) && canCount) { u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); retval += delta; PSXCNT_LOG(" (delta = %lx)", delta); } + else if (!canCount && (psxCounters[index].mode & IOPCNT_ENABLE_GATE) && (psxCounters[index].mode & IOPCNT_MODE_GATE) == 4) + retval = 0; return (u16)retval; } @@ -839,35 +827,19 @@ u32 psxRcntRcount32(int index) PSXCNT_LOG("IOP Counter[%d] readCount32 = %lx", index, retval); - if (!(psxCounters[index].mode & IOPCNT_STOPPED) && - (psxCounters[index].rate != PSXHBLANK)) + const bool canCount = psxRcntCanCount(index); + if ((psxCounters[index].rate != PSXHBLANK) && canCount) { u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); retval += delta; PSXCNT_LOG(" (delta = %lx)", delta); } + else if (!canCount && (psxCounters[index].mode & IOPCNT_ENABLE_GATE) && (psxCounters[index].mode & IOPCNT_MODE_GATE) == 4) + retval = 0; return retval; } -void psxRcntSetGates() -{ - if (psxCounters[0].mode & IOPCNT_ENABLE_GATE) - psxhblankgate |= 1; - else - psxhblankgate &= ~1; - - if (psxCounters[1].mode & IOPCNT_ENABLE_GATE) - psxvblankgate |= 1 << 1; - else - psxvblankgate &= ~(1 << 1); - - if (psxCounters[3].mode & IOPCNT_ENABLE_GATE) - psxvblankgate |= 1 << 3; - else - psxvblankgate &= ~(1 << 3); -} - bool SaveStateBase::psxRcntFreeze() { if (!FreezeTag("iopCounters")) @@ -876,8 +848,8 @@ bool SaveStateBase::psxRcntFreeze() Freeze(psxCounters); Freeze(psxNextCounter); Freeze(psxNextsCounter); - Freeze(psxvblankgate); - Freeze(psxhblankgate); + Freeze(hBlanking); + Freeze(vBlanking); if (!IsOkay()) return false; diff --git a/pcsx2/IopCounters.h b/pcsx2/IopCounters.h index 4c6ab8254f..c56f21e9eb 100644 --- a/pcsx2/IopCounters.h +++ b/pcsx2/IopCounters.h @@ -29,7 +29,7 @@ extern u16 psxRcntRcount16(int index); extern u32 psxRcntRcount32(int index); extern u64 psxRcntCycles(int index); +extern void psxHBlankStart(); +extern void psxHBlankEnd(); extern void psxVBlankStart(); extern void psxVBlankEnd(); -extern void psxCheckStartGate16(int i); -extern void psxCheckEndGate16(int i); diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 107f121674..407b3d33f9 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -370,11 +370,33 @@ __fi void _cpuEventTest_Shared() if (cpuIntsEnabled(mask)) cpuException(mask, cpuRegs.branch); + // ---- IOP ------------- + // * It's important to run a iopEventTest before calling ExecuteBlock. This + // is because the IOP does not always perform branch tests before returning + // (during the prev branch) and also so it can act on the state the EE has + // given it before executing any code. + // + // * The IOP cannot always be run. If we run IOP code every time through the + // cpuEventTest, the IOP generally starts to run way ahead of the EE. - // ---- Counters ------------- - // Important: the vsync counter must be the first to be checked. It includes emulation - // escape/suspend hooks, and it's really a good idea to suspend/resume emulation before - // doing any actual meaningful branchtest logic. + // It's also important to sync up the IOP before updating the timers, since gates will depend on starting/stopping in the right place! + EEsCycle += cpuRegs.cycle - EEoCycle; + EEoCycle = cpuRegs.cycle; + + if (EEsCycle > 0) + iopEventAction = true; + + if (iopEventAction) + { + //if( EEsCycle < -450 ) + // Console.WriteLn( " IOP ahead by: %d cycles", -EEsCycle ); + + EEsCycle = psxCpu->ExecuteBlock(EEsCycle); + + iopEventAction = false; + } + + iopEventTest(); if (cpuTestCycle(nextsCounter, nextCounter)) { @@ -403,33 +425,6 @@ __fi void _cpuEventTest_Shared() _cpuTestInterrupts(); } - // ---- IOP ------------- - // * It's important to run a iopEventTest before calling ExecuteBlock. This - // is because the IOP does not always perform branch tests before returning - // (during the prev branch) and also so it can act on the state the EE has - // given it before executing any code. - // - // * The IOP cannot always be run. If we run IOP code every time through the - // cpuEventTest, the IOP generally starts to run way ahead of the EE. - - EEsCycle += cpuRegs.cycle - EEoCycle; - EEoCycle = cpuRegs.cycle; - - if (EEsCycle > 0) - iopEventAction = true; - - if (iopEventAction) - { - //if( EEsCycle < -450 ) - // Console.WriteLn( " IOP ahead by: %d cycles", -EEsCycle ); - - EEsCycle = psxCpu->ExecuteBlock(EEsCycle); - - iopEventAction = false; - } - - iopEventTest(); - // ---- VU Sync ------------- // We're in a EventTest. All dynarec registers are flushed // so there is no need to freeze registers here. diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index 000d09dccb..1111b3cb46 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -25,7 +25,7 @@ enum class FreezeAction // [SAVEVERSION+] // This informs the auto updater that the users savestates will be invalidated. -static const u32 g_SaveVersion = (0x9A4B << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A4C << 16) | 0x0000; // the freezing data between submodules and core