mirror of
https://github.com/holub/mame
synced 2025-04-26 02:07:14 +03:00
"You have taken your first step into a larger world." ―Obi-Wan Kenobi
Converted PlayStation DMA to an internal device to the CPU core. DMA to external devices can be set in the machine config, the old calls are still there until the rest of the code is converted. [smf] The following MAME core changes have been required to allow internal devices to be configurable by the main machine config & to work with internal memory maps. device.machine_config_additions() are now processed as soon as the device is added, so sub devices can be configured straight away. replacing or removing a device removes any devices owned by the device being removed, as now they are added straight away. device_t::subdevice() uses the machine config device list instead of the machine to find the device as the machine is not created until after all the devices have been created. devices in an internal address map are assumed to be owned by the CPU, while devices in a standard address maps are assumed to be siblings of the CPU. A code review and regression test would be a good idea.
This commit is contained in:
parent
edd7394ca8
commit
d1b109625d
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -374,6 +374,8 @@ src/emu/cpu/pps4/pps4.h svneol=native#text/plain
|
||||
src/emu/cpu/pps4/pps4dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/psx/dismips.c svneol=native#text/plain
|
||||
src/emu/cpu/psx/dismips.mak svneol=native#text/plain
|
||||
src/emu/cpu/psx/dma.c svneol=native#text/plain
|
||||
src/emu/cpu/psx/dma.h svneol=native#text/plain
|
||||
src/emu/cpu/psx/gte.c svneol=native#text/plain
|
||||
src/emu/cpu/psx/gte.h svneol=native#text/plain
|
||||
src/emu/cpu/psx/psx.c svneol=native#text/plain
|
||||
|
@ -60,7 +60,7 @@ inline void map_handler_data::set_tag(const device_t &device, const char *tag)
|
||||
m_tag = device.owner()->tag();
|
||||
}
|
||||
else
|
||||
m_tag = device.siblingtag(m_derived_tag, tag);
|
||||
m_tag = device.subtag(m_derived_tag, tag);
|
||||
}
|
||||
|
||||
|
||||
@ -718,7 +718,7 @@ address_map::address_map(const device_t &device, address_spacenum spacenum)
|
||||
|
||||
// construct the standard map */
|
||||
if (memintf->address_map(spacenum) != NULL)
|
||||
(*memintf->address_map(spacenum))(*this, device);
|
||||
(*memintf->address_map(spacenum))(*this, *device.owner());
|
||||
|
||||
// append the default device map (last so it can be overridden) */
|
||||
if (spaceconfig->m_default_map != NULL)
|
||||
|
@ -885,17 +885,20 @@ $(CPUOBJ)/mips/mips3drc.o: $(CPUSRC)/mips/mips3drc.c \
|
||||
|
||||
ifneq ($(filter PSX,$(CPUS)),)
|
||||
OBJDIRS += $(CPUOBJ)/psx
|
||||
CPUOBJS += $(CPUOBJ)/psx/psx.o $(CPUOBJ)/psx/gte.o
|
||||
CPUOBJS += $(CPUOBJ)/psx/psx.o $(CPUOBJ)/psx/gte.o $(CPUOBJ)/psx/dma.o
|
||||
DASMOBJS += $(CPUOBJ)/psx/psxdasm.o
|
||||
endif
|
||||
|
||||
$(CPUOBJ)/psx/psx.o: $(CPUSRC)/psx/psx.c \
|
||||
$(CPUSRC)/psx/psx.h \
|
||||
$(CPUSRC)/psx/dma.h \
|
||||
$(CPUSRC)/psx/gte.h \
|
||||
|
||||
$(CPUOBJ)/psx/gte.o: $(CPUSRC)/psx/gte.c \
|
||||
$(CPUSRC)/psx/gte.h
|
||||
|
||||
$(CPUOBJ)/psx/dma.o: $(CPUSRC)/psx/dma.c \
|
||||
$(CPUSRC)/psx/dma.h
|
||||
|
||||
#-------------------------------------------------
|
||||
# Mitsubishi M37702 and M37710 (based on 65C816)
|
||||
|
428
src/emu/cpu/psx/dma.c
Normal file
428
src/emu/cpu/psx/dma.c
Normal file
@ -0,0 +1,428 @@
|
||||
/*
|
||||
* PlayStation DMA emulator
|
||||
*
|
||||
* Copyright 2003-2011 smf
|
||||
*
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "dma.h"
|
||||
#include "includes/psx.h"
|
||||
|
||||
#define VERBOSE_LEVEL ( 0 )
|
||||
|
||||
INLINE void ATTR_PRINTF(3,4) verboselog( running_machine& machine, 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( "%s: %s", machine.describe_context(), buf );
|
||||
}
|
||||
}
|
||||
|
||||
const device_type PSX_DMA = &device_creator<psxdma_device>;
|
||||
|
||||
psxdma_device::psxdma_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, PSX_DMA, "PSX DMA", tag, owner, clock)
|
||||
{
|
||||
for( int index = 0; index < 7; index++ )
|
||||
{
|
||||
psx_dma_channel *dma = &channel[ index ];
|
||||
|
||||
dma->fn_read = NULL;
|
||||
dma->fn_write = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void psxdma_device::device_reset()
|
||||
{
|
||||
int n;
|
||||
|
||||
n_dpcp = 0;
|
||||
n_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++ )
|
||||
{
|
||||
dma_timer_adjust( n );
|
||||
}
|
||||
}
|
||||
|
||||
void psxdma_device::device_start()
|
||||
{
|
||||
for( int index = 0; index < 7; index++ )
|
||||
{
|
||||
psx_dma_channel *dma = &channel[ index ];
|
||||
|
||||
dma->timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(psxdma_device::dma_finished_callback), this));
|
||||
|
||||
machine().save().save_item( "psxdma", tag(), index, NAME(dma->n_base) );
|
||||
machine().save().save_item( "psxdma", tag(), index, NAME(dma->n_blockcontrol) );
|
||||
machine().save().save_item( "psxdma", tag(), index, NAME(dma->n_channelcontrol) );
|
||||
machine().save().save_item( "psxdma", tag(), index, NAME(dma->n_ticks) );
|
||||
machine().save().save_item( "psxdma", tag(), index, NAME(dma->b_running) );
|
||||
}
|
||||
|
||||
save_item( NAME(n_dpcp) );
|
||||
save_item( NAME(n_dicr) );
|
||||
}
|
||||
|
||||
void psxdma_device::dma_start_timer( int index, UINT32 n_ticks )
|
||||
{
|
||||
psx_dma_channel *dma = &channel[ 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 )
|
||||
{
|
||||
psx_dma_channel *dma = &channel[ index ];
|
||||
|
||||
dma->timer->adjust( attotime::never);
|
||||
dma->b_running = 0;
|
||||
}
|
||||
|
||||
void psxdma_device::dma_timer_adjust( int index )
|
||||
{
|
||||
psx_dma_channel *dma = &channel[ index ];
|
||||
|
||||
if( dma->b_running )
|
||||
{
|
||||
dma_start_timer( index, dma->n_ticks );
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_stop_timer( index );
|
||||
}
|
||||
}
|
||||
|
||||
void psxdma_device::dma_interrupt_update()
|
||||
{
|
||||
int n_int;
|
||||
int n_mask;
|
||||
|
||||
n_int = ( n_dicr >> 24 ) & 0x7f;
|
||||
n_mask = ( n_dicr >> 16 ) & 0xff;
|
||||
|
||||
if( ( n_mask & 0x80 ) != 0 && ( n_int & n_mask ) != 0 )
|
||||
{
|
||||
verboselog( machine(), 2, "dma_interrupt_update( %02x, %02x ) interrupt triggered\n", n_int, n_mask );
|
||||
n_dicr |= 0x80000000;
|
||||
psx_irq_set( machine(), PSX_IRQ_DMA );
|
||||
}
|
||||
else if( n_int != 0 )
|
||||
{
|
||||
verboselog( machine(), 2, "dma_interrupt_update( %02x, %02x ) interrupt not enabled\n", n_int, n_mask );
|
||||
}
|
||||
n_dicr &= 0x00ffffff | ( n_dicr << 8 );
|
||||
}
|
||||
|
||||
void psxdma_device::dma_finished( int index )
|
||||
{
|
||||
psx_machine *p_psx = machine().driver_data<psx_state>()->m_p_psx;
|
||||
|
||||
UINT32 *p_n_psxram = p_psx->p_n_psxram;
|
||||
psx_dma_channel *dma = &channel[ index ];
|
||||
|
||||
if( dma->n_channelcontrol == 0x01000401 && index == 2 )
|
||||
{
|
||||
UINT32 n_size;
|
||||
UINT32 n_total;
|
||||
UINT32 n_address = ( dma->n_base & 0xffffff );
|
||||
UINT32 n_adrmask = p_psx->n_psxramsize - 1;
|
||||
UINT32 n_nextaddress;
|
||||
|
||||
if( n_address != 0xffffff )
|
||||
{
|
||||
n_total = 0;
|
||||
for( ;; )
|
||||
{
|
||||
if( n_address == 0xffffff )
|
||||
{
|
||||
dma->n_base = n_address;
|
||||
dma_start_timer( index, 19000 );
|
||||
return;
|
||||
}
|
||||
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 );
|
||||
return;
|
||||
}
|
||||
n_address &= n_adrmask;
|
||||
n_nextaddress = p_n_psxram[ n_address / 4 ];
|
||||
n_size = n_nextaddress >> 24;
|
||||
(*dma->fn_write)( machine(), n_address + 4, n_size );
|
||||
//FIXME:
|
||||
// The following conditions will cause an endless loop.
|
||||
// If stopping the transfer is correct I cannot judge
|
||||
// The patch is meant as a hint for somebody who knows
|
||||
// the hardware.
|
||||
// Mametesters.org: psyforce0105u5red, raystorm0111u1red
|
||||
if ((n_nextaddress & 0xffffff) != 0xffffff)
|
||||
if (n_address == p_n_psxram[ (n_nextaddress & 0xffffff) / 4])
|
||||
break;
|
||||
if (n_address == (n_nextaddress & 0xffffff) )
|
||||
break;
|
||||
n_address = ( n_nextaddress & 0xffffff );
|
||||
|
||||
n_total += ( n_size + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dma->n_channelcontrol &= ~( ( 1L << 0x18 ) | ( 1L << 0x1c ) );
|
||||
|
||||
n_dicr |= 1 << ( 24 + index );
|
||||
dma_interrupt_update();
|
||||
dma_stop_timer( index );
|
||||
}
|
||||
|
||||
void psxdma_device::dma_finished_callback(void *ptr, int param)
|
||||
{
|
||||
dma_finished(param);
|
||||
}
|
||||
|
||||
void psxdma_device::install_read_handler( int index, psx_dma_read_handler p_fn_dma_read )
|
||||
{
|
||||
channel[ index ].fn_read = p_fn_dma_read;
|
||||
}
|
||||
|
||||
void psxdma_device::install_write_handler( int index, psx_dma_read_handler p_fn_dma_write )
|
||||
{
|
||||
channel[ index ].fn_write = p_fn_dma_write;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( psxdma_device::write )
|
||||
{
|
||||
psx_machine *p_psx = machine().driver_data<psx_state>()->m_p_psx;
|
||||
|
||||
UINT32 *p_n_psxram = p_psx->p_n_psxram;
|
||||
int index = offset / 4;
|
||||
psx_dma_channel *dma = &channel[ index ];
|
||||
|
||||
if( index < 7 )
|
||||
{
|
||||
switch( offset % 4 )
|
||||
{
|
||||
case 0:
|
||||
verboselog( machine(), 2, "dmabase( %d ) = %08x\n", index, data );
|
||||
dma->n_base = data;
|
||||
break;
|
||||
case 1:
|
||||
verboselog( machine(), 2, "dmablockcontrol( %d ) = %08x\n", index, data );
|
||||
dma->n_blockcontrol = data;
|
||||
break;
|
||||
case 2:
|
||||
verboselog( machine(), 2, "dmachannelcontrol( %d ) = %08x\n", index, data );
|
||||
dma->n_channelcontrol = data;
|
||||
if( ( dma->n_channelcontrol & ( 1L << 0x18 ) ) != 0 && ( n_dpcp & ( 1 << ( 3 + ( index * 4 ) ) ) ) != 0 )
|
||||
{
|
||||
INT32 n_size;
|
||||
UINT32 n_address;
|
||||
UINT32 n_nextaddress;
|
||||
UINT32 n_adrmask;
|
||||
|
||||
n_adrmask = p_psx->n_psxramsize - 1;
|
||||
|
||||
n_address = ( dma->n_base & n_adrmask );
|
||||
n_size = dma->n_blockcontrol;
|
||||
if( ( dma->n_channelcontrol & 0x200 ) != 0 )
|
||||
{
|
||||
UINT32 n_ba;
|
||||
n_ba = dma->n_blockcontrol >> 16;
|
||||
if( n_ba == 0 )
|
||||
{
|
||||
n_ba = 0x10000;
|
||||
}
|
||||
n_size = ( n_size & 0xffff ) * n_ba;
|
||||
}
|
||||
|
||||
if( dma->n_channelcontrol == 0x01000000 &&
|
||||
dma->fn_read != NULL )
|
||||
{
|
||||
verboselog( machine(), 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
|
||||
(*dma->fn_read)( machine(), n_address, n_size );
|
||||
dma_finished( index );
|
||||
}
|
||||
else if (dma->n_channelcontrol == 0x11000000 && // CD DMA
|
||||
dma->fn_read != NULL )
|
||||
{
|
||||
verboselog( machine(), 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
|
||||
|
||||
// pSX's CD DMA size calc formula
|
||||
int oursize = (dma->n_blockcontrol>>16);
|
||||
oursize = (oursize > 1) ? oursize : 1;
|
||||
oursize *= (dma->n_blockcontrol&0xffff);
|
||||
|
||||
(*dma->fn_read)( machine(), n_address, oursize );
|
||||
dma_finished( index );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x01000200 &&
|
||||
dma->fn_read != NULL )
|
||||
{
|
||||
verboselog( machine(), 1, "dma %d read block %08x %08x\n", index, n_address, n_size );
|
||||
(*dma->fn_read)( machine(), n_address, n_size );
|
||||
if( index == 1 )
|
||||
{
|
||||
dma_start_timer( index, 26000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_finished( index );
|
||||
}
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x01000201 &&
|
||||
dma->fn_write != NULL )
|
||||
{
|
||||
verboselog( machine(), 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
|
||||
(*dma->fn_write)( machine(), n_address, n_size );
|
||||
dma_finished( index );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x11050100 &&
|
||||
dma->fn_write != NULL )
|
||||
{
|
||||
/* todo: check this is a write not a read... */
|
||||
verboselog( machine(), 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
|
||||
(*dma->fn_write)( machine(), n_address, n_size );
|
||||
dma_finished( index );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x11150100 &&
|
||||
dma->fn_write != NULL )
|
||||
{
|
||||
/* todo: check this is a write not a read... */
|
||||
verboselog( machine(), 1, "dma %d write block %08x %08x\n", index, n_address, n_size );
|
||||
(*dma->fn_write)( machine(), n_address, n_size );
|
||||
dma_finished( index );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x01000401 &&
|
||||
index == 2 &&
|
||||
dma->fn_write != NULL )
|
||||
{
|
||||
verboselog( machine(), 1, "dma %d write linked list %08x\n",
|
||||
index, dma->n_base );
|
||||
|
||||
dma_finished( index );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x11000002 &&
|
||||
index == 6 )
|
||||
{
|
||||
verboselog( machine(), 1, "dma 6 reverse clear %08x %08x\n",
|
||||
dma->n_base, dma->n_blockcontrol );
|
||||
if( n_size > 0 )
|
||||
{
|
||||
n_size--;
|
||||
while( n_size > 0 )
|
||||
{
|
||||
n_nextaddress = ( n_address - 4 ) & 0xffffff;
|
||||
p_n_psxram[ n_address / 4 ] = n_nextaddress;
|
||||
n_address = n_nextaddress;
|
||||
n_size--;
|
||||
}
|
||||
p_n_psxram[ n_address / 4 ] = 0xffffff;
|
||||
}
|
||||
dma_start_timer( index, 2150 );
|
||||
}
|
||||
else
|
||||
{
|
||||
verboselog( machine(), 1, "dma %d unknown mode %08x\n", index, dma->n_channelcontrol );
|
||||
}
|
||||
}
|
||||
else if( dma->n_channelcontrol != 0 )
|
||||
{
|
||||
verboselog( machine(), 1, "psx_dma_w( %04x, %08x, %08x ) channel not enabled\n", offset, dma->n_channelcontrol, mem_mask );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
verboselog( machine(), 1, "psx_dma_w( %04x, %08x, %08x ) Unknown dma channel register\n", offset, data, mem_mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( offset % 4 )
|
||||
{
|
||||
case 0x0:
|
||||
verboselog( machine(), 1, "psx_dma_w( %04x, %08x, %08x ) dpcp\n", offset, data, mem_mask );
|
||||
n_dpcp = ( n_dpcp & ~mem_mask ) | data;
|
||||
break;
|
||||
case 0x1:
|
||||
|
||||
n_dicr = ( n_dicr & ( 0x80000000 | ~mem_mask ) ) |
|
||||
( n_dicr & ~data & 0x7f000000 & mem_mask ) |
|
||||
( data & 0x00ffffff & mem_mask );
|
||||
|
||||
if( ( n_dicr & 0x80000000 ) != 0 && ( n_dicr & 0x7f000000 ) == 0 )
|
||||
{
|
||||
verboselog( machine(), 2, "dma interrupt cleared\n" );
|
||||
n_dicr &= ~0x80000000;
|
||||
}
|
||||
|
||||
verboselog( machine(), 1, "psx_dma_w( %04x, %08x, %08x ) dicr -> %08x\n", offset, data, mem_mask, n_dicr );
|
||||
break;
|
||||
default:
|
||||
verboselog( machine(), 0, "psx_dma_w( %04x, %08x, %08x ) Unknown dma control register\n", offset, data, mem_mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
READ32_MEMBER( psxdma_device::read )
|
||||
{
|
||||
int index = offset / 4;
|
||||
psx_dma_channel *dma = &channel[ index ];
|
||||
|
||||
if( index < 7 )
|
||||
{
|
||||
switch( offset % 4 )
|
||||
{
|
||||
case 0:
|
||||
verboselog( machine(), 1, "psx_dma_r dmabase[ %d ] ( %08x )\n", index, dma->n_base );
|
||||
return dma->n_base;
|
||||
case 1:
|
||||
verboselog( machine(), 1, "psx_dma_r dmablockcontrol[ %d ] ( %08x )\n", index, dma->n_blockcontrol );
|
||||
return dma->n_blockcontrol;
|
||||
case 2:
|
||||
verboselog( machine(), 1, "psx_dma_r dmachannelcontrol[ %d ] ( %08x )\n", index, dma->n_channelcontrol );
|
||||
return dma->n_channelcontrol;
|
||||
default:
|
||||
verboselog( machine(), 0, "psx_dma_r( %08x, %08x ) Unknown dma channel register\n", offset, mem_mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( offset % 4 )
|
||||
{
|
||||
case 0x0:
|
||||
verboselog( machine(), 1, "psx_dma_r dpcp ( %08x )\n", n_dpcp );
|
||||
return n_dpcp;
|
||||
case 0x1:
|
||||
verboselog( machine(), 1, "psx_dma_r dicr ( %08x )\n", n_dicr );
|
||||
return n_dicr;
|
||||
default:
|
||||
verboselog( machine(), 0, "psx_dma_r( %08x, %08x ) Unknown dma control register\n", offset, mem_mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
63
src/emu/cpu/psx/dma.h
Normal file
63
src/emu/cpu/psx/dma.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* PlayStation DMA emulator
|
||||
*
|
||||
* Copyright 2003-2011 smf
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(PSXDMA_H)
|
||||
|
||||
#define PSXDMA_H (1)
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
extern const device_type PSX_DMA;
|
||||
|
||||
typedef void ( *psx_dma_read_handler )( running_machine &, UINT32, INT32 );
|
||||
typedef void ( *psx_dma_write_handler )( running_machine &, UINT32, INT32 );
|
||||
|
||||
typedef struct _psx_dma_channel psx_dma_channel;
|
||||
struct _psx_dma_channel
|
||||
{
|
||||
UINT32 n_base;
|
||||
UINT32 n_blockcontrol;
|
||||
UINT32 n_channelcontrol;
|
||||
emu_timer *timer;
|
||||
psx_dma_read_handler fn_read;
|
||||
psx_dma_write_handler fn_write;
|
||||
UINT32 n_ticks;
|
||||
UINT32 b_running;
|
||||
};
|
||||
|
||||
class psxdma_device : public device_t
|
||||
{
|
||||
public:
|
||||
psxdma_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
void install_read_handler( int n_channel, psx_dma_read_handler p_fn_dma_read );
|
||||
void install_write_handler( int n_channel, psx_dma_read_handler p_fn_dma_write );
|
||||
|
||||
WRITE32_MEMBER( write );
|
||||
READ32_MEMBER( read );
|
||||
|
||||
protected:
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_post_load();
|
||||
|
||||
private:
|
||||
void dma_start_timer( int n_channel, UINT32 n_ticks );
|
||||
void dma_stop_timer( int n_channel );
|
||||
void dma_timer_adjust( int n_channel );
|
||||
void dma_interrupt_update();
|
||||
void dma_finished( int n_channel );
|
||||
void dma_finished_callback(void *ptr, int param);
|
||||
void write( offs_t offset, UINT32 data, UINT32 mem_mask );
|
||||
UINT32 read( offs_t offset, UINT32 mem_mask );
|
||||
|
||||
psx_dma_channel channel[7];
|
||||
UINT32 n_dpcp;
|
||||
UINT32 n_dicr;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Geometry Transformation Engine
|
||||
* PlayStation Geometry Transformation Engine emulator
|
||||
*
|
||||
* Copyright 2003-2011 smf
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Geometry Transformation Engine
|
||||
* PlayStation Geometry Transformation Engine emulator
|
||||
*
|
||||
* Copyright 2003-2011 smf
|
||||
*
|
||||
@ -9,10 +9,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "emu.h"
|
||||
#ifndef __PSXGTE_H__
|
||||
#define __PSXGTE_H__
|
||||
|
||||
#ifndef __GTE_H__
|
||||
#define __GTE_H__
|
||||
#include "emu.h"
|
||||
|
||||
#define GTE_OP( op ) ( ( op >> 20 ) & 31 )
|
||||
#define GTE_SF( op ) ( ( op >> 19 ) & 1 )
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* PlayStation CPU emulator by smf
|
||||
* PlayStation CPU emulator
|
||||
*
|
||||
* Licensed to the MAME Team for distribution under the MAME license.
|
||||
* Copyright 2003-2011 smf
|
||||
*
|
||||
* Known chip id's
|
||||
* CXD8530AQ
|
||||
@ -64,6 +64,7 @@
|
||||
#include "emu.h"
|
||||
#include "debugger.h"
|
||||
#include "psx.h"
|
||||
#include "dma.h"
|
||||
#include "includes/psx.h"
|
||||
#include "sound/spu.h"
|
||||
|
||||
@ -186,33 +187,23 @@ static const UINT32 mtc0_writemask[]=
|
||||
0x00000000 /* PRID */
|
||||
};
|
||||
|
||||
static READ32_DEVICE_HANDLER( psx_berr_r )
|
||||
READ32_MEMBER( psxcpu_device::berr_r )
|
||||
{
|
||||
downcast<psxcpu_device *>(device)->set_berr();
|
||||
m_berr = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static WRITE32_DEVICE_HANDLER( psx_berr_w )
|
||||
WRITE32_MEMBER( psxcpu_device::berr_w )
|
||||
{
|
||||
downcast<psxcpu_device *>(device)->set_berr();
|
||||
m_berr = 1;
|
||||
}
|
||||
|
||||
static READ32_DEVICE_HANDLER( psx_biu_r )
|
||||
{
|
||||
return downcast<psxcpu_device *>(device)->get_biu();
|
||||
}
|
||||
|
||||
static WRITE32_DEVICE_HANDLER( psx_biu_w )
|
||||
{
|
||||
downcast<psxcpu_device *>(device)->set_biu( data, mem_mask );
|
||||
}
|
||||
|
||||
UINT32 psxcpu_device::get_biu()
|
||||
READ32_MEMBER( psxcpu_device::biu_r )
|
||||
{
|
||||
return m_biu;
|
||||
}
|
||||
|
||||
void psxcpu_device::set_biu( UINT32 data, UINT32 mem_mask )
|
||||
WRITE32_MEMBER( psxcpu_device::biu_w )
|
||||
{
|
||||
UINT32 old = m_biu;
|
||||
|
||||
@ -1244,20 +1235,15 @@ void psxcpu_device::update_address_masks()
|
||||
}
|
||||
}
|
||||
|
||||
void psxcpu_device::set_berr()
|
||||
{
|
||||
m_berr = 1;
|
||||
}
|
||||
|
||||
void psxcpu_device::update_scratchpad()
|
||||
{
|
||||
if( ( m_biu & BIU_RAM ) == 0 )
|
||||
{
|
||||
m_program->install_legacy_readwrite_handler( *this, 0x1f800000, 0x1f8003ff, FUNC(psx_berr_r), FUNC(psx_berr_w) );
|
||||
m_program->install_readwrite_handler( 0x1f800000, 0x1f8003ff, read32_delegate( FUNC(psxcpu_device::berr_r), this ), write32_delegate( FUNC(psxcpu_device::berr_w), this ) );
|
||||
}
|
||||
else if( ( m_biu & BIU_DS ) == 0 )
|
||||
{
|
||||
m_program->install_legacy_read_handler( *this, 0x1f800000, 0x1f8003ff, FUNC(psx_berr_r) );
|
||||
m_program->install_read_handler( 0x1f800000, 0x1f8003ff, read32_delegate( FUNC(psxcpu_device::berr_r), this ) );
|
||||
m_program->nop_write( 0x1f800000, 0x1f8003ff);
|
||||
}
|
||||
else
|
||||
@ -1534,50 +1520,50 @@ int psxcpu_device::store_data_address_breakpoint( UINT32 address )
|
||||
|
||||
// On-board RAM and peripherals
|
||||
static ADDRESS_MAP_START( psxcpu_internal_map, AS_PROGRAM, 32 )
|
||||
AM_RANGE(0x00800000, 0x1effffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0x00800000, 0x1effffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0x1f800000, 0x1f8003ff) AM_NOP /* scratchpad */
|
||||
AM_RANGE(0x1f800400, 0x1f800fff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0x1f800400, 0x1f800fff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0x1f801004, 0x1f80101f) AM_RAM
|
||||
AM_RANGE(0x1f801020, 0x1f801023) AM_READWRITE(psx_com_delay_r, psx_com_delay_w)
|
||||
AM_RANGE(0x1f801024, 0x1f80102f) AM_RAM
|
||||
AM_RANGE(0x1f801040, 0x1f80105f) AM_READWRITE(psx_sio_r, psx_sio_w)
|
||||
AM_RANGE(0x1f801060, 0x1f80106f) AM_RAM
|
||||
AM_RANGE(0x1f801070, 0x1f801077) AM_READWRITE(psx_irq_r, psx_irq_w)
|
||||
AM_RANGE(0x1f801080, 0x1f8010ff) AM_READWRITE(psx_dma_r, psx_dma_w)
|
||||
AM_RANGE(0x1f801080, 0x1f8010ff) AM_DEVREADWRITE_MODERN("dma", psxdma_device, read, write)
|
||||
AM_RANGE(0x1f801100, 0x1f80112f) AM_READWRITE(psx_counter_r, psx_counter_w)
|
||||
AM_RANGE(0x1f801810, 0x1f801817) AM_READWRITE(psx_gpu_r, psx_gpu_w)
|
||||
AM_RANGE(0x1f801820, 0x1f801827) AM_READWRITE(psx_mdec_r, psx_mdec_w)
|
||||
AM_RANGE(0x1f801c00, 0x1f801dff) AM_READWRITE16(spu_r, spu_w, 0xffffffff)
|
||||
AM_RANGE(0x1f802020, 0x1f802033) AM_RAM /* ?? */
|
||||
AM_RANGE(0x1f802040, 0x1f802043) AM_WRITENOP
|
||||
AM_RANGE(0x20000000, 0x7fffffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0x80800000, 0x9effffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0xa0800000, 0xbeffffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0xc0000000, 0xfffdffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0xfffe0130, 0xfffe0133) AM_DEVREADWRITE(DEVICE_SELF,psx_biu_r, psx_biu_w)
|
||||
AM_RANGE(0x20000000, 0x7fffffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0x80800000, 0x9effffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0xa0800000, 0xbeffffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0xc0000000, 0xfffdffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0xfffe0130, 0xfffe0133) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, biu_r, biu_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( cxd8661r_internal_map, AS_PROGRAM, 32 )
|
||||
AM_RANGE(0x01000000, 0x1effffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0x01000000, 0x1effffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0x1f800000, 0x1f8003ff) AM_NOP /* scratchpad */
|
||||
AM_RANGE(0x1f800400, 0x1f800fff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0x1f800400, 0x1f800fff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0x1f801004, 0x1f80101f) AM_RAM
|
||||
AM_RANGE(0x1f801020, 0x1f801023) AM_READWRITE(psx_com_delay_r, psx_com_delay_w)
|
||||
AM_RANGE(0x1f801024, 0x1f80102f) AM_RAM
|
||||
AM_RANGE(0x1f801040, 0x1f80105f) AM_READWRITE(psx_sio_r, psx_sio_w)
|
||||
AM_RANGE(0x1f801060, 0x1f80106f) AM_RAM
|
||||
AM_RANGE(0x1f801070, 0x1f801077) AM_READWRITE(psx_irq_r, psx_irq_w)
|
||||
AM_RANGE(0x1f801080, 0x1f8010ff) AM_READWRITE(psx_dma_r, psx_dma_w)
|
||||
AM_RANGE(0x1f801080, 0x1f8010ff) AM_DEVREADWRITE_MODERN("dma", psxdma_device, read, write)
|
||||
AM_RANGE(0x1f801100, 0x1f80112f) AM_READWRITE(psx_counter_r, psx_counter_w)
|
||||
AM_RANGE(0x1f801810, 0x1f801817) AM_READWRITE(psx_gpu_r, psx_gpu_w)
|
||||
AM_RANGE(0x1f801820, 0x1f801827) AM_READWRITE(psx_mdec_r, psx_mdec_w)
|
||||
AM_RANGE(0x1f801c00, 0x1f801dff) AM_READWRITE16(spu_r, spu_w, 0xffffffff)
|
||||
AM_RANGE(0x1f802040, 0x1f802043) AM_WRITENOP
|
||||
AM_RANGE(0x20000000, 0x7fffffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0x81000000, 0x9effffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0xa1000000, 0xbeffffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0xc0000000, 0xfffdffff) AM_DEVREADWRITE(DEVICE_SELF,psx_berr_r, psx_berr_w)
|
||||
AM_RANGE(0xfffe0130, 0xfffe0133) AM_DEVREADWRITE(DEVICE_SELF,psx_biu_r, psx_biu_w)
|
||||
AM_RANGE(0x20000000, 0x7fffffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0x81000000, 0x9effffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0xa1000000, 0xbeffffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0xc0000000, 0xfffdffff) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, berr_r, berr_w)
|
||||
AM_RANGE(0xfffe0130, 0xfffe0133) AM_DEVREADWRITE_MODERN(DEVICE_SELF, psxcpu_device, biu_r, biu_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
@ -3157,3 +3143,27 @@ UINT32 psxcpu_device::getcp3cr( int reg )
|
||||
void psxcpu_device::setcp3cr( int reg, UINT32 value )
|
||||
{
|
||||
}
|
||||
|
||||
void psxcpu_device::install_dma_read_handler( device_t &device, int channel, psx_dma_read_handler handler )
|
||||
{
|
||||
(downcast<psxdma_device*>(device.subdevice("dma")))->install_read_handler( channel, handler );
|
||||
}
|
||||
|
||||
void psxcpu_device::install_dma_write_handler( device_t &device, int channel, psx_dma_write_handler handler )
|
||||
{
|
||||
(downcast<psxdma_device*>(device.subdevice("dma")))->install_write_handler( channel, handler );
|
||||
}
|
||||
|
||||
static MACHINE_CONFIG_FRAGMENT( psx )
|
||||
MCFG_DEVICE_ADD("dma", PSX_DMA, 0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
//-------------------------------------------------
|
||||
// machine_config_additions - return a pointer to
|
||||
// the device's machine fragment
|
||||
//-------------------------------------------------
|
||||
|
||||
machine_config_constructor psxcpu_device::device_mconfig_additions() const
|
||||
{
|
||||
return MACHINE_CONFIG_NAME( psx );
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
/***************************************************************************
|
||||
|
||||
psx.h
|
||||
|
||||
Sony PlayStation CPU emulator.
|
||||
|
||||
***************************************************************************/
|
||||
/*
|
||||
* PlayStation CPU emulator
|
||||
*
|
||||
* Copyright 2003-2011 smf
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __PSXCPU_H__
|
||||
#define __PSXCPU_H__
|
||||
|
||||
#include "includes/psx.h"
|
||||
#include "gte.h"
|
||||
#include "dma.h"
|
||||
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
@ -102,8 +103,11 @@ enum
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
//#define MCFG_PSXCPU_CONFIG(_config)
|
||||
// psxcpu_device::static_set_config(*device, _config);
|
||||
#define MCFG_PSX_DMA_CHANNEL_READ( channel, handler ) \
|
||||
psxcpu_device::install_dma_read_handler( *device, channel, handler ); \
|
||||
|
||||
#define MCFG_PSX_DMA_CHANNEL_WRITE( channel, handler ) \
|
||||
psxcpu_device::install_dma_write_handler( *device, channel, handler ); \
|
||||
|
||||
|
||||
|
||||
@ -120,9 +124,13 @@ public:
|
||||
psxcpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// public interfaces
|
||||
void set_berr();
|
||||
void set_biu( UINT32 data, UINT32 mem_mask );
|
||||
UINT32 get_biu();
|
||||
WRITE32_MEMBER( biu_w );
|
||||
READ32_MEMBER( biu_r );
|
||||
WRITE32_MEMBER( berr_w );
|
||||
READ32_MEMBER( berr_r );
|
||||
|
||||
static void install_dma_read_handler( device_t &device, int channel, psx_dma_read_handler handler );
|
||||
static void install_dma_write_handler( device_t &device, int channel, psx_dma_write_handler handler );
|
||||
|
||||
protected:
|
||||
psxcpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map);
|
||||
@ -131,6 +139,7 @@ protected:
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_post_load();
|
||||
machine_config_constructor device_mconfig_additions() const;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual UINT32 execute_min_cycles() const { return 1; }
|
||||
|
@ -435,7 +435,7 @@ device_t *device_t::subdevice(const char *_tag) const
|
||||
|
||||
// build a fully-qualified name
|
||||
astring tempstring;
|
||||
return machine().device(subtag(tempstring, _tag));
|
||||
return mconfig().devicelist().find((const char *)subtag(tempstring, _tag));
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,15 +88,6 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options)
|
||||
throw emu_fatalerror("Machine configuration missing driver_device");
|
||||
driver_device::static_set_game(*root, gamedrv);
|
||||
|
||||
// process any device-specific machine configurations
|
||||
for (device_t *device = m_devicelist.first(); device != NULL; device = device->next())
|
||||
if (!device->configured())
|
||||
{
|
||||
machine_config_constructor additions = device->machine_config_additions();
|
||||
if (additions != NULL)
|
||||
(*additions)(*this, device);
|
||||
}
|
||||
|
||||
// then notify all devices that their configuration is complete
|
||||
for (device_t *device = m_devicelist.first(); device != NULL; device = device->next())
|
||||
if (!device->configured())
|
||||
@ -124,6 +115,43 @@ screen_device *machine_config::first_screen() const
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_subdevices - helper to add
|
||||
// devices owned by the device
|
||||
//-------------------------------------------------
|
||||
|
||||
void machine_config::device_add_subdevices(device_t *device)
|
||||
{
|
||||
machine_config_constructor additions = device->machine_config_additions();
|
||||
if (additions != NULL)
|
||||
(*additions)(*this, device);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_remove_subdevices - helper to remove
|
||||
// devices owned by the device
|
||||
//-------------------------------------------------
|
||||
|
||||
void machine_config::device_remove_subdevices(const device_t *device)
|
||||
{
|
||||
if (device != NULL)
|
||||
{
|
||||
device_t *sub_device = m_devicelist.first();
|
||||
while (sub_device != NULL)
|
||||
{
|
||||
device_t *next_device = sub_device->next();
|
||||
if (sub_device->owner() == device)
|
||||
{
|
||||
device_remove_subdevices(sub_device);
|
||||
m_devicelist.remove(sub_device->tag());
|
||||
}
|
||||
sub_device = next_device;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add - configuration helper to add a
|
||||
// new device
|
||||
@ -133,7 +161,9 @@ device_t *machine_config::device_add(device_t *owner, const char *tag, device_ty
|
||||
{
|
||||
astring tempstring;
|
||||
const char *fulltag = owner->subtag(tempstring, tag);
|
||||
return &m_devicelist.append(fulltag, *(*type)(*this, fulltag, owner, clock));
|
||||
device_t *device = &m_devicelist.append(fulltag, *(*type)(*this, fulltag, owner, clock));
|
||||
device_add_subdevices(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
@ -146,7 +176,10 @@ device_t *machine_config::device_replace(device_t *owner, const char *tag, devic
|
||||
{
|
||||
astring tempstring;
|
||||
const char *fulltag = owner->subtag(tempstring, tag);
|
||||
return &m_devicelist.replace_and_remove(fulltag, *(*type)(*this, fulltag, owner, clock));
|
||||
device_remove_subdevices(m_devicelist.find(fulltag));
|
||||
device_t *device = &m_devicelist.replace_and_remove(fulltag, *(*type)(*this, fulltag, owner, clock));
|
||||
device_add_subdevices(device);
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
@ -159,6 +192,7 @@ device_t *machine_config::device_remove(device_t *owner, const char *tag)
|
||||
{
|
||||
astring tempstring;
|
||||
const char *fulltag = owner->subtag(tempstring, tag);
|
||||
device_remove_subdevices(m_devicelist.find(fulltag));
|
||||
m_devicelist.remove(fulltag);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -157,6 +157,9 @@ public:
|
||||
device_t *device_find(device_t *owner, const char *tag);
|
||||
|
||||
private:
|
||||
void device_add_subdevices(device_t *device);
|
||||
void device_remove_subdevices(const device_t *device);
|
||||
|
||||
const game_driver & m_gamedrv;
|
||||
emu_options & m_options;
|
||||
device_list m_devicelist; // list of device configs
|
||||
|
@ -350,8 +350,6 @@ static MACHINE_START( konamigq )
|
||||
/* init the scsi controller and hook up it's DMA */
|
||||
am53cf96_init(machine, &scsi_intf);
|
||||
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(konamigq_exit), &machine));
|
||||
psx_dma_install_read_handler(machine, 5, scsi_dma_read);
|
||||
psx_dma_install_write_handler(machine, 5, scsi_dma_write);
|
||||
|
||||
state->save_pointer(NAME(state->m_p_n_pcmram), 0x380000);
|
||||
state->save_item(NAME(state->m_sndto000));
|
||||
@ -367,7 +365,9 @@ static MACHINE_RESET( konamigq )
|
||||
static MACHINE_CONFIG_START( konamigq, konamigq_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD( "maincpu", CXD8530BQ, XTAL_67_7376MHz )
|
||||
MCFG_CPU_PROGRAM_MAP( konamigq_map)
|
||||
MCFG_PSX_DMA_CHANNEL_READ( 5, scsi_dma_read )
|
||||
MCFG_PSX_DMA_CHANNEL_WRITE( 5, scsi_dma_write )
|
||||
MCFG_CPU_PROGRAM_MAP( konamigq_map )
|
||||
MCFG_CPU_VBLANK_INT("screen", psx_vblank)
|
||||
|
||||
MCFG_CPU_ADD( "soundcpu", M68000, 8000000 )
|
||||
|
@ -296,8 +296,6 @@ static DRIVER_INIT( konamigv )
|
||||
/* init the scsi controller and hook up it's DMA */
|
||||
am53cf96_init(machine, &scsi_intf);
|
||||
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(konamigv_exit), &machine));
|
||||
psx_dma_install_read_handler(machine, 5, scsi_dma_read);
|
||||
psx_dma_install_write_handler(machine, 5, scsi_dma_write);
|
||||
}
|
||||
|
||||
static MACHINE_START( konamigv )
|
||||
@ -331,7 +329,9 @@ static void spu_irq(device_t *device, UINT32 data)
|
||||
static MACHINE_CONFIG_START( konamigv, konamigv_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD( "maincpu", CXD8530BQ, XTAL_67_7376MHz )
|
||||
MCFG_CPU_PROGRAM_MAP( konamigv_map)
|
||||
MCFG_PSX_DMA_CHANNEL_READ( 5, scsi_dma_read )
|
||||
MCFG_PSX_DMA_CHANNEL_WRITE( 5, scsi_dma_write )
|
||||
MCFG_CPU_PROGRAM_MAP( konamigv_map )
|
||||
MCFG_CPU_VBLANK_INT("screen", psx_vblank)
|
||||
|
||||
MCFG_MACHINE_START( konamigv )
|
||||
|
@ -1265,8 +1265,6 @@ static DRIVER_INIT( konami573 )
|
||||
|
||||
psx_driver_init(machine);
|
||||
atapi_init(machine);
|
||||
psx_dma_install_read_handler(machine, 5, cdrom_dma_read);
|
||||
psx_dma_install_write_handler(machine, 5, cdrom_dma_write);
|
||||
|
||||
state->save_item( NAME(state->m_n_security_control) );
|
||||
|
||||
@ -2963,7 +2961,9 @@ static const adc083x_interface konami573_adc_interface = {
|
||||
static MACHINE_CONFIG_START( konami573, ksys573_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD( "maincpu", CXD8530CQ, XTAL_67_7376MHz )
|
||||
MCFG_CPU_PROGRAM_MAP( konami573_map)
|
||||
MCFG_PSX_DMA_CHANNEL_READ( 5, cdrom_dma_read )
|
||||
MCFG_PSX_DMA_CHANNEL_WRITE( 5, cdrom_dma_write )
|
||||
MCFG_CPU_PROGRAM_MAP( konami573_map )
|
||||
MCFG_CPU_VBLANK_INT("screen", sys573_vblank)
|
||||
|
||||
MCFG_MACHINE_RESET( konami573 )
|
||||
|
@ -1600,8 +1600,6 @@ static DRIVER_INIT( namcos12 )
|
||||
|
||||
psx_driver_init(machine);
|
||||
|
||||
psx_dma_install_read_handler( machine, 5, namcos12_rom_read );
|
||||
|
||||
memory_configure_bank(machine, "bank1", 0, machine.region( "user2" )->bytes() / 0x200000, machine.region( "user2" )->base(), 0x200000 );
|
||||
|
||||
state->m_s12_porta = 0;
|
||||
@ -1642,6 +1640,8 @@ static DRIVER_INIT( ghlpanic )
|
||||
static MACHINE_CONFIG_START( coh700, namcos12_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD( "maincpu", CXD8661R, XTAL_100MHz )
|
||||
MCFG_PSX_DMA_CHANNEL_READ( 5, namcos12_rom_read )
|
||||
|
||||
MCFG_CPU_PROGRAM_MAP( namcos12_map)
|
||||
MCFG_CPU_VBLANK_INT("screen", psx_vblank)
|
||||
|
||||
|
@ -848,8 +848,6 @@ static DRIVER_INIT( twinkle )
|
||||
{
|
||||
psx_driver_init(machine);
|
||||
am53cf96_init(machine, &scsi_intf);
|
||||
psx_dma_install_read_handler(machine, 5, scsi_dma_read);
|
||||
psx_dma_install_write_handler(machine, 5, scsi_dma_write);
|
||||
|
||||
device_t *i2cmem = machine.device("security");
|
||||
i2cmem_e0_write( i2cmem, 0 );
|
||||
@ -882,6 +880,8 @@ static const i2cmem_interface i2cmem_interface =
|
||||
static MACHINE_CONFIG_START( twinkle, twinkle_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD( "maincpu", CXD8530CQ, XTAL_67_7376MHz )
|
||||
MCFG_PSX_DMA_CHANNEL_READ( 5, scsi_dma_read )
|
||||
MCFG_PSX_DMA_CHANNEL_WRITE( 5, scsi_dma_write )
|
||||
MCFG_CPU_PROGRAM_MAP( main_map )
|
||||
MCFG_CPU_VBLANK_INT( "mainscreen", psx_vblank )
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#if !defined( PSX_H )
|
||||
|
||||
#include "cpu/psx/dma.h"
|
||||
|
||||
#define PSX_RC_STOP ( 0x01 )
|
||||
#define PSX_RC_RESET ( 0x04 ) /* guess */
|
||||
#define PSX_RC_COUNTTARGET ( 0x08 )
|
||||
@ -35,11 +37,108 @@
|
||||
#define PSX_SIO_IN_DSR ( 2 ) /* ACK */
|
||||
#define PSX_SIO_IN_CTS ( 4 )
|
||||
|
||||
typedef void ( *psx_dma_read_handler )( running_machine &, UINT32, INT32 );
|
||||
typedef void ( *psx_dma_write_handler )( running_machine &, UINT32, INT32 );
|
||||
typedef void ( *psx_sio_handler )( running_machine &, int );
|
||||
|
||||
#define DCTSIZE ( 8 )
|
||||
#define DCTSIZE2 ( DCTSIZE * DCTSIZE )
|
||||
|
||||
#define SIO_BUF_SIZE ( 8 )
|
||||
|
||||
#define SIO_STATUS_TX_RDY ( 1 << 0 )
|
||||
#define SIO_STATUS_RX_RDY ( 1 << 1 )
|
||||
#define SIO_STATUS_TX_EMPTY ( 1 << 2 )
|
||||
#define SIO_STATUS_OVERRUN ( 1 << 4 )
|
||||
#define SIO_STATUS_DSR ( 1 << 7 )
|
||||
#define SIO_STATUS_IRQ ( 1 << 9 )
|
||||
|
||||
#define SIO_CONTROL_TX_ENA ( 1 << 0 )
|
||||
#define SIO_CONTROL_IACK ( 1 << 4 )
|
||||
#define SIO_CONTROL_RESET ( 1 << 6 )
|
||||
#define SIO_CONTROL_TX_IENA ( 1 << 10 )
|
||||
#define SIO_CONTROL_RX_IENA ( 1 << 11 )
|
||||
#define SIO_CONTROL_DSR_IENA ( 1 << 12 )
|
||||
#define SIO_CONTROL_DTR ( 1 << 13 )
|
||||
|
||||
#define MDEC_COS_PRECALC_BITS ( 21 )
|
||||
|
||||
typedef struct _psx_root psx_root;
|
||||
struct _psx_root
|
||||
{
|
||||
emu_timer *timer;
|
||||
UINT16 n_count;
|
||||
UINT16 n_mode;
|
||||
UINT16 n_target;
|
||||
UINT64 n_start;
|
||||
};
|
||||
|
||||
typedef struct _psx_sio psx_sio;
|
||||
struct _psx_sio
|
||||
{
|
||||
UINT32 n_status;
|
||||
UINT32 n_mode;
|
||||
UINT32 n_control;
|
||||
UINT32 n_baud;
|
||||
UINT32 n_tx;
|
||||
UINT32 n_rx;
|
||||
UINT32 n_tx_prev;
|
||||
UINT32 n_rx_prev;
|
||||
UINT32 n_tx_data;
|
||||
UINT32 n_rx_data;
|
||||
UINT32 n_tx_shift;
|
||||
UINT32 n_rx_shift;
|
||||
UINT32 n_tx_bits;
|
||||
UINT32 n_rx_bits;
|
||||
|
||||
emu_timer *timer;
|
||||
psx_sio_handler fn_handler;
|
||||
};
|
||||
|
||||
typedef struct _psx_mdec psx_mdec;
|
||||
struct _psx_mdec
|
||||
{
|
||||
UINT32 n_decoded;
|
||||
UINT32 n_offset;
|
||||
UINT16 p_n_output[ 24 * 16 ];
|
||||
|
||||
INT32 p_n_quantize_y[ DCTSIZE2 ];
|
||||
INT32 p_n_quantize_uv[ DCTSIZE2 ];
|
||||
INT32 p_n_cos[ DCTSIZE2 ];
|
||||
INT32 p_n_cos_precalc[ DCTSIZE2 * DCTSIZE2 ];
|
||||
|
||||
UINT32 n_0_command;
|
||||
UINT32 n_0_address;
|
||||
UINT32 n_0_size;
|
||||
UINT32 n_1_command;
|
||||
UINT32 n_1_status;
|
||||
|
||||
UINT16 p_n_clamp8[ 256 * 3 ];
|
||||
UINT16 p_n_r5[ 256 * 3 ];
|
||||
UINT16 p_n_g5[ 256 * 3 ];
|
||||
UINT16 p_n_b5[ 256 * 3 ];
|
||||
|
||||
INT32 p_n_unpacked[ DCTSIZE2 * 6 * 2 ];
|
||||
};
|
||||
|
||||
typedef struct _psx_machine psx_machine;
|
||||
struct _psx_machine
|
||||
{
|
||||
running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
|
||||
|
||||
running_machine *m_machine;
|
||||
UINT32 *p_n_psxram;
|
||||
size_t n_psxramsize;
|
||||
|
||||
UINT32 n_com_delay;
|
||||
UINT32 n_irqdata;
|
||||
UINT32 n_irqmask;
|
||||
|
||||
psx_root root[3];
|
||||
|
||||
psx_sio sio[2];
|
||||
|
||||
psx_mdec mdec;
|
||||
};
|
||||
|
||||
typedef struct _psx_gpu psx_gpu;
|
||||
|
||||
class psx_state : public driver_device
|
||||
|
@ -12,124 +12,6 @@
|
||||
|
||||
#define VERBOSE_LEVEL ( 0 )
|
||||
|
||||
#define DCTSIZE ( 8 )
|
||||
#define DCTSIZE2 ( DCTSIZE * DCTSIZE )
|
||||
|
||||
#define SIO_BUF_SIZE ( 8 )
|
||||
|
||||
#define SIO_STATUS_TX_RDY ( 1 << 0 )
|
||||
#define SIO_STATUS_RX_RDY ( 1 << 1 )
|
||||
#define SIO_STATUS_TX_EMPTY ( 1 << 2 )
|
||||
#define SIO_STATUS_OVERRUN ( 1 << 4 )
|
||||
#define SIO_STATUS_DSR ( 1 << 7 )
|
||||
#define SIO_STATUS_IRQ ( 1 << 9 )
|
||||
|
||||
#define SIO_CONTROL_TX_ENA ( 1 << 0 )
|
||||
#define SIO_CONTROL_IACK ( 1 << 4 )
|
||||
#define SIO_CONTROL_RESET ( 1 << 6 )
|
||||
#define SIO_CONTROL_TX_IENA ( 1 << 10 )
|
||||
#define SIO_CONTROL_RX_IENA ( 1 << 11 )
|
||||
#define SIO_CONTROL_DSR_IENA ( 1 << 12 )
|
||||
#define SIO_CONTROL_DTR ( 1 << 13 )
|
||||
|
||||
#define MDEC_COS_PRECALC_BITS ( 21 )
|
||||
|
||||
|
||||
typedef struct _psx_dma_channel psx_dma_channel;
|
||||
struct _psx_dma_channel
|
||||
{
|
||||
UINT32 n_base;
|
||||
UINT32 n_blockcontrol;
|
||||
UINT32 n_channelcontrol;
|
||||
emu_timer *timer;
|
||||
psx_dma_read_handler fn_read;
|
||||
psx_dma_write_handler fn_write;
|
||||
UINT32 n_ticks;
|
||||
UINT32 b_running;
|
||||
};
|
||||
|
||||
typedef struct _psx_root psx_root;
|
||||
struct _psx_root
|
||||
{
|
||||
emu_timer *timer;
|
||||
UINT16 n_count;
|
||||
UINT16 n_mode;
|
||||
UINT16 n_target;
|
||||
UINT64 n_start;
|
||||
};
|
||||
|
||||
typedef struct _psx_sio psx_sio;
|
||||
struct _psx_sio
|
||||
{
|
||||
UINT32 n_status;
|
||||
UINT32 n_mode;
|
||||
UINT32 n_control;
|
||||
UINT32 n_baud;
|
||||
UINT32 n_tx;
|
||||
UINT32 n_rx;
|
||||
UINT32 n_tx_prev;
|
||||
UINT32 n_rx_prev;
|
||||
UINT32 n_tx_data;
|
||||
UINT32 n_rx_data;
|
||||
UINT32 n_tx_shift;
|
||||
UINT32 n_rx_shift;
|
||||
UINT32 n_tx_bits;
|
||||
UINT32 n_rx_bits;
|
||||
|
||||
emu_timer *timer;
|
||||
psx_sio_handler fn_handler;
|
||||
};
|
||||
|
||||
typedef struct _psx_mdec psx_mdec;
|
||||
struct _psx_mdec
|
||||
{
|
||||
UINT32 n_decoded;
|
||||
UINT32 n_offset;
|
||||
UINT16 p_n_output[ 24 * 16 ];
|
||||
|
||||
INT32 p_n_quantize_y[ DCTSIZE2 ];
|
||||
INT32 p_n_quantize_uv[ DCTSIZE2 ];
|
||||
INT32 p_n_cos[ DCTSIZE2 ];
|
||||
INT32 p_n_cos_precalc[ DCTSIZE2 * DCTSIZE2 ];
|
||||
|
||||
UINT32 n_0_command;
|
||||
UINT32 n_0_address;
|
||||
UINT32 n_0_size;
|
||||
UINT32 n_1_command;
|
||||
UINT32 n_1_status;
|
||||
|
||||
UINT16 p_n_clamp8[ 256 * 3 ];
|
||||
UINT16 p_n_r5[ 256 * 3 ];
|
||||
UINT16 p_n_g5[ 256 * 3 ];
|
||||
UINT16 p_n_b5[ 256 * 3 ];
|
||||
|
||||
INT32 p_n_unpacked[ DCTSIZE2 * 6 * 2 ];
|
||||
};
|
||||
|
||||
struct _psx_machine
|
||||
{
|
||||
running_machine &machine() const { assert(m_machine != NULL); return *m_machine; }
|
||||
|
||||
running_machine *m_machine;
|
||||
UINT32 *p_n_psxram;
|
||||
size_t n_psxramsize;
|
||||
|
||||
UINT32 n_com_delay;
|
||||
UINT32 n_irqdata;
|
||||
UINT32 n_irqmask;
|
||||
|
||||
UINT32 n_dpcp;
|
||||
UINT32 n_dicr;
|
||||
psx_dma_channel channel[7];
|
||||
|
||||
psx_root root[3];
|
||||
|
||||
psx_sio sio[2];
|
||||
|
||||
psx_mdec mdec;
|
||||
};
|
||||
|
||||
|
||||
INLINE void ATTR_PRINTF(3,4) verboselog( psx_machine *p_psx, int n_level, const char *s_fmt, ... )
|
||||
{
|
||||
if( VERBOSE_LEVEL >= n_level )
|
||||
@ -243,355 +125,15 @@ void psx_irq_set( running_machine &machine, UINT32 data )
|
||||
|
||||
/* DMA */
|
||||
|
||||
static void dma_start_timer( psx_machine *p_psx, int n_channel, UINT32 n_ticks )
|
||||
{
|
||||
psx_dma_channel *dma = &p_psx->channel[ n_channel ];
|
||||
|
||||
dma->timer->adjust( attotime::from_hz(33868800) * n_ticks, n_channel);
|
||||
dma->n_ticks = n_ticks;
|
||||
dma->b_running = 1;
|
||||
}
|
||||
|
||||
static void dma_stop_timer( psx_machine *p_psx, int n_channel )
|
||||
{
|
||||
psx_dma_channel *dma = &p_psx->channel[ n_channel ];
|
||||
|
||||
dma->timer->adjust( attotime::never);
|
||||
dma->b_running = 0;
|
||||
}
|
||||
|
||||
static void dma_timer_adjust( psx_machine *p_psx, int n_channel )
|
||||
{
|
||||
psx_dma_channel *dma = &p_psx->channel[ n_channel ];
|
||||
|
||||
if( dma->b_running )
|
||||
{
|
||||
dma_start_timer( p_psx, n_channel, dma->n_ticks );
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_stop_timer( p_psx, n_channel );
|
||||
}
|
||||
}
|
||||
|
||||
static void dma_interrupt_update( psx_machine *p_psx )
|
||||
{
|
||||
int n_int;
|
||||
int n_mask;
|
||||
|
||||
n_int = ( p_psx->n_dicr >> 24 ) & 0x7f;
|
||||
n_mask = ( p_psx->n_dicr >> 16 ) & 0xff;
|
||||
|
||||
if( ( n_mask & 0x80 ) != 0 && ( n_int & n_mask ) != 0 )
|
||||
{
|
||||
verboselog( p_psx, 2, "dma_interrupt_update( %02x, %02x ) interrupt triggered\n", n_int, n_mask );
|
||||
p_psx->n_dicr |= 0x80000000;
|
||||
psx_irq_set( p_psx->machine(), PSX_IRQ_DMA );
|
||||
}
|
||||
else if( n_int != 0 )
|
||||
{
|
||||
verboselog( p_psx, 2, "dma_interrupt_update( %02x, %02x ) interrupt not enabled\n", n_int, n_mask );
|
||||
}
|
||||
p_psx->n_dicr &= 0x00ffffff | ( p_psx->n_dicr << 8 );
|
||||
}
|
||||
|
||||
static void dma_finished(psx_machine *p_psx, int n_channel)
|
||||
{
|
||||
UINT32 *p_n_psxram = p_psx->p_n_psxram;
|
||||
psx_dma_channel *dma = &p_psx->channel[ n_channel ];
|
||||
|
||||
if( dma->n_channelcontrol == 0x01000401 && n_channel == 2 )
|
||||
{
|
||||
UINT32 n_size;
|
||||
UINT32 n_total;
|
||||
UINT32 n_address = ( dma->n_base & 0xffffff );
|
||||
UINT32 n_adrmask = p_psx->n_psxramsize - 1;
|
||||
UINT32 n_nextaddress;
|
||||
|
||||
if( n_address != 0xffffff )
|
||||
{
|
||||
n_total = 0;
|
||||
for( ;; )
|
||||
{
|
||||
if( n_address == 0xffffff )
|
||||
{
|
||||
dma->n_base = n_address;
|
||||
dma_start_timer( p_psx, n_channel, 19000 );
|
||||
return;
|
||||
}
|
||||
if( n_total > 65535 )
|
||||
{
|
||||
dma->n_base = n_address;
|
||||
//FIXME:
|
||||
// 16000 below is based on try and error.
|
||||
// Mametesters.org: sfex20103red
|
||||
//dma_start_timer( p_psx, n_channel, 16 );
|
||||
dma_start_timer( p_psx, n_channel, 16000 );
|
||||
return;
|
||||
}
|
||||
n_address &= n_adrmask;
|
||||
n_nextaddress = p_n_psxram[ n_address / 4 ];
|
||||
n_size = n_nextaddress >> 24;
|
||||
(*dma->fn_write)( p_psx->machine(), n_address + 4, n_size );
|
||||
//FIXME:
|
||||
// The following conditions will cause an endless loop.
|
||||
// If stopping the transfer is correct I cannot judge
|
||||
// The patch is meant as a hint for somebody who knows
|
||||
// the hardware.
|
||||
// Mametesters.org: psyforce0105u5red, raystorm0111u1red
|
||||
if ((n_nextaddress & 0xffffff) != 0xffffff)
|
||||
if (n_address == p_n_psxram[ (n_nextaddress & 0xffffff) / 4])
|
||||
break;
|
||||
if (n_address == (n_nextaddress & 0xffffff) )
|
||||
break;
|
||||
n_address = ( n_nextaddress & 0xffffff );
|
||||
|
||||
n_total += ( n_size + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dma->n_channelcontrol &= ~( ( 1L << 0x18 ) | ( 1L << 0x1c ) );
|
||||
|
||||
p_psx->n_dicr |= 1 << ( 24 + n_channel );
|
||||
dma_interrupt_update(p_psx);
|
||||
dma_stop_timer( p_psx, n_channel );
|
||||
}
|
||||
|
||||
static TIMER_CALLBACK( dma_finished_callback )
|
||||
{
|
||||
psx_machine *p_psx = machine.driver_data<psx_state>()->m_p_psx;
|
||||
|
||||
dma_finished(p_psx, param);
|
||||
}
|
||||
|
||||
void psx_dma_install_read_handler( running_machine &machine, int n_channel, psx_dma_read_handler p_fn_dma_read )
|
||||
{
|
||||
psx_machine *p_psx = machine.driver_data<psx_state>()->m_p_psx;
|
||||
|
||||
p_psx->channel[ n_channel ].fn_read = p_fn_dma_read;
|
||||
{
|
||||
psxcpu_device::install_dma_read_handler( *machine.device("maincpu"), n_channel, p_fn_dma_read );
|
||||
}
|
||||
|
||||
void psx_dma_install_write_handler( running_machine &machine, int n_channel, psx_dma_read_handler p_fn_dma_write )
|
||||
{
|
||||
psx_machine *p_psx = machine.driver_data<psx_state>()->m_p_psx;
|
||||
|
||||
p_psx->channel[ n_channel ].fn_write = p_fn_dma_write;
|
||||
}
|
||||
|
||||
WRITE32_HANDLER( psx_dma_w )
|
||||
{
|
||||
psx_machine *p_psx = space->machine().driver_data<psx_state>()->m_p_psx;
|
||||
UINT32 *p_n_psxram = p_psx->p_n_psxram;
|
||||
int n_channel = offset / 4;
|
||||
psx_dma_channel *dma = &p_psx->channel[ n_channel ];
|
||||
|
||||
if( n_channel < 7 )
|
||||
{
|
||||
switch( offset % 4 )
|
||||
{
|
||||
case 0:
|
||||
verboselog( p_psx, 2, "dmabase( %d ) = %08x\n", n_channel, data );
|
||||
dma->n_base = data;
|
||||
break;
|
||||
case 1:
|
||||
verboselog( p_psx, 2, "dmablockcontrol( %d ) = %08x\n", n_channel, data );
|
||||
dma->n_blockcontrol = data;
|
||||
break;
|
||||
case 2:
|
||||
verboselog( p_psx, 2, "dmachannelcontrol( %d ) = %08x\n", n_channel, data );
|
||||
dma->n_channelcontrol = data;
|
||||
if( ( dma->n_channelcontrol & ( 1L << 0x18 ) ) != 0 && ( p_psx->n_dpcp & ( 1 << ( 3 + ( n_channel * 4 ) ) ) ) != 0 )
|
||||
{
|
||||
INT32 n_size;
|
||||
UINT32 n_address;
|
||||
UINT32 n_nextaddress;
|
||||
UINT32 n_adrmask;
|
||||
|
||||
n_adrmask = p_psx->n_psxramsize - 1;
|
||||
|
||||
n_address = ( dma->n_base & n_adrmask );
|
||||
n_size = dma->n_blockcontrol;
|
||||
if( ( dma->n_channelcontrol & 0x200 ) != 0 )
|
||||
{
|
||||
UINT32 n_ba;
|
||||
n_ba = dma->n_blockcontrol >> 16;
|
||||
if( n_ba == 0 )
|
||||
{
|
||||
n_ba = 0x10000;
|
||||
}
|
||||
n_size = ( n_size & 0xffff ) * n_ba;
|
||||
}
|
||||
|
||||
if( dma->n_channelcontrol == 0x01000000 &&
|
||||
dma->fn_read != NULL )
|
||||
{
|
||||
verboselog( p_psx, 1, "dma %d read block %08x %08x\n", n_channel, n_address, n_size );
|
||||
(*dma->fn_read)( space->machine(), n_address, n_size );
|
||||
dma_finished( p_psx, n_channel );
|
||||
}
|
||||
else if (dma->n_channelcontrol == 0x11000000 && // CD DMA
|
||||
dma->fn_read != NULL )
|
||||
{
|
||||
verboselog( p_psx, 1, "dma %d read block %08x %08x\n", n_channel, n_address, n_size );
|
||||
|
||||
// pSX's CD DMA size calc formula
|
||||
int oursize = (dma->n_blockcontrol>>16);
|
||||
oursize = (oursize > 1) ? oursize : 1;
|
||||
oursize *= (dma->n_blockcontrol&0xffff);
|
||||
|
||||
(*dma->fn_read)( space->machine(), n_address, oursize );
|
||||
dma_finished( p_psx, n_channel );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x01000200 &&
|
||||
dma->fn_read != NULL )
|
||||
{
|
||||
verboselog( p_psx, 1, "dma %d read block %08x %08x\n", n_channel, n_address, n_size );
|
||||
(*dma->fn_read)( space->machine(), n_address, n_size );
|
||||
if( n_channel == 1 )
|
||||
{
|
||||
dma_start_timer( p_psx, n_channel, 26000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
dma_finished( p_psx, n_channel );
|
||||
}
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x01000201 &&
|
||||
dma->fn_write != NULL )
|
||||
{
|
||||
verboselog( p_psx, 1, "dma %d write block %08x %08x\n", n_channel, n_address, n_size );
|
||||
(*dma->fn_write)( space->machine(), n_address, n_size );
|
||||
dma_finished( p_psx, n_channel );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x11050100 &&
|
||||
dma->fn_write != NULL )
|
||||
{
|
||||
/* todo: check this is a write not a read... */
|
||||
verboselog( p_psx, 1, "dma %d write block %08x %08x\n", n_channel, n_address, n_size );
|
||||
(*dma->fn_write)( space->machine(), n_address, n_size );
|
||||
dma_finished( p_psx, n_channel );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x11150100 &&
|
||||
dma->fn_write != NULL )
|
||||
{
|
||||
/* todo: check this is a write not a read... */
|
||||
verboselog( p_psx, 1, "dma %d write block %08x %08x\n", n_channel, n_address, n_size );
|
||||
(*dma->fn_write)( space->machine(), n_address, n_size );
|
||||
dma_finished( p_psx, n_channel );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x01000401 &&
|
||||
n_channel == 2 &&
|
||||
dma->fn_write != NULL )
|
||||
{
|
||||
verboselog( p_psx, 1, "dma %d write linked list %08x\n",
|
||||
n_channel, dma->n_base );
|
||||
|
||||
dma_finished( p_psx, n_channel );
|
||||
}
|
||||
else if( dma->n_channelcontrol == 0x11000002 &&
|
||||
n_channel == 6 )
|
||||
{
|
||||
verboselog( p_psx, 1, "dma 6 reverse clear %08x %08x\n",
|
||||
dma->n_base, dma->n_blockcontrol );
|
||||
if( n_size > 0 )
|
||||
{
|
||||
n_size--;
|
||||
while( n_size > 0 )
|
||||
{
|
||||
n_nextaddress = ( n_address - 4 ) & 0xffffff;
|
||||
p_n_psxram[ n_address / 4 ] = n_nextaddress;
|
||||
n_address = n_nextaddress;
|
||||
n_size--;
|
||||
}
|
||||
p_n_psxram[ n_address / 4 ] = 0xffffff;
|
||||
}
|
||||
dma_start_timer( p_psx, n_channel, 2150 );
|
||||
}
|
||||
else
|
||||
{
|
||||
verboselog( p_psx, 1, "dma %d unknown mode %08x\n", n_channel, dma->n_channelcontrol );
|
||||
}
|
||||
}
|
||||
else if( dma->n_channelcontrol != 0 )
|
||||
{
|
||||
verboselog( p_psx, 1, "psx_dma_w( %04x, %08x, %08x ) channel not enabled\n", offset, dma->n_channelcontrol, mem_mask );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
verboselog( p_psx, 1, "psx_dma_w( %04x, %08x, %08x ) Unknown dma channel register\n", offset, data, mem_mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( offset % 4 )
|
||||
{
|
||||
case 0x0:
|
||||
verboselog( p_psx, 1, "psx_dma_w( %04x, %08x, %08x ) dpcp\n", offset, data, mem_mask );
|
||||
p_psx->n_dpcp = ( p_psx->n_dpcp & ~mem_mask ) | data;
|
||||
break;
|
||||
case 0x1:
|
||||
|
||||
p_psx->n_dicr = ( p_psx->n_dicr & ( 0x80000000 | ~mem_mask ) ) |
|
||||
( p_psx->n_dicr & ~data & 0x7f000000 & mem_mask ) |
|
||||
( data & 0x00ffffff & mem_mask );
|
||||
|
||||
if( ( p_psx->n_dicr & 0x80000000 ) != 0 && ( p_psx->n_dicr & 0x7f000000 ) == 0 )
|
||||
{
|
||||
verboselog( p_psx, 2, "dma interrupt cleared\n" );
|
||||
p_psx->n_dicr &= ~0x80000000;
|
||||
}
|
||||
|
||||
verboselog( p_psx, 1, "psx_dma_w( %04x, %08x, %08x ) dicr -> %08x\n", offset, data, mem_mask, p_psx->n_dicr );
|
||||
break;
|
||||
default:
|
||||
verboselog( p_psx, 0, "psx_dma_w( %04x, %08x, %08x ) Unknown dma control register\n", offset, data, mem_mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
READ32_HANDLER( psx_dma_r )
|
||||
{
|
||||
psx_machine *p_psx = space->machine().driver_data<psx_state>()->m_p_psx;
|
||||
int n_channel = offset / 4;
|
||||
psx_dma_channel *dma = &p_psx->channel[ n_channel ];
|
||||
|
||||
if( n_channel < 7 )
|
||||
{
|
||||
switch( offset % 4 )
|
||||
{
|
||||
case 0:
|
||||
verboselog( p_psx, 1, "psx_dma_r dmabase[ %d ] ( %08x )\n", n_channel, dma->n_base );
|
||||
return dma->n_base;
|
||||
case 1:
|
||||
verboselog( p_psx, 1, "psx_dma_r dmablockcontrol[ %d ] ( %08x )\n", n_channel, dma->n_blockcontrol );
|
||||
return dma->n_blockcontrol;
|
||||
case 2:
|
||||
verboselog( p_psx, 1, "psx_dma_r dmachannelcontrol[ %d ] ( %08x )\n", n_channel, dma->n_channelcontrol );
|
||||
return dma->n_channelcontrol;
|
||||
default:
|
||||
verboselog( p_psx, 0, "psx_dma_r( %08x, %08x ) Unknown dma channel register\n", offset, mem_mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( offset % 4 )
|
||||
{
|
||||
case 0x0:
|
||||
verboselog( p_psx, 1, "psx_dma_r dpcp ( %08x )\n", p_psx->n_dpcp );
|
||||
return p_psx->n_dpcp;
|
||||
case 0x1:
|
||||
verboselog( p_psx, 1, "psx_dma_r dicr ( %08x )\n", p_psx->n_dicr );
|
||||
return p_psx->n_dicr;
|
||||
default:
|
||||
verboselog( p_psx, 0, "psx_dma_r( %08x, %08x ) Unknown dma control register\n", offset, mem_mask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
psxcpu_device::install_dma_write_handler( *machine.device("maincpu"), n_channel, p_fn_dma_write );
|
||||
}
|
||||
|
||||
/* Root Counters */
|
||||
@ -1595,21 +1137,12 @@ void psx_machine_init( running_machine &machine )
|
||||
p_psx->n_irqdata = 0;
|
||||
p_psx->n_irqmask = 0;
|
||||
|
||||
/* dma */
|
||||
p_psx->n_dpcp = 0;
|
||||
p_psx->n_dicr = 0;
|
||||
|
||||
p_psx->mdec.n_0_command = 0;
|
||||
p_psx->mdec.n_0_address = 0;
|
||||
p_psx->mdec.n_0_size = 0;
|
||||
p_psx->mdec.n_1_command = 0;
|
||||
p_psx->mdec.n_1_status = 0;
|
||||
|
||||
for( n = 0; n < 7; n++ )
|
||||
{
|
||||
dma_stop_timer( p_psx, n );
|
||||
}
|
||||
|
||||
for( n = 0; n < 2; n++ )
|
||||
{
|
||||
p_psx->sio[ n ].n_status = SIO_STATUS_TX_EMPTY | SIO_STATUS_TX_RDY;
|
||||
@ -1637,11 +1170,6 @@ static void psx_postload(psx_machine *p_psx)
|
||||
|
||||
psx_irq_update(p_psx);
|
||||
|
||||
for( n = 0; n < 7; n++ )
|
||||
{
|
||||
dma_timer_adjust( p_psx, n );
|
||||
}
|
||||
|
||||
for( n = 0; n < 3; n++ )
|
||||
{
|
||||
root_timer_adjust( p_psx, n );
|
||||
@ -1668,13 +1196,6 @@ void psx_driver_init( running_machine &machine )
|
||||
p_psx->p_n_psxram = state->m_p_n_psxram;
|
||||
p_psx->n_psxramsize = state->m_n_psxramsize;
|
||||
|
||||
for( n = 0; n < 7; n++ )
|
||||
{
|
||||
p_psx->channel[ n ].timer = machine.scheduler().timer_alloc( FUNC(dma_finished_callback), &machine );
|
||||
p_psx->channel[ n ].fn_read = NULL;
|
||||
p_psx->channel[ n ].fn_write = NULL;
|
||||
}
|
||||
|
||||
for( n = 0; n < 3; n++ )
|
||||
{
|
||||
p_psx->root[ n ].timer = machine.scheduler().timer_alloc( FUNC(root_finished ));
|
||||
@ -1713,17 +1234,6 @@ void psx_driver_init( running_machine &machine )
|
||||
|
||||
state_save_register_global( machine, p_psx->n_irqdata );
|
||||
state_save_register_global( machine, p_psx->n_irqmask );
|
||||
for (n = 0; n < 7; n++ )
|
||||
{
|
||||
state_save_register_item( machine, "psxdma", NULL, n, p_psx->channel[n].n_base );
|
||||
state_save_register_item( machine, "psxdma", NULL, n, p_psx->channel[n].n_blockcontrol );
|
||||
state_save_register_item( machine, "psxdma", NULL, n, p_psx->channel[n].n_channelcontrol );
|
||||
state_save_register_item( machine, "psxdma", NULL, n, p_psx->channel[n].n_ticks );
|
||||
state_save_register_item( machine, "psxdma", NULL, n, p_psx->channel[n].b_running );
|
||||
}
|
||||
|
||||
state_save_register_global( machine, p_psx->n_dpcp );
|
||||
state_save_register_global( machine, p_psx->n_dicr );
|
||||
for ( n = 0; n < 3; n++ )
|
||||
{
|
||||
state_save_register_item( machine, "psxroot", NULL, n, p_psx->root[n].n_count );
|
||||
|
Loading…
Reference in New Issue
Block a user