X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fpsxcounters.c;h=35823dacdafc3cd34ab92c66c84d00285b538957;hb=HEAD;hp=3342770e98afba47d8d8677347679123a88c1eea;hpb=e78515041f52dad93f52e09195231d13b609487d;p=pcsx_rearmed.git diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c index 3342770e..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() @@ -30,11 +31,12 @@ enum { - Rc0Gate = 0x0001, // 0 not implemented - Rc1Gate = 0x0001, // 0 not implemented - Rc2Disable = 0x0001, // 0 partially implemented - RcUnknown1 = 0x0002, // 1 ? - RcUnknown2 = 0x0004, // 2 ? + RcSyncModeEnable = 0x0001, // 0 + Rc01BlankPause = 0 << 1, // 1,2 + Rc01UnblankReset = 1 << 1, // 1,2 + Rc01UnblankReset2 = 2 << 1, // 1,2 + Rc2Stop = 0 << 1, // 1,2 + Rc2Stop2 = 3 << 1, // 1,2 RcCountToTarget = 0x0008, // 3 RcIrqOnTarget = 0x0010, // 4 RcIrqOnOverflow = 0x0020, // 5 @@ -60,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 @@ -73,12 +74,51 @@ Rcnt rcnts[ CounterQuantity ]; u32 hSyncCount = 0; u32 frame_counter = 0; static u32 hsync_steps = 0; -static u32 base_cycle = 0; 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 { @@ -188,7 +224,8 @@ void _psxRcntWmode( u32 index, u32 value ) } // TODO: wcount must work. - if( value & Rc2Disable ) + if( (value & 7) == (RcSyncModeEnable | Rc2Stop) || + (value & 7) == (RcSyncModeEnable | Rc2Stop2) ) { rcnts[index].rate = 0xffffffff; } @@ -223,8 +260,7 @@ void psxRcntSet() } } - psxRegs.interrupt |= (1 << PSXINT_RCNT); - new_dyna_set_event(PSXINT_RCNT, psxNextCounter); + set_event(PSXINT_RCNT, psxNextCounter); } /******************************************************************************/ @@ -293,16 +329,49 @@ void psxRcntReset( u32 index ) } } +static void scheduleRcntBase(void) +{ + // Schedule next call, in hsyncs + if (hSyncCount < VBlankStart) + hsync_steps = VBlankStart - hSyncCount; + else + hsync_steps = HSyncTotal[Config.PsxType] - hSyncCount; + + if (hSyncCount + hsync_steps == HSyncTotal[Config.PsxType]) + { + rcnts[3].cycle = frameCycles(); + } + else + { + // clk / 50 / 314 ~= 2157.25 + // clk / 60 / 263 ~= 2146.31 + u32 mult = Config.PsxType ? 8836089 : 8791293; + rcnts[3].cycle = hsync_steps * mult >> 12; + } +} + void psxRcntUpdate() { - u32 cycle; + u32 cycle, cycles_passed; cycle = psxRegs.cycle; // rcnt 0. - while( cycle - rcnts[0].cycleStart >= rcnts[0].cycle ) + cycles_passed = cycle - rcnts[0].cycleStart; + while( cycles_passed >= rcnts[0].cycle ) { - psxRcntReset( 0 ); + if (((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || + (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) + && cycles_passed > lineCycles()) + { + u32 q = cycles_passed / (lineCycles() + 1u); + rcnts[0].cycleStart += q * lineCycles(); + break; + } + else + psxRcntReset( 0 ); + + cycles_passed = cycle - rcnts[0].cycleStart; } // rcnt 1. @@ -320,15 +389,12 @@ void psxRcntUpdate() // rcnt base. if( cycle - rcnts[3].cycleStart >= rcnts[3].cycle ) { - u32 leftover_cycles = cycle - rcnts[3].cycleStart - rcnts[3].cycle; - u32 next_vsync; - hSyncCount += hsync_steps; // VSync irq. if( hSyncCount == VBlankStart ) { - HW_GPU_STATUS &= ~PSXGPU_LCF; + HW_GPU_STATUS &= SWAP32(~PSXGPU_LCF); GPU_vBlank( 1, 0 ); setIrq( 0x01 ); @@ -341,38 +407,50 @@ void psxRcntUpdate() } } - // Update lace. (with InuYasha fix) - if( hSyncCount >= (Config.VSyncWA ? HSyncTotal[Config.PsxType] / BIAS : HSyncTotal[Config.PsxType]) ) + // Update lace. + if( hSyncCount >= HSyncTotal[Config.PsxType] ) { + u32 status, field = 0; + rcnts[3].cycleStart += frameCycles(); hSyncCount = 0; frame_counter++; gpuSyncPluginSR(); - if( (HW_GPU_STATUS & PSXGPU_ILACE_BITS) == PSXGPU_ILACE_BITS ) - HW_GPU_STATUS |= frame_counter << 31; - GPU_vBlank( 0, HW_GPU_STATUS >> 31 ); - } + status = SWAP32(HW_GPU_STATUS) | PSXGPU_FIELD; + if ((status & PSXGPU_ILACE_BITS) == PSXGPU_ILACE_BITS) { + field = frame_counter & 1; + status |= field << 31; + status ^= field << 13; + } + HW_GPU_STATUS = SWAP32(status); + GPU_vBlank(0, field); + if ((s32)(psxRegs.gpuIdleAfter - psxRegs.cycle) < 0) + psxRegs.gpuIdleAfter = psxRegs.cycle - 1; // prevent overflow - // Schedule next call, in hsyncs - hsync_steps = HSyncTotal[Config.PsxType] - hSyncCount; - next_vsync = VBlankStart - hSyncCount; // ok to overflow - if( next_vsync && next_vsync < hsync_steps ) - hsync_steps = next_vsync; + if ((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || + (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) + { + rcnts[0].cycleStart = rcnts[3].cycleStart; + } - rcnts[3].cycleStart = cycle - leftover_cycles; - if (Config.PsxType) - // 20.12 precision, clk / 50 / 313 ~= 2164.14 - base_cycle += hsync_steps * 8864320; - else - // clk / 60 / 263 ~= 2146.31 - base_cycle += hsync_steps * 8791293; - rcnts[3].cycle = base_cycle >> 12; - base_cycle &= 0xfff; + 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) + { + // adjust to remove the rounding error + _psxRcntWcount(1, (psxRegs.cycle - rcnts[1].cycleStart) / rcnts[1].rate); + } + } + + scheduleRcntBase(); } psxRcntSet(); -#ifndef NDEBUG +#if 0 //ndef NDEBUG DebugVSync(); #endif } @@ -410,25 +488,47 @@ void psxRcntWtarget( u32 index, u32 value ) /******************************************************************************/ -u32 psxRcntRcount( u32 index ) +u32 psxRcntRcount0() { + u32 index = 0; u32 count; - count = _psxRcntRcount( index ); - - // Parasite Eve 2 fix. - if( Config.RCntFix ) + if ((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || + (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) { - if( index == 2 ) - { - if( rcnts[index].counterState == CountToTarget ) - { - count /= BIAS; - } - } + count = psxRegs.cycle - rcnts[index].cycleStart; + //count = ((16u * count) % (16u * PSXCLK / 60 / 263)) / 16u; + count = count % lineCycles(); + rcnts[index].cycleStart = psxRegs.cycle - count; } + else + count = _psxRcntRcount( index ); - verboseLog( 2, "[RCNT %i] rcount: %x\n", index, count ); + verboseLog( 2, "[RCNT 0] rcount: %04x m: %04x\n", count, rcnts[index].mode); + + return count; +} + +u32 psxRcntRcount1() +{ + u32 index = 1; + u32 count; + + count = _psxRcntRcount( index ); + + verboseLog( 2, "[RCNT 1] rcount: %04x m: %04x\n", count, rcnts[index].mode); + + return count; +} + +u32 psxRcntRcount2() +{ + u32 index = 2; + u32 count; + + count = _psxRcntRcount( index ); + + verboseLog( 2, "[RCNT 2] rcount: %04x m: %04x\n", count, rcnts[index].mode); return count; } @@ -472,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 ) { @@ -483,6 +581,7 @@ void psxRcntInit() hSyncCount = 0; hsync_steps = 1; + scheduleRcntBase(); psxRcntSet(); } @@ -502,23 +601,20 @@ 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 ); } - hsync_steps = 0; - if (rcnts[3].target) - hsync_steps = (psxRegs.cycle - rcnts[3].cycleStart) / rcnts[3].target; + scheduleRcntBase(); psxRcntSet(); - - base_cycle = 0; } return 0; } /******************************************************************************/ +// vim:ts=4:shiftwidth=4:expandtab