diff options
Diffstat (limited to 'src/emu/mconfig.h')
-rw-r--r-- | src/emu/mconfig.h | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/src/emu/mconfig.h b/src/emu/mconfig.h index ce3317a17b2..c7f071d0a91 100644 --- a/src/emu/mconfig.h +++ b/src/emu/mconfig.h @@ -20,6 +20,7 @@ #include <cassert> #include <memory> +#include <tuple> #include <type_traits> #include <typeinfo> #include <utility> @@ -36,6 +37,13 @@ // TYPE DEFINITIONS //************************************************************************** +namespace emu { namespace detail { + +struct machine_config_replace { machine_config &config; }; + +} } // namesapce emu::detail + + struct internal_layout { size_t decompressed_size; @@ -109,6 +117,7 @@ public: m_current_device = &device; return token(*this, device); } + emu::detail::machine_config_replace replace() { return emu::detail::machine_config_replace{ *this }; }; device_t *device_add(const char *tag, device_type type, u32 clock); template <typename Creator> device_t *device_add(const char *tag, Creator &&type, u32 clock) @@ -132,7 +141,27 @@ public: return device_add(tag, std::forward<Creator>(type), clock.value(), std::forward<Params>(args)...); } device_t *device_replace(const char *tag, device_type type, u32 clock); - device_t *device_replace(const char *tag, device_type type, const XTAL &xtal); + template <typename Creator> + device_t *device_replace(const char *tag, Creator &&type, u32 clock) + { + return device_add(tag, device_type(type), clock); + } + template <typename Creator, typename... Params> + auto device_replace(const char *tag, Creator &&type, Params &&... args) + { + std::tuple<const char *, device_t *, device_t *> const existing(prepare_replace(tag)); + auto device(type.create(*this, std::get<0>(existing), std::get<1>(existing), std::forward<Params>(args)...)); + auto &result(*device); + assert(type.type() == typeid(result)); + replace_device(std::move(device), *std::get<1>(existing), std::get<2>(existing)); + return &result; + } + template <typename Creator, typename... Params> + auto device_replace(const char *tag, Creator &&type, XTAL clock, Params &&... args) + { + clock.validate(std::string("Replacing device ") + tag); + return device_replace(tag, std::forward<Creator>(type), clock.value(), std::forward<Params>(args)...); + } device_t *device_remove(const char *tag); device_t *device_find(device_t *owner, const char *tag); @@ -141,7 +170,9 @@ private: // internal helpers std::pair<const char *, device_t *> resolve_owner(const char *tag) const; - device_t *add_device(std::unique_ptr<device_t> &&device, device_t *owner); + std::tuple<const char *, device_t *, device_t *> prepare_replace(const char *tag); + device_t &add_device(std::unique_ptr<device_t> &&device, device_t *owner); + device_t &replace_device(std::unique_ptr<device_t> &&device, device_t &owner, device_t *existing); void remove_references(ATTR_UNUSED device_t &device); // internal state @@ -164,6 +195,16 @@ inline std::enable_if_t<emu::detail::is_device_interface<typename std::remove_re { return &type(mconfig, std::forward<Tag>(tag), std::forward<Params>(args)...).device(); } +template <typename Tag, typename Creator, typename... Params> +inline std::enable_if_t<emu::detail::is_device_implementation<typename std::remove_reference_t<Creator>::exposed_type>::value, typename std::remove_reference_t<Creator>::exposed_type *> device_replace_impl(machine_config &mconfig, Tag &&tag, Creator &&type, Params &&... args) +{ + return &type(mconfig.replace(), std::forward<Tag>(tag), std::forward<Params>(args)...); +} +template <typename Tag, typename Creator, typename... Params> +inline std::enable_if_t<emu::detail::is_device_interface<typename std::remove_reference_t<Creator>::exposed_type>::value, device_t *> device_replace_impl(machine_config &mconfig, Tag &&tag, Creator &&type, Params &&... args) +{ + return &type(mconfig.replace(), std::forward<Tag>(tag), std::forward<Params>(args)...).device(); +} } } // namespace emu::detail @@ -211,8 +252,8 @@ Ends a machine_config. // add/remove devices #define MCFG_DEVICE_ADD(_tag, ...) \ device = emu::detail::device_add_impl(config, _tag, __VA_ARGS__); -#define MCFG_DEVICE_REPLACE(_tag, _type, _clock) \ - device = config.device_replace(_tag, _type, _clock); +#define MCFG_DEVICE_REPLACE(_tag, ...) \ + device = emu::detail::device_replace_impl(config, _tag, __VA_ARGS__); #define MCFG_DEVICE_REMOVE(_tag) \ device = config.device_remove(_tag); #define MCFG_DEVICE_MODIFY(_tag) \ |