summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2018-05-02 14:43:01 +1000
committer Vas Crabb <vas@vastheman.com>2018-05-02 14:43:01 +1000
commit8795d808087298025e66c818482f9d9b68968f1f (patch)
tree2b5edb3d3778917a83f28d7f613c5caf2f11b60c /src/emu
parent7c8d486909ffda985e169c454874cc08733f7ed6 (diff)
Allow devcb to be bound to a device/mixin or the target of a device
finder. This works outside machine configuration context so the workarounds in ATA HLE and MSX slots are no longer necessary. It also allows reduction in tag repetition in machine configuration (see converted osborne1.cpp, zorba.cpp or the more extreme tranz330.cpp). Allow reimagined device instantiation to take a device finder based on current device being configured to reduce repetition (see tranz330.cpp).
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/devcb.h362
-rw-r--r--src/emu/devdelegate.h66
-rw-r--r--src/emu/devfind.h12
-rw-r--r--src/emu/device.h1
-rw-r--r--src/emu/device.ipp27
-rw-r--r--src/emu/emu.h2
-rw-r--r--src/emu/emufwd.h1
-rw-r--r--src/emu/mconfig.h11
8 files changed, 325 insertions, 157 deletions
diff --git a/src/emu/devcb.h b/src/emu/devcb.h
index f884dc7a517..fee31ce1ca4 100644
--- a/src/emu/devcb.h
+++ b/src/emu/devcb.h
@@ -18,53 +18,125 @@
#define MAME_EMU_DEVCB_H
#include <functional>
+#include <type_traits>
+#include <utility>
+
+
+namespace emu { namespace detail {
+
+template <typename Delegate> struct devcb_delegate_initialiser
+{
+ template <typename T> struct is_device_implementation
+ { static constexpr bool value = std::is_base_of<device_t, T>::value; };
+ template <typename T> struct is_device_interface
+ { static constexpr bool value = std::is_base_of<device_interface, T>::value && !is_device_implementation<T>::value; };
+
+ devcb_delegate_initialiser(char const *tag, Delegate &&delegate) : m_base(nullptr), m_delegate(std::move(delegate))
+ {
+ }
+ template <typename T>
+ devcb_delegate_initialiser(T &device, std::enable_if_t<is_device_implementation<T>::value, Delegate &&> delegate) : m_base(&device), m_delegate(std::move(delegate))
+ {
+ }
+ template <typename T>
+ devcb_delegate_initialiser(T &interface, std::enable_if_t<is_device_interface<T>::value, Delegate &&> delegate) : m_base(&interface.device()), m_delegate(std::move(delegate))
+ {
+ }
+ template <typename DeviceClass, bool Required>
+ devcb_delegate_initialiser(device_finder<DeviceClass, Required> const &finder, Delegate &&delegate) : m_base(&finder.finder_target().first), m_delegate(std::move(delegate))
+ {
+ }
+
+ device_t *m_base;
+ Delegate &&m_delegate;
+};
+
+inline char const *devcb_delegate_get_tag(char const *tag) { return tag; }
+template <typename T>
+inline std::enable_if_t<devcb_delegate_initialiser<bool>::is_device_implementation<T>::value, char const *> devcb_delegate_get_tag(T &device) { return DEVICE_SELF; }
+template <typename T>
+inline std::enable_if_t<devcb_delegate_initialiser<bool>::is_device_interface<T>::value, char const *> devcb_delegate_get_tag(T &interface) { return DEVICE_SELF; }
+template <typename DeviceClass, bool Required>
+inline char const *devcb_delegate_get_tag(device_finder<DeviceClass, Required> const &finder) { return finder.finder_tag(); }
+
+template <typename DescType> struct devcb_tag_desc_creator
+{
+ static DescType create(char const *tag)
+ {
+ return DescType{ nullptr, tag };
+ }
+ static DescType create(device_t &device)
+ {
+ return DescType{ &device, DEVICE_SELF };
+ }
+ static DescType create(device_interface &interface)
+ {
+ return DescType{ &interface.device(), DEVICE_SELF };
+ }
+ template <typename DeviceClass, bool Required>
+ static DescType create(device_finder<DeviceClass, Required> const &finder)
+ {
+ std::pair<device_t &, char const *> const target(finder.finder_target());
+ return DescType{ &target.first, target.second };
+ }
+};
+
+template <typename DescType> struct devcb_line_desc_creator
+{
+ static DescType create(char const *tag, int inputnum)
+ {
+ return DescType{ nullptr, tag, inputnum };
+ }
+ static DescType create(device_t &device, int inputnum)
+ {
+ return DescType{ &device, DEVICE_SELF, inputnum };
+ }
+ static DescType create(device_interface &interface, int inputnum)
+ {
+ return DescType{ &interface.device(), DEVICE_SELF, inputnum };
+ }
+ template <typename DeviceClass, bool Required>
+ static DescType create(device_finder<DeviceClass, Required> const &finder, int inputnum)
+ {
+ std::pair<device_t &, char const *> const target(finder.finder_target());
+ return DescType{ &target.first, target.second, inputnum };
+ }
+};
+
+} } // namespace emu::detail
//**************************************************************************
// MACROS
//**************************************************************************
-// 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_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)
-#define DEVCB_ASSERTLINE(_tag, _line) devcb_base::assertline_desc(_tag, _line)
-#define DEVCB_CLEARLINE(_tag, _line) devcb_base::clearline_desc(_tag, _line)
-#define DEVCB_HOLDLINE(_tag, _line) devcb_base::holdline_desc(_tag, _line)
-#define DEVCB_VCC DEVCB_CONSTANT(1)
-#define DEVCB_GND DEVCB_CONSTANT(0)
-
// wrappers for read callbacks into the owner device
-#define DEVCB_READLINE(_class, _func) read_line_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
-#define DEVCB_READ8(_class, _func) read8_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
-#define DEVCB_READ16(_class, _func) read16_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
-#define DEVCB_READ32(_class, _func) read32_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
-#define DEVCB_READ64(_class, _func) read64_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
+#define DEVCB_READLINE(_class, _func) (emu::detail::devcb_delegate_initialiser<read_line_delegate>(DEVICE_SELF, read_line_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
+#define DEVCB_READ8(_class, _func) (emu::detail::devcb_delegate_initialiser<read8_delegate>(DEVICE_SELF, read8_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
+#define DEVCB_READ16(_class, _func) (emu::detail::devcb_delegate_initialiser<read16_delegate>(DEVICE_SELF, read16_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
+#define DEVCB_READ32(_class, _func) (emu::detail::devcb_delegate_initialiser<read32_delegate>(DEVICE_SELF, read32_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
+#define DEVCB_READ64(_class, _func) (emu::detail::devcb_delegate_initialiser<read64_delegate>(DEVICE_SELF, read64_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
// wrappers for read callbacks into any tagged device
-#define DEVCB_DEVREADLINE(tag, _class, _func) read_line_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
-#define DEVCB_DEVREAD8(tag, _class, _func) read8_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
-#define DEVCB_DEVREAD16(tag, _class, _func) read16_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
-#define DEVCB_DEVREAD32(tag, _class, _func) read32_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
-#define DEVCB_DEVREAD64(tag, _class, _func) read64_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
+#define DEVCB_DEVREADLINE(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<read_line_delegate>((tag), read_line_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
+#define DEVCB_DEVREAD8(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<read8_delegate>((tag), read8_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
+#define DEVCB_DEVREAD16(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<read16_delegate>((tag), read16_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
+#define DEVCB_DEVREAD32(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<read32_delegate>((tag), read32_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
+#define DEVCB_DEVREAD64(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<read64_delegate>((tag), read64_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
// wrappers for write callbacks into the owner device
-#define DEVCB_WRITELINE(_class, _func) write_line_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
-#define DEVCB_WRITE8(_class, _func) write8_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
-#define DEVCB_WRITE16(_class, _func) write16_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
-#define DEVCB_WRITE32(_class, _func) write32_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
-#define DEVCB_WRITE64(_class, _func) write64_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)
+#define DEVCB_WRITELINE(_class, _func) (emu::detail::devcb_delegate_initialiser<write_line_delegate>(DEVICE_SELF, write_line_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
+#define DEVCB_WRITE8(_class, _func) (emu::detail::devcb_delegate_initialiser<write8_delegate>(DEVICE_SELF, write8_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
+#define DEVCB_WRITE16(_class, _func) (emu::detail::devcb_delegate_initialiser<write16_delegate>(DEVICE_SELF, write16_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
+#define DEVCB_WRITE32(_class, _func) (emu::detail::devcb_delegate_initialiser<write32_delegate>(DEVICE_SELF, write32_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
+#define DEVCB_WRITE64(_class, _func) (emu::detail::devcb_delegate_initialiser<write64_delegate>(DEVICE_SELF, write64_delegate(&_class::_func, #_class "::" #_func, DEVICE_SELF, (_class *)nullptr)))
// wrappers for write callbacks into any tagged device
-#define DEVCB_DEVWRITELINE(tag, _class, _func) write_line_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
-#define DEVCB_DEVWRITE8(tag, _class, _func) write8_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
-#define DEVCB_DEVWRITE16(tag, _class, _func) write16_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
-#define DEVCB_DEVWRITE32(tag, _class, _func) write32_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
-#define DEVCB_DEVWRITE64(tag, _class, _func) write64_delegate(&_class::_func, #_class "::" #_func, tag, (_class *)nullptr)
+#define DEVCB_DEVWRITELINE(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<write_line_delegate>((tag), write_line_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
+#define DEVCB_DEVWRITE8(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<write8_delegate>((tag), write8_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
+#define DEVCB_DEVWRITE16(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<write16_delegate>((tag), write16_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
+#define DEVCB_DEVWRITE32(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<write32_delegate>((tag), write32_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
+#define DEVCB_DEVWRITE64(tag, _class, _func) (emu::detail::devcb_delegate_initialiser<write64_delegate>((tag), write64_delegate(&_class::_func, #_class "::" #_func, emu::detail::devcb_delegate_get_tag(tag), (_class *)nullptr)))
// machine config helpers to add shift, mask, or address space configuration
#define MCFG_DEVCB_RSHIFT(_shift) devcb->set_rshift(_shift);
@@ -117,6 +189,21 @@ protected:
devcb_base(device_t &device, u64 defmask);
virtual ~devcb_base();
+ template <callback_type Type> struct tag_desc
+ {
+ constexpr tag_desc(device_t *base, char const *tag) : m_base(base), m_tag(tag) { }
+ device_t *m_base;
+ char const *m_tag;
+ };
+
+ template <callback_type Type> struct line_desc
+ {
+ constexpr line_desc(device_t *base, char const *tag, int inputnum) : m_base(base), m_tag(tag), m_inputnum(inputnum) { }
+ device_t *m_base;
+ char const *m_tag;
+ int m_inputnum;
+ };
+
public:
// getters
bool isnull() const { return (m_type == CALLBACK_NONE); }
@@ -128,84 +215,38 @@ public:
devcb_base &set_xor(u64 xorval) { m_xor = xorval; return *this; }
// construction helper classes
- class null_desc
- {
- public:
- null_desc() { }
- };
-
- class ioport_desc
- {
- public:
- ioport_desc(const char *tag) { m_tag = tag; }
- const char *m_tag;
- };
-
- class membank_desc
+ struct null_desc
{
- public:
- membank_desc(const char *tag) { m_tag = tag; }
- const char *m_tag;
};
- class output_desc
- {
- public:
- output_desc(const char *tag) { m_tag = tag; }
- const char *m_tag;
- };
+ using ioport_desc = tag_desc<CALLBACK_IOPORT>;
+ using membank_desc = tag_desc<CALLBACK_MEMBANK>;
+ using output_desc = tag_desc<CALLBACK_OUTPUT>;
- class constant_desc
+ struct constant_desc
{
- public:
- constant_desc(u64 value) { m_value = value; }
u64 m_value;
};
- class logger_desc
+ struct logger_desc
{
- public:
- logger_desc(const char *string) { m_string = string; }
const char *m_string;
};
- class inputline_desc
- {
- public:
- inputline_desc(const char *tag, int inputnum) { m_tag = tag; m_inputnum = inputnum; }
- const char *m_tag;
- 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;
- };
-
- class holdline_desc
- {
- public:
- holdline_desc(const char *tag, int inputnum) { m_tag = tag; m_inputnum = inputnum; }
- const char *m_tag;
- int m_inputnum;
- };
+ using inputline_desc = line_desc<CALLBACK_INPUTLINE>;
+ using assertline_desc = line_desc<CALLBACK_ASSERTLINE>;
+ using clearline_desc = line_desc<CALLBACK_CLEARLINE>;
+ using holdline_desc = line_desc<CALLBACK_HOLDLINE>;
// 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(output_desc output) { reset(CALLBACK_OUTPUT); m_target_tag = output.m_tag; return *this; }
+ template <callback_type Type> devcb_base &set_callback(tag_desc<Type> desc)
+ {
+ if (desc.m_base) reset(*desc.m_base, Type);
+ else reset(Type);
+ m_target_tag = desc.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(m_owner, CALLBACK_NONE); }
@@ -262,14 +303,52 @@ protected:
// construction/destruction
devcb_read_base(device_t &device, u64 defmask, bool chained = false);
+ template <typename Delegate, typename Dummy> struct set_helper
+ {
+ static constexpr bool valid = false;
+ };
+ template <typename Dummy> struct set_helper<read_line_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_LINE;
+ static void apply(devcb_read_base &devcb, read_line_delegate &&delegate) { devcb.m_readline = std::move(delegate); }
+ };
+ template <typename Dummy> struct set_helper<read8_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_8;
+ static void apply(devcb_read_base &devcb, read8_delegate &&delegate) { devcb.m_read8 = std::move(delegate); }
+ };
+ template <typename Dummy> struct set_helper<read16_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_16;
+ static void apply(devcb_read_base &devcb, read16_delegate &&delegate) { devcb.m_read16 = std::move(delegate); }
+ };
+ template <typename Dummy> struct set_helper<read32_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_32;
+ static void apply(devcb_read_base &devcb, read32_delegate &&delegate) { devcb.m_read32 = std::move(delegate); }
+ };
+ template <typename Dummy> struct set_helper<read64_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_64;
+ static void apply(devcb_read_base &devcb, read64_delegate &&delegate) { devcb.m_read64 = std::move(delegate); }
+ };
+
public:
// callback configuration
using devcb_base::set_callback;
- devcb_base &set_callback(read_line_delegate func) { reset(CALLBACK_LINE); m_readline = func; return *this; }
- devcb_base &set_callback(read8_delegate func) { reset(CALLBACK_8); m_read8 = func; return *this; }
- 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; }
+ template <typename Delegate>
+ std::enable_if_t<set_helper<Delegate, void>::valid, devcb_base &> set_callback(emu::detail::devcb_delegate_initialiser<Delegate> &&desc)
+ {
+ if (desc.m_base) reset(*desc.m_base, set_helper<Delegate, void>::type);
+ else reset(set_helper<Delegate, void>::type);
+ set_helper<Delegate, void>::apply(*this, std::move(desc.m_delegate));
+ return *this;
+ }
devcb_read_base &chain_alloc();
// resolution
@@ -318,18 +397,60 @@ protected:
// construction/destruction
devcb_write_base(device_t &device, u64 defmask, bool chained = false);
+ template <typename Delegate, typename Dummy> struct set_helper
+ {
+ static constexpr bool valid = false;
+ };
+ template <typename Dummy> struct set_helper<write_line_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_LINE;
+ static void apply(devcb_write_base &devcb, write_line_delegate &&delegate) { devcb.m_writeline = std::move(delegate); }
+ };
+ template <typename Dummy> struct set_helper<write8_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_8;
+ static void apply(devcb_write_base &devcb, write8_delegate &&delegate) { devcb.m_write8 = std::move(delegate); }
+ };
+ template <typename Dummy> struct set_helper<write16_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_16;
+ static void apply(devcb_write_base &devcb, write16_delegate &&delegate) { devcb.m_write16 = std::move(delegate); }
+ };
+ template <typename Dummy> struct set_helper<write32_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_32;
+ static void apply(devcb_write_base &devcb, write32_delegate &&delegate) { devcb.m_write32 = std::move(delegate); }
+ };
+ template <typename Dummy> struct set_helper<write64_delegate, Dummy>
+ {
+ static constexpr bool valid = true;
+ static constexpr callback_type type = CALLBACK_64;
+ static void apply(devcb_write_base &devcb, write64_delegate &&delegate) { devcb.m_write64 = std::move(delegate); }
+ };
+
public:
// callback configuration
using devcb_base::set_callback;
- devcb_base &set_callback(write_line_delegate func) { reset(CALLBACK_LINE); m_writeline = func; return *this; }
- devcb_base &set_callback(write8_delegate func) { reset(CALLBACK_8); m_write8 = func; return *this; }
- 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_base &set_callback(holdline_desc inputline) { reset(CALLBACK_HOLDLINE); m_target_tag = inputline.m_tag; m_target_int = inputline.m_inputnum; return *this; }
+ template <typename Delegate>
+ std::enable_if_t<set_helper<Delegate, void>::valid, devcb_base &> set_callback(emu::detail::devcb_delegate_initialiser<Delegate> &&desc)
+ {
+ if (desc.m_base) reset(*desc.m_base, set_helper<Delegate, void>::type);
+ else reset(set_helper<Delegate, void>::type);
+ set_helper<Delegate, void>::apply(*this, std::move(desc.m_delegate));
+ return *this;
+ }
+ template <callback_type Type> devcb_base &set_callback(line_desc<Type> desc)
+ {
+ if (desc.m_base) reset(*desc.m_base, Type);
+ else reset(Type);
+ m_target_tag = desc.m_tag;
+ m_target_int = desc.m_inputnum;
+ return *this;
+ }
devcb_write_base &chain_alloc();
// resolution
@@ -520,4 +641,21 @@ inline void devcb_write_base::write(address_space &space, offs_t offset, u64 dat
}
-#endif /* MAME_EMU_DEVCB_H */
+//-------------------------------------------------
+// wrappers for ioports, constants, and loggers
+//-------------------------------------------------
+
+#define DEVCB_NOOP devcb_base::null_desc{ }
+template <typename... Params> inline devcb_base::ioport_desc DEVCB_IOPORT(Params &&... args) { return emu::detail::devcb_tag_desc_creator<devcb_base::ioport_desc>::create(std::forward<Params>(args)...); }
+template <typename... Params> inline devcb_base::membank_desc DEVCB_MEMBANK(Params &&... args) { return emu::detail::devcb_tag_desc_creator<devcb_base::membank_desc>::create(std::forward<Params>(args)...); }
+template <typename... Params> inline devcb_base::output_desc DEVCB_OUTPUT(Params &&... args) { return emu::detail::devcb_tag_desc_creator<devcb_base::output_desc>::create(std::forward<Params>(args)...); }
+inline devcb_base::constant_desc DEVCB_CONSTANT(u64 value) { return devcb_base::constant_desc{ value }; }
+inline devcb_base::logger_desc DEVCB_LOGGER(char const *string) { return devcb_base::logger_desc{ string }; }
+template <typename... Params> inline devcb_base::inputline_desc DEVCB_INPUTLINE(Params &&... args) { return emu::detail::devcb_line_desc_creator<devcb_base::inputline_desc>::create(std::forward<Params>(args)...); }
+template <typename... Params> inline devcb_base::assertline_desc DEVCB_ASSERTLINE(Params &&... args) { return emu::detail::devcb_line_desc_creator<devcb_base::assertline_desc>::create(std::forward<Params>(args)...); }
+template <typename... Params> inline devcb_base::clearline_desc DEVCB_CLEARLINE(Params &&... args) { return emu::detail::devcb_line_desc_creator<devcb_base::clearline_desc>::create(std::forward<Params>(args)...); }
+template <typename... Params> inline devcb_base::holdline_desc DEVCB_HOLDLINE(Params &&... args) { return emu::detail::devcb_line_desc_creator<devcb_base::holdline_desc>::create(std::forward<Params>(args)...); }
+#define DEVCB_VCC DEVCB_CONSTANT(1)
+#define DEVCB_GND DEVCB_CONSTANT(0)
+
+#endif // MAME_EMU_DEVCB_H
diff --git a/src/emu/devdelegate.h b/src/emu/devdelegate.h
index 96d9512d79b..544253ecfda 100644
--- a/src/emu/devdelegate.h
+++ b/src/emu/devdelegate.h
@@ -39,24 +39,30 @@ protected:
// ======================> named_delegate
-template<typename _Signature>
-class named_delegate : public delegate<_Signature>
+template <typename Signature>
+class named_delegate : public delegate<Signature>
{
- typedef delegate<_Signature> basetype;
+protected:
+ using basetype = delegate<Signature>;
+ template <class FunctionClass> using member_func_type = typename basetype::template traits<FunctionClass>::member_func_type;
+ template <class FunctionClass> using const_member_func_type = typename basetype::template traits<FunctionClass>::const_member_func_type;
+ template <class FunctionClass> using static_func_type = typename basetype::template traits<FunctionClass>::static_func_type;
+ template <class FunctionClass> using static_ref_func_type = typename basetype::template traits<FunctionClass>::static_ref_func_type;
public:
// create a standard set of constructors
named_delegate() : basetype(), m_name(nullptr) { }
explicit named_delegate(const basetype &src) : basetype(src), m_name(src.m_name) { }
named_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), m_name(src.m_name) { }
- template<class _FunctionClass> named_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
- template<class _FunctionClass> named_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
- explicit named_delegate(std::function<_Signature> funcptr, const char *name) : basetype(funcptr), m_name(name) { }
- template<class _FunctionClass> named_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
- template<class _FunctionClass> named_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
- named_delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; m_name = src.m_name; return *this; }
+ template <class FunctionClass> named_delegate(member_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
+ template <class FunctionClass> named_delegate(const_member_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
+ explicit named_delegate(std::function<Signature> funcptr, const char *name) : basetype(funcptr), m_name(name) { }
+ template <class FunctionClass> named_delegate(static_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
+ template <class FunctionClass> named_delegate(static_ref_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, object), m_name(name) { }
+ named_delegate &operator=(const basetype &src) { basetype::operator=(src); m_name = src.m_name; return *this; }
const char *name() const { return m_name; }
+
private:
const char * m_name; // name string
};
@@ -65,33 +71,37 @@ private:
// device_delegate is a delegate that wraps with a device tag and can be easily
// late bound without replicating logic everywhere
-template<typename _Signature>
-class device_delegate : public named_delegate<_Signature>, public device_delegate_helper
+template <typename Signature>
+class device_delegate : public named_delegate<Signature>, public device_delegate_helper
{
- typedef device_delegate<_Signature> thistype;
- typedef named_delegate<_Signature> basetype;
+ using thistype = device_delegate<Signature>;
+ using basetype = named_delegate<Signature>;
+ template <class FunctionClass> using member_func_type = typename basetype::template member_func_type<FunctionClass>;
+ template <class FunctionClass> using const_member_func_type = typename basetype::template const_member_func_type<FunctionClass>;
+ template <class FunctionClass> using static_func_type = typename basetype::template static_func_type<FunctionClass>;
+ template <class FunctionClass> using static_ref_func_type = typename basetype::template static_ref_func_type<FunctionClass>;
public:
// provide the same constructors as the base class
device_delegate() : basetype(), device_delegate_helper(nullptr) { }
device_delegate(const basetype &src) : basetype(src), device_delegate_helper(src.m_device_name) { }
device_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), device_delegate_helper(src.m_device_name) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
- device_delegate(std::function<_Signature> funcptr, const char *name) : basetype(funcptr,name), device_delegate_helper(nullptr) { }
- device_delegate &operator=(const thistype &src) { *static_cast<basetype *>(this) = src; m_device_name = src.m_device_name; return *this; }
+ template <class FunctionClass> device_delegate(member_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
+ template <class FunctionClass> device_delegate(const_member_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
+ template <class FunctionClass> device_delegate(static_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
+ template <class FunctionClass> device_delegate(static_ref_func_type<FunctionClass> funcptr, const char *name, FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
+ device_delegate(std::function<Signature> funcptr, const char *name) : basetype(funcptr, name), device_delegate_helper(nullptr) { }
+ device_delegate &operator=(const thistype &src) { basetype::operator=(src); m_device_name = src.m_device_name; return *this; }
// provide additional constructors that take a device name string
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
- device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
- device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
+ template <class FunctionClass> device_delegate(member_func_type<FunctionClass> funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
+ template <class FunctionClass> device_delegate(member_func_type<FunctionClass> funcptr, const char *name, const char *devname, FunctionClass *) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
+ template <class FunctionClass> device_delegate(const_member_func_type<FunctionClass> funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
+ template <class FunctionClass> device_delegate(const_member_func_type<FunctionClass> funcptr, const char *name, const char *devname, FunctionClass *) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
+ template <class FunctionClass> device_delegate(static_func_type<FunctionClass> funcptr, const char *name, const char *devname, FunctionClass *) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
+ template <class FunctionClass> device_delegate(static_ref_func_type<FunctionClass> funcptr, const char *name, const char *devname, FunctionClass *) : basetype(funcptr, name, static_cast<FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
+ device_delegate(static_func_type<device_t> funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
+ device_delegate(static_ref_func_type<device_t> funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
// and constructors that provide a search root
device_delegate(const thistype &src, device_t &search_root) : basetype(src), device_delegate_helper(src.m_device_name) { bind_relative_to(search_root); }
@@ -104,4 +114,4 @@ public:
};
-#endif /* MAME_EMU_DEVDELEGATE_H */
+#endif // MAME_EMU_DEVDELEGATE_H
diff --git a/src/emu/devfind.h b/src/emu/devfind.h
index cc15c201af9..1e61ad1c866 100644
--- a/src/emu/devfind.h
+++ b/src/emu/devfind.h
@@ -22,6 +22,7 @@
#include <stdexcept>
#include <string>
#include <type_traits>
+#include <utility>
//**************************************************************************
// TYPE DEFINITIONS
@@ -263,7 +264,14 @@ public:
///
/// Returns the search tag.
/// \return The object tag this helper will search for.
- const char *finder_tag() const { return m_tag; }
+ char const *finder_tag() const { return m_tag; }
+
+ /// \brief Get search target
+ ///
+ /// Returns the search base device and tag.
+ /// \return a pair consisting of a reference to the device to search
+ /// relative to and the relative tag.
+ std::pair<device_t &, char const *> finder_target() const { return std::make_pair(m_base, m_tag); }
/// \brief Set search tag
///
@@ -519,7 +527,7 @@ public:
/// During configuration, device_finder instances may be assigned
/// a reference to the anticipated target device to avoid the need
/// for tempories during configuration. Normal resolution will
- /// still happen after machine configuration is completed to ensure
+ /// still happen after machine configuration is completed to ensure
/// device removal/replacement is handled properly.
/// \param [in] device Reference to anticipated target device.
/// \return The same reference supplied by the caller.
diff --git a/src/emu/device.h b/src/emu/device.h
index 8ff57dcc83f..3dbaa5f4e37 100644
--- a/src/emu/device.h
+++ b/src/emu/device.h
@@ -265,6 +265,7 @@ class device_type_impl : public device_type_impl_base
public:
using device_type_impl_base::device_type_impl_base;
template <typename... Params> DeviceClass &operator()(machine_config &config, char const *tag, Params &&... args) const;
+ template <typename Exposed, bool Required, typename... Params> DeviceClass &operator()(machine_config &config, device_finder<Exposed, Required> &finder, Params &&... args) const;
};
diff --git a/src/emu/device.ipp b/src/emu/device.ipp
index c5c97568313..848223dd0c7 100644
--- a/src/emu/device.ipp
+++ b/src/emu/device.ipp
@@ -14,8 +14,8 @@
#error Dont include this file directly; include emu.h instead.
#endif
-#ifndef __DEVICE_IPP__
-#define __DEVICE_IPP__
+#ifndef MAME_EMU_DEVICE_IPP
+#define MAME_EMU_DEVICE_IPP
//**************************************************************************
// TYPE DEFINITIONS
@@ -23,10 +23,31 @@
typedef device_delegate<void (u32)> clock_update_delegate;
+
//**************************************************************************
// MEMBER TEMPLATES
//**************************************************************************
+namespace emu { namespace detail {
+
+template <class DeviceClass> template <typename... Params>
+DeviceClass &device_type_impl<DeviceClass>::operator()(machine_config &config, char const *tag, Params &&... args) const
+{
+ return dynamic_cast<DeviceClass &>(*config.device_add(tag, *this, std::forward<Params>(args)...));
+}
+
+template <class DeviceClass> template <typename Exposed, bool Required, typename... Params>
+DeviceClass &device_type_impl<DeviceClass>::operator()(machine_config &config, device_finder<Exposed, Required> &finder, Params &&... args) const
+{
+ std::pair<device_t &, char const *> const target(finder.finder_target());
+ assert(&config.current_device() == &target.first);
+ DeviceClass &result(dynamic_cast<DeviceClass &>(*config.device_add(target.second, *this, std::forward<Params>(args)...)));
+ return finder = result;
+}
+
+} } // namespace emu::detail
+
+
template <typename Format, typename... Params>
inline void device_t::popmessage(Format &&fmt, Params &&... args) const
{
@@ -54,4 +75,4 @@ inline void device_t::logerror(Format &&fmt, Params &&... args) const
}
}
-#endif // __DEVICE_IPP__
+#endif // MAME_EMU_DEVICE_IPP
diff --git a/src/emu/emu.h b/src/emu/emu.h
index a1f72c051f3..642bc65ad54 100644
--- a/src/emu/emu.h
+++ b/src/emu/emu.h
@@ -111,4 +111,4 @@ class address_map; // Forward declaration
// member templates that don't like incomplete types
#include "device.ipp"
-#endif /* __EMU_H__ */
+#endif // __EMU_H__
diff --git a/src/emu/emufwd.h b/src/emu/emufwd.h
index f5de6232f05..41e725e7a58 100644
--- a/src/emu/emufwd.h
+++ b/src/emu/emufwd.h
@@ -103,6 +103,7 @@ class devcb_write_base;
// declared in devfind.h
class finder_base;
+template <class DeviceClass, bool Required> class device_finder;
// declared in device.h
class device_interface;
diff --git a/src/emu/mconfig.h b/src/emu/mconfig.h
index 86902c4b525..0c09f4b69ab 100644
--- a/src/emu/mconfig.h
+++ b/src/emu/mconfig.h
@@ -128,17 +128,6 @@ private:
};
-namespace emu { namespace detail {
-
-template <class DeviceClass> template <typename... Params>
-DeviceClass &device_type_impl<DeviceClass>::operator()(machine_config &config, char const *tag, Params &&... args) const
-{
- return dynamic_cast<DeviceClass &>(*config.device_add(tag, *this, std::forward<Params>(args)...));
-}
-
-} } // namespace emu::detail
-
-
//*************************************************************************/
/** @name Machine config start/end macros */
//*************************************************************************/