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:
AJR 2018-04-29 19:48:38 -04:00
parent 9927ef4440
commit 1185fb25f3
4 changed files with 62 additions and 6 deletions

View File

@ -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

View File

@ -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); }
};

View File

@ -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
-------------------------------------------------*/

View File

@ -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