summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2018-05-04 03:01:32 +1000
committer Vas Crabb <vas@vastheman.com>2018-05-04 03:01:32 +1000
commit32a73f450da82c345b0f694bee311af34a5e717d (patch)
treede6259ee4c0120e992f348afcc9078e16bbe49d4 /src/emu
parentaa96f47092f764f089c2ce9e0f26d756197150e8 (diff)
Make MCFG_DEVICE_ADD and callable device types more flexible:
* Allows defaulted clocks (see subtle example with vboy) * Allows additional constructors (see RS232 port in tranz330) * Allows use of device finder in place of tag in MCFG_DEVICE_ADD * Requires out-of-line destructor for devices using incomplete types * Requires XTAL or explicit u32 for clocks for devices with private types Devices must still define the standard constructor. When writing additional constructors, be aware that the constructor runs before device_add_mconfig in the context of the existing device, not the new device. See osborne1, zorba, tranz330, and vboy for examples of this in use. Compilation is a bit slower, but this is temporary while refactoring is in progress. Eliminated the need for MCFG_SOUND_ROUTE_EX. Removed macros from slot option configuration - they just obfuscated code and slowed it down with needless dynamic casts, but didn't actually simplify it.
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/devcb.h11
-rw-r--r--src/emu/devfind.h9
-rw-r--r--src/emu/device.h32
-rw-r--r--src/emu/device.ipp10
-rw-r--r--src/emu/dislot.cpp57
-rw-r--r--src/emu/dislot.h89
-rw-r--r--src/emu/disound.cpp9
-rw-r--r--src/emu/disound.h16
-rw-r--r--src/emu/mconfig.cpp40
-rw-r--r--src/emu/mconfig.h50
-rw-r--r--src/emu/speaker.h7
-rw-r--r--src/emu/validity.cpp3
12 files changed, 212 insertions, 121 deletions
diff --git a/src/emu/devcb.h b/src/emu/devcb.h
index fee31ce1ca4..2fd6e53ae19 100644
--- a/src/emu/devcb.h
+++ b/src/emu/devcb.h
@@ -26,11 +26,6 @@ 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))
{
}
@@ -53,9 +48,9 @@ template <typename Delegate> struct devcb_delegate_initialiser
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; }
+inline std::enable_if_t<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; }
+inline std::enable_if_t<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(); }
@@ -191,14 +186,12 @@ protected:
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;
diff --git a/src/emu/devfind.h b/src/emu/devfind.h
index 1e61ad1c866..9bd5ad48fde 100644
--- a/src/emu/devfind.h
+++ b/src/emu/devfind.h
@@ -540,17 +540,12 @@ public:
}
private:
- 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; };
-
/// \brief Check that device implementation has expected tag
/// \param [in] device Reference to device.
/// \return True if supplied device matches the configured target
/// tag, or false otherwise.
template <typename T>
- std::enable_if_t<is_device_implementation<T>::value, bool> is_expected_tag(T const &device) const
+ std::enable_if_t<emu::detail::is_device_implementation<T>::value, bool> is_expected_tag(T const &device) const
{
return this->m_base.get().subtag(this->m_tag) == device.tag();
}
@@ -560,7 +555,7 @@ private:
/// \return True if supplied mixin matches the configured target
/// tag, or false otherwise.
template <typename T>
- std::enable_if_t<is_device_interface<T>::value, bool> is_expected_tag(T const &interface) const
+ std::enable_if_t<emu::detail::is_device_interface<T>::value, bool> is_expected_tag(T const &interface) const
{
return this->m_base.get().subtag(this->m_tag) == interface.device().tag();
}
diff --git a/src/emu/device.h b/src/emu/device.h
index 3dbaa5f4e37..cc8b5209945 100644
--- a/src/emu/device.h
+++ b/src/emu/device.h
@@ -75,6 +75,17 @@ namespace emu { namespace detail {
class device_type_impl_base;
+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;
+};
+
+
struct device_feature
{
enum type : u32
@@ -203,6 +214,8 @@ private:
device_type_impl_base *m_next;
public:
+ using exposed_type = device_t;
+
device_type_impl_base(std::nullptr_t)
: m_creator(nullptr)
, m_type(typeid(std::nullptr_t))
@@ -252,6 +265,10 @@ public:
{
return m_creator(*this, mconfig, tag, owner, clock);
}
+ std::unique_ptr<device_t> create(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) const
+ {
+ return m_creator(*this, mconfig, tag, owner, clock);
+ }
explicit operator bool() const { return bool(m_creator); }
bool operator==(device_type_impl_base const &that) const { return &that == this; }
@@ -263,9 +280,20 @@ template <class DeviceClass>
class device_type_impl : public device_type_impl_base
{
public:
+ using exposed_type = DeviceClass;
+
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;
+ using device_type_impl_base::create;
+ using device_type_impl_base::operator();
+
+ template <typename... Params>
+ std::unique_ptr<DeviceClass> create(machine_config &mconfig, char const *tag, device_t *owner, Params &&... args) const
+ {
+ return make_unique_clear<DeviceClass>(mconfig, tag, owner, std::forward<Params>(args)...);
+ }
+
+ template <typename... Params> DeviceClass &operator()(machine_config &mconfig, char const *tag, Params &&... args) const;
+ template <typename Exposed, bool Required, typename... Params> DeviceClass &operator()(machine_config &mconfig, device_finder<Exposed, Required> &finder, Params &&... args) const;
};
diff --git a/src/emu/device.ipp b/src/emu/device.ipp
index 848223dd0c7..4fa6b2fe1ec 100644
--- a/src/emu/device.ipp
+++ b/src/emu/device.ipp
@@ -31,17 +31,17 @@ typedef device_delegate<void (u32)> clock_update_delegate;
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
+inline DeviceClass &device_type_impl<DeviceClass>::operator()(machine_config &mconfig, char const *tag, Params &&... args) const
{
- return dynamic_cast<DeviceClass &>(*config.device_add(tag, *this, std::forward<Params>(args)...));
+ return dynamic_cast<DeviceClass &>(*mconfig.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
+inline DeviceClass &device_type_impl<DeviceClass>::operator()(machine_config &mconfig, 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)...)));
+ assert(&mconfig.current_device() == &target.first);
+ DeviceClass &result(dynamic_cast<DeviceClass &>(*mconfig.device_add(target.second, *this, std::forward<Params>(args)...)));
return finder = result;
}
diff --git a/src/emu/dislot.cpp b/src/emu/dislot.cpp
index e89fd8b77bd..37acf1dfddd 100644
--- a/src/emu/dislot.cpp
+++ b/src/emu/dislot.cpp
@@ -15,8 +15,8 @@
// ctor
// -------------------------------------------------
-device_slot_interface::device_slot_interface(const machine_config &mconfig, device_t &device)
- : device_interface(device, "slot"),
+device_slot_interface::device_slot_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "slot"),
m_default_option(nullptr),
m_fixed(false),
m_card_device(nullptr)
@@ -37,10 +37,10 @@ device_slot_interface::~device_slot_interface()
// device_slot_option ctor
// -------------------------------------------------
-device_slot_option::device_slot_option(const char *name, const device_type &devtype):
+device_slot_interface::slot_option::slot_option(const char *name, const device_type &devtype, bool selectable) :
m_name(name),
m_devtype(devtype),
- m_selectable(true),
+ m_selectable(selectable),
m_default_bios(nullptr),
m_machine_config(nullptr),
m_input_device_defaults(nullptr),
@@ -53,14 +53,33 @@ device_slot_option::device_slot_option(const char *name, const device_type &devt
// option_add
// -------------------------------------------------
-void device_slot_interface::option_add(const char *name, const device_type &devtype)
+device_slot_interface::slot_option &device_slot_interface::option_add(const char *name, const device_type &devtype)
{
- device_slot_option *slot_option = option(name);
+ const slot_option *const existing = option(name);
+ if (existing)
+ throw emu_fatalerror("slot '%s' duplicate option '%s'\n", device().tag(), name);
+
+ if (m_options.count(name))
+ throw tag_add_exception(name);
+
+ return *m_options.emplace(name, std::make_unique<slot_option>(name, devtype, true)).first->second;
+}
+
+
+// -------------------------------------------------
+// option_add_internal
+// -------------------------------------------------
- if (slot_option != nullptr)
+device_slot_interface::slot_option &device_slot_interface::option_add_internal(const char *name, const device_type &devtype)
+{
+ const slot_option *const existing = option(name);
+ if (existing)
throw emu_fatalerror("slot '%s' duplicate option '%s'\n", device().tag(), name);
- if (m_options.count(name) != 0) throw tag_add_exception(name);
- m_options.emplace(std::make_pair(name, std::make_unique<device_slot_option>(name, devtype)));
+
+ if (m_options.count(name))
+ throw tag_add_exception(name);
+
+ return *m_options.emplace(name, std::make_unique<slot_option>(name, devtype, false)).first->second;
}
@@ -68,14 +87,13 @@ void device_slot_interface::option_add(const char *name, const device_type &devt
// option
// -------------------------------------------------
-device_slot_option *device_slot_interface::config_option(const char *name)
+device_slot_interface::slot_option *device_slot_interface::config_option(const char *name)
{
- device_slot_option *slot_option = option(name);
-
- if (slot_option == nullptr)
- throw emu_fatalerror("slot '%s' has no option '%s'\n", device().tag(), name);
+ auto const search = m_options.find(name);
+ if (search != m_options.end())
+ return search->second.get();
- return slot_option;
+ throw emu_fatalerror("slot '%s' has no option '%s'\n", device().tag(), name);
}
@@ -99,16 +117,15 @@ bool device_slot_interface::has_selectable_options() const
// option
// -------------------------------------------------
-device_slot_option *device_slot_interface::option(const char *name) const
+const device_slot_interface::slot_option *device_slot_interface::option(const char *name) const
{
- device_slot_option *result = nullptr;
if (name)
{
- auto search = m_options.find(name);
+ auto const search = m_options.find(name);
if (search != m_options.end())
- result = search->second.get();
+ return search->second.get();
}
- return result;
+ return nullptr;
}
diff --git a/src/emu/dislot.h b/src/emu/dislot.h
index f8f1d5a8a70..be10da760cd 100644
--- a/src/emu/dislot.h
+++ b/src/emu/dislot.h
@@ -13,17 +13,7 @@
// LEGACY MACROS
//**************************************************************************
-#define MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_option, _fixed) MCFG_SLOT_OPTION_RESET slot_options_##_slot_intf(device); MCFG_SLOT_DEFAULT_OPTION(_def_option) MCFG_SLOT_FIXED(_fixed)
-#define SLOT_INTERFACE_NAME(name) slot_options_##name
-#define SLOT_INTERFACE_START(name) void slot_options_##name(device_t *device) {
-#define SLOT_INTERFACE(name,device) MCFG_SLOT_OPTION_ADD(name, device)
-#define SLOT_INTERFACE_INTERNAL(name,device) MCFG_SLOT_OPTION_ADD(name, device) MCFG_SLOT_OPTION_SELECTABLE(name, false)
-#define SLOT_INTERFACE_END }
-#define SLOT_INTERFACE_EXTERN(name) void slot_options_##name(device_t *device)
-#define MCFG_DEVICE_CARD_DEFAULT_BIOS(_option, _default_bios) MCFG_SLOT_OPTION_DEFAULT_BIOS(_option, _default_bios)
-#define MCFG_DEVICE_CARD_MACHINE_CONFIG(_option, _machine_config_name) MCFG_SLOT_OPTION_MACHINE_CONFIG(_option, _machine_config_name)
-#define MCFG_DEVICE_CARD_DEVICE_INPUT_DEFAULTS(_option, _dev_inp_def) MCFG_SLOT_OPTION_DEVICE_INPUT_DEFAULTS(_option, _dev_inp_def)
-#define MCFG_DEVICE_CARD_CLOCK(_option, _clock) MCFG_SLOT_OPTION_CLOCK(_option, _clock)
+#define MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_option, _fixed) MCFG_SLOT_OPTION_RESET _slot_intf(dynamic_cast<device_slot_interface &>(*device)); MCFG_SLOT_DEFAULT_OPTION(_def_option) MCFG_SLOT_FIXED(_fixed)
//**************************************************************************
@@ -42,9 +32,6 @@
#define MCFG_SLOT_OPTION_ADD(_option, _devtype) \
dynamic_cast<device_slot_interface &>(*device).option_add(_option, _devtype);
-#define MCFG_SLOT_OPTION_SELECTABLE(_option, _selectable) \
- dynamic_cast<device_slot_interface &>(*device).set_option_selectable(_option, _selectable);
-
#define MCFG_SLOT_OPTION_DEFAULT_BIOS(_option, _default_bios) \
dynamic_cast<device_slot_interface &>(*device).set_option_default_bios(_option, _default_bios);
@@ -62,35 +49,6 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> device_slot_option
-
-class device_slot_option
-{
- friend class device_slot_interface;
-
-public:
- device_slot_option(const char *name, const device_type &devtype);
-
- const char *name() const { return m_name; }
- const device_type &devtype() const { return m_devtype; }
- bool selectable() const { return m_selectable; }
- const char *default_bios() const { return m_default_bios; }
- std::function<void (device_t *)> machine_config() const { return m_machine_config; }
- const input_device_default *input_device_defaults() const { return m_input_device_defaults; }
- u32 clock() const { return m_clock; }
-
-private:
- // internal state
- const char *m_name;
- const device_type &m_devtype;
- bool m_selectable;
- const char *m_default_bios;
- std::function<void (device_t *)> m_machine_config;
- const input_device_default *m_input_device_defaults;
- u32 m_clock;
-};
-
-
// ======================> get_default_card_software_hook
class get_default_card_software_hook
@@ -124,6 +82,38 @@ private:
class device_slot_interface : public device_interface
{
public:
+ class slot_option
+ {
+ public:
+ slot_option(char const *name, device_type const &devtype, bool selectable);
+
+ char const *name() const { return m_name; }
+ device_type const &devtype() const { return m_devtype; }
+ bool selectable() const { return m_selectable; }
+ char const *default_bios() const { return m_default_bios; }
+ std::function<void (device_t *)> const &machine_config() const { return m_machine_config; }
+ input_device_default const *input_device_defaults() const { return m_input_device_defaults; }
+ u32 clock() const { return m_clock; }
+
+ slot_option &default_bios(char const *default_bios) { m_default_bios = default_bios; return *this; }
+ template <typename Object> slot_option &machine_config(Object &&cb) { m_machine_config = std::forward<Object>(cb); return *this; }
+ slot_option &input_device_defaults(input_device_default const *dev_inp_def) { m_input_device_defaults = dev_inp_def; return *this; }
+ slot_option &clock(u32 clock) { m_clock = clock; return *this; }
+ slot_option &clock(XTAL clock) { clock.validate(std::string("Configuring slot option ") + m_name); m_clock = clock.value(); return *this; }
+
+ private:
+ // internal state
+ char const *const m_name;
+ device_type const m_devtype;
+ bool const m_selectable;
+ char const *m_default_bios;
+ std::function<void (device_t *)> m_machine_config;
+ input_device_default const *m_input_device_defaults;
+ u32 m_clock;
+
+ friend class device_slot_interface;
+ };
+
// construction/destruction
device_slot_interface(const machine_config &mconfig, device_t &device);
virtual ~device_slot_interface();
@@ -131,17 +121,16 @@ public:
void set_fixed(bool fixed) { m_fixed = fixed; }
void set_default_option(const char *option) { m_default_option = option; }
void option_reset() { m_options.clear(); }
- void option_add(const char *option, const device_type &devtype);
- void set_option_selectable(const char *option, bool selectable){ config_option(option)->m_selectable = selectable; }
+ slot_option &option_add(const char *option, const device_type &devtype);
+ slot_option &option_add_internal(const char *option, const device_type &devtype);
void set_option_default_bios(const char *option, const char *default_bios) { config_option(option)->m_default_bios = default_bios; }
void set_option_machine_config(const char *option, std::function<void (device_t *)> machine_config) { config_option(option)->m_machine_config = machine_config; }
void set_option_device_input_defaults(const char *option, const input_device_default *default_input) { config_option(option)->m_input_device_defaults = default_input; }
- void set_option_clock(const char *option, u32 default_clock) { config_option(option)->m_clock = default_clock; }
bool fixed() const { return m_fixed; }
bool has_selectable_options() const;
const char *default_option() const { return m_default_option; }
- const std::unordered_map<std::string, std::unique_ptr<device_slot_option>> &option_list() const { return m_options; }
- device_slot_option *option(const char *name) const;
+ const std::unordered_map<std::string, std::unique_ptr<slot_option>> &option_list() const { return m_options; }
+ const slot_option *option(const char *name) const;
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const { return std::string(); }
device_t *get_card_device() const { return m_card_device; }
void set_card_device(device_t *dev) { m_card_device = dev; }
@@ -149,12 +138,12 @@ public:
private:
// internal state
- std::unordered_map<std::string,std::unique_ptr<device_slot_option>> m_options;
+ std::unordered_map<std::string,std::unique_ptr<slot_option>> m_options;
const char *m_default_option;
bool m_fixed;
device_t *m_card_device;
- device_slot_option *config_option(const char *option);
+ slot_option *config_option(const char *option);
};
// iterator
diff --git a/src/emu/disound.cpp b/src/emu/disound.cpp
index 2e16107b996..59d511e4e48 100644
--- a/src/emu/disound.cpp
+++ b/src/emu/disound.cpp
@@ -42,22 +42,25 @@ device_sound_interface::~device_sound_interface()
// add_route - send sound output to a consumer
//-------------------------------------------------
-void device_sound_interface::add_route(u32 output, const char *target, double gain, u32 input, u32 mixoutput)
+device_sound_interface &device_sound_interface::add_route(u32 output, const char *target, double gain, u32 input, u32 mixoutput)
{
assert(!device().started());
m_route_list.emplace_back(sound_route{ output, input, mixoutput, float(gain), device().mconfig().current_device(), target });
+ return *this;
}
-void device_sound_interface::add_route(u32 output, device_sound_interface &target, double gain, u32 input, u32 mixoutput)
+device_sound_interface &device_sound_interface::add_route(u32 output, device_sound_interface &target, double gain, u32 input, u32 mixoutput)
{
assert(!device().started());
m_route_list.emplace_back(sound_route{ output, input, mixoutput, float(gain), target.device(), DEVICE_SELF });
+ return *this;
}
-void device_sound_interface::add_route(u32 output, speaker_device &target, double gain, u32 input, u32 mixoutput)
+device_sound_interface &device_sound_interface::add_route(u32 output, speaker_device &target, double gain, u32 input, u32 mixoutput)
{
assert(!device().started());
m_route_list.emplace_back(sound_route{ output, input, mixoutput, float(gain), target, DEVICE_SELF });
+ return *this;
}
diff --git a/src/emu/disound.h b/src/emu/disound.h
index da968abd789..05bba47f5b1 100644
--- a/src/emu/disound.h
+++ b/src/emu/disound.h
@@ -44,10 +44,8 @@ constexpr int AUTO_ALLOC_INPUT = 65535;
#define MCFG_SOUND_REPLACE(_tag, _type, _clock) \
MCFG_DEVICE_REPLACE(_tag, _type, _clock)
-#define MCFG_SOUND_ROUTE(_output, _target, _gain) \
- dynamic_cast<device_sound_interface &>(*device).add_route(_output, _target, _gain);
-#define MCFG_SOUND_ROUTE_EX(_output, _target, _gain, _input) \
- dynamic_cast<device_sound_interface &>(*device).add_route(_output, _target, _gain, _input);
+#define MCFG_SOUND_ROUTE(_output, _target, ...) \
+ dynamic_cast<device_sound_interface &>(*device).add_route(_output, _target, __VA_ARGS__);
#define MCFG_SOUND_ROUTES_RESET() \
dynamic_cast<device_sound_interface &>(*device).reset_routes();
@@ -86,10 +84,10 @@ public:
std::vector<sound_route> const &routes() const { return m_route_list; }
// configuration helpers
- void add_route(u32 output, const char *target, double gain, u32 input = AUTO_ALLOC_INPUT, u32 mixoutput = 0);
- void add_route(u32 output, device_sound_interface &target, double gain, u32 input = AUTO_ALLOC_INPUT, u32 mixoutput = 0);
- void add_route(u32 output, speaker_device &target, double gain, u32 input = AUTO_ALLOC_INPUT, u32 mixoutput = 0);
- void reset_routes() { m_route_list.clear(); }
+ device_sound_interface &add_route(u32 output, const char *target, double gain, u32 input = AUTO_ALLOC_INPUT, u32 mixoutput = 0);
+ device_sound_interface &add_route(u32 output, device_sound_interface &target, double gain, u32 input = AUTO_ALLOC_INPUT, u32 mixoutput = 0);
+ device_sound_interface &add_route(u32 output, speaker_device &target, double gain, u32 input = AUTO_ALLOC_INPUT, u32 mixoutput = 0);
+ device_sound_interface &reset_routes() { m_route_list.clear(); return *this; }
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) = 0;
@@ -154,4 +152,4 @@ protected:
typedef device_interface_iterator<device_mixer_interface> mixer_interface_iterator;
-#endif /* MAME_EMU_DISOUND_H */
+#endif // MAME_EMU_DISOUND_H
diff --git a/src/emu/mconfig.cpp b/src/emu/mconfig.cpp
index eef4a143969..546ce1c885f 100644
--- a/src/emu/mconfig.cpp
+++ b/src/emu/mconfig.cpp
@@ -73,7 +73,8 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options)
if (selval && *selval)
{
- device_slot_option const *const option = slot.option(selval);
+ // TODO: make this thing more self-contained so it can apply itself - shouldn't need to know all this here
+ device_slot_interface::slot_option const *option = slot.option(selval);
if (option && (is_default || option->selectable()))
{
// create the device
@@ -115,11 +116,11 @@ machine_config::~machine_config()
//-------------------------------------------------
-// device_add - configuration helper to add a
-// new device
+// resolve_owner - get the actual owner and base
+// tag given tag relative to current context
//-------------------------------------------------
-device_t *machine_config::device_add(const char *tag, device_type type, u32 clock)
+std::pair<const char *, device_t *> machine_config::resolve_owner(const char *tag) const
{
assert(bool(m_current_device) == bool(m_root_device));
char const *const orig_tag = tag;
@@ -145,19 +146,30 @@ device_t *machine_config::device_add(const char *tag, device_type type, u32 cloc
}
assert(tag[0] != '\0');
+ return std::make_pair(tag, owner);
+}
+
+
+//-------------------------------------------------
+// add_device - add a new device at the correct
+// point in the hierarchy
+//-------------------------------------------------
+
+device_t *machine_config::add_device(std::unique_ptr<device_t> &&device, device_t *owner)
+{
current_device_stack context(*this);
if (owner)
{
// allocate the new device and append it to the owner's list
- device_t *const device = &owner->subdevices().m_list.append(*type(*this, tag, owner, clock).release());
- device->add_machine_configuration(*this);
- return device;
+ device_t *const result = &owner->subdevices().m_list.append(*device.release());
+ result->add_machine_configuration(*this);
+ return result;
}
else
{
// allocate the root device directly
assert(!m_root_device);
- m_root_device = type(*this, tag, nullptr, clock);
+ m_root_device = std::move(device);
driver_device *driver = dynamic_cast<driver_device *>(m_root_device.get());
if (driver)
driver->set_game_driver(m_gamedrv);
@@ -168,6 +180,18 @@ device_t *machine_config::device_add(const char *tag, device_type type, u32 cloc
//-------------------------------------------------
+// device_add - configuration helper to add a
+// new device
+//-------------------------------------------------
+
+device_t *machine_config::device_add(const char *tag, device_type type, u32 clock)
+{
+ std::pair<const char *, device_t *> const owner(resolve_owner(tag));
+ return add_device(type(*this, owner.first, owner.second, clock), owner.second);
+}
+
+
+//-------------------------------------------------
// device_replace - configuration helper to
// replace one device with a new device
//-------------------------------------------------
diff --git a/src/emu/mconfig.h b/src/emu/mconfig.h
index 0c09f4b69ab..ce3317a17b2 100644
--- a/src/emu/mconfig.h
+++ b/src/emu/mconfig.h
@@ -18,6 +18,13 @@
#ifndef MAME_EMU_MCONFIG_H
#define MAME_EMU_MCONFIG_H
+#include <cassert>
+#include <memory>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+
//**************************************************************************
// CONSTANTS
//**************************************************************************
@@ -103,11 +110,26 @@ public:
return token(*this, device);
}
device_t *device_add(const char *tag, device_type type, u32 clock);
- template <typename... Params>
- device_t *device_add(const char *tag, device_type type, const XTAL &clock, Params &&... args)
+ template <typename Creator>
+ device_t *device_add(const char *tag, Creator &&type, u32 clock)
+ {
+ return device_add(tag, device_type(type), clock);
+ }
+ template <typename Creator, typename... Params>
+ auto device_add(const char *tag, Creator &&type, Params &&... args)
+ {
+ std::pair<const char *, device_t *> const owner(resolve_owner(tag));
+ auto device(type.create(*this, owner.first, owner.second, std::forward<Params>(args)...));
+ auto &result(*device);
+ assert(type.type() == typeid(result));
+ add_device(std::move(device), owner.second);
+ return &result;
+ }
+ template <typename Creator, typename... Params>
+ auto device_add(const char *tag, Creator &&type, XTAL clock, Params &&... args)
{
clock.validate(std::string("Instantiating device ") + tag);
- return device_add(tag, type, clock.value(), std::forward<Params>(args)...);
+ 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);
@@ -118,6 +140,8 @@ private:
class current_device_stack;
// 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);
void remove_references(ATTR_UNUSED device_t &device);
// internal state
@@ -128,6 +152,22 @@ private:
};
+namespace emu { namespace detail {
+
+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_add_impl(machine_config &mconfig, Tag &&tag, Creator &&type, Params &&... args)
+{
+ return &type(mconfig, 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_add_impl(machine_config &mconfig, Tag &&tag, Creator &&type, Params &&... args)
+{
+ return &type(mconfig, std::forward<Tag>(tag), std::forward<Params>(args)...).device();
+}
+
+} } // namespace emu::detail
+
+
//*************************************************************************/
/** @name Machine config start/end macros */
//*************************************************************************/
@@ -169,8 +209,8 @@ Ends a machine_config.
config.m_default_layout = &(_layout);
// add/remove devices
-#define MCFG_DEVICE_ADD(_tag, _type, _clock) \
- device = config.device_add(_tag, _type, _clock);
+#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_REMOVE(_tag) \
diff --git a/src/emu/speaker.h b/src/emu/speaker.h
index 4665dbdf2e8..2280b883250 100644
--- a/src/emu/speaker.h
+++ b/src/emu/speaker.h
@@ -53,7 +53,10 @@ public:
virtual ~speaker_device();
// inline configuration helpers
- void set_position(double x, double y, double z) { m_x = x; m_y = y; m_z = z; }
+ speaker_device &set_position(double x, double y, double z) { m_x = x; m_y = y; m_z = z; return *this; }
+ speaker_device &standard_mono() { set_position(0.0, 0.0, 1.0); return *this; }
+ speaker_device &standard_left() { set_position(-0.2, 0.0, 1.0); return *this; }
+ speaker_device &standard_right() { set_position(0.2, 0.0, 1.0); return *this; }
// internally for use by the sound system
void mix(s32 *leftmix, s32 *rightmix, int &samples_this_update, bool suppress);
@@ -80,4 +83,4 @@ protected:
typedef device_type_iterator<speaker_device> speaker_device_iterator;
-#endif /* MAME_EMU_SPEAKER_H */
+#endif // MAME_EMU_SPEAKER_H
diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp
index 456cd5656b0..c5213ec8c96 100644
--- a/src/emu/validity.cpp
+++ b/src/emu/validity.cpp
@@ -1988,7 +1988,8 @@ void validity_checker::validate_devices()
{
if (subslot.fixed())
{
- device_slot_option const *const suboption = subslot.option(subslot.default_option());
+ // TODO: make this self-contained so it can apply itself
+ device_slot_interface::slot_option const *suboption = subslot.option(subslot.default_option());
if (suboption)
{
machine_config::token const tok(m_current_config->begin_configuration(subslot.device()));