Merge pull request #1847 from ajrhacker/devcb_chain

Overhaul of devcb (nw)
This commit is contained in:
R. Belmont 2016-12-22 12:08:46 -05:00 committed by GitHub
commit 4d73ed0072
12 changed files with 296 additions and 196 deletions

View File

@ -93,8 +93,6 @@ files {
MAME_DIR .. "src/emu/dislot.h",
MAME_DIR .. "src/emu/disound.cpp",
MAME_DIR .. "src/emu/disound.h",
MAME_DIR .. "src/emu/dispatch.cpp",
MAME_DIR .. "src/emu/dispatch.h",
MAME_DIR .. "src/emu/distate.cpp",
MAME_DIR .. "src/emu/distate.h",
MAME_DIR .. "src/emu/divideo.cpp",

View File

@ -22,11 +22,27 @@
devcb_base::devcb_base(device_t &device, u64 defmask)
: m_device(device),
m_type(CALLBACK_NONE),
m_target_tag(nullptr),
m_target_int(0),
m_space_tag(nullptr),
m_space_num(AS_0),
m_space(nullptr),
m_rshift(0),
m_mask(defmask),
m_defmask(defmask),
m_xor(0)
{
reset();
m_target.ptr = nullptr;
}
//-------------------------------------------------
// devcb_base - destructor
//-------------------------------------------------
devcb_base::~devcb_base()
{
}
@ -45,6 +61,8 @@ void devcb_base::reset(callback_type type)
m_target.ptr = nullptr;
m_rshift = 0;
m_mask = ~u64(0);
m_xor = 0;
devcb_reset();
}
@ -59,6 +77,26 @@ void devcb_base::resolve_ioport()
m_target.ioport = (m_target_tag != nullptr) ? m_device.owner()->ioport(m_target_tag) : nullptr;
if (m_target.ioport == nullptr)
throw emu_fatalerror("Unable to resolve I/O port callback reference to '%s' in device '%s'\n", m_target_tag, m_device.tag());
// adjust the mask to match the port bits
u64 port_mask = 0;
for (const ioport_field &field : m_target.ioport->fields())
port_mask |= field.mask();
m_mask = shift_mask(port_mask);
}
//-------------------------------------------------
// resolve_membank - resolve a memory bank or
// fatal error if we can't find it
//-------------------------------------------------
void devcb_base::resolve_membank()
{
// attempt to resolve, fatal error if fail
m_target.membank = (m_target_tag != nullptr) ? m_device.owner()->membank(m_target_tag) : nullptr;
if (m_target.membank == nullptr)
throw emu_fatalerror("Unable to resolve memory bank callback reference to '%s' in device '%s'\n", m_target_tag, m_device.tag());
}
@ -109,27 +147,37 @@ void devcb_base::resolve_space()
devcb_read_base::devcb_read_base(device_t &device, u64 defmask)
: devcb_base(device, defmask),
m_adapter(nullptr)
m_adapter(&devcb_read_base::read_unresolved_adapter)
{
}
//-------------------------------------------------
// reset - reset/initialize state
// devcb_reset - reset/initialize local state
//-------------------------------------------------
void devcb_read_base::reset(callback_type type)
void devcb_read_base::devcb_reset()
{
// parent first
devcb_base::reset(type);
// local stuff
m_readline = read_line_delegate();
m_read8 = read8_delegate();
m_read16 = read16_delegate();
m_read32 = read32_delegate();
m_read64 = read64_delegate();
m_adapter = &devcb_read_base::read_unresolved_adapter;
m_chain = nullptr;
}
//-------------------------------------------------
// chain_alloc - add another callback to the
// input chain
//-------------------------------------------------
devcb_read_base &devcb_read_base::chain_alloc()
{
// set up the chained callback pointer
m_chain.reset(new devcb_read_base(m_device, m_defmask));
return *m_chain;
}
@ -160,6 +208,7 @@ void devcb_read_base::resolve()
m_readline.bind_relative_to(*m_device.owner());
m_target_int = 0;
m_adapter = m_readline.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read_line_adapter;
m_mask = shift_mask(1);
break;
case CALLBACK_8:
@ -167,6 +216,7 @@ void devcb_read_base::resolve()
m_read8.bind_relative_to(*m_device.owner());
m_target_int = 0;
m_adapter = m_read8.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read8_adapter;
m_mask = shift_mask(0xff);
break;
case CALLBACK_16:
@ -174,6 +224,7 @@ void devcb_read_base::resolve()
m_read16.bind_relative_to(*m_device.owner());
m_target_int = 0;
m_adapter = m_read16.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read16_adapter;
m_mask = shift_mask(0xffff);
break;
case CALLBACK_32:
@ -181,6 +232,7 @@ void devcb_read_base::resolve()
m_read32.bind_relative_to(*m_device.owner());
m_target_int = 0;
m_adapter = m_read32.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read32_adapter;
m_mask = shift_mask(0xffffffff);
break;
case CALLBACK_64:
@ -191,20 +243,30 @@ void devcb_read_base::resolve()
break;
case CALLBACK_IOPORT:
name = m_target_tag;
resolve_ioport();
m_target_int = 0;
m_adapter = (m_target.ioport == nullptr) ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read_ioport_adapter;
m_adapter = &devcb_read_base::read_ioport_adapter;
break;
case CALLBACK_MEMBANK:
throw emu_fatalerror("Device read callbacks can't be connected to bank switches\n");
case CALLBACK_LOG:
m_adapter = &devcb_read_base::read_logged_adapter;
m_mask = 0;
break;
case CALLBACK_CONSTANT:
if (m_xor != 0)
throw emu_fatalerror("devcb_read: Attempt to invert constant value (%lX ^ %lX)\n", (unsigned long)shift_mask(m_target_int), (unsigned long)m_xor);
m_adapter = &devcb_read_base::read_constant_adapter;
m_mask = shift_mask(m_target_int);
break;
case CALLBACK_INPUTLINE:
case CALLBACK_ASSERTLINE:
case CALLBACK_CLEARLINE:
throw emu_fatalerror("Device read callbacks can't be connected to input lines\n");
}
}
@ -212,6 +274,15 @@ void devcb_read_base::resolve()
{
throw emu_fatalerror("devcb_read: Error performing a late bind of type %s to %s (name=%s)\n", binderr.m_actual_type.name(), binderr.m_target_type.name(), name);
}
// resolve callback chain recursively
if (m_chain != nullptr)
m_chain->resolve();
// protect against bus contention (the masks must not overlap)
for (const devcb_read_base *chained_cb = m_chain.get(); chained_cb != nullptr; chained_cb = chained_cb->m_chain.get())
if ((m_mask & chained_cb->m_mask) != 0)
throw emu_fatalerror("Device %s read callback (name=%s) overlaps with chained callback (%lX & %lX)", m_device.tag(), name, (unsigned long)m_mask, (unsigned long)chained_cb->m_mask);
}
@ -305,14 +376,14 @@ u64 devcb_read_base::read_ioport_adapter(address_space &space, offs_t offset, u6
//-------------------------------------------------
// read_logged_adapter - log a read and return a
// constant
// read_logged_adapter - log a read and return
// zero
//-------------------------------------------------
u64 devcb_read_base::read_logged_adapter(address_space &space, offs_t offset, u64 mask)
{
m_device.logerror("%s: read %s\n", m_device.machine().describe_context(), m_target_tag);
return shift_mask_xor(m_target_int);
m_device.logerror("%s: %s\n", m_device.machine().describe_context(), m_target_tag);
return 0;
}
@ -322,7 +393,7 @@ u64 devcb_read_base::read_logged_adapter(address_space &space, offs_t offset, u6
u64 devcb_read_base::read_constant_adapter(address_space &space, offs_t offset, u64 mask)
{
return shift_mask_xor(m_target_int);
return shift_mask(m_target_int);
}
@ -337,27 +408,37 @@ u64 devcb_read_base::read_constant_adapter(address_space &space, offs_t offset,
devcb_write_base::devcb_write_base(device_t &device, u64 defmask)
: devcb_base(device, defmask),
m_adapter(nullptr)
m_adapter(&devcb_write_base::write_unresolved_adapter)
{
}
//-------------------------------------------------
// reset - reset/initialize state
// devcb_reset - reset/initialize local state
//-------------------------------------------------
void devcb_write_base::reset(callback_type type)
void devcb_write_base::devcb_reset()
{
// parent first
devcb_base::reset(type);
// local stuff
m_writeline = write_line_delegate();
m_write8 = write8_delegate();
m_write16 = write16_delegate();
m_write32 = write32_delegate();
m_write64 = write64_delegate();
m_adapter = &devcb_write_base::write_unresolved_adapter;
m_chain = nullptr;
}
//-------------------------------------------------
// chain_alloc - add another callback to the
// output chain
//-------------------------------------------------
devcb_write_base &devcb_write_base::chain_alloc()
{
// set up the chained callback pointer
m_chain.reset(new devcb_write_base(m_device, m_defmask));
return *m_chain;
}
@ -418,6 +499,11 @@ void devcb_write_base::resolve()
m_adapter = (m_target.ioport == nullptr) ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_ioport_adapter;
break;
case CALLBACK_MEMBANK:
resolve_membank();
m_adapter = (m_target.membank == nullptr) ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_membank_adapter;
break;
case CALLBACK_LOG:
m_adapter = &devcb_write_base::write_logged_adapter;
break;
@ -430,12 +516,26 @@ void devcb_write_base::resolve()
resolve_inputline();
m_adapter = &devcb_write_base::write_inputline_adapter;
break;
case CALLBACK_ASSERTLINE:
resolve_inputline();
m_adapter = &devcb_write_base::write_assertline_adapter;
break;
case CALLBACK_CLEARLINE:
resolve_inputline();
m_adapter = &devcb_write_base::write_clearline_adapter;
break;
}
}
catch (binding_type_exception &binderr)
{
throw emu_fatalerror("devcb_write: Error performing a late bind of type %s to %s (name=%s)\n", binderr.m_actual_type.name(), binderr.m_target_type.name(), name);
}
// resolve callback chain recursively
if (m_chain != nullptr)
m_chain->resolve();
}
@ -515,7 +615,7 @@ void devcb_write_base::write64_adapter(address_space &space, offs_t offset, u64
//-------------------------------------------------
// write_ioport - write from an I/O port
// write_ioport_adapter - write to an I/O port
//-------------------------------------------------
void devcb_write_base::write_ioport_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
@ -526,13 +626,25 @@ void devcb_write_base::write_ioport_adapter(address_space &space, offs_t offset,
//-------------------------------------------------
// write_logged_adapter - logging unresolved
// adapter
// write_membank_adapter - switch a memory bank
//-------------------------------------------------
void devcb_write_base::write_membank_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
{
if (m_target.membank)
m_target.membank->set_entry(unshift_mask_xor(data));
}
//-------------------------------------------------
// write_logged_adapter - log write if masked
// value is nonzero
//-------------------------------------------------
void devcb_write_base::write_logged_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
{
m_device.logerror("%s: unresolved devcb write\n", m_device.machine().describe_context());
if (unshift_mask_xor(data) != 0)
m_device.logerror("%s: %s\n", m_device.machine().describe_context(), m_target_tag);
}
@ -547,7 +659,7 @@ void devcb_write_base::write_noop_adapter(address_space &space, offs_t offset, u
//-------------------------------------------------
// write_inputline_adapter - write to an device's
// write_inputline_adapter - write to a device's
// input line
//-------------------------------------------------
@ -555,3 +667,27 @@ void devcb_write_base::write_inputline_adapter(address_space &space, offs_t offs
{
m_target.device->execute().set_input_line(m_target_int, unshift_mask_xor(data) & 1);
}
//-------------------------------------------------
// write_assertline_adapter - write to a device's
// input line
//-------------------------------------------------
void devcb_write_base::write_assertline_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
{
if (unshift_mask_xor(data) & 1)
m_target.device->execute().set_input_line(m_target_int, ASSERT_LINE);
}
//-------------------------------------------------
// write_clearline_adapter - write to a device's
// input line
//-------------------------------------------------
void devcb_write_base::write_clearline_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
{
if (unshift_mask_xor(data) & 1)
m_target.device->execute().set_input_line(m_target_int, CLEAR_LINE);
}

View File

@ -25,9 +25,12 @@
// wrappers for ioports, constants, and loggers
#define DEVCB_NOOP devcb_base::null_desc()
#define DEVCB_IOPORT(_tag) devcb_base::ioport_desc(_tag)
#define DEVCB_MEMBANK(_tag) devcb_base::membank_desc(_tag)
#define DEVCB_CONSTANT(_value) devcb_base::constant_desc(_value)
#define DEVCB_LOGGER(_string, _value) devcb_base::logger_desc(_string, _value)
#define DEVCB_LOGGER(_string) devcb_base::logger_desc(_string)
#define DEVCB_INPUTLINE(_tag, _line) devcb_base::inputline_desc(_tag, _line)
#define DEVCB_ASSERTLINE(_tag, _line) devcb_base::assertline_desc(_tag, _line)
#define DEVCB_CLEARLINE(_tag, _line) devcb_base::clearline_desc(_tag, _line)
#define DEVCB_VCC DEVCB_CONSTANT(1)
#define DEVCB_GND DEVCB_CONSTANT(0)
@ -62,10 +65,14 @@
// machine config helpers to add shift, mask, or address space configuration
#define MCFG_DEVCB_RSHIFT(_shift) devcb->set_rshift(_shift);
#define MCFG_DEVCB_MASK(_mask) devcb->set_mask(_mask);
#define MCFG_DEVCB_BIT(_bit) devcb->set_rshift(-(_bit)).set_mask(1ULL << (_bit));
#define MCFG_DEVCB_XOR(_xor) devcb->set_xor(_xor);
#define MCFG_DEVCB_INVERT devcb->set_xor(~u64(0));
#define MCFG_DEVCB_ADDRESS_SPACE(_device, _spacenum) devcb->set_space(_device, _spacenum);
// machine config helpers for chaining callbacks
#define MCFG_DEVCB_CHAIN_INPUT(_desc) devcb = &downcast<devcb_read_base &>(*devcb).chain_alloc().set_callback(DEVCB_##_desc);
#define MCFG_DEVCB_CHAIN_OUTPUT(_desc) devcb = &downcast<devcb_write_base &>(*devcb).chain_alloc().set_callback(DEVCB_##_desc);
//**************************************************************************
@ -92,13 +99,17 @@ protected:
CALLBACK_32,
CALLBACK_64,
CALLBACK_IOPORT,
CALLBACK_MEMBANK,
CALLBACK_LOG,
CALLBACK_CONSTANT,
CALLBACK_INPUTLINE
CALLBACK_INPUTLINE,
CALLBACK_ASSERTLINE,
CALLBACK_CLEARLINE
};
// construction/destruction
devcb_base(device_t &device, u64 defmask);
virtual ~devcb_base();
public:
// getters
@ -124,6 +135,13 @@ public:
const char *m_tag;
};
class membank_desc
{
public:
membank_desc(const char *tag) { m_tag = tag; }
const char *m_tag;
};
class constant_desc
{
public:
@ -134,9 +152,8 @@ public:
class logger_desc
{
public:
logger_desc(const char *string, u64 value = 0) { m_string = string; m_value = value; }
logger_desc(const char *string) { m_string = string; }
const char *m_string;
u64 m_value;
};
class inputline_desc
@ -147,20 +164,40 @@ public:
int m_inputnum;
};
class assertline_desc
{
public:
assertline_desc(const char *tag, int inputnum) { m_tag = tag; m_inputnum = inputnum; }
const char *m_tag;
int m_inputnum;
};
class clearline_desc
{
public:
clearline_desc(const char *tag, int inputnum) { m_tag = tag; m_inputnum = inputnum; }
const char *m_tag;
int m_inputnum;
};
// shared callback setters
devcb_base &set_callback(null_desc null) { reset(CALLBACK_NONE); return *this; }
devcb_base &set_callback(ioport_desc ioport) { reset(CALLBACK_IOPORT); m_target_tag = ioport.m_tag; return *this; }
devcb_base &set_callback(membank_desc membank) { reset(CALLBACK_MEMBANK); m_target_tag = membank.m_tag; return *this; }
devcb_base &set_callback(constant_desc constant) { reset(CALLBACK_CONSTANT); m_target_int = constant.m_value; return *this; }
devcb_base &set_callback(logger_desc logger) { reset(CALLBACK_LOG); m_target_int = logger.m_value; m_target_tag = logger.m_string; return *this; }
devcb_base &set_callback(inputline_desc inputline) { reset(CALLBACK_INPUTLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
devcb_base &set_callback(logger_desc logger) { reset(CALLBACK_LOG); m_target_tag = logger.m_string; return *this; }
void reset() { reset(CALLBACK_NONE); }
protected:
// internal helpers
inline u64 shift_mask(u64 value) const { return ((m_rshift < 0) ? (value << -m_rshift) : (value >> m_rshift)) & m_mask; }
inline u64 shift_mask_xor(u64 value) const { return (((m_rshift < 0) ? (value << -m_rshift) : (value >> m_rshift)) ^ m_xor) & m_mask; }
inline u64 unshift_mask(u64 value) const { return (m_rshift < 0) ? ((value & m_mask) >> -m_rshift) : ((value & m_mask) << m_rshift); }
inline u64 unshift_mask_xor(u64 value) const { return (m_rshift < 0) ? (((value ^ m_xor) & m_mask) >> -m_rshift) : (((value ^ m_xor) & m_mask) << m_rshift); }
void reset(callback_type type = CALLBACK_NONE);
void reset(callback_type type);
virtual void devcb_reset() = 0;
void resolve_ioport();
void resolve_membank();
void resolve_inputline();
void resolve_space();
@ -170,6 +207,7 @@ protected:
void * ptr;
device_t * device;
ioport_port * ioport;
memory_bank * membank;
};
// configuration
@ -185,6 +223,7 @@ protected:
callback_target m_target; // resolved pointer to target object
int m_rshift; // right shift to apply to data read
u64 m_mask; // mask to apply to data read
const u64 m_defmask; // default mask
u64 m_xor; // XOR to apply to data read
};
@ -205,6 +244,7 @@ public:
devcb_base &set_callback(read16_delegate func) { reset(CALLBACK_16); m_read16 = func; return *this; }
devcb_base &set_callback(read32_delegate func) { reset(CALLBACK_32); m_read32 = func; return *this; }
devcb_base &set_callback(read64_delegate func) { reset(CALLBACK_64); m_read64 = func; return *this; }
devcb_read_base &chain_alloc();
// resolution
void resolve();
@ -212,8 +252,10 @@ public:
protected:
// internal helpers
void reset(callback_type type = CALLBACK_NONE);
virtual void devcb_reset() override;
inline u64 read(address_space &space, offs_t offset, u64 mask);
private:
// adapters
u64 read_unresolved_adapter(address_space &space, offs_t offset, u64 mask);
u64 read_line_adapter(address_space &space, offs_t offset, u64 mask);
@ -235,6 +277,7 @@ protected:
// derived state
typedef u64 (devcb_read_base::*adapter_func)(address_space &, offs_t, u64);
adapter_func m_adapter; // actual callback to invoke
std::unique_ptr<devcb_read_base> m_chain; // next callback for chained input
};
@ -254,6 +297,10 @@ public:
devcb_base &set_callback(write16_delegate func) { reset(CALLBACK_16); m_write16 = func; return *this; }
devcb_base &set_callback(write32_delegate func) { reset(CALLBACK_32); m_write32 = func; return *this; }
devcb_base &set_callback(write64_delegate func) { reset(CALLBACK_64); m_write64 = func; return *this; }
devcb_base &set_callback(inputline_desc inputline) { reset(CALLBACK_INPUTLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
devcb_base &set_callback(assertline_desc inputline) { reset(CALLBACK_ASSERTLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
devcb_base &set_callback(clearline_desc inputline) { reset(CALLBACK_CLEARLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
devcb_write_base &chain_alloc();
// resolution
void resolve();
@ -261,8 +308,10 @@ public:
protected:
// internal helpers
void reset(callback_type type = CALLBACK_NONE);
virtual void devcb_reset() override;
inline void write(address_space &space, offs_t offset, u64 data, u64 mask);
private:
// adapters
void write_unresolved_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write_line_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
@ -271,9 +320,12 @@ protected:
void write32_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write64_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write_ioport_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write_membank_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write_logged_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write_noop_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write_inputline_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write_assertline_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
void write_clearline_adapter(address_space &space, offs_t offset, u64 data, u64 mask);
// configuration
write_line_delegate m_writeline; // copy of registered line writer
@ -285,6 +337,7 @@ protected:
// derived state
typedef void (devcb_write_base::*adapter_func)(address_space &, offs_t, u64, u64);
adapter_func m_adapter; // actual callback to invoke
std::unique_ptr<devcb_write_base> m_chain; // next callback for chained output
};
@ -294,8 +347,8 @@ class devcb_read_line : public devcb_read_base
{
public:
devcb_read_line(device_t &device) : devcb_read_base(device, 0xff) { }
int operator()() { return (this->*m_adapter)(*m_space, 0, 0xffU) & 1; }
int operator()(address_space &space) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, 0, 0xffU) & 1; }
int operator()() { return read(*m_space, 0, 0xffU) & 1; }
int operator()(address_space &space) { return read((m_space_tag != nullptr) ? *m_space : space, 0, 0xffU) & 1; }
};
@ -305,8 +358,8 @@ class devcb_read8 : public devcb_read_base
{
public:
devcb_read8(device_t &device) : devcb_read_base(device, 0xff) { }
u8 operator()(offs_t offset = 0, u8 mask = 0xff) { return (this->*m_adapter)(*m_space, offset, mask) & mask; }
u8 operator()(address_space &space, offs_t offset = 0, u8 mask = 0xff) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
u8 operator()(offs_t offset = 0, u8 mask = 0xff) { return read(*m_space, offset, mask) & mask; }
u8 operator()(address_space &space, offs_t offset = 0, u8 mask = 0xff) { return read((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
};
@ -316,8 +369,8 @@ class devcb_read16 : public devcb_read_base
{
public:
devcb_read16(device_t &device) : devcb_read_base(device, 0xffff) { }
u16 operator()(offs_t offset = 0, u16 mask = 0xffff) { return (this->*m_adapter)(*m_space, offset, mask) & mask; }
u16 operator()(address_space &space, offs_t offset = 0, u16 mask = 0xffff) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
u16 operator()(offs_t offset = 0, u16 mask = 0xffff) { return read(*m_space, offset, mask) & mask; }
u16 operator()(address_space &space, offs_t offset = 0, u16 mask = 0xffff) { return read((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
};
@ -327,8 +380,8 @@ class devcb_read32 : public devcb_read_base
{
public:
devcb_read32(device_t &device) : devcb_read_base(device, 0xffffffff) { }
u32 operator()(offs_t offset = 0, u32 mask = 0xffffffff) { return (this->*m_adapter)(*m_space, offset, mask) & mask; }
u32 operator()(address_space &space, offs_t offset = 0, u32 mask = 0xffffffff) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
u32 operator()(offs_t offset = 0, u32 mask = 0xffffffff) { return read(*m_space, offset, mask) & mask; }
u32 operator()(address_space &space, offs_t offset = 0, u32 mask = 0xffffffff) { return read((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
};
@ -338,8 +391,8 @@ class devcb_read64 : public devcb_read_base
{
public:
devcb_read64(device_t &device) : devcb_read_base(device, 0xffffffffffffffffU) { }
u64 operator()(offs_t offset = 0, u64 mask = 0xffffffffffffffffU) { return (this->*m_adapter)(*m_space, offset, mask) & mask; }
u64 operator()(address_space &space, offs_t offset = 0, u64 mask = 0xffffffffffffffffU) { return (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
u64 operator()(offs_t offset = 0, u64 mask = 0xffffffffffffffffU) { return read(*m_space, offset, mask) & mask; }
u64 operator()(address_space &space, offs_t offset = 0, u64 mask = 0xffffffffffffffffU) { return read((m_space_tag != nullptr) ? *m_space : space, offset, mask) & mask; }
};
@ -349,8 +402,8 @@ class devcb_write_line : public devcb_write_base
{
public:
devcb_write_line(device_t &device) : devcb_write_base(device, 0xff) { }
void operator()(int state) { (this->*m_adapter)(*m_space, 0, state & 1, 0xffU); }
void operator()(address_space &space, int state) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, 0, state & 1, 0xffU); }
void operator()(int state) { write(*m_space, 0, state & 1, 0xffU); }
void operator()(address_space &space, int state) { write((m_space_tag != nullptr) ? *m_space : space, 0, state & 1, 0xffU); }
};
@ -360,9 +413,9 @@ class devcb_write8 : public devcb_write_base
{
public:
devcb_write8(device_t &device) : devcb_write_base(device, 0xff) { }
void operator()(u8 data, u8 mask = 0xff) { (this->*m_adapter)(*m_space, 0, data, mask); }
void operator()(offs_t offset, u8 data, u8 mask = 0xff) { (this->*m_adapter)(*m_space, offset, data, mask); }
void operator()(address_space &space, offs_t offset, u8 data, u8 mask = 0xff) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
void operator()(u8 data, u8 mask = 0xff) { write(*m_space, 0, data, mask); }
void operator()(offs_t offset, u8 data, u8 mask = 0xff) { write(*m_space, offset, data, mask); }
void operator()(address_space &space, offs_t offset, u8 data, u8 mask = 0xff) { write((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
};
@ -372,9 +425,9 @@ class devcb_write16 : public devcb_write_base
{
public:
devcb_write16(device_t &device) : devcb_write_base(device, 0xffff) { }
void operator()(u16 data, u16 mask = 0xffff) { (this->*m_adapter)(*m_space, 0, data, mask); }
void operator()(offs_t offset, u16 data, u16 mask = 0xffff) { (this->*m_adapter)(*m_space, offset, data, mask); }
void operator()(address_space &space, offs_t offset, u16 data, u16 mask = 0xffff) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
void operator()(u16 data, u16 mask = 0xffff) { write(*m_space, 0, data, mask); }
void operator()(offs_t offset, u16 data, u16 mask = 0xffff) { write(*m_space, offset, data, mask); }
void operator()(address_space &space, offs_t offset, u16 data, u16 mask = 0xffff) { write((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
};
@ -384,9 +437,9 @@ class devcb_write32 : public devcb_write_base
{
public:
devcb_write32(device_t &device) : devcb_write_base(device, 0xffffffff) { }
void operator()(u32 data, u32 mask = 0xffffffff) { (this->*m_adapter)(*m_space, 0, data, mask); }
void operator()(offs_t offset, u32 data, u32 mask = 0xffffffff) { (this->*m_adapter)(*m_space, offset, data, mask); }
void operator()(address_space &space, offs_t offset, u32 data, u32 mask = 0xffffffff) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
void operator()(u32 data, u32 mask = 0xffffffff) { write(*m_space, 0, data, mask); }
void operator()(offs_t offset, u32 data, u32 mask = 0xffffffff) { write(*m_space, offset, data, mask); }
void operator()(address_space &space, offs_t offset, u32 data, u32 mask = 0xffffffff) { write((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
};
@ -396,10 +449,40 @@ class devcb_write64 : public devcb_write_base
{
public:
devcb_write64(device_t &device) : devcb_write_base(device, 0xffffffffffffffffU) { }
void operator()(u64 data, u64 mask = 0xffffffffffffffffU) { (this->*m_adapter)(*m_space, 0, data, mask); }
void operator()(offs_t offset, u64 data, u64 mask = 0xffffffffffffffffU) { (this->*m_adapter)(*m_space, offset, data, mask); }
void operator()(address_space &space, offs_t offset, u64 data, u64 mask = 0xffffffffffffffffU) { (this->*m_adapter)((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
void operator()(u64 data, u64 mask = 0xffffffffffffffffU) { write(*m_space, 0, data, mask); }
void operator()(offs_t offset, u64 data, u64 mask = 0xffffffffffffffffU) { write(*m_space, offset, data, mask); }
void operator()(address_space &space, offs_t offset, u64 data, u64 mask = 0xffffffffffffffffU) { write((m_space_tag != nullptr) ? *m_space : space, offset, data, mask); }
};
//**************************************************************************
// INLINE FUNCTIONS
//**************************************************************************
//-------------------------------------------------
// read - generic read callback dispatch
//-------------------------------------------------
inline u64 devcb_read_base::read(address_space &space, offs_t offset, u64 mask)
{
u64 result = (this->*m_adapter)(space, offset, mask);
if (m_chain != nullptr)
result |= m_chain->read(space, offset, mask);
return result;
}
//-------------------------------------------------
// write - generic write callback dispatch
//-------------------------------------------------
inline void devcb_write_base::write(address_space &space, offs_t offset, u64 data, u64 mask)
{
(this->*m_adapter)(space, offset, data, mask);
if (m_chain != nullptr)
m_chain->write(space, offset, data, mask);
}
#endif /* MAME_EMU_DEVCB_H */

View File

@ -1,40 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
#include "emu.h"
const device_type DEVCB_LINE_DISPATCH_2 = &device_creator<devcb_line_dispatch_device<2> >;
const device_type DEVCB_LINE_DISPATCH_3 = &device_creator<devcb_line_dispatch_device<3> >;
const device_type DEVCB_LINE_DISPATCH_4 = &device_creator<devcb_line_dispatch_device<4> >;
const device_type DEVCB_LINE_DISPATCH_5 = &device_creator<devcb_line_dispatch_device<5> >;
const device_type DEVCB_LINE_DISPATCH_6 = &device_creator<devcb_line_dispatch_device<6> >;
template<> devcb_line_dispatch_device<2>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, DEVCB_LINE_DISPATCH_2, "Line dispatcher (2 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
{
init_fwd();
}
template<> devcb_line_dispatch_device<3>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, DEVCB_LINE_DISPATCH_3, "Line dispatcher (3 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
{
init_fwd();
}
template<> devcb_line_dispatch_device<4>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, DEVCB_LINE_DISPATCH_4, "Line dispatcher (4 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
{
init_fwd();
}
template<> devcb_line_dispatch_device<5>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, DEVCB_LINE_DISPATCH_5, "Line dispatcher (5 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
{
init_fwd();
}
template<> devcb_line_dispatch_device<6>::devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, DEVCB_LINE_DISPATCH_6, "Line dispatcher (6 slots)", tag, owner, clock, "devcb_line_dispatch", __FILE__)
{
init_fwd();
}

View File

@ -1,64 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************
dispatch.h
Signal dispatching devices.
***************************************************************************/
#pragma once
#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif
#ifndef MAME_EMU_DISPATCH_H
#define MAME_EMU_DISPATCH_H
#define MCFG_LINE_DISPATCH_ADD(_tag, _count) \
MCFG_DEVICE_ADD(_tag, DEVCB_LINE_DISPATCH_ ## _count, 0)
#define MCFG_LINE_DISPATCH_FWD_CB(_entry, _count, _devcb) \
devcb = &devcb_line_dispatch_device<_count>::set_fwd_cb(*device, _entry, DEVCB_##_devcb);
extern const device_type DEVCB_LINE_DISPATCH_2;
extern const device_type DEVCB_LINE_DISPATCH_3;
extern const device_type DEVCB_LINE_DISPATCH_4;
extern const device_type DEVCB_LINE_DISPATCH_5;
extern const device_type DEVCB_LINE_DISPATCH_6;
template<int N> class devcb_line_dispatch_device : public device_t {
public:
devcb_line_dispatch_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, DEVCB_LINE_DISPATCH_2, "DEVCB_LINE_DISPATCH_2", tag, owner, clock, "devcb_line_dispatch_2", __FILE__) { }
void init_fwd() {
for(auto & elem : fwd_cb)
elem = new devcb_write_line(*this);
}
virtual ~devcb_line_dispatch_device() {
for(auto & elem : fwd_cb)
delete elem;
}
template<class _Object> static devcb_base &set_fwd_cb(device_t &device, int entry, _Object object) { return downcast<devcb_line_dispatch_device<N> &>(device).fwd_cb[entry]->set_callback(object); }
WRITE_LINE_MEMBER( in_w ) {
for(auto & elem : fwd_cb)
(*(elem))(state);
}
protected:
virtual void device_start() override {
for(auto & elem : fwd_cb)
elem->resolve_safe();
}
private:
devcb_write_line *fwd_cb[N];
};
#endif // MAME_EMU_DISPATCH_H

View File

@ -110,7 +110,6 @@ typedef device_t * (*machine_config_constructor)(machine_config &config, device_
// generic helpers
#include "devcb.h"
#include "dispatch.h"
#include "drivers/xtal.h"
#include "bookkeeping.h"
#include "video/generic.h"

View File

@ -293,7 +293,7 @@ static MACHINE_CONFIG_START( midcoin24cdjuke, midcoin24cdjuke_state )
MCFG_I8255_OUT_PORTC_CB(WRITE8(midcoin24cdjuke_state, kb_col_w))
MCFG_DEVICE_ADD("ic31", I8255A, 0)
MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B", 0))
MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B"))
MCFG_I8255_IN_PORTC_CB(IOPORT("MD4"))
MACHINE_CONFIG_END

View File

@ -748,10 +748,10 @@ static MACHINE_CONFIG_START( dmv, dmv_state )
MCFG_I8237_OUT_EOP_CB(WRITELINE(dmv_state, dmac_eop))
MCFG_I8237_IN_MEMR_CB(READ8(dmv_state, program_r))
MCFG_I8237_OUT_MEMW_CB(WRITE8(dmv_state, program_w))
MCFG_I8237_IN_IOR_0_CB(LOGGER("DMA CH1", 0))
MCFG_I8237_OUT_IOW_0_CB(LOGGER("DMA CH1", 0))
MCFG_I8237_IN_IOR_1_CB(LOGGER("DMA CH2", 0))
MCFG_I8237_OUT_IOW_1_CB(LOGGER("DMA CH2", 0))
MCFG_I8237_IN_IOR_0_CB(LOGGER("Read DMA CH1"))
MCFG_I8237_OUT_IOW_0_CB(LOGGER("Write DMA CH1"))
MCFG_I8237_IN_IOR_1_CB(LOGGER("Read DMA CH2"))
MCFG_I8237_OUT_IOW_1_CB(LOGGER("Write DMA CH2"))
MCFG_I8237_IN_IOR_2_CB(DEVREAD8("upd7220", upd7220_device, dack_r))
MCFG_I8237_OUT_IOW_2_CB(DEVWRITE8("upd7220", upd7220_device, dack_w))
MCFG_I8237_IN_IOR_3_CB(DEVREAD8("i8272", i8272a_device, mdma_r))

View File

@ -501,8 +501,8 @@ static MACHINE_CONFIG_START( imolagp, imolagp_state )
MCFG_DEVICE_ADD("ppi8255", I8255A, 0)
// mode $91 - ports A & C-lower as input, ports B & C-upper as output
MCFG_I8255_IN_PORTA_CB(IOPORT("IN0"))
MCFG_I8255_IN_PORTB_CB(LOGGER("PPI8255 - unmapped read port B", 0))
MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B", 0))
MCFG_I8255_IN_PORTB_CB(LOGGER("PPI8255 - unmapped read port B"))
MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B"))
MCFG_I8255_IN_PORTC_CB(IOPORT("IN1"))
/* video hardware */

View File

@ -244,13 +244,13 @@ static MACHINE_CONFIG_START( kopunch, kopunch_state )
MCFG_DEVICE_ADD("ppi8255_1", I8255A, 0)
// $34 - always $80 (PPI mode 0, ports A & B & C as output)
MCFG_I8255_OUT_PORTA_CB(WRITE8(kopunch_state, coin_w))
MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B", 0))
MCFG_I8255_OUT_PORTC_CB(LOGGER("PPI8255 - unmapped write port C", 0))
MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B"))
MCFG_I8255_OUT_PORTC_CB(LOGGER("PPI8255 - unmapped write port C"))
MCFG_DEVICE_ADD("ppi8255_2", I8255A, 0)
// $38 - always $89 (PPI mode 0, ports A & B as output, port C as input)
MCFG_I8255_OUT_PORTA_CB(WRITE8(kopunch_state, lamp_w))
MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B", 0))
MCFG_I8255_OUT_PORTB_CB(LOGGER("PPI8255 - unmapped write port B"))
MCFG_I8255_IN_PORTC_CB(IOPORT("DSW"))
MCFG_DEVICE_ADD("ppi8255_3", I8255A, 0)

View File

@ -1688,13 +1688,10 @@ static MACHINE_CONFIG_START( coh700, namcos12_state )
MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
MCFG_RTC4543_DATA_CALLBACK(DEVWRITELINE("sub:sci1", h8_sci_device, rx_w))
MCFG_LINE_DISPATCH_ADD("clk_dispatch", 2)
MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
MCFG_DEVICE_MODIFY("sub:sci1")
MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":namco_settings", namco_settings_device, data_w))
MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":clk_dispatch", devcb_line_dispatch_device<2>, in_w))
MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
MCFG_AT28C16_ADD("at28c16", nullptr)

View File

@ -3566,13 +3566,10 @@ static MACHINE_CONFIG_START( gorgon, namcos23_state )
MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
MCFG_RTC4543_DATA_CALLBACK(DEVWRITELINE("subcpu:sci1", h8_sci_device, rx_w))
MCFG_LINE_DISPATCH_ADD("clk_dispatch", 2)
MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
MCFG_DEVICE_MODIFY("subcpu:sci1")
MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":namco_settings", namco_settings_device, data_w))
MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":clk_dispatch", devcb_line_dispatch_device<2>, in_w))
MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
MCFG_NVRAM_ADD_0FILL("nvram")
@ -3635,13 +3632,10 @@ static MACHINE_CONFIG_START( s23, namcos23_state )
MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
MCFG_RTC4543_DATA_CALLBACK(DEVWRITELINE("subcpu:sci1", h8_sci_device, rx_w))
MCFG_LINE_DISPATCH_ADD("clk_dispatch", 2)
MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
MCFG_DEVICE_MODIFY("subcpu:sci1")
MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":namco_settings", namco_settings_device, data_w))
MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":clk_dispatch", devcb_line_dispatch_device<2>, in_w))
MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
MCFG_NVRAM_ADD_0FILL("nvram")
@ -3715,13 +3709,10 @@ static MACHINE_CONFIG_START( ss23, namcos23_state )
MCFG_RTC4543_ADD("rtc", XTAL_32_768kHz)
MCFG_RTC4543_DATA_CALLBACK(DEVWRITELINE("subcpu:sci1", h8_sci_device, rx_w))
MCFG_LINE_DISPATCH_ADD("clk_dispatch", 2)
MCFG_LINE_DISPATCH_FWD_CB(0, 2, DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
MCFG_LINE_DISPATCH_FWD_CB(1, 2, DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
MCFG_DEVICE_MODIFY("subcpu:sci1")
MCFG_H8_SCI_TX_CALLBACK(DEVWRITELINE(":namco_settings", namco_settings_device, data_w))
MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":clk_dispatch", devcb_line_dispatch_device<2>, in_w))
MCFG_H8_SCI_CLK_CALLBACK(DEVWRITELINE(":rtc", rtc4543_device, clk_w)) MCFG_DEVCB_INVERT
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE(":namco_settings", namco_settings_device, clk_w))
MCFG_NVRAM_ADD_0FILL("nvram")