New callback for generic_latch_8/16_device (nw)

- Add MCFG_GENERIC_LATCH_DATA_PENDING_CB to raise and lower a line automatically as the latch is written and read. This should make sound IRQs easier to deliver and reduce the incidence of HOLD_LINE in drivers.
- Update a few drivers to use this new callback.
This commit is contained in:
AJR 2016-12-29 19:23:04 -05:00
parent 2b74e4c0be
commit 95a914d30e
5 changed files with 118 additions and 78 deletions

View File

@ -5,6 +5,7 @@
Generic 8bit and 16 bit latch devices
***************************************************************************/
#include "emu.h"
#include "gen_latch.h"
@ -13,26 +14,70 @@
//**************************************************************************
const device_type GENERIC_LATCH_8 = &device_creator<generic_latch_8_device>;
const device_type GENERIC_LATCH_16 = &device_creator<generic_latch_16_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// generic_latch_base_device - constructor
//-------------------------------------------------
generic_latch_base_device::generic_latch_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source) :
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
m_latch_read(false),
m_data_pending_cb(*this)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void generic_latch_base_device::device_start()
{
m_data_pending_cb.resolve_safe();
save_item(NAME(m_latch_read));
}
//-------------------------------------------------
// pending_r - tell whether the latch is waiting
// to be read
//-------------------------------------------------
READ_LINE_MEMBER(generic_latch_base_device::pending_r)
{
return !m_latch_read;
}
//-------------------------------------------------
// set_latch_read - helper to signal that latch
// has been read or is waiting to be read
//-------------------------------------------------
void generic_latch_base_device::set_latch_read(bool latch_read)
{
if (m_latch_read != latch_read)
{
m_latch_read = latch_read;
m_data_pending_cb(!latch_read);
}
}
//-------------------------------------------------
// generic_latch_8_device - constructor
//-------------------------------------------------
generic_latch_8_device::generic_latch_8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, GENERIC_LATCH_8, "Generic 8-bit latch", tag, owner, clock, "generic_latch_8", __FILE__),
m_latched_value(0),
m_latch_read(0)
generic_latch_8_device::generic_latch_8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
generic_latch_base_device(mconfig, GENERIC_LATCH_8, "Generic 8-bit latch", tag, owner, clock, "generic_latch_8", __FILE__),
m_latched_value(0)
{
}
READ8_MEMBER( generic_latch_8_device::read )
{
m_latch_read = 1;
set_latch_read(true);
return m_latched_value;
}
@ -66,17 +111,17 @@ WRITE_LINE_MEMBER( generic_latch_8_device::clear_w )
// callback to set a latch value
//-------------------------------------------------
void generic_latch_8_device::sync_callback(void *ptr, int32_t param)
void generic_latch_8_device::sync_callback(void *ptr, s32 param)
{
uint8_t value = param;
u8 value = param;
// if the latch hasn't been read and the value is changed, log a warning
if (!m_latch_read && m_latched_value != value)
logerror("Warning: latch %s written before being read. Previous: %02x, new: %02x\n", tag(), m_latched_value, value);
if (!is_latch_read() && m_latched_value != value)
logerror("Warning: latch written before being read. Previous: %02x, new: %02x\n", m_latched_value, value);
// store the new value and mark it not read
m_latched_value = value;
m_latch_read = 0;
set_latch_read(false);
}
//-------------------------------------------------
@ -86,35 +131,23 @@ void generic_latch_8_device::sync_callback(void *ptr, int32_t param)
void generic_latch_8_device::device_start()
{
// register for state saving
generic_latch_base_device::device_start();
save_item(NAME(m_latched_value));
save_item(NAME(m_latch_read));
}
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
const device_type GENERIC_LATCH_16 = &device_creator<generic_latch_16_device>;
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// generic_latch_16_device - constructor
//-------------------------------------------------
generic_latch_16_device::generic_latch_16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, GENERIC_LATCH_16, "Generic 16-bit latch", tag, owner, clock, "generic_latch_16", __FILE__),
m_latched_value(0),
m_latch_read(0)
generic_latch_16_device::generic_latch_16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
generic_latch_base_device(mconfig, GENERIC_LATCH_16, "Generic 16-bit latch", tag, owner, clock, "generic_latch_16", __FILE__),
m_latched_value(0)
{
}
READ16_MEMBER( generic_latch_16_device::read )
{
m_latch_read = 1;
set_latch_read(true);
return m_latched_value;
}
@ -148,17 +181,17 @@ WRITE_LINE_MEMBER( generic_latch_16_device::clear_w )
// callback to set a latch value
//-------------------------------------------------
void generic_latch_16_device::sync_callback(void *ptr, int32_t param)
void generic_latch_16_device::sync_callback(void *ptr, s32 param)
{
uint16_t value = param;
u16 value = param;
// if the latch hasn't been read and the value is changed, log a warning
if (!m_latch_read && m_latched_value != value)
logerror("Warning: latch %s written before being read. Previous: %02x, new: %02x\n", tag(), m_latched_value, value);
if (!is_latch_read() && m_latched_value != value)
logerror("Warning: latch written before being read. Previous: %02x, new: %02x\n", m_latched_value, value);
// store the new value and mark it not read
m_latched_value = value;
m_latch_read = 0;
set_latch_read(false);
}
//-------------------------------------------------
@ -168,6 +201,6 @@ void generic_latch_16_device::sync_callback(void *ptr, int32_t param)
void generic_latch_16_device::device_start()
{
// register for state saving
generic_latch_base_device::device_start();
save_item(NAME(m_latched_value));
save_item(NAME(m_latch_read));
}

