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
This commit is contained in:
ramapcsx2 2008-11-23 01:10:54 +00:00 committed by Gregory Hainaut
parent 266875132d
commit 361afda5ed
5 changed files with 100 additions and 100 deletions

View File

@ -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<<i) ) continue;
if ((counters[i].mode & 0x80) && (counters[i].mode & 0x3) != 0x3) {
// We want to count gated counters (except the hblank which excluded below)
//if ( gates & (1<<i) ) continue;
if (!(counters[i].mode & 0x80)) continue;
if((counters[i].mode & 0x3) != 0x3) { // don't count hblank sources
s32 change = cpuRegs.cycle - counters[i].sCycleT;
if( change > 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<<index);
SysPrintf("Counters: Gate Disabled\n");
//counters[index].mode &= ~0x80;
}
else if (counters[index].mode & 0x4) {
gates |= (1<<index);
counters[index].mode &= ~0x80;
rcntReset(index);
}
else gates &= ~(1<<index);
}
void rcntWmode(int index, u32 value)
{
if(counters[index].mode & 0x80) {
@ -692,21 +699,11 @@ void rcntWmode(int index, u32 value)
case 3: counters[index].rate = vSyncInfo.hBlank+vSyncInfo.hRender; break;
}
if((counters[index].mode & 0xF) == 0x7) {
gates &= ~(1<<index);
SysPrintf("Counters: Gate Disabled\n");
//counters[index].mode &= ~0x80;
}
else if (counters[index].mode & 0x4) {
gates |= (1<<index);
counters[index].mode &= ~0x80;
rcntReset(index);
}
else gates &= ~(1<<index);
_rcntSetGate( index );
_rcntSet( index );
}
// mode - 0 means hblank source, 8 means vblank source.
void rcntStartGate(unsigned int mode, u32 sCycle) {
int i;
@ -749,6 +746,7 @@ void rcntStartGate(unsigned int mode, u32 sCycle) {
// rcntUpdate, since we're being called from there anyway.
}
// mode - 0 means hblank signal, 8 means vblank signal.
void rcntEndGate(unsigned int mode, u32 sCycle) {
int i;
@ -764,7 +762,7 @@ void rcntEndGate(unsigned int mode, u32 sCycle) {
counters[i].count = rcntRcount(i);
counters[i].mode &= ~0x80;
counters[i].sCycleT = sCycle;
break;
case 0x10: // Reset and start counting on Vsync start
// this is the vsync end so do nothing
@ -825,22 +823,14 @@ u32 rcntCycle(int index) {
int rcntFreeze(gzFile f, int Mode) {
if( Mode == 1 )
{
// Temp Hack Fix: Adjust some values so that they'll load properly
// in the future (this should be removed when a new savestate version
// is introduced).
counters[4].sCycle += vSyncInfo.hRender;
counters[5].sCycle += vSyncInfo.Render;
}
gzfreezel(counters);
gzfreeze(&nextCounter, sizeof(nextCounter));
gzfreeze(&nextsCounter, sizeof(nextsCounter));
if( Mode == 0 )
{
int i;
// Sanity check for loading older savestates:
if( counters[4].sCycle == 0 )
@ -848,17 +838,14 @@ int rcntFreeze(gzFile f, int Mode) {
if( counters[5].sCycle == 0 )
counters[5].sCycle = cpuRegs.cycle;
// make sure the gate flags are set based on the counter modes...
for( i=0; i<4; i++ )
_rcntSetGate( i );
}
// Old versions of PCSX2 saved the counters *after* incrementing them.
// So if we don't roll back here, the counters move past cpuRegs.cycle
// and everthing explodes!
// Note: Roll back regardless of load or save, since we roll them forward
// when saving (above). It's a hack, but it works.
counters[4].sCycle -= vSyncInfo.hRender;
counters[5].sCycle -= vSyncInfo.Render;
iopBranchAction = 1; // probably not needed but won't hurt anything either.
return 0;
}

View File

@ -24,9 +24,10 @@
typedef struct {
u32 count, mode, target, hold;
u32 rate, interrupt;
u32 Cycle, sCycle;
u32 Cycle;
u32 sCycle; // start cycle of timer
s32 CycleT;
u32 sCycleT;
u32 sCycleT; // delta values should be signed.
} Counter;
//------------------------------------------------------------------

View File

@ -485,6 +485,7 @@ int SaveState(const char *file) {
gzwrite(f, &psxRegs.cycle, sizeof(u32)); // used to be IOPoCycle. This retains compatibility.
gzwrite(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle));
gzwrite(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle));
gzwrite(f, &psxNextsCounter, sizeof(psxNextsCounter));
gzwrite(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle));
gzwrite(f, s_iLastPERFCycle, sizeof(u32)*2);
gzwrite(f, &g_psxWriteOk, sizeof(g_psxWriteOk));
@ -616,6 +617,7 @@ int LoadState(const char *file) {
gzread(f, &dud, sizeof(u32)); // was IOPoCycle
gzread(f, &g_nextBranchCycle, sizeof(g_nextBranchCycle));
gzread(f, &g_psxNextBranchCycle, sizeof(g_psxNextBranchCycle));
gzread(f, &psxNextsCounter, sizeof(psxNextsCounter));
gzread(f, &s_iLastCOP0Cycle, sizeof(s_iLastCOP0Cycle));
if( dwCurSaveStateVer >= 0x7a30000e ) {
gzread(f, s_iLastPERFCycle, sizeof(u32)*2);

View File

@ -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;

View File

@ -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 {