static inline void _psxRcntWcount( u32 index, u32 value ) { if( value > 0xffff ) { verboseLog( 1, "[RCNT %i] wcount > 0xffff: %x\n", index, value ); value &= 0xffff; } rcnts[index].cycleStart = psxRegs.cycle; rcnts[index].cycleStart -= value * rcnts[index].rate; // TODO: <=. if( value < rcnts[index].target ) { rcnts[index].cycle = rcnts[index].target * rcnts[index].rate; rcnts[index].counterState = CountToTarget; } else { rcnts[index].cycle = 0xffff * rcnts[index].rate; rcnts[index].counterState = CountToOverflow; } verboseLog( 5, "[RCNT %i] scount: %x\n", index, value ); }
static void psxRcntReset( u32 index ) { u32 count; if( rcnts[index].counterState == CountToTarget ) { if( rcnts[index].mode & RcCountToTarget ) { count = psxRegs.cycle; count -= rcnts[index].cycleStart; count /= rcnts[index].rate; count -= rcnts[index].target; } else { count = _psxRcntRcount( index ); } _psxRcntWcount( index, count ); if( rcnts[index].mode & RcIrqOnTarget ) { if( (rcnts[index].mode & RcIrqRegenerate) || (!rcnts[index].irqState) ) { verboseLog( 3, "[RCNT %i] irq: %x\n", index, count ); setIrq( rcnts[index].irq ); rcnts[index].irqState = 1; } } rcnts[index].mode |= RcCountEqTarget; } else if( rcnts[index].counterState == CountToOverflow ) { count = psxRegs.cycle; count -= rcnts[index].cycleStart; count /= rcnts[index].rate; count -= 0xffff; _psxRcntWcount( index, count ); if( rcnts[index].mode & RcIrqOnOverflow ) { if( (rcnts[index].mode & RcIrqRegenerate) || (!rcnts[index].irqState) ) { verboseLog( 3, "[RCNT %i] irq: %x\n", index, count ); setIrq( rcnts[index].irq ); rcnts[index].irqState = 1; } } rcnts[index].mode |= RcOverflow; } rcnts[index].mode |= RcUnknown10; psxRcntSet(); }
void psxRcntWcount( u32 index, u32 value ) { verboseLog( 2, "[RCNT %i] wcount: %x\n", index, value ); psxRcntUpdate(); _psxRcntWcount( index, value ); psxRcntSet(); }
void psxRcntWtarget( u32 index, u32 value ) { verboseLog( 1, "[RCNT %i] wtarget: %x\n", index, value ); psxRcntUpdate(); rcnts[index].target = value; _psxRcntWcount( index, _psxRcntRcount( index ) ); psxRcntSet(); }
void psxRcntWmode( u32 index, u32 value ) { verboseLog( 1, "[RCNT %i] wmode: %x\n", index, value ); psxRcntUpdate(); rcnts[index].mode = value; rcnts[index].irqState = 0; switch( index ) { case 0: if( value & Rc0PixelClock ) { rcnts[index].rate = 5; } else { rcnts[index].rate = 1; } break; case 1: if( value & Rc1HSyncClock ) { rcnts[index].rate = (PSXCLK / (FrameRate[Config.PsxType] * HSyncTotal[Config.PsxType])); } else { rcnts[index].rate = 1; } break; case 2: if( value & Rc2OneEighthClock ) { rcnts[index].rate = 8; } else { rcnts[index].rate = 1; } // TODO: wcount must work. if( value & Rc2Disable ) { rcnts[index].rate = 0xffffffff; } break; } _psxRcntWcount( index, 0 ); psxRcntSet(); }
u32 psxRcntRmode( u32 index ) { u16 mode; psxRcntUpdate(); mode = rcnts[index].mode; rcnts[index].mode &= 0xe7ff; verboseLog( 2, "[RCNT %i] rmode: %x\n", index, mode ); return mode; }
u32 psxRcntRcount( u32 index ) { u32 count; psxRcntUpdate(); count = _psxRcntRcount( index ); // Parasite Eve 2 fix - artificial clock jitter based on BIAS // TODO: any other games depend on getting excepted value from RCNT? if( Config.HackFix && index == 2 && rcnts[index].counterState == CountToTarget && (Config.RCntFix || ((rcnts[index].mode & 0x2FF) == JITTER_FLAGS)) ) { /* *The problem is that... * *We generate too many cycles during PSX HW hardware operations. * *OR * *We simply count too many cycles here for RCNTs. * *OR * *RCNT implementation here is only 99% compatible. Assumed this since easities to fix (only PE2 known to be affected). */ static u32 clast = 0xffff; static u32 cylast = 0; u32 count1 = count; count /= BIAS; verboseLog( 4, "[RCNT %i] rcountpe2: %x %x %x (%u)\n", index, count, count1, clast, (psxRegs.cycle-cylast)); cylast=psxRegs.cycle; clast=count; } verboseLog( 2, "[RCNT %i] rcount: %x\n", index, count ); return count; }
static inline u32 _psxRcntRcount( u32 index ) { u32 count = psxRegs.cycle; count -= rcnts[index].cycleStart; if (rcnts[index].rate > 1) count /= rcnts[index].rate; #ifdef DEBUG if( count > 0x10000 ) verboseLog( 1, "[RCNT %i] rcount > 0x10000: %x\n", index, count ); #endif count &= 0xffff; return count; }
static inline u32 _psxRcntRcount( u32 index ) { u32 count; count = psxRegs.cycle; count -= rcnts[index].cycleStart; count /= rcnts[index].rate; if( count > 0xffff ) { verboseLog( 1, "[RCNT %i] rcount > 0xffff: %x\n", index, count ); count &= 0xffff; } return count; }
u32 psxRcntRcount( u32 index ) { u32 count; psxRcntUpdate(); count = _psxRcntRcount( index ); // Parasite Eve 2 fix. if( Config.RCntFix ) { if( index == 2 ) { if( rcnts[index].counterState == CountToTarget ) { count /= BIAS; } } } verboseLog( 2, "[RCNT %i] rcount: %x\n", index, count ); return count; }
u32 psxRcntRtarget( u32 index ) { verboseLog( 2, "[RCNT %i] rtarget: %x\n", index, rcnts[index].target ); return rcnts[index].target; }
static void psxRcntReset( u32 index ) { u32 rcycles; rcnts[index].mode |= RcUnknown10; if( rcnts[index].counterState == CountToTarget ) { rcycles = psxRegs.cycle - rcnts[index].cycleStart; if( rcnts[index].mode & RcCountToTarget ) { rcycles -= rcnts[index].target * rcnts[index].rate; rcnts[index].cycleStart = psxRegs.cycle - rcycles; } else { rcnts[index].cycle = 0x10000 * rcnts[index].rate; rcnts[index].counterState = CountToOverflow; } if( rcnts[index].mode & RcIrqOnTarget ) { if( (rcnts[index].mode & RcIrqRegenerate) || (!rcnts[index].irqState) ) { verboseLog( 3, "[RCNT %i] irq\n", index ); setIrq( rcnts[index].irq ); rcnts[index].irqState = 1; } } rcnts[index].mode |= RcCountEqTarget; if( rcycles < 0x10000 * rcnts[index].rate ) return; } if( rcnts[index].counterState == CountToOverflow ) { rcycles = psxRegs.cycle - rcnts[index].cycleStart; rcycles -= 0x10000 * rcnts[index].rate; rcnts[index].cycleStart = psxRegs.cycle - rcycles; if( rcycles < rcnts[index].target * rcnts[index].rate ) { rcnts[index].cycle = rcnts[index].target * rcnts[index].rate; rcnts[index].counterState = CountToTarget; } if( rcnts[index].mode & RcIrqOnOverflow ) { if( (rcnts[index].mode & RcIrqRegenerate) || (!rcnts[index].irqState) ) { verboseLog( 3, "[RCNT %i] irq\n", index ); setIrq( rcnts[index].irq ); rcnts[index].irqState = 1; } } rcnts[index].mode |= RcOverflow; } }