X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxcounters.c;h=35823dacdafc3cd34ab92c66c84d00285b538957;hb=HEAD;hp=388fb89da1960d6e1714e489e25ce6fd3a1335fe;hpb=11d23573173ec4b5074eb35665c6012a46034d5c;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c index 388fb89d..887fe8a4 100644 --- a/libpcsxcore/psxcounters.c +++ b/libpcsxcore/psxcounters.c @@ -22,6 +22,7 @@ */ #include "psxcounters.h" +#include "psxevents.h" #include "gpu.h" //#include "debug.h" #define DebugVSync() @@ -61,9 +62,8 @@ enum static const u32 CountToOverflow = 0; static const u32 CountToTarget = 1; -static const u32 FrameRate[] = { 60, 50 }; -static const u32 HSyncTotal[] = { 263, 314 }; // actually one more on odd lines for PAL -#define VBlankStart 240 +static const u32 HSyncTotal[] = { 263, 314 }; +#define VBlankStart 240 // todo: depend on the actual GPU setting #define VERBOSE_LEVEL 0 @@ -79,6 +79,46 @@ u32 psxNextCounter = 0, psxNextsCounter = 0; /******************************************************************************/ +#define FPS_FRACTIONAL_PAL (53203425/314./3406) // ~49.75 +#define FPS_FRACTIONAL_NTSC (53693175/263./3413) // ~59.81 + +static inline +u32 frameCycles(void) +{ + int ff = Config.FractionalFramerate >= 0 + ? Config.FractionalFramerate : Config.hacks.fractional_Framerate; + if (ff) + { + if (Config.PsxType) + return (u32)(PSXCLK / FPS_FRACTIONAL_PAL); + else + return (u32)(PSXCLK / FPS_FRACTIONAL_NTSC); + } + return Config.PsxType ? (PSXCLK / 50) : (PSXCLK / 60); +} + +// used to inform the frontend about the exact framerate +double psxGetFps() +{ + int ff = Config.FractionalFramerate >= 0 + ? Config.FractionalFramerate : Config.hacks.fractional_Framerate; + if (ff) + return Config.PsxType ? FPS_FRACTIONAL_PAL : FPS_FRACTIONAL_NTSC; + else + return Config.PsxType ? 50.0 : 60.0; +} + +// to inform the frontend about the exact famerate +static inline +u32 lineCycles(void) +{ + // should be more like above, but our timing is already poor anyway + if (Config.PsxType) + return PSXCLK / 50 / HSyncTotal[1]; + else + return PSXCLK / 60 / HSyncTotal[0]; +} + static inline void setIrq( u32 irq ) { @@ -109,11 +149,7 @@ void verboseLog( u32 level, const char *str, ... ) static inline void _psxRcntWcount( u32 index, u32 value ) { - if( value > 0xffff ) - { - verboseLog( 1, "[RCNT %i] wcount > 0xffff: %x\n", index, value ); - value &= 0xffff; - } + value &= 0xffff; rcnts[index].cycleStart = psxRegs.cycle; rcnts[index].cycleStart -= value * rcnts[index].rate; @@ -170,7 +206,7 @@ void _psxRcntWmode( u32 index, u32 value ) case 1: if( value & Rc1HSyncClock ) { - rcnts[index].rate = (PSXCLK / (FrameRate[Config.PsxType] * HSyncTotal[Config.PsxType])); + rcnts[index].rate = lineCycles(); } else { @@ -224,8 +260,7 @@ void psxRcntSet() } } - psxRegs.interrupt |= (1 << PSXINT_RCNT); - new_dyna_set_event(PSXINT_RCNT, psxNextCounter); + set_event(PSXINT_RCNT, psxNextCounter); } /******************************************************************************/ @@ -304,7 +339,7 @@ static void scheduleRcntBase(void) if (hSyncCount + hsync_steps == HSyncTotal[Config.PsxType]) { - rcnts[3].cycle = Config.PsxType ? PSXCLK / 50 : PSXCLK / 60; + rcnts[3].cycle = frameCycles(); } else { @@ -327,10 +362,10 @@ void psxRcntUpdate() { if (((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) - && cycles_passed > PSXCLK / 60 / 263) + && cycles_passed > lineCycles()) { - u32 q = cycles_passed / (PSXCLK / 60 / 263 + 1u); - rcnts[0].cycleStart += q * (PSXCLK / 60) / 263u; + u32 q = cycles_passed / (lineCycles() + 1u); + rcnts[0].cycleStart += q * lineCycles(); break; } else @@ -375,8 +410,8 @@ void psxRcntUpdate() // Update lace. if( hSyncCount >= HSyncTotal[Config.PsxType] ) { - u32 status, field = 0, i; - rcnts[3].cycleStart += Config.PsxType ? PSXCLK / 50 : PSXCLK / 60; + u32 status, field = 0; + rcnts[3].cycleStart += frameCycles(); hSyncCount = 0; frame_counter++; @@ -389,14 +424,24 @@ void psxRcntUpdate() } HW_GPU_STATUS = SWAP32(status); GPU_vBlank(0, field); + if ((s32)(psxRegs.gpuIdleAfter - psxRegs.cycle) < 0) + psxRegs.gpuIdleAfter = psxRegs.cycle - 1; // prevent overflow + + if ((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || + (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) + { + rcnts[0].cycleStart = rcnts[3].cycleStart; + } - for (i = 0; i < 2; i++) + if ((rcnts[1].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || + (rcnts[1].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) + { + rcnts[1].cycleStart = rcnts[3].cycleStart; + } + else if (rcnts[1].mode & Rc1HSyncClock) { - if ((rcnts[i].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || - (rcnts[i].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) - { - rcnts[i].cycleStart = rcnts[3].cycleStart; - } + // adjust to remove the rounding error + _psxRcntWcount(1, (psxRegs.cycle - rcnts[1].cycleStart) / rcnts[1].rate); } } @@ -452,7 +497,8 @@ u32 psxRcntRcount0() (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) { count = psxRegs.cycle - rcnts[index].cycleStart; - count = ((16u * count) % (16u * PSXCLK / 60 / 263)) / 16u; + //count = ((16u * count) % (16u * PSXCLK / 60 / 263)) / 16u; + count = count % lineCycles(); rcnts[index].cycleStart = psxRegs.cycle - count; } else @@ -526,8 +572,6 @@ void psxRcntInit() // rcnt base. rcnts[3].rate = 1; - rcnts[3].mode = RcCountToTarget; - rcnts[3].target = (PSXCLK / (FrameRate[Config.PsxType] * HSyncTotal[Config.PsxType])); for( i = 0; i < CounterQuantity; ++i ) { @@ -537,6 +581,7 @@ void psxRcntInit() hSyncCount = 0; hsync_steps = 1; + scheduleRcntBase(); psxRcntSet(); } @@ -556,13 +601,13 @@ s32 psxRcntFreeze( void *f, s32 Mode ) if (Mode == 0) { - // don't trust things from a savestate rcnts[3].rate = 1; - for( i = 0; i < CounterQuantity; ++i ) + for( i = 0; i < CounterQuantity - 1; ++i ) { _psxRcntWmode( i, rcnts[i].mode ); count = (psxRegs.cycle - rcnts[i].cycleStart) / rcnts[i].rate; - _psxRcntWcount( i, count ); + if (count > 0x1000) + _psxRcntWcount( i, count & 0xffff ); } scheduleRcntBase(); psxRcntSet();