mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
devcb updates (nw)
- Write callbacks can now be configured as `OUTPUT("item_name")`. This behaves equivalently to a zero-dimensional `output_finder`, while eliminating the need to instantiate and resolve this in driver classes separately from the callback itself. - The width of a callback's default mask now properly depends on its type (as was half-implemented before), instead of always being reset to 0xffffffffffffffff when actually configured. This allows MCFG_DEVCB_INVERT to work with line write callbacks as one might logically expect.
This commit is contained in:
parent
9927ef4440
commit
1185fb25f3
@ -60,7 +60,7 @@ void devcb_base::reset(callback_type type)
|
||||
m_space = nullptr;
|
||||
m_target.ptr = nullptr;
|
||||
m_rshift = 0;
|
||||
m_mask = ~u64(0);
|
||||
m_mask = m_defmask;
|
||||
m_xor = 0;
|
||||
devcb_reset();
|
||||
}
|
||||
@ -100,6 +100,17 @@ void devcb_base::resolve_membank()
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// resolve_output - resolve an output item
|
||||
//-------------------------------------------------
|
||||
|
||||
void devcb_base::resolve_output()
|
||||
{
|
||||
assert(m_target_tag != nullptr);
|
||||
m_target.item = &m_device.machine().output().find_or_create_item(m_target_tag, 0);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// resolve_inputline - resolve a device and input
|
||||
// number or fatal error if we can't find it
|
||||
@ -254,6 +265,9 @@ void devcb_read_base::resolve()
|
||||
case CALLBACK_MEMBANK:
|
||||
throw emu_fatalerror("Device read callbacks can't be connected to bank switches\n");
|
||||
|
||||
case CALLBACK_OUTPUT:
|
||||
throw emu_fatalerror("Device read callbacks can't be connected to output items\n");
|
||||
|
||||
case CALLBACK_LOG:
|
||||
m_adapter = &devcb_read_base::read_logged_adapter;
|
||||
m_mask = 0;
|
||||
@ -444,6 +458,10 @@ void devcb_read_base::validity_check(validity_checker &valid) const
|
||||
osd_printf_error("Device read callbacks can't be connected to bank switches\n");
|
||||
break;
|
||||
|
||||
case CALLBACK_OUTPUT:
|
||||
osd_printf_error("Device read callbacks can't be connected to output items\n");
|
||||
break;
|
||||
|
||||
case CALLBACK_INPUTLINE:
|
||||
case CALLBACK_ASSERTLINE:
|
||||
case CALLBACK_CLEARLINE:
|
||||
@ -566,6 +584,11 @@ void devcb_write_base::resolve()
|
||||
m_adapter = (m_target.membank == nullptr) ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_membank_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_OUTPUT:
|
||||
resolve_output();
|
||||
m_adapter = (m_target.item == nullptr) ? &devcb_write_base::write_noop_adapter : &devcb_write_base::write_output_adapter;
|
||||
break;
|
||||
|
||||
case CALLBACK_LOG:
|
||||
m_adapter = &devcb_write_base::write_logged_adapter;
|
||||
break;
|
||||
@ -636,6 +659,7 @@ void devcb_write_base::validity_check(validity_checker &valid) const
|
||||
case CALLBACK_LOG:
|
||||
case CALLBACK_IOPORT:
|
||||
case CALLBACK_MEMBANK:
|
||||
case CALLBACK_OUTPUT:
|
||||
break;
|
||||
|
||||
case CALLBACK_LINE:
|
||||
@ -769,6 +793,17 @@ void devcb_write_base::write_membank_adapter(address_space &space, offs_t offset
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write_output_adapter - set an output item
|
||||
//-------------------------------------------------
|
||||
|
||||
void devcb_write_base::write_output_adapter(address_space &space, offs_t offset, u64 data, u64 mask)
|
||||
{
|
||||
if (m_target.item)
|
||||
m_target.item->set(unshift_mask_xor(data));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// write_logged_adapter - log write if masked
|
||||
// value is nonzero
|
||||
|
@ -26,6 +26,7 @@
|
||||
#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_OUTPUT(_tag) devcb_base::output_desc(_tag)
|
||||
#define DEVCB_CONSTANT(_value) devcb_base::constant_desc(_value)
|
||||
#define DEVCB_LOGGER(_string) devcb_base::logger_desc(_string)
|
||||
#define DEVCB_INPUTLINE(_tag, _line) devcb_base::inputline_desc(_tag, _line)
|
||||
@ -101,6 +102,7 @@ protected:
|
||||
CALLBACK_64,
|
||||
CALLBACK_IOPORT,
|
||||
CALLBACK_MEMBANK,
|
||||
CALLBACK_OUTPUT,
|
||||
CALLBACK_LOG,
|
||||
CALLBACK_CONSTANT,
|
||||
CALLBACK_INPUTLINE,
|
||||
@ -144,6 +146,13 @@ public:
|
||||
const char *m_tag;
|
||||
};
|
||||
|
||||
class output_desc
|
||||
{
|
||||
public:
|
||||
output_desc(const char *tag) { m_tag = tag; }
|
||||
const char *m_tag;
|
||||
};
|
||||
|
||||
class constant_desc
|
||||
{
|
||||
public:
|
||||
@ -194,6 +203,7 @@ public:
|
||||
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(output_desc output) { reset(CALLBACK_OUTPUT); m_target_tag = output.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_tag = logger.m_string; return *this; }
|
||||
void reset() { reset(CALLBACK_NONE); }
|
||||
@ -208,6 +218,7 @@ protected:
|
||||
virtual void devcb_reset() = 0;
|
||||
void resolve_ioport();
|
||||
void resolve_membank();
|
||||
void resolve_output();
|
||||
void resolve_inputline();
|
||||
void resolve_space();
|
||||
|
||||
@ -218,6 +229,7 @@ protected:
|
||||
device_t * device;
|
||||
ioport_port * ioport;
|
||||
memory_bank * membank;
|
||||
output_manager::output_item *item;
|
||||
};
|
||||
|
||||
// configuration
|
||||
@ -338,6 +350,7 @@ private:
|
||||
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_output_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);
|
||||
@ -364,7 +377,7 @@ private:
|
||||
class devcb_read_line : public devcb_read_base
|
||||
{
|
||||
public:
|
||||
devcb_read_line(device_t &device) : devcb_read_base(device, 0xff) { }
|
||||
devcb_read_line(device_t &device) : devcb_read_base(device, 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; }
|
||||
};
|
||||
@ -419,7 +432,7 @@ public:
|
||||
class devcb_write_line : public devcb_write_base
|
||||
{
|
||||
public:
|
||||
devcb_write_line(device_t &device) : devcb_write_base(device, 0xff) { }
|
||||
devcb_write_line(device_t &device) : devcb_write_base(device, 1) { }
|
||||
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); }
|
||||
};
|
||||
|
@ -58,9 +58,7 @@ void output_manager::output_item::notify(s32 value)
|
||||
void output_manager::item_proxy::resolve(device_t &device, std::string const &name)
|
||||
{
|
||||
assert(!m_item);
|
||||
m_item = device.machine().output().find_item(name.c_str());
|
||||
if (!m_item)
|
||||
m_item = &device.machine().output().create_new_item(name.c_str(), 0);
|
||||
m_item = &device.machine().output().find_or_create_item(name.c_str(), 0);
|
||||
}
|
||||
|
||||
|
||||
@ -110,6 +108,12 @@ output_manager::output_item &output_manager::create_new_item(const char *outname
|
||||
return ins.first->second;
|
||||
}
|
||||
|
||||
output_manager::output_item &output_manager::find_or_create_item(const char *outname, s32 value)
|
||||
{
|
||||
output_item *const item = find_item(outname);
|
||||
return item ? *item : create_new_item(outname, value);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
output_pause - send pause message
|
||||
-------------------------------------------------*/
|
||||
|
@ -27,6 +27,9 @@ typedef void (*output_notifier_func)(const char *outname, s32 value, void *param
|
||||
|
||||
class output_manager
|
||||
{
|
||||
friend class devcb_base;
|
||||
friend class devcb_write_base;
|
||||
|
||||
private:
|
||||
class output_notify
|
||||
{
|
||||
@ -190,6 +193,7 @@ private:
|
||||
|
||||
output_item *find_item(const char *string);
|
||||
output_item &create_new_item(const char *outname, s32 value);
|
||||
output_item &find_or_create_item(const char *outname, s32 value);
|
||||
|
||||
// internal state
|
||||
running_machine &m_machine; // reference to our machine
|
||||
|
Loading…
Reference in New Issue
Block a user