From 361afda5ed18d5c03486864ad6d639485ab76e0d Mon Sep 17 00:00:00 2001 From: ramapcsx2 Date: Sun, 23 Nov 2008 01:10:54 +0000 Subject: [PATCH] Some updates by Jake and 2 lines from me, hope this fixes savestates. Please test guys :) git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@359 a6443dda-0b58-4228-96e9-037be469359c --- pcsx2/Counters.c | 125 ++++++++++++++++++++------------------------ pcsx2/Counters.h | 5 +- pcsx2/Misc.c | 2 + pcsx2/PsxCounters.c | 66 +++++++++++++---------- pcsx2/PsxCounters.h | 2 +- 5 files changed, 100 insertions(+), 100 deletions(-) diff --git a/pcsx2/Counters.c b/pcsx2/Counters.c index 0cebba4bf6..a184a33421 100644 --- a/pcsx2/Counters.c +++ b/pcsx2/Counters.c @@ -83,14 +83,6 @@ static __forceinline void cpuRcntSet() nextsCounter = cpuRegs.cycle; nextCounter = (counters[5].sCycle + counters[5].CycleT) - cpuRegs.cycle; - // if we're running behind, the diff will be negative. - // (and running behind means we need to branch again ASAP) - if( nextCounter <= 0 ) - { - nextCounter = 0; - return; - } - for (i = 0; i < 4; i++) _rcntSet( i ); @@ -487,7 +479,6 @@ static __forceinline void VSyncEnd(u32 sCycle) // VSync End hwIntcIrq(3); // HW Irq psxVBlankEnd(); // psxCounters vBlank End if (gates) rcntEndGate(0x8, sCycle); // Counters End Gate Code - SysUpdate(); // check for and handle keyevents frameLimit(); // limit FPS (also handles frameskip and VUskip) } @@ -542,6 +533,8 @@ __forceinline void rcntUpdate_vSync() counters[5].sCycle += vSyncInfo.Blank; counters[5].CycleT = vSyncInfo.Render; counters[5].mode = MODE_VRENDER; + + SysUpdate(); // check for and handle keyevents } else // VSYNC end / VRENDER begin { @@ -570,7 +563,7 @@ __forceinline void rcntUpdate_vSync() static __forceinline void __fastcall _cpuTestTarget( int i ) { - //counters[i].target &= 0xffff; + if (counters[i].count < counters[i].target) return; if(counters[i].mode & 0x100) { @@ -586,6 +579,21 @@ static __forceinline void __fastcall _cpuTestTarget( int i ) else counters[i].target |= 0x10000000; } +static __forceinline void _cpuTestOverflow( int i ) +{ + if (counters[i].count <= 0xffff) return; + + if (counters[i].mode & 0x0200) { // Overflow interrupt + EECNT_LOG("EE counter %d overflow mode %x count %x target %x\n", i, counters[i].mode, counters[i].count, counters[i].target); + counters[i].mode |= 0x0800; // Overflow flag + hwIntcIrq(counters[i].interrupt); + } + + // wrap counter back around zero, and enable the future target: + counters[i].count -= 0x10000; + counters[i].target &= 0xffff; +} + // forceinline note: this method is called from two locations, but one // of them is the interpreter, which doesn't count. ;) So might as @@ -596,14 +604,16 @@ __forceinline void rcntUpdate() rcntUpdate_vSync(); - // Update all counters? - // This code shouldn't be needed. Counters are updated as needed when - // Reads, Writes, and Target/Overflow events occur. The rest of the - // time the counters can be left unmodified. - + // Update counters so that we can perform overflow and target tests. + for (i=0; i<=3; i++) { - if ( gates & (1< 0 ) { @@ -621,26 +631,8 @@ __forceinline void rcntUpdate() { if (!(counters[i].mode & 0x80)) continue; // Stopped - // Target reached? - if (counters[i].count >= counters[i].target) - _cpuTestTarget( i ); - - if (counters[i].count > 0xffff) { - - if (counters[i].mode & 0x0200) { // Overflow interrupt - EECNT_LOG("EE counter %d overflow mode %x count %x target %x\n", i, counters[i].mode, counters[i].count, counters[i].target); - counters[i].mode |= 0x0800; // Overflow flag - hwIntcIrq(counters[i].interrupt); - } - counters[i].count -= 0x10000; - counters[i].target &= 0xffff; - - // Target reached after overflow? - // It's possible that a Target very near zero (1-10, etc) could have already been reached. - // Checking for it now - //if (counters[i].count >= counters[i].target) - // _cpuTestTarget( i ); - } + _cpuTestTarget( i ); + _cpuTestOverflow( i ); } cpuRcntSet(); } @@ -665,6 +657,21 @@ void rcntWcount(int index, u32 value) _rcntSet( index ); } +static void _rcntSetGate( int index ) +{ + if((counters[index].mode & 0xF) == 0x7) { + gates &= ~(1<= 0x7a30000e ) { gzread(f, s_iLastPERFCycle, sizeof(u32)*2); diff --git a/pcsx2/PsxCounters.c b/pcsx2/PsxCounters.c index 4e505c2350..5eec04fad4 100644 --- a/pcsx2/PsxCounters.c +++ b/pcsx2/PsxCounters.c @@ -27,8 +27,8 @@ u8 psxhblankgate = 0; u8 psxvblankgate = 0; u8 psxcntmask = 0; -// flags when the gate is on (counting) -#define IOPCNT_GATE_STOPPED (0x10000000ul) +// flags when the gate is off or counter disabled. (do not count) +#define IOPCNT_STOPPED (0x10000000ul) // used to disable targets until after an overflow #define IOPCNT_FUTURE_TARGET (0x1000000000ULL) @@ -41,7 +41,7 @@ u8 psxcntmask = 0; // Use an arbitrary value to flag HBLANK counters. // These counters will be counted by the hblank gates coming from the EE, // which ensures they stay 100% in sync with the EE's hblank counters. -#define PSXHBLANK 0x2000 +#define PSXHBLANK 0x2001 static void psxRcntReset(int index) { @@ -63,7 +63,7 @@ __forceinline static void _rcntSet( int i ) // that into account. Adding the difference from that cycle count to the current one // will do the trick! - if( psxCounters[i].mode & IOPCNT_GATE_STOPPED || psxCounters[i].rate == PSXHBLANK) return; + if( psxCounters[i].mode & IOPCNT_STOPPED || psxCounters[i].rate == PSXHBLANK) return; c = (u64)((overflowCap - psxCounters[i].count) * psxCounters[i].rate) - (psxRegs.cycle - psxCounters[i].sCycleT); c += psxRegs.cycle - psxNextsCounter; // adjust for time passed since last rcntUpdate(); @@ -226,7 +226,7 @@ static void _psxCheckStartGate( int i ) // get the current count at the time of stoppage: psxCounters[i].count = ( i < 3 ) ? psxRcntRcount16( i ) : psxRcntRcount32( i ); - psxCounters[i].mode |= IOPCNT_GATE_STOPPED; + psxCounters[i].mode |= IOPCNT_STOPPED; return; case 0x1: //GATE_ON_ClearStart - count normally with resets after every end gate @@ -236,7 +236,7 @@ static void _psxCheckStartGate( int i ) case 0x2: //GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end psxCounters[i].count = 0; psxCounters[i].sCycleT = psxRegs.cycle; - psxCounters[i].mode &= ~IOPCNT_GATE_STOPPED; + psxCounters[i].mode &= ~IOPCNT_STOPPED; break; case 0x3: //GATE_ON_Start - start and count normally on gate end (no restarts or stops or clears) @@ -256,21 +256,21 @@ static void _psxCheckEndGate(int i) case 0x1: //GATE_ON_ClearStart - count normally with resets after every end gate psxCounters[i].count = 0; psxCounters[i].sCycleT = psxRegs.cycle; - psxCounters[i].mode &= ~IOPCNT_GATE_STOPPED; + 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_GATE_STOPPED; + psxCounters[i].mode |= IOPCNT_STOPPED; return; // do not set the counter case 0x3: //GATE_ON_Start - start and count normally (no restarts or stops or clears) - if( psxCounters[i].mode & IOPCNT_GATE_STOPPED ) + if( psxCounters[i].mode & IOPCNT_STOPPED ) { psxCounters[i].count = 0; psxCounters[i].sCycleT = psxRegs.cycle; - psxCounters[i].mode &= ~IOPCNT_GATE_STOPPED; + psxCounters[i].mode &= ~IOPCNT_STOPPED; } break; } @@ -289,7 +289,7 @@ void psxCheckStartGate16(int i) // 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_GATE_STOPPED | altSourceCheck ); + const u32 stoppedGateCheck = (IOPCNT_STOPPED | altSourceCheck ); // count if alt source is enabled and either: // * the gate is enabled and not stopped. @@ -364,7 +364,7 @@ void psxRcntUpdate() // We can't check the ALTSOURCE flag because the PSXCLOCK source *should* // be counted here. - if( psxCounters[i].mode & (IOPCNT_GATE_STOPPED | IOPCNT_ENABLE_GATE) ) continue; + if( psxCounters[i].mode & (IOPCNT_STOPPED | IOPCNT_ENABLE_GATE) ) continue; if( psxCounters[i].rate == PSXHBLANK ) continue; if( change <= 0 ) continue; @@ -387,7 +387,7 @@ void psxRcntUpdate() // 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_GATE_STOPPED ) continue; + if( psxCounters[i].mode & IOPCNT_STOPPED ) continue; _rcntTestTarget( i ); _rcntTestOverflow( i ); @@ -542,7 +542,7 @@ void psxRcnt2Wmode(u32 value) if((psxCounters[2].mode & 0x7) == 0x7 || (psxCounters[2].mode & 0x7) == 0x1) { //SysPrintf("Gate set on IOP C2, disabling\n"); - psxCounters[2].mode |= IOPCNT_GATE_STOPPED; + psxCounters[2].mode |= IOPCNT_STOPPED; } psxCounters[2].count = 0; @@ -593,7 +593,7 @@ void psxRcnt4Wmode(u32 value) if((psxCounters[4].mode & 0x7) == 0x7 || (psxCounters[4].mode & 0x7) == 0x1) { SysPrintf("Gate set on IOP C4, disabling\n"); - psxCounters[4].mode |= IOPCNT_GATE_STOPPED; + psxCounters[4].mode |= IOPCNT_STOPPED; } psxCounters[4].count = 0; @@ -620,7 +620,7 @@ void psxRcnt5Wmode(u32 value) if((psxCounters[5].mode & 0x7) == 0x7 || (psxCounters[5].mode & 0x7) == 0x1) { SysPrintf("Gate set on IOP C5, disabling\n"); - psxCounters[5].mode |= IOPCNT_GATE_STOPPED; + psxCounters[5].mode |= IOPCNT_STOPPED; } psxCounters[5].count = 0; @@ -673,7 +673,7 @@ u16 psxRcntRcount16(int index) // Don't count HBLANK timers // Don't count stopped gates either. - if( !( psxCounters[index].mode & IOPCNT_GATE_STOPPED ) && + if( !( psxCounters[index].mode & IOPCNT_STOPPED ) && ( psxCounters[index].rate != PSXHBLANK ) ) { u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); @@ -693,7 +693,7 @@ u32 psxRcntRcount32(int index) PSXCNT_LOG("IOP Counter[%d] > readCount32 = %lx", index, retval ); - if( !( psxCounters[index].mode & IOPCNT_GATE_STOPPED ) && + if( !( psxCounters[index].mode & IOPCNT_STOPPED ) && ( psxCounters[index].rate != PSXHBLANK ) ) { u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); @@ -707,7 +707,7 @@ u32 psxRcntRcount32(int index) u64 psxRcntCycles(int index) { - if(psxCounters[index].mode & IOPCNT_GATE_STOPPED || psxCounters[index].rate == PSXHBLANK ) return psxCounters[index].count; + if(psxCounters[index].mode & IOPCNT_STOPPED || psxCounters[index].rate == PSXHBLANK ) return psxCounters[index].count; return (u64)(psxCounters[index].count + (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); } @@ -716,7 +716,7 @@ int psxRcntFreeze(gzFile f, int Mode) { if( Mode == 0 && (dwCurSaveStateVer < 0x7a300010) ) { - // --- Reading Mode --- + // --- Reading Mode, Old Version --- // struct used to be 32bit count and target int i; u32 val; @@ -731,16 +731,26 @@ int psxRcntFreeze(gzFile f, int Mode) else { gzfreezel(psxCounters); + } - if( Mode == 0 ) - { - // This is needed to make old save states compatible. - psxCounters[6].rate = ((Config.Hacks & 0x4) ? 768 : (768*8)); - psxCounters[6].CycleT = psxCounters[6].rate; - psxCounters[7].rate = PSXCLK/1000; - psxCounters[7].CycleT = psxCounters[7].rate; + if( Mode == 0 ) + { + // This is needed to make old save states compatible. + + psxCounters[6].rate = ((Config.Hacks & 0x4) ? 768 : (768*8)); + psxCounters[6].CycleT = psxCounters[6].rate; + psxCounters[7].rate = PSXCLK/1000; + psxCounters[7].CycleT = psxCounters[7].rate; + + // PSXHBLANK is now an arbitrary value, since it can differ based + // on PAL/NTSC and is timed by the EE. + + if(psxCounters[1].mode & IOPCNT_ALT_SOURCE) + psxCounters[1].rate = PSXHBLANK; + + if(psxCounters[3].mode & IOPCNT_ALT_SOURCE) + psxCounters[3].rate = PSXHBLANK; - } } return 0; diff --git a/pcsx2/PsxCounters.h b/pcsx2/PsxCounters.h index 41b831e6c6..f7198421a7 100644 --- a/pcsx2/PsxCounters.h +++ b/pcsx2/PsxCounters.h @@ -19,7 +19,7 @@ #ifndef __PSXCOUNTERS_H__ #define __PSXCOUNTERS_H__ -// fixme: sCycle and Cycle are unused. +// fixme: sCycle, Cycle, and otarget are unused // Can't remove them without making a new savestate version though. typedef struct {