View File

@ -11,6 +11,8 @@
#ifndef __GEN_LATCH_H__
#define __GEN_LATCH_H__
#include "emu.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
@ -21,17 +23,46 @@
#define MCFG_GENERIC_LATCH_16_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, GENERIC_LATCH_16, 0)
#define MCFG_GENERIC_LATCH_DATA_PENDING_CB(_devcb) \
devcb = &generic_latch_base_device::set_data_pending_callback(*device, DEVCB_##_devcb);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> generic_latch_base_device
class generic_latch_base_device : public device_t
{
protected:
// construction/destruction
generic_latch_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source);
public:
// static configuration
template<class _Object> static devcb_base &set_data_pending_callback(device_t &device, _Object object) { return downcast<generic_latch_base_device &>(device).m_data_pending_cb.set_callback(object); }
DECLARE_READ_LINE_MEMBER(pending_r);
protected:
virtual void device_start() override;
bool is_latch_read() const { return m_latch_read; }
void set_latch_read(bool latch_read);
private:
bool m_latch_read;
devcb_write_line m_data_pending_cb;
};
// ======================> generic_latch_8_device
class generic_latch_8_device : public device_t
class generic_latch_8_device : public generic_latch_base_device
{
public:
// construction/destruction
generic_latch_8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
generic_latch_8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
@ -41,15 +72,15 @@ public:
DECLARE_WRITE_LINE_MEMBER( preset_w );
DECLARE_WRITE_LINE_MEMBER( clear_w );
void preset_w(uint16_t value) { m_latched_value = value; }
void preset_w(u8 value) { m_latched_value = value; }
protected:
virtual void device_start() override;
void sync_callback(void *ptr, int32_t param);
void sync_callback(void *ptr, s32 param);
private:
uint16_t m_latched_value;
uint8_t m_latch_read;
u8 m_latched_value;
};
// device type definition
@ -58,11 +89,11 @@ extern const device_type GENERIC_LATCH_8;
// ======================> generic_latch_16_device
class generic_latch_16_device : public device_t
class generic_latch_16_device : public generic_latch_base_device
{
public:
// construction/destruction
generic_latch_16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
generic_latch_16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
DECLARE_READ16_MEMBER( read );
DECLARE_WRITE16_MEMBER( write );
@ -72,13 +103,15 @@ public:
DECLARE_WRITE_LINE_MEMBER( preset_w );
DECLARE_WRITE_LINE_MEMBER( clear_w );
void preset_w(u16 value) { m_latched_value = value; }
protected:
virtual void device_start() override;
void sync_callback(void *ptr, int32_t param);
void sync_callback(void *ptr, s32 param);
private:
uint16_t m_latched_value;
uint8_t m_latch_read;
u16 m_latched_value;
};
// device type definition

View File

