summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/mconfig.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/mconfig.cpp')
-rw-r--r--src/emu/mconfig.cpp179
1 files changed, 129 insertions, 50 deletions
diff --git a/src/emu/mconfig.cpp b/src/emu/mconfig.cpp
index e9533aff7d8..275a4af46ae 100644
--- a/src/emu/mconfig.cpp
+++ b/src/emu/mconfig.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- mconfig.c
+ mconfig.cpp
Machine configuration macros and functions.
@@ -12,8 +12,10 @@
#include "emuopts.h"
#include "screen.h"
-#include <ctype.h>
+#include <cctype>
+
#include <cstring>
+#include <numeric>
//**************************************************************************
@@ -37,18 +39,19 @@ private:
//-------------------------------------------------
machine_config::machine_config(const game_driver &gamedrv, emu_options &options)
- : m_minimum_quantum(attotime::zero)
- , m_gamedrv(gamedrv)
+ : m_gamedrv(gamedrv)
, m_options(options)
, m_root_device()
, m_default_layouts([] (char const *a, char const *b) { return 0 > std::strcmp(a, b); })
, m_current_device(nullptr)
+ , m_maximum_quantums([] (char const *a, char const *b) { return 0 > std::strcmp(a, b); })
+ , m_perfect_quantum_device(nullptr, "")
{
// add the root device
device_add("root", gamedrv.type, 0);
// intialize slot devices - make sure that any required devices have been allocated
- for (device_slot_interface &slot : slot_interface_iterator(root_device()))
+ for (device_slot_interface &slot : slot_interface_enumerator(root_device()))
{
device_t &owner = slot.device();
const char *slot_option_name = owner.tag() + 1;
@@ -101,7 +104,7 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options)
}
// then notify all devices that their configuration is complete
- for (device_t &device : device_iterator(root_device()))
+ for (device_t &device : device_enumerator(root_device()))
if (!device.configured())
device.config_complete();
}
@@ -117,6 +120,51 @@ machine_config::~machine_config()
//-------------------------------------------------
+// maximum_quantum - get smallest configured
+// maximum quantum
+//-------------------------------------------------
+
+attotime machine_config::maximum_quantum(attotime const &default_quantum) const
+{
+ return std::accumulate(
+ m_maximum_quantums.begin(),
+ m_maximum_quantums.end(),
+ default_quantum,
+ [] (attotime const &lhs, maximum_quantum_map::value_type const &rhs) { return (std::min)(lhs, rhs.second); });
+}
+
+//-------------------------------------------------
+// perfect_quantum_device - get device configured
+// for perfect quantum if any
+//-------------------------------------------------
+
+device_execute_interface *machine_config::perfect_quantum_device() const
+{
+ if (!m_perfect_quantum_device.first)
+ return nullptr;
+
+ device_t *const found(m_perfect_quantum_device.first->subdevice(m_perfect_quantum_device.second));
+ if (!found)
+ {
+ throw emu_fatalerror(
+ "Device %s relative to %s specified for perfect interleave is not present!\n",
+ m_perfect_quantum_device.second,
+ m_perfect_quantum_device.first->tag());
+ }
+
+ device_execute_interface *result;
+ if (!found->interface(result))
+ {
+ throw emu_fatalerror("Device %s (%s) specified for perfect interleave does not implement device_execute_interface!\n",
+ found->tag(),
+ found->shortname());
+ }
+
+ return result;
+}
+
+
+//-------------------------------------------------
// set_default_layout - set layout for current
// device
//-------------------------------------------------
@@ -130,6 +178,19 @@ void machine_config::set_default_layout(internal_layout const &layout)
//-------------------------------------------------
+// set_maximum_quantum - set maximum scheduling
+// quantum for current device device
+//-------------------------------------------------
+
+void machine_config::set_maximum_quantum(attotime const &quantum)
+{
+ std::pair<maximum_quantum_map::iterator, bool> const ins(m_maximum_quantums.emplace(current_device().tag(), quantum));
+ if (!ins.second)
+ ins.first->second = quantum;
+}
+
+
+//-------------------------------------------------
// device_add - configuration helper to add a
// new device
//-------------------------------------------------
@@ -178,7 +239,7 @@ device_t *machine_config::device_remove(const char *tag)
remove_references(*device);
// let the device's owner do the work
- owner->subdevices().m_list.remove(*device);
+ owner->subdevices().remove(*device);
}
return nullptr;
}
@@ -196,25 +257,23 @@ std::pair<const char *, device_t *> machine_config::resolve_owner(const char *ta
device_t *owner(m_current_device);
// if the device path is absolute, start from the root
- if (tag[0] == ':')
- {
- tag++;
- owner = m_root_device.get();
- }
+ if (!*tag || (':' == *tag) || ('^' == *tag))
+ throw emu_fatalerror("Attempting to add device with tag containing parent references '%s'\n", orig_tag);
// go down the path until we're done with it
- std::string part;
- while (strchr(tag, ':'))
+ char const *next;
+ while ((next = strchr(tag, ':')) != nullptr)
{
- const char *next = strchr(tag, ':');
assert(next != tag);
- part.assign(tag, next - tag);
+ std::string_view part(tag, next - tag);
owner = owner->subdevices().find(part);
if (!owner)
- throw emu_fatalerror("Could not find %s when looking up path for device %s\n", part.c_str(), orig_tag);
- tag = next+1;
+ throw emu_fatalerror("Could not find '%s' when looking up path for device '%s'\n", part, orig_tag);
+ tag = next + 1;
+ if ('^' == *tag)
+ throw emu_fatalerror("Attempting to add device with tag containing parent references '%s'\n", orig_tag);
}
- assert(tag[0] != '\0');
+ assert(*tag != '\0');
return std::make_pair(tag, owner);
}
@@ -236,7 +295,7 @@ std::tuple<const char *, device_t *, device_t *> machine_config::prepare_replace
if (old_device)
remove_references(*old_device);
else
- osd_printf_warning("Warning: attempting to replace non-existent device '%s'\n", tag);
+ throw emu_fatalerror("Attempting to replace non-existent device '%s'\n", tag);
return std::make_tuple(owner.first, owner.second, old_device);
}
@@ -253,7 +312,7 @@ device_t &machine_config::add_device(std::unique_ptr<device_t> &&device, device_
if (owner)
{
// allocate the new device and append it to the owner's list
- device_t &result(owner->subdevices().m_list.append(*device.release()));
+ device_t &result(owner->subdevices().append(std::move(device)));
result.add_machine_configuration(*this);
return result;
}
@@ -262,9 +321,6 @@ device_t &machine_config::add_device(std::unique_ptr<device_t> &&device, device_
// allocate the root device directly
assert(!m_root_device);
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);
m_root_device->add_machine_configuration(*this);
return *m_root_device;
}
@@ -280,51 +336,74 @@ device_t &machine_config::replace_device(std::unique_ptr<device_t> &&device, dev
{
current_device_stack const context(*this);
device_t &result(existing
- ? owner.subdevices().m_list.replace_and_remove(*device.release(), *existing)
- : owner.subdevices().m_list.append(*device.release()));
+ ? owner.subdevices().replace_and_remove(std::move(device), *existing)
+ : owner.subdevices().append(std::move(device)));
result.add_machine_configuration(*this);
return result;
}
//-------------------------------------------------
-// device_find - configuration helper to
-// locate a device
-//-------------------------------------------------
-
-device_t *machine_config::device_find(device_t *owner, const char *tag)
-{
- // find the original device by relative tag (must exist)
- assert(owner != nullptr);
- device_t *device = owner->subdevice(tag);
- if (device == nullptr)
- throw emu_fatalerror("Unable to find device '%s'\n", tag);
-
- // return the device
- return device;
-}
-
-
-//-------------------------------------------------
// remove_references - globally remove references
// to a device about to be removed from the tree
//-------------------------------------------------
void machine_config::remove_references(device_t &device)
{
- // remove default layouts for subdevices
+ // sanity check
+ if (m_perfect_quantum_device.first == &device)
+ {
+ throw emu_fatalerror(
+ "Removing %s device %s would make the perfect quantum device target invalid\n",
+ device.shortname(),
+ device.tag());
+ }
+
+ // remove default layouts and maximum quantum settings for subdevices
char const *const tag(device.tag());
std::size_t const taglen(std::strlen(tag));
- default_layout_map::iterator it(m_default_layouts.lower_bound(tag));
- while ((m_default_layouts.end() != it) && !std::strncmp(tag, it->first, taglen))
+ for (auto it = m_default_layouts.lower_bound(tag); (m_default_layouts.end() != it) && !std::strncmp(tag, it->first, taglen); )
{
if (!it->first[taglen] || (':' == it->first[taglen]))
it = m_default_layouts.erase(it);
else
++it;
}
+ for (auto it = m_maximum_quantums.lower_bound(tag); (m_maximum_quantums.end() != it) && !std::strncmp(tag, it->first, taglen); )
+ {
+ if (!it->first[taglen] || (':' == it->first[taglen]))
+ it = m_maximum_quantums.erase(it);
+ else
+ ++it;
+ }
+}
+
+
+//-------------------------------------------------
+// set_perfect_quantum - set device to base
+// scheduling interval on
+//-------------------------------------------------
+
+void machine_config::set_perfect_quantum(device_t &device, std::string tag)
+{
+ if (!m_current_device)
+ {
+ throw emu_fatalerror(
+ "Perfect quantum device can only be set during configuration (set to %s relative to %s)\n",
+ tag,
+ device.tag());
+ }
+
+ if (m_current_device != m_root_device.get())
+ {
+ throw emu_fatalerror(
+ "Perfect quantum device can only be set by the root device (set to %s relative to %s while configuring %s device %s)\n",
+ tag,
+ device.tag(),
+ m_current_device->shortname(),
+ m_current_device->tag());
+ }
- // iterate over all devices and remove any references
- for (device_t &scan : device_iterator(root_device()))
- scan.subdevices().m_tagmap.clear();
+ m_perfect_quantum_device.first = tag.empty() ? nullptr : &device;
+ m_perfect_quantum_device.second = std::move(tag);
}