summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/psx/dma.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/psx/dma.cpp')
-rw-r--r--src/devices/cpu/psx/dma.cpp386
1 files changed, 191 insertions, 195 deletions
diff --git a/src/devices/cpu/psx/dma.cpp b/src/devices/cpu/psx/dma.cpp
index 5ec8e29fdbd..d0c3836ea43 100644
--- a/src/devices/cpu/psx/dma.cpp
+++ b/src/devices/cpu/psx/dma.cpp
@@ -10,22 +10,19 @@
#include "emu.h"
#include "dma.h"
-#define VERBOSE_LEVEL ( 0 )
+#define LOG_READ (1U << 1)
+#define LOG_WRITE (1U << 2)
+#define LOG_DMA (1U << 3)
+#define LOG_IRQ (1U << 4)
-static inline void ATTR_PRINTF(3,4) verboselog( device_t& device, 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 );
- device.logerror( "%s: %s", device.machine().describe_context(), buf );
- }
-}
+//#define VERBOSE (LOG_READ | LOG_WRITE | LOG_DMA | LOG_IRQ)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-DEFINE_DEVICE_TYPE(PSX_DMA, psxdma_device, "psxdma", "Sony PSX DMA")
+#define LOGREAD(...) LOGMASKED(LOG_READ, __VA_ARGS__)
+#define LOGWRITE(...) LOGMASKED(LOG_WRITE, __VA_ARGS__)
+#define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__)
+#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__)
psxdma_device::psxdma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PSX_DMA, tag, owner, clock), m_ram(), m_ramsize(0), m_dpcp(0), m_dicr(0),
@@ -35,77 +32,61 @@ psxdma_device::psxdma_device(const machine_config &mconfig, const char *tag, dev
void psxdma_device::device_reset()
{
- int n;
-
m_dpcp = 0;
m_dicr = 0;
- for( n = 0; n < 7; n++ )
- {
- dma_stop_timer( n );
- }
-}
-
-void psxdma_device::device_post_load()
-{
- int n;
-
- for( n = 0; n < 7; n++ )
+ for (int n = 0; n < 7; n++)
{
- dma_timer_adjust( n );
+ dma_stop_timer(n);
+ m_channel[n].n_channelcontrol = 0;
}
}
void psxdma_device::device_start()
{
- m_irq_handler.resolve_safe();
-
- for( int index = 0; index < 7; index++ )
+ for (int index = 0; index < 7; index++)
{
- psx_dma_channel *dma = &m_channel[ index ];
+ psx_dma_channel *dma = &m_channel[index];
- dma->timer = timer_alloc(index);
+ dma->timer = timer_alloc(FUNC(psxdma_device::dma_finished), this);
+ dma->b_running = 0;
- save_item( NAME( dma->n_base ), index );
- save_item( NAME( dma->n_blockcontrol ), index );
- save_item( NAME( dma->n_channelcontrol ), index );
- save_item( NAME( dma->n_ticks ), index );
- save_item( NAME( dma->b_running ), index );
+ save_item(NAME(dma->n_base), index);
+ save_item(NAME(dma->n_blockcontrol), index);
+ save_item(NAME(dma->n_channelcontrol), index);
+ save_item(NAME(dma->n_ticks), index);
+ save_item(NAME(dma->b_running), index);
}
- save_item( NAME(m_dpcp) );
- save_item( NAME(m_dicr) );
+ save_item(NAME(m_dpcp));
+ save_item(NAME(m_dicr));
}
-void psxdma_device::dma_start_timer( int index, uint32_t n_ticks )
+void psxdma_device::dma_start_timer(int index, uint32_t n_ticks)
{
- psx_dma_channel *dma = &m_channel[ index ];
+ psx_dma_channel *dma = &m_channel[index];
- dma->timer->adjust( attotime::from_hz(33868800) * n_ticks, index);
+ dma->timer->adjust(attotime::from_hz(33868800) * n_ticks, index);
dma->n_ticks = n_ticks;
dma->b_running = 1;
}
-void psxdma_device::dma_stop_timer( int index )
+void psxdma_device::dma_stop_timer(int index)
{
- psx_dma_channel *dma = &m_channel[ index ];
+ psx_dma_channel *dma = &m_channel[index];
- dma->timer->adjust( attotime::never);
+ dma->timer->adjust(attotime::never);
dma->b_running = 0;
}
-void psxdma_device::dma_timer_adjust( int index )
+void psxdma_device::dma_timer_adjust(int index)
{
- psx_dma_channel *dma = &m_channel[ index ];
+ psx_dma_channel *dma = &m_channel[index];
- if( dma->b_running )
- {
- dma_start_timer( index, dma->n_ticks );
- }
+ if (dma->b_running)
+ dma_start_timer(index, dma->n_ticks);
else
- {
- dma_stop_timer( index );
- }
+ dma_stop_timer(index);
}
void psxdma_device::dma_interrupt_update()
@@ -113,61 +94,85 @@ void psxdma_device::dma_interrupt_update()
int n_int;
int n_mask;
- n_int = ( m_dicr >> 24 ) & 0x7f;
- n_mask = ( m_dicr >> 16 ) & 0xff;
+ n_int = (m_dicr >> 24) & 0x7f;
+ n_mask = (m_dicr >> 16) & 0xff;
- if( ( n_mask & 0x80 ) != 0 && ( n_int & n_mask ) != 0 )
+ if ((n_mask & 0x80) != 0 && (n_int & n_mask) != 0)
{
- verboselog( *this, 2, "dma_interrupt_update( %02x, %02x ) interrupt triggered\n", n_int, n_mask );
+ LOGIRQ("dma_interrupt_update( %02x, %02x ) interrupt triggered\n", machine().describe_context(), n_int, n_mask);
m_dicr |= 0x80000000;
m_irq_handler(1);
}
- else if( n_int != 0 )
+ else if (n_int != 0)
{
- verboselog( *this, 2, "dma_interrupt_update( %02x, %02x ) interrupt not enabled\n", n_int, n_mask );
+ LOGIRQ("dma_interrupt_update( %02x, %02x ) interrupt not enabled\n", machine().describe_context(), n_int, n_mask);
}
- m_dicr &= 0x00ffffff | ( m_dicr << 8 );
+ m_dicr &= 0x00ffffff | (m_dicr << 8);
}
-void psxdma_device::dma_finished( int index )
+TIMER_CALLBACK_MEMBER(psxdma_device::dma_finished)
{
- psx_dma_channel *dma = &m_channel[ index ];
+ int const index = param;
+ psx_dma_channel *dma = &m_channel[index];
- if( dma->n_channelcontrol == 0x01000401 && index == 2 )
+ if (dma->n_channelcontrol == 0x01000201)
+ {
+ int32_t n_size;
+ uint32_t n_address;
+ uint32_t n_adrmask;
+
+ n_adrmask = m_ramsize - 1;
+ n_address = (dma->n_base & n_adrmask);
+ n_size = dma->n_blockcontrol;
+ if ((dma->n_channelcontrol & 0x200) != 0)
+ {
+ uint32_t n_ba;
+ n_ba = dma->n_blockcontrol >> 16;
+ if (n_ba == 0)
+ {
+ n_ba = 0x10000;
+ }
+ n_size = (n_size & 0xffff) * n_ba;
+ }
+
+ LOGDMA("%s dma %d write block %08x %08x\n", machine().describe_context(), index, n_address, n_size);
+ dma->fn_write(m_ram, n_address, n_size);
+ }
+ else if (dma->n_channelcontrol == 0x01000401 && index == 2)
{
uint32_t n_size;
uint32_t n_total;
- uint32_t n_address = ( dma->n_base & 0xffffff );
+ uint32_t n_address = (dma->n_base & 0xffffff);
uint32_t n_adrmask = m_ramsize - 1;
uint32_t n_nextaddress;
- if( n_address != 0xffffff )
+ if (n_address != 0xffffff)
{
n_total = 0;
- for( ;; )
+ for (;; )
{
- if( n_address == 0xffffff )
+ if (n_address == 0xffffff)
{
dma->n_base = n_address;
//HACK: fixes pse bios 2.x & other texture uploading issues, breaks kdeadeye test mode, gtrfrk7m & gtrkfrk8m loading
//dma_start_timer( index, 19000 );
- dma_start_timer( index, 500 );
+ dma_start_timer(index, 500);
return;
}
- if( n_total > 65535 )
+ if (n_total > 65535)
{
dma->n_base = n_address;
//FIXME:
// 16000 below is based on try and error.
// Mametesters.org: sfex20103red
//dma_start_timer( index, 16 );
- dma_start_timer( index, 16000 );
+ dma_start_timer(index, 16000);
return;
}
n_address &= n_adrmask;
- n_nextaddress = m_ram[ n_address / 4 ];
+ n_nextaddress = m_ram[n_address / 4];
n_size = n_nextaddress >> 24;
- dma->fn_write( m_ram, n_address + 4, n_size );
+ dma->fn_write(m_ram, n_address + 4, n_size);
//FIXME:
// The following conditions will cause an endless loop.
// If stopping the transfer is correct I cannot judge
@@ -176,62 +181,61 @@ void psxdma_device::dma_finished( int index )
// Mametesters.org: psyforce0105u5red, raystorm0111u1red
if ((n_nextaddress & 0xffffff) != 0xffffff)
{
- if (n_address == m_ram[ (n_nextaddress & n_adrmask) / 4] ||
- n_address == (n_nextaddress & n_adrmask) )
+ if (n_address == m_ram[(n_nextaddress & n_adrmask) / 4] ||
+ n_address == (n_nextaddress & n_adrmask))
{
break;
}
}
- n_address = ( n_nextaddress & 0xffffff );
+ n_address = (n_nextaddress & 0xffffff);
- n_total += ( n_size + 1 );
+ n_total += (n_size + 1);
}
}
}
- dma->n_channelcontrol &= ~( ( 1L << 0x18 ) | ( 1L << 0x1c ) );
+ dma->n_channelcontrol &= ~((1L << 0x18) | (1L << 0x1c));
- m_dicr |= 1 << ( 24 + index );
+ m_dicr |= 1 << (24 + index);
dma_interrupt_update();
- dma_stop_timer( index );
-}
-
-void psxdma_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- dma_finished(id);
+ dma_stop_timer(index);
}
-void psxdma_device::install_read_handler( int index, read_delegate p_fn_dma_read )
+void psxdma_device::install_read_handler(int index, read_delegate p_fn_dma_read)
{
- m_channel[ index ].fn_read = p_fn_dma_read;
+ m_channel[index].fn_read = p_fn_dma_read;
}
-void psxdma_device::install_write_handler( int index, write_delegate p_fn_dma_write )
+void psxdma_device::install_write_handler(int index, write_delegate p_fn_dma_write)
{
- m_channel[ index ].fn_write = p_fn_dma_write;
+ m_channel[index].fn_write = p_fn_dma_write;
}
-WRITE32_MEMBER( psxdma_device::write )
+void psxdma_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
{
int index = offset / 4;
- psx_dma_channel *dma = &m_channel[ index ];
+ psx_dma_channel *dma = &m_channel[index];
- if( index < 7 )
+ if (index < 7)
{
- switch( offset % 4 )
+ switch (offset % 4)
{
case 0:
- verboselog( *this, 2, "dmabase( %d ) = %08x\n", index, data );
+ LOGWRITE("%s dmabase( %d ) = %08x\n", machine().describe_context(), index, data);
dma->n_base = data;
break;
+
case 1:
- verboselog( *this, 2, "dmablockcontrol( %d ) = %08x\n", index, data );
+ LOGWRITE("%s dmablockcontrol( %d ) = %08x\n", machine().describe_context(), index, data);
dma->n_blockcontrol = data;
break;
+
case 2:
- verboselog( *this, 2, "dmachannelcontrol( %d ) = %08x\n", index, data );
+ case 3:
+ LOGWRITE("%s dmachannelcontrol( %d ) = %08x\n", machine().describe_context(), index, data);
dma->n_channelcontrol = data;
- if( ( dma->n_channelcontrol & ( 1L << 0x18 ) ) != 0 && ( m_dpcp & ( 1 << ( 3 + ( index * 4 ) ) ) ) != 0 )
+
+ if ((dma->n_channelcontrol & (1L << 0x18)) != 0 && (m_dpcp & (1 << (3 + (index * 4)))) != 0)
{
int32_t n_size;
uint32_t n_address;
@@ -240,185 +244,177 @@ WRITE32_MEMBER( psxdma_device::write )
n_adrmask = m_ramsize - 1;
- n_address = ( dma->n_base & n_adrmask );
+ n_address = (dma->n_base & n_adrmask);
n_size = dma->n_blockcontrol;
- if( ( dma->n_channelcontrol & 0x200 ) != 0 )
+ if ((dma->n_channelcontrol & 0x200) != 0)
{
uint32_t n_ba;
n_ba = dma->n_blockcontrol >> 16;
- if( n_ba == 0 )
- {
+ if (n_ba == 0)
n_ba = 0x10000;
- }
- n_size = ( n_size & 0xffff ) * n_ba;
+ n_size = (n_size & 0xffff) * n_ba;
}
- if( dma->n_channelcontrol == 0x01000000 &&
- !dma->fn_read.isnull() )
+ if (dma->n_channelcontrol == 0x01000000 &&
+ !dma->fn_read.isnull())
{
- verboselog( *this, 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
- dma->fn_read( m_ram, n_address, n_size );
- dma_finished( index );
+ LOGDMA("%s dma %d read block %08x %08x\n", machine().describe_context(), index, n_address, n_size);
+ dma->fn_read(m_ram, n_address, n_size);
+ dma_finished(index);
}
else if ((dma->n_channelcontrol & 0xffbffeff) == 0x11000000 && // CD DMA
- !dma->fn_read.isnull() )
+ !dma->fn_read.isnull())
{
- verboselog( *this, 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
+ LOGDMA("%s dma %d read block %08x %08x\n", machine().describe_context(), index, n_address, n_size);
// pSX's CD DMA size calc formula
- int oursize = (dma->n_blockcontrol>>16);
+ int oursize = (dma->n_blockcontrol >> 16);
oursize = (oursize > 1) ? oursize : 1;
- oursize *= (dma->n_blockcontrol&0xffff);
+ oursize *= (dma->n_blockcontrol & 0xffff);
- dma->fn_read( m_ram, n_address, oursize );
- dma_finished( index );
+ dma->fn_read(m_ram, n_address, oursize);
+ dma_finished(index);
}
- else if( dma->n_channelcontrol == 0x01000200 &&
- !dma->fn_read.isnull() )
+ else if (dma->n_channelcontrol == 0x01000200 &&
+ !dma->fn_read.isnull())
{
- verboselog( *this, 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
- dma->fn_read( m_ram, n_address, n_size );
- if( index == 1 )
- {
- dma_start_timer( index, 26000 );
- }
+ LOGDMA("%s dma %d read block %08x %08x\n", machine().describe_context(), index, n_address, n_size);
+ dma->fn_read(m_ram, n_address, n_size);
+ if (index == 1)
+ dma_start_timer(index, 26000);
else
- {
- dma_finished( index );
- }
+ dma_finished(index);
}
- else if( dma->n_channelcontrol == 0x01000201 &&
- !dma->fn_write.isnull() )
+ else if (dma->n_channelcontrol == 0x01000201 &&
+ !dma->fn_write.isnull())
{
- verboselog( *this, 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
- dma->fn_write( m_ram, n_address, n_size );
- dma_finished( index );
+ if (index == 4)
+ dma_start_timer(index, 24000);
+ else
+ dma_finished(index);
}
- else if( dma->n_channelcontrol == 0x11050100 &&
- !dma->fn_write.isnull() )
+ else if (dma->n_channelcontrol == 0x11050100 &&
+ !dma->fn_write.isnull())
{
/* todo: check this is a write not a read... */
- verboselog( *this, 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
- dma->fn_write( m_ram, n_address, n_size );
- dma_finished( index );
+ LOGDMA("%s dma %d write block %08x %08x\n", machine().describe_context(), index, n_address, n_size);
+ dma->fn_write(m_ram, n_address, n_size);
+ dma_finished(index);
}
- else if( dma->n_channelcontrol == 0x11150100 &&
- !dma->fn_write.isnull() )
+ else if (dma->n_channelcontrol == 0x11150100 &&
+ !dma->fn_write.isnull())
{
/* todo: check this is a write not a read... */
- verboselog( *this, 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
- dma->fn_write( m_ram, n_address, n_size );
- dma_finished( index );
+ LOGDMA("%s dma %d write block %08x %08x\n", machine().describe_context(), index, n_address, n_size);
+ dma->fn_write(m_ram, n_address, n_size);
+ dma_finished(index);
}
- else if( dma->n_channelcontrol == 0x01000401 &&
+ else if (dma->n_channelcontrol == 0x01000401 &&
index == 2 &&
- !dma->fn_write.isnull() )
+ !dma->fn_write.isnull())
{
- verboselog( *this, 1, "dma %d write linked list %08x\n",
- index, dma->n_base );
+ LOGDMA("%s dma %d write linked list %08x\n", machine().describe_context(), index, dma->n_base);
- dma_finished( index );
+ dma_finished(index);
}
- else if( dma->n_channelcontrol == 0x11000002 &&
- index == 6 )
+ else if (dma->n_channelcontrol == 0x11000002 &&
+ index == 6)
{
- verboselog( *this, 1, "dma 6 reverse clear %08x %08x\n",
- dma->n_base, dma->n_blockcontrol );
- if( n_size > 0 )
+ LOGDMA("%s dma 6 reverse clear %08x %08x\n", machine().describe_context(), dma->n_base, dma->n_blockcontrol);
+ if (n_size > 0)
{
n_size--;
- while( n_size > 0 )
+ while (n_size > 0)
{
- n_nextaddress = ( n_address - 4 ) & 0xffffff;
- m_ram[ n_address / 4 ] = n_nextaddress;
+ n_nextaddress = (n_address - 4) & 0xffffff;
+ m_ram[n_address / 4] = n_nextaddress;
n_address = n_nextaddress;
n_size--;
}
- m_ram[ n_address / 4 ] = 0xffffff;
+ m_ram[n_address / 4] = 0xffffff;
}
- dma_start_timer( index, 2150 );
+ dma_start_timer(index, 2150);
}
else
- {
- verboselog( *this, 1, "dma %d unknown mode %08x\n", index, dma->n_channelcontrol );
- }
- }
- else if( dma->n_channelcontrol != 0 )
- {
- verboselog( *this, 1, "psx_dma_w( %04x, %08x, %08x ) channel not enabled\n", offset, dma->n_channelcontrol, mem_mask );
+ LOGDMA("%s dma %d unknown mode %08x\n", machine().describe_context(), index, dma->n_channelcontrol);
}
- break;
- default:
- verboselog( *this, 1, "psx_dma_w( %04x, %08x, %08x ) Unknown dma channel register\n", offset, data, mem_mask );
+ else if (dma->n_channelcontrol != 0)
+ LOGDMA("%s psx_dma_w( %04x, %08x, %08x ) channel not enabled\n", machine().describe_context(), offset, dma->n_channelcontrol, mem_mask);
break;
}
}
else
{
- switch( offset % 4 )
+ switch (offset % 4)
{
case 0x0:
- verboselog( *this, 1, "psx_dma_w( %04x, %08x, %08x ) dpcp\n", offset, data, mem_mask );
- m_dpcp = ( m_dpcp & ~mem_mask ) | data;
+ LOGWRITE("%s dpcr_w(0x%08x)\n", machine().describe_context(), data);
+ m_dpcp = data;
break;
case 0x1:
+ {
+ uint32_t dicr = (m_dicr & 0x80000000) |
+ (m_dicr & ~data & 0x7f000000) |
+ (data & 0xff803f);
- m_dicr = ( m_dicr & ( 0x80000000 | ~mem_mask ) ) |
- ( m_dicr & ~data & 0x7f000000 & mem_mask ) |
- ( data & 0x00ffffff & mem_mask );
+ LOGWRITE("%s dicr_w(0x%08x) 0x%08x -> 0x%08x\n", machine().describe_context(), data, m_dicr, dicr);
+ m_dicr = dicr;
+ }
- if( ( m_dicr & 0x80000000 ) != 0 && ( m_dicr & 0x7f000000 ) == 0 )
+ if ((m_dicr & 0x80000000) != 0 && (m_dicr & 0x7f000000) == 0)
{
- verboselog( *this, 2, "dma interrupt cleared\n" );
+ LOGIRQ("%s dma interrupt cleared\n", machine().describe_context());
m_dicr &= ~0x80000000;
+ m_irq_handler(0);
}
-
- verboselog( *this, 1, "psx_dma_w( %04x, %08x, %08x ) dicr -> %08x\n", offset, data, mem_mask, m_dicr );
- break;
- default:
- verboselog( *this, 0, "psx_dma_w( %04x, %08x, %08x ) Unknown dma control register\n", offset, data, mem_mask );
break;
}
}
}
-READ32_MEMBER( psxdma_device::read )
+uint32_t psxdma_device::read(offs_t offset, uint32_t mem_mask)
{
int index = offset / 4;
- psx_dma_channel *dma = &m_channel[ index ];
+ psx_dma_channel *dma = &m_channel[index];
- if( index < 7 )
+ if (index < 7)
{
- switch( offset % 4 )
+ switch (offset % 4)
{
case 0:
- verboselog( *this, 1, "psx_dma_r dmabase[ %d ] ( %08x )\n", index, dma->n_base );
+ if (!machine().side_effects_disabled())
+ LOGREAD("%s psx_dma_r dmabase[ %d ] ( %08x )\n", machine().describe_context(), index, dma->n_base);
return dma->n_base;
+
case 1:
- verboselog( *this, 1, "psx_dma_r dmablockcontrol[ %d ] ( %08x )\n", index, dma->n_blockcontrol );
+ if (!machine().side_effects_disabled())
+ LOGREAD("%s psx_dma_r dmablockcontrol[ %d ] ( %08x )\n", machine().describe_context(), index, dma->n_blockcontrol);
return dma->n_blockcontrol;
+
case 2:
- verboselog( *this, 1, "psx_dma_r dmachannelcontrol[ %d ] ( %08x )\n", index, dma->n_channelcontrol );
+ case 3:
+ if (!machine().side_effects_disabled())
+ LOGREAD("%s psx_dma_r dmachannelcontrol[ %d ] ( %08x )\n", machine().describe_context(), index, dma->n_channelcontrol);
return dma->n_channelcontrol;
- default:
- verboselog( *this, 0, "psx_dma_r( %08x, %08x ) Unknown dma channel register\n", offset, mem_mask );
- break;
}
}
else
{
- switch( offset % 4 )
+ switch (offset % 4)
{
case 0x0:
- verboselog( *this, 1, "psx_dma_r dpcp ( %08x )\n", m_dpcp );
+ if (!machine().side_effects_disabled())
+ LOGREAD("%s dpcr_r() 0x%08x\n", machine().describe_context(), m_dpcp);
return m_dpcp;
+
case 0x1:
- verboselog( *this, 1, "psx_dma_r dicr ( %08x )\n", m_dicr );
+ if (!machine().side_effects_disabled())
+ LOGREAD("%s dicr_r() 0x%08x\n", machine().describe_context(), m_dicr);
return m_dicr;
- default:
- verboselog( *this, 0, "psx_dma_r( %08x, %08x ) Unknown dma control register\n", offset, mem_mask );
- break;
}
}
+
return 0;
}
+
+DEFINE_DEVICE_TYPE(PSX_DMA, psxdma_device, "psxdma", "Sony PSX DMA")