diff --git a/src/emu/devcb.cpp b/src/emu/devcb.cpp index 540c8d249c9..fe8deacfba1 100644 --- a/src/emu/devcb.cpp +++ b/src/emu/devcb.cpp @@ -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 diff --git a/src/emu/devcb.h b/src/emu/devcb.h index 20d19161bff..bbfc273f0be 100644 --- a/src/emu/devcb.h +++ b/src/emu/devcb.h @@ -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); } }; diff --git a/src/emu/output.cpp b/src/emu/output.cpp index f31bb0a8e52..5969d1dbfc5 100644 --- a/src/emu/output.cpp +++ b/src/emu/output.cpp @@ -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 -------------------------------------------------*/ diff --git a/src/emu/output.h b/src/emu/output.h index f5f06511b16..d766f9dd853 100644 --- a/src/emu/output.h +++ b/src/emu/output.h @@ -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