mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Register device callbacks and add some basic validation for them
This commit is contained in:
parent
5f9a181487
commit
12cf6b64eb
@ -149,6 +149,7 @@ devcb_read_base::devcb_read_base(device_t &device, u64 defmask)
|
||||
: devcb_base(device, defmask),
|
||||
m_adapter(&devcb_read_base::read_unresolved_adapter)
|
||||
{
|
||||
device.m_input_callbacks.push_back(this);
|
||||
}
|
||||
|
||||
|
||||
@ -200,75 +201,75 @@ void devcb_read_base::resolve()
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case CALLBACK_NONE:
|
||||
break;
|
||||
case CALLBACK_NONE:
|
||||
break;
|
||||
|
||||
case CALLBACK_LINE:
|
||||
name = m_readline.name();
|
||||
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_LINE:
|
||||
name = m_readline.name();
|
||||
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:
|
||||
name = m_read8.name();
|
||||
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_8:
|
||||
name = m_read8.name();
|
||||
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:
|
||||
name = m_read16.name();
|
||||
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_16:
|
||||
name = m_read16.name();
|
||||
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:
|
||||
name = m_read32.name();
|
||||
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_32:
|
||||
name = m_read32.name();
|
||||
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:
|
||||
name = m_read64.name();
|
||||
m_read64.bind_relative_to(*m_device.owner());
|
||||
m_target_int = 0;
|
||||
m_adapter = m_read64.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read64_adapter;
|
||||
break;
|
||||
case CALLBACK_64:
|
||||
name = m_read64.name();
|
||||
m_read64.bind_relative_to(*m_device.owner());
|
||||
m_target_int = 0;
|
||||
m_adapter = m_read64.isnull() ? &devcb_read_base::read_constant_adapter : &devcb_read_base::read64_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_IOPORT:
|
||||
name = m_target_tag;
|
||||
resolve_ioport();
|
||||
m_target_int = 0;
|
||||
m_adapter = &devcb_read_base::read_ioport_adapter;
|
||||
break;
|
||||
case CALLBACK_IOPORT:
|
||||
name = m_target_tag;
|
||||
resolve_ioport();
|
||||
m_target_int = 0;
|
||||
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_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_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_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:
|
||||
case CALLBACK_HOLDLINE:
|
||||
throw emu_fatalerror("Device read callbacks can't be connected to input lines\n");
|
||||
case CALLBACK_INPUTLINE:
|
||||
case CALLBACK_ASSERTLINE:
|
||||
case CALLBACK_CLEARLINE:
|
||||
case CALLBACK_HOLDLINE:
|
||||
throw emu_fatalerror("Device read callbacks can't be connected to input lines\n");
|
||||
}
|
||||
}
|
||||
catch (binding_type_exception &binderr)
|
||||
@ -398,6 +399,63 @@ u64 devcb_read_base::read_constant_adapter(address_space &space, offs_t offset,
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// validity_check - check the validity of the
|
||||
// callback object
|
||||
//-------------------------------------------------
|
||||
|
||||
void devcb_read_base::validity_check(validity_checker &valid) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case CALLBACK_NONE:
|
||||
case CALLBACK_CONSTANT:
|
||||
case CALLBACK_LOG:
|
||||
case CALLBACK_IOPORT:
|
||||
break;
|
||||
|
||||
case CALLBACK_LINE:
|
||||
if (m_device.owner()->subdevice(m_readline.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for READLINE callback (%s)\n", m_readline.device_name(), m_readline.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_8:
|
||||
if (m_device.owner()->subdevice(m_read8.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for READ8 callback (%s)\n", m_read8.device_name(), m_read8.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_16:
|
||||
if (m_device.owner()->subdevice(m_read16.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for READ16 callback (%s)\n", m_read16.device_name(), m_read16.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_32:
|
||||
if (m_device.owner()->subdevice(m_read32.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for READ32 callback (%s)\n", m_read32.device_name(), m_read32.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_64:
|
||||
if (m_device.owner()->subdevice(m_read64.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for READ64 callback (%s)\n", m_read64.device_name(), m_read64.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_MEMBANK:
|
||||
osd_printf_error("Device read callbacks can't be connected to bank switches\n");
|
||||
break;
|
||||
|
||||
case CALLBACK_INPUTLINE:
|
||||
case CALLBACK_ASSERTLINE:
|
||||
case CALLBACK_CLEARLINE:
|
||||
case CALLBACK_HOLDLINE:
|
||||
throw emu_fatalerror("Device read callbacks can't be connected to input lines\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_chain != nullptr)
|
||||
m_chain->validity_check(valid);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVCB WRITE CLASS
|
||||
@ -411,6 +469,7 @@ devcb_write_base::devcb_write_base(device_t &device, u64 defmask)
|
||||
: devcb_base(device, defmask),
|
||||
m_adapter(&devcb_write_base::write_unresolved_adapter)
|
||||
{
|
||||
device.m_output_callbacks.push_back(this);
|
||||
}
|
||||
|
||||
|
||||
@ -462,76 +521,76 @@ void devcb_write_base::resolve()
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case CALLBACK_NONE:
|
||||
break;
|
||||
case CALLBACK_NONE:
|
||||
break;
|
||||
|
||||
case CALLBACK_LINE:
|
||||
name = m_writeline.name();
|
||||
m_writeline.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_writeline.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_line_adapter;
|
||||
break;
|
||||
case CALLBACK_LINE:
|
||||
name = m_writeline.name();
|
||||
m_writeline.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_writeline.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_line_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_8:
|
||||
name = m_write8.name();
|
||||
m_write8.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_write8.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write8_adapter;
|
||||
break;
|
||||
case CALLBACK_8:
|
||||
name = m_write8.name();
|
||||
m_write8.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_write8.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write8_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_16:
|
||||
name = m_write16.name();
|
||||
m_write16.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_write16.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write16_adapter;
|
||||
break;
|
||||
case CALLBACK_16:
|
||||
name = m_write16.name();
|
||||
m_write16.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_write16.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write16_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_32:
|
||||
name = m_write32.name();
|
||||
m_write32.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_write32.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write32_adapter;
|
||||
break;
|
||||
case CALLBACK_32:
|
||||
name = m_write32.name();
|
||||
m_write32.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_write32.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write32_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_64:
|
||||
name = m_write64.name();
|
||||
m_write64.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_write64.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write64_adapter;
|
||||
break;
|
||||
case CALLBACK_64:
|
||||
name = m_write64.name();
|
||||
m_write64.bind_relative_to(*m_device.owner());
|
||||
m_adapter = m_write64.isnull() ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write64_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_IOPORT:
|
||||
resolve_ioport();
|
||||
m_adapter = (m_target.ioport == nullptr) ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_ioport_adapter;
|
||||
break;
|
||||
case CALLBACK_IOPORT:
|
||||
resolve_ioport();
|
||||
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_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;
|
||||
case CALLBACK_LOG:
|
||||
m_adapter = &devcb_write_base::write_logged_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_CONSTANT:
|
||||
m_adapter = &devcb_write_base::write_noop_adapter;
|
||||
break;
|
||||
case CALLBACK_CONSTANT:
|
||||
m_adapter = &devcb_write_base::write_noop_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_INPUTLINE:
|
||||
resolve_inputline();
|
||||
m_adapter = &devcb_write_base::write_inputline_adapter;
|
||||
break;
|
||||
case CALLBACK_INPUTLINE:
|
||||
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_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;
|
||||
case CALLBACK_CLEARLINE:
|
||||
resolve_inputline();
|
||||
m_adapter = &devcb_write_base::write_clearline_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_HOLDLINE:
|
||||
resolve_inputline();
|
||||
m_adapter = &devcb_write_base::write_holdline_adapter;
|
||||
break;
|
||||
case CALLBACK_HOLDLINE:
|
||||
resolve_inputline();
|
||||
m_adapter = &devcb_write_base::write_holdline_adapter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (binding_type_exception &binderr)
|
||||
@ -559,6 +618,70 @@ void devcb_write_base::resolve_safe()
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// validity_check - check the validity of the
|
||||
// callback object
|
||||
//-------------------------------------------------
|
||||
|
||||
void devcb_write_base::validity_check(validity_checker &valid) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case CALLBACK_NONE:
|
||||
case CALLBACK_CONSTANT:
|
||||
case CALLBACK_LOG:
|
||||
case CALLBACK_IOPORT:
|
||||
case CALLBACK_MEMBANK:
|
||||
break;
|
||||
|
||||
case CALLBACK_LINE:
|
||||
if (m_device.owner()->subdevice(m_writeline.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for WRITELINE callback (%s)\n", m_writeline.device_name(), m_writeline.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_8:
|
||||
if (m_device.owner()->subdevice(m_write8.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for WRITE8 callback (%s)\n", m_write8.device_name(), m_write8.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_16:
|
||||
if (m_device.owner()->subdevice(m_write16.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for WRITE16 callback (%s)\n", m_write16.device_name(), m_write16.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_32:
|
||||
if (m_device.owner()->subdevice(m_write32.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for WRITE32 callback (%s)\n", m_write32.device_name(), m_write32.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_64:
|
||||
if (m_device.owner()->subdevice(m_write64.device_name()) == nullptr)
|
||||
osd_printf_error("Device %s not found for WRITE64 callback (%s)\n", m_write64.device_name(), m_write64.name());
|
||||
break;
|
||||
|
||||
case CALLBACK_INPUTLINE:
|
||||
case CALLBACK_ASSERTLINE:
|
||||
case CALLBACK_CLEARLINE:
|
||||
case CALLBACK_HOLDLINE:
|
||||
{
|
||||
device_t *device = m_device.owner()->subdevice(m_target_tag);
|
||||
if (device == nullptr)
|
||||
osd_printf_error("Device %s not found for INPUTLINE callback (%d)\n", m_target_tag, int(m_target_int));
|
||||
else
|
||||
{
|
||||
device_execute_interface *execute;
|
||||
if (!device->interface(execute))
|
||||
osd_printf_error("Device %s has no interface for INPUTLINE callback (%d)\n", m_target_tag, int(m_target_int));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_chain != nullptr)
|
||||
m_chain->validity_check(valid);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write_unresolved_adapter - error-generating
|
||||
// unresolved adapter
|
||||
|
@ -260,6 +260,9 @@ public:
|
||||
void resolve();
|
||||
void resolve_safe(u64 none_constant_value);
|
||||
|
||||
// validity checking
|
||||
void validity_check(validity_checker &valid) const;
|
||||
|
||||
protected:
|
||||
// internal helpers
|
||||
virtual void devcb_reset() override;
|
||||
@ -317,6 +320,9 @@ public:
|
||||
void resolve();
|
||||
void resolve_safe();
|
||||
|
||||
// validity checking
|
||||
void validity_check(validity_checker &valid) const;
|
||||
|
||||
protected:
|
||||
// internal helpers
|
||||
virtual void devcb_reset() override;
|
||||
|
@ -330,6 +330,8 @@ class device_t : public delegate_late_bind
|
||||
friend class simple_list<device_t>;
|
||||
friend class running_machine;
|
||||
friend class finder_base;
|
||||
friend class devcb_read_base;
|
||||
friend class devcb_write_base;
|
||||
|
||||
class subdevice_list
|
||||
{
|
||||
@ -477,6 +479,8 @@ public:
|
||||
// owned object helpers
|
||||
subdevice_list &subdevices() { return m_subdevices; }
|
||||
const subdevice_list &subdevices() const { return m_subdevices; }
|
||||
const std::list<devcb_read_base *> input_callbacks() const { return m_input_callbacks; }
|
||||
const std::list<devcb_write_base *> output_callbacks() const { return m_output_callbacks; }
|
||||
|
||||
// device-relative tag lookups
|
||||
std::string subtag(const char *tag) const;
|
||||
@ -613,6 +617,8 @@ private:
|
||||
bool m_started; // true if the start function has succeeded
|
||||
finder_base * m_auto_finder_list; // list of objects to auto-find
|
||||
mutable std::vector<rom_entry> m_rom_entries;
|
||||
std::list<devcb_read_base *> m_input_callbacks;
|
||||
std::list<devcb_write_base *> m_output_callbacks;
|
||||
|
||||
// string formatting buffer for logerror
|
||||
mutable util::ovectorstream m_string_buffer;
|
||||
|
@ -97,6 +97,10 @@ class symbol_table;
|
||||
// declared in debugger.h
|
||||
class debugger_manager;
|
||||
|
||||
// declared in devcb.h
|
||||
class devcb_read_base;
|
||||
class devcb_write_base;
|
||||
|
||||
// declared in devfind.h
|
||||
class finder_base;
|
||||
|
||||
|
@ -1922,6 +1922,12 @@ void validity_checker::validate_devices()
|
||||
device.findit(true, true);
|
||||
device.findit(false, true);
|
||||
|
||||
// validate callbacks
|
||||
for (auto &cb : device.input_callbacks())
|
||||
cb->validity_check(*this);
|
||||
for (auto &cb : device.output_callbacks())
|
||||
cb->validity_check(*this);
|
||||
|
||||
// validate the device tag
|
||||
validate_tag(device.basetag());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user