Пример #1
0
void psxRcnt0Wmode(u32 value)
{
	PSXCNT_LOG("IOP Counter[0] writeMode = %lx\n", value);

	psxCounters[0].mode = value;
	psxCounters[0].mode|= 0x0400;
	psxCounters[0].rate = 1;

	if(value & IOPCNT_ALT_SOURCE)
		psxCounters[0].rate = PSXPIXEL;
	
	if(psxCounters[0].mode & IOPCNT_ENABLE_GATE)
	{
		// gated counters are added up as per the h/vblank timers.
		PSXCNT_LOG("IOP Counter[0] Gate Check set, value = %x\n", value);
		psxhblankgate |= 1;
	}
	else psxhblankgate &= ~1;

	psxCounters[0].count = 0;
	psxCounters[0].sCycleT = psxRegs.cycle;
	psxCounters[0].target &= 0xffff;

	_rcntSet( 0 );
}
Пример #2
0
__fi void psxRcntWmode16( int index, u32 value )
{
	PSXCNT_LOG( "IOP Counter[%d] writeMode = 0x%04X", index, value );

	pxAssume( index >= 0 && index < 3 );
	psxCounter& counter = psxCounters[index];

	counter.mode  = value;
	counter.mode |= 0x0400;

	if( index == 2 )
	{
		switch(value & 0x200)
		{
		case 0x000: psxCounters[2].rate = 1; break;
		case 0x200: psxCounters[2].rate = 8; break;
			jNO_DEFAULT;
		}

		if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
		{
			counter.mode |= IOPCNT_STOPPED;
		}
	}
	else
	{
		// Counters 0 and 1 can select PIXEL or HSYNC as an alternate source:
		counter.rate = 1;

		if(value & IOPCNT_ALT_SOURCE)
			counter.rate = (index==0) ? PSXPIXEL : PSXHBLANK;

		if(counter.mode & IOPCNT_ENABLE_GATE)
		{
			// gated counters are added up as per the h/vblank timers.
			// (the PIXEL alt source becomes a vsync gate)
			counter.mode |= IOPCNT_STOPPED;
			PSXCNT_LOG( "IOP Counter[%d] Gate Check set, value = 0x%04X", index, value );
			if( index == 0 )
				psxhblankgate |= 1;		// fixme: these gate flags should be one var >_<
			else
				psxvblankgate |= 1<<1;
		}
		else
		{
			if( index == 0 )
				psxhblankgate &= ~1;
			else
				psxvblankgate &= ~(1<<1);
		}
	}

	counter.count = 0;
	counter.sCycleT = psxRegs.cycle;
	counter.target &= 0xffff;

	_rcntSet( index );
}
Пример #3
0
__fi void psxRcntWmode32( int index, u32 value )
{
	PSXCNT_LOG( "IOP Counter[%d] writeMode = 0x%04x", index, value );

	pxAssume( index >= 3 && index < 6 );
	psxCounter& counter = psxCounters[index];

	counter.mode  = value;
	counter.mode |= 0x0400;

	if( index == 3 )
	{
		// Counter 3 has the HBlank as an alternate source.
		counter.rate  = 1;
		if(value & IOPCNT_ALT_SOURCE)
			counter.rate = PSXHBLANK;

		if(counter.mode & IOPCNT_ENABLE_GATE)
		{
			PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
			counter.mode |= IOPCNT_STOPPED;
			psxvblankgate |= 1<<3;
		}
		else psxvblankgate &= ~(1<<3);
	}
	else
	{
		switch(value & 0x6000)
		{
		case 0x0000: counter.rate = 1;   break;
		case 0x2000: counter.rate = 8;   break;
		case 0x4000: counter.rate = 16;  break;
		case 0x6000: counter.rate = 256; break;
		}

		// Need to set a rate and target
		if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
		{
			Console.WriteLn( "Gate set on IOP Counter %d, disabling", index );
			counter.mode |= IOPCNT_STOPPED;
		}
	}

	counter.count = 0;
	counter.sCycleT = psxRegs.cycle;
	counter.target &= 0xffffffff;
	_rcntSet( index );
}
Пример #4
0
void psxRcnt5Wmode(u32 value)
{
	PSXCNT_LOG("IOP Counter[5] writeMode = %lx\n", value);

	psxCounters[5].mode = value;
	psxCounters[5].mode|= 0x0400;

	switch(value & 0x6000)
	{
		case 0x0000: psxCounters[5].rate = 1; break;
		case 0x2000: psxCounters[5].rate = 8; break;
		case 0x4000: psxCounters[5].rate = 16; break;
		case 0x6000: psxCounters[5].rate = 256; break;
	}
	// Need to set a rate and target
	if((psxCounters[5].mode & 0x7) == 0x7 || (psxCounters[5].mode & 0x7) == 0x1)
	{
		SysPrintf("Gate set on IOP C5, disabling\n");
		psxCounters[5].mode |= IOPCNT_STOPPED;
	}
	
	psxCounters[5].count = 0;
	psxCounters[5].sCycleT = psxRegs.cycle;
	psxCounters[5].target &= 0xffffffff;
	_rcntSet( 5 );
}
Пример #5
0
static __forceinline void _rcntTestOverflow( int i )
{
	u64 maxTarget = ( i < 3 ) ? 0xffff : 0xfffffffful;
	if( psxCounters[i].count <= maxTarget ) return;

	PSXCNT_LOG("IOP Counter[%d] overflow 0x%I64x >= 0x%I64x (mode: %x)\n",
		i, psxCounters[i].count, maxTarget, psxCounters[i].mode );

	if(psxCounters[i].mode & IOPCNT_INT_OVERFLOW)
	{
		// Overflow interrupt
		psxHu32(0x1070) |= psxCounters[i].interrupt;
		psxCounters[i].mode |= 0x1000; // Overflow flag
		if(psxCounters[i].mode & 0x80)
			psxCounters[i].mode &= ~0x0400; // Interrupt flag
	}
	
	// Update count and target.
	// Count wraps around back to zero, while the target is restored (if needed).
	// (high bit of the target gets set by rcntWtarget when the target is behind
	// the counter value, and thus should not be flagged until after an overflow)
	
	psxCounters[i].count &= maxTarget;
	psxCounters[i].target &= maxTarget;
}
Пример #6
0
static void __fastcall _rcntTestTarget( int i )
{
	if( psxCounters[i].count < psxCounters[i].target ) return;

	PSXCNT_LOG("IOP Counter[%d] target 0x%I64x >= 0x%I64x (mode: %x)\n",
		i, psxCounters[i].count, psxCounters[i].target, psxCounters[i].mode);

	if (psxCounters[i].mode & IOPCNT_INT_TARGET)
	{
		// Target interrupt

		if(psxCounters[i].mode & 0x80)
			psxCounters[i].mode &= ~0x0400; // Interrupt flag
		psxCounters[i].mode |= 0x0800; // Target flag

		psxHu32(0x1070) |= psxCounters[i].interrupt;
	}
	
	if (psxCounters[i].mode & 0x08)
	{
		// Reset on target
		psxCounters[i].count -= psxCounters[i].target;
		if(!(psxCounters[i].mode & 0x40))
		{
			SysPrintf("Counter %x repeat intr not set on zero ret, ignoring target\n", i);
			psxCounters[i].target |= IOPCNT_FUTURE_TARGET;
		}
	} else psxCounters[i].target |= IOPCNT_FUTURE_TARGET;
}
Пример #7
0
void psxRcntWcount32(int index, u32 value)
{
	u32 change;

	pxAssert( index >= 3 && index < 6 );
	PSXCNT_LOG("32bit IOP Counter[%d] writeCount32 = %x", index, value);

	if(psxCounters[index].rate != PSXHBLANK)
	{
		// Re-adjust the sCycleT to match where the counter is currently
		// (remainder of the rate divided into the time passed will do the trick)

		change = psxRegs.cycle - psxCounters[index].sCycleT;
		psxCounters[index].sCycleT = psxRegs.cycle - (change % psxCounters[index].rate);
	}

	psxCounters[index].count = value;
	if ((psxCounters[index].mode & 0x400) || (psxCounters[index].mode & 0x40)) { //IRQ not triggered (one shot) or toggle
		psxCounters[index].target &= 0xffffffff;
	}
	if (value > psxCounters[index].target) {//Count already higher than Target
		//DevCon.Warning("32bit Count already higher than target");
		psxCounters[index].target |= IOPCNT_FUTURE_TARGET;
	}
	_rcntSet( index );
}
Пример #8
0
u32 psxRcntRcount32(int index)
{
	u32 retval = (u32)psxCounters[index].count;
	
	assert( index >= 3 && index < 6 );

	PSXCNT_LOG("IOP Counter[%d] readCount32 = %lx\n", index, retval );

	if( !( psxCounters[index].mode & IOPCNT_STOPPED ) &&
		( psxCounters[index].rate != PSXHBLANK ) )
	{
		u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate);
		retval += delta;
		PSXCNT_LOG("               (delta = %lx)\n", delta );
	}

	return retval;
}
Пример #9
0
u16 psxRcntRcount16(int index)
{
	u32 retval = (u32)psxCounters[index].count;

	assert( index < 3 );

	PSXCNT_LOG("IOP Counter[%d] readCount16 = %lx\n", index, (u16)retval );

	// Don't count HBLANK timers
	// Don't count stopped gates either.

	if( !( psxCounters[index].mode & IOPCNT_STOPPED ) &&
		( psxCounters[index].rate != PSXHBLANK ) )
	{
		u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate);
		retval += delta;
		PSXCNT_LOG("              (delta = %lx)\n", delta );
	}

	return (u16)retval;
}
Пример #10
0
void psxRcnt3Wmode(u32 value)
{
	PSXCNT_LOG("IOP Counter[3] writeMode = %lx\n", value);

	psxCounters[3].mode = value;
	psxCounters[3].rate = 1;
	psxCounters[3].mode|= 0x0400;

	if(value & IOPCNT_ALT_SOURCE)
		psxCounters[3].rate = PSXHBLANK;
  
	if(psxCounters[3].mode & IOPCNT_ENABLE_GATE)
	{
		PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x\n", value);
		psxvblankgate |= 1<<3;
	}
	else psxvblankgate &= ~(1<<3);

	psxCounters[3].count = 0;
	psxCounters[3].sCycleT = psxRegs.cycle;
	psxCounters[3].target &= 0xffffffff;
	_rcntSet( 3 );
}
Пример #11
0
void psxRcntWtarget16(int index, u32 value)
{
	assert( index < 3 );
	PSXCNT_LOG("IOP Counter[%d] writeTarget16 = %lx\n", index, value);
	psxCounters[index].target = value & 0xffff;

	// protect the target from an early arrival.
	// if the target is behind the current count, then set the target overflow
	// flag, so that the target won't be active until after the next overflow.
	
	if(psxCounters[index].target <= psxRcntCycles(index))
		psxCounters[index].target |= IOPCNT_FUTURE_TARGET;

	_rcntSet( index );
}
Пример #12
0
void psxRcntWcount32(int index, u32 value)
{
	u32 change;

	assert( index >= 3 && index < 6 );
	PSXCNT_LOG("IOP Counter[%d] writeCount32 = %x\n", index, value);
	
	if(psxCounters[index].rate != PSXHBLANK)
	{
		// Re-adjust the sCycleT to match where the counter is currently
		// (remainder of the rate divided into the time passed will do the trick)

		change = psxRegs.cycle - psxCounters[index].sCycleT;
		psxCounters[index].sCycleT = psxRegs.cycle - (change % psxCounters[index].rate);
	}

	psxCounters[index].count = value & 0xffffffff;
	psxCounters[index].target &= 0xffffffff;	
	_rcntSet( index );
}
Пример #13
0
static __fi void _rcntTestOverflow( int i )
{
	u64 maxTarget = ( i < 3 ) ? 0xffff : 0xfffffffful;
	if( psxCounters[i].count <= maxTarget ) return;

	PSXCNT_LOG("IOP Counter[%d] overflow 0x%I64x >= 0x%I64x (mode: %x)",
		i, psxCounters[i].count, maxTarget, psxCounters[i].mode );
	if (!(psxCounters[i].mode & 0x40)) //One shot, whichever condition is met first
	{
		if (psxCounters[i].target < IOPCNT_FUTURE_TARGET) { //Target didn't trigger so we can overflow
			// Overflow interrupt
			if ((psxCounters[i].mode & IOPCNT_INT_OVERFLOW)) {
				if (_rcntFireInterrupt(i, true))
					psxCounters[i].mode |= 0x1000; // Overflow flag		
			}
		}
		psxCounters[i].target |= IOPCNT_FUTURE_TARGET;

	}
	else
	{
		// Overflow interrupt
		if ((psxCounters[i].mode & IOPCNT_INT_OVERFLOW)) {
			if (_rcntFireInterrupt(i, true))
				psxCounters[i].mode |= 0x1000; // Overflow flag
		}
		psxCounters[i].target &= maxTarget;		
	}

	// Update count.
	// Count wraps around back to zero, while the target is restored (if not in one shot mode).
	// (high bit of the target gets set by rcntWtarget when the target is behind
	// the counter value, and thus should not be flagged until after an overflow)

	psxCounters[i].count -= maxTarget;
		

	
}
Пример #14
0
void psxRcnt2Wmode(u32 value)
{
	PSXCNT_LOG("IOP Counter[0] writeMode = %lx\n", value);

	psxCounters[2].mode = value;
	psxCounters[2].mode|= 0x0400;

	switch(value & 0x200)
	{
		case 0x200: psxCounters[2].rate = 8; break;
		case 0x000: psxCounters[2].rate = 1; break;
	}

	if((psxCounters[2].mode & 0x7) == 0x7 || (psxCounters[2].mode & 0x7) == 0x1)
	{
		//SysPrintf("Gate set on IOP C2, disabling\n");
		psxCounters[2].mode |= IOPCNT_STOPPED;
	}
	
	psxCounters[2].count = 0;
	psxCounters[2].sCycleT = psxRegs.cycle;
	psxCounters[2].target &= 0xffff;
	_rcntSet( 2 );
}
Пример #15
0
static void __fastcall _rcntTestTarget( int i )
{
	if( psxCounters[i].count < psxCounters[i].target ) return;

	PSXCNT_LOG("IOP Counter[%d] target 0x%I64x >= 0x%I64x (mode: %x)",
		i, psxCounters[i].count, psxCounters[i].target, psxCounters[i].mode);

	if (psxCounters[i].mode & IOPCNT_INT_TARGET)
	{
		// Target interrupt
		
		if(_rcntFireInterrupt(i, false))
			psxCounters[i].mode |= 0x0800; // Target flag
	}

	if (psxCounters[i].mode & 0x08)
	{
		// Reset on target
		psxCounters[i].count -= psxCounters[i].target;
	}
	else
		psxCounters[i].target |= IOPCNT_FUTURE_TARGET;
	
}
Пример #16
0
__fi void psxRcntWmode32( int index, u32 value )
{
	PSXCNT_LOG("32bit IOP Counter[%d] writeMode = 0x%04x", index, value );
	int irqmode = 0;
	pxAssume( index >= 3 && index < 6 );
	psxCounter& counter = psxCounters[index];

	counter.mode  = value;
	counter.mode |= 0x0400; //IRQ enable

	if (value & (1 << 4)) {
		irqmode += 1;
	}
	if (value & (1 << 5)) {
		irqmode += 2;
	}
	if (value & (1 << 7)) {
		PSXCNT_LOG("32 Counter %d Toggle IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow"));
	}
	else
	{
		PSXCNT_LOG("32 Counter %d Pulsed IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow"));
	}
	if (!(value & (1 << 6))) {
		PSXCNT_LOG("32 Counter %d One Shot", index);
	}
	else {
		PSXCNT_LOG("32 Counter %d Repeat", index);
	}
	if( index == 3 )
	{
		// Counter 3 has the HBlank as an alternate source.
		counter.rate  = 1;
		if(value & IOPCNT_ALT_SOURCE)
			counter.rate = PSXHBLANK;

		if(counter.mode & IOPCNT_ENABLE_GATE)
		{
			PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
			counter.mode |= IOPCNT_STOPPED;
			psxvblankgate |= 1<<3;
		}
		else psxvblankgate &= ~(1<<3);
	}
	else
	{
		switch(value & 0x6000)
		{
		case 0x0000: counter.rate = 1;   break;
		case 0x2000: counter.rate = 8;   break;
		case 0x4000: counter.rate = 16;  break;
		case 0x6000: counter.rate = 256; break;
		}

		// Need to set a rate and target
		if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
		{
			Console.WriteLn( "Gate set on IOP Counter %d, disabling", index );
			counter.mode |= IOPCNT_STOPPED;
		}
	}

	counter.count = 0;
	counter.sCycleT = psxRegs.cycle;
	counter.target &= 0xffffffff;
	_rcntSet( index );
}