/*

    Non-DMA SPU write, hacked by bITmASTER@bigfoot.com
    v0.1                              
*/

char *SpuWrite( char *addr, int size, int spu_addr )
{
   	volatile short *spu = (short *) 0x1f801c00;
#define SPU_ADDR 0x1a6 / 2
#define SPU_DATA 0x1a8 / 2
#define SPU_CTRL 0x1aa / 2
#define SPU_STAT 0x1ae / 2
	short spu_status; 
    int block_size;
    short *ptr;
    short d;
    int i, time_out;
    
	spu_status = spu[SPU_STAT] & 0x7ff;
	spu[SPU_ADDR] = spu_addr >> 3;
	wait();
    ptr = (short *) addr;
    
	while( size > 0 ) {
		block_size = ( size > 64 ) ? 64 : size; 
		for( i = 0; i < block_size; i += 2 )
			spu[SPU_DATA] = *ptr++;     
			
     	d = spu[SPU_CTRL];
     	d = ( d & 0xffcf ) | 0x10;
     	spu[SPU_CTRL] = d;				// write Block to SPU-Memory
		wait();
		     	
     	time_out = 0;
    	while( spu[SPU_STAT] & 0x400 ) {
    		time_out++;
    		if ( time_out == 3840 ){
    			return( "SPU:T/O wait (wrdy H -> L)\n" );
    		}
    	}
    	wait();
    	wait(); 	
		size -= block_size;
	}     
	
	spu[SPU_CTRL] &= 0xffcf;
	
	time_out = 0;
	while( ( spu[SPU_STAT] & 0x7ff ) != spu_status ) {
		time_out++;
    	if ( time_out == 3840 ){
    		return( "SPU:T/O dmaf clear/W\n" );
    	}
    }			 
	return( 0 );
}

int wait( void )
{
	int i;
	
	for ( i = 0; i < 100; i++ );
		
	return( 0 );
}


