diff options
Diffstat (limited to 'src/emu/sound/psx.c')
-rw-r--r-- | src/emu/sound/psx.c | 695 |
1 files changed, 695 insertions, 0 deletions
diff --git a/src/emu/sound/psx.c b/src/emu/sound/psx.c new file mode 100644 index 00000000000..aa887e2278e --- /dev/null +++ b/src/emu/sound/psx.c @@ -0,0 +1,695 @@ +/*************************************************************************** + + PSX SPU + + CXD2922BQ/CXD2925Q + + preliminary version by smf. + +***************************************************************************/ + +#include <stdarg.h> +#include "sndintrf.h" +#include "streams.h" +#include "cpuintrf.h" +#include "psx.h" + +#define VERBOSE_LEVEL ( 0 ) + +INLINE void verboselog( int n_level, const char *s_fmt, ... ) +{ + if( VERBOSE_LEVEL >= n_level ) + { + va_list v; + char buf[ 32768 ]; + va_start( v, s_fmt ); + vsprintf( buf, s_fmt, v ); + va_end( v ); + logerror( "%08x: %s", activecpu_get_pc(), buf ); + } +} + +#define MAX_CHANNEL ( 24 ) +#define SPU_RAM_SIZE ( 512 * 1024 ) +#define SAMPLES_PER_BLOCK ( 28 ) +#define PITCH_SHIFT ( 12 ) + +struct psxinfo +{ + const struct PSXSPUinterface *intf; + + UINT32 *g_p_n_psxram; + UINT16 m_n_mainvolumeleft; + UINT16 m_n_mainvolumeright; + UINT16 m_n_reverberationdepthleft; + UINT16 m_n_reverberationdepthright; + UINT32 m_n_voiceon; + UINT32 m_n_voiceoff; + UINT32 m_n_modulationmode; + UINT32 m_n_noisemode; + UINT32 m_n_reverbmode; + UINT32 m_n_channelonoff; + UINT16 m_n_reverbworkareastart; + UINT16 m_n_irqaddress; + UINT32 m_n_spuoffset; + UINT16 m_n_spudata; + UINT16 m_n_spucontrol; + UINT32 m_n_spustatus; + UINT16 m_n_cdvolumeleft; + UINT16 m_n_cdvolumeright; + UINT16 m_n_externalvolumeleft; + UINT16 m_n_externalvolumeright; + UINT16 m_p_n_volumeleft[ MAX_CHANNEL ]; + UINT16 m_p_n_volumeright[ MAX_CHANNEL ]; + UINT16 m_p_n_pitch[ MAX_CHANNEL ]; + UINT16 m_p_n_address[ MAX_CHANNEL ]; + UINT16 m_p_n_attackdecaysustain[ MAX_CHANNEL ]; + UINT16 m_p_n_sustainrelease[ MAX_CHANNEL ]; + UINT16 m_p_n_adsrvolume[ MAX_CHANNEL ]; + UINT16 m_p_n_repeataddress[ MAX_CHANNEL ]; + UINT32 m_p_n_effect[ 16 ]; + UINT16 *m_p_n_spuram; + UINT32 m_p_n_blockaddress[ MAX_CHANNEL ]; + UINT32 m_p_n_blockoffset[ MAX_CHANNEL ]; + UINT32 m_p_n_blockstatus[ MAX_CHANNEL ]; + INT16 m_p_n_blockbuffer[ MAX_CHANNEL * SAMPLES_PER_BLOCK ]; + INT16 m_p_n_s1[ MAX_CHANNEL ]; + INT16 m_p_n_s2[ MAX_CHANNEL ]; + UINT32 m_n_loop[ MAX_CHANNEL ]; + + sound_stream *stream; +}; + +#define SPU_REG( a ) ( ( a - 0xc00 ) / 4 ) +#define SPU_CHANNEL_REG( a ) ( a / 4 ) + +INLINE int volume( UINT16 n_volume ) +{ + if( ( n_volume & 0x8000 ) != 0 ) + { + n_volume = ( n_volume & 0x7f ) * 0x80; + } + else if( ( n_volume & 0x4000 ) != 0 ) + { + n_volume = -( n_volume & 0x3fff ); + } + return n_volume; +} + +INLINE int limit( int v ) +{ + if( v < -32768 ) + { + return -32768; + } + else if( v > 32767 ) + { + return 32767; + } + return v; +} + +static void PSXSPU_update(void *param, stream_sample_t **inputs, stream_sample_t **buffer, int length) +{ + struct psxinfo *chip = param; + int v; + int voll; + int volr; + int n_channel; + int n_sample; + int n_word; + int n_shift; + int n_predict; + int n_flags; + int n_nibble; + int n_packed; + int n_unpacked; + + static const int f[ 5 ][ 2 ] = + { + { 0, 0 }, + { 60, 0 }, + { 115, -52 }, + { 98, -55 }, + { 122, -60 } + }; + + memset( buffer[ 0 ], 0, length * sizeof( *buffer[ 0 ] )); + memset( buffer[ 1 ], 0, length * sizeof( *buffer[ 1 ] )); + + for( n_channel = 0; n_channel < MAX_CHANNEL; n_channel++ ) + { + voll = volume( chip->m_p_n_volumeleft[ n_channel ] ); + volr = volume( chip->m_p_n_volumeright[ n_channel ] ); + + for( n_sample = 0; n_sample < length; n_sample++ ) + { + if( chip->m_p_n_blockoffset[ n_channel ] >= ( SAMPLES_PER_BLOCK << PITCH_SHIFT ) ) + { + if( !chip->m_p_n_blockstatus[ n_channel ] ) + { + break; + } + if( ( chip->m_n_spucontrol & 0x40 ) != 0 && + ( chip->m_n_irqaddress * 4 ) >= chip->m_p_n_blockaddress[ n_channel ] && + ( chip->m_n_irqaddress * 4 ) <= chip->m_p_n_blockaddress[ n_channel ] + 7 ) + { + chip->intf->irq_set( 0x0200 ); + } + + n_shift = ( chip->m_p_n_spuram[ chip->m_p_n_blockaddress[ n_channel ] ] >> 0 ) & 0x0f; + n_predict = ( chip->m_p_n_spuram[ chip->m_p_n_blockaddress[ n_channel ] ] >> 4 ) & 0x0f; + n_flags = ( chip->m_p_n_spuram[ chip->m_p_n_blockaddress[ n_channel ] ] >> 8 ) & 0xff; + if( ( n_flags & 4 ) != 0 ) + { + chip->m_n_loop[ n_channel ] = chip->m_p_n_blockaddress[ n_channel ]; + } + chip->m_p_n_blockaddress[ n_channel ]++; + chip->m_p_n_blockaddress[ n_channel ] %= ( SPU_RAM_SIZE / 2 ); + + for( n_word = 0; n_word < 7; n_word++ ) + { + n_packed = chip->m_p_n_spuram[ chip->m_p_n_blockaddress[ n_channel ] ]; + chip->m_p_n_blockaddress[ n_channel ]++; + chip->m_p_n_blockaddress[ n_channel ] %= ( SPU_RAM_SIZE / 2 ); + + for( n_nibble = 0; n_nibble < 4; n_nibble++ ) + { + n_unpacked = ( ( n_packed & 0xf ) << 12 ); + if( ( n_unpacked & 0x8000 ) != 0 ) + { + n_unpacked |= 0xffff0000; + } + n_unpacked = ( n_unpacked >> n_shift ) + + ( ( chip->m_p_n_s1[ n_channel ] * f[ n_predict ][ 0 ] ) >> 6 ) + + ( ( chip->m_p_n_s2[ n_channel ] * f[ n_predict ][ 1 ] ) >> 6 ); + chip->m_p_n_s2[ n_channel ] = chip->m_p_n_s1[ n_channel ]; + chip->m_p_n_s1[ n_channel ] = n_unpacked; + + chip->m_p_n_blockbuffer[ ( n_channel * SAMPLES_PER_BLOCK ) + ( n_word * 4 ) + n_nibble ] = n_unpacked; + n_packed >>= 4; + } + } + if( ( n_flags & 1 ) != 0 ) + { + if( n_flags != 3 ) + { + chip->m_p_n_blockstatus[ n_channel ] = 0; + } + else + { + chip->m_p_n_blockaddress[ n_channel ] = chip->m_n_loop[ n_channel ]; + } + } + chip->m_p_n_blockoffset[ n_channel ] %= ( SAMPLES_PER_BLOCK << PITCH_SHIFT ); + } + v = chip->m_p_n_blockbuffer[ ( n_channel * SAMPLES_PER_BLOCK ) + ( chip->m_p_n_blockoffset[ n_channel ] >> PITCH_SHIFT ) ]; + chip->m_p_n_blockoffset[ n_channel ] += chip->m_p_n_pitch[ n_channel ]; + buffer[ 0 ][ n_sample ] = limit( buffer[ 0 ][ n_sample ] + ( ( v * voll ) / 0x4000 ) ); + buffer[ 1 ][ n_sample ] = limit( buffer[ 1 ][ n_sample ] + ( ( v * volr ) / 0x4000 ) ); + } + } +} + +static void spu_read( UINT32 n_address, INT32 n_size ) +{ + struct psxinfo *chip = sndti_token(SOUND_PSXSPU, 0); + verboselog( 1, "spu_read( %08x, %08x )\n", n_address, n_size ); + + while( n_size > 0 ) + { + chip->g_p_n_psxram[ n_address / 4 ] = + ( chip->m_p_n_spuram[ chip->m_n_spuoffset + 0 ] << 0 ) | + ( chip->m_p_n_spuram[ chip->m_n_spuoffset + 1 ] << 16 ); + verboselog( 2, "%08x > %04x\n", chip->m_n_spuoffset + 0, chip->m_p_n_spuram[ chip->m_n_spuoffset + 0 ] ); + verboselog( 2, "%08x > %04x\n", chip->m_n_spuoffset + 1, chip->m_p_n_spuram[ chip->m_n_spuoffset + 1 ] ); + chip->m_n_spuoffset += 2; + chip->m_n_spuoffset %= ( SPU_RAM_SIZE / 2 ); + n_address += 4; + n_size--; + } +} + +static void spu_write( UINT32 n_address, INT32 n_size ) +{ + struct psxinfo *chip = sndti_token(SOUND_PSXSPU, 0); + verboselog( 1, "spu_write( %08x, %08x )\n", n_address, n_size ); + + while( n_size > 0 ) + { + chip->m_p_n_spuram[ chip->m_n_spuoffset + 0 ] = ( chip->g_p_n_psxram[ n_address / 4 ] >> 0 ); + chip->m_p_n_spuram[ chip->m_n_spuoffset + 1 ] = ( chip->g_p_n_psxram[ n_address / 4 ] >> 16 ); + verboselog( 2, "%08x < %04x\n", chip->m_n_spuoffset + 0, chip->m_p_n_spuram[ chip->m_n_spuoffset + 0 ] ); + verboselog( 2, "%08x < %04x\n", chip->m_n_spuoffset + 1, chip->m_p_n_spuram[ chip->m_n_spuoffset + 1 ] ); + chip->m_n_spuoffset += 2; + chip->m_n_spuoffset %= ( SPU_RAM_SIZE / 2 ); + n_address += 4; + n_size--; + } +} + +static void *psxspu_start(int sndindex, int clock, const void *config) +{ + struct psxinfo *chip; + int n_effect; + int n_channel; + + chip = auto_malloc(sizeof(*chip)); + memset(chip, 0, sizeof(*chip)); + + chip->intf = config; + chip->g_p_n_psxram = *(chip->intf->p_psxram); + + chip->m_n_mainvolumeleft = 0; + chip->m_n_mainvolumeright = 0; + chip->m_n_reverberationdepthleft = 0; + chip->m_n_reverberationdepthright = 0; + chip->m_n_voiceon = 0; + chip->m_n_voiceoff = 0; + chip->m_n_modulationmode = 0; + chip->m_n_noisemode = 0; + chip->m_n_reverbmode = 0; + chip->m_n_channelonoff = 0; + chip->m_n_reverbworkareastart = 0; + chip->m_n_irqaddress = 0; + chip->m_n_spuoffset = 0; + chip->m_n_spudata = 0; + chip->m_n_spucontrol = 0; + chip->m_n_spustatus = 0; + chip->m_n_cdvolumeleft = 0; + chip->m_n_cdvolumeright = 0; + chip->m_n_externalvolumeleft = 0; + chip->m_n_externalvolumeright = 0; + + for( n_channel = 0; n_channel < MAX_CHANNEL; n_channel++ ) + { + chip->m_p_n_volumeleft[ n_channel ] = 0; + chip->m_p_n_volumeright[ n_channel ] = 0; + chip->m_p_n_pitch[ n_channel ] = 0; + chip->m_p_n_address[ n_channel ] = 0; + chip->m_p_n_attackdecaysustain[ n_channel ] = 0; + chip->m_p_n_sustainrelease[ n_channel ] = 0; + chip->m_p_n_adsrvolume[ n_channel ] = 0; + chip->m_p_n_repeataddress[ n_channel ] = 0; + chip->m_p_n_blockaddress[ n_channel ] = 0; + chip->m_p_n_blockoffset[ n_channel ] = 0; + chip->m_p_n_blockstatus[ n_channel ] = 0; + { + char s[ 1024 ]; + sprintf( s, "SPU%d", n_channel ); + } + } + + for( n_effect = 0; n_effect < 16; n_effect++ ) + { + chip->m_p_n_effect[ n_effect ] = 0; + } + + chip->m_p_n_spuram = auto_malloc( SPU_RAM_SIZE ); + + state_save_register_item( "psx", sndindex, chip->m_n_mainvolumeleft ); + state_save_register_item( "psx", sndindex, chip->m_n_mainvolumeright ); + state_save_register_item( "psx", sndindex, chip->m_n_reverberationdepthleft ); + state_save_register_item( "psx", sndindex, chip->m_n_reverberationdepthright ); + state_save_register_item( "psx", sndindex, chip->m_n_voiceon ); + state_save_register_item( "psx", sndindex, chip->m_n_voiceoff ); + state_save_register_item( "psx", sndindex, chip->m_n_modulationmode ); + state_save_register_item( "psx", sndindex, chip->m_n_noisemode ); + state_save_register_item( "psx", sndindex, chip->m_n_reverbmode ); + state_save_register_item( "psx", sndindex, chip->m_n_channelonoff ); + state_save_register_item( "psx", sndindex, chip->m_n_reverbworkareastart ); + state_save_register_item( "psx", sndindex, chip->m_n_irqaddress ); + state_save_register_item( "psx", sndindex, chip->m_n_spuoffset ); + state_save_register_item( "psx", sndindex, chip->m_n_spudata ); + state_save_register_item( "psx", sndindex, chip->m_n_spucontrol ); + state_save_register_item( "psx", sndindex, chip->m_n_spustatus ); + state_save_register_item( "psx", sndindex, chip->m_n_cdvolumeleft ); + state_save_register_item( "psx", sndindex, chip->m_n_cdvolumeright ); + state_save_register_item( "psx", sndindex, chip->m_n_externalvolumeleft ); + state_save_register_item( "psx", sndindex, chip->m_n_externalvolumeright ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_volumeleft ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_volumeright ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_pitch ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_address ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_attackdecaysustain ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_sustainrelease ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_adsrvolume ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_repeataddress ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_effect ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_spuram ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_blockaddress ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_blockoffset ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_blockstatus ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_blockbuffer ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_s1 ); + state_save_register_item_array( "psx", sndindex, chip->m_p_n_s2 ); + state_save_register_item_array( "psx", sndindex, chip->m_n_loop ); + + chip->intf->spu_install_read_handler( 4, spu_read ); + chip->intf->spu_install_write_handler( 4, spu_write ); + + chip->stream = stream_create( 0, 2, 44100, chip, PSXSPU_update ); + return chip; +} + + +static UINT32 psx_spu_delay = 0; + +WRITE32_HANDLER( psx_spu_delay_w ) +{ + COMBINE_DATA( &psx_spu_delay ); + verboselog( 1, "psx_spu_delay_w( %08x %08x )\n", data, mem_mask ); +} + +READ32_HANDLER( psx_spu_delay_r ) +{ + verboselog( 1, "psx_spu_delay_r( %08x )\n", mem_mask ); + return psx_spu_delay; +} + +READ32_HANDLER( psx_spu_r ) +{ + struct psxinfo *chip = sndti_token(SOUND_PSXSPU, 0); + int n_channel; + n_channel = offset / 4; + if( n_channel < MAX_CHANNEL ) + { + switch( offset % 4 ) + { + case SPU_CHANNEL_REG( 0x8 ): + if( ACCESSING_LSW32 ) + { + verboselog( 1, "psx_spu_r() channel %d attack/decay/sustain = %04x\n", n_channel, chip->m_p_n_attackdecaysustain[ n_channel ] ); + } + if( ACCESSING_MSW32 ) + { + verboselog( 1, "psx_spu_r() channel %d sustain/release = %04x\n", n_channel, chip->m_p_n_sustainrelease[ n_channel ] ); + } + return ( chip->m_p_n_sustainrelease[ n_channel ] << 16 ) | chip->m_p_n_attackdecaysustain[ n_channel ]; + case SPU_CHANNEL_REG( 0xc ): + if( ACCESSING_LSW32 ) + { + verboselog( 1, "psx_spu_r() channel %d adsr volume = %04x\n", n_channel, chip->m_p_n_adsrvolume[ n_channel ] ); + } + if( ACCESSING_MSW32 ) + { + verboselog( 1, "psx_spu_r() channel %d repeat address = %04x\n", n_channel, chip->m_p_n_repeataddress[ n_channel ] ); + } + return ( chip->m_p_n_repeataddress[ n_channel ] << 16 ) | chip->m_p_n_adsrvolume[ n_channel ]; + default: + verboselog( 0, "psx_spu_r( %08x, %08x ) channel %d reg %d\n", offset, mem_mask, n_channel, offset % 4 ); + return 0; + } + } + else + { + switch( offset ) + { + case SPU_REG( 0xd88 ): + verboselog( 1, "psx_spu_r( %08x ) voice on = %08x\n", mem_mask, chip->m_n_voiceon ); + return chip->m_n_voiceon; + case SPU_REG( 0xd8c ): + verboselog( 1, "psx_spu_r( %08x ) voice off = %08x\n", mem_mask, chip->m_n_voiceoff ); + return chip->m_n_voiceoff; + case SPU_REG( 0xd90 ): + verboselog( 1, "psx_spu_r( %08x ) modulation mode = %08x\n", mem_mask, chip->m_n_modulationmode ); + return chip->m_n_modulationmode; + case SPU_REG( 0xd94 ): + verboselog( 1, "psx_spu_r( %08x ) noise mode = %08x\n", mem_mask, chip->m_n_noisemode ); + return chip->m_n_noisemode; + case SPU_REG( 0xd98 ): + verboselog( 1, "psx_spu_r( %08x ) reverb mode = %08x\n", mem_mask, chip->m_n_reverbmode ); + return chip->m_n_reverbmode; + case SPU_REG( 0xda4 ): + verboselog( 1, "psx_spu_r( %08x ) dma/irq address = %08x\n", mem_mask, ( ( chip->m_n_spuoffset / 4 ) << 16 ) | chip->m_n_irqaddress ); + return ( ( chip->m_n_spuoffset / 4 ) << 16 ) | chip->m_n_irqaddress; + case SPU_REG( 0xda8 ): + verboselog( 1, "psx_spu_r( %08x ) spu control/data = %08x\n", mem_mask, ( chip->m_n_spucontrol << 16 ) | chip->m_n_spudata ); + return chip->m_n_spudata | ( chip->m_n_spucontrol << 16 ); + case SPU_REG( 0xdac ): + verboselog( 1, "psx_spu_r( %08x ) spu status = %08x\n", mem_mask, chip->m_n_spustatus ); + return chip->m_n_spustatus; + default: + verboselog( 0, "psx_spu_r( %08x, %08x ) %08x\n", offset, mem_mask, 0xc00 + ( offset * 4 ) ); + return 0; + } + } +} + +WRITE32_HANDLER( psx_spu_w ) +{ + struct psxinfo *chip = sndti_token(SOUND_PSXSPU, 0); + int n_channel; + n_channel = offset / 4; + if( n_channel < MAX_CHANNEL ) + { + switch( offset % 4 ) + { + case SPU_CHANNEL_REG( 0x0 ): + if( ACCESSING_LSW32 ) + { + chip->m_p_n_volumeleft[ n_channel ] = data & 0xffff; + verboselog( 1, "psx_spu_w() channel %d volume left = %04x\n", n_channel, chip->m_p_n_volumeleft[ n_channel ] ); + } + if( ACCESSING_MSW32 ) + { + chip->m_p_n_volumeright[ n_channel ] = data >> 16; + verboselog( 1, "psx_spu_w() channel %d volume right = %04x\n", n_channel, chip->m_p_n_volumeright[ n_channel ] ); + } + break; + case SPU_CHANNEL_REG( 0x4 ): + if( ACCESSING_LSW32 ) + { + chip->m_p_n_pitch[ n_channel ] = data & 0xffff; + verboselog( 1, "psx_spu_w() channel %d pitch = %04x\n", n_channel, chip->m_p_n_pitch[ n_channel ] ); + } + if( ACCESSING_MSW32 ) + { + chip->m_p_n_address[ n_channel ] = data >> 16; + verboselog( 1, "psx_spu_w() channel %d address = %04x\n", n_channel, chip->m_p_n_address[ n_channel ] ); + } + break; + case SPU_CHANNEL_REG( 0x8 ): + if( ACCESSING_LSW32 ) + { + chip->m_p_n_attackdecaysustain[ n_channel ] = data & 0xffff; + verboselog( 1, "psx_spu_w() channel %d attack/decay/sustain = %04x\n", n_channel, chip->m_p_n_attackdecaysustain[ n_channel ] ); + } + if( ACCESSING_MSW32 ) + { + chip->m_p_n_sustainrelease[ n_channel ] = data >> 16; + verboselog( 1, "psx_spu_w() channel %d sustain/release = %04x\n", n_channel, chip->m_p_n_sustainrelease[ n_channel ] ); + } + break; + case SPU_CHANNEL_REG( 0xc ): + if( ACCESSING_LSW32 ) + { + chip->m_p_n_adsrvolume[ n_channel ] = data & 0xffff; + verboselog( 1, "psx_spu_w() channel %d adsr volume = %04x\n", n_channel, chip->m_p_n_adsrvolume[ n_channel ] ); + } + if( ACCESSING_MSW32 ) + { + chip->m_p_n_repeataddress[ n_channel ] = data >> 16; + verboselog( 1, "psx_spu_w() channel %d repeat address = %04x\n", n_channel, chip->m_p_n_repeataddress[ n_channel ] ); + } + break; + default: + verboselog( 0, "psx_spu_w( %08x, %08x, %08x ) channel %d reg %d\n", offset, mem_mask, data, n_channel, offset % 4 ); + break; + } + } + else + { + switch( offset ) + { + case SPU_REG( 0xd80 ): + if( ACCESSING_LSW32 ) + { + chip->m_n_mainvolumeleft = data & 0xffff; + verboselog( 1, "psx_spu_w() main volume left = %04x\n", chip->m_n_mainvolumeleft ); + } + if( ACCESSING_MSW32 ) + { + chip->m_n_mainvolumeright = data >> 16; + verboselog( 1, "psx_spu_w() main volume right = %04x\n", chip->m_n_mainvolumeright ); + } + break; + case SPU_REG( 0xd84 ): + if( ACCESSING_LSW32 ) + { + chip->m_n_reverberationdepthleft = data & 0xffff; + verboselog( 1, "psx_spu_w() reverberation depth left = %04x\n", chip->m_n_reverberationdepthleft ); + } + if( ACCESSING_MSW32 ) + { + chip->m_n_reverberationdepthright = data >> 16; + verboselog( 1, "psx_spu_w() reverberation depth right = %04x\n", chip->m_n_reverberationdepthright ); + } + break; + case SPU_REG( 0xd88 ): + chip->m_n_voiceon = 0; + COMBINE_DATA( &chip->m_n_voiceon ); + verboselog( 1, "psx_spu_w() voice on = %08x\n", chip->m_n_voiceon ); + for( n_channel = 0; n_channel < 32; n_channel++ ) + { + if( ( chip->m_n_voiceon & ( 1 << n_channel ) ) != 0 ) + { + chip->m_p_n_blockaddress[ n_channel ] = ( chip->m_p_n_address[ n_channel ] * 4 ) % ( SPU_RAM_SIZE / 2 ); + chip->m_p_n_blockoffset[ n_channel ] = ( SAMPLES_PER_BLOCK << PITCH_SHIFT ); + chip->m_p_n_s1[ n_channel ] = 0; + chip->m_p_n_s2[ n_channel ] = 0; + chip->m_p_n_blockstatus[ n_channel ] = 1; + } + } + break; + case SPU_REG( 0xd8c ): + chip->m_n_voiceoff = 0; + COMBINE_DATA( &chip->m_n_voiceoff ); + verboselog( 1, "psx_spu_w() voice off = %08x\n", chip->m_n_voiceoff ); + break; + case SPU_REG( 0xd90 ): + COMBINE_DATA( &chip->m_n_modulationmode ); + verboselog( 1, "psx_spu_w() modulation mode = %08x\n", chip->m_n_modulationmode ); + break; + case SPU_REG( 0xd94 ): + COMBINE_DATA( &chip->m_n_noisemode ); + verboselog( 1, "psx_spu_w() noise mode = %08x\n", chip->m_n_noisemode ); + break; + case SPU_REG( 0xd98 ): + COMBINE_DATA( &chip->m_n_reverbmode ); + verboselog( 1, "psx_spu_w() reverb mode = %08x\n", chip->m_n_reverbmode ); + break; + case SPU_REG( 0xd9c ): + COMBINE_DATA( &chip->m_n_channelonoff ); + verboselog( 1, "psx_spu_w() channel on/off = %08x\n", chip->m_n_channelonoff ); + break; + case SPU_REG( 0xda0 ): + if( ACCESSING_LSW32 ) + { + verboselog( 0, "psx_spu_w( %08x, %08x, %08x ) %08x\n", offset, mem_mask, data, 0xc00 + ( offset * 4 ) ); + } + if( ACCESSING_MSW32 ) + { + chip->m_n_reverbworkareastart = data >> 16; + verboselog( 1, "psx_spu_w() reverb work area start = %04x\n", chip->m_n_reverbworkareastart ); + } + break; + case SPU_REG( 0xda4 ): + if( ACCESSING_LSW32 ) + { + chip->m_n_irqaddress = data & 0xffff; + verboselog( 1, "psx_spu_w() irq address = %04x\n", chip->m_n_irqaddress ); + } + if( ACCESSING_MSW32 ) + { + chip->m_n_spuoffset = ( data >> 16 ) * 4; + chip->m_n_spuoffset %= ( SPU_RAM_SIZE / 2 ); + verboselog( 1, "psx_spu_w() spu offset = %04x\n", chip->m_n_spuoffset ); + } + break; + case SPU_REG( 0xda8 ): + if( ACCESSING_LSW32 ) + { + chip->m_n_spudata = data & 0xffff; + chip->m_p_n_spuram[ chip->m_n_spuoffset++ ] = chip->m_n_spudata; + chip->m_n_spuoffset %= ( SPU_RAM_SIZE / 2 ); + verboselog( 1, "psx_spu_w() spu data = %04x\n", chip->m_n_spudata ); + } + if( ACCESSING_MSW32 ) + { + chip->m_n_spucontrol = data >> 16; + verboselog( 1, "psx_spu_w() spu control = %04x\n", chip->m_n_spucontrol ); + } + break; + case SPU_REG( 0xdac ): + COMBINE_DATA( &chip->m_n_spustatus ); + chip->m_n_spustatus &= 0xf800ffff; + verboselog( 1, "psx_spu_w() spu status = %08x\n", chip->m_n_spustatus ); + break; + case SPU_REG( 0xdb0 ): + if( ACCESSING_LSW32 ) + { + chip->m_n_cdvolumeleft = data & 0xffff; + verboselog( 1, "psx_spu_w() cd volume left = %04x\n", chip->m_n_cdvolumeleft ); + } + if( ACCESSING_MSW32 ) + { + chip->m_n_cdvolumeright = data >> 16; + verboselog( 1, "psx_spu_w() cd volume right = %04x\n", chip->m_n_cdvolumeright ); + } + break; + case SPU_REG( 0xdb4 ): + if( ACCESSING_LSW32 ) + { + chip->m_n_externalvolumeleft = data & 0xffff; + verboselog( 1, "psx_spu_w() external volume left = %04x\n", chip->m_n_externalvolumeleft ); + } + if( ACCESSING_MSW32 ) + { + chip->m_n_externalvolumeright = data >> 16; + verboselog( 1, "psx_spu_w() external volume right = %04x\n", chip->m_n_externalvolumeright ); + } + break; + case SPU_REG( 0xdc0 ): + case SPU_REG( 0xdc4 ): + case SPU_REG( 0xdc8 ): + case SPU_REG( 0xdcc ): + case SPU_REG( 0xdd0 ): + case SPU_REG( 0xdd4 ): + case SPU_REG( 0xdd8 ): + case SPU_REG( 0xddc ): + case SPU_REG( 0xde0 ): + case SPU_REG( 0xde4 ): + case SPU_REG( 0xde8 ): + case SPU_REG( 0xdec ): + case SPU_REG( 0xdf0 ): + case SPU_REG( 0xdf4 ): + case SPU_REG( 0xdf8 ): + case SPU_REG( 0xdfc ): + COMBINE_DATA( &chip->m_p_n_effect[ offset & 0x0f ] ); + verboselog( 1, "psx_spu_w() effect %d = %04x\n", offset & 0x0f, chip->m_p_n_effect[ offset & 0x0f ] ); + break; + default: + verboselog( 0, "psx_spu_w( %08x, %08x, %08x ) %08x\n", offset, mem_mask, data, 0xc00 + ( offset * 4 ) ); + break; + } + } +} + + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +static void psxspu_set_info(void *token, UINT32 state, sndinfo *info) +{ + switch (state) + { + /* no parameters to set */ + } +} + + +void psxspu_get_info(void *token, UINT32 state, sndinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case SNDINFO_PTR_SET_INFO: info->set_info = psxspu_set_info; break; + case SNDINFO_PTR_START: info->start = psxspu_start; break; + case SNDINFO_PTR_STOP: /* Nothing */ break; + case SNDINFO_PTR_RESET: /* Nothing */ break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case SNDINFO_STR_NAME: info->s = "SPU"; break; + case SNDINFO_STR_CORE_FAMILY: info->s = "Sony custom"; break; + case SNDINFO_STR_CORE_VERSION: info->s = "1.0"; break; + case SNDINFO_STR_CORE_FILE: info->s = __FILE__; break; + case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright (c) 2004, The MAME Team"; break; + } +} + |