// hacked by bITmASTER 
// last update 24/06/98

char *SpuDMAWrite( char *addr, int size, int spu_addr )
{
   	volatile unsigned short *spu = (unsigned short *) 0x1f801c00;
   	volatile unsigned int *spuxx = (unsigned int *) 0x1f801014;
   	volatile int *spu_dma = (int *) 0x1f8010c0;
   	
    short d;
    int time_out;
    
	spu[SPU_ADDR] = spu_addr >> 3;
    time_out = 0;
   	while( spu[SPU_ADDR] != ( spu_addr >> 3 ) ) {
   		time_out++;
   		if ( time_out == 3840 ){
   			return( "SPU:T/O wait spu_addr\n" );
   		}
   	}    

   	spu[SPU_CTRL] = ( spu[SPU_CTRL] & 0xffcf ) | 0x20;	// write Block to SPU-Memory via DMA
    time_out = 0;
   	while( ( spu[SPU_CTRL] & 0x30 ) != 0x20 ) {
   		time_out++;
   		if ( time_out == 3840 ){
   			return( "SPU:T/O wait spu_dma_wr\n" );
   		}
   	} 

    *spuxx = ( *spuxx & 0xf0ffffff ) | 0x20000000;   	// ?????
     
	spu_dma[0] = (int) addr;
	d = size / 64;
	if ( size % 64 )
		d++;
		
	spu_dma[1] = ( d << 16 ) | 0x10;    		// 0x10
	spu_dma[3] = 0x01000201;                    // 0x01000201
    

	return( 0 );
}      

int dma_status( void )
{
   	volatile int *spu_dma = (int *) 0x1f8010c0;    
    
	return( ( spu_dma[3] >> 24 ) & 1 );      		// return 0 if dma transfer complete
}
      

char *SpuDMARead( char *addr, int size, int spu_addr )
{
   	volatile unsigned short *spu = (unsigned short *) 0x1f801c00;
   	volatile unsigned int *spuxx = (unsigned int *) 0x1f801014;
   	volatile int *spu_dma = (int *) 0x1f8010c0;
   	
    short d;
    int time_out;
    
	spu[SPU_ADDR] = spu_addr >> 3;
    time_out = 0;
   	while( spu[SPU_ADDR] != ( spu_addr >> 3 ) ) {
   		time_out++;
   		if ( time_out == 3840 ){
   			return( "SPU:T/O wait spu_addr\n" );
   		}
   	}    

   	spu[SPU_CTRL] = ( spu[SPU_CTRL] & 0xffcf ) | 0x30;	// read Block to SPU-Memory via DMA
    time_out = 0;
   	while( ( spu[SPU_CTRL] & 0x30 ) != 0x30 ) {
   		time_out++;
   		if ( time_out == 3840 ){
   			return( "SPU:T/O wait spu_dma_wr\n" );
   		}
   	} 

    *spuxx = ( *spuxx & 0xf0ffffff ) | 0x22000000;   	// ?????

	spu_dma[0] = (int) addr;
	d = size / 64;
	if ( size % 64 )
		d++;
		
	spu_dma[1] = ( d << 16 ) | 0x10;
	spu_dma[3] = 0x01000200;    
    

	return( 0 );
}