@ -229,10 +229,7 @@ WRITE16_MEMBER(dec0_automat_state::automat_control_w)
{
case 0xe: /* z80 sound cpu */
if (ACCESSING_BITS_0_7)
{
m_soundlatch->write(space, 0, data & 0xff);
m_audiocpu->set_input_line(0, HOLD_LINE);
}
break;
case 12: /* DMA flag */
@ -282,15 +279,6 @@ WRITE16_MEMBER(dec0_state::midres_sound_w)
}
}
WRITE16_MEMBER(dec0_automat_state::secretab_sound_w)
{
if (ACCESSING_BITS_0_7)
{
m_soundlatch->write(space, 0, data & 0xff);
m_audiocpu->set_input_line(0, HOLD_LINE);
}
}
/******************************************************************************/
static ADDRESS_MAP_START( dec0_map, AS_PROGRAM, 16, dec0_state )
@ -621,7 +609,7 @@ static ADDRESS_MAP_START( secretab_map, AS_PROGRAM, 16, dec0_automat_state )
// AM_RANGE(0x340400, 0x3407ff) AM_DEVREADWRITE("tilegen1", deco_bac06_device, pf_rowscroll_r, pf_rowscroll_w)
AM_RANGE(0x314008, 0x31400f) AM_READ(slyspy_controls_r)
AM_RANGE(0x314000, 0x314001) AM_WRITE(secretab_sound_w)
AM_RANGE(0x314000, 0x314001) AM_DEVWRITE8("soundlatch", generic_latch_8_device, write, 0x00ff)
AM_RANGE(0x300000, 0x300007) AM_RAM
AM_RANGE(0x300010, 0x300017) AM_RAM
@ -640,7 +628,7 @@ static ADDRESS_MAP_START( automat_s_map, AS_PROGRAM, 8, dec0_automat_state )
AM_RANGE(0xc000, 0xc7ff) AM_RAM
AM_RANGE(0xc800, 0xc801) AM_DEVREADWRITE("2203a", ym2203_device, read, write)
AM_RANGE(0xd000, 0xd001) AM_DEVREADWRITE("2203b", ym2203_device, read, write)
AM_RANGE(0xd800, 0xd800) AM_READ(sound_command_r)
AM_RANGE(0xd800, 0xd800) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
AM_RANGE(0xe000, 0xe000) AM_DEVWRITE("adpcm_select2", ls157_device, ba_w)
AM_RANGE(0xe800, 0xe800) AM_WRITE(sound_bankswitch_w)
AM_RANGE(0xf000, 0xf000) AM_DEVWRITE("adpcm_select1", ls157_device, ba_w)
@ -652,7 +640,7 @@ static ADDRESS_MAP_START( secretab_s_map, AS_PROGRAM, 8, dec0_automat_state )
AM_RANGE(0xc000, 0xc7ff) AM_RAM
AM_RANGE(0xc800, 0xc801) AM_DEVREADWRITE("2203a", ym2203_device, read, write)
AM_RANGE(0xd000, 0xd001) AM_DEVREADWRITE("ym3812", ym3812_device, read, write)
AM_RANGE(0xd800, 0xd800) AM_READ(sound_command_r)
AM_RANGE(0xd800, 0xd800) AM_DEVREAD("soundlatch", generic_latch_8_device, read)
AM_RANGE(0xe000, 0xe000) AM_DEVWRITE("adpcm_select2", ls157_device, ba_w)
AM_RANGE(0xe800, 0xe800) AM_WRITE(sound_bankswitch_w)
AM_RANGE(0xf000, 0xf000) AM_DEVWRITE("adpcm_select1", ls157_device, ba_w)
@ -1385,12 +1373,6 @@ static MACHINE_CONFIG_DERIVED( dec1, dec0_base )
MACHINE_CONFIG_END
READ8_MEMBER(dec0_automat_state::sound_command_r)
{
m_audiocpu->set_input_line(0, CLEAR_LINE);
return m_soundlatch->read(space, 0);
}
WRITE8_MEMBER(dec0_automat_state::sound_bankswitch_w)
{
m_msm1->reset_w(BIT(data, 3));
@ -1462,6 +1444,7 @@ static MACHINE_CONFIG_START( automat, dec0_automat_state )
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_GENERIC_LATCH_8_ADD("soundlatch")
MCFG_GENERIC_LATCH_DATA_PENDING_CB(INPUTLINE("audiocpu", 0))
MCFG_SOUND_ADD("2203a", YM2203, 1250000)
MCFG_SOUND_ROUTE(0, "mono", 0.90)
@ -1536,6 +1519,7 @@ static MACHINE_CONFIG_START( secretab, dec0_automat_state )
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_GENERIC_LATCH_8_ADD("soundlatch")
MCFG_GENERIC_LATCH_DATA_PENDING_CB(INPUTLINE("audiocpu", 0))
MCFG_SOUND_ADD("2203a", YM2203, 1250000)
MCFG_SOUND_ROUTE(0, "mono", 0.90)

View File

@ -88,7 +88,6 @@ public:
DECLARE_WRITE8_MEMBER(rambank_select_w);
DECLARE_WRITE8_MEMBER(discoboy_port_00_w);
DECLARE_WRITE8_MEMBER(discoboy_port_01_w);
DECLARE_WRITE8_MEMBER(discoboy_port_03_w);
DECLARE_WRITE8_MEMBER(discoboy_port_06_w);
DECLARE_WRITE8_MEMBER(rambank_w);
DECLARE_READ8_MEMBER(rambank_r);
@ -249,14 +248,6 @@ WRITE8_MEMBER(discoboy_state::discoboy_port_01_w)
membank("bank1")->set_entry(data & 0x07);
}
WRITE8_MEMBER(discoboy_state::discoboy_port_03_w)// sfx? (to sound cpu)
{
// printf("unk discoboy_port_03_w %02x\n", data);
// m_audiocpu->set_input_line(INPUT_LINE_NMI, HOLD_LINE);
m_soundlatch->write(space, 0, data);
m_audiocpu->set_input_line(0, HOLD_LINE);
}
WRITE8_MEMBER(discoboy_state::discoboy_port_06_w)
{
//printf("unk discoboy_port_06_w %02x\n",data);
@ -333,7 +324,7 @@ static ADDRESS_MAP_START( io_map, AS_IO, 8, discoboy_state )
AM_RANGE(0x00, 0x00) AM_READ_PORT("DSWA") AM_WRITE(discoboy_port_00_w)
AM_RANGE(0x01, 0x01) AM_READ_PORT("SYSTEM") AM_WRITE(discoboy_port_01_w)
AM_RANGE(0x02, 0x02) AM_READ_PORT("P1")
AM_RANGE(0x03, 0x03) AM_READ_PORT("P2") AM_WRITE(discoboy_port_03_w)
AM_RANGE(0x03, 0x03) AM_READ_PORT("P2") AM_DEVWRITE("soundlatch", generic_latch_8_device, write)
AM_RANGE(0x04, 0x04) AM_READ_PORT("DSWB")
AM_RANGE(0x06, 0x06) AM_READWRITE(discoboy_port_06_r, discoboy_port_06_w) // ???
AM_RANGE(0x07, 0x07) AM_WRITE(rambank_select_w) // 0x20 is palette bank bit.. others?
@ -512,6 +503,7 @@ static MACHINE_CONFIG_START( discoboy, discoboy_state )
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_GENERIC_LATCH_8_ADD("soundlatch")
MCFG_GENERIC_LATCH_DATA_PENDING_CB(INPUTLINE("audiocpu", 0))
MCFG_SOUND_ADD("ymsnd", YM3812, XTAL_10MHz/4) /* 2.5 MHz? */
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.6)

View File

@ -134,14 +134,12 @@ public:
uint16_t m_automat_scroll_regs[4];
DECLARE_WRITE16_MEMBER(automat_control_w);
DECLARE_WRITE16_MEMBER(secretab_sound_w);
DECLARE_READ16_MEMBER( automat_palette_r );
DECLARE_WRITE16_MEMBER( automat_palette_w );
DECLARE_WRITE16_MEMBER( automat_scroll_w )
{
COMBINE_DATA(&m_automat_scroll_regs[offset]);
}
DECLARE_READ8_MEMBER(sound_command_r);
DECLARE_WRITE8_MEMBER(sound_bankswitch_w);
DECLARE_WRITE_LINE_MEMBER(msm1_vclk_cb);
DECLARE_WRITE_LINE_MEMBER(msm2_vclk_cb);