summaryrefslogtreecommitdiffstats
path: root/docs/release/src/emu/validity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docs/release/src/emu/validity.cpp')
-rw-r--r--docs/release/src/emu/validity.cpp140
1 files changed, 130 insertions, 10 deletions
diff --git a/docs/release/src/emu/validity.cpp b/docs/release/src/emu/validity.cpp
index d0007311a76..9fef85821ca 100644
--- a/docs/release/src/emu/validity.cpp
+++ b/docs/release/src/emu/validity.cpp
@@ -15,6 +15,9 @@
#include "video/rgbutil.h"
#include <ctype.h>
+#include <type_traits>
+#include <typeindex>
+#include <typeinfo>
//**************************************************************************
@@ -126,15 +129,15 @@ void validity_checker::validate_tag(const char *tag)
//-------------------------------------------------
validity_checker::validity_checker(emu_options &options)
- : m_drivlist(options),
- m_errors(0),
- m_warnings(0),
- m_print_verbose(options.verbose()),
- m_current_driver(nullptr),
- m_current_config(nullptr),
- m_current_device(nullptr),
- m_current_ioport(nullptr),
- m_validate_all(false)
+ : m_drivlist(options)
+ , m_errors(0)
+ , m_warnings(0)
+ , m_print_verbose(options.verbose())
+ , m_current_driver(nullptr)
+ , m_current_config(nullptr)
+ , m_current_device(nullptr)
+ , m_current_ioport(nullptr)
+ , m_validate_all(false)
{
// pre-populate the defstr map with all the default strings
for (int strnum = 1; strnum < INPUT_STRING_COUNT; strnum++)
@@ -220,6 +223,10 @@ bool validity_checker::check_all_matching(const char *string)
if (m_drivlist.matches(string, m_drivlist.driver().name))
validate_one(m_drivlist.driver());
+ // validate devices
+ if (!string)
+ validate_device_types();
+
// cleanup
validate_end();
@@ -1854,6 +1861,119 @@ void validity_checker::validate_devices()
//-------------------------------------------------
+// validate_devices_types - check validity of
+// registered device types
+//-------------------------------------------------
+
+void validity_checker::validate_device_types()
+{
+ // reset error/warning state
+ int start_errors = m_errors;
+ int start_warnings = m_warnings;
+ m_error_text.clear();
+ m_warning_text.clear();
+ m_verbose_text.clear();
+
+ std::unordered_map<std::string, std::add_pointer_t<device_type> > device_name_map, device_shortname_map;
+ std::unordered_set<std::type_index> device_types;
+ machine_config config(GAME_NAME(___empty), m_drivlist.options());
+ for (device_type type : registered_device_types)
+ {
+ if (!device_types.emplace(type.type()).second)
+ {
+ osd_printf_error("Device class '%s' registered multiple times\n", type.type().name());
+ }
+ else
+ {
+ device_t *const dev = config.device_add(&config.root_device(), "_tmp", type, 0);
+
+ char const *name((dev->shortname() && *dev->shortname()) ? dev->shortname() : type.type().name());
+ std::string const description((dev->source() && *dev->source()) ? util::string_format("%s(%s)", core_filename_extract_base(dev->source()).c_str(), name) : name);
+
+ // ensure shortname exists
+ if (!dev->shortname() || !*dev->shortname())
+ {
+ osd_printf_error("Device %s does not have short name defined\n", description.c_str());
+ }
+ else
+ {
+ // check for invalid characters in shortname
+ for (char const *s = dev->shortname(); *s; ++s)
+ {
+ if (((*s < '0') || (*s > '9')) && ((*s < 'a') || (*s > 'z')) && (*s != '_'))
+ {
+ osd_printf_error("Device %s short name contains invalid characters\n", description.c_str());
+ break;
+ }
+ }
+
+ // check for name conflicts
+ auto const drvname(m_names_map.find(dev->shortname()));
+ auto const devname(device_shortname_map.emplace(dev->shortname(), &type));
+ if (m_names_map.end() != drvname)
+ {
+ game_driver const &dup(*drvname->second);
+ osd_printf_error("Device %s short name is a duplicate of %s(%s)\n", description.c_str(), core_filename_extract_base(dup.source_file).c_str(), dup.name);
+ }
+ else if (!devname.second)
+ {
+ device_t *const dup = config.device_add(&config.root_device(), "_dup", *devname.first->second, 0);
+ osd_printf_error("Device %s short name is a duplicate of %s(%s)\n", description.c_str(), core_filename_extract_base(dup->source()).c_str(), dup->shortname());
+ config.device_remove(&config.root_device(), "_dup");
+ }
+ }
+
+ // ensure name exists
+ if (!dev->name() || !*dev->name())
+ {
+ osd_printf_error("Device %s does not have name defined\n", description.c_str());
+ }
+ else
+ {
+ // check for description conflicts
+ auto const drvdesc(m_descriptions_map.find(dev->name()));
+ auto const devdesc(device_name_map.emplace(dev->name(), &type));
+ if (m_names_map.end() != drvdesc)
+ {
+ game_driver const &dup(*drvdesc->second);
+ osd_printf_error("Device %s name is a duplicate of %s(%s)\n", description.c_str(), core_filename_extract_base(dup.source_file).c_str(), dup.name);
+ }
+ else if (!devdesc.second)
+ {
+ device_t *const dup = config.device_add(&config.root_device(), "_dup", *devdesc.first->second, 0);
+ osd_printf_error("Device %s name is a duplicate of %s(%s)\n", description.c_str(), core_filename_extract_base(dup->source()).c_str(), dup->shortname());
+ config.device_remove(&config.root_device(), "_dup");
+ }
+ }
+
+ // ensure source exists
+ if (!dev->source() || !*dev->source())
+ osd_printf_error("Device %s does not have source defined\n", description.c_str());
+
+ // check that reported type matches supplied type
+ if (dev->type().type() != type.type())
+ osd_printf_error("Device %s reports type '%s' (created with '%s')\n", description.c_str(), dev->type().type().name(), type.type().name());
+
+ config.device_remove(&config.root_device(), "_tmp");
+ }
+ }
+
+ // if we had warnings or errors, output
+ if (m_errors > start_errors || m_warnings > start_warnings || !m_verbose_text.empty())
+ {
+ output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "%d errors, %d warnings\n", m_errors - start_errors, m_warnings - start_warnings);
+ if (m_errors > start_errors)
+ output_indented_errors(m_error_text, "Errors");
+ if (m_warnings > start_warnings)
+ output_indented_errors(m_warning_text, "Warnings");
+ if (!m_verbose_text.empty())
+ output_indented_errors(m_verbose_text, "Messages");
+ output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "\n");
+ }
+}
+
+
+//-------------------------------------------------
// build_output_prefix - create a prefix
// indicating the current source file, driver,
// and device
@@ -1866,7 +1986,7 @@ void validity_checker::build_output_prefix(std::string &str)
// if we have a current (non-root) device, indicate that
if (m_current_device != nullptr && m_current_device->owner() != nullptr)
- str.append(m_current_device->name()).append(" device '").append(m_current_device->tag()+1).append("': ");
+ str.append(m_current_device->name()).append(" device '").append(m_current_device->tag() + 1).append("': ");
// if we have a current port, indicate that as well
if (m_current_ioport != nullptr)