From 3696028dbe32518725e78db6804f3a2a90a23eb1 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Thu, 4 Dec 2008 19:48:10 +0000 Subject: [PATCH] Fixed frameskipping when using a strict framerate setting (minfps==maxfps). The setting is ideal for users playing high-fps games as it allows you to disable the timestretching on your SPU2 plugin. :) git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@390 a6443dda-0b58-4228-96e9-037be469359c --- pcsx2/Counters.c | 8 ++++++-- pcsx2/GS.cpp | 21 +++++++++++++++------ pcsx2/GS.h | 3 ++- pcsx2/Misc.c | 15 ++++++++++----- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/pcsx2/Counters.c b/pcsx2/Counters.c index b096feb05e..4fb478bafa 100644 --- a/pcsx2/Counters.c +++ b/pcsx2/Counters.c @@ -115,7 +115,6 @@ void rcntInit() { // debug code, used for stats int g_nCounters[4]; static int iFrame = 0; -//long iFrameLimitEnable = 1; #ifndef _WIN32 #include @@ -327,6 +326,11 @@ void vSyncDebugStuff() { #endif } +void frameLimitReset() +{ + m_iStart = GetCPUTicks(); +} + // Framelimiter - Measures the delta time between calls and stalls until a // certain amount of time passes if such time hasn't passed yet. // See the GS FrameSkip function for details on why this is here and not in the GS. @@ -356,7 +360,7 @@ static __forceinline void frameLimit() // Keeps the GS skipper from trying to catch up to a framerate // that the limiter already gave up on. - gsSyncLimiterStartTime( m_iStart ); + gsSyncLimiterLostTime( (s32)(m_iStart - uExpectedEnd) ); return; } diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index e13e399675..0c5384c738 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -1660,7 +1660,7 @@ void gifMFIFOInterrupt() cpuRegs.interrupt &= ~(1 << 11); } -extern "C" void gsSyncLimiterStartTime( u64 startTime ) +extern "C" void gsSyncLimiterLostTime( s32 deltaTime ) { // This sync issue applies only to configs that are trying to maintain // a perfect "specific" framerate (where both min and max fps are the same) @@ -1672,17 +1672,17 @@ extern "C" void gsSyncLimiterStartTime( u64 startTime ) if( CHECK_MULTIGS ) { - const u32* stp = (u32*)&startTime; + //const u32* stp = (u32*)&startTime; GSRingBufSimplePacket( GS_RINGTYPE_STARTTIME, - stp[0], - stp[1], + deltaTime, + 0, 0 ); } else { - m_iSlowStart = startTime; + m_iSlowStart += deltaTime; //m_justSkipped = false; } } @@ -1847,6 +1847,15 @@ extern "C" void gsResetFrameSkip() _resetFrameskip(); } +extern "C" void frameLimitReset(); +extern "C" void gsDynamicSkipEnable() +{ + if( !m_StrictSkipping ) return; + + gsWaitGS(); + m_iSlowStart = GetCPUTicks(); + frameLimitReset(); +} GS_THREADPROC { @@ -2030,7 +2039,7 @@ GS_THREADPROC break; case GS_RINGTYPE_STARTTIME: - m_iSlowStart = *(u64*)(g_pGSRingPos+4); + m_iSlowStart += *(u32*)(g_pGSRingPos+4); //m_justSkipped = false; break; diff --git a/pcsx2/GS.h b/pcsx2/GS.h index 8a7ff01867..e857550898 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -81,7 +81,8 @@ void gsShutdown(); void gsReset(); void gsSetVideoRegionType( u32 isPal ); void gsResetFrameSkip(); -void gsSyncLimiterStartTime( u64 startTime ); +void gsSyncLimiterLostTime( s32 deltaTime ); +void gsDynamicSkipEnable(); // mem and size are the ones from GSRingBufCopy extern void GSRINGBUF_DONECOPY(const u8 *mem, u32 size); diff --git a/pcsx2/Misc.c b/pcsx2/Misc.c index 2e04a213c5..a59380aa1f 100644 --- a/pcsx2/Misc.c +++ b/pcsx2/Misc.c @@ -881,22 +881,23 @@ void ProcessFKeys(int fkey, int shift) case 4: { const char* limitMsg; + u32 newOptions; #ifdef PCSX2_NORECBUILD SysPrintf("frame skipping only valid for recompiler build\n"); #else // cycle if( shift ) { // previous - Config.Options = (Config.Options&~PCSX2_FRAMELIMIT_MASK)|(((Config.Options&PCSX2_FRAMELIMIT_MASK)+PCSX2_FRAMELIMIT_VUSKIP)&PCSX2_FRAMELIMIT_MASK); + newOptions = (Config.Options&~PCSX2_FRAMELIMIT_MASK)|(((Config.Options&PCSX2_FRAMELIMIT_MASK)+PCSX2_FRAMELIMIT_VUSKIP)&PCSX2_FRAMELIMIT_MASK); } else { // next - Config.Options = (Config.Options&~PCSX2_FRAMELIMIT_MASK)|(((Config.Options&PCSX2_FRAMELIMIT_MASK)+PCSX2_FRAMELIMIT_LIMIT)&PCSX2_FRAMELIMIT_MASK); + newOptions = (Config.Options&~PCSX2_FRAMELIMIT_MASK)|(((Config.Options&PCSX2_FRAMELIMIT_MASK)+PCSX2_FRAMELIMIT_LIMIT)&PCSX2_FRAMELIMIT_MASK); } gsResetFrameSkip(); - switch(CHECK_FRAMELIMIT) { + switch(newOptions & PCSX2_FRAMELIMIT_MASK) { case PCSX2_FRAMELIMIT_NORMAL: limitMsg = "None/Normal"; break; @@ -907,17 +908,21 @@ void ProcessFKeys(int fkey, int shift) case PCSX2_FRAMELIMIT_VUSKIP: if( GSsetFrameSkip == NULL ) { - Config.Options &= ~PCSX2_FRAMELIMIT_MASK; + newOptions &= ~PCSX2_FRAMELIMIT_MASK; SysPrintf("Notice: GS Plugin does not support frameskipping.\n"); limitMsg = "None/Normal"; } else { - limitMsg = (CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_SKIP) ? "Skip" : "VUSkip"; + // When enabling Skipping we have to make sure Skipper (GS) and Limiter (EE) + // are properly synchronized. + gsDynamicSkipEnable(); + limitMsg = ((newOptions & PCSX2_FRAMELIMIT_MASK) == PCSX2_FRAMELIMIT_SKIP) ? "Skip" : "VUSkip"; } break; } + InterlockedExchange( &Config.Options, newOptions ); SysPrintf("Frame Limit Mode Changed: %s\n", limitMsg );