diff options
author | 2012-01-24 20:18:55 +0000 | |
---|---|---|
committer | 2012-01-24 20:18:55 +0000 | |
commit | ed0207f1267c34dd195a9807d47b74e9fab155e0 (patch) | |
tree | d162988b04326e6b945e0aa5c8a228acdb90f92a /src/emu | |
parent | f2ed9c39edc94438907152a05459483d930ab5ef (diff) |
Move devices into a proper hierarchy and handle naming
and paths consistently for devices, I/O ports, memory
regions, memory banks, and memory shares. [Aaron Giles]
NOTE: there are likely regressions lurking here, mostly
due to devices not being properly found. I have temporarily
added more logging to -verbose to help understand what's
going on. Please let me know ASAP if anything that is being
actively worked on got broken.
As before, the driver device is the root device and all
other devices are owned by it. Previously all devices
were kept in a single master list, and the hierarchy was
purely logical. With this change, each device owns its
own list of subdevices, and the hierarchy is explicitly
manifest. This means when a device is removed, all of its
subdevices are automatically removed as well.
A side effect of this is that walking the device list is
no longer simple. To address this, a new set of iterator
classes is provided, which walks the device tree in a depth
first manner. There is a general device_iterator class for
walking all devices, plus templates for a device_type_iterator
and a device_interface_iterator which are used to build
iterators for identifying only devices of a given type or
with a given interface. Typedefs for commonly-used cases
(e.g., screen_device_iterator, memory_interface_iterator)
are provided. Iterators can also provide counts, and can
perform indexed lookups.
All device name lookups are now done relative to another
device. The maching_config and running_machine classes now
have a root_device() method to get the root of the hierarchy.
The existing machine->device("name") is now equivalent to
machine->root_device().subdevice("name").
A proper and normalized device path structure is now
supported. Device names that start with a colon are
treated as absolute paths from the root device. Device
names can also use a caret (^) to refer to the owning
device. Querying the device's tag() returns the device's
full path from the root. A new method basetag() returns
just the final tag.
The new pathing system is built on top of the
device_t::subtag() method, so anyone using that will
automatically support the new pathing rules. Each device
has its own internal map to cache successful lookups so
that subsequent lookups should be very fast.
Updated every place I could find that referenced devices,
memory regions, I/O ports, memory banks and memory shares
to leverage subtag/subdevice (or siblingtag/siblingdevice
which are built on top).
Removed the device_list class, as it doesn't apply any
more. Moved some of its methods into running_machine
instead.
Simplified the device callback system since the new
pathing can describe all of the special-case devices that
were previously handled manually.
Changed the core output function callbacks to be delegates.
Completely rewrote the validity checking mechanism. The
validity checker is now a proper C++ class, and temporarily
takes over the error and warning outputs. All errors and
warnings are collected during a session, and then output in
a consistent manner, with an explicit driver and source file
listed for each one, as well as additional device and/or
I/O port contexts where appropriate. Validity checkers
should no longer explicitly output this information, just
the error, assuming that the context is provided.
Rewrote the software_list_device as a modern device, getting
rid of the software_list_config abstraction and simplifying
things.
Changed the way FLAC compiles so that it works like other
external libraries, and also compiles successfully for MSVC
builds.
Diffstat (limited to 'src/emu')
105 files changed, 2771 insertions, 2762 deletions
diff --git a/src/emu/addrmap.c b/src/emu/addrmap.c index 78f6317ceba..e1bd5d7331e 100644 --- a/src/emu/addrmap.c +++ b/src/emu/addrmap.c @@ -45,29 +45,6 @@ //************************************************************************** //------------------------------------------------- -// set_tag - set the appropriate tag for a device -//------------------------------------------------- - -inline void map_handler_data::set_tag(const device_t &device, const char *tag) -{ - if (strcmp(tag, DEVICE_SELF) == 0) - m_tag = device.tag(); - else if (strcmp(tag, DEVICE_SELF_OWNER) == 0) - { - assert(device.owner() != NULL); - m_tag = device.owner()->tag(); - } - else - m_tag = device.subtag(m_derived_tag, tag); -} - - - -//************************************************************************** -// ADDRESS MAP ENTRY -//************************************************************************** - -//------------------------------------------------- // address_map_entry - constructor //------------------------------------------------- @@ -132,7 +109,7 @@ void address_map_entry::set_mask(offs_t _mask) void address_map_entry::set_read_port(const device_t &device, const char *tag) { m_read.m_type = AMH_PORT; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); } @@ -144,7 +121,7 @@ void address_map_entry::set_read_port(const device_t &device, const char *tag) void address_map_entry::set_write_port(const device_t &device, const char *tag) { m_write.m_type = AMH_PORT; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); } @@ -156,9 +133,9 @@ void address_map_entry::set_write_port(const device_t &device, const char *tag) void address_map_entry::set_readwrite_port(const device_t &device, const char *tag) { m_read.m_type = AMH_PORT; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_write.m_type = AMH_PORT; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); } @@ -170,7 +147,7 @@ void address_map_entry::set_readwrite_port(const device_t &device, const char *t void address_map_entry::set_read_bank(const device_t &device, const char *tag) { m_read.m_type = AMH_BANK; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); } @@ -182,7 +159,7 @@ void address_map_entry::set_read_bank(const device_t &device, const char *tag) void address_map_entry::set_write_bank(const device_t &device, const char *tag) { m_write.m_type = AMH_BANK; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); } @@ -194,9 +171,9 @@ void address_map_entry::set_write_bank(const device_t &device, const char *tag) void address_map_entry::set_readwrite_bank(const device_t &device, const char *tag) { m_read.m_type = AMH_BANK; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_write.m_type = AMH_BANK; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); } @@ -213,10 +190,10 @@ void address_map_entry::set_submap(const device_t &device, const char *tag, addr assert(unitmask_is_appropriate(bits, mask, func.name())); m_read.m_type = AMH_DEVICE_SUBMAP; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_read.m_mask = mask; m_write.m_type = AMH_DEVICE_SUBMAP; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_write.m_mask = mask; m_submap_delegate = func; m_submap_bits = bits; @@ -267,7 +244,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_read.m_bits = 8; m_read.m_mask = unitmask; m_read.m_name = string; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_rdevice8 = func; } @@ -280,7 +257,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_write.m_bits = 8; m_write.m_mask = unitmask; m_write.m_name = string; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_wdevice8 = func; } @@ -300,7 +277,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_read.m_bits = 8; m_read.m_mask = unitmask; m_read.m_name = func.name(); - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_rproto8 = func; } @@ -313,7 +290,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_write.m_bits = 8; m_write.m_mask = unitmask; m_write.m_name = func.name(); - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_wproto8 = func; } @@ -369,7 +346,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_read.m_bits = 16; m_read.m_mask = unitmask; m_read.m_name = string; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_rdevice16 = func; } @@ -382,7 +359,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_write.m_bits = 16; m_write.m_mask = unitmask; m_write.m_name = string; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_wdevice16 = func; } @@ -402,7 +379,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_read.m_bits = 16; m_read.m_mask = unitmask; m_read.m_name = func.name(); - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_rproto16 = func; } @@ -415,7 +392,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_write.m_bits = 16; m_write.m_mask = unitmask; m_write.m_name = func.name(); - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_wproto16 = func; } @@ -471,7 +448,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_read.m_bits = 32; m_read.m_mask = unitmask; m_read.m_name = string; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_rdevice32 = func; } @@ -484,7 +461,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_write.m_bits = 32; m_write.m_mask = unitmask; m_write.m_name = string; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_wdevice32 = func; } @@ -504,7 +481,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_read.m_bits = 32; m_read.m_mask = unitmask; m_read.m_name = func.name(); - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_rproto32 = func; } @@ -517,7 +494,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_write.m_bits = 32; m_write.m_mask = unitmask; m_write.m_name = func.name(); - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_wproto32 = func; } @@ -573,7 +550,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_read.m_bits = 64; m_read.m_mask = 0; m_read.m_name = string; - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_rdevice64 = func; } @@ -586,7 +563,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_write.m_bits = 64; m_write.m_mask = 0; m_write.m_name = string; - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_wdevice64 = func; } @@ -606,7 +583,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_read.m_bits = 64; m_read.m_mask = 0; m_read.m_name = func.name(); - m_read.set_tag(device, tag); + device.subtag(m_read.m_tag, tag); m_rproto64 = func; } @@ -619,7 +596,7 @@ void address_map_entry::internal_set_handler(const device_t &device, const char m_write.m_bits = 64; m_write.m_mask = 0; m_write.m_name = func.name(); - m_write.set_tag(device, tag); + device.subtag(m_write.m_tag, tag); m_wproto64 = func; } diff --git a/src/emu/addrmap.h b/src/emu/addrmap.h index fb82b2aa769..af1eae23b04 100644 --- a/src/emu/addrmap.h +++ b/src/emu/addrmap.h @@ -85,17 +85,13 @@ public: : m_type(AMH_NONE), m_bits(0), m_mask(0), - m_name(NULL), - m_tag(NULL) { } + m_name(NULL) { } map_handler_type m_type; // type of the handler UINT8 m_bits; // width of the handler in bits, or 0 for default UINT64 m_mask; // mask for which lanes apply const char * m_name; // name of the handler - const char * m_tag; // tag pointing to a reference - astring m_derived_tag; // string used to hold derived names - - void set_tag(const device_t &device, const char *tag); + astring m_tag; // path to the target tag }; diff --git a/src/emu/audit.c b/src/emu/audit.c index 345baccc9e0..bfc4466d977 100644 --- a/src/emu/audit.c +++ b/src/emu/audit.c @@ -76,7 +76,7 @@ media_auditor::summary media_auditor::audit_media(const char *validation) // temporary hack until romload is update: get the driver path and support it for // all searches -const char *driverpath = m_enumerator.config().devicelist().find("root")->searchpath(); +const char *driverpath = m_enumerator.config().root_device().searchpath(); // iterate over ROM sources and regions int found = 0; @@ -234,49 +234,49 @@ media_auditor::summary media_auditor::audit_samples() int found = 0; // iterate over sample entries - for (const device_t *device = m_enumerator.config().first_device(); device != NULL; device = device->next()) - if (device->type() == SAMPLES) + samples_device_iterator iter(m_enumerator.config().root_device()); + for (samples_device *device = iter.first(); device != NULL; device = iter.next()) + { + const samples_interface *intf = reinterpret_cast<const samples_interface *>(device->static_config()); + if (intf->samplenames != NULL) { - const samples_interface *intf = reinterpret_cast<const samples_interface *>(device->static_config()); - if (intf->samplenames != NULL) - { - // by default we just search using the driver name - astring searchpath(m_enumerator.driver().name); + // by default we just search using the driver name + astring searchpath(m_enumerator.driver().name); - // iterate over samples in this entry - for (int sampnum = 0; intf->samplenames[sampnum] != NULL; sampnum++) + // iterate over samples in this entry + for (int sampnum = 0; intf->samplenames[sampnum] != NULL; sampnum++) + { + // starred entries indicate an additional searchpath + if (intf->samplenames[sampnum][0] == '*') { - // starred entries indicate an additional searchpath - if (intf->samplenames[sampnum][0] == '*') - { - searchpath.cat(";").cat(&intf->samplenames[sampnum][1]); - continue; - } + searchpath.cat(";").cat(&intf->samplenames[sampnum][1]); + continue; + } - required++; + required++; - // create a new record - audit_record &record = m_record_list.append(*global_alloc(audit_record(intf->samplenames[sampnum], audit_record::MEDIA_SAMPLE))); + // create a new record + audit_record &record = m_record_list.append(*global_alloc(audit_record(intf->samplenames[sampnum], audit_record::MEDIA_SAMPLE))); - // look for the files - emu_file file(m_enumerator.options().sample_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD); - path_iterator path(searchpath); - astring curpath; - while (path.next(curpath, intf->samplenames[sampnum])) + // look for the files + emu_file file(m_enumerator.options().sample_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD); + path_iterator path(searchpath); + astring curpath; + while (path.next(curpath, intf->samplenames[sampnum])) + { + // attempt to access the file + file_error filerr = file.open(curpath); + if (filerr == FILERR_NONE) { - // attempt to access the file - file_error filerr = file.open(curpath); - if (filerr == FILERR_NONE) - { - record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD); - found++; - } - else - record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND); + record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD); + found++; } + else + record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND); } } } + } if (found == 0 && required > 0) { diff --git a/src/emu/cheat.c b/src/emu/cheat.c index e058398717f..d9939bc2f93 100644 --- a/src/emu/cheat.c +++ b/src/emu/cheat.c @@ -1174,8 +1174,8 @@ void cheat_manager::reload() // load the cheat file, MESS will load a crc32.xml ( eg. 01234567.xml ) // and MAME will load gamename.xml - device_image_interface *image = NULL; - for (bool gotone = machine().devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine().root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) if (image->exists()) { // if we are loading through software lists, try to load shortname.xml diff --git a/src/emu/clifront.c b/src/emu/clifront.c index 00bc2dde8bf..c7339c078ff 100644 --- a/src/emu/clifront.c +++ b/src/emu/clifront.c @@ -183,14 +183,14 @@ int cli_frontend::execute(int argc, char **argv) if (strlen(m_options.software_name()) > 0) { machine_config config(*system, m_options); - if (!config.devicelist().first(SOFTWARE_LIST)) + software_list_device_iterator iter(config.root_device()); + if (iter.first() == NULL) throw emu_fatalerror(MAMERR_FATALERROR, "Error: unknown option: %s\n", m_options.software_name()); bool found = FALSE; - for (device_t *swlists = config.devicelist().first(SOFTWARE_LIST); swlists != NULL; swlists = swlists->typenext()) + for (software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(swlists)->inline_config(); - software_list *list = software_list_open(m_options, swlist->list_name, FALSE, NULL); + software_list *list = software_list_open(m_options, swlist->list_name(), FALSE, NULL); if (list) { software_info *swinfo = software_list_find(list, m_options.software_name(), NULL); @@ -205,8 +205,8 @@ int cli_frontend::execute(int argc, char **argv) if (mount == NULL || strcmp(mount,"no") != 0) { // search for an image device with the right interface - const device_image_interface *image = NULL; - for (bool gotone = config.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator imgiter(config.root_device()); + for (device_image_interface *image = imgiter.first(); image != NULL; image = imgiter.next()) { const char *interface = image->image_interface(); if (interface != NULL) @@ -218,7 +218,7 @@ int cli_frontend::execute(int argc, char **argv) if (strlen(option) == 0) { astring val; - val.printf("%s:%s:%s",swlist->list_name,m_options.software_name(),swpart->name); + val.printf("%s:%s:%s",swlist->list_name(),m_options.software_name(),swpart->name); // call this in order to set slot devices according to mounting m_options.parse_slot_devices(argc, argv, option_errors, image->instance_name(), val.cstr()); break; @@ -238,7 +238,7 @@ int cli_frontend::execute(int argc, char **argv) } if (!found) { - software_display_matches(config.devicelist(),m_options, NULL,m_options.software_name()); + software_display_matches(config,m_options, NULL,m_options.software_name()); throw emu_fatalerror(MAMERR_FATALERROR, ""); } } @@ -551,11 +551,8 @@ void cli_frontend::listsamples(const char *gamename) while (drivlist.next()) { // see if we have samples - const device_t *device; - for (device = drivlist.config().first_device(); device != NULL; device = device->next()) - if (device->type() == SAMPLES) - break; - if (device == NULL) + samples_device_iterator iter(drivlist.config().root_device()); + if (iter.first() == NULL) continue; // print a header @@ -565,16 +562,15 @@ void cli_frontend::listsamples(const char *gamename) mame_printf_info("Samples required for driver \"%s\".\n", drivlist.driver().name); // iterate over samples devices - for ( ; device != NULL; device = device->next()) - if (device->type() == SAMPLES) - { - // if the list is legit, walk it and print the sample info - const char *const *samplenames = reinterpret_cast<const samples_interface *>(device->static_config())->samplenames; - if (samplenames != NULL) - for (int sampnum = 0; samplenames[sampnum] != NULL; sampnum++) - if (samplenames[sampnum][0] != '*') - mame_printf_info("%s\n", samplenames[sampnum]); - } + for (samples_device *device = iter.first(); device != NULL; device = iter.next()) + { + // if the list is legit, walk it and print the sample info + const char *const *samplenames = reinterpret_cast<const samples_interface *>(device->static_config())->samplenames; + if (samplenames != NULL) + for (int sampnum = 0; samplenames[sampnum] != NULL; sampnum++) + if (samplenames[sampnum][0] != '*') + mame_printf_info("%s\n", samplenames[sampnum]); + } } } @@ -602,7 +598,8 @@ void cli_frontend::listdevices(const char *gamename) printf("Driver %s (%s):\n", drivlist.driver().name, drivlist.driver().description); // iterate through devices - for (const device_t *device = drivlist.config().first_device(); device != NULL; device = device->next()) + device_iterator iter(drivlist.config().root_device()); + for (const device_t *device = iter.first(); device != NULL; device = iter.next()) { printf(" %s ('%s')", device->name(), device->tag()); @@ -642,9 +639,9 @@ void cli_frontend::listslots(const char *gamename) while (drivlist.next()) { // iterate - const device_slot_interface *slot = NULL; + slot_interface_iterator iter(drivlist.config().root_device()); bool first = true; - for (bool gotone = drivlist.config().devicelist().first(slot); gotone; gotone = slot->next(slot)) + for (const device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) { // output the line, up to the list of extensions printf("%-13s%-10s ", first ? drivlist.driver().name : "", slot->device().tag()); @@ -653,7 +650,7 @@ void cli_frontend::listslots(const char *gamename) const slot_interface* intf = slot->get_slot_interfaces(); for (int i = 0; intf[i].name != NULL; i++) { - device_t *dev = (*intf[i].devtype)(drivlist.config(), "dummy", drivlist.config().devicelist().first(), 0); + device_t *dev = (*intf[i].devtype)(drivlist.config(), "dummy", &drivlist.config().root_device(), 0); dev->config_complete(); if (i==0) { printf("%-15s %s\n", intf[i].name,dev->name()); @@ -694,9 +691,9 @@ void cli_frontend::listmedia(const char *gamename) while (drivlist.next()) { // iterate - const device_image_interface *imagedev = NULL; + image_interface_iterator iter(drivlist.config().root_device()); bool first = true; - for (bool gotone = drivlist.config().devicelist().first(imagedev); gotone; gotone = imagedev->next(imagedev)) + for (const device_image_interface *imagedev = iter.first(); imagedev != NULL; imagedev = iter.next()) { // extract the shortname with parentheses astring paren_shortname; @@ -798,7 +795,7 @@ void cli_frontend::verifyroms(const char *gamename) driver_enumerator dummy_drivlist(m_options); dummy_drivlist.next(); machine_config &config = dummy_drivlist.config(); - device_t *owner = config.devicelist().first(); + device_t *owner = &config.root_device(); // check if all are listed, note that empty one is included for (int i = 0; i < m_device_count; i++) { @@ -994,12 +991,12 @@ void cli_frontend::listsoftware(const char *gamename) // first determine the maximum number of lists we might encounter int list_count = 0; while (drivlist.next()) - for (const device_t *dev = drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) - { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config(); - if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) + { + software_list_device_iterator iter(drivlist.config().root_device()); + for (const software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) + if (swlist->list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) list_count++; - } + } // allocate a list astring *lists = global_alloc_array(astring, list_count); @@ -1079,28 +1076,28 @@ void cli_frontend::listsoftware(const char *gamename) drivlist.reset(); list_count = 0; while (drivlist.next()) - for (const device_t *dev = drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) + { + software_list_device_iterator iter(drivlist.config().root_device()); + for (const software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config(); - - if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) + if (swlist->list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) { - software_list *list = software_list_open(m_options, swlist->list_name, FALSE, NULL); + software_list *list = software_list_open(m_options, swlist->list_name(), FALSE, NULL); if ( list ) { /* Verify if we have encountered this list before */ bool seen_before = false; for (int seen_index = 0; seen_index < list_count && !seen_before; seen_index++) - if (lists[seen_index] == swlist->list_name) + if (lists[seen_index] == swlist->list_name()) seen_before = true; if (!seen_before) { - lists[list_count++] = swlist->list_name; + lists[list_count++] = swlist->list_name(); software_list_parse( list, NULL, NULL ); - fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlist->list_name, xml_normalize_string(software_list_get_description(list)) ); + fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlist->list_name(), xml_normalize_string(software_list_get_description(list)) ); for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) ) { @@ -1239,6 +1236,7 @@ void cli_frontend::listsoftware(const char *gamename) } } } + } if (list_count > 0) fprintf( out, "</softwarelists>\n" ); @@ -1300,8 +1298,8 @@ void cli_frontend::execute_commands(const char *exename) // validate? if (strcmp(m_options.command(), CLICOMMAND_VALIDATE) == 0) { - validate_drivers(m_options); - validate_softlists(m_options); + validity_checker valid(m_options); + valid.check_all(); return; } @@ -1634,10 +1632,10 @@ int media_identifier::find_by_hash(const hash_collection &hashes, int length) } // next iterate over softlists - for (const device_t *dev = m_drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) + software_list_device_iterator iter(m_drivlist.config().root_device()); + for (const software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config(); - software_list *list = software_list_open(m_drivlist.options(), swlist->list_name, FALSE, NULL); + software_list *list = software_list_open(m_drivlist.options(), swlist->list_name(), FALSE, NULL); for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) for (software_part *part = software_find_part(swinfo, NULL, NULL); part != NULL; part = software_part_next(part)) @@ -1652,7 +1650,7 @@ int media_identifier::find_by_hash(const hash_collection &hashes, int length) // output information about the match if (found) mame_printf_info(" "); - mame_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlist->list_name, swinfo->shortname, swinfo->longname); + mame_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlist->list_name(), swinfo->shortname, swinfo->longname); found++; } } diff --git a/src/emu/cpu/psx/psx.c b/src/emu/cpu/psx/psx.c index e743ca4ec1e..0795b2180bc 100644 --- a/src/emu/cpu/psx/psx.c +++ b/src/emu/cpu/psx/psx.c @@ -3158,29 +3158,24 @@ void psxcpu_device::setcp3cr( int reg, UINT32 value ) psxcpu_device *psxcpu_device::getcpu( device_t &device, const char *cputag ) { - if( strcmp( cputag, DEVICE_SELF ) == 0 ) - { - return downcast<psxcpu_device *>( &device ); - } - - return downcast<psxcpu_device *>( device.siblingdevice( cputag ) ); + return downcast<psxcpu_device *>( device.subdevice( cputag ) ); } void psxcpu_device::irq_set( device_t &device, const char *cputag, UINT32 bitmask ) { - psxirq_device *irq = downcast<psxirq_device *>( getcpu( device, cputag )->subdevice("irq") ); + psxirq_device *irq = getcpu( device, cputag )->subdevice<psxirq_device>("irq"); irq->set( bitmask ); } void psxcpu_device::install_sio_handler( device_t &device, const char *cputag, int n_port, psx_sio_handler p_f_sio_handler ) { - psxsio_device *sio = downcast<psxsio_device *>( getcpu( device, cputag )->subdevice("sio") ); + psxsio_device *sio = getcpu( device, cputag )->subdevice<psxsio_device>("sio"); sio->install_handler( n_port, p_f_sio_handler ); } void psxcpu_device::sio_input( device_t &device, const char *cputag, int n_port, int n_mask, int n_data ) { - psxsio_device *sio = downcast<psxsio_device *>( getcpu( device, cputag )->subdevice("sio") ); + psxsio_device *sio = getcpu( device, cputag )->subdevice<psxsio_device>("sio"); sio->input( n_port, n_mask, n_data ); } diff --git a/src/emu/cpu/psx/psx.h b/src/emu/cpu/psx/psx.h index 6b5e9349daf..6c984186f5f 100644 --- a/src/emu/cpu/psx/psx.h +++ b/src/emu/cpu/psx/psx.h @@ -105,10 +105,10 @@ enum //************************************************************************** #define MCFG_PSX_DMA_CHANNEL_READ( cputag, channel, handler ) \ - downcast<psxdma_device *>( psxcpu_device::getcpu( *owner, cputag )->subdevice("dma") )->install_read_handler( channel, handler ); + psxcpu_device::getcpu( *owner, cputag )->subdevice<psxdma_device>("dma")->install_read_handler( channel, handler ); #define MCFG_PSX_DMA_CHANNEL_WRITE( cputag, channel, handler ) \ - downcast<psxdma_device *>( psxcpu_device::getcpu( *owner, cputag )->subdevice("dma") )->install_write_handler( channel, handler ); + psxcpu_device::getcpu( *owner, cputag )->subdevice<psxdma_device>("dma")->install_write_handler( channel, handler ); diff --git a/src/emu/cpu/tms34010/tms34010.c b/src/emu/cpu/tms34010/tms34010.c index 36252211cb4..e6068214e2d 100644 --- a/src/emu/cpu/tms34010/tms34010.c +++ b/src/emu/cpu/tms34010/tms34010.c @@ -1087,7 +1087,8 @@ SCREEN_UPDATE_IND16( tms340x0_ind16 ) int x; /* find the owning CPU */ - for (cpu = screen.machine().devicelist().first(); cpu != NULL; cpu = cpu->next()) + device_iterator iter(screen.machine().root_device()); + for (cpu = iter.first(); cpu != NULL; cpu = iter.next()) { device_type type = cpu->type(); if (type == TMS34010 || type == TMS34020) @@ -1135,7 +1136,8 @@ SCREEN_UPDATE_RGB32( tms340x0_rgb32 ) int x; /* find the owning CPU */ - for (cpu = screen.machine().devicelist().first(); cpu != NULL; cpu = cpu->next()) + device_iterator iter(screen.machine().root_device()); + for (cpu = iter.first(); cpu != NULL; cpu = iter.next()) { device_type type = cpu->type(); if (type == TMS34010 || type == TMS34020) diff --git a/src/emu/debug/debugcmd.c b/src/emu/debug/debugcmd.c index 5f5606f1968..4711418c06d 100644 --- a/src/emu/debug/debugcmd.c +++ b/src/emu/debug/debugcmd.c @@ -391,7 +391,8 @@ void debug_command_init(running_machine &machine) static void debug_command_exit(running_machine &machine) { /* turn off all traces */ - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) device->debug()->trace(NULL, 0, NULL); if (cheat.length) @@ -545,8 +546,8 @@ int debug_command_parameter_cpu(running_machine &machine, const char *param, dev } /* if we got a valid one, return */ - device_execute_interface *exec = NULL; - for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator iter(machine.root_device()); + for (device_execute_interface *exec = iter.first(); exec != NULL; exec = iter.next()) if (cpunum-- == 0) { *result = &exec->device(); @@ -982,8 +983,8 @@ static void execute_focus(running_machine &machine, int ref, int params, const c cpu->debug()->ignore(false); /* then loop over CPUs and set the ignore flags on all other CPUs */ - device_execute_interface *exec = NULL; - for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator iter(machine.root_device()); + for (device_execute_interface *exec = iter.first(); exec != NULL; exec = iter.next()) if (&exec->device() != cpu) exec->device().debug()->ignore(true); debug_console_printf(machine, "Now focused on CPU '%s'\n", cpu->tag()); @@ -1002,8 +1003,8 @@ static void execute_ignore(running_machine &machine, int ref, int params, const astring buffer; /* loop over all executable devices */ - device_execute_interface *exec = NULL; - for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator iter(machine.root_device()); + for (device_execute_interface *exec = iter.first(); exec != NULL; exec = iter.next()) /* build up a comma-separated list */ if (!exec->device().debug()->observing()) @@ -1034,11 +1035,14 @@ static void execute_ignore(running_machine &machine, int ref, int params, const for (int paramnum = 0; paramnum < params; paramnum++) { /* make sure this isn't the last live CPU */ - device_execute_interface *exec = NULL; - bool gotone; - for (gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator iter(machine.root_device()); + bool gotone = false; + for (device_execute_interface *exec = iter.first(); exec != NULL; exec = iter.next()) if (&exec->device() != devicelist[paramnum] && exec->device().debug()->observing()) + { + gotone = true; break; + } if (!gotone) { debug_console_printf(machine, "Can't ignore all devices!\n"); @@ -1064,8 +1068,8 @@ static void execute_observe(running_machine &machine, int ref, int params, const astring buffer; /* loop over all executable devices */ - device_execute_interface *exec = NULL; - for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator iter(machine.root_device()); + for (device_execute_interface *exec = iter.first(); exec != NULL; exec = iter.next()) /* build up a comma-separated list */ if (exec->device().debug()->observing()) @@ -1214,7 +1218,8 @@ static void execute_bpclear(running_machine &machine, int ref, int params, const /* if 0 parameters, clear all */ if (params == 0) { - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) device->debug()->breakpoint_clear_all(); debug_console_printf(machine, "Cleared all breakpoints\n"); } @@ -1224,8 +1229,9 @@ static void execute_bpclear(running_machine &machine, int ref, int params, const return; else { + device_iterator iter(machine.root_device()); bool found = false; - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->debug()->breakpoint_clear(bpindex)) found = true; if (found) @@ -1248,7 +1254,8 @@ static void execute_bpdisenable(running_machine &machine, int ref, int params, c /* if 0 parameters, clear all */ if (params == 0) { - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) device->debug()->breakpoint_enable_all(ref); if (ref == 0) debug_console_printf(machine, "Disabled all breakpoints\n"); @@ -1261,8 +1268,9 @@ static void execute_bpdisenable(running_machine &machine, int ref, int params, c return; else { + device_iterator iter(machine.root_device()); bool found = false; - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->debug()->breakpoint_enable(bpindex, ref)) found = true; if (found) @@ -1284,7 +1292,8 @@ static void execute_bplist(running_machine &machine, int ref, int params, const astring buffer; /* loop over all CPUs */ - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->debug()->breakpoint_first() != NULL) { debug_console_printf(machine, "Device '%s' breakpoints:\n", device->tag()); @@ -1372,7 +1381,8 @@ static void execute_wpclear(running_machine &machine, int ref, int params, const /* if 0 parameters, clear all */ if (params == 0) { - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) device->debug()->watchpoint_clear_all(); debug_console_printf(machine, "Cleared all watchpoints\n"); } @@ -1382,8 +1392,9 @@ static void execute_wpclear(running_machine &machine, int ref, int params, const return; else { + device_iterator iter(machine.root_device()); bool found = false; - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->debug()->watchpoint_clear(wpindex)) found = true; if (found) @@ -1406,7 +1417,8 @@ static void execute_wpdisenable(running_machine &machine, int ref, int params, c /* if 0 parameters, clear all */ if (params == 0) { - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) device->debug()->watchpoint_enable_all(ref); if (ref == 0) debug_console_printf(machine, "Disabled all watchpoints\n"); @@ -1419,8 +1431,9 @@ static void execute_wpdisenable(running_machine &machine, int ref, int params, c return; else { + device_iterator iter(machine.root_device()); bool found = false; - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->debug()->watchpoint_enable(wpindex, ref)) found = true; if (found) @@ -1442,7 +1455,8 @@ static void execute_wplist(running_machine &machine, int ref, int params, const astring buffer; /* loop over all CPUs */ - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++) if (device->debug()->watchpoint_first(spacenum) != NULL) { @@ -1484,7 +1498,8 @@ static void execute_hotspot(running_machine &machine, int ref, int params, const bool cleared = false; /* loop over CPUs and find live spots */ - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->debug()->hotspot_tracking_enabled()) { device->debug()->hotspot_track(0, 0); @@ -2498,7 +2513,8 @@ static void execute_snap(running_machine &machine, int ref, int params, const ch const char *filename = param[0]; int scrnum = (params > 1) ? atoi(param[1]) : 0; - screen_device *screen = downcast<screen_device *>(machine.devicelist().find(SCREEN, scrnum)); + screen_device_iterator iter(machine.root_device()); + screen_device *screen = iter.byindex(scrnum); if ((screen == NULL) || !machine.render().is_live(*screen)) { @@ -2682,12 +2698,12 @@ static void execute_hardreset(running_machine &machine, int ref, int params, con static void execute_images(running_machine &machine, int ref, int params, const char **param) { - device_image_interface *img = NULL; - for (bool gotone = machine.devicelist().first(img); gotone; gotone = img->next(img)) + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *img = iter.first(); img != NULL; img = iter.next()) { debug_console_printf(machine, "%s: %s\n",img->brief_instance_name(),img->exists() ? img->filename() : "[empty slot]"); } - if (!machine.devicelist().first(img)) { + if (iter.first() == NULL) { debug_console_printf(machine, "No image devices in this driver\n"); } } @@ -2698,9 +2714,9 @@ static void execute_images(running_machine &machine, int ref, int params, const static void execute_mount(running_machine &machine, int ref, int params, const char **param) { - device_image_interface *img = NULL; + image_interface_iterator iter(machine.root_device()); bool done = false; - for (bool gotone = machine.devicelist().first(img); gotone; gotone = img->next(img)) + for (device_image_interface *img = iter.first(); img != NULL; img = iter.next()) { if (strcmp(img->brief_instance_name(),param[0])==0) { if (img->load(param[1])==IMAGE_INIT_FAIL) { @@ -2722,9 +2738,9 @@ static void execute_mount(running_machine &machine, int ref, int params, const c static void execute_unmount(running_machine &machine, int ref, int params, const char **param) { - device_image_interface *img = NULL; + image_interface_iterator iter(machine.root_device()); bool done = false; - for (bool gotone = machine.devicelist().first(img); gotone; gotone = img->next(img)) + for (device_image_interface *img = iter.first(); img != NULL; img = iter.next()) { if (strcmp(img->brief_instance_name(),param[0])==0) { img->unload(); diff --git a/src/emu/debug/debugcpu.c b/src/emu/debug/debugcpu.c index c4a092dd160..9e46112abf6 100644 --- a/src/emu/debug/debugcpu.c +++ b/src/emu/debug/debugcpu.c @@ -201,7 +201,8 @@ void debug_cpu_flush_traces(running_machine &machine) { /* this can be called on exit even when no debugging is enabled, so make sure the devdebug is valid before proceeding */ - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->debug() != NULL) device->debug()->trace_flush(); } @@ -337,8 +338,9 @@ bool debug_comment_save(running_machine &machine) xml_set_attribute(systemnode, "name", machine.system().name); // for each device + device_iterator iter(machine.root_device()); bool found_comments = false; - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->debug()->comment_count() > 0) { // create a node for this device @@ -1081,7 +1083,8 @@ static void on_vblank(running_machine &machine, screen_device &device, bool vbla static void reset_transient_flags(running_machine &machine) { /* loop over CPUs and reset the transient flags */ - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) device->debug()->reset_transient_flag(); machine.debugcpu_data->m_stop_when_not_device = NULL; } @@ -1144,9 +1147,8 @@ static void process_source_file(running_machine &machine) static device_t *expression_get_device(running_machine &machine, const char *tag) { - device_t *device; - - for (device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (mame_stricmp(device->tag(), tag) == 0) return device; @@ -1630,15 +1632,8 @@ static UINT64 get_cpunum(symbol_table &table, void *ref) running_machine &machine = *reinterpret_cast<running_machine *>(table.globalref()); device_t *target = machine.debugcpu_data->visiblecpu; - device_execute_interface *exec = NULL; - int index = 0; - for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec)) - { - if (&exec->device() == target) - return index; - index++; - } - return 0; + execute_interface_iterator iter(machine.root_device()); + return iter.indexof(target->execute()); } diff --git a/src/emu/debug/dvdisasm.c b/src/emu/debug/dvdisasm.c index ac3a89a8803..a8041abc168 100644 --- a/src/emu/debug/dvdisasm.c +++ b/src/emu/debug/dvdisasm.c @@ -132,9 +132,9 @@ void debug_view_disasm::enumerate_sources() m_source_list.reset(); // iterate over devices with disassembly interfaces - device_disasm_interface *dasm = NULL; + disasm_interface_iterator iter(machine().root_device()); astring name; - for (bool gotone = machine().devicelist().first(dasm); gotone; gotone = dasm->next(dasm)) + for (device_disasm_interface *dasm = iter.first(); dasm != NULL; dasm = iter.next()) { name.printf("%s '%s'", dasm->device().name(), dasm->device().tag()); m_source_list.append(*auto_alloc(machine(), debug_view_disasm_source(name, dasm->device()))); diff --git a/src/emu/debug/dvmemory.c b/src/emu/debug/dvmemory.c index a1d4d88f9f8..779e10f256d 100644 --- a/src/emu/debug/dvmemory.c +++ b/src/emu/debug/dvmemory.c @@ -152,8 +152,8 @@ void debug_view_memory::enumerate_sources() astring name; // first add all the devices' address spaces - device_memory_interface *memintf = NULL; - for (bool gotone = machine().devicelist().first(memintf); gotone; gotone = memintf->next(memintf)) + memory_interface_iterator iter(machine().root_device()); + for (device_memory_interface *memintf = iter.first(); memintf != NULL; memintf = iter.next()) for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++) { address_space *space = memintf->space(spacenum); diff --git a/src/emu/debug/dvstate.c b/src/emu/debug/dvstate.c index 9d14f1c83d8..5cbd08091eb 100644 --- a/src/emu/debug/dvstate.c +++ b/src/emu/debug/dvstate.c @@ -103,9 +103,9 @@ void debug_view_state::enumerate_sources() m_source_list.reset(); // iterate over devices that have state interfaces - device_state_interface *state = NULL; + state_interface_iterator iter(machine().root_device()); astring name; - for (bool gotone = machine().devicelist().first(state); gotone; gotone = state->next(state)) + for (device_state_interface *state = iter.first(); state != NULL; state = iter.next()) { name.printf("%s '%s'", state->device().name(), state->device().tag()); m_source_list.append(*auto_alloc(machine(), debug_view_state_source(name, state->device()))); diff --git a/src/emu/devcb.c b/src/emu/devcb.c index 03c18f75c52..089dcd3388b 100644 --- a/src/emu/devcb.c +++ b/src/emu/devcb.c @@ -96,17 +96,7 @@ const input_port_config *devcb_resolver::resolve_port(const char *tag, device_t device_t *devcb_resolver::resolve_device(int index, const char *tag, device_t ¤t) { - device_t *result = NULL; - - if (index == DEVCB_DEVICE_SELF) - result = ¤t; - else if (index == DEVCB_DEVICE_DRIVER) - result = current.machine().driver_data(); - else if (strcmp(tag, DEVICE_SELF_OWNER) == 0) - result = current.owner(); - else - result = current.siblingdevice(tag); - + device_t *result = current.siblingdevice(tag); if (result == NULL) throw emu_fatalerror("Unable to resolve device '%s' (requested by callback to %s '%s')", tag, current.name(), current.tag()); return result; diff --git a/src/emu/devcb.h b/src/emu/devcb.h index 6ce7c70ca3f..cbb39d4feb9 100644 --- a/src/emu/devcb.h +++ b/src/emu/devcb.h @@ -93,14 +93,6 @@ enum DEVCB_TYPE_CONSTANT // constant value read }; -// for DEVCB_TYPE_DEVICE, some further differentiation -enum -{ - DEVCB_DEVICE_SELF, // ignore 'tag', refers to the device itself - DEVCB_DEVICE_DRIVER, // ignore 'tag', refers to the driver device - DEVCB_DEVICE_OTHER // device specified by 'tag' -}; - //************************************************************************** @@ -158,20 +150,20 @@ void devcb_stub16(device_t *device, offs_t offset, UINT16 data) #define DEVCB_NULL { DEVCB_TYPE_NULL } // standard line or read/write handlers with the calling device passed -#define DEVCB_LINE(func) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_SELF, NULL, #func, func, NULL, NULL } -#define DEVCB_LINE_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_SELF, NULL, #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL } -#define DEVCB_HANDLER(func) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_SELF, NULL, #func, NULL, func, NULL } -#define DEVCB_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_SELF, NULL, #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL } +#define DEVCB_LINE(func) { DEVCB_TYPE_DEVICE, 0, "", #func, func, NULL, NULL } +#define DEVCB_LINE_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, 0, "", #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL } +#define DEVCB_HANDLER(func) { DEVCB_TYPE_DEVICE, 0, "", #func, NULL, func, NULL } +#define DEVCB_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, 0, "", #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL } // line or read/write handlers for the driver device -#define DEVCB_DRIVER_LINE_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_DRIVER, NULL, #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL } -#define DEVCB_DRIVER_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_DRIVER, NULL, #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL } +#define DEVCB_DRIVER_LINE_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, 0, ":", #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL } +#define DEVCB_DRIVER_MEMBER(cls,memb) { DEVCB_TYPE_DEVICE, 0, ":", #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL } // line or read/write handlers for another device -#define DEVCB_DEVICE_LINE(tag,func) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_OTHER, tag, #func, func, NULL, NULL } -#define DEVCB_DEVICE_LINE_MEMBER(tag,cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_OTHER, tag, #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL } -#define DEVCB_DEVICE_HANDLER(tag,func) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_OTHER, tag, #func, NULL, func, NULL } -#define DEVCB_DEVICE_MEMBER(tag,cls,memb) { DEVCB_TYPE_DEVICE, DEVCB_DEVICE_OTHER, tag, #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL } +#define DEVCB_DEVICE_LINE(tag,func) { DEVCB_TYPE_DEVICE, 0, tag, #func, func, NULL, NULL } +#define DEVCB_DEVICE_LINE_MEMBER(tag,cls,memb) { DEVCB_TYPE_DEVICE, 0, tag, #cls "::" #memb, &devcb_line_stub<cls, &cls::memb>, NULL, NULL } +#define DEVCB_DEVICE_HANDLER(tag,func) { DEVCB_TYPE_DEVICE, 0, tag, #func, NULL, func, NULL } +#define DEVCB_DEVICE_MEMBER(tag,cls,memb) { DEVCB_TYPE_DEVICE, 0, tag, #cls "::" #memb, NULL, &devcb_stub<cls, &cls::memb>, NULL } // constant values #define DEVCB_CONSTANT(value) { DEVCB_TYPE_CONSTANT, value, NULL, NULL, NULL, NULL } diff --git a/src/emu/device.c b/src/emu/device.c index cf974663892..9b166287dc4 100644 --- a/src/emu/device.c +++ b/src/emu/device.c @@ -87,234 +87,6 @@ resource_pool &machine_get_pool(running_machine &machine) //************************************************************************** -// DEVICE LIST MANAGEMENT -//************************************************************************** - -//------------------------------------------------- -// device_list - device list constructor -//------------------------------------------------- - -device_list::device_list(resource_pool &pool) - : tagged_list<device_t>(pool) -{ -} - - -//------------------------------------------------- -// set_machine_all - once the machine is created, -// tell every device about it -//------------------------------------------------- - -void device_list::set_machine_all(running_machine &machine) -{ - // add exit and reset callbacks - m_machine = &machine; - - // iterate over devices and set their machines as well - for (device_t *device = first(); device != NULL; device = device->next()) - device->set_machine(machine); -} - - -//------------------------------------------------- -// start_all - start all the devices in the -// list -//------------------------------------------------- - -void device_list::start_all() -{ - // add exit and reset callbacks - machine().add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(device_list::reset_all), this)); - machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(device_list::exit), this)); - - // add pre-save and post-load callbacks - machine().save().register_presave(save_prepost_delegate(FUNC(device_list::presave_all), this)); - machine().save().register_postload(save_prepost_delegate(FUNC(device_list::postload_all), this)); - - // start_new_devices does all the necessary work - start_new_devices(); -} - - -//------------------------------------------------- -// start_new_devices - start any unstarted devices -//------------------------------------------------- - -void device_list::start_new_devices() -{ - assert(m_machine != NULL); - - // iterate through the devices - device_t *nextdevice; - for (device_t *device = first(); device != NULL; device = nextdevice) - { - // see if this device is what we want - nextdevice = device->next(); - if (!device->started()) - { - // attempt to start the device, catching any expected exceptions - try - { - // if the device doesn't have a machine yet, set it first - if (device->m_machine == NULL) - device->set_machine(machine()); - - // now start the device - mame_printf_verbose("Starting %s '%s'\n", device->name(), device->tag()); - device->start(); - } - - // handle missing dependencies by moving the device to the end - catch (device_missing_dependencies &) - { - // if we're the end, fail - mame_printf_verbose(" (missing dependencies; rescheduling)\n"); - if (nextdevice == NULL) - throw emu_fatalerror("Circular dependency in device startup; unable to start %s '%s'\n", device->name(), device->tag()); - detach(*device); - append(device->tag(), *device); - } - } - } -} - - -//------------------------------------------------- -// reset_all - reset all devices in the list -//------------------------------------------------- - -void device_list::reset_all() -{ - // iterate over devices and reset them - for (device_t *device = first(); device != NULL; device = device->next()) - device->reset(); -} - - -//------------------------------------------------- -// stop_all - stop all the devices in the -// list -//------------------------------------------------- - -void device_list::stop_all() -{ - // iterate over devices and stop them - for (device_t *device = first(); device != NULL; device = device->next()) - device->stop(); - - // leave with no machine - m_machine = NULL; -} - - -//------------------------------------------------- -// first - return the first device of the given -// type -//------------------------------------------------- - -device_t *device_list::first(device_type type) const -{ - device_t *cur; - for (cur = super::first(); cur != NULL && cur->type() != type; cur = cur->next()) ; - return cur; -} - - -//------------------------------------------------- -// count - count the number of devices of the -// given type -//------------------------------------------------- - -int device_list::count(device_type type) const -{ - int num = 0; - for (const device_t *curdev = first(type); curdev != NULL; curdev = curdev->typenext()) num++; - return num; -} - - -//------------------------------------------------- -// indexof - return the index of the given device -// among its kind -//------------------------------------------------- - -int device_list::indexof(device_type type, device_t &object) const -{ - int num = 0; - for (device_t *cur = first(type); cur != NULL; cur = cur->typenext(), num++) - if (cur == &object) return num; - return -1; -} - - -//------------------------------------------------- -// indexof - return the index of the given device -// among its kind -//------------------------------------------------- - -int device_list::indexof(device_type type, const char *tag) const -{ - device_t *object = find(tag); - return (object != NULL && object->type() == type) ? indexof(type, *object) : -1; -} - - -//------------------------------------------------- -// find - find a device by type + index -//------------------------------------------------- - -device_t *device_list::find(device_type type, int index) const -{ - for (device_t *cur = first(type); cur != NULL; cur = cur->typenext()) - if (index-- == 0) return cur; - return NULL; -} - - -//------------------------------------------------- -// static_exit - tear down all the devices -//------------------------------------------------- - -void device_list::exit() -{ - // first let the debugger save comments - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - debug_comment_save(machine()); - - // stop all the devices before we go away - stop_all(); - - // then nuke the devices - reset(); -} - - -//------------------------------------------------- -// presave_all - tell all the devices we are -// about to save -//------------------------------------------------- - -void device_list::presave_all() -{ - for (device_t *device = first(); device != NULL; device = device->next()) - device->pre_save(); -} - - -//------------------------------------------------- -// postload_all - tell all the devices we just -// completed a load -//------------------------------------------------- - -void device_list::postload_all() -{ - for (device_t *device = first(); device != NULL; device = device->next()) - device->post_load(); -} - - - -//************************************************************************** // LIVE DEVICE MANAGEMENT //************************************************************************** @@ -325,63 +97,75 @@ void device_list::postload_all() //------------------------------------------------- device_t::device_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) - : m_debug(NULL), + : m_type(type), + m_name(name), + m_owner(owner), + m_next(NULL), + m_interface_list(NULL), m_execute(NULL), m_memory(NULL), m_state(NULL), - m_next(NULL), - m_owner(owner), - m_interface_list(NULL), - m_type(type), m_configured_clock(clock), - m_machine_config(mconfig), - m_static_config(NULL), - m_input_defaults(NULL), - m_name(name), - m_started(false), - m_clock(clock), - m_region(NULL), m_unscaled_clock(clock), + m_clock(clock), m_clock_scale(1.0), m_attoseconds_per_clock((clock == 0) ? 0 : HZ_TO_ATTOSECONDS(clock)), + + m_debug(NULL), + m_region(NULL), + m_machine_config(mconfig), + m_static_config(NULL), + m_input_defaults(NULL), m_auto_finder_list(NULL), m_machine(NULL), m_save(NULL), - m_tag(tag), - m_config_complete(false) + m_basetag(tag), + m_config_complete(false), + m_started(false) { + if (owner != NULL) + m_tag.cpy((owner->owner() == NULL) ? "" : owner->tag()).cat(":").cat(tag); + else + m_tag.cpy(":"); + mame_printf_verbose("device '%s' created\n", this->tag()); static_set_clock(*this, clock); } device_t::device_t(const machine_config &mconfig, device_type type, const char *name, const char *shortname, const char *tag, device_t *owner, UINT32 clock) - : m_debug(NULL), + : m_type(type), + m_name(name), + m_shortname(shortname), + m_searchpath(shortname), + m_owner(owner), + m_next(NULL), + m_interface_list(NULL), m_execute(NULL), m_memory(NULL), m_state(NULL), - m_next(NULL), - m_owner(owner), - m_interface_list(NULL), - m_type(type), m_configured_clock(clock), - m_machine_config(mconfig), - m_static_config(NULL), - m_input_defaults(NULL), - m_name(name), - m_shortname(shortname), - m_searchpath(shortname), - m_started(false), - m_clock(clock), - m_region(NULL), m_unscaled_clock(clock), + m_clock(clock), m_clock_scale(1.0), m_attoseconds_per_clock((clock == 0) ? 0 : HZ_TO_ATTOSECONDS(clock)), + + m_debug(NULL), + m_region(NULL), + m_machine_config(mconfig), + m_static_config(NULL), + m_input_defaults(NULL), m_auto_finder_list(NULL), m_machine(NULL), m_save(NULL), - m_tag(tag), - m_config_complete(false) + m_basetag(tag), + m_config_complete(false), + m_started(false) { + if (owner != NULL) + m_tag.cpy((owner->owner() == NULL) ? "" : owner->tag()).cat(":").cat(tag); + else + m_tag.cpy(":"); + mame_printf_verbose("device '%s' created\n", this->tag()); static_set_clock(*this, clock); } @@ -406,43 +190,9 @@ const memory_region *device_t::subregion(const char *_tag) const if (this == NULL) return NULL; - // build a fully-qualified name - astring tempstring; - return machine().region(subtag(tempstring, _tag)); -} - - -//------------------------------------------------- -// subdevice - return a pointer to the given -// device that is owned by us -//------------------------------------------------- - -device_t *device_t::subdevice(const char *_tag) const -{ - // safety first - if (this == NULL) - return NULL; - - // build a fully-qualified name - astring tempstring; - return mconfig().devicelist().find((const char *)subtag(tempstring, _tag)); -} - - -//------------------------------------------------- -// siblingdevice - return a pointer to the given -// device that is owned by our same owner -//------------------------------------------------- - -device_t *device_t::siblingdevice(const char *_tag) const -{ - // safety first - if (this == NULL) - return NULL; - - // build a fully-qualified name - astring tempstring; - return mconfig().devicelist().find((const char *)siblingtag(tempstring, _tag)); + // build a fully-qualified name and look it up + astring fullpath; + return machine().region(subtag(fullpath, _tag)); } @@ -489,20 +239,14 @@ void device_t::config_complete() // configuration has been constructed //------------------------------------------------- -bool device_t::validity_check(emu_options &options, const game_driver &driver) const +void device_t::validity_check(validity_checker &valid) const { - bool error = false; - // validate via the interfaces for (device_interface *intf = m_interface_list; intf != NULL; intf = intf->interface_next()) - if (intf->interface_validity_check(options, driver)) - error = true; + intf->interface_validity_check(valid); // let the device itself validate - if (device_validity_check(options, driver)) - error = true; - - return error; + device_validity_check(valid); } @@ -780,10 +524,9 @@ void device_t::device_config_complete() // the configuration has been constructed //------------------------------------------------- -bool device_t::device_validity_check(emu_options &options, const game_driver &driver) const +void device_t::device_validity_check(validity_checker &valid) const { - // indicate no error by default - return false; + // do nothing by default } @@ -812,7 +555,6 @@ machine_config_constructor device_t::device_mconfig_additions() const } - //------------------------------------------------- // input_ports - return a pointer to the implicit // input ports description for this device @@ -908,6 +650,157 @@ void device_t::device_timer(emu_timer &timer, device_timer_id id, int param, voi //------------------------------------------------- +// subdevice_slow - perform a slow name lookup, +// caching the results +//------------------------------------------------- + +device_t *device_t::subdevice_slow(const char *tag) const +{ + // resolve the full path + astring fulltag; + subtag(fulltag, tag); + + // we presume the result is a rooted path; also doubled colons mess up our + // tree walk, so catch them early + assert(fulltag[0] == ':'); + assert(fulltag.find("::") == -1); + + // walk the device list to the final path + device_t *curdevice = &mconfig().root_device(); + if (fulltag.len() > 1) + for (int start = 1, end = fulltag.chr(start, ':'); start != 0 && curdevice != NULL; start = end + 1, end = fulltag.chr(start, ':')) + { + astring part(fulltag, start, (end == -1) ? -1 : end - start); + for (curdevice = curdevice->m_subdevice_list.first(); curdevice != NULL; curdevice = curdevice->next()) + if (part == curdevice->m_basetag) + break; + } + + // if we got a match, add to the fast map + if (curdevice != NULL) + { + m_device_map.add(tag, curdevice); + mame_printf_verbose("device '%s' adding mapping for '%s' => '%s'\n", this->tag(), tag, fulltag.cstr()); + } + return curdevice; +} + + +//------------------------------------------------- +// subtag - create a fully resolved path relative +// to our device based on the provided tag +//------------------------------------------------- + +astring &device_t::subtag(astring &result, const char *tag) const +{ + // if the tag begins with a colon, ignore our path and start from the root + if (*tag == ':') + { + tag++; + result.cpy(":"); + } + + // otherwise, start with our path + else + { + result.cpy(m_tag); + if (result != ":") + result.cat(":"); + } + + // iterate over the tag, look for special path characters to resolve + const char *caret; + while ((caret = strchr(tag, '^')) != NULL) + { + // copy everything up to there + result.cat(tag, caret - tag); + tag = caret + 1; + + // strip trailing colons + int len = result.len(); + while (result[--len] == ':') + result.substr(0, len); + + // remove the last path part, leaving the last colon + if (result != ":") + { + int lastcolon = result.rchr(0, ':'); + if (lastcolon != -1) + result.substr(0, lastcolon + 1); + } + } + + // copy everything else + result.cat(tag); + + // strip trailing colons up to the root + int len = result.len(); + while (len > 1 && result[--len] == ':') + result.substr(0, len); + return result; +} + + +//------------------------------------------------- +// add_subdevice - create a new device and add it +// as a subdevice +//------------------------------------------------- + +device_t *device_t::add_subdevice(device_type type, const char *tag, UINT32 clock) +{ + // allocate the device and append to our list + device_t *device = (*type)(mconfig(), tag, this, clock); + m_subdevice_list.append(*device); + + // apply any machine configuration owned by the device now + machine_config_constructor additions = device->machine_config_additions(); + if (additions != NULL) + (*additions)(const_cast<machine_config &>(mconfig()), device); + return device; +} + + +//------------------------------------------------- +// add_subdevice - create a new device and use it +// to replace an existing subdevice +//------------------------------------------------- + +device_t *device_t::replace_subdevice(device_t &old, device_type type, const char *tag, UINT32 clock) +{ + // iterate over all devices and remove any references to the old device + device_iterator iter(mconfig().root_device()); + for (device_t *scan = iter.first(); scan != NULL; scan = iter.next()) + scan->m_device_map.remove(&old); + + // create a new device, and substitute it for the old one + device_t *device = (*type)(mconfig(), tag, this, clock); + m_subdevice_list.replace_and_remove(*device, old); + + // apply any machine configuration owned by the device now + machine_config_constructor additions = device->machine_config_additions(); + if (additions != NULL) + (*additions)(const_cast<machine_config &>(mconfig()), device); + return device; +} + + +//------------------------------------------------- +// remove_subdevice - remove a given subdevice +//------------------------------------------------- + +void device_t::remove_subdevice(device_t &device) +{ + // iterate over all devices and remove any references + device_iterator iter(mconfig().root_device()); + for (device_t *scan = iter.first(); scan != NULL; scan = iter.next()) + scan->m_device_map.remove(&device); + + // remove from our list + m_subdevice_list.remove(device); +} + + +//------------------------------------------------- // register_auto_finder - add a new item to the // list of stuff to find after we go live //------------------------------------------------- @@ -1022,9 +915,8 @@ void device_interface::interface_config_complete() // constructed //------------------------------------------------- -bool device_interface::interface_validity_check(emu_options &options, const game_driver &driver) const +void device_interface::interface_validity_check(validity_checker &valid) const { - return false; } diff --git a/src/emu/device.h b/src/emu/device.h index a1028944b20..4be5c1c1170 100644 --- a/src/emu/device.h +++ b/src/emu/device.h @@ -91,41 +91,13 @@ class device_interface; class device_execute_interface; class device_memory_interface; class device_state_interface; +class validity_checker; struct rom_entry; class machine_config; class emu_timer; typedef struct _input_device_default input_device_default; -// ======================> device_delegate - -// 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 delegate<_Signature> -{ - typedef delegate<_Signature> basetype; - -public: - // provide same set of constructors as the base class, with additional device name - // parameter - device_delegate() : basetype(), m_device_name(NULL) { } - device_delegate(const basetype &src) : basetype(src), m_device_name(src.m_device_name) { } - device_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), m_device_name(src.m_device_name) { } - template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { } - template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { } - device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), m_device_name(NULL) { } - device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), m_device_name(NULL) { } - device_delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; m_device_name = src.m_device_name; return *this; } - - // perform the binding - void bind_relative_to(device_t &search_root); - -private: - // internal state - const char *m_device_name; -}; - // exception classes class device_missing_dependencies : public emu_exception { }; @@ -153,56 +125,6 @@ typedef void (*write_line_device_func)(device_t *device, int state); -// ======================> tagged_device_list - -// tagged_device_list is a tagged_list with additional searching based on type -class device_list : public tagged_list<device_t> -{ - typedef tagged_list<device_t> super; - -public: - // construction/destruction - device_list(resource_pool &pool = global_resource_pool); - - // getters - running_machine &machine() const { assert(m_machine != NULL); return *m_machine; } - - // bulk operations - void set_machine_all(running_machine &machine); - void start_all(); - void start_new_devices(); - void reset_all(); - void stop_all(); - - // pull the generic forms forward - using super::first; - using super::count; - using super::indexof; - using super::find; - - // provide type-specific overrides - device_t *first(device_type type) const; - int count(device_type type) const; - int indexof(device_type type, device_t &object) const; - int indexof(device_type type, const char *tag) const; - device_t *find(device_type type, int index) const; - - // provide interface-specific overrides - template<class _InterfaceClass> - bool first(_InterfaceClass *&intf) const; - -private: - // internal helpers - void exit(); - void presave_all(); - void postload_all(); - - // internal state - running_machine *m_machine; -}; - - - // ======================> device_t // device_t represents a device @@ -216,6 +138,8 @@ class device_t : public delegate_late_bind friend class device_execute_interface; friend class simple_list<device_t>; friend class device_list; + friend class machine_config; + friend class running_machine; protected: // construction/destruction @@ -226,12 +150,15 @@ protected: public: // getters running_machine &machine() const { assert(m_machine != NULL); return *m_machine; } + const char *tag() const { return m_tag; } + const char *basetag() const { return m_basetag; } device_type type() const { return m_type; } - UINT32 configured_clock() const { return m_configured_clock; } const char *name() const { return m_name; } const char *shortname() const { return m_shortname; } const char *searchpath() const { return m_searchpath; } - const char *tag() const { return m_tag; } + device_t *owner() const { return m_owner; } + device_t *next() const { return m_next; } + UINT32 configured_clock() const { return m_configured_clock; } const void *static_config() const { return m_static_config; } const machine_config &mconfig() const { return m_machine_config; } const input_device_default *input_ports_defaults() const { return m_input_defaults; } @@ -239,21 +166,9 @@ public: machine_config_constructor machine_config_additions() const { return device_mconfig_additions(); } ioport_constructor input_ports() const { return device_input_ports(); } - // iteration helpers - device_t *next() const { return m_next; } - device_t *typenext() const; - device_t *owner() const { return m_owner; } - // interface helpers template<class _DeviceClass> bool interface(_DeviceClass *&intf) { intf = dynamic_cast<_DeviceClass *>(this); return (intf != NULL); } template<class _DeviceClass> bool interface(_DeviceClass *&intf) const { intf = dynamic_cast<const _DeviceClass *>(this); return (intf != NULL); } - template<class _DeviceClass> bool next(_DeviceClass *&intf) const - { - for (device_t *cur = m_next; cur != NULL; cur = cur->m_next) - if (cur->interface(intf)) - return true; - return false; - } // specialized helpers for common core interfaces bool interface(device_execute_interface *&intf) { intf = m_execute; return (intf != NULL); } @@ -266,13 +181,14 @@ public: device_memory_interface &memory() const { assert(m_memory != NULL); return *m_memory; } // owned object helpers + device_t *first_subdevice() const { return m_subdevice_list.first(); } astring &subtag(astring &dest, const char *tag) const; - astring &siblingtag(astring &dest, const char *tag) const; + astring &siblingtag(astring &dest, const char *tag) const { return (this != NULL && m_owner != NULL) ? m_owner->subtag(dest, tag) : dest.cpy(tag); } const memory_region *subregion(const char *tag) const; device_t *subdevice(const char *tag) const; - device_t *siblingdevice(const char *tag) const; - template<class _DeviceClass> inline _DeviceClass *subdevice(const char *tag) { return downcast<_DeviceClass *>(subdevice(tag)); } - template<class _DeviceClass> inline _DeviceClass *siblingdevice(const char *tag) { return downcast<_DeviceClass *>(siblingdevice(tag)); } + device_t *siblingdevice(const char *tag) const { return (this != NULL && m_owner != NULL) ? m_owner->subdevice(tag) : NULL; } + template<class _DeviceClass> inline _DeviceClass *subdevice(const char *tag) const { return downcast<_DeviceClass *>(subdevice(tag)); } + template<class _DeviceClass> inline _DeviceClass *siblingdevice(const char *tag) const { return downcast<_DeviceClass *>(siblingdevice(tag)); } const memory_region *region() const { return m_region; } // configuration helpers @@ -283,7 +199,7 @@ public: // state helpers void config_complete(); bool configured() const { return m_config_complete; } - bool validity_check(emu_options &options, const game_driver &driver) const; + void validity_check(validity_checker &valid) const; bool started() const { return m_started; } void reset(); @@ -328,7 +244,7 @@ protected: virtual machine_config_constructor device_mconfig_additions() const; virtual ioport_constructor device_input_ports() const; virtual void device_config_complete(); - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const ATTR_COLD; + virtual void device_validity_check(validity_checker &valid) const ATTR_COLD; virtual void device_start() ATTR_COLD = 0; virtual void device_stop() ATTR_COLD; virtual void device_reset() ATTR_COLD; @@ -340,37 +256,37 @@ protected: //------------------- end derived class overrides - device_debug * m_debug; - - // core device interfaces for speed - device_execute_interface *m_execute; - device_memory_interface *m_memory; - device_state_interface *m_state; + // core device properties + const device_type m_type; // device type + astring m_name; // name of the device + astring m_shortname; // short name of the device + astring m_searchpath; // search path, used for media loading // device relationships - device_t * m_next; // next device (of any type/class) - device_t * m_owner; // device that owns us, or NULL if nobody + device_t * m_owner; // device that owns us + device_t * m_next; // next device by the same owner (of any type/class) + simple_list<device_t> m_subdevice_list; // list of sub-devices we own + mutable tagmap_t<device_t *> m_device_map; // map of device names looked up and found + + // device interfaces device_interface * m_interface_list; // head of interface list + device_execute_interface *m_execute; // pre-cached pointer to execute interface + device_memory_interface *m_memory; // pre-cached pointer to memory interface + device_state_interface *m_state; // pre-cached pointer to state interface - const device_type m_type; // device type + // device clocks UINT32 m_configured_clock; // originally configured device clock + UINT32 m_unscaled_clock; // current unscaled device clock + UINT32 m_clock; // current device clock, after scaling + double m_clock_scale; // clock scale factor + attoseconds_t m_attoseconds_per_clock;// period in attoseconds + device_debug * m_debug; + const memory_region * m_region; // our device-local region const machine_config & m_machine_config; // reference to the machine's configuration const void * m_static_config; // static device configuration const input_device_default *m_input_defaults; // devices input ports default overrides - astring m_name; // name of the device - astring m_shortname; // short name of the device - astring m_searchpath; // search path, used for media loading - - bool m_started; // true if the start function has succeeded - UINT32 m_clock; // device clock - const memory_region * m_region; // our device-local region - - UINT32 m_unscaled_clock; // unscaled clock - double m_clock_scale; // clock scale factor - attoseconds_t m_attoseconds_per_clock;// period in attoseconds - // helper class to request auto-object discovery in the constructor of a derived class class auto_finder_base { @@ -480,11 +396,19 @@ protected: auto_finder_base * m_auto_finder_list; private: + // private helpers + device_t *add_subdevice(device_type type, const char *tag, UINT32 clock); + device_t *replace_subdevice(device_t &old, device_type type, const char *tag, UINT32 clock); + void remove_subdevice(device_t &device); + device_t *subdevice_slow(const char *tag) const; + // private state; accessor use required running_machine * m_machine; save_manager * m_save; - astring m_tag; // tag for this instance + astring m_tag; // full tag for this instance + astring m_basetag; // base part of the tag bool m_config_complete; // have we completed our configuration? + bool m_started; // true if the start function has succeeded }; @@ -514,7 +438,7 @@ public: // optional operation overrides virtual void interface_config_complete(); - virtual bool interface_validity_check(emu_options &options, const game_driver &driver) const; + virtual void interface_validity_check(validity_checker &valid) const; virtual void interface_pre_start(); virtual void interface_post_start(); virtual void interface_pre_reset(); @@ -533,48 +457,299 @@ protected: }; +// ======================> device_iterator -//************************************************************************** -// INLINE FUNCTIONS -//************************************************************************** +// helper class to iterate over the hierarchy of devices depth-first +class device_iterator +{ +public: + // construction + device_iterator(device_t &root, int maxdepth = 255) + : m_root(&root), + m_current(NULL), + m_curdepth(0), + m_maxdepth(maxdepth) { } + + // getters + device_t *current() const { return m_current; } + // setters + void set_current(device_t ¤t) { m_current = ¤t; } + + // reset and return first item + device_t *first() + { + m_current = m_root; + return m_current; + } -// ======================> device config helpers + // advance depth-first + device_t *next() + { + // remember our starting position, and end immediately if we're NULL + device_t *start = m_current; + if (start == NULL) + return NULL; -// find the next device_t of the same type -inline device_t *device_t::typenext() const + // search down first + if (m_curdepth < m_maxdepth) + { + m_current = start->first_subdevice(); + if (m_current != NULL) + { + m_curdepth++; + return m_current; + } + } + + // search next for neighbors up the ownership chain + while (m_curdepth > 0) + { + // found a neighbor? great! + m_current = start->next(); + if (m_current != NULL) + return m_current; + + // no? try our parent + start = start->owner(); + m_curdepth--; + } + + // returned to the top; we're done + return m_current = NULL; + } + + // return the number of items available + int count() + { + int result = 0; + for (device_t *item = first(); item != NULL; item = next()) + result++; + return result; + } + + // return the index of a given item in the virtual list + int indexof(device_t &device) + { + int index = 0; + for (device_t *item = first(); item != NULL; item = next(), index++) + if (item == &device) + return index; + return -1; + } + + // return the indexed item in the list + device_t *byindex(int index) + { + for (device_t *item = first(); item != NULL; item = next(), index--) + if (index == 0) + return item; + return NULL; + } + +private: + // internal state + device_t * m_root; + device_t * m_current; + int m_curdepth; + int m_maxdepth; +}; + + +// ======================> device_type_iterator + +// helper class to find devices of a given type in the device hierarchy +template<device_type _DeviceType, class _DeviceClass = device_t> +class device_type_iterator { - device_t *cur; - for (cur = m_next; cur != NULL && cur->m_type != m_type; cur = cur->m_next) ; - return cur; -} +public: + // construction + device_type_iterator(device_t &root, int maxdepth = 255) + : m_iterator(root, maxdepth) { } + + // getters + _DeviceClass *current() const { return downcast<_DeviceClass *>(m_iterator.current()); } + + // setters + void set_current(_DeviceClass ¤t) { m_iterator.set_current(current); } -// create a tag for an object that is owned by this device -inline astring &device_t::subtag(astring &dest, const char *_tag) const + // reset and return first item + _DeviceClass *first() + { + for (device_t *device = m_iterator.first(); device != NULL; device = m_iterator.next()) + if (device->type() == _DeviceType) + return downcast<_DeviceClass *>(device); + return NULL; + } + + // advance depth-first + _DeviceClass *next() + { + for (device_t *device = m_iterator.next(); device != NULL; device = m_iterator.next()) + if (device->type() == _DeviceType) + return downcast<_DeviceClass *>(device); + return NULL; + } + + // return the number of items available + int count() + { + int result = 0; + for (_DeviceClass *item = first(); item != NULL; item = next()) + result++; + return result; + } + + // return the index of a given item in the virtual list + int indexof(_DeviceClass &device) + { + int index = 0; + for (_DeviceClass *item = first(); item != NULL; item = next(), index++) + if (item == &device) + return index; + return -1; + } + + // return the indexed item in the list + _DeviceClass *byindex(int index) + { + for (_DeviceClass *item = first(); item != NULL; item = next(), index--) + if (index == 0) + return item; + return NULL; + } + +private: + // internal state + device_iterator m_iterator; +}; + + +// ======================> device_interface_iterator + +// helper class to find devices with a given interface in the device hierarchy +// also works for findnig devices derived from a given subclass +template<class _InterfaceClass> +class device_interface_iterator { - // temp. for now: don't include the root tag in the full tag name - return (this != NULL && m_owner != NULL) ? dest.cpy(m_tag).cat(":").cat(_tag) : dest.cpy(_tag); -} +public: + // construction + device_interface_iterator(device_t &root, int maxdepth = 255) + : m_iterator(root, maxdepth), + m_current(NULL) { } + + // getters + _InterfaceClass *current() const { return m_current; } + + // setters + void set_current(_InterfaceClass ¤t) { m_current = ¤t; m_iterator.set_current(current.device()); } -// create a tag for an object that a sibling to this device -inline astring &device_t::siblingtag(astring &dest, const char *_tag) const + // reset and return first item + _InterfaceClass *first() + { + for (device_t *device = m_iterator.first(); device != NULL; device = m_iterator.next()) + if (device->interface(m_current)) + return m_current; + return NULL; + } + + // advance depth-first + _InterfaceClass *next() + { + for (device_t *device = m_iterator.next(); device != NULL; device = m_iterator.next()) + if (device->interface(m_current)) + return m_current; + return NULL; + } + + // return the number of items available + int count() + { + int result = 0; + for (_InterfaceClass *item = first(); item != NULL; item = next()) + result++; + return result; + } + + // return the index of a given item in the virtual list + int indexof(_InterfaceClass &intrf) + { + int index = 0; + for (_InterfaceClass *item = first(); item != NULL; item = next(), index++) + if (item == &intrf) + return index; + return -1; + } + + // return the indexed item in the list + _InterfaceClass *byindex(int index) + { + for (_InterfaceClass *item = first(); item != NULL; item = next(), index--) + if (index == 0) + return item; + return NULL; + } + +private: + // internal state + device_iterator m_iterator; + _InterfaceClass * m_current; +}; + + +// ======================> device_delegate + +// 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 delegate<_Signature> { - return (this != NULL && m_owner != NULL) ? m_owner->subtag(dest, _tag) : dest.cpy(_tag); -} + typedef delegate<_Signature> basetype; + +public: + // provide same set of constructors as the base class, with additional device name + // parameter + device_delegate() : basetype(), m_device_name(NULL) { } + device_delegate(const basetype &src) : basetype(src), m_device_name(src.m_device_name) { } + device_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), m_device_name(src.m_device_name) { } + template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { } + template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), m_device_name(devname) { } + device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), m_device_name(NULL) { } + device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), m_device_name(NULL) { } + device_delegate &operator=(const basetype &src) { *static_cast<basetype *>(this) = src; m_device_name = src.m_device_name; return *this; } + + // perform the binding + void bind_relative_to(device_t &search_root); + +private: + // internal state + const char *m_device_name; +}; + + +//************************************************************************** +// INLINE FUNCTIONS +//************************************************************************** //------------------------------------------------- -// first - return the first device in the list -// with the given interface +// subdevice - given a tag, find the device by +// name relative to this device //------------------------------------------------- -template<class _InterfaceClass> -bool device_list::first(_InterfaceClass *&intf) const +inline device_t *device_t::subdevice(const char *tag) const { - for (device_t *cur = super::first(); cur != NULL; cur = cur->next()) - if (cur->interface(intf)) - return true; - return false; + // safety first + if (this == NULL) + return NULL; + + // empty string or NULL means this device + if (tag == NULL || *tag == 0) + return const_cast<device_t *>(this); + + // do a quick lookup and return that if possible + device_t *quick = m_device_map.find(tag); + return (quick != NULL) ? quick : subdevice_slow(tag); } @@ -588,8 +763,9 @@ void device_delegate<_Signature>::bind_relative_to(device_t &search_root) { if (!basetype::isnull()) { - device_t *device = (m_device_name == NULL) ? &search_root : search_root.subdevice(m_device_name); - if (device == NULL) throw emu_fatalerror("Unable to locate device '%s' relative to '%s'\n", m_device_name, search_root.tag()); + device_t *device = search_root.subdevice(m_device_name); + if (device == NULL) + throw emu_fatalerror("Unable to locate device '%s' relative to '%s'\n", m_device_name, search_root.tag()); basetype::late_bind(*device); } } diff --git a/src/emu/devlegcy.c b/src/emu/devlegcy.c index 1b15e10a2cf..185996188a8 100644 --- a/src/emu/devlegcy.c +++ b/src/emu/devlegcy.c @@ -200,12 +200,11 @@ void legacy_device_base::static_set_inline_float(device_t &device, UINT32 offset // checks on a device configuration //------------------------------------------------- -bool legacy_device_base::device_validity_check(emu_options &options, const game_driver &driver) const +void legacy_device_base::device_validity_check(validity_checker &valid) const { device_validity_check_func validity_func = reinterpret_cast<device_validity_check_func>(get_legacy_fct(DEVINFO_FCT_VALIDITY_CHECK)); if (validity_func != NULL) - return (*validity_func)(&driver, this, options); - return false; + (*validity_func)(&mconfig().gamedrv(), this, mconfig().options()); } @@ -239,7 +238,7 @@ void legacy_device_base::device_reset() void legacy_device_base::device_stop() { - if (m_started) + if (started()) { device_stop_func stop_func = reinterpret_cast<device_stop_func>(get_legacy_fct(DEVINFO_FCT_STOP)); if (stop_func != NULL) diff --git a/src/emu/devlegcy.h b/src/emu/devlegcy.h index f598a80d2a3..b68133c5a2d 100644 --- a/src/emu/devlegcy.h +++ b/src/emu/devlegcy.h @@ -429,7 +429,7 @@ protected: virtual const rom_entry *device_rom_region() const { return reinterpret_cast<const rom_entry *>(get_legacy_ptr(DEVINFO_PTR_ROM_REGION)); } virtual machine_config_constructor device_mconfig_additions() const { return reinterpret_cast<machine_config_constructor>(get_legacy_ptr(DEVINFO_PTR_MACHINE_CONFIG)); } virtual ioport_constructor device_input_ports() const { return reinterpret_cast<ioport_constructor>(get_legacy_ptr(DEVINFO_PTR_INPUT_PORTS)); } - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); virtual void device_stop(); diff --git a/src/emu/didisasm.h b/src/emu/didisasm.h index f6debcb4cdf..ade6827cd72 100644 --- a/src/emu/didisasm.h +++ b/src/emu/didisasm.h @@ -98,5 +98,8 @@ protected: virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) = 0; }; +// iterator +typedef device_interface_iterator<device_disasm_interface> disasm_interface_iterator; + #endif /* __DIDISASM_H__ */ diff --git a/src/emu/diexec.c b/src/emu/diexec.c index 417ed67aea4..99c43cbc389 100644 --- a/src/emu/diexec.c +++ b/src/emu/diexec.c @@ -484,37 +484,22 @@ void device_execute_interface::execute_set_input(int linenum, int state) // constructed //------------------------------------------------- -bool device_execute_interface::interface_validity_check(emu_options &options, const game_driver &driver) const +void device_execute_interface::interface_validity_check(validity_checker &valid) const { - bool error = false; - - /* validate the interrupts */ + // validate the interrupts if (m_vblank_interrupt != NULL) { - if (device().mconfig().devicelist().count(SCREEN) == 0) - { - mame_printf_error("%s: %s device '%s' has a VBLANK interrupt, but the driver is screenless!\n", driver.source_file, driver.name, device().tag()); - error = true; - } - else if (m_vblank_interrupt_screen != NULL && device().mconfig().devicelist().find(m_vblank_interrupt_screen) == NULL) - { - mame_printf_error("%s: %s device '%s' VBLANK interrupt with a non-existant screen tag (%s)!\n", driver.source_file, driver.name, device().tag(), m_vblank_interrupt_screen); - error = true; - } + screen_device_iterator iter(device().mconfig().root_device()); + if (iter.first() == NULL) + mame_printf_error("VBLANK interrupt specified, but the driver is screenless\n"); + else if (m_vblank_interrupt_screen != NULL && device().siblingdevice(m_vblank_interrupt_screen) == NULL) + mame_printf_error("VBLANK interrupt references a non-existant screen tag '%s'\n", m_vblank_interrupt_screen); } if (m_timed_interrupt != NULL && m_timed_interrupt_period == attotime::zero) - { - mame_printf_error("%s: %s device '%s' has a timer interrupt handler with 0 period!\n", driver.source_file, driver.name, device().tag()); - error = true; - } + mame_printf_error("Timed interrupt handler specified with 0 period\n"); else if (m_timed_interrupt == NULL && m_timed_interrupt_period != attotime::zero) - { - mame_printf_error("%s: %s device '%s' has a no timer interrupt handler but has a non-0 period given!\n", driver.source_file, driver.name, device().tag()); - error = true; - } - - return error; + mame_printf_error("No timer interrupt handler specified, but has a non-0 period given\n"); } @@ -526,7 +511,8 @@ bool device_execute_interface::interface_validity_check(emu_options &options, co void device_execute_interface::interface_pre_start() { // fill in the initial states - int index = device().machine().devicelist().indexof(m_device); + execute_interface_iterator iter(device().machine().root_device()); + int index = iter.indexof(*this); m_suspend = SUSPEND_REASON_RESET; m_profiler = profile_type(index + PROFILER_DEVICE_FIRST); m_inttrigger = index + TRIGGER_INT; @@ -540,13 +526,13 @@ void device_execute_interface::interface_pre_start() m_timedint_timer = device().machine().scheduler().timer_alloc(FUNC(static_trigger_periodic_interrupt), (void *)this); // register for save states - m_device.save_item(NAME(m_suspend)); - m_device.save_item(NAME(m_nextsuspend)); - m_device.save_item(NAME(m_eatcycles)); - m_device.save_item(NAME(m_nexteatcycles)); - m_device.save_item(NAME(m_trigger)); - m_device.save_item(NAME(m_totalcycles)); - m_device.save_item(NAME(m_localtime)); + device().save_item(NAME(m_suspend)); + device().save_item(NAME(m_nextsuspend)); + device().save_item(NAME(m_eatcycles)); + device().save_item(NAME(m_nexteatcycles)); + device().save_item(NAME(m_trigger)); + device().save_item(NAME(m_totalcycles)); + device().save_item(NAME(m_localtime)); } @@ -627,7 +613,7 @@ void device_execute_interface::interface_post_reset() void device_execute_interface::interface_clock_changed() { // recompute cps and spc - m_cycles_per_second = clocks_to_cycles(m_device.clock()); + m_cycles_per_second = clocks_to_cycles(device().clock()); m_attoseconds_per_cycle = HZ_TO_ATTOSECONDS(m_cycles_per_second); // update the device's divisor @@ -660,14 +646,14 @@ int device_execute_interface::standard_irq_callback(int irqline) { // get the default vector and acknowledge the interrupt if needed int vector = m_input[irqline].default_irq_callback(); - LOG(("static_standard_irq_callback('%s', %d) $%04x\n", m_device.tag(), irqline, vector)); + LOG(("static_standard_irq_callback('%s', %d) $%04x\n", device().tag(), irqline, vector)); // if there's a driver callback, run it to get the vector if (m_driver_irq != NULL) - vector = (*m_driver_irq)(&m_device, irqline); + vector = (*m_driver_irq)(&device(), irqline); // notify the debugger - debugger_interrupt_hook(&m_device, irqline); + debugger_interrupt_hook(&device(), irqline); return vector; } @@ -682,7 +668,7 @@ attoseconds_t device_execute_interface::minimum_quantum() const // if we don't have that information, compute it attoseconds_t basetick = m_attoseconds_per_cycle; if (basetick == 0) - basetick = HZ_TO_ATTOSECONDS(clocks_to_cycles(m_device.clock())); + basetick = HZ_TO_ATTOSECONDS(clocks_to_cycles(device().clock())); // apply the minimum cycle count return basetick * min_cycles(); @@ -714,9 +700,10 @@ void device_execute_interface::on_vblank(screen_device &screen, bool vblank_stat // generate the interrupt callback if (!suspended(SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE)) - (*m_vblank_interrupt)(&m_device); + (*m_vblank_interrupt)(&device()); } + //------------------------------------------------- // static_trigger_periodic_interrupt - timer // callback for timed interrupts @@ -731,7 +718,7 @@ void device_execute_interface::trigger_periodic_interrupt() { // bail if there is no routine if (m_timed_interrupt != NULL && !suspended(SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE)) - (*m_timed_interrupt)(&m_device); + (*m_timed_interrupt)(&device()); } @@ -765,7 +752,7 @@ device_execute_interface::device_input::device_input() void device_execute_interface::device_input::start(device_execute_interface *execute, int linenum) { m_execute = execute; - m_device = &m_execute->m_device; + m_device = &m_execute->device(); m_linenum = linenum; reset(); diff --git a/src/emu/diexec.h b/src/emu/diexec.h index 8a7b97c4909..59804199127 100644 --- a/src/emu/diexec.h +++ b/src/emu/diexec.h @@ -228,7 +228,7 @@ protected: virtual void execute_set_input(int linenum, int state); // interface-level overrides - virtual bool interface_validity_check(emu_options &options, const game_driver &driver) const; + virtual void interface_validity_check(validity_checker &valid) const; virtual void interface_pre_start(); virtual void interface_post_start(); virtual void interface_pre_reset(); @@ -322,6 +322,9 @@ private: attoseconds_t minimum_quantum() const; }; +// iterator +typedef device_interface_iterator<device_execute_interface> execute_interface_iterator; + //************************************************************************** diff --git a/src/emu/diimage.c b/src/emu/diimage.c index f23c4823599..9ceefc34c38 100644 --- a/src/emu/diimage.c +++ b/src/emu/diimage.c @@ -1067,17 +1067,9 @@ void device_image_interface::unload() void device_image_interface::update_names() { - const device_image_interface *image = NULL; - int count = 0; - int index = -1; - - for (bool gotone = device().mconfig().devicelist().first(image); gotone; gotone = image->next(image)) - { - if (this == image) - index = count; - if (image->image_type() == image_type()) - count++; - } + image_interface_iterator iter(device().mconfig().root_device()); + int count = iter.count(); + int index = iter.indexof(*this); if (count > 1) { m_instance_name.printf("%s%d", device_typename(image_type()), index + 1); m_brief_instance_name.printf("%s%d", device_brieftypename(image_type()), index + 1); @@ -1103,7 +1095,7 @@ ui_menu_control_device_image::ui_menu_control_device_image(running_machine &mach { image = _image; - slc = 0; + sld = 0; swi = image->software_entry(); swp = image->part_entry(); @@ -1220,8 +1212,8 @@ void ui_menu_control_device_image::handle() } case START_SOFTLIST: - slc = 0; - ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software(machine(), container, image->image_interface(), &slc))); + sld = 0; + ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software(machine(), container, image->image_interface(), &sld))); state = SELECT_SOFTLIST; break; @@ -1233,17 +1225,17 @@ void ui_menu_control_device_image::handle() } case SELECT_SOFTLIST: - if(!slc) { + if(!sld) { ui_menu::stack_pop(machine()); break; } software_info_name = ""; - ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software_list(machine(), container, slc, image->image_interface(), software_info_name))); + ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software_list(machine(), container, sld, image->image_interface(), software_info_name))); state = SELECT_PARTLIST; break; case SELECT_PARTLIST: - swl = software_list_open(machine().options(), slc->list_name, false, NULL); + swl = software_list_open(machine().options(), sld->list_name(), false, NULL); swi = software_list_find(swl, software_info_name, NULL); if(swinfo_has_multiple_parts(swi, image->image_interface())) { submenu_result = -1; diff --git a/src/emu/diimage.h b/src/emu/diimage.h index 583b058f607..84fafc69952 100644 --- a/src/emu/diimage.h +++ b/src/emu/diimage.h @@ -324,6 +324,9 @@ protected: bool m_is_loading; }; +// iterator +typedef device_interface_iterator<device_image_interface> image_interface_iterator; + class ui_menu_control_device_image : public ui_menu { public: ui_menu_control_device_image(running_machine &machine, render_container *container, device_image_interface *image); @@ -344,10 +347,10 @@ protected: int submenu_result; bool create_confirmed; bool softlist_done; - const class software_list *swl; - const class software_info *swi; - const class software_part *swp; - const class software_list_config *slc; + const struct software_list *swl; + const software_info *swi; + const software_part *swp; + const class software_list_device *sld; astring software_info_name; void test_create(bool &can_create, bool &need_confirm); diff --git a/src/emu/dimemory.c b/src/emu/dimemory.c index bf9a5b2cfb7..0a806d82341 100644 --- a/src/emu/dimemory.c +++ b/src/emu/dimemory.c @@ -227,10 +227,9 @@ bool device_memory_interface::memory_readop(offs_t offset, int size, UINT64 &val // checks on the memory configuration //------------------------------------------------- -bool device_memory_interface::interface_validity_check(emu_options &options, const game_driver &driver) const +void device_memory_interface::interface_validity_check(validity_checker &valid) const { bool detected_overlap = DETECT_OVERLAPPING_MEMORY ? false : true; - bool error = false; // loop over all address spaces for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++) @@ -253,15 +252,9 @@ bool device_memory_interface::interface_validity_check(emu_options &options, con // validate the global map parameters if (map->m_spacenum != spacenum) - { - mame_printf_error("%s: %s device '%s' space %d has address space %d handlers!\n", driver.source_file, driver.name, device().tag(), spacenum, map->m_spacenum); - error = true; - } + mame_printf_error("Space %d has address space %d handlers!\n", spacenum, map->m_spacenum); if (map->m_databits != datawidth) - { - mame_printf_error("%s: %s device '%s' uses wrong memory handlers for %s space! (width = %d, memory = %08x)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, datawidth, map->m_databits); - error = true; - } + mame_printf_error("Wrong memory handlers provided for %s space! (width = %d, memory = %08x)\n", spaceconfig->m_name, datawidth, map->m_databits); // loop over entries and look for errors for (address_map_entry *entry = map->m_entrylist.first(); entry != NULL; entry = entry->next()) @@ -278,7 +271,7 @@ bool device_memory_interface::interface_validity_check(emu_options &options, con ((entry->m_read.m_type != AMH_NONE && scan->m_read.m_type != AMH_NONE) || (entry->m_write.m_type != AMH_NONE && scan->m_write.m_type != AMH_NONE))) { - mame_printf_warning("%s: %s '%s' %s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type); + mame_printf_warning("%s space has overlapping memory (%X-%X,%d,%d) vs (%X-%X,%d,%d)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_read.m_type, entry->m_write.m_type, scan->m_addrstart, scan->m_addrend, scan->m_read.m_type, scan->m_write.m_type); detected_overlap = true; break; } @@ -286,17 +279,11 @@ bool device_memory_interface::interface_validity_check(emu_options &options, con // look for inverted start/end pairs if (byteend < bytestart) - { - mame_printf_error("%s: %s wrong %s memory read handler start = %08x > end = %08x\n", driver.source_file, driver.name, spaceconfig->m_name, entry->m_addrstart, entry->m_addrend); - error = true; - } + mame_printf_error("Wrong %s memory read handler start = %08x > end = %08x\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend); // look for misaligned entries if ((bytestart & (alignunit - 1)) != 0 || (byteend & (alignunit - 1)) != (alignunit - 1)) - { - mame_printf_error("%s: %s wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", driver.source_file, driver.name, spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit); - error = true; - } + mame_printf_error("Wrong %s memory read handler start = %08x, end = %08x ALIGN = %d\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, alignunit); // if this is a program space, auto-assign implicit ROM entries if (entry->m_read.m_type == AMH_ROM && entry->m_region == NULL) @@ -308,81 +295,54 @@ bool device_memory_interface::interface_validity_check(emu_options &options, con // if this entry references a memory region, validate it if (entry->m_region != NULL && entry->m_share == 0) { - // look for the region + // make sure we can resolve the full path to the region bool found = false; + astring entry_region; + device().siblingtag(entry_region, entry->m_region); + + // look for the region for (const rom_source *source = rom_first_source(device().mconfig()); source != NULL && !found; source = rom_next_source(*source)) - for (const rom_entry *romp = rom_first_region(*source); !ROMENTRY_ISEND(romp) && !found; romp++) + for (const rom_entry *romp = rom_first_region(*source); romp != NULL && !found; romp = rom_next_region(romp)) { - const char *regiontag_c = ROMREGION_GETTAG(romp); - if (regiontag_c != NULL) + astring fulltag; + rom_region_name(fulltag, &device().mconfig().gamedrv(), source, romp); + if (fulltag == entry_region) { - astring fulltag; - astring regiontag; - - // a leading : on a region name indicates an absolute region, so fix up accordingly - if (entry->m_region[0] == ':') - { - regiontag = &entry->m_region[1]; - } - else - { - if (strchr(entry->m_region,':')) { - regiontag = entry->m_region; - } else { - device().siblingtag(regiontag, entry->m_region); - } - } - rom_region_name(fulltag, &driver, source, romp); - if (fulltag.cmp(regiontag) == 0) - { - // verify the address range is within the region's bounds - offs_t length = ROMREGION_GETLENGTH(romp); - if (entry->m_rgnoffs + (byteend - bytestart + 1) > length) - { - mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length); - error = true; - } - found = true; - } + // verify the address range is within the region's bounds + offs_t length = ROMREGION_GETLENGTH(romp); + if (entry->m_rgnoffs + (byteend - bytestart + 1) > length) + mame_printf_error("%s space memory map entry %X-%X extends beyond region '%s' size (%X)\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region, length); + found = true; } } // error if not found if (!found) - { - mame_printf_error("%s: %s device '%s' %s space memory map entry %X-%X references non-existant region '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region); - error = true; - } + mame_printf_error("%s space memory map entry %X-%X references non-existant region '%s'\n", spaceconfig->m_name, entry->m_addrstart, entry->m_addrend, entry->m_region); } // make sure all devices exist - if ((entry->m_read.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_read.m_tag != NULL && device().mconfig().devicelist().find(entry->m_read.m_tag) == NULL) || - (entry->m_write.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_write.m_tag != NULL && device().mconfig().devicelist().find(entry->m_write.m_tag) == NULL)) - { - mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant device '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_write.m_tag); - error = true; - } + if (entry->m_read.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_read.m_tag && device().siblingdevice(entry->m_read.m_tag) == NULL) + mame_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_read.m_tag.cstr()); + if (entry->m_write.m_type == AMH_LEGACY_DEVICE_HANDLER && entry->m_write.m_tag && device().siblingdevice(entry->m_write.m_tag) == NULL) + mame_printf_error("%s space memory map entry references nonexistant device '%s'\n", spaceconfig->m_name, entry->m_write.m_tag.cstr()); // make sure ports exist // if ((entry->m_read.m_type == AMH_PORT && entry->m_read.m_tag != NULL && portlist.find(entry->m_read.m_tag) == NULL) || // (entry->m_write.m_type == AMH_PORT && entry->m_write.m_tag != NULL && portlist.find(entry->m_write.m_tag) == NULL)) -// { -// mame_printf_error("%s: %s device '%s' %s space memory map entry references nonexistant port tag '%s'\n", driver.source_file, driver.name, device().tag(), spaceconfig->m_name, entry->m_read.tag); -// error = true; -// } +// mame_printf_error("%s space memory map entry references nonexistant port tag '%s'\n", spaceconfig->m_name, entry->m_read.m_tag.cstr()); // validate bank and share tags - if (entry->m_read.m_type == AMH_BANK && !validate_tag(driver, "bank", entry->m_read.m_tag)) - error = true ; - if (entry->m_write.m_type == AMH_BANK && !validate_tag(driver, "bank", entry->m_write.m_tag)) - error = true; - if (entry->m_share != NULL && !validate_tag(driver, "share", entry->m_share)) - error = true; + if (entry->m_read.m_type == AMH_BANK) + valid.validate_tag(entry->m_read.m_tag); + if (entry->m_write.m_type == AMH_BANK) + valid.validate_tag(entry->m_write.m_tag); + if (entry->m_share != NULL) + valid.validate_tag(entry->m_share); } // release the address map global_free(map); } } - return error; } diff --git a/src/emu/dimemory.h b/src/emu/dimemory.h index b0e2da346bb..c6efce57ebe 100644 --- a/src/emu/dimemory.h +++ b/src/emu/dimemory.h @@ -134,13 +134,16 @@ protected: virtual bool memory_readop(offs_t offset, int size, UINT64 &value); // interface-level overrides - virtual bool interface_validity_check(emu_options &options, const game_driver &driver) const; + virtual void interface_validity_check(validity_checker &valid) const; // configuration address_map_constructor m_address_map[ADDRESS_SPACES]; // address maps for each address space address_space * m_addrspace[ADDRESS_SPACES]; // reported address spaces }; +// iterator +typedef device_interface_iterator<device_memory_interface> memory_interface_iterator; + //************************************************************************** diff --git a/src/emu/dinetwork.h b/src/emu/dinetwork.h index 592853af78a..bc1546e17c4 100644 --- a/src/emu/dinetwork.h +++ b/src/emu/dinetwork.h @@ -28,4 +28,9 @@ protected: class netdev *m_dev; int m_intf; }; + + +// iterator +typedef device_interface_iterator<device_network_interface> network_interface_iterator; + #endif diff --git a/src/emu/dinvram.h b/src/emu/dinvram.h index 30b490c60a1..ad9947ea1cc 100644 --- a/src/emu/dinvram.h +++ b/src/emu/dinvram.h @@ -74,5 +74,8 @@ protected: virtual void nvram_write(emu_file &file) = 0; }; +// iterator +typedef device_interface_iterator<device_nvram_interface> nvram_interface_iterator; + #endif /* __DINVRAM_H__ */ diff --git a/src/emu/dislot.h b/src/emu/dislot.h index 630a76b677e..bdc7413dc92 100644 --- a/src/emu/dislot.h +++ b/src/emu/dislot.h @@ -48,8 +48,8 @@ public: static void static_set_slot_info(device_t &device, const slot_interface *slots_info, const char *default_card,const input_device_default *default_input); const slot_interface* get_slot_interfaces() const { return m_slot_interfaces; }; - const char * get_default_card(const device_list &devlist, emu_options &options) const { return m_default_card; }; - virtual const char * get_default_card_software(const device_list &devlist, emu_options &options) const { return NULL; }; + const char * get_default_card(const machine_config &config, emu_options &options) const { return m_default_card; }; + virtual const char * get_default_card_software(const machine_config &config, emu_options &options) const { return NULL; }; const input_device_default *input_ports_defaults() const { return m_input_defaults; } device_t* get_card_device(); protected: @@ -58,6 +58,9 @@ protected: const slot_interface *m_slot_interfaces; }; +// iterator +typedef device_interface_iterator<device_slot_interface> slot_interface_iterator; + // ======================> device_slot_card_interface class device_slot_card_interface : public device_interface diff --git a/src/emu/disound.c b/src/emu/disound.c index cb004c28fa2..2889d58f852 100644 --- a/src/emu/disound.c +++ b/src/emu/disound.c @@ -232,30 +232,21 @@ void device_sound_interface::set_output_gain(int outputnum, float gain) // constructed //------------------------------------------------- -bool device_sound_interface::interface_validity_check(emu_options &options, const game_driver &driver) const +void device_sound_interface::interface_validity_check(validity_checker &valid) const { - bool error = false; - // loop over all the routes for (const sound_route *route = first_route(); route != NULL; route = route->next()) { // find a device with the requested tag - const device_t *target = device().mconfig().devicelist().find(route->m_target.cstr()); + const device_t *target = device().siblingdevice(route->m_target.cstr()); if (target == NULL) - { - mame_printf_error("%s: %s attempting to route sound to non-existant device '%s'\n", driver.source_file, driver.name, route->m_target.cstr()); - error = true; - } + mame_printf_error("Attempting to route sound to non-existant device '%s'\n", route->m_target.cstr()); // if it's not a speaker or a sound device, error const device_sound_interface *sound; if (target != NULL && target->type() != SPEAKER && !target->interface(sound)) - { - mame_printf_error("%s: %s attempting to route sound to a non-sound device '%s' (%s)\n", driver.source_file, driver.name, route->m_target.cstr(), target->name()); - error = true; - } + mame_printf_error("Attempting to route sound to a non-sound device '%s' (%s)\n", route->m_target.cstr(), target->name()); } - return error; } @@ -267,8 +258,8 @@ bool device_sound_interface::interface_validity_check(emu_options &options, cons void device_sound_interface::interface_pre_start() { // scan all the sound devices - device_sound_interface *sound = NULL; - for (bool gotone = m_device.machine().devicelist().first(sound); gotone; gotone = sound->next(sound)) + sound_interface_iterator iter(m_device.machine().root_device()); + for (device_sound_interface *sound = iter.first(); sound != NULL; sound = iter.next()) { // scan each route on the device for (const sound_route *route = sound->first_route(); route != NULL; route = route->next()) @@ -282,7 +273,7 @@ void device_sound_interface::interface_pre_start() // now iterate through devices again and assign any auto-allocated inputs m_auto_allocated_inputs = 0; - for (bool gotone = m_device.machine().devicelist().first(sound); gotone; gotone = sound->next(sound)) + for (device_sound_interface *sound = iter.first(); sound != NULL; sound = iter.next()) { // scan each route on the device for (const sound_route *route = sound->first_route(); route != NULL; route = route->next()) @@ -307,8 +298,8 @@ void device_sound_interface::interface_pre_start() void device_sound_interface::interface_post_start() { // iterate over all the sound devices - device_sound_interface *sound = NULL; - for (bool gotone = m_device.machine().devicelist().first(sound); gotone; gotone = sound->next(sound)) + sound_interface_iterator iter(m_device.machine().root_device()); + for (device_sound_interface *sound = iter.first(); sound != NULL; sound = iter.next()) { // scan each route on the device for (const sound_route *route = sound->first_route(); route != NULL; route = route->next()) diff --git a/src/emu/disound.h b/src/emu/disound.h index c4c9a2f13c0..c94187337c4 100644 --- a/src/emu/disound.h +++ b/src/emu/disound.h @@ -138,7 +138,7 @@ public: protected: // optional operation overrides - virtual bool interface_validity_check(emu_options &options, const game_driver &driver) const; + virtual void interface_validity_check(validity_checker &valid) const; virtual void interface_pre_start(); virtual void interface_post_start(); virtual void interface_pre_reset(); @@ -149,5 +149,7 @@ protected: int m_auto_allocated_inputs; // number of auto-allocated inputs targeting us }; +// iterator +typedef device_interface_iterator<device_sound_interface> sound_interface_iterator; #endif /* __DISOUND_H__ */ diff --git a/src/emu/distate.c b/src/emu/distate.c index 2a18ea59c9d..6a0621d3eac 100644 --- a/src/emu/distate.c +++ b/src/emu/distate.c @@ -517,7 +517,7 @@ device_state_entry &device_state_interface::state_add(int index, const char *sym assert(symbol != NULL); // allocate new entry - device_state_entry *entry = auto_alloc(device().machine(), device_state_entry(index, symbol, data, size)); + device_state_entry *entry = global_alloc(device_state_entry(index, symbol, data, size)); // append to the end of the list m_state_list.append(*entry); diff --git a/src/emu/distate.h b/src/emu/distate.h index b38f692fc7e..66b756e566b 100644 --- a/src/emu/distate.h +++ b/src/emu/distate.h @@ -195,6 +195,9 @@ protected: // fast access to common entries }; +// iterator +typedef device_interface_iterator<device_state_interface> state_interface_iterator; + //************************************************************************** diff --git a/src/emu/emuopts.c b/src/emu/emuopts.c index 7d7196fbfc0..cc06c91c98f 100644 --- a/src/emu/emuopts.c +++ b/src/emu/emuopts.c @@ -226,11 +226,11 @@ bool emu_options::add_slot_options(bool isfirst) // iterate through all slot devices options_entry entry[2] = { { 0 }, { 0 } }; bool first = true; - const device_slot_interface *slot = NULL; // create the configuration machine_config config(*cursystem, *this); bool added = false; - for (bool gotone = config.devicelist().first(slot); gotone; gotone = slot->next(slot)) + slot_interface_iterator iter(config.root_device()); + for (const device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) { // first device? add the header as to be pretty if (first && isfirst) @@ -253,7 +253,7 @@ bool emu_options::add_slot_options(bool isfirst) entry[0].name = slot->device().tag(); entry[0].description = NULL; entry[0].flags = OPTION_STRING | OPTION_FLAG_DEVICE; - entry[0].defvalue = (slot->get_slot_interfaces() != NULL) ? slot->get_default_card(config.devicelist(),*this) : NULL; + entry[0].defvalue = (slot->get_slot_interfaces() != NULL) ? slot->get_default_card(config,*this) : NULL; add_entries(entry, true); added = true; @@ -275,10 +275,10 @@ void emu_options::update_slot_options() return; // iterate through all slot devices - const device_slot_interface *slot = NULL; // create the configuration machine_config config(*cursystem, *this); - for (bool gotone = config.devicelist().first(slot); gotone; gotone = slot->next(slot)) + slot_interface_iterator iter(config.root_device()); + for (const device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) { // retrieve info about the device instance astring option_name; @@ -286,7 +286,7 @@ void emu_options::update_slot_options() if (exists(slot->device().tag())) { if (slot->get_slot_interfaces() != NULL) { - const char *def = slot->get_default_card_software(config.devicelist(),*this); + const char *def = slot->get_default_card_software(config,*this); if (def) set_default_value(slot->device().tag(),def); } } @@ -308,9 +308,9 @@ void emu_options::add_device_options(bool isfirst) options_entry entry[2] = { { 0 }, { 0 } }; bool first = true; // iterate through all image devices - const device_image_interface *image = NULL; machine_config config(*cursystem, *this); - for (bool gotone = config.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(config.root_device()); + for (const device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { // first device? add the header as to be pretty if (first && isfirst) @@ -438,7 +438,8 @@ void emu_options::parse_standard_inis(astring &error_string) // parse "vector.ini" for vector games { machine_config config(*cursystem, *this); - for (const screen_device *device = config.first_screen(); device != NULL; device = device->next_screen()) + screen_device_iterator iter(config.root_device()); + for (const screen_device *device = iter.first(); device != NULL; device = iter.next()) if (device->screen_type() == SCREEN_TYPE_VECTOR) { parse_one_ini("vector", OPTION_PRIORITY_VECTOR_INI, &error_string); diff --git a/src/emu/image.c b/src/emu/image.c index fc8776fa218..260bef069c9 100644 --- a/src/emu/image.c +++ b/src/emu/image.c @@ -68,7 +68,6 @@ static void image_dirs_load(running_machine &machine, int config_type, xml_data_ xml_data_node *node; const char *dev_instance; const char *working_directory; - device_image_interface *image = NULL; if ((config_type == CONFIG_TYPE_GAME) && (parentnode != NULL)) { @@ -78,7 +77,8 @@ static void image_dirs_load(running_machine &machine, int config_type, xml_data_ if ((dev_instance != NULL) && (dev_instance[0] != '\0')) { - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { if (!strcmp(dev_instance, image->instance_name())) { working_directory = xml_get_attribute_string(node, "directory", NULL); @@ -102,12 +102,12 @@ static void image_dirs_save(running_machine &machine, int config_type, xml_data_ { xml_data_node *node; const char *dev_instance; - device_image_interface *image = NULL; /* only care about game-specific data */ if (config_type == CONFIG_TYPE_GAME) { - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { dev_instance = image->instance_name(); @@ -160,9 +160,9 @@ static void image_options_extract(running_machine &machine) no need to assert in case they are missing */ { int index = 0; - device_image_interface *image = NULL; - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { const char *filename = image->filename(); @@ -186,12 +186,11 @@ static void image_options_extract(running_machine &machine) void image_unload_all(running_machine &machine) { - device_image_interface *image = NULL; - // extract the options image_options_extract(machine); - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { // unload this image image->unload(); @@ -205,10 +204,10 @@ void image_unload_all(running_machine &machine) void image_device_init(running_machine &machine) { const char *image_name; - device_image_interface *image = NULL; /* make sure that any required devices have been allocated */ - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { /* is an image specified for this image */ image_name = machine.options().device_option(*image); @@ -239,7 +238,7 @@ void image_device_init(running_machine &machine) } } - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { /* is an image specified for this image */ image_name = image->filename(); @@ -264,10 +263,9 @@ void image_device_init(running_machine &machine) void image_postdevice_init(running_machine &machine) { - device_image_interface *image = NULL; - /* make sure that any required devices have been allocated */ - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { int result = image->finish_load(); /* did the image load fail? */ @@ -373,8 +371,6 @@ static char *strip_extension(const char *filename) astring &image_info_astring(running_machine &machine, astring &string) { - device_image_interface *image = NULL; - string.printf("%s\n\n", machine.system().description); #if 0 @@ -385,7 +381,8 @@ astring &image_info_astring(running_machine &machine, astring &string) } #endif - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { const char *name = image->filename(); if (name != NULL) @@ -480,15 +477,8 @@ void image_battery_save_by_name(emu_options &options, const char *filename, cons -------------------------------------------------*/ device_image_interface *image_from_absolute_index(running_machine &machine, int absolute_index) { - device_image_interface *image = NULL; - int cnt = 0; - /* make sure that any required devices have been allocated */ - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) - { - if (cnt==absolute_index) return image; - cnt++; - } - return NULL; + image_interface_iterator iter(machine.root_device()); + return iter.byindex(absolute_index); } /*------------------------------------------------- diff --git a/src/emu/imagedev/bitbngr.h b/src/emu/imagedev/bitbngr.h index 25a25915537..a6f887201ae 100644 --- a/src/emu/imagedev/bitbngr.h +++ b/src/emu/imagedev/bitbngr.h @@ -163,4 +163,7 @@ private: // device type definition extern const device_type BITBANGER; +// device iterator +typedef device_type_iterator<&device_creator<bitbanger_device>, bitbanger_device> bitbanger_device_iterator; + #endif /* __BITBNGR_H__ */ diff --git a/src/emu/imagedev/cassette.c b/src/emu/imagedev/cassette.c index 474256d5ec5..dd2408f729d 100644 --- a/src/emu/imagedev/cassette.c +++ b/src/emu/imagedev/cassette.c @@ -336,7 +336,7 @@ void cassette_image_device::call_display() int n; double position, length; cassette_state uistate; - device_t *dev; + cassette_image_device *dev; static const UINT8 shapes[8] = { 0x2d, 0x5c, 0x7c, 0x2f, 0x2d, 0x20, 0x20, 0x20 }; /* abort if we should not be showing the image */ @@ -354,13 +354,9 @@ void cassette_image_device::call_display() x = 0.2f; y = 0.5f; - dev = device().machine().devicelist().first(CASSETTE ); - - while ( dev && strcmp( dev->tag(), device().tag() ) ) - { + cassette_device_iterator iter(device().machine().root_device()); + for (dev = iter.first(); dev != NULL && strcmp( dev->tag(), device().tag() ); dev = iter.next()) y += 1; - dev = dev->typenext(); - } y *= ui_get_line_height(device().machine()) + 2.0f * UI_BOX_TB_BORDER; /* choose which frame of the animation we are at */ diff --git a/src/emu/imagedev/cassette.h b/src/emu/imagedev/cassette.h index c7476e169a0..cec381c2e0f 100644 --- a/src/emu/imagedev/cassette.h +++ b/src/emu/imagedev/cassette.h @@ -113,6 +113,9 @@ private: // device type definition extern const device_type CASSETTE; +// device iterator +typedef device_type_iterator<&device_creator<cassette_image_device>, cassette_image_device> cassette_device_iterator; + /*************************************************************************** DEVICE CONFIGURATION MACROS ***************************************************************************/ diff --git a/src/emu/info.c b/src/emu/info.c index e9f15949c33..2ce0ad90692 100644 --- a/src/emu/info.c +++ b/src/emu/info.c @@ -266,13 +266,13 @@ void info_xml_creator::output_devices() m_drivlist.reset(); m_drivlist.next(); machine_config &config = m_drivlist.config(); - device_t *owner = config.devicelist().first(); + device_t &owner = config.root_device(); // check if all are listed, note that empty one is included bool display_all = driver_list::total() == (m_drivlist.count()+1); for(int i=0;i<m_device_count;i++) { if (display_all || (m_device_used[i]!=0)) { device_type type = *s_devices_sorted[i]; - device_t *dev = (*type)(config, "dummy", owner, 0); + device_t *dev = (*type)(config, "dummy", &owner, 0); dev->config_complete(); // print the header and the game name @@ -311,7 +311,8 @@ void info_xml_creator::output_one() machine_config &config = m_drivlist.config(); ioport_list portlist; astring errors; - for (device_t *device = config.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(config.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) input_port_list_init(*device, portlist, errors); // print the header and the game name @@ -407,7 +408,8 @@ void info_xml_creator::output_device_roms() void info_xml_creator::output_sampleof() { // iterate over sample devices - for (const device_t *device = m_drivlist.config().devicelist().first(SAMPLES); device != NULL; device = device->typenext()) + samples_device_iterator iter(m_drivlist.config().root_device()); + for (samples_device *device = iter.first(); device != NULL; device = iter.next()) { const char *const *samplenames = ((const samples_interface *)device->static_config())->samplenames; if (samplenames != NULL) @@ -566,7 +568,8 @@ void info_xml_creator::output_rom(const rom_source *source) void info_xml_creator::output_sample() { // iterate over sample devices - for (const device_t *device = m_drivlist.config().devicelist().first(SAMPLES); device != NULL; device = device->typenext()) + samples_device_iterator iter(m_drivlist.config().root_device()); + for (const device_t *device = iter.first(); device != NULL; device = iter.next()) { const char *const *samplenames = ((const samples_interface *)device->static_config())->samplenames; if (samplenames != NULL) @@ -602,8 +605,8 @@ void info_xml_creator::output_sample() void info_xml_creator::output_chips() { // iterate over executable devices - device_execute_interface *exec = NULL; - for (bool gotone = m_drivlist.config().devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator execiter(m_drivlist.config().root_device()); + for (device_execute_interface *exec = execiter.first(); exec != NULL; exec = execiter.next()) { fprintf(m_output, "\t\t<chip"); fprintf(m_output, " type=\"cpu\""); @@ -614,8 +617,8 @@ void info_xml_creator::output_chips() } // iterate over sound devices - device_sound_interface *sound = NULL; - for (bool gotone = m_drivlist.config().devicelist().first(sound); gotone; gotone = sound->next(sound)) + sound_interface_iterator sounditer(m_drivlist.config().root_device()); + for (device_sound_interface *sound = sounditer.first(); sound != NULL; sound = sounditer.next()) { fprintf(m_output, "\t\t<chip"); fprintf(m_output, " type=\"audio\""); @@ -636,7 +639,8 @@ void info_xml_creator::output_chips() void info_xml_creator::output_display() { // iterate over screens - for (const screen_device *device = m_drivlist.config().first_screen(); device != NULL; device = device->next_screen()) + screen_device_iterator iter(m_drivlist.config().root_device()); + for (const screen_device *device = iter.first(); device != NULL; device = iter.next()) { fprintf(m_output, "\t\t<display"); @@ -714,11 +718,12 @@ void info_xml_creator::output_display() void info_xml_creator::output_sound() { - int speakers = m_drivlist.config().devicelist().count(SPEAKER); + speaker_device_iterator spkiter(m_drivlist.config().root_device()); + int speakers = spkiter.count(); // if we have no sound, zero m_output the speaker count - const device_sound_interface *sound = NULL; - if (!m_drivlist.config().devicelist().first(sound)) + sound_interface_iterator snditer(m_drivlist.config().root_device()); + if (snditer.first() == NULL) speakers = 0; fprintf(m_output, "\t\t<sound channels=\"%d\"/>\n", speakers); @@ -1144,8 +1149,8 @@ void info_xml_creator::output_driver() void info_xml_creator::output_images() { - const device_image_interface *dev = NULL; - for (bool gotone = m_drivlist.config().devicelist().first(dev); gotone; gotone = dev->next(dev)) + image_interface_iterator iter(m_drivlist.config().root_device()); + for (const device_image_interface *dev = iter.first(); dev != NULL; dev = iter.next()) { // print m_output device type fprintf(m_output, "\t\t<device type=\"%s\"", xml_normalize_string(dev->image_type_name())); @@ -1194,8 +1199,8 @@ void info_xml_creator::output_images() void info_xml_creator::output_slots() { - const device_slot_interface *slot = NULL; - for (bool gotone = m_drivlist.config().devicelist().first(slot); gotone; gotone = slot->next(slot)) + slot_interface_iterator iter(m_drivlist.config().root_device()); + for (const device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) { // print m_output device type fprintf(m_output, "\t\t<slot name=\"%s\">\n", xml_normalize_string(slot->device().tag())); @@ -1210,9 +1215,9 @@ void info_xml_creator::output_slots() { fprintf(m_output, "\t\t\t<slotoption"); fprintf(m_output, " name=\"%s\"", xml_normalize_string(intf[i].name)); - if (slot->get_default_card(m_drivlist.config().devicelist(), m_drivlist.options())) + if (slot->get_default_card(m_drivlist.config(), m_drivlist.options())) { - if (slot->get_default_card(m_drivlist.config().devicelist(), m_drivlist.options()) == intf[i].name) + if (slot->get_default_card(m_drivlist.config(), m_drivlist.options()) == intf[i].name) fprintf(m_output, " default=\"yes\""); } fprintf(m_output, "/>\n"); @@ -1230,13 +1235,13 @@ void info_xml_creator::output_slots() void info_xml_creator::output_software_list() { - for (const device_t *dev = m_drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) + software_list_device_iterator iter(m_drivlist.config().root_device()); + for (const software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config(); - fprintf(m_output, "\t\t<softwarelist name=\"%s\" ", swlist->list_name); - fprintf(m_output, "status=\"%s\" ", (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible"); - if (swlist->filter) { - fprintf(m_output, "filter=\"%s\" ", swlist->filter); + fprintf(m_output, "\t\t<softwarelist name=\"%s\" ", swlist->list_name()); + fprintf(m_output, "status=\"%s\" ", (swlist->list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible"); + if (swlist->filter()) { + fprintf(m_output, "filter=\"%s\" ", swlist->filter()); } fprintf(m_output, "/>\n"); } @@ -1251,10 +1256,9 @@ void info_xml_creator::output_software_list() void info_xml_creator::output_ramoptions() { - for (const device_t *device = m_drivlist.config().devicelist().first(RAM); device != NULL; device = device->typenext()) + ram_device_iterator iter(m_drivlist.config().root_device()); + for (const ram_device *ram = iter.first(); ram != NULL; ram = iter.next()) { - const ram_device *ram = downcast<const ram_device *>(device); - fprintf(m_output, "\t\t<ramoption default=\"1\">%u</ramoption>\n", ram->default_size()); if (ram->extra_options() != NULL) diff --git a/src/emu/ioport.c b/src/emu/ioport.c index 5215b7735f3..7f93baa417c 100644 --- a/src/emu/ioport.c +++ b/src/emu/ioport.c @@ -903,7 +903,8 @@ time_t input_port_init(running_machine &machine) init_port_types(machine); /* if we have a token list, proceed */ - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) { astring errors; input_port_list_init(*device, machine.m_portlist, errors); @@ -1500,10 +1501,10 @@ input_port_value input_port_read(running_machine &machine, const char *tag) a device input port specified by tag -------------------------------------------------*/ -input_port_value input_port_read(device_t *device, const char *tag) +input_port_value input_port_read(device_t &device, const char *tag) { - astring tempstring; - const input_port_config *port = device->machine().port(device->subtag(tempstring, tag)); + astring fullpath; + const input_port_config *port = device.machine().port(device.subtag(fullpath, tag)); if (port == NULL) fatalerror("Unable to locate input port '%s'", tag); return input_port_read_direct(port); @@ -1721,7 +1722,7 @@ void input_port_write_safe(running_machine &machine, const char *tag, input_port if the given condition attached is true -------------------------------------------------*/ -int input_condition_true(running_machine &machine, const input_condition *condition,device_t &owner) +int input_condition_true(running_machine &machine, const input_condition *condition, device_t &owner) { input_port_value condvalue; @@ -1939,20 +1940,6 @@ static astring &get_keyboard_key_name(astring &name, const input_field_config *f states based on the tokens -------------------------------------------------*/ -inline const char *get_device_tag(const device_t &device, const char *tag, astring &finaltag) -{ - if (strcmp(tag, DEVICE_SELF) == 0) - finaltag.cpy(device.tag()); - else if (strcmp(tag, DEVICE_SELF_OWNER) == 0) - { - assert(device.owner() != NULL); - finaltag.cpy(device.owner()->tag()); - } - else - device.subtag(finaltag, tag); - return finaltag; -} - static void init_port_state(running_machine &machine) { const char *joystick_map_default = machine.options().joystick_map(); @@ -2012,7 +1999,7 @@ static void init_port_state(running_machine &machine) astring devicetag; if (!field->read.isnull()) { - *readdevicetail = init_field_device_info(field, get_device_tag(port->owner(), field->read_device, devicetag)); + *readdevicetail = init_field_device_info(field, port->owner().subtag(devicetag, field->read_device)); field->read.late_bind(*(*readdevicetail)->device); readdevicetail = &(*readdevicetail)->next; } @@ -2020,7 +2007,7 @@ static void init_port_state(running_machine &machine) /* if this entry has device output, allocate memory for the tracking structure */ if (!field->write.isnull()) { - *writedevicetail = init_field_device_info(field, get_device_tag(port->owner(), field->write_device, devicetag)); + *writedevicetail = init_field_device_info(field, port->owner().subtag(devicetag, field->write_device)); field->write.late_bind(*(*writedevicetail)->device); writedevicetail = &(*writedevicetail)->next; } @@ -2028,7 +2015,7 @@ static void init_port_state(running_machine &machine) /* if this entry has device output, allocate memory for the tracking structure */ if (!field->crossmapper.isnull()) { - device_t *device = machine.device(get_device_tag(port->owner(), field->crossmapper_device, devicetag)); + device_t *device = machine.device(port->owner().subtag(devicetag, field->crossmapper_device)); field->crossmapper.late_bind(*device); } @@ -2842,16 +2829,13 @@ static int frame_get_digital_field_state(const input_field_config *field, int mo UINT32 port_default_value(const char *fulltag, UINT32 mask, UINT32 defval, device_t &owner) { - astring tempstring; - const input_device_default *def = NULL; - def = owner.input_ports_defaults(); - if (def!=NULL) { - while (def->tag!=NULL) { - if ((strcmp(fulltag,owner.subtag(tempstring,def->tag))==0) && (def->mask == mask)) { + const input_device_default *def = owner.input_ports_defaults(); + if (def != NULL) + { + astring fullpath; + for ( ; def->tag != NULL; def++) + if (owner.subtag(fullpath, def->tag) == fulltag && def->mask == mask) return def->defvalue; - } - def++; - } } return defval; } @@ -4830,6 +4814,7 @@ input_port_config *ioconfig_alloc_port(ioport_list &portlist, device_t &device, { astring fulltag; device.subtag(fulltag, tag); +mame_printf_verbose("ioport '%s' created\n", fulltag.cstr()); return &portlist.append(fulltag, *global_alloc(input_port_config(device, fulltag))); } diff --git a/src/emu/ioport.h b/src/emu/ioport.h index 25ca0aa17cf..1d70ac210f0 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -1333,7 +1333,7 @@ input_port_value input_port_read_direct(const input_port_config *port); input_port_value input_port_read(running_machine &machine, const char *tag); /* return the value of a device input port specified by tag */ -input_port_value input_port_read(device_t *device, const char *tag); +input_port_value input_port_read(device_t &device, const char *tag); /* return the value of an input port specified by tag, or a default value if the port does not exist */ input_port_value input_port_read_safe(running_machine &machine, const char *tag, input_port_value defvalue); diff --git a/src/emu/machine.c b/src/emu/machine.c index 172f15e31a5..4118d3b0370 100644 --- a/src/emu/machine.c +++ b/src/emu/machine.c @@ -150,7 +150,6 @@ running_machine::running_machine(const machine_config &_config, osd_interface &o memory_data(NULL), palette_data(NULL), romload_data(NULL), - input_data(NULL), input_port_data(NULL), ui_input_data(NULL), debugcpu_data(NULL), @@ -171,7 +170,6 @@ running_machine::running_machine(const machine_config &_config, osd_interface &o m_video(NULL), m_tilemap(NULL), m_debug_view(NULL), - m_driver_device(NULL), m_current_phase(MACHINE_PHASE_PREINIT), m_paused(false), m_hard_reset_pending(false), @@ -194,21 +192,19 @@ running_machine::running_machine(const machine_config &_config, osd_interface &o memset(&m_base_time, 0, sizeof(m_base_time)); // set the machine on all devices - const_cast<device_list &>(devicelist()).set_machine_all(*this); - - // find the driver device config and tell it which game - m_driver_device = device<driver_device>("root"); - if (m_driver_device == NULL) - throw emu_fatalerror("Machine configuration missing driver_device"); + device_iterator iter(root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) + device->set_machine(*this); // find devices - primary_screen = downcast<screen_device *>(devicelist().first(SCREEN)); - for (device_t *device = devicelist().first(); device != NULL; device = device->next()) + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (dynamic_cast<cpu_device *>(device) != NULL) { firstcpu = downcast<cpu_device *>(device); break; } + screen_device_iterator screeniter(root_device()); + primary_screen = screeniter.first(); // fetch core options if (options().debug()) @@ -318,8 +314,12 @@ void running_machine::start() // so this location in the init order is important ui_set_startup_text(*this, "Initializing...", true); - // start up the devices - const_cast<device_list &>(devicelist()).start_all(); + // register callbacks for the devices, then start them + add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(FUNC(running_machine::reset_all_devices), this)); + add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(running_machine::stop_all_devices), this)); + save().register_presave(save_prepost_delegate(FUNC(running_machine::presave_all_devices), this)); + save().register_postload(save_prepost_delegate(FUNC(running_machine::postload_all_devices), this)); + start_all_devices(); // if we're coming in with a savegame request, process it now const char *savegame = options().state(); @@ -344,25 +344,15 @@ void running_machine::start() device_t &running_machine::add_dynamic_device(device_t &owner, device_type type, const char *tag, UINT32 clock) { - // allocate and append this device - astring fulltag; - owner.subtag(fulltag, tag); - device_t &device = const_cast<device_list &>(devicelist()).append(fulltag, *type(m_config, fulltag, &owner, clock)); - - // append any machine config additions from new devices - for (device_t *curdevice = devicelist().first(); curdevice != NULL; curdevice = curdevice->next()) - if (!curdevice->configured()) - { - machine_config_constructor machconfig = curdevice->machine_config_additions(); - if (machconfig != NULL) - (*machconfig)(const_cast<machine_config &>(m_config), curdevice); - } - - // notify any new devices that their configurations are complete - for (device_t *curdevice = devicelist().first(); curdevice != NULL; curdevice = curdevice->next()) - if (!curdevice->configured()) - curdevice->config_complete(); - return device; + // add the device in a standard manner + device_t *device = const_cast<machine_config &>(m_config).device_add(&owner, tag, type, clock); + + // notify this device and all its subdevices that they are now configured + device_iterator iter(root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) + if (!device->configured()) + device->config_complete(); + return *device; } @@ -633,6 +623,7 @@ void running_machine::resume() memory_region *running_machine::region_alloc(const char *name, UINT32 length, UINT8 width, endianness_t endian) { +mame_printf_verbose("Region '%s' created\n", name); // make sure we don't have a region of the same name; also find the end of the list memory_region *info = m_regionlist.find(name); if (info != NULL) @@ -887,6 +878,115 @@ void running_machine::logfile_callback(running_machine &machine, const char *buf machine.m_logfile->puts(buffer); } + +//------------------------------------------------- +// start_all_devices - start any unstarted devices +//------------------------------------------------- + +void running_machine::start_all_devices() +{ + // iterate through the devices + int last_failed_starts = -1; + while (last_failed_starts != 0) + { + // iterate over all devices + int failed_starts = 0; + device_iterator iter(root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) + if (!device->started()) + { + // attempt to start the device, catching any expected exceptions + try + { + // if the device doesn't have a machine yet, set it first + if (device->m_machine == NULL) + device->set_machine(*this); + + // now start the device + mame_printf_verbose("Starting %s '%s'\n", device->name(), device->tag()); + device->start(); + } + + // handle missing dependencies by moving the device to the end + catch (device_missing_dependencies &) + { + // if we're the end, fail + mame_printf_verbose(" (missing dependencies; rescheduling)\n"); + failed_starts++; + } + } + + // each iteration should reduce the number of failed starts; error if + // this doesn't happen + if (failed_starts == last_failed_starts) + throw emu_fatalerror("Circular dependency in device startup!"); + last_failed_starts = failed_starts; + } +} + + +//------------------------------------------------- +// reset_all_devices - reset all devices in the +// hierarchy +//------------------------------------------------- + +void running_machine::reset_all_devices() +{ + // iterate over devices and reset them + device_iterator iter(root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) + device->reset(); +} + + +//------------------------------------------------- +// stop_all_devices - stop all the devices in the +// hierarchy +//------------------------------------------------- + +void running_machine::stop_all_devices() +{ + // first let the debugger save comments + if ((debug_flags & DEBUG_FLAG_ENABLED) != 0) + debug_comment_save(*this); + + // iterate over devices and stop them + device_iterator iter(root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) + device->stop(); + + // then nuke the device tree +// global_free(m_root_device); +} + + +//------------------------------------------------- +// presave_all_devices - tell all the devices we +// are about to save +//------------------------------------------------- + +void running_machine::presave_all_devices() +{ + device_iterator iter(root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) + device->pre_save(); +} + + +//------------------------------------------------- +// postload_all_devices - tell all the devices we +// just completed a load +//------------------------------------------------- + +void running_machine::postload_all_devices() +{ + device_iterator iter(root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) + device->post_load(); +} + + + /*************************************************************************** MEMORY REGIONS ***************************************************************************/ @@ -1143,8 +1243,10 @@ ioport_constructor driver_device::device_input_ports() const void driver_device::device_start() { // reschedule ourselves to be last - if (next() != NULL) - throw device_missing_dependencies(); + device_iterator iter(*this); + for (device_t *test = iter.first(); test != NULL; test = iter.next()) + if (test != this && !test->started()) + throw device_missing_dependencies(); // call the game-specific init if (m_system->driver_init != NULL) diff --git a/src/emu/machine.h b/src/emu/machine.h index f80d60ef84a..dbaf69f93fc 100644 --- a/src/emu/machine.h +++ b/src/emu/machine.h @@ -186,7 +186,6 @@ class osd_interface; typedef struct _memory_private memory_private; typedef struct _palette_private palette_private; typedef struct _romload_private romload_private; -typedef struct _input_private input_private; typedef struct _input_port_private input_port_private; typedef struct _ui_input_private ui_input_private; typedef struct _debugcpu_private debugcpu_private; @@ -331,7 +330,7 @@ public: // getters const machine_config &config() const { return m_config; } - const device_list &devicelist() const { return m_config.devicelist(); } + device_t &root_device() const { return m_config.root_device(); } const game_driver &system() const { return m_system; } osd_interface &osd() const { return m_osd; } resource_pool &respool() { return m_respool; } @@ -344,8 +343,8 @@ public: video_manager &video() const { assert(m_video != NULL); return *m_video; } tilemap_manager &tilemap() const { assert(m_tilemap != NULL); return *m_tilemap; } debug_view_manager &debug_view() const { assert(m_debug_view != NULL); return *m_debug_view; } - driver_device *driver_data() const { return m_driver_device; } - template<class _DriverClass> _DriverClass *driver_data() const { return downcast<_DriverClass *>(m_driver_device); } + driver_device *driver_data() const { return &downcast<driver_device &>(root_device()); } + template<class _DriverClass> _DriverClass *driver_data() const { return &downcast<_DriverClass &>(root_device()); } machine_phase phase() const { return m_current_phase; } bool paused() const { return m_paused || (m_current_phase != MACHINE_PHASE_RUNNING); } bool exit_pending() const { return m_exit_pending; } @@ -364,7 +363,7 @@ public: bool scheduled_event_pending() const { return m_exit_pending || m_hard_reset_pending; } // fetch items by name - inline device_t *device(const char *tag); + inline device_t *device(const char *tag) { return root_device().subdevice(tag); } template<class _DeviceClass> inline _DeviceClass *device(const char *tag) { return downcast<_DeviceClass *>(device(tag)); } inline const input_port_config *port(const char *tag); inline const memory_region *region(const char *tag); @@ -408,7 +407,7 @@ public: ioport_list m_portlist; // points to a list of input port configurations // CPU information - cpu_device * firstcpu; // first CPU (allows for quick iteration via typenext) + cpu_device * firstcpu; // first CPU // video-related information gfx_element * gfx[MAX_GFX_ELEMENTS];// array of pointers to graphic sets (chars, sprites) @@ -419,7 +418,7 @@ public: const pen_t * pens; // remapped palette pen numbers colortable_t * colortable; // global colortable for remapping pen_t * shadow_table; // table for looking up a shadowed pen - bitmap_ind8 priority_bitmap; // priority bitmap + bitmap_ind8 priority_bitmap; // priority bitmap // debugger-related information UINT32 debug_flags; // the current debug flags @@ -431,7 +430,6 @@ public: memory_private * memory_data; // internal data from memory.c palette_private * palette_data; // internal data from palette.c romload_private * romload_data; // internal data from romload.c - input_private * input_data; // internal data from input.c input_port_private * input_port_data; // internal data from inptport.c ui_input_private * ui_input_data; // internal data from uiinput.c debugcpu_private * debugcpu_data; // internal data from debugcpu.c @@ -446,10 +444,17 @@ private: void fill_systime(system_time &systime, time_t t); void handle_saveload(); void soft_reset(void *ptr = NULL, INT32 param = 0); - + // internal callbacks static void logfile_callback(running_machine &machine, const char *buffer); + // internal device helpers + void start_all_devices(); + void reset_all_devices(); + void stop_all_devices(); + void presave_all_devices(); + void postload_all_devices(); + // internal state const machine_config & m_config; // reference to the constructed machine_config const game_driver & m_system; // reference to the definition of the game machine @@ -469,9 +474,6 @@ private: tilemap_manager * m_tilemap; // internal data from tilemap.c debug_view_manager * m_debug_view; // internal data from debugvw.c - // driver state - driver_device * m_driver_device; // pointer to the current driver device - // system state machine_phase m_current_phase; // current execution phase bool m_paused; // paused? @@ -716,25 +718,26 @@ device_t *driver_device_creator(const machine_config &mconfig, const char *tag, // INLINE FUNCTIONS //************************************************************************** -inline device_t *running_machine::device(const char *tag) -{ - return devicelist().find(tag); -} - inline const input_port_config *running_machine::port(const char *tag) { - return m_portlist.find(tag); + // if tag begins with a :, it's absolute + if (tag[0] == ':') + return m_portlist.find(tag); + + // otherwise, compute it relative to the root device + astring fulltag; + return m_portlist.find(root_device().subtag(fulltag, tag).cstr()); } inline const memory_region *running_machine::region(const char *tag) { // if tag begins with a :, it's absolute if (tag[0] == ':') - { - return m_regionlist.find(&tag[1]); - } + return m_regionlist.find(tag); - return m_regionlist.find(tag); + // otherwise, compute it relative to the root device + astring fulltag; + return m_regionlist.find(root_device().subtag(fulltag, tag).cstr()); } diff --git a/src/emu/machine/6532riot.c b/src/emu/machine/6532riot.c index da5bcc2105f..c8a2dfcdbb1 100644 --- a/src/emu/machine/6532riot.c +++ b/src/emu/machine/6532riot.c @@ -469,7 +469,8 @@ void riot6532_device::device_start() assert(this != NULL); /* set static values */ - m_index = machine().devicelist().indexof(RIOT6532, tag()); + device_type_iterator<&device_creator<riot6532_device>, riot6532_device> iter(machine().root_device()); + m_index = iter.indexof(*this); /* configure the ports */ m_port[0].m_in_func.resolve(m_in_a_cb, *this); diff --git a/src/emu/machine/7474.c b/src/emu/machine/7474.c index 5a9c957cc57..0c5570913a9 100644 --- a/src/emu/machine/7474.c +++ b/src/emu/machine/7474.c @@ -86,7 +86,7 @@ void ttl7474_device::static_set_output_cb(device_t &device, write_line_device_fu if (callback != NULL) { ttl7474.m_output_cb.type = DEVCB_TYPE_DEVICE; - ttl7474.m_output_cb.index = DEVCB_DEVICE_OTHER; + ttl7474.m_output_cb.index = 0; ttl7474.m_output_cb.writeline = callback; } else @@ -105,7 +105,7 @@ void ttl7474_device::static_set_comp_output_cb(device_t &device, write_line_devi if (callback != NULL) { ttl7474.m_comp_output_cb.type = DEVCB_TYPE_DEVICE; - ttl7474.m_comp_output_cb.index = DEVCB_DEVICE_OTHER; + ttl7474.m_comp_output_cb.index = 0; ttl7474.m_comp_output_cb.writeline = callback; } else diff --git a/src/emu/machine/at28c16.c b/src/emu/machine/at28c16.c index 1101b3ee8e4..bfb66894cec 100644 --- a/src/emu/machine/at28c16.c +++ b/src/emu/machine/at28c16.c @@ -65,9 +65,8 @@ void at28c16_device::device_config_complete() // on this device //------------------------------------------------- -bool at28c16_device::device_validity_check( emu_options &options, const game_driver &driver ) const +void at28c16_device::device_validity_check(validity_checker &valid) const { - return false; } diff --git a/src/emu/machine/at28c16.h b/src/emu/machine/at28c16.h index a891d51881b..d81fe6abe0e 100644 --- a/src/emu/machine/at28c16.h +++ b/src/emu/machine/at28c16.h @@ -52,7 +52,7 @@ public: protected: // device-level overrides virtual void device_config_complete(); - virtual bool device_validity_check( emu_options &options, const game_driver &driver ) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); diff --git a/src/emu/machine/ctronics.c b/src/emu/machine/ctronics.c index 2fb045b8894..a06cf944c8b 100644 --- a/src/emu/machine/ctronics.c +++ b/src/emu/machine/ctronics.c @@ -101,7 +101,7 @@ static DEVICE_START( centronics ) centronics->strobe = TRUE; /* get printer device */ - centronics->printer = downcast<printer_image_device *>(device->subdevice("printer")); + centronics->printer = device->subdevice<printer_image_device>("printer"); /* resolve callbacks */ centronics->out_ack_func.resolve(intf->out_ack_func, *device); diff --git a/src/emu/machine/eeprom.c b/src/emu/machine/eeprom.c index 129c9968c11..11929be6b77 100644 --- a/src/emu/machine/eeprom.c +++ b/src/emu/machine/eeprom.c @@ -170,17 +170,10 @@ void eeprom_device::static_set_default_value(device_t &device, UINT16 value) // on this device //------------------------------------------------- -bool eeprom_device::device_validity_check(emu_options &options, const game_driver &driver) const +void eeprom_device::device_validity_check(validity_checker &valid) const { - bool error = false; - if (m_data_bits != 8 && m_data_bits != 16) - { - mame_printf_error("%s: %s eeprom device '%s' specified invalid data width %d\n", driver.source_file, driver.name, tag(), m_data_bits); - error = true; - } - - return error; + mame_printf_error("Invalid data width %d specified\n", m_data_bits); } diff --git a/src/emu/machine/eeprom.h b/src/emu/machine/eeprom.h index 31c44d15ec1..c7605dec4db 100644 --- a/src/emu/machine/eeprom.h +++ b/src/emu/machine/eeprom.h @@ -86,7 +86,7 @@ public: protected: // device-level overrides - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); diff --git a/src/emu/machine/generic.c b/src/emu/machine/generic.c index 5a809bdb158..ba6192d3c91 100644 --- a/src/emu/machine/generic.c +++ b/src/emu/machine/generic.c @@ -94,9 +94,9 @@ void generic_machine_init(running_machine &machine) // map devices to the interrupt state memset(state->interrupt_device, 0, sizeof(state->interrupt_device)); - device_execute_interface *exec = NULL; + execute_interface_iterator iter(machine.root_device()); int index = 0; - for (bool gotone = machine.devicelist().first(exec); gotone && index < ARRAY_LENGTH(state->interrupt_device); gotone = exec->next(exec)) + for (device_execute_interface *exec = iter.first(); exec != NULL && index < ARRAY_LENGTH(state->interrupt_device); exec = iter.next()) state->interrupt_device[index++] = &exec->device(); /* register coin save state */ @@ -364,23 +364,18 @@ void nvram_load(running_machine &machine) } } - device_nvram_interface *nvram = NULL; - if (machine.devicelist().first(nvram)) + nvram_interface_iterator iter(machine.root_device()); + for (device_nvram_interface *nvram = iter.first(); nvram != NULL; nvram = iter.next()) { - for (bool gotone = (nvram != NULL); gotone; gotone = nvram->next(nvram)) + astring filename; + emu_file file(machine.options().nvram_directory(), OPEN_FLAG_READ); + if (file.open(nvram_filename(nvram->device(),filename)) == FILERR_NONE) { - astring filename; - emu_file file(machine.options().nvram_directory(), OPEN_FLAG_READ); - if (file.open(nvram_filename(nvram->device(),filename)) == FILERR_NONE) - { - nvram->nvram_load(file); - file.close(); - } - else - { - nvram->nvram_reset(); - } + nvram->nvram_load(file); + file.close(); } + else + nvram->nvram_reset(); } } @@ -402,18 +397,15 @@ void nvram_save(running_machine &machine) } } - device_nvram_interface *nvram = NULL; - if (machine.devicelist().first(nvram)) + nvram_interface_iterator iter(machine.root_device()); + for (device_nvram_interface *nvram = iter.first(); nvram != NULL; nvram = iter.next()) { - for (bool gotone = (nvram != NULL); gotone; gotone = nvram->next(nvram)) + astring filename; + emu_file file(machine.options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); + if (file.open(nvram_filename(nvram->device(),filename)) == FILERR_NONE) { - astring filename; - emu_file file(machine.options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(nvram_filename(nvram->device(),filename)) == FILERR_NONE) - { - nvram->nvram_save(file); - file.close(); - } + nvram->nvram_save(file); + file.close(); } } } diff --git a/src/emu/machine/i2cmem.c b/src/emu/machine/i2cmem.c index 0aaacf24026..288a430de7c 100644 --- a/src/emu/machine/i2cmem.c +++ b/src/emu/machine/i2cmem.c @@ -125,10 +125,8 @@ void i2cmem_device::device_config_complete() // on this device //------------------------------------------------- -bool i2cmem_device::device_validity_check( emu_options &options, const game_driver &driver ) const +void i2cmem_device::device_validity_check(validity_checker &valid) const { - bool error = false; - return error; } diff --git a/src/emu/machine/i2cmem.h b/src/emu/machine/i2cmem.h index f0c6aa14deb..1dded6826fd 100644 --- a/src/emu/machine/i2cmem.h +++ b/src/emu/machine/i2cmem.h @@ -70,7 +70,7 @@ public: protected: // device-level overrides virtual void device_config_complete(); - virtual bool device_validity_check( emu_options &options, const game_driver &driver ) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); diff --git a/src/emu/machine/i8243.c b/src/emu/machine/i8243.c index cf1355585eb..cb1650413d2 100644 --- a/src/emu/machine/i8243.c +++ b/src/emu/machine/i8243.c @@ -41,7 +41,8 @@ void i8243_device::static_set_read_handler(device_t &device, read8_device_func c if(callback != NULL) { i8243.m_readhandler_cb.type = DEVCB_TYPE_DEVICE; - i8243.m_readhandler_cb.index = DEVCB_DEVICE_SELF; + i8243.m_readhandler_cb.index = 0; + i8243.m_readhandler_cb.tag = ""; i8243.m_readhandler_cb.readdevice = callback; } else @@ -62,7 +63,8 @@ void i8243_device::static_set_write_handler(device_t &device, write8_device_func if(callback != NULL) { i8243.m_writehandler_cb.type = DEVCB_TYPE_DEVICE; - i8243.m_writehandler_cb.index = DEVCB_DEVICE_SELF; + i8243.m_writehandler_cb.index = 0; + i8243.m_writehandler_cb.tag = ""; i8243.m_writehandler_cb.writedevice = callback; } else diff --git a/src/emu/machine/laserdsc.h b/src/emu/machine/laserdsc.h index 185b2296586..b7c0df154e9 100644 --- a/src/emu/machine/laserdsc.h +++ b/src/emu/machine/laserdsc.h @@ -380,6 +380,9 @@ private: render_texture * m_overtex; // texture for the overlay }; +// iterator - interface iterator works for subclasses too +typedef device_interface_iterator<laserdisc_device> laserdisc_device_iterator; + //************************************************************************** diff --git a/src/emu/machine/mb3773.c b/src/emu/machine/mb3773.c index 925def0a33f..cfe37d36eb7 100644 --- a/src/emu/machine/mb3773.c +++ b/src/emu/machine/mb3773.c @@ -47,9 +47,8 @@ void mb3773_device::device_config_complete() // on this device //------------------------------------------------- -bool mb3773_device::device_validity_check( emu_options &options, const game_driver &driver ) const +void mb3773_device::device_validity_check(validity_checker &valid) const { - return false; } diff --git a/src/emu/machine/mb3773.h b/src/emu/machine/mb3773.h index 24874b3f534..b139477f2dc 100644 --- a/src/emu/machine/mb3773.h +++ b/src/emu/machine/mb3773.h @@ -35,7 +35,7 @@ public: protected: // device-level overrides virtual void device_config_complete(); - virtual bool device_validity_check( emu_options &options, const game_driver &driver ) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); diff --git a/src/emu/machine/msm6242.c b/src/emu/machine/msm6242.c index dd7bda24758..cc859c84e28 100644 --- a/src/emu/machine/msm6242.c +++ b/src/emu/machine/msm6242.c @@ -121,10 +121,8 @@ TIMER_CALLBACK( msm6242_device::rtc_inc_callback ) // on this device //------------------------------------------------- -bool msm6242_device::device_validity_check(emu_options &options, const game_driver &driver) const +void msm6242_device::device_validity_check(validity_checker &valid) const { - bool error = false; - return error; } //------------------------------------------------- diff --git a/src/emu/machine/msm6242.h b/src/emu/machine/msm6242.h index 3addb6b9df9..21b57dc1f5e 100644 --- a/src/emu/machine/msm6242.h +++ b/src/emu/machine/msm6242.h @@ -55,7 +55,7 @@ public: protected: // device-level overrides virtual void device_config_complete(); - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); diff --git a/src/emu/machine/ram.c b/src/emu/machine/ram.c index 3c69f5e54dd..7c9648dbc47 100644 --- a/src/emu/machine/ram.c +++ b/src/emu/machine/ram.c @@ -75,38 +75,32 @@ void ram_device::device_start() // checks //------------------------------------------------- -bool ram_device::device_validity_check(emu_options &options, const game_driver &driver) const +void ram_device::device_validity_check(validity_checker &valid) const { const char *ramsize_string = NULL; int is_valid = FALSE; UINT32 specified_ram = 0; - bool error = FALSE; const char *gamename_option = NULL; /* verify default ram value */ if (default_size() == 0) - { - mame_printf_error("%s: '%s' has an invalid default RAM option: %s\n", driver.source_file, driver.name, m_default_size); - error = TRUE; - } + mame_printf_error("Invalid default RAM option: %s\n", m_default_size); /* command line options are only parsed for the device named RAM_TAG */ if (tag() != NULL && strcmp(tag(), RAM_TAG) == 0) { /* verify command line ram option */ - ramsize_string = options.ram_size(); - gamename_option = options.system_name(); + ramsize_string = mconfig().options().ram_size(); + gamename_option = mconfig().options().system_name(); if ((ramsize_string != NULL) && (ramsize_string[0] != '\0')) { specified_ram = parse_string(ramsize_string); if (specified_ram == 0) - { - mame_printf_error("%s: '%s' cannot recognize the RAM option %s\n", driver.source_file, driver.name, ramsize_string); - error = TRUE; - } - if (gamename_option != NULL && *gamename_option != 0 && strcmp(gamename_option, driver.name) == 0) + mame_printf_error("Cannot recognize the RAM option %s\n", ramsize_string); + + if (gamename_option != NULL && *gamename_option != 0 && strcmp(gamename_option, mconfig().gamedrv().name) == 0) { /* compare command line option to default value */ if (default_size() == specified_ram) @@ -130,10 +124,7 @@ bool ram_device::device_validity_check(emu_options &options, const game_driver & UINT32 option_ram_size = parse_string(p); if (option_ram_size == 0) - { - mame_printf_error("%s: '%s' has an invalid RAM option: %s\n", driver.source_file, driver.name, p); - error = TRUE; - } + mame_printf_error("Invalid RAM option: %s\n", p); if (option_ram_size == specified_ram) is_valid = TRUE; @@ -163,18 +154,17 @@ bool ram_device::device_validity_check(emu_options &options, const game_driver & if (!is_valid) { - mame_printf_error("%s: '%s' cannot recognize the RAM option %s", driver.source_file, driver.name, ramsize_string); - mame_printf_error(" (valid options are %s", m_default_size); + astring output; + output.catprintf("Cannot recognize the RAM option %s", ramsize_string); + output.catprintf(" (valid options are %s", m_default_size); if (m_extra_options != NULL) - mame_printf_error(",%s).\n", m_extra_options); + output.catprintf(",%s).\n", m_extra_options); else - mame_printf_error(").\n"); + output.catprintf(").\n"); - error = TRUE; + mame_printf_error("%s", output.cstr()); } - - return error; } diff --git a/src/emu/machine/ram.h b/src/emu/machine/ram.h index 43a363aa0ca..238d7dcfabd 100644 --- a/src/emu/machine/ram.h +++ b/src/emu/machine/ram.h @@ -65,7 +65,7 @@ public: protected: virtual void device_start(void); - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; private: // device state @@ -82,4 +82,7 @@ private: // device type definition extern const device_type RAM; +// device iterator +typedef device_type_iterator<&device_creator<ram_device>, ram_device> ram_device_iterator; + #endif /* __RAM_H__ */ diff --git a/src/emu/machine/rtc9701.c b/src/emu/machine/rtc9701.c index 2ac36ee0072..7812a858696 100644 --- a/src/emu/machine/rtc9701.c +++ b/src/emu/machine/rtc9701.c @@ -81,10 +81,8 @@ TIMER_CALLBACK( rtc9701_device::rtc_inc_callback ) // on this device //------------------------------------------------- -bool rtc9701_device::device_validity_check(emu_options &options, const game_driver &driver) const +void rtc9701_device::device_validity_check(validity_checker &valid) const { - bool error = false; - return error; } //------------------------------------------------- diff --git a/src/emu/machine/rtc9701.h b/src/emu/machine/rtc9701.h index 4d633167e66..9c5b96be74c 100644 --- a/src/emu/machine/rtc9701.h +++ b/src/emu/machine/rtc9701.h @@ -62,7 +62,7 @@ public: protected: // device-level overrides - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); diff --git a/src/emu/machine/scsihd.c b/src/emu/machine/scsihd.c index 606350800b1..05f372aa6e9 100644 --- a/src/emu/machine/scsihd.c +++ b/src/emu/machine/scsihd.c @@ -279,7 +279,8 @@ static void scsihd_alloc_instance( SCSIInstance *scsiInstance, const char *diskr if (our_this->disk == NULL) { // try to locate the CHD from an image subdevice - for (device_t *device = machine.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(machine.root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) { if (device->subdevice(diskregion) != NULL) { diff --git a/src/emu/machine/v3021.c b/src/emu/machine/v3021.c index 66b788a36f1..13d2d5796a4 100644 --- a/src/emu/machine/v3021.c +++ b/src/emu/machine/v3021.c @@ -78,10 +78,8 @@ TIMER_CALLBACK( v3021_device::rtc_inc_callback ) // on this device //------------------------------------------------- -bool v3021_device::device_validity_check(emu_options &options, const game_driver &driver) const +void v3021_device::device_validity_check(validity_checker &valid) const { - bool error = false; - return error; } //------------------------------------------------- diff --git a/src/emu/machine/v3021.h b/src/emu/machine/v3021.h index 9a8bec9c3b2..af826448fbd 100644 --- a/src/emu/machine/v3021.h +++ b/src/emu/machine/v3021.h @@ -48,7 +48,7 @@ public: protected: // device-level overrides - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); diff --git a/src/emu/machine/wd17xx.c b/src/emu/machine/wd17xx.c index b1e9b5e4beb..b0d19483609 100644 --- a/src/emu/machine/wd17xx.c +++ b/src/emu/machine/wd17xx.c @@ -1247,14 +1247,7 @@ void wd17xx_set_drive(device_t *device, UINT8 drive) if (w->intf->floppy_drive_tags[drive] != NULL) { - if (device->owner() != NULL) { - w->drive = device->owner()->subdevice(w->intf->floppy_drive_tags[drive]); - if (w->drive == NULL) { - w->drive = device->machine().device(w->intf->floppy_drive_tags[drive]); - } - } - else - w->drive = device->machine().device(w->intf->floppy_drive_tags[drive]); + w->drive = device->siblingdevice(w->intf->floppy_drive_tags[drive]); } } @@ -2083,14 +2076,7 @@ static DEVICE_RESET( wd1770 ) if(w->intf->floppy_drive_tags[i]!=NULL) { device_t *img = NULL; - if (device->owner() != NULL) - img = device->owner()->subdevice(w->intf->floppy_drive_tags[i]); - if (img == NULL) { - img = device->machine().device(w->intf->floppy_drive_tags[i]); - } - - else - img = device->machine().device(w->intf->floppy_drive_tags[i]); + img = device->siblingdevice(w->intf->floppy_drive_tags[i]); if (img!=NULL) { floppy_drive_set_controller(img,device); diff --git a/src/emu/mame.c b/src/emu/mame.c index 5407fe4c2d6..c5a523251a6 100644 --- a/src/emu/mame.c +++ b/src/emu/mame.c @@ -104,8 +104,21 @@ static bool print_verbose = false; static running_machine *global_machine; /* output channels */ -static output_callback_func output_cb[OUTPUT_CHANNEL_COUNT]; -static void *output_cb_param[OUTPUT_CHANNEL_COUNT]; +static output_delegate output_cb[OUTPUT_CHANNEL_COUNT] = +{ + output_delegate(FUNC(mame_file_output_callback), stderr), // OUTPUT_CHANNEL_ERROR + output_delegate(FUNC(mame_file_output_callback), stderr), // OUTPUT_CHANNEL_WARNING + output_delegate(FUNC(mame_file_output_callback), stdout), // OUTPUT_CHANNEL_INFO +#ifdef MAME_DEBUG + output_delegate(FUNC(mame_file_output_callback), stdout), // OUTPUT_CHANNEL_DEBUG +#else + output_delegate(FUNC(mame_null_output_callback), stdout), // OUTPUT_CHANNEL_DEBUG +#endif + output_delegate(FUNC(mame_file_output_callback), stdout), // OUTPUT_CHANNEL_VERBOSE + output_delegate(FUNC(mame_file_output_callback), stdout) // OUTPUT_CHANNEL_LOG +}; + + /*************************************************************************** CORE IMPLEMENTATION @@ -151,7 +164,10 @@ int mame_execute(emu_options &options, osd_interface &osd) // otherwise, perform validity checks before anything else else - validate_drivers(options, system); + { + validity_checker valid(options); + valid.check_shared_source(*system); + } firstgame = false; @@ -203,20 +219,17 @@ int mame_execute(emu_options &options, osd_interface &osd) channel -------------------------------------------------*/ -void mame_set_output_channel(output_channel channel, output_callback_func callback, void *param, output_callback_func *prevcb, void **prevparam) +output_delegate mame_set_output_channel(output_channel channel, output_delegate callback) { assert(channel < OUTPUT_CHANNEL_COUNT); - assert(callback != NULL); + assert(!callback.isnull()); /* return the originals if requested */ - if (prevcb != NULL) - *prevcb = output_cb[channel]; - if (prevparam != NULL) - *prevparam = output_cb_param[channel]; + output_delegate prevcb = output_cb[channel]; /* set the new ones */ output_cb[channel] = callback; - output_cb_param[channel] = param; + return prevcb; } @@ -225,9 +238,9 @@ void mame_set_output_channel(output_channel channel, output_callback_func callba for file output -------------------------------------------------*/ -void mame_file_output_callback(void *param, const char *format, va_list argptr) +void mame_file_output_callback(FILE *param, const char *format, va_list argptr) { - vfprintf((FILE *)param, format, argptr); + vfprintf(param, format, argptr); } @@ -236,7 +249,7 @@ void mame_file_output_callback(void *param, const char *format, va_list argptr) for no output -------------------------------------------------*/ -void mame_null_output_callback(void *param, const char *format, va_list argptr) +void mame_null_output_callback(FILE *param, const char *format, va_list argptr) { } @@ -250,16 +263,9 @@ void mame_printf_error(const char *format, ...) { va_list argptr; - /* by default, we go to stderr */ - if (output_cb[OUTPUT_CHANNEL_ERROR] == NULL) - { - output_cb[OUTPUT_CHANNEL_ERROR] = mame_file_output_callback; - output_cb_param[OUTPUT_CHANNEL_ERROR] = stderr; - } - /* do the output */ va_start(argptr, format); - (*output_cb[OUTPUT_CHANNEL_ERROR])(output_cb_param[OUTPUT_CHANNEL_ERROR], format, argptr); + output_cb[OUTPUT_CHANNEL_ERROR](format, argptr); va_end(argptr); } @@ -273,16 +279,9 @@ void mame_printf_warning(const char *format, ...) { va_list argptr; - /* by default, we go to stderr */ - if (output_cb[OUTPUT_CHANNEL_WARNING] == NULL) - { - output_cb[OUTPUT_CHANNEL_WARNING] = mame_file_output_callback; - output_cb_param[OUTPUT_CHANNEL_WARNING] = stderr; - } - /* do the output */ va_start(argptr, format); - (*output_cb[OUTPUT_CHANNEL_WARNING])(output_cb_param[OUTPUT_CHANNEL_WARNING], format, argptr); + output_cb[OUTPUT_CHANNEL_WARNING](format, argptr); va_end(argptr); } @@ -296,16 +295,9 @@ void mame_printf_info(const char *format, ...) { va_list argptr; - /* by default, we go to stdout */ - if (output_cb[OUTPUT_CHANNEL_INFO] == NULL) - { - output_cb[OUTPUT_CHANNEL_INFO] = mame_file_output_callback; - output_cb_param[OUTPUT_CHANNEL_INFO] = stdout; - } - /* do the output */ va_start(argptr, format); - (*output_cb[OUTPUT_CHANNEL_INFO])(output_cb_param[OUTPUT_CHANNEL_INFO], format, argptr); + output_cb[OUTPUT_CHANNEL_INFO](format, argptr); va_end(argptr); } @@ -323,16 +315,9 @@ void mame_printf_verbose(const char *format, ...) if (!print_verbose) return; - /* by default, we go to stdout */ - if (output_cb[OUTPUT_CHANNEL_VERBOSE] == NULL) - { - output_cb[OUTPUT_CHANNEL_VERBOSE] = mame_file_output_callback; - output_cb_param[OUTPUT_CHANNEL_VERBOSE] = stdout; - } - /* do the output */ va_start(argptr, format); - (*output_cb[OUTPUT_CHANNEL_VERBOSE])(output_cb_param[OUTPUT_CHANNEL_VERBOSE], format, argptr); + output_cb[OUTPUT_CHANNEL_VERBOSE](format, argptr); va_end(argptr); } @@ -346,21 +331,9 @@ void mame_printf_debug(const char *format, ...) { va_list argptr; - /* by default, we go to stderr */ - if (output_cb[OUTPUT_CHANNEL_DEBUG] == NULL) - { -#ifdef MAME_DEBUG - output_cb[OUTPUT_CHANNEL_DEBUG] = mame_file_output_callback; - output_cb_param[OUTPUT_CHANNEL_DEBUG] = stdout; -#else - output_cb[OUTPUT_CHANNEL_DEBUG] = mame_null_output_callback; - output_cb_param[OUTPUT_CHANNEL_DEBUG] = NULL; -#endif - } - /* do the output */ va_start(argptr, format); - (*output_cb[OUTPUT_CHANNEL_DEBUG])(output_cb_param[OUTPUT_CHANNEL_DEBUG], format, argptr); + output_cb[OUTPUT_CHANNEL_DEBUG](format, argptr); va_end(argptr); } @@ -375,16 +348,9 @@ void mame_printf_log(const char *format, ...) { va_list argptr; - /* by default, we go to stderr */ - if (output_cb[OUTPUT_CHANNEL_LOG] == NULL) - { - output_cb[OUTPUT_CHANNEL_LOG] = mame_file_output_callback; - output_cb_param[OUTPUT_CHANNEL_LOG] = stderr; - } - /* do the output */ va_start(argptr, format); - (*output_cb[OUTPUT_CHANNEL_LOG])(output_cb_param[OUTPUT_CHANNEL_LOG], format, argptr); + output_cb[OUTPUT_CHANNEL_LOG])(format, argptr); va_end(argptr); } #endif diff --git a/src/emu/mame.h b/src/emu/mame.h index 13b51c696fc..cdec7d1db1f 100644 --- a/src/emu/mame.h +++ b/src/emu/mame.h @@ -49,7 +49,7 @@ enum //************************************************************************** // output channel callback -typedef void (*output_callback_func)(void *param, const char *format, va_list argptr); +typedef delegate<void (const char *, va_list)> output_delegate; class emulator_info { @@ -76,6 +76,8 @@ public: static void printf_usage(const char *par1, const char *par2); }; + + //************************************************************************** // GLOBAL VARIABLES //************************************************************************** @@ -102,11 +104,11 @@ int mame_is_valid_machine(running_machine &machine); /* ----- output management ----- */ /* set the output handler for a channel, returns the current one */ -void mame_set_output_channel(output_channel channel, output_callback_func callback, void *param, output_callback_func *prevcb, void **prevparam); +output_delegate mame_set_output_channel(output_channel channel, output_delegate callback); /* built-in default callbacks */ -void mame_file_output_callback(void *param, const char *format, va_list argptr); -void mame_null_output_callback(void *param, const char *format, va_list argptr); +void mame_file_output_callback(FILE *file, const char *format, va_list argptr); +void mame_null_output_callback(FILE *param, const char *format, va_list argptr); /* calls to be used by the code */ void mame_printf_error(const char *format, ...) ATTR_PRINTF(1,2); diff --git a/src/emu/mconfig.c b/src/emu/mconfig.c index 6ef83f2e0ec..43c76b7ee7f 100644 --- a/src/emu/mconfig.c +++ b/src/emu/mconfig.c @@ -62,14 +62,15 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options) m_total_colors(0), m_default_layout(NULL), m_gamedrv(gamedrv), - m_options(options) + m_options(options), + m_root_device(NULL) { // construct the config (*gamedrv.machine_config)(*this, NULL); // intialize slot devices - make sure that any required devices have been allocated - device_slot_interface *slot = NULL; - for (bool gotone = m_devicelist.first(slot); gotone; gotone = slot->next(slot)) + slot_interface_iterator slotiter(root_device()); + for (device_slot_interface *slot = slotiter.first(); slot != NULL; slot = slotiter.next()) { const slot_interface *intf = slot->get_slot_interfaces(); if (intf != NULL) @@ -77,16 +78,19 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options) device_t &owner = slot->device(); const char *selval = options.value(owner.tag()); if (!options.exists(owner.tag())) - selval = slot->get_default_card(devicelist(), options); + selval = slot->get_default_card(*this, options); - if (selval != NULL && strlen(selval)!=0) { + if (selval != NULL && strlen(selval) != 0) + { bool found = false; - for (int i = 0; intf[i].name != NULL; i++) { - if (strcmp(selval, intf[i].name) == 0) { + for (int i = 0; intf[i].name != NULL; i++) + { + if (strcmp(selval, intf[i].name) == 0) + { device_t *new_dev = device_add(&owner, intf[i].name, intf[i].devtype, 0); found = true; - const char *def = slot->get_default_card(devicelist(), options); - if ((def!=NULL) && (strcmp(def,selval)==0)) + const char *def = slot->get_default_card(*this, options); + if (def != NULL && strcmp(def, selval) == 0) device_t::static_set_input_default(*new_dev, slot->input_ports_defaults()); } } @@ -97,13 +101,11 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options) } // when finished, set the game driver - device_t *root = m_devicelist.find("root"); - if (root == NULL) - throw emu_fatalerror("Machine configuration missing driver_device"); - driver_device::static_set_game(*root, gamedrv); + driver_device::static_set_game(*m_root_device, gamedrv); // then notify all devices that their configuration is complete - for (device_t *device = m_devicelist.first(); device != NULL; device = device->next()) + device_iterator iter(root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) if (!device->configured()) device->config_complete(); } @@ -115,6 +117,7 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options) machine_config::~machine_config() { + global_free(m_root_device); } @@ -125,46 +128,8 @@ machine_config::~machine_config() screen_device *machine_config::first_screen() const { - return downcast<screen_device *>(m_devicelist.first(SCREEN)); -} - - -//------------------------------------------------- -// device_add_subdevices - helper to add -// devices owned by the device -//------------------------------------------------- - -void machine_config::device_add_subdevices(device_t *device) -{ - machine_config_constructor additions = device->machine_config_additions(); - if (additions != NULL) - (*additions)(*this, device); -} - - -//------------------------------------------------- -// device_remove_subdevices - helper to remove -// devices owned by the device -//------------------------------------------------- - -void machine_config::device_remove_subdevices(const device_t *device) -{ - if (device != NULL) - { - device_t *sub_device = m_devicelist.first(); - while (sub_device != NULL) - { - if (sub_device->owner() == device) - device_remove_subdevices(sub_device); - - device_t *next_device = sub_device->next(); - - if (sub_device->owner() == device) - m_devicelist.remove(*sub_device); - - sub_device = next_device; - } - } + screen_device_iterator iter(root_device()); + return iter.first(); } @@ -175,11 +140,19 @@ void machine_config::device_remove_subdevices(const device_t *device) device_t *machine_config::device_add(device_t *owner, const char *tag, device_type type, UINT32 clock) { - astring tempstring; - const char *fulltag = owner->subtag(tempstring, tag); - device_t *device = &m_devicelist.append(fulltag, *(*type)(*this, fulltag, owner, clock)); - device_add_subdevices(device); - return device; + // if there's an owner, let the owner do the work + if (owner != NULL) + return owner->add_subdevice(type, tag, clock); + + // otherwise, allocate the device directly + assert(m_root_device == NULL); + m_root_device = (*type)(*this, tag, owner, clock); + + // apply any machine configuration owned by the device now + machine_config_constructor additions = m_root_device->machine_config_additions(); + if (additions != NULL) + (*additions)(*this, m_root_device); + return m_root_device; } @@ -190,12 +163,17 @@ device_t *machine_config::device_add(device_t *owner, const char *tag, device_ty device_t *machine_config::device_replace(device_t *owner, const char *tag, device_type type, UINT32 clock) { - astring tempstring; - const char *fulltag = owner->subtag(tempstring, tag); - device_remove_subdevices(m_devicelist.find(fulltag)); - device_t *device = &m_devicelist.replace_and_remove(fulltag, *(*type)(*this, fulltag, owner, clock)); - device_add_subdevices(device); - return device; + // find the original device by this name (must exist) + assert(owner != NULL); + device_t *device = owner->subdevice(tag); + if (device == NULL) + { + mame_printf_warning("Warning: attempting to replace non-existent device '%s'\n", tag); + return device_add(owner, tag, type, clock); + } + + // let the device's owner do the work + return device->owner()->replace_subdevice(*device, type, tag, clock); } @@ -206,11 +184,17 @@ device_t *machine_config::device_replace(device_t *owner, const char *tag, devic device_t *machine_config::device_remove(device_t *owner, const char *tag) { - astring tempstring; - const char *fulltag = owner->subtag(tempstring, tag); - device_t *device=m_devicelist.find(fulltag); - device_remove_subdevices(device); - m_devicelist.remove(*device); + // find the original device by this name (must exist) + assert(owner != NULL); + device_t *device = owner->subdevice(tag); + if (device == NULL) + { + mame_printf_warning("Warning: attempting to remove non-existent device '%s'\n", tag); + return NULL; + } + + // let the device's owner do the work + device->owner()->remove_subdevice(*device); return NULL; } @@ -222,10 +206,13 @@ device_t *machine_config::device_remove(device_t *owner, const char *tag) device_t *machine_config::device_find(device_t *owner, const char *tag) { - astring tempstring; - const char *fulltag = owner->subtag(tempstring, tag); - device_t *device = m_devicelist.find(fulltag); + // find the original device by this name (must exist) + assert(owner != NULL); + device_t *device = owner->subdevice(tag); + assert(device != NULL); if (device == NULL) - throw emu_fatalerror("Unable to find device: tag=%s\n", fulltag); + throw emu_fatalerror("Unable to find device '%s'\n", tag); + + // return the device return device; } diff --git a/src/emu/mconfig.h b/src/emu/mconfig.h index e4b619eba2a..73f7770cf92 100644 --- a/src/emu/mconfig.h +++ b/src/emu/mconfig.h @@ -131,10 +131,11 @@ public: // getters const game_driver &gamedrv() const { return m_gamedrv; } - const device_list &devicelist() const { return m_devicelist; } - const device_t *first_device() const { return m_devicelist.first(); } + device_t &root_device() const { assert(m_root_device != NULL); return *m_root_device; } screen_device *first_screen() const; emu_options &options() const { return m_options; } + inline device_t *device(const char *tag) const { return root_device().subdevice(tag); } + template<class _DeviceClass> inline _DeviceClass *device(const char *tag) const { return downcast<_DeviceClass *>(device(tag)); } // public state attotime m_minimum_quantum; // minimum scheduling quantum @@ -142,9 +143,11 @@ public: INT32 m_watchdog_vblank_count; // number of VBLANKs until the watchdog kills us attotime m_watchdog_time; // length of time until the watchdog kills us + // legacy callbacks nvram_handler_func m_nvram_handler; // NVRAM save/load callback memcard_handler_func m_memcard_handler; // memory card save/load callback + // other parameters UINT32 m_video_attributes; // flags describing the video system const gfx_decode_entry *m_gfxdecodeinfo; // pointer to array of graphics decoding information UINT32 m_total_colors; // total number of colors in the palette @@ -157,12 +160,10 @@ public: device_t *device_find(device_t *owner, const char *tag); private: - void device_add_subdevices(device_t *device); - void device_remove_subdevices(const device_t *device); - + // internal state const game_driver & m_gamedrv; emu_options & m_options; - device_list m_devicelist; // list of device configs + device_t * m_root_device; }; diff --git a/src/emu/memory.c b/src/emu/memory.c index dd11e6dd51c..521eb09d871 100644 --- a/src/emu/memory.c +++ b/src/emu/memory.c @@ -1726,8 +1726,8 @@ void memory_init(running_machine &machine) memdata->banknext = STATIC_BANK1; // loop over devices and spaces within each device - device_memory_interface *memory = NULL; - for (bool gotone = machine.devicelist().first(memory); gotone; gotone = memory->next(memory)) + memory_interface_iterator iter(machine.root_device()); + for (device_memory_interface *memory = iter.first(); memory != NULL; memory = iter.next()) for (address_spacenum spacenum = AS_0; spacenum < ADDRESS_SPACES; spacenum++) { // if there is a configuration for this space, we need an address space @@ -1781,10 +1781,22 @@ address_space *memory_nonspecific_space(running_machine &machine) void memory_configure_bank(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) { + memory_configure_bank(machine.root_device(), tag, startentry, numentries, base, stride); +} + + +//------------------------------------------------- +// memory_configure_bank - configure the +// addresses for a bank +//------------------------------------------------- + +void memory_configure_bank(device_t &device, const char *tag, int startentry, int numentries, void *base, offs_t stride) +{ // validation checks - memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag); + astring fulltag; + memory_bank *bank = device.machine().memory_data->bankmap.find_hash_only(device.subtag(fulltag, tag)); if (bank == NULL) - fatalerror("memory_configure_bank called for unknown bank '%s'", tag); + fatalerror("memory_configure_bank called for unknown bank '%s'", fulltag.cstr()); if (base == NULL) fatalerror("memory_configure_bank called NULL base"); @@ -1795,14 +1807,13 @@ void memory_configure_bank(running_machine &machine, const char *tag, int starte //------------------------------------------------- -// memory_configure_bank - configure the -// addresses for a bank +// memory_configure_bank_decrypted - configure +// the decrypted addresses for a bank //------------------------------------------------- -void memory_configure_bank(device_t *device, const char *tag, int startentry, int numentries, void *base, offs_t stride) +void memory_configure_bank_decrypted(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) { - astring tempstring; - memory_configure_bank(device->machine(), device->subtag(tempstring, tag), startentry, numentries, base, stride); + memory_configure_bank_decrypted(machine.root_device(), tag, startentry, numentries, base, stride); } @@ -1811,12 +1822,13 @@ void memory_configure_bank(device_t *device, const char *tag, int startentry, in // the decrypted addresses for a bank //------------------------------------------------- -void memory_configure_bank_decrypted(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) +void memory_configure_bank_decrypted(device_t &device, const char *tag, int startentry, int numentries, void *base, offs_t stride) { // validation checks - memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag); + astring fulltag; + memory_bank *bank = device.machine().memory_data->bankmap.find_hash_only(device.subtag(fulltag, tag)); if (bank == NULL) - fatalerror("memory_configure_bank_decrypted called for unknown bank '%s'", tag); + fatalerror("memory_configure_bank_decrypted called for unknown bank '%s'", fulltag.cstr()); if (base == NULL) fatalerror("memory_configure_bank_decrypted called NULL base"); @@ -1827,14 +1839,13 @@ void memory_configure_bank_decrypted(running_machine &machine, const char *tag, //------------------------------------------------- -// memory_configure_bank_decrypted - configure -// the decrypted addresses for a bank +// memory_set_bank - select one pre-configured +// entry to be the new bank base //------------------------------------------------- -void memory_configure_bank_decrypted(device_t *device, const char *tag, int startentry, int numentries, void *base, offs_t stride) +void memory_set_bank(running_machine &machine, const char *tag, int entrynum) { - astring tempstring; - memory_configure_bank_decrypted(device->machine(), device->subtag(tempstring, tag), startentry, numentries, base, stride); + memory_set_bank(machine.root_device(), tag, entrynum); } @@ -1843,12 +1854,13 @@ void memory_configure_bank_decrypted(device_t *device, const char *tag, int star // entry to be the new bank base //------------------------------------------------- -void memory_set_bank(running_machine &machine, const char *tag, int entrynum) +void memory_set_bank(device_t &device, const char *tag, int entrynum) { // validation checks - memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag); + astring fulltag; + memory_bank *bank = device.machine().memory_data->bankmap.find_hash_only(device.subtag(fulltag, tag)); if (bank == NULL) - fatalerror("memory_set_bank called for unknown bank '%s'", tag); + fatalerror("memory_set_bank called for unknown bank '%s'", fulltag.cstr()); // set the base bank->set_entry(entrynum); @@ -1856,14 +1868,13 @@ void memory_set_bank(running_machine &machine, const char *tag, int entrynum) //------------------------------------------------- -// memory_set_bank - select one pre-configured -// entry to be the new bank base +// memory_get_bank - return the currently +// selected bank //------------------------------------------------- -void memory_set_bank(device_t *device, const char *tag, int entrynum) +int memory_get_bank(running_machine &machine, const char *tag) { - astring tempstring; - memory_set_bank(device->machine(), device->subtag(tempstring, tag), entrynum); + return memory_get_bank(machine.root_device(), tag); } @@ -1872,12 +1883,13 @@ void memory_set_bank(device_t *device, const char *tag, int entrynum) // selected bank //------------------------------------------------- -int memory_get_bank(running_machine &machine, const char *tag) +int memory_get_bank(device_t &device, const char *tag) { // validation checks - memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag); + astring fulltag; + memory_bank *bank = device.machine().memory_data->bankmap.find_hash_only(device.subtag(fulltag, tag)); if (bank == NULL) - fatalerror("memory_get_bank called for unknown bank '%s'", tag); + fatalerror("memory_get_bank called for unknown bank '%s'", fulltag.cstr()); // return the current entry return bank->entry(); @@ -1885,14 +1897,12 @@ int memory_get_bank(running_machine &machine, const char *tag) //------------------------------------------------- -// memory_get_bank - return the currently -// selected bank +// memory_set_bankptr - set the base of a bank //------------------------------------------------- -int memory_get_bank(device_t *device, const char *tag) +void memory_set_bankptr(running_machine &machine, const char *tag, void *base) { - astring tempstring; - return memory_get_bank(device->machine(), device->subtag(tempstring, tag)); + memory_set_bankptr(machine.root_device(), tag, base); } @@ -1900,12 +1910,13 @@ int memory_get_bank(device_t *device, const char *tag) // memory_set_bankptr - set the base of a bank //------------------------------------------------- -void memory_set_bankptr(running_machine &machine, const char *tag, void *base) +void memory_set_bankptr(device_t &device, const char *tag, void *base) { // validation checks - memory_bank *bank = machine.memory_data->bankmap.find_hash_only(tag); + astring fulltag; + memory_bank *bank = device.machine().memory_data->bankmap.find_hash_only(device.subtag(fulltag, tag)); if (bank == NULL) - throw emu_fatalerror("memory_set_bankptr called for unknown bank '%s'", tag); + throw emu_fatalerror("memory_set_bankptr called for unknown bank '%s'", fulltag.cstr()); // set the base bank->set_base(base); @@ -1913,17 +1924,6 @@ void memory_set_bankptr(running_machine &machine, const char *tag, void *base) //------------------------------------------------- -// memory_set_bankptr - set the base of a bank -//------------------------------------------------- - -void memory_set_bankptr(device_t *device, const char *tag, void *base) -{ - astring tempstring; - return memory_set_bankptr(device->machine(), device->subtag(tempstring, tag), base); -} - - -//------------------------------------------------- // memory_get_shared - get a pointer to a shared // memory region by tag //------------------------------------------------- @@ -1936,7 +1936,8 @@ void *memory_get_shared(running_machine &machine, const char *tag) void *memory_get_shared(running_machine &machine, const char *tag, size_t &length) { - memory_share *share = machine.memory_data->sharemap.find(tag); + astring fulltag; + memory_share *share = machine.memory_data->sharemap.find(machine.root_device().subtag(fulltag, tag)); if (share == NULL) return NULL; length = share->size(); @@ -2186,11 +2187,16 @@ void address_space::prepare_map() adjust_addresses(entry->m_bytestart, entry->m_byteend, entry->m_bytemask, entry->m_bytemirror); // if we have a share entry, add it to our map - if (entry->m_share != NULL && machine().memory_data->sharemap.find(entry->m_share) == NULL) + if (entry->m_share != NULL) { - VPRINTF(("Creating share '%s' of length 0x%X\n", entry->m_share, entry->m_byteend + 1 - entry->m_bytestart)); - memory_share *share = auto_alloc(machine(), memory_share(entry->m_byteend + 1 - entry->m_bytestart)); - machine().memory_data->sharemap.add(entry->m_share, share, false); + // if we can't find it, add it to our map + astring fulltag; + if (machine().memory_data->sharemap.find(device().siblingtag(fulltag, entry->m_share)) == NULL) + { + VPRINTF(("Creating share '%s' of length 0x%X\n", fulltag.cstr(), entry->m_byteend + 1 - entry->m_bytestart)); + memory_share *share = auto_alloc(machine(), memory_share(entry->m_byteend + 1 - entry->m_bytestart)); + machine().memory_data->sharemap.add(fulltag, share, false); + } } // if this is a ROM handler without a specified region, attach it to the implicit region @@ -2207,22 +2213,12 @@ void address_space::prepare_map() // validate adjusted addresses against implicit regions if (entry->m_region != NULL && entry->m_share == NULL && entry->m_baseptr == NULL) { - astring regiontag; + // determine full tag + astring fulltag; + device().siblingtag(fulltag, entry->m_region); - // a leading : on a region name indicates an absolute region, so fix up accordingly - if (entry->m_region[0] == ':') - { - regiontag = &entry->m_region[1]; - } - else - { - if (strchr(entry->m_region,':')) { - regiontag = entry->m_region; - } else { - m_device.siblingtag(regiontag, entry->m_region); - } - } - const memory_region *region = machine().region(regiontag.cstr()); + // find the region + const memory_region *region = machine().region(fulltag); if (region == NULL) fatalerror("Error: device '%s' %s space memory map entry %X-%X references non-existant region \"%s\"", m_device.tag(), m_name, entry->m_addrstart, entry->m_addrend, entry->m_region); @@ -2232,14 +2228,14 @@ void address_space::prepare_map() } // convert any region-relative entries to their memory pointers - if (entry->m_region != NULL) { - astring regiontag; - if (strchr(entry->m_region,':')) { - regiontag = entry->m_region; - } else { - m_device.siblingtag(regiontag, entry->m_region); - } - entry->m_memory = machine().region(regiontag.cstr())->base() + entry->m_rgnoffs; + if (entry->m_region != NULL) + { + // determine full tag + astring fulltag; + device().siblingtag(fulltag, entry->m_region); + + // set the memory address + entry->m_memory = machine().region(fulltag.cstr())->base() + entry->m_rgnoffs; } } @@ -2286,7 +2282,8 @@ void address_space::populate_from_map() void address_space::populate_map_entry(const address_map_entry &entry, read_or_write readorwrite) { const map_handler_data &data = (readorwrite == ROW_READ) ? entry.m_read : entry.m_write; - device_t *device; + device_t *target_device; + astring fulltag; // based on the handler type, alter the bits, name, funcptr, and object switch (data.m_type) @@ -2313,25 +2310,25 @@ void address_space::populate_map_entry(const address_map_entry &entry, read_or_w break; case AMH_DEVICE_DELEGATE: - device = machine().device(data.m_tag); - if (device == NULL) - throw emu_fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", data.m_tag, m_name, m_device.tag()); + target_device = device().siblingdevice(data.m_tag); + if (target_device == NULL) + throw emu_fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", data.m_tag.cstr(), m_name, m_device.tag()); if (readorwrite == ROW_READ) switch (data.m_bits) { - case 8: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read8_delegate(entry.m_rproto8, *device), data.m_mask); break; - case 16: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read16_delegate(entry.m_rproto16, *device), data.m_mask); break; - case 32: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read32_delegate(entry.m_rproto32, *device), data.m_mask); break; - case 64: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read64_delegate(entry.m_rproto64, *device), data.m_mask); break; + case 8: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read8_delegate(entry.m_rproto8, *target_device), data.m_mask); break; + case 16: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read16_delegate(entry.m_rproto16, *target_device), data.m_mask); break; + case 32: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read32_delegate(entry.m_rproto32, *target_device), data.m_mask); break; + case 64: install_read_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, read64_delegate(entry.m_rproto64, *target_device), data.m_mask); break; } else switch (data.m_bits) { - case 8: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write8_delegate(entry.m_wproto8, *device), data.m_mask); break; - case 16: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write16_delegate(entry.m_wproto16, *device), data.m_mask); break; - case 32: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write32_delegate(entry.m_wproto32, *device), data.m_mask); break; - case 64: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write64_delegate(entry.m_wproto64, *device), data.m_mask); break; + case 8: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write8_delegate(entry.m_wproto8, *target_device), data.m_mask); break; + case 16: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write16_delegate(entry.m_wproto16, *target_device), data.m_mask); break; + case 32: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write32_delegate(entry.m_wproto32, *target_device), data.m_mask); break; + case 64: install_write_handler(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, write64_delegate(entry.m_wproto64, *target_device), data.m_mask); break; } break; @@ -2355,42 +2352,42 @@ void address_space::populate_map_entry(const address_map_entry &entry, read_or_w break; case AMH_LEGACY_DEVICE_HANDLER: - device = machine().device(data.m_tag); - if (device == NULL) - fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", data.m_tag, m_name, m_device.tag()); + target_device = device().siblingdevice(data.m_tag); + if (target_device == NULL) + fatalerror("Attempted to map a non-existent device '%s' in space %s of device '%s'\n", data.m_tag.cstr(), m_name, m_device.tag()); if (readorwrite == ROW_READ) switch (data.m_bits) { - case 8: install_legacy_read_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice8, data.m_name, data.m_mask); break; - case 16: install_legacy_read_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice16, data.m_name, data.m_mask); break; - case 32: install_legacy_read_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice32, data.m_name, data.m_mask); break; - case 64: install_legacy_read_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice64, data.m_name, data.m_mask); break; + case 8: install_legacy_read_handler(*target_device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice8, data.m_name, data.m_mask); break; + case 16: install_legacy_read_handler(*target_device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice16, data.m_name, data.m_mask); break; + case 32: install_legacy_read_handler(*target_device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice32, data.m_name, data.m_mask); break; + case 64: install_legacy_read_handler(*target_device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_rdevice64, data.m_name, data.m_mask); break; } else switch (data.m_bits) { - case 8: install_legacy_write_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice8, data.m_name, data.m_mask); break; - case 16: install_legacy_write_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice16, data.m_name, data.m_mask); break; - case 32: install_legacy_write_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice32, data.m_name, data.m_mask); break; - case 64: install_legacy_write_handler(*device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice64, data.m_name, data.m_mask); break; + case 8: install_legacy_write_handler(*target_device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice8, data.m_name, data.m_mask); break; + case 16: install_legacy_write_handler(*target_device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice16, data.m_name, data.m_mask); break; + case 32: install_legacy_write_handler(*target_device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice32, data.m_name, data.m_mask); break; + case 64: install_legacy_write_handler(*target_device, entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, entry.m_wdevice64, data.m_name, data.m_mask); break; } break; case AMH_PORT: install_readwrite_port(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, - (readorwrite == ROW_READ) ? data.m_tag : NULL, - (readorwrite == ROW_WRITE) ? data.m_tag : NULL); + (readorwrite == ROW_READ) ? data.m_tag.cstr() : NULL, + (readorwrite == ROW_WRITE) ? data.m_tag.cstr() : NULL); break; case AMH_BANK: install_bank_generic(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror, - (readorwrite == ROW_READ) ? data.m_tag : NULL, - (readorwrite == ROW_WRITE) ? data.m_tag : NULL); + (readorwrite == ROW_READ) ? data.m_tag.cstr() : NULL, + (readorwrite == ROW_WRITE) ? data.m_tag.cstr() : NULL); break; case AMH_DEVICE_SUBMAP: - throw emu_fatalerror("Internal mapping error: leftover mapping of '%s'.\n", data.m_tag); + throw emu_fatalerror("Internal mapping error: leftover mapping of '%s'.\n", data.m_tag.cstr()); } } @@ -2478,13 +2475,13 @@ void address_space::locate_memory() if (entry->m_baseptr != NULL) *entry->m_baseptr = entry->m_memory; if (entry->m_baseptroffs_plus1 != 0) - *(void **)(reinterpret_cast<UINT8 *>(machine().driver_data<void>()) + entry->m_baseptroffs_plus1 - 1) = entry->m_memory; + *(void **)(reinterpret_cast<UINT8 *>(machine().driver_data()) + entry->m_baseptroffs_plus1 - 1) = entry->m_memory; if (entry->m_genbaseptroffs_plus1 != 0) *(void **)((UINT8 *)&machine().generic + entry->m_genbaseptroffs_plus1 - 1) = entry->m_memory; if (entry->m_sizeptr != NULL) *entry->m_sizeptr = entry->m_byteend - entry->m_bytestart + 1; if (entry->m_sizeptroffs_plus1 != 0) - *(size_t *)(reinterpret_cast<UINT8 *>(machine().driver_data<void>()) + entry->m_sizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1; + *(size_t *)(reinterpret_cast<UINT8 *>(machine().driver_data()) + entry->m_sizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1; if (entry->m_gensizeptroffs_plus1 != 0) *(size_t *)((UINT8 *)&machine().generic + entry->m_gensizeptroffs_plus1 - 1) = entry->m_byteend - entry->m_bytestart + 1; } @@ -2562,7 +2559,8 @@ address_map_entry *address_space::block_assign_intersecting(offs_t bytestart, of // if we haven't assigned this block yet, see if we have a mapped shared pointer for it if (entry->m_memory == NULL && entry->m_share != NULL) { - memory_share *share = memdata->sharemap.find(entry->m_share); + astring fulltag; + memory_share *share = memdata->sharemap.find(device().siblingtag(fulltag, entry->m_share)); if (share != NULL && share->ptr() != NULL) { entry->m_memory = share->ptr(); @@ -2584,7 +2582,8 @@ address_map_entry *address_space::block_assign_intersecting(offs_t bytestart, of // if we're the first match on a shared pointer, assign it now if (entry->m_memory != NULL && entry->m_share != NULL) { - memory_share *share = memdata->sharemap.find(entry->m_share); + astring fulltag; + memory_share *share = memdata->sharemap.find(device().siblingtag(fulltag, entry->m_share)); if (share != NULL && share->ptr() == NULL) { share->set_ptr(entry->m_memory); @@ -2685,7 +2684,9 @@ void address_space::install_readwrite_port(offs_t addrstart, offs_t addrend, off if (rtag != NULL) { // find the port - const input_port_config *port = machine().port(rtag); + astring fulltag; + device().siblingtag(fulltag, rtag); + const input_port_config *port = machine().port(fulltag); if (port == NULL) throw emu_fatalerror("Attempted to map non-existent port '%s' for read in space %s of device '%s'\n", rtag, m_name, m_device.tag()); @@ -2696,7 +2697,9 @@ void address_space::install_readwrite_port(offs_t addrstart, offs_t addrend, off if (wtag != NULL) { // find the port - const input_port_config *port = machine().port(wtag); + astring fulltag; + device().siblingtag(fulltag, wtag); + const input_port_config *port = machine().port(fulltag); if (port == NULL) fatalerror("Attempted to map non-existent port '%s' for write in space %s of device '%s'\n", wtag, m_name, m_device.tag()); @@ -2724,14 +2727,18 @@ void address_space::install_bank_generic(offs_t addrstart, offs_t addrend, offs_ // map the read bank if (rtag != NULL) { - memory_bank &bank = bank_find_or_allocate(rtag, addrstart, addrend, addrmask, addrmirror, ROW_READ); + astring fulltag; + device().siblingtag(fulltag, rtag); + memory_bank &bank = bank_find_or_allocate(fulltag, addrstart, addrend, addrmask, addrmirror, ROW_READ); read().map_range(addrstart, addrend, addrmask, addrmirror, bank.index()); } // map the write bank if (wtag != NULL) { - memory_bank &bank = bank_find_or_allocate(wtag, addrstart, addrend, addrmask, addrmirror, ROW_WRITE); + astring fulltag; + device().siblingtag(fulltag, wtag); + memory_bank &bank = bank_find_or_allocate(fulltag, addrstart, addrend, addrmask, addrmirror, ROW_WRITE); write().map_range(addrstart, addrend, addrmask, addrmirror, bank.index()); } @@ -3224,7 +3231,8 @@ bool address_space::needs_backing_store(const address_map_entry *entry) // if we are sharing, and we don't have a pointer yet, create one if (entry->m_share != NULL) { - memory_share *share = machine().memory_data->sharemap.find(entry->m_share); + astring fulltag; + memory_share *share = machine().memory_data->sharemap.find(device().siblingtag(fulltag, entry->m_share)); if (share != NULL && share->ptr() == NULL) return true; } diff --git a/src/emu/memory.h b/src/emu/memory.h index ec45c6fb342..717b77eeaf5 100644 --- a/src/emu/memory.h +++ b/src/emu/memory.h @@ -676,23 +676,23 @@ void memory_init(running_machine &machine); // configure the addresses for a bank void memory_configure_bank(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5); -void memory_configure_bank(device_t *device, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5); +void memory_configure_bank(device_t &device, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5); // configure the decrypted addresses for a bank void memory_configure_bank_decrypted(running_machine &machine, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5); -void memory_configure_bank_decrypted(device_t *device, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5); +void memory_configure_bank_decrypted(device_t &device, const char *tag, int startentry, int numentries, void *base, offs_t stride) ATTR_NONNULL(5); // select one pre-configured entry to be the new bank base void memory_set_bank(running_machine &machine, const char *tag, int entrynum); -void memory_set_bank(device_t *device, const char *tag, int entrynum); +void memory_set_bank(device_t &device, const char *tag, int entrynum); // return the currently selected bank int memory_get_bank(running_machine &machine, const char *tag); -int memory_get_bank(device_t *device, const char *tag); +int memory_get_bank(device_t &device, const char *tag); // set the absolute address of a bank base void memory_set_bankptr(running_machine &machine, const char *tag, void *base) ATTR_NONNULL(3); -void memory_set_bankptr(device_t *device, const char *tag, void *base) ATTR_NONNULL(3); +void memory_set_bankptr(device_t &device, const char *tag, void *base) ATTR_NONNULL(3); // get a pointer to a shared memory region by tag void *memory_get_shared(running_machine &machine, const char *tag); diff --git a/src/emu/network.c b/src/emu/network.c index cd44270c556..3da575835af 100644 --- a/src/emu/network.c +++ b/src/emu/network.c @@ -23,7 +23,6 @@ static void network_load(running_machine &machine, int config_type, xml_data_node *parentnode) { xml_data_node *node; - device_network_interface *network = NULL; if ((config_type == CONFIG_TYPE_GAME) && (parentnode != NULL)) { for (node = xml_get_sibling(parentnode->child, "device"); node; node = xml_get_sibling(node->next, "device")) @@ -32,7 +31,8 @@ static void network_load(running_machine &machine, int config_type, xml_data_nod if ((tag != NULL) && (tag[0] != '\0')) { - for (bool gotone = machine.devicelist().first(network); gotone; gotone = network->next(network)) + network_interface_iterator iter(machine.root_device()); + for (device_network_interface *network = iter.first(); network != NULL; network = iter.next()) { if (!strcmp(tag, network->device().tag())) { int interface = xml_get_attribute_int(node, "interface", 0); @@ -56,12 +56,12 @@ static void network_load(running_machine &machine, int config_type, xml_data_nod static void network_save(running_machine &machine, int config_type, xml_data_node *parentnode) { xml_data_node *node; - device_network_interface *network = NULL; /* only care about game-specific data */ if (config_type == CONFIG_TYPE_GAME) { - for (bool gotone = machine.devicelist().first(network); gotone; gotone = network->next(network)) + network_interface_iterator iter(machine.root_device()); + for (device_network_interface *network = iter.first(); network != NULL; network = iter.next()) { node = xml_add_child(parentnode, "device", NULL); if (node != NULL) diff --git a/src/emu/profiler.c b/src/emu/profiler.c index c4c6e49a4e1..71b8735c052 100644 --- a/src/emu/profiler.c +++ b/src/emu/profiler.c @@ -233,6 +233,7 @@ const char *real_profiler_state::text(running_machine &machine, astring &string) } // loop over all types and generate the string + device_iterator iter(machine.root_device()); for (curtype = PROFILER_DEVICE_FIRST; curtype < PROFILER_TOTAL; curtype++) { // determine the accumulated time for this type @@ -252,7 +253,7 @@ const char *real_profiler_state::text(running_machine &machine, astring &string) // and then the text if (curtype >= PROFILER_DEVICE_FIRST && curtype <= PROFILER_DEVICE_MAX) - string.catprintf("'%s'", machine.devicelist().find(curtype - PROFILER_DEVICE_FIRST)->tag()); + string.catprintf("'%s'", iter.byindex(curtype - PROFILER_DEVICE_FIRST)->tag()); else for (int nameindex = 0; nameindex < ARRAY_LENGTH(names); nameindex++) if (names[nameindex].type == curtype) diff --git a/src/emu/render.c b/src/emu/render.c index 0975c03f036..7f971618b25 100644 --- a/src/emu/render.c +++ b/src/emu/render.c @@ -1120,17 +1120,15 @@ int render_target::configured_view(const char *viewname, int targetindex, int nu } // if we don't have a match, default to the nth view - int scrcount = m_manager.machine().devicelist().count(SCREEN); + screen_device_iterator iter(m_manager.machine().root_device()); + int scrcount = iter.count(); if (view == NULL && scrcount > 0) { // if we have enough targets to be one per screen, assign in order if (numtargets >= scrcount) { int ourindex = index() % scrcount; - screen_device *screen; - for (screen = m_manager.machine().first_screen(); screen != NULL; screen = screen->next_screen()) - if (ourindex-- == 0) - break; + screen_device *screen = iter.byindex(ourindex); // find the first view with this screen and this screen only for (view = view_by_index(viewindex = 0); view != NULL; view = view_by_index(++viewindex)) @@ -1157,7 +1155,7 @@ int render_target::configured_view(const char *viewname, int targetindex, int nu if (viewscreens.count() >= scrcount) { screen_device *screen; - for (screen = m_manager.machine().first_screen(); screen != NULL; screen = screen->next_screen()) + for (screen = iter.first(); screen != NULL; screen = iter.next()) if (!viewscreens.contains(*screen)) break; if (screen == NULL) @@ -1576,7 +1574,8 @@ void render_target::load_layout_files(const char *layoutfile, bool singlefile) else have_default |= true; } - int screens = m_manager.machine().devicelist().count(SCREEN); + screen_device_iterator iter(m_manager.machine().root_device()); + int screens = iter.count(); // now do the built-in layouts for single-screen games if (screens == 1) { @@ -2432,7 +2431,8 @@ render_manager::render_manager(running_machine &machine) config_register(machine, "video", config_saveload_delegate(FUNC(render_manager::config_load), this), config_saveload_delegate(FUNC(render_manager::config_save), this)); // create one container per screen - for (screen_device *screen = machine.first_screen(); screen != NULL; screen = screen->next_screen()) + screen_device_iterator iter(machine.root_device()); + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) screen->set_container(*container_alloc(screen)); } diff --git a/src/emu/rendlay.c b/src/emu/rendlay.c index 64db4b26c36..7bad91878dc 100644 --- a/src/emu/rendlay.c +++ b/src/emu/rendlay.c @@ -203,10 +203,10 @@ static int get_variable_value(running_machine &machine, const char *string, char char temp[100]; // screen 0 parameters - for (const screen_device *device = machine.first_screen(); device != NULL; device = device->next_screen()) + screen_device_iterator iter(machine.root_device()); + int scrnum = 0; + for (const screen_device *device = iter.first(); device != NULL; device = iter.next(), scrnum++) { - int scrnum = machine.devicelist().indexof(SCREEN, device->tag()); - // native X aspect factor sprintf(temp, "~scr%dnativexaspect~", scrnum); if (!strncmp(string, temp, strlen(temp))) @@ -1863,7 +1863,10 @@ layout_view::item::item(running_machine &machine, xml_data_node &itemnode, simpl // fetch common data int index = xml_get_attribute_int_with_subst(machine, itemnode, "index", -1); if (index != -1) - m_screen = downcast<screen_device *>(machine.devicelist().find(SCREEN, index)); + { + screen_device_iterator iter(machine.root_device()); + m_screen = iter.byindex(index); + } m_input_mask = xml_get_attribute_int_with_subst(machine, itemnode, "inputmask", 0); if (m_output_name[0] != 0 && m_element != NULL) output_set_value(m_output_name, m_element->default_state()); diff --git a/src/emu/romload.c b/src/emu/romload.c index b350e8d6d54..9289d692189 100644 --- a/src/emu/romload.c +++ b/src/emu/romload.c @@ -188,7 +188,8 @@ void set_disk_handle(running_machine &machine, const char *region, emu_file &fil const rom_source *rom_first_source(const machine_config &config) { /* look through devices */ - for (const device_t *device = config.devicelist().first(); device != NULL; device = device->next()) + device_iterator iter(config.root_device()); + for (const device_t *device = iter.first(); device != NULL; device = iter.next()) if (device->rom_region() != NULL) return device; @@ -204,9 +205,16 @@ const rom_source *rom_first_source(const machine_config &config) const rom_source *rom_next_source(const rom_source &previous) { /* look for further devices with ROM definitions */ - for (const device_t *device = previous.next(); device != NULL; device = device->next()) +// fixme: this is awful + device_iterator iter(previous.mconfig().root_device()); + const device_t *device; + for (device = iter.first(); device != NULL; device = iter.next()) + if (device == &previous) + break; + + for (device = iter.next(); device != NULL; device = iter.next()) if (device->rom_region() != NULL) - return (rom_source *)device; + return device; return NULL; } @@ -273,7 +281,7 @@ const rom_entry *rom_next_file(const rom_entry *romp) astring &rom_region_name(astring &result, const game_driver *drv, const rom_source *source, const rom_entry *romp) { - return source->subtag(result, ROMREGION_GETTAG(romp)); + return source->subtag(result, ROM_GETNAME(romp)); } diff --git a/src/emu/schedule.c b/src/emu/schedule.c index 614ed8bdacb..741ae074896 100644 --- a/src/emu/schedule.c +++ b/src/emu/schedule.c @@ -788,8 +788,8 @@ void device_scheduler::rebuild_execute_list() device_execute_interface **suspend_tailptr = &suspend_list; // iterate over all devices - device_execute_interface *exec = NULL; - for (bool gotone = machine().devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator iter(machine().root_device()); + for (device_execute_interface *exec = iter.first(); exec != NULL; exec = iter.next()) { // append to the appropriate list exec->m_nextexec = NULL; diff --git a/src/emu/screen.c b/src/emu/screen.c index 4bd2b8ebc39..aab40d9fced 100644 --- a/src/emu/screen.c +++ b/src/emu/screen.c @@ -244,42 +244,26 @@ void screen_device::static_set_screen_vblank(device_t &device, screen_vblank_del // configuration //------------------------------------------------- -bool screen_device::device_validity_check(emu_options &options, const game_driver &driver) const +void screen_device::device_validity_check(validity_checker &valid) const { - bool error = false; - // sanity check dimensions if (m_width <= 0 || m_height <= 0) - { - mame_printf_error("%s: %s screen '%s' has invalid display dimensions\n", driver.source_file, driver.name, tag()); - error = true; - } + mame_printf_error("Invalid display dimensions\n"); // sanity check display area if (m_type != SCREEN_TYPE_VECTOR) { if (m_visarea.empty() || m_visarea.max_x >= m_width || m_visarea.max_y >= m_height) - { - mame_printf_error("%s: %s screen '%s' has an invalid display area\n", driver.source_file, driver.name, tag()); - error = true; - } + mame_printf_error("Invalid display area\n"); // sanity check screen formats if (m_screen_update_ind16.isnull() && m_screen_update_rgb32.isnull()) - { - mame_printf_error("%s: %s screen '%s' has no SCREEN_UPDATE function\n", driver.source_file, driver.name, tag()); - error = true; - } + mame_printf_error("Missing SCREEN_UPDATE function\n"); } // check for zero frame rate if (m_refresh == 0) - { - mame_printf_error("%s: %s screen '%s' has a zero refresh rate\n", driver.source_file, driver.name, tag()); - error = true; - } - - return error; + mame_printf_error("Invalid (zero) refresh rate\n"); } diff --git a/src/emu/screen.h b/src/emu/screen.h index e9f496e11ba..aeb927f8143 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -192,7 +192,6 @@ public: static void static_set_screen_vblank(device_t &device, screen_vblank_delegate callback); // information getters - screen_device *next_screen() const { return downcast<screen_device *>(typenext()); } render_container &container() const { assert(m_container != NULL); return *m_container; } // dynamic configuration @@ -244,7 +243,7 @@ private: }; // device-level overrides - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_stop(); virtual void device_post_load(); @@ -334,6 +333,9 @@ private: // device type definition extern const device_type SCREEN; +// iterator helper +typedef device_type_iterator<&device_creator<screen_device>, screen_device> screen_device_iterator; + //************************************************************************** diff --git a/src/emu/softlist.c b/src/emu/softlist.c index 1bb5dd3dc2d..c3470d897c2 100644 --- a/src/emu/softlist.c +++ b/src/emu/softlist.c @@ -17,6 +17,63 @@ typedef tagmap_t<software_info *> softlist_map; + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +tagmap_t<UINT8> software_list_device::s_checked_lists; + +// device type definition +const device_type SOFTWARE_LIST = &device_creator<software_list_device>; + +//------------------------------------------------- +// software_list_device - constructor +//------------------------------------------------- + +software_list_device::software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, SOFTWARE_LIST, "Software lists", tag, owner, clock), + m_list_name(NULL), + m_list_type(SOFTWARE_LIST_ORIGINAL_SYSTEM), + m_filter(NULL) +{ +} + + +//------------------------------------------------- +// static_set_interface - configuration helper +// to set the interface +//------------------------------------------------- + +void software_list_device::static_set_config(device_t &device, const char *list, softlist_type list_type) +{ + software_list_device &softlist = downcast<software_list_device &>(device); + softlist.m_list_name = list; + softlist.m_list_type = list_type; +} + + +//------------------------------------------------- +// static_set_custom_handler - configuration +// helper to set a custom callback +//------------------------------------------------- + +void software_list_device::static_set_filter(device_t &device, const char *filter) +{ + downcast<software_list_device &>(device).m_filter = filter; +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void software_list_device::device_start() +{ +} + + + /*************************************************************************** EXPAT INTERFACES ***************************************************************************/ @@ -1216,7 +1273,7 @@ static int softlist_penalty_compare(const char *source, const char *target) software_list_find_approx_matches -------------------------------------------------*/ -void software_list_find_approx_matches(software_list_config *swlistcfg, software_list *swlist, const char *name, int matches, software_info **list, const char* interface) +void software_list_find_approx_matches(software_list_device *swlistdev, software_list *swlist, const char *name, int matches, software_info **list, const char* interface) { #undef rand @@ -1243,7 +1300,7 @@ void software_list_find_approx_matches(software_list_config *swlistcfg, software software_info *candidate = swinfo; software_part *part = software_find_part(swinfo, NULL, NULL); - if ((interface==NULL || !strcmp(interface, part->interface_)) && (is_software_compatible(part, swlistcfg))) + if ((interface==NULL || !strcmp(interface, part->interface_)) && (is_software_compatible(part, swlistdev))) { /* pick the best match between driver name and description */ @@ -1442,19 +1499,19 @@ software_part *software_part_next(software_part *part) software_display_matches -------------------------------------------------*/ -void software_display_matches(const device_list &devlist,emu_options &options, const char *interface ,const char *name) +void software_display_matches(const machine_config &config,emu_options &options, const char *interface ,const char *name) { // check if there is at least a software list - if (devlist.first(SOFTWARE_LIST)) + software_list_device_iterator deviter(config.root_device()); + if (deviter.first()) { mame_printf_error("\n\"%s\" approximately matches the following\n" "supported software items (best match first):\n\n", name); } - for (device_t *swlists = devlist.first(SOFTWARE_LIST); swlists != NULL; swlists = swlists->typenext()) + for (software_list_device *swlist = deviter.first(); swlist != NULL; swlist = deviter.next()) { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(swlists)->inline_config(); - software_list *list = software_list_open(options, swlist->list_name, FALSE, NULL); + software_list *list = software_list_open(options, swlist->list_name(), FALSE, NULL); if (list) { @@ -1467,10 +1524,10 @@ void software_display_matches(const device_list &devlist,emu_options &options, c if (matches[0] != 0) { - if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) - mame_printf_error("* Software list \"%s\" (%s) matches: \n", swlist->list_name, software_list_get_description(list)); + if (swlist->list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) + mame_printf_error("* Software list \"%s\" (%s) matches: \n", swlist->list_name(), software_list_get_description(list)); else - mame_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlist->list_name, software_list_get_description(list)); + mame_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlist->list_name(), software_list_get_description(list)); // print them out for (softnum = 0; softnum < ARRAY_LENGTH(matches); softnum++) @@ -1484,7 +1541,7 @@ void software_display_matches(const device_list &devlist,emu_options &options, c } } -static void find_software_item(const device_list &devlist, emu_options &options, const device_image_interface *image, const char *path, software_list **software_list_ptr, software_info **software_info_ptr,software_part **software_part_ptr, const char **sw_list_name) +static void find_software_item(const machine_config &config, emu_options &options, const device_image_interface *image, const char *path, software_list **software_list_ptr, software_info **software_info_ptr,software_part **software_part_ptr, const char **sw_list_name) { char *swlist_name, *swname, *swpart; //, *swname_bckp; *software_list_ptr = NULL; @@ -1516,33 +1573,28 @@ static void find_software_item(const device_list &devlist, emu_options &options, else { /* Loop through all the software lists named in the driver */ - for (device_t *swlists = devlist.first(SOFTWARE_LIST); swlists != NULL; swlists = swlists->typenext()) + software_list_device_iterator deviter(config.root_device()); + for (software_list_device *swlist = deviter.first(); swlist != NULL; swlist = deviter.next()) { - if ( swlists ) - { + const char *swlist_name = swlist->list_name(); - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(swlists)->inline_config(); + if (swlist->list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) + { + if ( *software_list_ptr ) + { + software_list_close( *software_list_ptr ); + } - swlist_name = swlist->list_name; + *software_list_ptr = software_list_open( options, swlist_name, FALSE, NULL ); - if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) + if ( software_list_ptr ) { - if ( *software_list_ptr ) - { - software_list_close( *software_list_ptr ); - } + *software_info_ptr = software_list_find( *software_list_ptr, swname, NULL ); - *software_list_ptr = software_list_open( options, swlist_name, FALSE, NULL ); - - if ( software_list_ptr ) + if ( *software_info_ptr ) { - *software_info_ptr = software_list_find( *software_list_ptr, swname, NULL ); - - if ( *software_info_ptr ) - { - *software_part_ptr = software_find_part( *software_info_ptr, swpart, interface ); - if (*software_part_ptr) break; - } + *software_part_ptr = software_find_part( *software_info_ptr, swpart, interface ); + if (*software_part_ptr) break; } } } @@ -1634,12 +1686,12 @@ bool load_software_part(emu_options &options, device_image_interface *image, con *sw_info = NULL; *sw_part = NULL; - find_software_item(image->device().machine().devicelist(), options, image, path, &software_list_ptr, &software_info_ptr, &software_part_ptr, &swlist_name); + find_software_item(image->device().machine().config(), options, image, path, &software_list_ptr, &software_info_ptr, &software_part_ptr, &swlist_name); // if no match has been found, we suggest similar shortnames if (software_info_ptr == NULL) { - software_display_matches(image->device().machine().devicelist(),image->device().machine().options(), image->image_interface(), path); + software_display_matches(image->device().machine().config(),image->device().machine().options(), image->image_interface(), path); } if ( software_part_ptr ) @@ -1704,12 +1756,12 @@ bool load_software_part(emu_options &options, device_image_interface *image, con *full_sw_name = auto_alloc_array( image->device().machine(), char, strlen(swlist_name) + strlen(software_info_ptr->shortname) + strlen(software_part_ptr->name) + 3 ); sprintf( *full_sw_name, "%s:%s:%s", swlist_name, software_info_ptr->shortname, software_part_ptr->name ); - for (device_t *swlists = image->device().machine().devicelist().first(SOFTWARE_LIST); swlists != NULL; swlists = swlists->typenext()) + software_list_device_iterator iter(image->device().machine().root_device()); + for (software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(swlists)->inline_config(); - if (strcmp(swlist->list_name,swlist_name)==0) { + if (strcmp(swlist->list_name(),swlist_name)==0) { if (!is_software_compatible(software_part_ptr, swlist)) { - mame_printf_warning("WARNING! the set %s might not work on this system due to missing filter(s) '%s'\n",software_info_ptr->shortname,swlist->filter); + mame_printf_warning("WARNING! the set %s might not work on this system due to missing filter(s) '%s'\n",software_info_ptr->shortname,swlist->filter()); } break; } @@ -1723,12 +1775,12 @@ bool load_software_part(emu_options &options, device_image_interface *image, con software_part *req_software_part_ptr = NULL; const char *req_swlist_name = NULL; - find_software_item(image->device().machine().devicelist(), options, NULL, requirement, &req_software_list_ptr, &req_software_info_ptr, &req_software_part_ptr, &req_swlist_name); + find_software_item(image->device().machine().config(), options, NULL, requirement, &req_software_list_ptr, &req_software_info_ptr, &req_software_part_ptr, &req_swlist_name); if ( req_software_list_ptr ) { - device_image_interface *req_image = NULL; - for (bool gotone = image->device().machine().devicelist().first(req_image); gotone; gotone = req_image->next(req_image)) + image_interface_iterator imgiter(image->device().machine().root_device()); + for (device_image_interface *req_image = imgiter.first(); req_image != NULL; req_image = imgiter.next()) { const char *interface = req_image->image_interface(); if (interface != NULL) @@ -1791,7 +1843,7 @@ const char *software_part_get_feature(const software_part *part, const char *fea software_get_default_slot -------------------------------------------------*/ - const char *software_get_default_slot(const device_list &devlist, emu_options &options, const device_image_interface *image, const char* default_card_slot) + const char *software_get_default_slot(const machine_config &config, emu_options &options, const device_image_interface *image, const char* default_card_slot) { const char* retVal = NULL; const char* path = options.value(image->instance_name()); @@ -1802,7 +1854,7 @@ const char *software_part_get_feature(const software_part *part, const char *fea if (strlen(path)>0) { retVal = default_card_slot; - find_software_item(devlist, options, image, path, &software_list_ptr, &software_info_ptr, &software_part_ptr, &swlist_name); + find_software_item(config, options, image, path, &software_list_ptr, &software_info_ptr, &software_part_ptr, &swlist_name); if (software_part_ptr!=NULL) { const char *slot = software_part_get_feature(software_part_ptr, "slot"); if (slot!=NULL) { @@ -1819,10 +1871,10 @@ const char *software_part_get_feature(const software_part *part, const char *fea is_software_compatible -------------------------------------------------*/ -bool is_software_compatible(const software_part *swpart, const software_list_config *swlist) +bool is_software_compatible(const software_part *swpart, const software_list_device *swlist) { const char *compatibility = software_part_get_feature(swpart, "compatibility"); - const char *filter = swlist->filter; + const char *filter = swlist->filter(); if ((compatibility==NULL) || (filter==NULL)) return TRUE; astring comp = astring(compatibility,","); char *filt = core_strdup(filter); @@ -1856,229 +1908,138 @@ bool swinfo_has_multiple_parts(const software_info *swinfo, const char *interfac ***************************************************************************/ -static DEVICE_START( software_list ) -{ -} - void validate_error_proc(const char *message) { - mame_printf_error("%s",message); + mame_printf_error("%s", message); } -void validate_softlists(emu_options &options) +void software_list_device::device_validity_check(validity_checker &valid) const { - driver_enumerator drivlist(options); - // first determine the maximum number of lists we might encounter - int list_count = 0; - while (drivlist.next()) - for (const device_t *dev = drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) - { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config(); + // add to the global map whenever we check a list so we don't re-check + // it in the future + if (s_checked_lists.add(m_list_name, 1, false) == TMERR_DUPLICATE) + return; - if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) - list_count++; - } + softlist_map names; + softlist_map descriptions; - // allocate a list - astring *lists = global_alloc_array(astring, list_count); - bool error = FALSE; - if (list_count) + enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 }; + + software_list *list = software_list_open(mconfig().options(), m_list_name, FALSE, NULL); + if ( list ) { - drivlist.reset(); - list_count = 0; - while (drivlist.next()) - for (const device_t *dev = drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) + software_list_parse( list, &validate_error_proc, NULL ); + + for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) { - software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config(); - softlist_map names; - softlist_map descriptions; + const char *s; + int is_clone = 0; - enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 }; + /* First, check if the xml got corrupted: */ - software_list *list = software_list_open(options, swlist->list_name, FALSE, NULL); - if ( list ) + /* Did we lost any description? */ + if (swinfo->longname == NULL) { - /* Verify if we have encountered this list before */ - bool seen_before = false; - for (int seen_index = 0; seen_index < list_count && !seen_before; seen_index++) - if (lists[seen_index] == swlist->list_name) - seen_before = true; + mame_printf_error("%s: %s has no description\n", list->file->filename(), swinfo->shortname); + break; + } - if (!seen_before) - { - lists[list_count++] = swlist->list_name; - software_list_parse( list, &validate_error_proc, NULL ); + /* Did we lost any year? */ + if (swinfo->year == NULL) + { + mame_printf_error("%s: %s has no year\n", list->file->filename(), swinfo->shortname); + break; + } - for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo)) - { - const char *s; - int is_clone = 0; + /* Did we lost any publisher? */ + if (swinfo->publisher == NULL) + { + mame_printf_error("%s: %s has no publisher\n", list->file->filename(), swinfo->shortname); + break; + } - /* First, check if the xml got corrupted: */ + /* Second, since the xml is fine, run additional checks: */ - /* Did we lost any description? */ - if (swinfo->longname == NULL) - { - mame_printf_error("%s: %s has no description\n", list->file->filename(), swinfo->shortname); - error = TRUE; break; - } + /* check for duplicate names */ + if (names.add(swinfo->shortname, swinfo, FALSE) == TMERR_DUPLICATE) + { + software_info *match = names.find(swinfo->shortname); + mame_printf_error("%s: %s is a duplicate name (%s)\n", list->file->filename(), swinfo->shortname, match->shortname); + } - /* Did we lost any year? */ - if (swinfo->year == NULL) - { - mame_printf_error("%s: %s has no year\n", list->file->filename(), swinfo->shortname); - error = TRUE; break; - } + /* check for duplicate descriptions */ + if (descriptions.add(astring(swinfo->longname).makelower().cstr(), swinfo, FALSE) == TMERR_DUPLICATE) + mame_printf_error("%s: %s is a duplicate description (%s)\n", list->file->filename(), swinfo->longname, swinfo->shortname); - /* Did we lost any publisher? */ - if (swinfo->publisher == NULL) - { - mame_printf_error("%s: %s has no publisher\n", list->file->filename(), swinfo->shortname); - error = TRUE; break; - } + if (swinfo->parentname != NULL) + { + is_clone = 1; - /* Second, since the xml is fine, run additional checks: */ + if (strcmp(swinfo->parentname, swinfo->shortname) == 0) + { + mame_printf_error("%s: %s is set as a clone of itself\n", list->file->filename(), swinfo->shortname); + break; + } - /* check for duplicate names */ - if (names.add(swinfo->shortname, swinfo, FALSE) == TMERR_DUPLICATE) - { - software_info *match = names.find(swinfo->shortname); - mame_printf_error("%s: %s is a duplicate name (%s)\n", list->file->filename(), swinfo->shortname, match->shortname); - error = TRUE; - } + /* make sure the parent exists */ + software_info *swinfo2 = software_list_find(list, swinfo->parentname, NULL ); - /* check for duplicate descriptions */ - if (descriptions.add(astring(swinfo->longname).makelower().cstr(), swinfo, FALSE) == TMERR_DUPLICATE) - { - mame_printf_error("%s: %s is a duplicate description (%s)\n", list->file->filename(), swinfo->longname, swinfo->shortname); - error = TRUE; - } + if (!swinfo2) + mame_printf_error("%s: parent '%s' software for '%s' not found\n", list->file->filename(), swinfo->parentname, swinfo->shortname); + else if (swinfo2->parentname != NULL) + mame_printf_error("%s: %s is a clone of a clone\n", list->file->filename(), swinfo->shortname); + } - if (swinfo->parentname != NULL) - { - is_clone = 1; + /* make sure the driver name is 8 chars or less */ + if ((is_clone && strlen(swinfo->shortname) > NAME_LEN_CLONE) || ((!is_clone) && strlen(swinfo->shortname) > NAME_LEN_PARENT)) + mame_printf_error("%s: %s %s driver name must be %d characters or less\n", list->file->filename(), swinfo->shortname, + is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT); - if (strcmp(swinfo->parentname, swinfo->shortname) == 0) - { - mame_printf_error("%s: %s is set as a clone of itself\n", list->file->filename(), swinfo->shortname); - error = TRUE; - break; - } + /* make sure the year is only digits, '?' or '+' */ + for (s = swinfo->year; *s; s++) + if (!isdigit((UINT8)*s) && *s != '?' && *s != '+') + { + mame_printf_error("%s: %s has an invalid year '%s'\n", list->file->filename(), swinfo->shortname, swinfo->year); + break; + } - /* make sure the parent exists */ - software_info *swinfo2 = software_list_find(list, swinfo->parentname, NULL ); + softlist_map part_names; - if (!swinfo2) - { - mame_printf_error("%s: parent '%s' software for '%s' not found\n", list->file->filename(), swinfo->parentname, swinfo->shortname); - error = TRUE; - } - else - { - if (swinfo2->parentname != NULL) - { - mame_printf_error("%s: %s is a clone of a clone\n", list->file->filename(), swinfo->shortname); - error = TRUE; - } - } - } - - /* make sure the driver name is 8 chars or less */ - if ((is_clone && strlen(swinfo->shortname) > NAME_LEN_CLONE) || ((!is_clone) && strlen(swinfo->shortname) > NAME_LEN_PARENT)) - { - mame_printf_error("%s: %s %s driver name must be %d characters or less\n", list->file->filename(), swinfo->shortname, - is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT); - error = TRUE; - } + for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) + { + if (swpart->interface_ == NULL) + mame_printf_error("%s: %s has a part (%s) without interface\n", list->file->filename(), swinfo->shortname, swpart->name); - /* make sure the year is only digits, '?' or '+' */ - for (s = swinfo->year; *s; s++) - if (!isdigit((UINT8)*s) && *s != '?' && *s != '+') - { - mame_printf_error("%s: %s has an invalid year '%s'\n", list->file->filename(), swinfo->shortname, swinfo->year); - error = TRUE; - break; - } + if (software_find_romdata(swpart, NULL) == NULL) + mame_printf_error("%s: %s has a part (%s) with no data\n", list->file->filename(), swinfo->shortname, swpart->name); - softlist_map part_names; + if (part_names.add(swpart->name, swinfo, FALSE) == TMERR_DUPLICATE) + mame_printf_error("%s: %s has a part (%s) whose name is duplicate\n", list->file->filename(), swinfo->shortname, swpart->name); - for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart)) - { - if (swpart->interface_ == NULL) - { - mame_printf_error("%s: %s has a part (%s) without interface\n", list->file->filename(), swinfo->shortname, swpart->name); - error = TRUE; - } + for (struct rom_entry *swdata = software_find_romdata(swpart, NULL); swdata != NULL; swdata = software_romdata_next(swdata)) + { + struct rom_entry *data = swdata; - if (software_find_romdata(swpart, NULL) == NULL) - { - mame_printf_error("%s: %s has a part (%s) with no data\n", list->file->filename(), swinfo->shortname, swpart->name); - error = TRUE; - } + if (data->_name && data->_hashdata) + { + const char *str; - if (part_names.add(swpart->name, swinfo, FALSE) == TMERR_DUPLICATE) + /* make sure it's all lowercase */ + for (str = data->_name; *str; str++) + if (tolower((UINT8)*str) != *str) { - mame_printf_error("%s: %s has a part (%s) whose name is duplicate\n", list->file->filename(), swinfo->shortname, swpart->name); - error = TRUE; + mame_printf_error("%s: %s has upper case ROM name %s\n", list->file->filename(), swinfo->shortname, data->_name); + break; } - for (struct rom_entry *swdata = software_find_romdata(swpart, NULL); swdata != NULL; swdata = software_romdata_next(swdata)) - { - struct rom_entry *data = swdata; - - if (data->_name && data->_hashdata) - { - const char *str; - - /* make sure it's all lowercase */ - for (str = data->_name; *str; str++) - if (tolower((UINT8)*str) != *str) - { - mame_printf_error("%s: %s has upper case ROM name %s\n", list->file->filename(), swinfo->shortname, data->_name); - error = TRUE; - break; - } - - /* make sure the hash is valid */ - hash_collection hashes; - if (!hashes.from_internal_string(data->_hashdata)) - { - mame_printf_error("%s: %s has rom '%s' with an invalid hash string '%s'\n", list->file->filename(), swinfo->shortname, data->_name, data->_hashdata); - error = TRUE; - } - } - } - } + /* make sure the hash is valid */ + hash_collection hashes; + if (!hashes.from_internal_string(data->_hashdata)) + mame_printf_error("%s: %s has rom '%s' with an invalid hash string '%s'\n", list->file->filename(), swinfo->shortname, data->_name, data->_hashdata); } } - software_list_close(list); } } + software_list_close(list); } - if (error) - throw emu_fatalerror(MAMERR_FAILED_VALIDITY, "Validity checks failed"); } - -DEVICE_GET_INFO( software_list ) -{ - switch (state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_INT_TOKEN_BYTES: info->i = 1; break; - case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(software_list_config); break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( software_list ); break; - case DEVINFO_FCT_STOP: /* Nothing */ break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "Software lists"); break; - case DEVINFO_STR_FAMILY: strcpy(info->s, "Software lists"); break; - case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; - case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; - case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break; - } -} - - -DEFINE_LEGACY_DEVICE(SOFTWARE_LIST, software_list); diff --git a/src/emu/softlist.h b/src/emu/softlist.h index 9983bcc68d6..6c8b5af041e 100644 --- a/src/emu/softlist.h +++ b/src/emu/softlist.h @@ -14,6 +14,84 @@ #include "pool.h" + +#define SOFTWARE_SUPPORTED_YES 0 +#define SOFTWARE_SUPPORTED_PARTIAL 1 +#define SOFTWARE_SUPPORTED_NO 2 + +enum softlist_type +{ + SOFTWARE_LIST_ORIGINAL_SYSTEM, + SOFTWARE_LIST_COMPATIBLE_SYSTEM +}; + +#define MCFG_SOFTWARE_LIST_CONFIG(_list,_list_type) \ + software_list_device::static_set_config(*device, _list, _list_type); + +#define MCFG_SOFTWARE_LIST_ADD( _tag, _list ) \ + MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \ + MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM) + +#define MCFG_SOFTWARE_LIST_COMPATIBLE_ADD( _tag, _list ) \ + MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \ + MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM) + +#define MCFG_SOFTWARE_LIST_MODIFY( _tag, _list ) \ + MCFG_DEVICE_MODIFY( _tag ) \ + MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM) + +#define MCFG_SOFTWARE_LIST_COMPATIBLE_MODIFY( _tag, _list ) \ + MCFG_DEVICE_MODIFY( _tag ) \ + MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM) + +#define MCFG_SOFTWARE_LIST_FILTER( _tag, _filter ) \ + MCFG_DEVICE_MODIFY( _tag ) \ + software_list_device::static_set_filter(*device, _filter); + + +// ======================> software_list_device + +class software_list_device : public device_t +{ +public: + // construction/destruction + software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // inline configuration helpers + static void static_set_config(device_t &device, const char *list, softlist_type list_type); + static void static_set_filter(device_t &device, const char *filter); + + // getters + const char *list_name() const { return m_list_name; } + softlist_type list_type() const { return m_list_type; } + const char *filter() const { return m_filter; } + + // validation helpers + static void reset_checked_lists() { s_checked_lists.reset(); } + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_validity_check(validity_checker &valid) const ATTR_COLD; + + // configuration state + const char * m_list_name; + softlist_type m_list_type; + const char * m_filter; + + // static state + static tagmap_t<UINT8> s_checked_lists; +}; + + +// device type definition +extern const device_type SOFTWARE_LIST; + +// device type iterator +typedef device_type_iterator<&device_creator<software_list_device>, software_list_device> software_list_device_iterator; + + + /********************************************************************* Internal structures and XML file handling @@ -95,13 +173,6 @@ struct software_list int list_entries; }; -struct software_list_config -{ - char *list_name; - UINT32 list_type; - const char *filter; -}; - /* Handling a software list */ software_list *software_list_open(emu_options &options, const char *listname, int is_preload, void (*error_proc)(const char *message)); void software_list_close(const software_list *swlist); @@ -123,53 +194,11 @@ const char *software_part_get_feature(const software_part *part, const char *fea bool load_software_part(emu_options &options, device_image_interface *image, const char *path, software_info **sw_info, software_part **sw_part, char **full_sw_name); -void software_display_matches(const device_list &devlist, emu_options &options,const char *interface,const char *swname_bckp); +void software_display_matches(const machine_config &config, emu_options &options,const char *interface,const char *swname_bckp); -const char *software_get_default_slot(const device_list &devlist, emu_options &options, const device_image_interface *image, const char* default_card_slot); +const char *software_get_default_slot(const machine_config &config, emu_options &options, const device_image_interface *image, const char* default_card_slot); -void validate_softlists(emu_options &options); - -bool is_software_compatible(const software_part *swpart, const software_list_config *swlist); +bool is_software_compatible(const software_part *swpart, const software_list_device *swlist); bool swinfo_has_multiple_parts(const software_info *swinfo, const char *interface); -/********************************************************************* - - Driver software list configuration - -*********************************************************************/ -DECLARE_LEGACY_DEVICE(SOFTWARE_LIST, software_list); - -#define SOFTWARE_SUPPORTED_YES 0 -#define SOFTWARE_SUPPORTED_PARTIAL 1 -#define SOFTWARE_SUPPORTED_NO 2 - -#define SOFTWARE_LIST_ORIGINAL_SYSTEM 0 -#define SOFTWARE_LIST_COMPATIBLE_SYSTEM 1 - -#define MCFG_SOFTWARE_LIST_CONFIG(_list,_list_type) \ - MCFG_DEVICE_CONFIG_DATAPTR(software_list_config, list_name, _list) \ - MCFG_DEVICE_CONFIG_DATA32(software_list_config, list_type, _list_type) - -#define MCFG_SOFTWARE_LIST_ADD( _tag, _list ) \ - MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \ - MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM) - - -#define MCFG_SOFTWARE_LIST_COMPATIBLE_ADD( _tag, _list ) \ - MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \ - MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM) - - -#define MCFG_SOFTWARE_LIST_MODIFY( _tag, _list ) \ - MCFG_DEVICE_MODIFY( _tag ) \ - MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM) - -#define MCFG_SOFTWARE_LIST_COMPATIBLE_MODIFY( _tag, _list ) \ - MCFG_DEVICE_MODIFY( _tag ) \ - MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM) - -#define MCFG_SOFTWARE_LIST_FILTER( _tag, _filter ) \ - MCFG_DEVICE_MODIFY( _tag ) \ - MCFG_DEVICE_CONFIG_DATAPTR(software_list_config, filter, _filter) - #endif diff --git a/src/emu/sound.c b/src/emu/sound.c index 0586b6a72e8..eb201a7448f 100644 --- a/src/emu/sound.c +++ b/src/emu/sound.c @@ -788,7 +788,10 @@ sound_manager::sound_manager(running_machine &machine) machine.m_sample_rate = 11025; // count the speakers - VPRINTF(("total speakers = %d\n", machine.devicelist().count(SPEAKER))); +#if VERBOSE + speaker_device_iterator iter(machine.root_device()); + VPRINTF(("total speakers = %d\n", iter.count())); +#endif // allocate memory for mix buffers m_leftmix = auto_alloc_array(machine, INT32, machine.sample_rate()); @@ -862,7 +865,8 @@ void sound_manager::set_attenuation(int attenuation) bool sound_manager::indexed_speaker_input(int index, speaker_input &info) const { // scan through the speakers until we find the indexed input - for (info.speaker = downcast<speaker_device *>(machine().devicelist().first(SPEAKER)); info.speaker != NULL; info.speaker = info.speaker->next_speaker()) + speaker_device_iterator iter(machine().root_device()); + for (info.speaker = iter.first(); info.speaker != NULL; info.speaker = iter.next()) { if (index < info.speaker->inputs()) { @@ -899,8 +903,8 @@ void sound_manager::mute(bool mute, UINT8 reason) void sound_manager::reset() { // reset all the sound chips - device_sound_interface *sound = NULL; - for (bool gotone = machine().devicelist().first(sound); gotone; gotone = sound->next(sound)) + sound_interface_iterator iter(machine().root_device()); + for (device_sound_interface *sound = iter.first(); sound != NULL; sound = iter.next()) sound->device().reset(); } @@ -1003,7 +1007,8 @@ void sound_manager::update() // force all the speaker streams to generate the proper number of samples int samples_this_update = 0; - for (speaker_device *speaker = downcast<speaker_device *>(machine().devicelist().first(SPEAKER)); speaker != NULL; speaker = speaker->next_speaker()) + speaker_device_iterator iter(machine().root_device()); + for (speaker_device *speaker = iter.first(); speaker != NULL; speaker = iter.next()) speaker->mix(m_leftmix, m_rightmix, samples_this_update, (m_muted & MUTE_REASON_SYSTEM)); // now downmix the final result diff --git a/src/emu/sound/bsmt2000.c b/src/emu/sound/bsmt2000.c index 4f3ddbf930a..20d9269cb85 100644 --- a/src/emu/sound/bsmt2000.c +++ b/src/emu/sound/bsmt2000.c @@ -173,7 +173,7 @@ machine_config_constructor bsmt2000_device::device_mconfig_additions() const void bsmt2000_device::device_start() { // find our CPU - m_cpu = downcast<tms32015_device*>(subdevice("bsmt2000")); + m_cpu = subdevice<tms32015_device>("bsmt2000"); // find our direct access m_direct = &space()->direct(); diff --git a/src/emu/sound/cdda.c b/src/emu/sound/cdda.c index 6eea9e498fb..8b4a9af1118 100644 --- a/src/emu/sound/cdda.c +++ b/src/emu/sound/cdda.c @@ -90,9 +90,8 @@ void cdda_set_cdrom(device_t *device, void *file) device_t *cdda_from_cdrom(running_machine &machine, void *file) { - device_sound_interface *sound = NULL; - - for (bool gotone = machine.devicelist().first(sound); gotone; gotone = sound->next(sound)) + sound_interface_iterator iter(machine.root_device()); + for (device_sound_interface *sound = iter.first(); sound != NULL; sound = iter.next()) if (sound->device().type() == CDDA) { cdda_info *info = get_safe_token(*sound); diff --git a/src/emu/sound/disc_inp.c b/src/emu/sound/disc_inp.c index d2e09bcd7e0..e30a9af4340 100644 --- a/src/emu/sound/disc_inp.c +++ b/src/emu/sound/disc_inp.c @@ -75,7 +75,8 @@ DISCRETE_RESET(dss_adjustment) { double min, max; - m_port = m_device->machine().m_portlist.find((const char *)this->custom_data()); + astring fulltag; + m_port = m_device->machine().m_portlist.find(m_device->siblingtag(fulltag, (const char *)this->custom_data()).cstr()); if (m_port == NULL) fatalerror("DISCRETE_ADJUSTMENT - NODE_%d has invalid tag", this->index()); diff --git a/src/emu/sound/samples.h b/src/emu/sound/samples.h index 0d44d994c2f..b3abd505b04 100644 --- a/src/emu/sound/samples.h +++ b/src/emu/sound/samples.h @@ -46,4 +46,6 @@ loaded_samples *readsamples(running_machine &machine, const char *const *samplen DECLARE_LEGACY_SOUND_DEVICE(SAMPLES, samples); +typedef device_type_iterator<&legacy_device_creator<samples_device>, samples_device> samples_device_iterator; + #endif /* __SAMPLES_H__ */ diff --git a/src/emu/sound/wave.c b/src/emu/sound/wave.c index 179b02512e6..1d879de288b 100644 --- a/src/emu/sound/wave.c +++ b/src/emu/sound/wave.c @@ -22,7 +22,6 @@ static STREAM_UPDATE( wave_sound_update ) { cassette_image_device *cass = (cassette_image_device *)param; - int speakers = cass->machine().devicelist().count(SPEAKER); cassette_image *cassette; cassette_state state; double time_index; @@ -31,6 +30,8 @@ static STREAM_UPDATE( wave_sound_update ) stream_sample_t *right_buffer = NULL; int i; + speaker_device_iterator spkiter(cass->machine().root_device()); + int speakers = spkiter.count(); if (speakers>1) right_buffer = outputs[1]; @@ -71,7 +72,8 @@ static DEVICE_START( wave ) assert( device != NULL ); assert( device->static_config() != NULL ); - int speakers = device->machine().config().devicelist().count(SPEAKER); + speaker_device_iterator spkiter(device->machine().root_device()); + int speakers = spkiter.count(); image = dynamic_cast<cassette_image_device *>(device->machine().device( (const char *)device->static_config())); if (speakers > 1) device->machine().sound().stream_alloc(*device, 0, 2, device->machine().sample_rate(), (void *)image, wave_sound_update); diff --git a/src/emu/speaker.h b/src/emu/speaker.h index 31b6f4696c7..3ead6eab11c 100644 --- a/src/emu/speaker.h +++ b/src/emu/speaker.h @@ -84,9 +84,6 @@ public: // inline configuration helpers static void static_set_position(device_t &device, double x, double y, double z); - // getters - speaker_device *next_speaker() const { return downcast<speaker_device *>(typenext()); } - // internally for use by the sound system void mix(INT32 *leftmix, INT32 *rightmix, int &samples_this_update, bool suppress); @@ -117,4 +114,8 @@ protected: extern const device_type SPEAKER; +// speaker device iterator +typedef device_type_iterator<&device_creator<speaker_device>, speaker_device> speaker_device_iterator; + + #endif /* __SOUND_H__ */ diff --git a/src/emu/timer.c b/src/emu/timer.c index 28ed940c93b..70a81315b6a 100644 --- a/src/emu/timer.c +++ b/src/emu/timer.c @@ -176,54 +176,40 @@ void timer_device::static_set_ptr(device_t &device, void *ptr) // configuration //------------------------------------------------- -bool timer_device::device_validity_check(emu_options &options, const game_driver &driver) const +void timer_device::device_validity_check(validity_checker &valid) const { - bool error = false; - // type based configuration switch (m_type) { case TIMER_TYPE_GENERIC: if (m_screen_tag != NULL || m_first_vpos != 0 || m_start_delay != attotime::zero) - mame_printf_warning("%s: %s generic timer '%s' specified parameters for a scanline timer\n", driver.source_file, driver.name, tag()); + mame_printf_warning("Generic timer specified parameters for a scanline timer\n"); if (m_period != attotime::zero || m_start_delay != attotime::zero) - mame_printf_warning("%s: %s generic timer '%s' specified parameters for a periodic timer\n", driver.source_file, driver.name, tag()); + mame_printf_warning("Generic timer specified parameters for a periodic timer\n"); break; case TIMER_TYPE_PERIODIC: if (m_screen_tag != NULL || m_first_vpos != 0) - mame_printf_warning("%s: %s periodic timer '%s' specified parameters for a scanline timer\n", driver.source_file, driver.name, tag()); + mame_printf_warning("Periodic timer specified parameters for a scanline timer\n"); if (m_period <= attotime::zero) - { - mame_printf_error("%s: %s periodic timer '%s' specified invalid period\n", driver.source_file, driver.name, tag()); - error = true; - } + mame_printf_error("Periodic timer specified invalid period\n"); break; case TIMER_TYPE_SCANLINE: if (m_period != attotime::zero || m_start_delay != attotime::zero) - mame_printf_warning("%s: %s scanline timer '%s' specified parameters for a periodic timer\n", driver.source_file, driver.name, tag()); + mame_printf_warning("Scanline timer specified parameters for a periodic timer\n"); if (m_param != 0) - mame_printf_warning("%s: %s scanline timer '%s' specified parameter which is ignored\n", driver.source_file, driver.name, tag()); + mame_printf_warning("Scanline timer specified parameter which is ignored\n"); if (m_first_vpos < 0) - { - mame_printf_error("%s: %s scanline timer '%s' specified invalid initial position\n", driver.source_file, driver.name, tag()); - error = true; - } + mame_printf_error("Scanline timer specified invalid initial position\n"); if (m_increment < 0) - { - mame_printf_error("%s: %s scanline timer '%s' specified invalid increment\n", driver.source_file, driver.name, tag()); - error = true; - } + mame_printf_error("Scanline timer specified invalid increment\n"); break; default: - mame_printf_error("%s: %s timer '%s' has an invalid type\n", driver.source_file, driver.name, tag()); - error = true; + mame_printf_error("Invalid type specified\n"); break; } - - return error; } diff --git a/src/emu/timer.h b/src/emu/timer.h index fff33be5ad4..7c01feb0375 100644 --- a/src/emu/timer.h +++ b/src/emu/timer.h @@ -142,7 +142,7 @@ public: private: // device-level overrides - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); diff --git a/src/emu/ui.c b/src/emu/ui.c index bdea3a453d2..eb87b3cf5ae 100644 --- a/src/emu/ui.c +++ b/src/emu/ui.c @@ -1018,29 +1018,30 @@ static astring &warnings_string(running_machine &machine, astring &string) astring &game_info_astring(running_machine &machine, astring &string) { - int scrcount = machine.devicelist().count(SCREEN); + screen_device_iterator scriter(machine.root_device()); + int scrcount = scriter.count(); int found_sound = FALSE; /* print description, manufacturer, and CPU: */ string.printf("%s\n%s %s\n\nCPU:\n", machine.system().description, machine.system().year, machine.system().manufacturer); /* loop over all CPUs */ - device_execute_interface *exec = NULL; - for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator execiter(machine.root_device()); + for (device_execute_interface *exec = execiter.first(); exec != NULL; exec = execiter.next()) { /* get cpu specific clock that takes internal multiplier/dividers into account */ int clock = exec->device().clock(); /* count how many identical CPUs we have */ int count = 1; - device_execute_interface *scan = NULL; - for (bool gotanother = exec->next(scan); gotanother; gotanother = scan->next(scan)) + for (device_execute_interface *scan = execiter.next(); scan != NULL; scan = execiter.next()) { if (exec->device().type() != scan->device().type() || exec->device().clock() != scan->device().clock()) break; count++; exec = scan; } + execiter.set_current(*exec); /* if more than one, prepend a #x in front of the CPU name */ if (count > 1) @@ -1055,8 +1056,8 @@ astring &game_info_astring(running_machine &machine, astring &string) } /* loop over all sound chips */ - device_sound_interface *sound = NULL; - for (bool gotone = machine.devicelist().first(sound); gotone; gotone = sound->next(sound)) + sound_interface_iterator snditer(machine.root_device()); + for (device_sound_interface *sound = snditer.first(); sound != NULL; sound = snditer.next()) { /* append the Sound: string */ if (!found_sound) @@ -1065,14 +1066,14 @@ astring &game_info_astring(running_machine &machine, astring &string) /* count how many identical sound chips we have */ int count = 1; - device_sound_interface *scan = NULL; - for (bool gotanother = sound->next(scan); gotanother; gotanother = scan->next(scan)) + for (device_sound_interface *scan = snditer.next(); scan != NULL; scan = snditer.next()) { if (sound->device().type() != scan->device().type() || sound->device().clock() != scan->device().clock()) break; count++; sound = scan; } + snditer.set_current(*sound); /* if more than one, prepend a #x in front of the CPU name */ if (count > 1) @@ -1095,7 +1096,8 @@ astring &game_info_astring(running_machine &machine, astring &string) string.cat("None\n"); else { - for (screen_device *screen = machine.first_screen(); screen != NULL; screen = screen->next_screen()) + screen_device_iterator iter(machine.root_device()); + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) { if (scrcount > 1) { @@ -1271,17 +1273,13 @@ void ui_paste(running_machine &machine) void ui_image_handler_ingame(running_machine &machine) { - device_image_interface *image = NULL; - /* run display routine for devices */ if (machine.phase() == MACHINE_PHASE_RUNNING) { - for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image)) - { + image_interface_iterator iter(machine.root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) image->call_display(); - } } - } /*------------------------------------------------- @@ -1644,7 +1642,6 @@ static slider_state *slider_init(running_machine &machine) { input_field_config *field; input_port_config *port; - device_t *device; slider_state *listhead = NULL; slider_state **tailptr = &listhead; astring string; @@ -1683,8 +1680,8 @@ static slider_state *slider_init(running_machine &machine) /* add CPU overclocking (cheat only) */ if (machine.options().cheat()) { - device_execute_interface *exec = NULL; - for (bool gotone = machine.devicelist().first(exec); gotone; gotone = exec->next(exec)) + execute_interface_iterator iter(machine.root_device()); + for (device_execute_interface *exec = iter.first(); exec != NULL; exec = iter.next()) { void *param = (void *)&exec->device(); string.printf("Overclock CPU %s", exec->device().tag()); @@ -1694,7 +1691,8 @@ static slider_state *slider_init(running_machine &machine) } /* add screen parameters */ - for (screen_device *screen = machine.first_screen(); screen != NULL; screen = screen->next_screen()) + screen_device_iterator scriter(machine.root_device()); + for (screen_device *screen = scriter.first(); screen != NULL; screen = scriter.next()) { int defxscale = floor(screen->xscale() * 1000.0f + 0.5f); int defyscale = floor(screen->yscale() * 1000.0f + 0.5f); @@ -1736,10 +1734,9 @@ static slider_state *slider_init(running_machine &machine) tailptr = &(*tailptr)->next; } - for (device = machine.devicelist().first(); device != NULL; device = device->next()) - { - laserdisc_device *laserdisc = dynamic_cast<laserdisc_device *>(device); - if (laserdisc != NULL && laserdisc->overlay_configured()) + laserdisc_device_iterator lditer(machine.root_device()); + for (laserdisc_device *laserdisc = lditer.first(); laserdisc != NULL; laserdisc = lditer.next()) + if (laserdisc->overlay_configured()) { laserdisc_overlay_config config; laserdisc->get_overlay_config(config); @@ -1763,9 +1760,8 @@ static slider_state *slider_init(running_machine &machine) *tailptr = slider_alloc(machine, string, -500, defyoffset, 500, 2, slider_overyoffset, param); tailptr = &(*tailptr)->next; } - } - for (screen_device *screen = machine.first_screen(); screen != NULL; screen = screen->next_screen()) + for (screen_device *screen = scriter.first(); screen != NULL; screen = scriter.next()) if (screen->screen_type() == SCREEN_TYPE_VECTOR) { /* add flicker control */ @@ -2172,7 +2168,8 @@ static INT32 slider_beam(running_machine &machine, void *arg, astring *string, I static char *slider_get_screen_desc(screen_device &screen) { - int scrcount = screen.machine().devicelist().count(SCREEN); + screen_device_iterator iter(screen.machine().root_device()); + int scrcount = iter.count(); static char descbuf[256]; if (scrcount > 1) diff --git a/src/emu/uiimage.c b/src/emu/uiimage.c index aaedc71c1e5..db1ad578bdf 100644 --- a/src/emu/uiimage.c +++ b/src/emu/uiimage.c @@ -770,11 +770,11 @@ ui_menu_file_manager::ui_menu_file_manager(running_machine &machine, render_cont void ui_menu_file_manager::populate() { char buffer[2048]; - device_image_interface *image = NULL; astring tmp_name; /* cycle through all devices for this system */ - for (bool gotone = machine().devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine().root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { /* get the image type/id */ snprintf(buffer, ARRAY_LENGTH(buffer), @@ -1000,15 +1000,8 @@ ui_menu_mess_bitbanger_control::~ui_menu_mess_bitbanger_control() int ui_menu_mess_tape_control::cassette_count() { - int count = 0; - device_t *device = machine().devicelist().first(CASSETTE); - - while ( device ) - { - count++; - device = device->typenext(); - } - return count; + cassette_device_iterator iter(machine().root_device()); + return iter.count(); } /*------------------------------------------------- @@ -1018,15 +1011,8 @@ int ui_menu_mess_tape_control::cassette_count() int ui_menu_mess_bitbanger_control::bitbanger_count() { - int count = 0; - device_t *device = machine().devicelist().first(BITBANGER); - - while ( device ) - { - count++; - device = device->typenext(); - } - return count; + bitbanger_device_iterator iter(machine().root_device()); + return iter.count(); } /*------------------------------------------------- @@ -1197,14 +1183,8 @@ void ui_menu_mess_tape_control::handle() /* do we have to load the device? */ if (device == NULL) { - int cindex = index; - for (bool gotone = machine().devicelist().first(device); gotone; gotone = device->next(device)) - { - if(device->device().type() == CASSETTE) { - if (cindex==0) break; - cindex--; - } - } + cassette_device_iterator iter(machine().root_device()); + device = iter.byindex(index); reset((ui_menu_reset_options)0); } @@ -1286,14 +1266,8 @@ void ui_menu_mess_bitbanger_control::handle() /* do we have to load the device? */ if (device == NULL) { - int cindex = index; - for (bool gotone = machine().devicelist().first(device); gotone; gotone = device->next(device)) - { - if(device->device().type() == BITBANGER) { - if (cindex==0) break; - cindex--; - } - } + bitbanger_device_iterator iter(machine().root_device()); + device = iter.byindex(index); reset((ui_menu_reset_options)0); } diff --git a/src/emu/uimain.c b/src/emu/uimain.c index d0e657533c1..fbbead0fa13 100644 --- a/src/emu/uimain.c +++ b/src/emu/uimain.c @@ -149,8 +149,8 @@ void ui_menu_main::populate() menu_text.printf("%s Information",emulator_info::get_capstartgamenoun()); item_append(menu_text.cstr(), NULL, 0, (void *)GAME_INFO); - device_image_interface *image = NULL; - if (machine().devicelist().first(image)) + image_interface_iterator imgiter(machine().root_device()); + if (imgiter.first() != NULL) { /* add image info menu */ item_append("Image Information", NULL, 0, (void *)IMAGE_MENU_IMAGE_INFO); @@ -159,23 +159,25 @@ void ui_menu_main::populate() item_append("File Manager", NULL, 0, (void *)IMAGE_MENU_FILE_MANAGER); /* add tape control menu */ - if (machine().devicelist().first(CASSETTE)) + cassette_device_iterator cassiter(machine().root_device()); + if (cassiter.first() != NULL) item_append("Tape Control", NULL, 0, (void *)MESS_MENU_TAPE_CONTROL); /* add bitbanger control menu */ - if (machine().devicelist().first(BITBANGER)) + bitbanger_device_iterator bititer(machine().root_device()); + if (bititer.first() != NULL) item_append("Bitbanger Control", NULL, 0, (void *)MESS_MENU_BITBANGER_CONTROL); } - device_slot_interface *slot = NULL; - if (machine().devicelist().first(slot)) + slot_interface_iterator slotiter(machine().root_device()); + if (slotiter.first() != NULL) { /* add image info menu */ item_append("Slot Devices", NULL, 0, (void *)SLOT_DEVICES); } - device_network_interface *network = NULL; - if (machine().devicelist().first(network)) + network_interface_iterator netiter(machine().root_device()); + if (netiter.first() != NULL) { /* add image info menu */ item_append("Network Devices", NULL, 0, (void*)NETWORK_DEVICES); @@ -427,10 +429,9 @@ ui_menu_slot_devices::ui_menu_slot_devices(running_machine &machine, render_cont void ui_menu_slot_devices::populate() { - device_slot_interface *slot = NULL; - /* cycle through all devices for this system */ - for (bool gotone = machine().devicelist().first(slot); gotone; gotone = slot->next(slot)) + slot_interface_iterator iter(machine().root_device()); + for (device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) { /* record the menu item */ const char *title = get_slot_device(slot); @@ -481,10 +482,9 @@ ui_menu_network_devices::~ui_menu_network_devices() void ui_menu_network_devices::populate() { - device_network_interface *network = NULL; - /* cycle through all devices for this system */ - for (bool gotone = machine().devicelist().first(network); gotone; gotone = network->next(network)) + network_interface_iterator iter(machine().root_device()); + for (device_network_interface *network = iter.first(); network != NULL; network = iter.next()) { int curr = network->get_interface(); const char *title = NULL; diff --git a/src/emu/uiswlist.c b/src/emu/uiswlist.c index 136e142eab4..44fcb9efd4d 100644 --- a/src/emu/uiswlist.c +++ b/src/emu/uiswlist.c @@ -157,7 +157,7 @@ ui_menu_software_list::entry_info *ui_menu_software_list::append_software_entry( return entry; } -ui_menu_software_list::ui_menu_software_list(running_machine &machine, render_container *container, const software_list_config *_swlist, const char *_interface, astring &_result) : ui_menu(machine, container), result(_result) +ui_menu_software_list::ui_menu_software_list(running_machine &machine, render_container *container, const software_list_device *_swlist, const char *_interface, astring &_result) : ui_menu(machine, container), result(_result) { swlist = _swlist; interface = _interface; @@ -171,7 +171,7 @@ ui_menu_software_list::~ui_menu_software_list() void ui_menu_software_list::populate() { - const software_list *list = software_list_open(machine().options(), swlist->list_name, false, NULL); + const software_list *list = software_list_open(machine().options(), swlist->list_name(), false, NULL); // build up the list of entries for the menu if (list) @@ -313,7 +313,7 @@ void ui_menu_software_list::handle() } /* list of available software lists - i.e. cartridges, floppies */ -ui_menu_software::ui_menu_software(running_machine &machine, render_container *container, const char *_interface, const software_list_config **_result) : ui_menu(machine, container) +ui_menu_software::ui_menu_software(running_machine &machine, render_container *container, const char *_interface, const software_list_device **_result) : ui_menu(machine, container) { interface = _interface; result = _result; @@ -324,13 +324,12 @@ void ui_menu_software::populate() bool haveCompatible = false; // Add original software lists for this system - for (const device_t *dev = machine().config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) + software_list_device_iterator iter(machine().config().root_device()); + for (const software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) { - const software_list_config *swlist = (const software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config(); - - if (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) + if (swlist->list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) { - const software_list *list = software_list_open(machine().options(), swlist->list_name, false, NULL); + const software_list *list = software_list_open(machine().options(), swlist->list_name(), false, NULL); if (list) { @@ -352,13 +351,11 @@ void ui_menu_software::populate() } // Add compatible software lists for this system - for (const device_t *dev = machine().config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) + for (const software_list_device *swlist = iter.first(); swlist != NULL; swlist = iter.next()) { - const software_list_config *swlist = (const software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config(); - - if (swlist->list_type == SOFTWARE_LIST_COMPATIBLE_SYSTEM) + if (swlist->list_type() == SOFTWARE_LIST_COMPATIBLE_SYSTEM) { - const software_list *list = software_list_open(machine().options(), swlist->list_name, false, NULL); + const software_list *list = software_list_open(machine().options(), swlist->list_name(), false, NULL); if (list) { @@ -396,7 +393,7 @@ void ui_menu_software::handle() if (event != NULL && event->iptkey == IPT_UI_SELECT) { // ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software_list(machine(), container, (software_list_config *)event->itemref, image))); - *result = (software_list_config *)event->itemref; + *result = (software_list_device *)event->itemref; ui_menu::stack_pop(machine()); } } diff --git a/src/emu/uiswlist.h b/src/emu/uiswlist.h index da92c9f5917..f914f0faedf 100644 --- a/src/emu/uiswlist.h +++ b/src/emu/uiswlist.h @@ -35,7 +35,7 @@ private: class ui_menu_software_list : public ui_menu { public: - ui_menu_software_list(running_machine &machine, render_container *container, const software_list_config *swlist, const char *interface, astring &result); + ui_menu_software_list(running_machine &machine, render_container *container, const software_list_device *swlist, const char *interface, astring &result); virtual ~ui_menu_software_list(); virtual void populate(); virtual void handle(); @@ -48,7 +48,7 @@ private: const char *long_name; }; - const software_list_config *swlist; /* currently selected list */ + const software_list_device *swlist; /* currently selected list */ const char *interface; astring &result; entry_info *entrylist; @@ -61,14 +61,14 @@ private: class ui_menu_software : public ui_menu { public: - ui_menu_software(running_machine &machine, render_container *container, const char *interface, const software_list_config **result); + ui_menu_software(running_machine &machine, render_container *container, const char *interface, const software_list_device **result); virtual ~ui_menu_software(); virtual void populate(); virtual void handle(); private: const char *interface; - const software_list_config **result; + const software_list_device **result; }; #endif /* __UISWLIST_H__ */ diff --git a/src/emu/validity.c b/src/emu/validity.c index 8a1ebd2e4ea..8fb14d76c82 100644 --- a/src/emu/validity.c +++ b/src/emu/validity.c @@ -4,8 +4,36 @@ Validity checks on internal data structures. - Copyright Nicola Salmoria and the MAME Team. - Visit http://mamedev.org for licensing and usage restrictions. +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ @@ -13,22 +41,15 @@ #include "hash.h" #include "validity.h" #include "emuopts.h" +#include "softlist.h" #include <ctype.h> -/*************************************************************************** - DEBUGGING -***************************************************************************/ - -#define REPORT_TIMES (0) - - +//************************************************************************** +// COMPILE-TIME VALIDATION +//************************************************************************** -/*************************************************************************** - COMPILE-TIME VALIDATION -***************************************************************************/ - -/* if the following lines error during compile, your PTR64 switch is set incorrectly in the makefile */ +// if the following lines error during compile, your PTR64 switch is set incorrectly in the makefile #ifdef PTR64 UINT8 your_ptr64_flag_is_wrong[(int)(sizeof(void *) - 7)]; #else @@ -37,131 +58,332 @@ UINT8 your_ptr64_flag_is_wrong[(int)(5 - sizeof(void *))]; -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** -typedef tagmap_t<const game_driver *> game_driver_map; +extern const device_type *s_devices_sorted[]; +extern int m_device_count; -typedef tagmap_t<FPTR> int_map; -class region_entry -{ -public: - region_entry() - : length(0) { } - astring tag; - UINT32 length; -}; +//************************************************************************** +// INLINE FUNCTIONS +//************************************************************************** +//------------------------------------------------- +// ioport_string_from_index - return an indexed +// string from the I/O port system +//------------------------------------------------- -class region_array +inline const char *validity_checker::ioport_string_from_index(UINT32 index) { -public: - region_entry entries[256]; -}; - - -extern const device_type *s_devices_sorted[]; -extern int m_device_count; + return input_port_string_from_token((const char *)(FPTR)index); +} -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ -/*------------------------------------------------- - input_port_string_from_index - return an - indexed string from the input port system --------------------------------------------------*/ +//------------------------------------------------- +// get_defstr_index - return the index of the +// string assuming it is one of the default +// strings +//------------------------------------------------- -INLINE const char *input_port_string_from_index(UINT32 index) +inline int validity_checker::get_defstr_index(const char *string, bool suppress_error) { - return input_port_string_from_token((const char *)(FPTR)index); + // check for strings that should be DEF_STR + int strindex = m_defstr_map.find(string); + if (!suppress_error && strindex != 0 && string != ioport_string_from_index(strindex)) + mame_printf_error("Must use DEF_STR( %s )\n", string); + return strindex; } -/*------------------------------------------------- - validate_tag - ensure that the given tag - meets the general requirements --------------------------------------------------*/ +//------------------------------------------------- +// validate_tag - ensure that the given tag +// meets the general requirements +//------------------------------------------------- -bool validate_tag(const game_driver &driver, const char *object, const char *tag) +void validity_checker::validate_tag(const char *tag) { - const char *validchars = "abcdefghijklmnopqrstuvwxyz0123456789_.:"; - const char *begin = strrchr(tag, ':'); - const char *p; - bool error = false; - - /* some common names that are now deprecated */ - if (strcmp(tag, "main") == 0 || - strcmp(tag, "audio") == 0 || - strcmp(tag, "sound") == 0 || - strcmp(tag, "left") == 0 || - strcmp(tag, "right") == 0) - { - mame_printf_error("%s: %s has invalid generic tag '%s'\n", driver.source_file, driver.name, tag); - error = true; - } + // some common names that are now deprecated + if (strcmp(tag, "main") == 0 || strcmp(tag, "audio") == 0 || strcmp(tag, "sound") == 0 || strcmp(tag, "left") == 0 || strcmp(tag, "right") == 0) + mame_printf_error("Invalid generic tag '%s' used\n", tag); - for (p = tag; *p != 0; p++) + // scan for invalid characters + static const char *validchars = "abcdefghijklmnopqrstuvwxyz0123456789_.:^$"; + for (const char *p = tag; *p != 0; p++) { + // only lower-case permitted if (*p != tolower((UINT8)*p)) { - mame_printf_error("%s: %s has %s with tag '%s' containing upper-case characters\n", driver.source_file, driver.name, object, tag); - error = true; + mame_printf_error("Tag '%s' contains upper-case characters\n", tag); break; } if (*p == ' ') { - mame_printf_error("%s: %s has %s with tag '%s' containing spaces\n", driver.source_file, driver.name, object, tag); - error = true; + mame_printf_error("Tag '%s' contains spaces\n", tag); break; } if (strchr(validchars, *p) == NULL) { - mame_printf_error("%s: %s has %s with tag '%s' containing invalid character '%c'\n", driver.source_file, driver.name, object, tag, *p); - error = true; + mame_printf_error("Tag '%s' contains invalid character '%c'\n", tag, *p); break; } } + // find the start of the final tag + const char *begin = strrchr(tag, ':'); if (begin == NULL) begin = tag; else begin += 1; + // 0-length = bad if (strlen(begin) == 0) + mame_printf_error("Found 0-length tag\n"); + + // too short/too long = bad + if (strlen(begin) < MIN_TAG_LENGTH) + mame_printf_error("Tag '%s' is too short (must be at least %d characters)\n", tag, MIN_TAG_LENGTH); + if (strlen(begin) > MAX_TAG_LENGTH) + mame_printf_error("Tag '%s' is too longer (must be less than %d characters)\n", tag, MAX_TAG_LENGTH); +} + + + +//************************************************************************** +// VALIDATION FUNCTIONS +//************************************************************************** + +//------------------------------------------------- +// validity_checker - constructor +//------------------------------------------------- + +validity_checker::validity_checker(emu_options &options) + : m_drivlist(options), + m_errors(0), + m_warnings(0), + m_current_driver(NULL), + m_current_config(NULL), + m_current_device(NULL), + m_current_ioport(NULL) +{ + // pre-populate the defstr map with all the default strings + for (int strnum = 1; strnum < INPUT_STRING_COUNT; strnum++) { - mame_printf_error("%s: %s has %s with 0-length tag\n", driver.source_file, driver.name, object); - error = true; + const char *string = ioport_string_from_index(strnum); + if (string != NULL) + m_defstr_map.add(string, strnum, false); } - if (strlen(begin) < MIN_TAG_LENGTH) +} + + +//------------------------------------------------- +// check_driver - check a single driver +//------------------------------------------------- + +void validity_checker::check_driver(const game_driver &driver) +{ + // simply validate the one driver + validate_begin(); + validate_one(driver); + validate_end(); +} + + +//------------------------------------------------- +// check_shared_source - check all drivers that +// share the same source file as the given driver +//------------------------------------------------- + +void validity_checker::check_shared_source(const game_driver &driver) +{ + // initialize + validate_begin(); + + // then iterate over all drivers and check the ones that share the same source file + m_drivlist.reset(); + while (m_drivlist.next()) + if (strcmp(driver.source_file, m_drivlist.driver().source_file) == 0) + validate_one(m_drivlist.driver()); + + // cleanup + validate_end(); +} + + +//------------------------------------------------- +// check_all - check all drivers +//------------------------------------------------- + +void validity_checker::check_all() +{ + // start by checking core stuff + validate_begin(); + validate_core(); + validate_inlines(); + + // then iterate over all drivers and check them + m_drivlist.reset(); + while (m_drivlist.next()) + validate_one(m_drivlist.driver()); + + // cleanup + validate_end(); +} + + +//------------------------------------------------- +// validate_begin - prepare for validation by +// taking over the output callbacks and resetting +// our internal state +//------------------------------------------------- + +void validity_checker::validate_begin() +{ + // take over error and warning outputs + m_saved_error_output = mame_set_output_channel(OUTPUT_CHANNEL_ERROR, output_delegate(FUNC(validity_checker::error_output), this)); + m_saved_warning_output = mame_set_output_channel(OUTPUT_CHANNEL_WARNING, output_delegate(FUNC(validity_checker::warning_output), this)); + + // reset all our maps + m_names_map.reset(); + m_descriptions_map.reset(); + m_roms_map.reset(); + m_defstr_map.reset(); + m_region_map.reset(); + + // reset internal state + m_errors = 0; + m_warnings = 0; + + // reset some special case state + software_list_device::reset_checked_lists(); +} + + +//------------------------------------------------- +// validate_end - restore output callbacks and +// clean up +//------------------------------------------------- + +void validity_checker::validate_end() +{ + // restore the original output callbacks + mame_set_output_channel(OUTPUT_CHANNEL_ERROR, m_saved_error_output); + mame_set_output_channel(OUTPUT_CHANNEL_WARNING, m_saved_warning_output); +} + + +//------------------------------------------------- +// validate_drivers - master validity checker +//------------------------------------------------- + +void validity_checker::validate_one(const game_driver &driver) +{ + // set the current driver + m_current_driver = &driver; + m_current_config = NULL; + m_current_device = NULL; + m_current_ioport = NULL; + m_region_map.reset(); + + // reset error/warning state + int start_errors = m_errors; + int start_warnings = m_warnings; + m_error_text.reset(); + m_warning_text.reset(); + + // wrap in try/except to catch fatalerrors + try { - mame_printf_error("%s: %s has %s with tag '%s' < %d characters\n", driver.source_file, driver.name, object, tag, MIN_TAG_LENGTH); - error = true; + machine_config config(driver, m_drivlist.options()); + m_current_config = &config; + validate_driver(); + validate_roms(); + validate_inputs(); + validate_display(); + validate_gfx(); + validate_devices(); + validate_slots(); } - if (strlen(begin) > MAX_TAG_LENGTH) + catch (emu_fatalerror &err) { - mame_printf_error("%s: %s has %s with tag '%s' > %d characters\n", driver.source_file, driver.name, object, tag, MAX_TAG_LENGTH); - error = true; + mame_printf_error("Fatal error %s", err.string()); + } + m_current_config = NULL; + + // if we had warnings or errors, output + if (m_errors > start_errors || m_warnings > start_warnings) + { + astring tempstr; + output_via_delegate(m_saved_error_output, "Driver %s (file %s): %d errors, %d warnings\n", driver.name, core_filename_extract_base(tempstr, driver.source_file).cstr(), m_errors - start_errors, m_warnings - start_warnings); + if (m_errors > start_errors) + { + m_error_text.replace("\n", "\n "); + output_via_delegate(m_saved_error_output, "Errors:\n %s", m_error_text.cstr()); + } + if (m_warnings > start_warnings) + { + m_warning_text.replace("\n", "\n "); + output_via_delegate(m_saved_error_output, "Warnings:\n %s", m_warning_text.cstr()); + } + output_via_delegate(m_saved_error_output, "\n"); } - return !error; + // reset the driver/device + m_current_driver = NULL; + m_current_config = NULL; + m_current_device = NULL; + m_current_ioport = NULL; } +//------------------------------------------------- +// validate_core - validate core internal systems +//------------------------------------------------- -/*************************************************************************** - VALIDATION FUNCTIONS -***************************************************************************/ +void validity_checker::validate_core() +{ -/*------------------------------------------------- - validate_inlines - validate inline function - behaviors --------------------------------------------------*/ + // basic system checks + UINT8 a = 0xff; + UINT8 b = a + 1; + if (b > a) mame_printf_error("UINT8 must be 8 bits\n"); + + // check size of core integer types + if (sizeof(INT8) != 1) mame_printf_error("INT8 must be 8 bits\n"); + if (sizeof(UINT8) != 1) mame_printf_error("UINT8 must be 8 bits\n"); + if (sizeof(INT16) != 2) mame_printf_error("INT16 must be 16 bits\n"); + if (sizeof(UINT16) != 2) mame_printf_error("UINT16 must be 16 bits\n"); + if (sizeof(INT32) != 4) mame_printf_error("INT32 must be 32 bits\n"); + if (sizeof(UINT32) != 4) mame_printf_error("UINT32 must be 32 bits\n"); + if (sizeof(INT64) != 8) mame_printf_error("INT64 must be 64 bits\n"); + if (sizeof(UINT64) != 8) mame_printf_error("UINT64 must be 64 bits\n"); + + // check pointer size +#ifdef PTR64 + if (sizeof(void *) != 8) mame_printf_error("PTR64 flag enabled, but was compiled for 32-bit target\n"); +#else + if (sizeof(void *) != 4) mame_printf_error("PTR64 flag not enabled, but was compiled for 64-bit target\n"); +#endif + + // check endianness definition + UINT16 lsbtest = 0; + *(UINT8 *)&lsbtest = 0xff; +#ifdef LSB_FIRST + if (lsbtest == 0xff00) mame_printf_error("LSB_FIRST specified, but running on a big-endian machine\n"); +#else + if (lsbtest == 0x00ff) mame_printf_error("LSB_FIRST not specified, but running on a little-endian machine\n"); +#endif +} + + +//------------------------------------------------- +// validate_inlines - validate inline function +// behaviors +//------------------------------------------------- -static bool validate_inlines(void) +void validity_checker::validate_inlines() { #undef rand volatile UINT64 testu64a = rand() ^ (rand() << 15) ^ ((UINT64)rand() << 30) ^ ((UINT64)rand() << 45); @@ -179,9 +401,8 @@ static bool validate_inlines(void) UINT64 resultu64, expectedu64; INT32 remainder, expremainder; UINT32 uremainder, expuremainder, bigu32 = 0xffffffff; - bool error = false; - /* use only non-zero, positive numbers */ + // use only non-zero, positive numbers if (testu64a == 0) testu64a++; if (testi64a == 0) testi64a++; else if (testi64a < 0) testi64a = -testi64a; @@ -199,32 +420,32 @@ static bool validate_inlines(void) resulti64 = mul_32x32(testi32a, testi32b); expectedi64 = (INT64)testi32a * (INT64)testi32b; if (resulti64 != expectedi64) - { mame_printf_error("Error testing mul_32x32 (%08X x %08X) = %08X%08X (expected %08X%08X)\n", testi32a, testi32b, (UINT32)(resulti64 >> 32), (UINT32)resulti64, (UINT32)(expectedi64 >> 32), (UINT32)expectedi64); error = true; } + mame_printf_error("Error testing mul_32x32 (%08X x %08X) = %08X%08X (expected %08X%08X)\n", testi32a, testi32b, (UINT32)(resulti64 >> 32), (UINT32)resulti64, (UINT32)(expectedi64 >> 32), (UINT32)expectedi64); resultu64 = mulu_32x32(testu32a, testu32b); expectedu64 = (UINT64)testu32a * (UINT64)testu32b; if (resultu64 != expectedu64) - { mame_printf_error("Error testing mulu_32x32 (%08X x %08X) = %08X%08X (expected %08X%08X)\n", testu32a, testu32b, (UINT32)(resultu64 >> 32), (UINT32)resultu64, (UINT32)(expectedu64 >> 32), (UINT32)expectedu64); error = true; } + mame_printf_error("Error testing mulu_32x32 (%08X x %08X) = %08X%08X (expected %08X%08X)\n", testu32a, testu32b, (UINT32)(resultu64 >> 32), (UINT32)resultu64, (UINT32)(expectedu64 >> 32), (UINT32)expectedu64); resulti32 = mul_32x32_hi(testi32a, testi32b); expectedi32 = ((INT64)testi32a * (INT64)testi32b) >> 32; if (resulti32 != expectedi32) - { mame_printf_error("Error testing mul_32x32_hi (%08X x %08X) = %08X (expected %08X)\n", testi32a, testi32b, resulti32, expectedi32); error = true; } + mame_printf_error("Error testing mul_32x32_hi (%08X x %08X) = %08X (expected %08X)\n", testi32a, testi32b, resulti32, expectedi32); resultu32 = mulu_32x32_hi(testu32a, testu32b); expectedu32 = ((INT64)testu32a * (INT64)testu32b) >> 32; if (resultu32 != expectedu32) - { mame_printf_error("Error testing mulu_32x32_hi (%08X x %08X) = %08X (expected %08X)\n", testu32a, testu32b, resultu32, expectedu32); error = true; } + mame_printf_error("Error testing mulu_32x32_hi (%08X x %08X) = %08X (expected %08X)\n", testu32a, testu32b, resultu32, expectedu32); resulti32 = mul_32x32_shift(testi32a, testi32b, 7); expectedi32 = ((INT64)testi32a * (INT64)testi32b) >> 7; if (resulti32 != expectedi32) - { mame_printf_error("Error testing mul_32x32_shift (%08X x %08X) >> 7 = %08X (expected %08X)\n", testi32a, testi32b, resulti32, expectedi32); error = true; } + mame_printf_error("Error testing mul_32x32_shift (%08X x %08X) >> 7 = %08X (expected %08X)\n", testi32a, testi32b, resulti32, expectedi32); resultu32 = mulu_32x32_shift(testu32a, testu32b, 7); expectedu32 = ((INT64)testu32a * (INT64)testu32b) >> 7; if (resultu32 != expectedu32) - { mame_printf_error("Error testing mulu_32x32_shift (%08X x %08X) >> 7 = %08X (expected %08X)\n", testu32a, testu32b, resultu32, expectedu32); error = true; } + mame_printf_error("Error testing mulu_32x32_shift (%08X x %08X) >> 7 = %08X (expected %08X)\n", testu32a, testu32b, resultu32, expectedu32); while ((INT64)testi32a * (INT64)0x7fffffff < testi64a) testi64a /= 2; @@ -234,34 +455,34 @@ static bool validate_inlines(void) resulti32 = div_64x32(testi64a, testi32a); expectedi32 = testi64a / (INT64)testi32a; if (resulti32 != expectedi32) - { mame_printf_error("Error testing div_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, expectedi32); error = true; } + mame_printf_error("Error testing div_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, expectedi32); resultu32 = divu_64x32(testu64a, testu32a); expectedu32 = testu64a / (UINT64)testu32a; if (resultu32 != expectedu32) - { mame_printf_error("Error testing divu_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, expectedu32); error = true; } + mame_printf_error("Error testing divu_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, expectedu32); resulti32 = div_64x32_rem(testi64a, testi32a, &remainder); expectedi32 = testi64a / (INT64)testi32a; expremainder = testi64a % (INT64)testi32a; if (resulti32 != expectedi32 || remainder != expremainder) - { mame_printf_error("Error testing div_64x32_rem (%08X%08X / %08X) = %08X,%08X (expected %08X,%08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, remainder, expectedi32, expremainder); error = true; } + mame_printf_error("Error testing div_64x32_rem (%08X%08X / %08X) = %08X,%08X (expected %08X,%08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, remainder, expectedi32, expremainder); resultu32 = divu_64x32_rem(testu64a, testu32a, &uremainder); expectedu32 = testu64a / (UINT64)testu32a; expuremainder = testu64a % (UINT64)testu32a; if (resultu32 != expectedu32 || uremainder != expuremainder) - { mame_printf_error("Error testing divu_64x32_rem (%08X%08X / %08X) = %08X,%08X (expected %08X,%08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, uremainder, expectedu32, expuremainder); error = true; } + mame_printf_error("Error testing divu_64x32_rem (%08X%08X / %08X) = %08X,%08X (expected %08X,%08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, uremainder, expectedu32, expuremainder); resulti32 = mod_64x32(testi64a, testi32a); expectedi32 = testi64a % (INT64)testi32a; if (resulti32 != expectedi32) - { mame_printf_error("Error testing mod_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, expectedi32); error = true; } + mame_printf_error("Error testing mod_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testi64a >> 32), (UINT32)testi64a, testi32a, resulti32, expectedi32); resultu32 = modu_64x32(testu64a, testu32a); expectedu32 = testu64a % (UINT64)testu32a; if (resultu32 != expectedu32) - { mame_printf_error("Error testing modu_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, expectedu32); error = true; } + mame_printf_error("Error testing modu_64x32 (%08X%08X / %08X) = %08X (expected %08X)\n", (UINT32)(testu64a >> 32), (UINT32)testu64a, testu32a, resultu32, expectedu32); while ((INT64)testi32a * (INT64)0x7fffffff < ((INT32)testi64a << 3)) testi64a /= 2; @@ -271,544 +492,377 @@ static bool validate_inlines(void) resulti32 = div_32x32_shift((INT32)testi64a, testi32a, 3); expectedi32 = ((INT64)(INT32)testi64a << 3) / (INT64)testi32a; if (resulti32 != expectedi32) - { mame_printf_error("Error testing div_32x32_shift (%08X << 3) / %08X = %08X (expected %08X)\n", (INT32)testi64a, testi32a, resulti32, expectedi32); error = true; } + mame_printf_error("Error testing div_32x32_shift (%08X << 3) / %08X = %08X (expected %08X)\n", (INT32)testi64a, testi32a, resulti32, expectedi32); resultu32 = divu_32x32_shift((UINT32)testu64a, testu32a, 3); expectedu32 = ((UINT64)(UINT32)testu64a << 3) / (UINT64)testu32a; if (resultu32 != expectedu32) - { mame_printf_error("Error testing divu_32x32_shift (%08X << 3) / %08X = %08X (expected %08X)\n", (UINT32)testu64a, testu32a, resultu32, expectedu32); error = true; } + mame_printf_error("Error testing divu_32x32_shift (%08X << 3) / %08X = %08X (expected %08X)\n", (UINT32)testu64a, testu32a, resultu32, expectedu32); if (fabs(recip_approx(100.0) - 0.01) > 0.0001) - { mame_printf_error("Error testing recip_approx\n"); error = true; } + mame_printf_error("Error testing recip_approx\n"); testi32a = (testi32a & 0x0000ffff) | 0x400000; if (count_leading_zeros(testi32a) != 9) - { mame_printf_error("Error testing count_leading_zeros\n"); error = true; } + mame_printf_error("Error testing count_leading_zeros\n"); testi32a = (testi32a | 0xffff0000) & ~0x400000; if (count_leading_ones(testi32a) != 9) - { mame_printf_error("Error testing count_leading_ones\n"); error = true; } + mame_printf_error("Error testing count_leading_ones\n"); testi32b = testi32a; if (compare_exchange32(&testi32a, testi32b, 1000) != testi32b || testi32a != 1000) - { mame_printf_error("Error testing compare_exchange32\n"); error = true; } + mame_printf_error("Error testing compare_exchange32\n"); #ifdef PTR64 testi64b = testi64a; if (compare_exchange64(&testi64a, testi64b, 1000) != testi64b || testi64a != 1000) - { mame_printf_error("Error testing compare_exchange64\n"); error = true; } + mame_printf_error("Error testing compare_exchange64\n"); #endif if (atomic_exchange32(&testi32a, testi32b) != 1000) - { mame_printf_error("Error testing atomic_exchange32\n"); error = true; } + mame_printf_error("Error testing atomic_exchange32\n"); if (atomic_add32(&testi32a, 45) != testi32b + 45) - { mame_printf_error("Error testing atomic_add32\n"); error = true; } + mame_printf_error("Error testing atomic_add32\n"); if (atomic_increment32(&testi32a) != testi32b + 46) - { mame_printf_error("Error testing atomic_increment32\n"); error = true; } + mame_printf_error("Error testing atomic_increment32\n"); if (atomic_decrement32(&testi32a) != testi32b + 45) - { mame_printf_error("Error testing atomic_decrement32\n"); error = true; } - - return error; + mame_printf_error("Error testing atomic_decrement32\n"); } -/*------------------------------------------------- - validate_driver - validate basic driver - information --------------------------------------------------*/ +//------------------------------------------------- +// validate_driver - validate basic driver +// information +//------------------------------------------------- -static bool validate_driver(driver_enumerator &drivlist, game_driver_map &names, game_driver_map &descriptions) +void validity_checker::validate_driver() { - const game_driver &driver = drivlist.driver(); - const machine_config &config = drivlist.config(); - const char *compatible_with; - bool error = FALSE, is_clone; - const char *s; - - enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 }; - - /* check for duplicate names */ - if (names.add(driver.name, &driver, FALSE) == TMERR_DUPLICATE) + // check for duplicate names + astring tempstr; + if (m_names_map.add(m_current_driver->name, m_current_driver, false) == TMERR_DUPLICATE) { - const game_driver *match = names.find(driver.name); - mame_printf_error("%s: %s is a duplicate name (%s, %s)\n", driver.source_file, driver.name, match->source_file, match->name); - error = true; + const game_driver *match = m_names_map.find(m_current_driver->name); + mame_printf_error("Driver name is a duplicate of %s(%s)\n", core_filename_extract_base(tempstr, match->source_file).cstr(), match->name); } - /* check for duplicate descriptions */ - if (descriptions.add(driver.description, &driver, FALSE) == TMERR_DUPLICATE) + // check for duplicate descriptions + if (m_descriptions_map.add(m_current_driver->description, m_current_driver, false) == TMERR_DUPLICATE) { - const game_driver *match = descriptions.find(driver.description); - mame_printf_error("%s: %s is a duplicate description (%s, %s)\n", driver.source_file, driver.description, match->source_file, match->description); - error = true; + const game_driver *match = m_descriptions_map.find(m_current_driver->description); + mame_printf_error("Driver description is a duplicate of %s(%s)\n", core_filename_extract_base(tempstr, match->source_file).cstr(), match->name); } - /* determine the clone */ - is_clone = (strcmp(driver.parent, "0") != 0); - int clone_of = drivlist.clone(driver); - if (clone_of != -1 && (drivlist.driver(clone_of).flags & GAME_IS_BIOS_ROOT)) + // determine if we are a clone + bool is_clone = (strcmp(m_current_driver->parent, "0") != 0); + int clone_of = m_drivlist.clone(*m_current_driver); + if (clone_of != -1 && (m_drivlist.driver(clone_of).flags & GAME_IS_BIOS_ROOT)) is_clone = false; - /* if we have at least 100 drivers, validate the clone */ - /* (100 is arbitrary, but tries to avoid tiny.mak dependencies) */ + // if we have at least 100 drivers, validate the clone + // (100 is arbitrary, but tries to avoid tiny.mak dependencies) if (driver_list::total() > 100 && clone_of == -1 && is_clone) - { - mame_printf_error("%s: %s is a non-existant clone\n", driver.source_file, driver.parent); - error = true; - } + mame_printf_error("Driver is a clone of nonexistant driver %s\n", m_current_driver->parent); - /* look for recursive cloning */ - if (clone_of != -1 && &drivlist.driver(clone_of) == &driver) - { - mame_printf_error("%s: %s is set as a clone of itself\n", driver.source_file, driver.name); - error = true; - } + // look for recursive cloning + if (clone_of != -1 && &m_drivlist.driver(clone_of) == m_current_driver) + mame_printf_error("Driver is a clone of itself\n"); - /* look for clones that are too deep */ - if (clone_of != -1 && (clone_of = drivlist.non_bios_clone(clone_of)) != -1) - { - mame_printf_error("%s: %s is a clone of a clone\n", driver.source_file, driver.name); - error = true; - } + // look for clones that are too deep + if (clone_of != -1 && (clone_of = m_drivlist.non_bios_clone(clone_of)) != -1) + mame_printf_error("Driver is a clone of a clone\n"); - /* make sure the driver name is 8 chars or less */ - if ((is_clone && strlen(driver.name) > NAME_LEN_CLONE) || ((!is_clone) && strlen(driver.name) > NAME_LEN_PARENT)) - { - mame_printf_error("%s: %s %s driver name must be %d characters or less\n", driver.source_file, driver.name, - is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT); - error = true; - } + // make sure the driver name is not too long + if (!is_clone && strlen(m_current_driver->name) > 8) + mame_printf_error("Parent driver name must be 8 characters or less\n"); + if (is_clone && strlen(m_current_driver->name) > 16) + mame_printf_error("Clone driver name must be 16 characters or less\n"); - /* make sure the year is only digits, '?' or '+' */ - for (s = driver.year; *s; s++) + // make sure the year is only digits, '?' or '+' + for (const char *s = m_current_driver->year; *s != 0; s++) if (!isdigit((UINT8)*s) && *s != '?' && *s != '+') { - mame_printf_error("%s: %s has an invalid year '%s'\n", driver.source_file, driver.name, driver.year); - error = true; + mame_printf_error("Driver has an invalid year '%s'\n", m_current_driver->year); break; } - /* normalize driver->compatible_with */ - compatible_with = driver.compatible_with; - if ((compatible_with != NULL) && !strcmp(compatible_with, "0")) + // normalize driver->compatible_with + const char *compatible_with = m_current_driver->compatible_with; + if (compatible_with != NULL && strcmp(compatible_with, "0") == 0) compatible_with = NULL; - /* check for this driver being compatible with a non-existant driver */ - if ((compatible_with != NULL) && (drivlist.find(driver.compatible_with) == -1)) - { - mame_printf_error("%s: is compatible with %s, which is not in drivers[]\n", driver.name, driver.compatible_with); - error = true; - } + // check for this driver being compatible with a non-existant driver + if (compatible_with != NULL && m_drivlist.find(m_current_driver->compatible_with) == -1) + mame_printf_error("Driver is listed as compatible with nonexistant driver %s\n", m_current_driver->compatible_with); - /* check for clone_of and compatible_with being specified at the same time */ - if ((drivlist.clone(driver) != -1) && (compatible_with != NULL)) - { - mame_printf_error("%s: both compatible_with and clone_of are specified\n", driver.name); - error = true; - } + // check for clone_of and compatible_with being specified at the same time + if (m_drivlist.clone(*m_current_driver) != -1 && compatible_with != NULL) + mame_printf_error("Driver cannot be both a clone and listed as compatible with another system\n"); - /* find any recursive dependencies on the current driver */ - for (int other_drv = drivlist.compatible_with(driver); other_drv != -1; other_drv = drivlist.compatible_with(other_drv)) - { - if (&driver == &drivlist.driver(other_drv)) + // find any recursive dependencies on the current driver + for (int other_drv = m_drivlist.compatible_with(*m_current_driver); other_drv != -1; other_drv = m_drivlist.compatible_with(other_drv)) + if (m_current_driver == &m_drivlist.driver(other_drv)) { - mame_printf_error("%s: recursive compatibility\n", driver.name); - error = true; + mame_printf_error("Driver is recursively compatible with itself\n"); break; } - } - - /* make sure sound-less drivers are flagged */ - const device_sound_interface *sound; - if ((driver.flags & GAME_IS_BIOS_ROOT) == 0 && !config.devicelist().first(sound) && (driver.flags & GAME_NO_SOUND) == 0 && (driver.flags & GAME_NO_SOUND_HW) == 0) - { - mame_printf_error("%s: %s missing GAME_NO_SOUND flag\n", driver.source_file, driver.name); - error = true; - } - return error; + // make sure sound-less drivers are flagged + sound_interface_iterator iter(m_current_config->root_device()); + if ((m_current_driver->flags & GAME_IS_BIOS_ROOT) == 0 && iter.first() == NULL && (m_current_driver->flags & GAME_NO_SOUND) == 0 && (m_current_driver->flags & GAME_NO_SOUND_HW) == 0) + mame_printf_error("Driver is missing GAME_NO_SOUND flag\n"); } -/*------------------------------------------------- - validate_roms - validate ROM definitions --------------------------------------------------*/ +//------------------------------------------------- +// validate_roms - validate ROM definitions +//------------------------------------------------- -static bool validate_roms(driver_enumerator &drivlist, region_array *rgninfo, game_driver_map &roms) +void validity_checker::validate_roms() { - const game_driver &driver = drivlist.driver(); - const machine_config &config = drivlist.config(); - int bios_flags = 0, last_bios = 0; - const char *last_rgnname = "???"; - const char *last_name = "???"; - region_entry *currgn = NULL; - int items_since_region = 1; - bool error = false; - - const rom_source *first_source = rom_first_source(config); - - /* iterate, starting with the driver's ROMs and continuing with device ROMs */ - for (const rom_source *source = rom_first_source(config); source != NULL; source = rom_next_source(*source)) + // iterate, starting with the driver's ROMs and continuing with device ROMs + for (const rom_source *source = rom_first_source(*m_current_config); source != NULL; source = rom_next_source(*source)) { - /* scan the ROM entries */ + // for non-root devices, track the current device + m_current_device = (source == &m_current_config->root_device()) ? NULL : source; + + // scan the ROM entries for this device + const char *last_region_name = "???"; + const char *last_name = "???"; + UINT32 current_length = 0; + int items_since_region = 1; + int last_bios = 0; + int total_files = 0; for (const rom_entry *romp = rom_first_region(*source); !ROMENTRY_ISEND(romp); romp++) { - /* if this is a region, make sure it's valid, and record the length */ + // if this is a region, make sure it's valid, and record the length if (ROMENTRY_ISREGION(romp)) { - const char *regiontag = ROMREGION_GETTAG(romp); - - /* if we haven't seen any items since the last region, print a warning */ + // if we haven't seen any items since the last region, print a warning if (items_since_region == 0) - mame_printf_warning("%s: %s has empty ROM region '%s' (warning)\n", driver.source_file, driver.name, last_rgnname); + mame_printf_warning("Empty ROM region '%s' (warning)\n", last_region_name); + + // reset our region tracking states + const char *basetag = ROMREGION_GETTAG(romp); items_since_region = (ROMREGION_ISERASE(romp) || ROMREGION_ISDISKDATA(romp)) ? 1 : 0; - currgn = NULL; - last_rgnname = regiontag; + last_region_name = basetag; - /* check for a valid tag */ - if (regiontag == NULL) + // check for a valid tag + if (basetag == NULL) { - mame_printf_error("%s: %s has NULL ROM_REGION tag\n", driver.source_file, driver.name); - error = true; + mame_printf_error("ROM_REGION tag with NULL name\n"); + continue; } - /* find any empty entry, checking for duplicates */ - else - { - astring fulltag; - - /* iterate over all regions found so far */ - rom_region_name(fulltag, &driver, source, romp); - for (int rgnnum = 0; rgnnum < ARRAY_LENGTH(rgninfo->entries); rgnnum++) - { - /* stop when we hit an empty */ - if (!rgninfo->entries[rgnnum].tag) - { - currgn = &rgninfo->entries[rgnnum]; - currgn->tag = fulltag; - currgn->length = ROMREGION_GETLENGTH(romp); - break; - } - - /* fail if we hit a duplicate */ - if (fulltag == rgninfo->entries[rgnnum].tag) - { - mame_printf_error("%s: %s has duplicate ROM_REGION tag '%s'\n", driver.source_file, driver.name, fulltag.cstr()); - error = true; - break; - } - } - } - - /* validate the region tag */ - if (!validate_tag(driver, "region", regiontag)) - error = true; + // validate the base tag + validate_tag(basetag); + + // generate the full tag + astring fulltag; + rom_region_name(fulltag, m_current_driver, source, romp); + + // attempt to add it to the map, reporting duplicates as errors + current_length = ROMREGION_GETLENGTH(romp); + if (m_region_map.add(fulltag, current_length, false) == TMERR_DUPLICATE) + mame_printf_error("Multiple ROM_REGIONs with the same tag '%s' defined\n", fulltag.cstr()); } - /* If this is a system bios, make sure it is using the next available bios number */ + // If this is a system bios, make sure it is using the next available bios number else if (ROMENTRY_ISSYSTEM_BIOS(romp)) { - bios_flags = ROM_GETBIOSFLAGS(romp); - if (last_bios+1 != bios_flags) - { - const char *name = ROM_GETNAME(romp); - mame_printf_error("%s: %s has non-sequential bios %s\n", driver.source_file, driver.name, name); - error = true; - } + int bios_flags = ROM_GETBIOSFLAGS(romp); + if (bios_flags != last_bios + 1) + mame_printf_error("Non-sequential bios %s (specified as %d, expected to be %d)\n", ROM_GETNAME(romp), bios_flags, last_bios + 1); last_bios = bios_flags; } - /* if this is a file, make sure it is properly formatted */ + // if this is a file, make sure it is properly formatted else if (ROMENTRY_ISFILE(romp)) { - const char *s; - - items_since_region++; - - /* track the last filename we found */ + // track the last filename we found last_name = ROM_GETNAME(romp); + total_files++; - /* make sure it's all lowercase */ - for (s = last_name; *s; s++) + // make sure it's all lowercase + for (const char *s = last_name; *s != 0; s++) if (tolower((UINT8)*s) != *s) { - mame_printf_error("%s: %s has upper case ROM name %s\n", driver.source_file, driver.name, last_name); - error = true; + mame_printf_error("ROM name '%s' contains upper case characters\n", last_name); break; } - /* make sure the hash is valid */ + // make sure the hash is valid hash_collection hashes; if (!hashes.from_internal_string(ROM_GETHASHDATA(romp))) - { - mame_printf_error("%s: rom '%s' has an invalid hash string '%s'\n", driver.name, last_name, ROM_GETHASHDATA(romp)); - error = true; - } + mame_printf_error("ROM '%s' has an invalid hash string '%s'\n", last_name, ROM_GETHASHDATA(romp)); } - // count copies/fills as valid items - else if (ROMENTRY_ISCOPY(romp) || ROMENTRY_ISFILL(romp)) - items_since_region++; - - /* for any non-region ending entries, make sure they don't extend past the end */ - if (!ROMENTRY_ISREGIONEND(romp) && currgn != NULL) + // for any non-region ending entries, make sure they don't extend past the end + if (!ROMENTRY_ISREGIONEND(romp) && current_length > 0) { items_since_region++; - - if (ROM_GETOFFSET(romp) + ROM_GETLENGTH(romp) > currgn->length) - { - mame_printf_error("%s: %s has ROM %s extending past the defined memory region\n", driver.source_file, driver.name, last_name); - error = true; - } + if (ROM_GETOFFSET(romp) + ROM_GETLENGTH(romp) > current_length) + mame_printf_error("ROM '%s' extends past the defined memory region\n", last_name); } } - /* final check for empty regions */ + // final check for empty regions if (items_since_region == 0) - mame_printf_warning("%s: %s has empty ROM region (warning)\n", driver.source_file, driver.name); + mame_printf_warning("Empty ROM region '%s' (warning)\n", last_region_name); - if (source!=first_source) { - // check for device roms - device_type type = source->type(); - int cnt = 0; - for (const rom_entry *romp = rom_first_region(*source); !ROMENTRY_ISEND(romp); romp++) - { - if (ROMENTRY_ISFILE(romp)) { - cnt++; - } - } - if (cnt > 0) { - bool found = false; - for(int i=0;i<m_device_count;i++) { - if (type==*s_devices_sorted[i]) - { - found = true; - break; - } + // make sure each device is listed in the device list if it loads ROMs + if (m_current_device != NULL && total_files > 0) + { + // scan the list of devices for this device type + bool found = false; + for (int i = 0; i < m_device_count; i++) + if (m_current_device->type() == *s_devices_sorted[i]) + { + found = true; + break; } - if (!found) - mame_printf_error("Device %s is not listed in device list (mame_dev.lst / mess_dev.lst)\n", source->shortname()); - } + + // if not found, report an error + if (!found) + mame_printf_error("Device %s is not listed in device list (mame_dev.lst / mess_dev.lst)\n", m_current_device->shortname()); } - } - return error; + // reset the current device + m_current_device = NULL; + } } -/*------------------------------------------------- - validate_display - validate display - configurations --------------------------------------------------*/ +//------------------------------------------------- +// validate_display - validate display +// configurations +//------------------------------------------------- -static bool validate_display(driver_enumerator &drivlist) +void validity_checker::validate_display() { - const game_driver &driver = drivlist.driver(); - const machine_config &config = drivlist.config(); + // iterate over screen devices looking for paletted screens + screen_device_iterator iter(m_current_config->root_device()); bool palette_modes = false; - bool error = false; - - for (const screen_device *scrconfig = config.first_screen(); scrconfig != NULL; scrconfig = scrconfig->next_screen()) + for (const screen_device *scrconfig = iter.first(); scrconfig != NULL; scrconfig = iter.next()) if (scrconfig->format() == BITMAP_FORMAT_IND16) palette_modes = true; - /* check for empty palette */ - if (palette_modes && config.m_total_colors == 0) - { - mame_printf_error("%s: %s has zero palette entries\n", driver.source_file, driver.name); - error = true; - } - - return error; + // check for empty palette + if (palette_modes && m_current_config->m_total_colors == 0) + mame_printf_error("Driver has zero palette entries but uses a palette-based bitmap format\n"); } -/*------------------------------------------------- - validate_gfx - validate graphics decoding - configuration --------------------------------------------------*/ +//------------------------------------------------- +// validate_gfx - validate graphics decoding +// configuration +//------------------------------------------------- -static bool validate_gfx(driver_enumerator &drivlist, region_array *rgninfo) +void validity_checker::validate_gfx() { - const game_driver &driver = drivlist.driver(); - const machine_config &config = drivlist.config(); - bool error = false; - int gfxnum; - - /* bail if no gfx */ - if (!config.m_gfxdecodeinfo) - return false; + // bail if no gfx + if (!m_current_config->m_gfxdecodeinfo) + return; - /* iterate over graphics decoding entries */ - for (gfxnum = 0; gfxnum < MAX_GFX_ELEMENTS && config.m_gfxdecodeinfo[gfxnum].gfxlayout != NULL; gfxnum++) + // iterate over graphics decoding entries + for (int gfxnum = 0; gfxnum < MAX_GFX_ELEMENTS && m_current_config->m_gfxdecodeinfo[gfxnum].gfxlayout != NULL; gfxnum++) { - const gfx_decode_entry *gfx = &config.m_gfxdecodeinfo[gfxnum]; - const char *region = gfx->memory_region; - int xscale = (config.m_gfxdecodeinfo[gfxnum].xscale == 0) ? 1 : config.m_gfxdecodeinfo[gfxnum].xscale; - int yscale = (config.m_gfxdecodeinfo[gfxnum].yscale == 0) ? 1 : config.m_gfxdecodeinfo[gfxnum].yscale; - const gfx_layout *gl = gfx->gfxlayout; - int israw = (gl->planeoffset[0] == GFX_RAW); - int planes = gl->planes; - UINT16 width = gl->width; - UINT16 height = gl->height; - UINT32 total = gl->total; - - /* make sure the region exists */ + const gfx_decode_entry &gfx = m_current_config->m_gfxdecodeinfo[gfxnum]; + const gfx_layout &layout = *gfx.gfxlayout; + + // make sure the region exists + const char *region = gfx.memory_region; if (region != NULL) { - int rgnnum; - - /* loop over gfx regions */ - for (rgnnum = 0; rgnnum < ARRAY_LENGTH(rgninfo->entries); rgnnum++) - { - /* stop if we hit an empty */ - if (!rgninfo->entries[rgnnum].tag) - { - mame_printf_error("%s: %s has gfx[%d] referencing non-existent region '%s'\n", driver.source_file, driver.name, gfxnum, region); - error = true; - break; - } - - /* if we hit a match, check against the length */ - if (rgninfo->entries[rgnnum].tag == region) - { - /* if we have a valid region, and we're not using auto-sizing, check the decode against the region length */ - if (!IS_FRAC(total)) - { - int len, avail, plane, start; - UINT32 charincrement = gl->charincrement; - const UINT32 *poffset = gl->planeoffset; + // resolve the region + astring gfxregion; + m_current_config->root_device().subtag(gfxregion, region); - /* determine which plane is the largest */ - start = 0; - for (plane = 0; plane < planes; plane++) - if (poffset[plane] > start) - start = poffset[plane]; - start &= ~(charincrement - 1); + // loop over gfx regions + UINT32 region_length = m_region_map.find(gfxregion); + if (region_length == 0) + mame_printf_error("gfx[%d] references non-existent region '%s'\n", gfxnum, region); - /* determine the total length based on this info */ - len = total * charincrement; - - /* do we have enough space in the region to cover the whole decode? */ - avail = rgninfo->entries[rgnnum].length - (gfx->start & ~(charincrement/8-1)); - - /* if not, this is an error */ - if ((start + len) / 8 > avail) - { - mame_printf_error("%s: %s has gfx[%d] extending past allocated memory of region '%s'\n", driver.source_file, driver.name, gfxnum, region); - error = true; - } - } - break; - } + // if we have a valid region, and we're not using auto-sizing, check the decode against the region length + else if (!IS_FRAC(layout.total)) + { + // determine which plane is at the largest offset + int start = 0; + for (int plane = 0; plane < layout.planes; plane++) + if (layout.planeoffset[plane] > start) + start = layout.planeoffset[plane]; + start &= ~(layout.charincrement - 1); + + // determine the total length based on this info + int len = layout.total * layout.charincrement; + + // do we have enough space in the region to cover the whole decode? + int avail = region_length - (gfx.start & ~(layout.charincrement / 8 - 1)); + + // if not, this is an error + if ((start + len) / 8 > avail) + mame_printf_error("gfx[%d] extends past allocated memory of region '%s'\n", gfxnum, region); } } - if (israw) + int xscale = (m_current_config->m_gfxdecodeinfo[gfxnum].xscale == 0) ? 1 : m_current_config->m_gfxdecodeinfo[gfxnum].xscale; + int yscale = (m_current_config->m_gfxdecodeinfo[gfxnum].yscale == 0) ? 1 : m_current_config->m_gfxdecodeinfo[gfxnum].yscale; + + // verify raw decode, which can only be full-region and have no scaling + if (layout.planeoffset[0] == GFX_RAW) { - if (total != RGN_FRAC(1,1)) - { - mame_printf_error("%s: %s has gfx[%d] with unsupported layout total\n", driver.source_file, driver.name, gfxnum); - error = true; - } - + if (layout.total != RGN_FRAC(1,1)) + mame_printf_error("gfx[%d] with unsupported layout total\n", gfxnum); if (xscale != 1 || yscale != 1) - { - mame_printf_error("%s: %s has gfx[%d] with unsupported xscale/yscale\n", driver.source_file, driver.name, gfxnum); - error = true; - } + mame_printf_error("gfx[%d] with unsupported xscale/yscale\n", gfxnum); } + + // verify traditional decode doesn't have too many planes or is not too large else { - if (planes > MAX_GFX_PLANES) - { - mame_printf_error("%s: %s has gfx[%d] with invalid planes\n", driver.source_file, driver.name, gfxnum); - error = true; - } - - if (xscale * width > MAX_ABS_GFX_SIZE || yscale * height > MAX_ABS_GFX_SIZE) - { - mame_printf_error("%s: %s has gfx[%d] with invalid xscale/yscale\n", driver.source_file, driver.name, gfxnum); - error = true; - } + if (layout.planes > MAX_GFX_PLANES) + mame_printf_error("gfx[%d] with invalid planes\n", gfxnum); + if (xscale * layout.width > MAX_ABS_GFX_SIZE || yscale * layout.height > MAX_ABS_GFX_SIZE) + mame_printf_error("gfx[%d] with invalid xscale/yscale\n", gfxnum); } } - - return error; -} - - -/*------------------------------------------------- - get_defstr_index - return the index of the - string assuming it is one of the default - strings --------------------------------------------------*/ - -static int get_defstr_index(int_map &defstr_map, const char *name, const game_driver &driver, bool *error) -{ - /* check for strings that should be DEF_STR */ - int strindex = defstr_map.find(name); - if (strindex != 0 && name != input_port_string_from_index(strindex) && error != NULL) - { - mame_printf_error("%s: %s must use DEF_STR( %s )\n", driver.source_file, driver.name, name); - *error = true; - } - - return strindex; } -/*------------------------------------------------- - validate_analog_input_field - validate an - analog input field --------------------------------------------------*/ +//------------------------------------------------- +// validate_analog_input_field - validate an +// analog input field +//------------------------------------------------- -static void validate_analog_input_field(input_field_config *field, const game_driver &driver, bool *error) +void validity_checker::validate_analog_input_field(input_field_config &field) { - INT32 analog_max = field->max; - INT32 analog_min = field->min; - int shift; + // analog ports must have a valid sensitivity + if (field.sensitivity == 0) + mame_printf_error("Analog port with zero sensitivity\n"); - if (field->type == IPT_POSITIONAL || field->type == IPT_POSITIONAL_V) - { - for (shift = 0; (shift <= 31) && (~field->mask & (1 << shift)); shift++) ; - /* convert the positional max value to be in the bitmask for testing */ - analog_max = (analog_max - 1) << shift; + // check that the default falls in the bitmask range + if (field.defvalue & ~field.mask) + mame_printf_error("Analog port with a default value (%X) out of the bitmask range (%X)\n", field.defvalue, field.mask); - /* positional port size must fit in bits used */ - if (((field->mask >> shift) + 1) < field->max) - { - mame_printf_error("%s: %s has an analog port with a positional port size bigger then the mask size\n", driver.source_file, driver.name); - *error = true; - } - } - else + // tests for positional devices + if (field.type == IPT_POSITIONAL || field.type == IPT_POSITIONAL_V) { - /* only positional controls use PORT_WRAPS */ - if (field->flags & ANALOG_FLAG_WRAPS) - { - mame_printf_error("%s: %s only positional analog ports use PORT_WRAPS\n", driver.source_file, driver.name); - *error = true; - } - } + int shift; + for (shift = 0; shift <= 31 && (~field.mask & (1 << shift)) != 0; shift++) ; - /* analog ports must have a valid sensitivity */ - if (field->sensitivity == 0) - { - mame_printf_error("%s: %s has an analog port with zero sensitivity\n", driver.source_file, driver.name); - *error = true; - } + // convert the positional max value to be in the bitmask for testing + INT32 analog_max = field.max; + analog_max = (analog_max - 1) << shift; - /* check that the default falls in the bitmask range */ - if (field->defvalue & ~field->mask) - { - mame_printf_error("%s: %s has an analog port with a default value out of the bitmask range\n", driver.source_file, driver.name); - *error = true; + // positional port size must fit in bits used + if ((field.mask >> shift) + 1 < field.max) + mame_printf_error("Analog port with a positional port size bigger then the mask size\n"); } - /* tests for absolute devices */ - if (field->type >= __ipt_analog_absolute_start && field->type <= __ipt_analog_absolute_end) + // tests for absolute devices + else if (field.type >= __ipt_analog_absolute_start && field.type <= __ipt_analog_absolute_end) { - INT32 default_value = field->defvalue; - - /* adjust for signed values */ + // adjust for signed values + INT32 default_value = field.defvalue; + INT32 analog_min = field.min; + INT32 analog_max = field.max; if (analog_min > analog_max) { analog_min = -analog_min; @@ -816,506 +870,388 @@ static void validate_analog_input_field(input_field_config *field, const game_dr default_value = -default_value; } - /* check that the default falls in the MINMAX range */ + // check that the default falls in the MINMAX range if (default_value < analog_min || default_value > analog_max) - { - mame_printf_error("%s: %s has an analog port with a default value out PORT_MINMAX range\n", driver.source_file, driver.name); - *error = true; - } + mame_printf_error("Analog port with a default value (%X) out of PORT_MINMAX range (%X-%X)\n", field.defvalue, field.min, field.max); - /* check that the MINMAX falls in the bitmask range */ - /* we use the unadjusted min for testing */ - if (field->min & ~field->mask || analog_max & ~field->mask) - { - mame_printf_error("%s: %s has an analog port with a PORT_MINMAX value out of the bitmask range\n", driver.source_file, driver.name); - *error = true; - } + // check that the MINMAX falls in the bitmask range + // we use the unadjusted min for testing + if (field.min & ~field.mask || analog_max & ~field.mask) + mame_printf_error("Analog port with a PORT_MINMAX (%X-%X) value out of the bitmask range (%X)\n", field.min, field.max, field.mask); - /* absolute analog ports do not use PORT_RESET */ - if (field->flags & ANALOG_FLAG_RESET) - { - mame_printf_error("%s: %s - absolute analog ports do not use PORT_RESET\n", driver.source_file, driver.name); - *error = true; - } + // absolute analog ports do not use PORT_RESET + if (field.flags & ANALOG_FLAG_RESET) + mame_printf_error("Absolute analog port using PORT_RESET\n"); + + // absolute analog ports do not use PORT_WRAPS + if (field.flags & ANALOG_FLAG_WRAPS) + mame_printf_error("Absolute analog port using PORT_WRAPS\n"); } - /* tests for relative devices */ + // tests for non IPT_POSITIONAL relative devices else { - /* tests for non IPT_POSITIONAL relative devices */ - if (field->type != IPT_POSITIONAL && field->type != IPT_POSITIONAL_V) - { - /* relative devices do not use PORT_MINMAX */ - if (field->min != 0 || field->max != field->mask) - { - mame_printf_error("%s: %s - relative ports do not use PORT_MINMAX\n", driver.source_file, driver.name); - *error = true; - } - - /* relative devices do not use a default value */ - /* the counter is at 0 on power up */ - if (field->defvalue != 0) - { - mame_printf_error("%s: %s - relative ports do not use a default value other then 0\n", driver.source_file, driver.name); - *error = true; - } - } + // relative devices do not use PORT_MINMAX + if (field.min != 0 || field.max != field.mask) + mame_printf_error("Relative port using PORT_MINMAX\n"); + + // relative devices do not use a default value + // the counter is at 0 on power up + if (field.defvalue != 0) + mame_printf_error("Relative port using non-0 default value\n"); + + // relative analog ports do not use PORT_WRAPS + if (field.flags & ANALOG_FLAG_WRAPS) + mame_printf_error("Absolute analog port using PORT_WRAPS\n"); } } -/*------------------------------------------------- - validate_dip_settings - validate a DIP switch - setting --------------------------------------------------*/ +//------------------------------------------------- +// validate_dip_settings - validate a DIP switch +// setting +//------------------------------------------------- -static void validate_dip_settings(input_field_config *field, const game_driver &driver, int_map &defstr_map, bool *error) +void validity_checker::validate_dip_settings(input_field_config &field) { - const char *demo_sounds = input_port_string_from_index(INPUT_STRING_Demo_Sounds); - const char *flipscreen = input_port_string_from_index(INPUT_STRING_Flip_Screen); + const char *demo_sounds = ioport_string_from_index(INPUT_STRING_Demo_Sounds); + const char *flipscreen = ioport_string_from_index(INPUT_STRING_Flip_Screen); UINT8 coin_list[__input_string_coinage_end + 1 - __input_string_coinage_start] = { 0 }; - const input_setting_config *setting; - int coin_error = FALSE; + bool coin_error = false; - /* iterate through the settings */ - for (setting = field->settinglist().first(); setting != NULL; setting = setting->next()) + // iterate through the settings + for (const input_setting_config *setting = field.settinglist().first(); setting != NULL; setting = setting->next()) { - int strindex = get_defstr_index(defstr_map, setting->name, driver, error); - - /* note any coinage strings */ + // note any coinage strings + int strindex = get_defstr_index(setting->name); if (strindex >= __input_string_coinage_start && strindex <= __input_string_coinage_end) coin_list[strindex - __input_string_coinage_start] = 1; - /* make sure demo sounds default to on */ - if (field->name == demo_sounds && strindex == INPUT_STRING_On && field->defvalue != setting->value) - { - mame_printf_error("%s: %s Demo Sounds must default to On\n", driver.source_file, driver.name); - *error = true; - } + // make sure demo sounds default to on + if (field.name == demo_sounds && strindex == INPUT_STRING_On && field.defvalue != setting->value) + mame_printf_error("Demo Sounds must default to On\n"); - /* check for bad demo sounds options */ - if (field->name == demo_sounds && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No)) - { - mame_printf_error("%s: %s has wrong Demo Sounds option %s (must be Off/On)\n", driver.source_file, driver.name, setting->name); - *error = true; - } + // check for bad demo sounds options + if (field.name == demo_sounds && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No)) + mame_printf_error("Demo Sounds option must be Off/On, not %s\n", setting->name); - /* check for bad flip screen options */ - if (field->name == flipscreen && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No)) - { - mame_printf_error("%s: %s has wrong Flip Screen option %s (must be Off/On)\n", driver.source_file, driver.name, setting->name); - *error = true; - } + // check for bad flip screen options + if (field.name == flipscreen && (strindex == INPUT_STRING_Yes || strindex == INPUT_STRING_No)) + mame_printf_error("Flip Screen option must be Off/On, not %s\n", setting->name); - /* if we have a neighbor, compare ourselves to him */ + // if we have a neighbor, compare ourselves to him if (setting->next() != NULL) { - int next_strindex = get_defstr_index(defstr_map, setting->next()->name, driver, error); - - /* check for inverted off/on dispswitch order */ + // check for inverted off/on dispswitch order + int next_strindex = get_defstr_index(setting->next()->name, true); if (strindex == INPUT_STRING_On && next_strindex == INPUT_STRING_Off) - { - mame_printf_error("%s: %s has inverted Off/On dipswitch order\n", driver.source_file, driver.name); - *error = true; - } + mame_printf_error("%s option must have Off/On options in the order: Off, On\n", field.name); - /* check for inverted yes/no dispswitch order */ + // check for inverted yes/no dispswitch order else if (strindex == INPUT_STRING_Yes && next_strindex == INPUT_STRING_No) - { - mame_printf_error("%s: %s has inverted No/Yes dipswitch order\n", driver.source_file, driver.name); - *error = true; - } + mame_printf_error("%s option must have Yes/No options in the order: No, Yes\n", field.name); - /* check for inverted upright/cocktail dispswitch order */ + // check for inverted upright/cocktail dispswitch order else if (strindex == INPUT_STRING_Cocktail && next_strindex == INPUT_STRING_Upright) - { - mame_printf_error("%s: %s has inverted Upright/Cocktail dipswitch order\n", driver.source_file, driver.name); - *error = true; - } + mame_printf_error("%s option must have Upright/Cocktail options in the order: Upright, Cocktail\n", field.name); - /* check for proper coin ordering */ + // check for proper coin ordering else if (strindex >= __input_string_coinage_start && strindex <= __input_string_coinage_end && next_strindex >= __input_string_coinage_start && next_strindex <= __input_string_coinage_end && strindex >= next_strindex && memcmp(&setting->condition, &setting->next()->condition, sizeof(setting->condition)) == 0) { - mame_printf_error("%s: %s has unsorted coinage %s > %s\n", driver.source_file, driver.name, setting->name, setting->next()->name); - coin_error = *error = true; + mame_printf_error("%s option has unsorted coinage %s > %s\n", field.name, setting->name, setting->next()->name); + coin_error = true; } } } - /* if we have a coin error, demonstrate the correct way */ + // if we have a coin error, demonstrate the correct way if (coin_error) { - int entry; - - mame_printf_error("%s: %s proper coin sort order should be:\n", driver.source_file, driver.name); - for (entry = 0; entry < ARRAY_LENGTH(coin_list); entry++) + output_via_delegate(m_saved_error_output, " Note proper coin sort order should be:\n"); + for (int entry = 0; entry < ARRAY_LENGTH(coin_list); entry++) if (coin_list[entry]) - mame_printf_error("%s\n", input_port_string_from_index(__input_string_coinage_start + entry)); + output_via_delegate(m_saved_error_output, " %s\n", ioport_string_from_index(__input_string_coinage_start + entry)); } } -/*------------------------------------------------- - validate_inputs - validate input configuration --------------------------------------------------*/ +//------------------------------------------------- +// validate_condition - validate a condition +// stored within an ioport field or setting +//------------------------------------------------- -static bool validate_inputs(driver_enumerator &drivlist, int_map &defstr_map, ioport_list &portlist) +void validity_checker::validate_condition(input_condition &condition, device_t &device, int_map &port_map) { - input_port_config *scanport; - input_port_config *port; - input_field_config *field; - const game_driver &driver = drivlist.driver(); - const machine_config &config = drivlist.config(); - int empty_string_found = FALSE; - bool error = false; - astring errorbuf; - - /* skip if no ports */ - if (driver.ipt == NULL) - return FALSE; - - /* allocate the input ports */ - for (device_t *cfg = config.devicelist().first(); cfg != NULL; cfg = cfg->next()) + // resolve the tag + astring porttag; + device.subtag(porttag, condition.tag); + + // then find a matching port + if (port_map.find(porttag) == 0) + mame_printf_error("Condition referencing non-existent ioport tag '%s'\n", condition.tag); +} + + +//------------------------------------------------- +// validate_inputs - validate input configuration +//------------------------------------------------- + +void validity_checker::validate_inputs() +{ + int_map port_map; + + // iterate over devices + device_iterator iter(m_current_config->root_device()); + for (device_t *device = iter.first(); device != NULL; device = iter.next()) { - input_port_list_init(*cfg, portlist, errorbuf); + // see if this device has ports; if not continue + if (device->input_ports() == NULL) + continue; + + // for non-root devices, track the current device + m_current_device = (device == &m_current_config->root_device()) ? NULL : device; + + // allocate the input ports + ioport_list portlist; + astring errorbuf; + input_port_list_init(*device, portlist, errorbuf); + + // report any errors during construction if (errorbuf) - { - mame_printf_error("%s: %s has input port errors:\n%s\n", driver.source_file, driver.name, errorbuf.cstr()); - error = true; - } - } + mame_printf_error("I/O port error during construction:\n%s\n", errorbuf.cstr()); - /* check for duplicate tags */ - for (port = portlist.first(); port != NULL; port = port->next()) - for (scanport = port->next(); scanport != NULL; scanport = scanport->next()) - if (strcmp(port->tag(), scanport->tag()) == 0) - { - mame_printf_error("%s: %s has a duplicate input port tag '%s'\n", driver.source_file, driver.name, port->tag()); - error = true; - } + // do a first pass over ports to add their names and find duplicates + for (input_port_config *port = portlist.first(); port != NULL; port = port->next()) + if (port_map.add(port->tag(), 1, false) == TMERR_DUPLICATE) + mame_printf_error("Multiple I/O ports with the same tag '%s' defined\n", port->tag()); - /* iterate over the results */ - for (port = portlist.first(); port != NULL; port = port->next()) - for (field = port->fieldlist().first(); field != NULL; field = field->next()) + // iterate over ports + for (input_port_config *port = portlist.first(); port != NULL; port = port->next()) { - input_setting_config *setting; - //int strindex = 0; - - /* verify analog inputs */ - if (input_type_is_analog(field->type)) - validate_analog_input_field(field, driver, &error); + m_current_ioport = port->tag(); - /* verify dip switches */ - if (field->type == IPT_DIPSWITCH) + // iterate through the fields on this port + for (input_field_config *field = port->fieldlist().first(); field != NULL; field = field->next()) { - /* dip switch fields must have a name */ - if (field->name == NULL) - { - mame_printf_error("%s: %s has a DIP switch name or setting with no name\n", driver.source_file, driver.name); - error = true; - } - - /* verify the settings list */ - validate_dip_settings(field, driver, defstr_map, &error); - } + // verify analog inputs + if (input_type_is_analog(field->type)) + validate_analog_input_field(*field); - /* look for invalid (0) types which should be mapped to IPT_OTHER */ - if (field->type == IPT_INVALID) - { - mame_printf_error("%s: %s has an input port with an invalid type (0); use IPT_OTHER instead\n", driver.source_file, driver.name); - error = true; - } + // look for invalid (0) types which should be mapped to IPT_OTHER + if (field->type == IPT_INVALID) + mame_printf_error("Field has an invalid type (0); use IPT_OTHER instead\n"); - /* verify names */ - if (field->name != NULL) - { - /* check for empty string */ - if (field->name[0] == 0 && !empty_string_found) + // verify dip switches + if (field->type == IPT_DIPSWITCH) { - mame_printf_error("%s: %s has an input with an empty string\n", driver.source_file, driver.name); - empty_string_found = error = true; - } + // dip switch fields must have a name + if (field->name == NULL) + mame_printf_error("DIP switch has a NULL name\n"); - /* check for trailing spaces */ - if (field->name[0] != 0 && field->name[strlen(field->name) - 1] == ' ') - { - mame_printf_error("%s: %s input '%s' has trailing spaces\n", driver.source_file, driver.name, field->name); - error = true; + // verify the settings list + validate_dip_settings(*field); } - /* check for invalid UTF-8 */ - if (!utf8_is_valid_string(field->name)) + // verify names + if (field->name != NULL) { - mame_printf_error("%s: %s input '%s' has invalid characters\n", driver.source_file, driver.name, field->name); - error = true; - } + // check for empty string + if (field->name[0] == 0) + mame_printf_error("Field name is an empty string\n"); - /* look up the string and print an error if default strings are not used */ - /*strindex = */get_defstr_index(defstr_map, field->name, driver, &error); - } + // check for trailing spaces + if (field->name[0] != 0 && field->name[strlen(field->name) - 1] == ' ') + mame_printf_error("Field '%s' has trailing spaces\n", field->name); - /* verify conditions on the field */ - if (field->condition.tag != NULL) - { - /* find a matching port */ - for (scanport = portlist.first(); scanport != NULL; scanport = scanport->next()) { - astring porttag; - port->owner().subtag(porttag, field->condition.tag); - if (strcmp(porttag.cstr(), scanport->tag()) == 0) - break; - } - /* if none, error */ - if (scanport == NULL) - { - mame_printf_error("%s: %s has a condition referencing non-existent input port tag '%s'\n", driver.source_file, driver.name, field->condition.tag); - error = true; - } - } + // check for invalid UTF-8 + if (!utf8_is_valid_string(field->name)) + mame_printf_error("Field '%s' has invalid characters\n", field->name); - /* verify conditions on the settings */ - for (setting = field->settinglist().first(); setting != NULL; setting = setting->next()) - if (setting->condition.tag != NULL) - { - /* find a matching port */ - for (scanport = portlist.first(); scanport != NULL; scanport = scanport->next()) { - astring porttag; - port->owner().subtag(porttag, setting->condition.tag); - if (strcmp(porttag.cstr(), scanport->tag()) == 0) - break; - } - /* if none, error */ - if (scanport == NULL) - { - mame_printf_error("%s: %s has a condition referencing non-existent input port tag '%s'\n", driver.source_file, driver.name, setting->condition.tag); - error = true; - } + // look up the string and print an error if default strings are not used + /*strindex =get_defstr_index(defstr_map, field->name, driver, &error);*/ } - } - error = error || validate_natural_keyboard_statics(); + // verify conditions on the field + if (field->condition.tag != NULL) + validate_condition(field->condition, *device, port_map); - return error; + // verify conditions on the settings + for (input_setting_config *setting = field->settinglist().first(); setting != NULL; setting = setting->next()) + if (setting->condition.tag != NULL) + validate_condition(setting->condition, *device, port_map); + } + + // done with this port + m_current_ioport = NULL; + } + + // done with this device + m_current_device = NULL; + } } -/*------------------------------------------------- - validate_devices - run per-device validity - checks --------------------------------------------------*/ +//------------------------------------------------- +// validate_devices - run per-device validity +// checks +//------------------------------------------------- -static bool validate_devices(driver_enumerator &drivlist, const ioport_list &portlist, region_array *rgninfo) +void validity_checker::validate_devices() { - bool error = false; - const game_driver &driver = drivlist.driver(); - const machine_config &config = drivlist.config(); + int_map device_map; - for (const device_t *device = config.devicelist().first(); device != NULL; device = device->next()) + // iterate over devices + device_iterator iter(m_current_config->root_device()); + for (const device_t *device = iter.first(); device != NULL; device = iter.next()) { - /* validate the device tag */ - if (!validate_tag(driver, device->name(), device->tag())) - error = true; + // for non-root devices, track the current device + m_current_device = (device == &m_current_config->root_device()) ? NULL : device; - /* look for duplicates */ - for (const device_t *scandevice = config.devicelist().first(); scandevice != device; scandevice = scandevice->next()) - if (strcmp(scandevice->tag(), device->tag()) == 0) - { - mame_printf_warning("%s: %s has multiple devices with the tag '%s'\n", driver.source_file, driver.name, device->tag()); - break; - } + // validate the device tag + validate_tag(device->basetag()); - if (device->rom_region() != NULL && (strcmp(device->shortname(),"") == 0)) { - mame_printf_warning("Device %s does not have short name defined\n", device->name()); - } - /* check for device-specific validity check */ - if (device->validity_check(config.options(), driver)) - error = true; + // look for duplicates + if (device_map.add(device->tag(), 0, false) == TMERR_DUPLICATE) + mame_printf_error("Multiple devices with the same tag '%s' defined\n", device->tag()); + + // if we have a ROM region, we must have a shortname + if (device->rom_region() != NULL && strcmp(device->shortname(), "") == 0) + mame_printf_error("Device %s has ROM definition but does not have short name defined\n", device->name()); + // check for device-specific validity check + device->validity_check(*this); + + // done with this device + m_current_device = NULL; } - return error; } -/*------------------------------------------------- - validate_slots - run per-slot validity - checks --------------------------------------------------*/ +//------------------------------------------------- +// validate_slots - run per-slot validity +// checks +//------------------------------------------------- -static bool validate_slots(driver_enumerator &drivlist) +void validity_checker::validate_slots() { - bool error = false; - const machine_config &config = drivlist.config(); - - const device_slot_interface *slot = NULL; - for (bool gotone = config.devicelist().first(slot); gotone; gotone = slot->next(slot)) + // iterate over slots + slot_interface_iterator iter(m_current_config->root_device()); + for (const device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) { - const slot_interface* intf = slot->get_slot_interfaces(); + // iterate over interfaces + const slot_interface *intf = slot->get_slot_interfaces(); for (int j = 0; intf[j].name != NULL; j++) { - device_t *dev = (*intf[j].devtype)(config, "dummy", config.devicelist().first(), 0); + // instantiate the device + device_t *dev = (*intf[j].devtype)(*m_current_config, "dummy", &m_current_config->root_device(), 0); dev->config_complete(); + + // if a ROM region is present if (dev->rom_region() != NULL) { - int cnt = 0; + bool has_romfiles = false; for (const rom_entry *romp = rom_first_region(*dev); !ROMENTRY_ISEND(romp); romp++) - { - if (ROMENTRY_ISFILE(romp)) { - cnt++; + if (ROMENTRY_ISFILE(romp)) + { + has_romfiles = true; + break; } - } - if (cnt > 0) { + if (has_romfiles) + { + // scan the list of devices for this device type bool found = false; - for(int i=0;i<m_device_count;i++) { - if (intf[j].devtype==*s_devices_sorted[i]) + for (int i = 0; i < m_device_count; i++) + if (dev->type() == *s_devices_sorted[i]) { found = true; break; } - } - if (!found) { - mame_printf_error("Device %s in slot %s is not listed in device list\n", dev->name(), intf[j].name); - error = true; - } + + // if not found, report an error + if (!found) + mame_printf_error("Device %s in slot %s is not listed in device list (mame_dev.lst / mess_dev.lst)\n", dev->shortname(), intf[j].name); } } global_free(dev); } } - return error; } -/*------------------------------------------------- - validate_drivers - master validity checker --------------------------------------------------*/ +//------------------------------------------------- +// build_output_prefix - create a prefix +// indicating the current source file, driver, +// and device +//------------------------------------------------- -void validate_drivers(emu_options &options, const game_driver *curdriver) +void validity_checker::build_output_prefix(astring &string) { - osd_ticks_t prep = 0; - osd_ticks_t driver_checks = 0; - osd_ticks_t rom_checks = 0; - osd_ticks_t gfx_checks = 0; - osd_ticks_t display_checks = 0; - osd_ticks_t input_checks = 0; - osd_ticks_t device_checks = 0; - - int strnum; - bool error = false; - UINT16 lsbtest; - UINT8 a, b; - - game_driver_map names; - game_driver_map descriptions; - game_driver_map roms; - int_map defstr; - - /* basic system checks */ - a = 0xff; - b = a + 1; - if (b > a) { mame_printf_error("UINT8 must be 8 bits\n"); error = true; } - - if (sizeof(INT8) != 1) { mame_printf_error("INT8 must be 8 bits\n"); error = true; } - if (sizeof(UINT8) != 1) { mame_printf_error("UINT8 must be 8 bits\n"); error = true; } - if (sizeof(INT16) != 2) { mame_printf_error("INT16 must be 16 bits\n"); error = true; } - if (sizeof(UINT16) != 2) { mame_printf_error("UINT16 must be 16 bits\n"); error = true; } - if (sizeof(INT32) != 4) { mame_printf_error("INT32 must be 32 bits\n"); error = true; } - if (sizeof(UINT32) != 4) { mame_printf_error("UINT32 must be 32 bits\n"); error = true; } - if (sizeof(INT64) != 8) { mame_printf_error("INT64 must be 64 bits\n"); error = true; } - if (sizeof(UINT64) != 8) { mame_printf_error("UINT64 must be 64 bits\n"); error = true; } -#ifdef PTR64 - if (sizeof(void *) != 8) { mame_printf_error("PTR64 flag enabled, but was compiled for 32-bit target\n"); error = true; } -#else - if (sizeof(void *) != 4) { mame_printf_error("PTR64 flag not enabled, but was compiled for 64-bit target\n"); error = true; } -#endif - lsbtest = 0; - *(UINT8 *)&lsbtest = 0xff; -#ifdef LSB_FIRST - if (lsbtest == 0xff00) { mame_printf_error("LSB_FIRST specified, but running on a big-endian machine\n"); error = true; } -#else - if (lsbtest == 0x00ff) { mame_printf_error("LSB_FIRST not specified, but running on a little-endian machine\n"); error = true; } -#endif + // start empty + string.reset(); + + // if we have a current device, indicate that + if (m_current_device != NULL) + string.cat(m_current_device->name()).cat(" device '").cat(m_current_device->tag()).cat("': "); + + // if we have a current port, indicate that as well + if (m_current_ioport != NULL) + string.cat("ioport '").cat(m_current_ioport).cat("': "); +} - /* validate inline function behavior */ - error = validate_inlines() || error; - get_profile_ticks(); +//------------------------------------------------- +// error_output - error message output override +//------------------------------------------------- - /* pre-populate the defstr tagmap with all the default strings */ - prep -= get_profile_ticks(); - for (strnum = 1; strnum < INPUT_STRING_COUNT; strnum++) - { - const char *string = input_port_string_from_index(strnum); - if (string != NULL) - defstr.add(string, strnum, FALSE); - } - prep += get_profile_ticks(); +void validity_checker::error_output(const char *format, va_list argptr) +{ + // count the error + m_errors++; + + // output the source(driver) device 'tag' + astring output; + build_output_prefix(output); + + // generate the string + output.catvprintf(format, argptr); + m_error_text.cat(output); +} - /* iterate over all drivers */ - emu_options validation_options(options); - validation_options.remove_device_options(); - driver_enumerator drivlist(validation_options); - while (drivlist.next()) - { - const game_driver &driver = drivlist.driver(); - ioport_list portlist; - region_array rgninfo; +//------------------------------------------------- +// warning_output - warning message output +// override +//------------------------------------------------- - /* non-debug builds only care about games in the same driver */ - if (curdriver != NULL && strcmp(curdriver->source_file, driver.source_file) != 0) - continue; +void validity_checker::warning_output(const char *format, va_list argptr) +{ + // count the error + m_warnings++; + + // output the source(driver) device 'tag' + astring output; + build_output_prefix(output); + + // generate the string and output to the original target + output.catvprintf(format, argptr); + m_warning_text.cat(output); +} - try - { - /* validate the driver entry */ - driver_checks -= get_profile_ticks(); - error = validate_driver(drivlist, names, descriptions) || error; - driver_checks += get_profile_ticks(); - - /* validate the ROM information */ - rom_checks -= get_profile_ticks(); - error = validate_roms(drivlist, &rgninfo, roms) || error; - rom_checks += get_profile_ticks(); - - /* validate input ports */ - input_checks -= get_profile_ticks(); - error = validate_inputs(drivlist, defstr, portlist) || error; - input_checks += get_profile_ticks(); - - /* validate the display */ - display_checks -= get_profile_ticks(); - error = validate_display(drivlist) || error; - display_checks += get_profile_ticks(); - - /* validate the graphics decoding */ - gfx_checks -= get_profile_ticks(); - error = validate_gfx(drivlist, &rgninfo) || error; - gfx_checks += get_profile_ticks(); - - /* validate devices */ - device_checks -= get_profile_ticks(); - error = validate_devices(drivlist, portlist, &rgninfo) || error; - error = validate_slots(drivlist) || error; - device_checks += get_profile_ticks(); - } - catch (emu_fatalerror &err) - { - throw emu_fatalerror("Validating %s (%s): %s", driver.name, driver.source_file, err.string()); - } - } -#if (REPORT_TIMES) - mame_printf_info("Prep: %8dm\n", (int)(prep / 1000000)); - mame_printf_info("Driver: %8dm\n", (int)(driver_checks / 1000000)); - mame_printf_info("ROM: %8dm\n", (int)(rom_checks / 1000000)); - mame_printf_info("CPU: %8dm\n", (int)(cpu_checks / 1000000)); - mame_printf_info("Display: %8dm\n", (int)(display_checks / 1000000)); - mame_printf_info("Graphics: %8dm\n", (int)(gfx_checks / 1000000)); - mame_printf_info("Input: %8dm\n", (int)(input_checks / 1000000)); -#endif +//------------------------------------------------- +// output_via_delegate - helper to output a +// message via a varargs string, so the argptr +// can be forwarded onto the given delegate +//------------------------------------------------- + +void validity_checker::output_via_delegate(output_delegate &delegate, const char *format, ...) +{ + va_list argptr; - // on a general error, throw rather than return - if (error) - throw emu_fatalerror(MAMERR_FAILED_VALIDITY, "Validity checks failed"); + // call through to the delegate with the proper parameters + va_start(argptr, format); + delegate(format, argptr); + va_end(argptr); } diff --git a/src/emu/validity.h b/src/emu/validity.h index 9864b229e61..d362e155a1e 100644 --- a/src/emu/validity.h +++ b/src/emu/validity.h @@ -4,8 +4,36 @@ Validity checks - Copyright Nicola Salmoria and the MAME Team. - Visit http://mamedev.org for licensing and usage restrictions. +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ @@ -14,7 +42,94 @@ #ifndef __VALIDITY_H__ #define __VALIDITY_H__ -void validate_drivers(emu_options &options, const game_driver *driver = NULL); -bool validate_tag(const game_driver &driver, const char *object, const char *tag); +#include "emu.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// forward declarations +class machine_config; + + +// core validity checker class +class validity_checker +{ + // internal map types + typedef tagmap_t<const game_driver *> game_driver_map; + typedef tagmap_t<FPTR> int_map; + +public: + validity_checker(emu_options &options); + + // getters + int errors() const { return m_errors; } + int warnings() const { return m_warnings; } + + // operations + void check_driver(const game_driver &driver); + void check_shared_source(const game_driver &driver); + void check_all(); + + // helpers for devices + void validate_tag(const char *tag); + +private: + // internal helpers + const char *ioport_string_from_index(UINT32 index); + int get_defstr_index(const char *string, bool suppress_error = false); + + // core helpers + void validate_begin(); + void validate_end(); + void validate_one(const game_driver &driver); + + // internal sub-checks + void validate_core(); + void validate_inlines(); + void validate_driver(); + void validate_roms(); + void validate_display(); + void validate_gfx(); + void validate_analog_input_field(input_field_config &field); + void validate_dip_settings(input_field_config &field); + void validate_condition(input_condition &condition, device_t &device, int_map &port_map); + void validate_inputs(); + void validate_devices(); + void validate_slots(); + + // output helpers + void build_output_prefix(astring &string); + void error_output(const char *format, va_list argptr); + void warning_output(const char *format, va_list argptr); + void output_via_delegate(output_delegate &delegate, const char *format, ...); + + // internal driver list + driver_enumerator m_drivlist; + + // error tracking + int m_errors; + int m_warnings; + astring m_error_text; + astring m_warning_text; + + // maps for finding duplicates + game_driver_map m_names_map; + game_driver_map m_descriptions_map; + game_driver_map m_roms_map; + int_map m_defstr_map; + + // current state + const game_driver * m_current_driver; + const machine_config * m_current_config; + const device_t * m_current_device; + const char * m_current_ioport; + int_map m_region_map; + + // callbacks + output_delegate m_saved_error_output; + output_delegate m_saved_warning_output; +}; #endif diff --git a/src/emu/video.c b/src/emu/video.c index c0514c8e605..e2956bc37ad 100644 --- a/src/emu/video.c +++ b/src/emu/video.c @@ -304,7 +304,8 @@ astring &video_manager::speed_text(astring &string) // display the number of partial updates as well int partials = 0; - for (screen_device *screen = machine().first_screen(); screen != NULL; screen = screen->next_screen()) + screen_device_iterator iter(machine().root_device()); + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) partials += screen->partial_updates(); if (partials > 1) string.catprintf("\n%d partial updates", partials); @@ -355,7 +356,8 @@ void video_manager::save_active_screen_snapshots() if (m_snap_native) { // write one snapshot per visible screen - for (screen_device *screen = machine().first_screen(); screen != NULL; screen = screen->next_screen()) + screen_device_iterator iter(machine().root_device()); + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) if (machine().render().is_live(*screen)) { emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); @@ -648,12 +650,13 @@ inline int video_manager::original_speed_setting() const bool video_manager::finish_screen_updates() { // finish updating the screens - for (screen_device *screen = machine().first_screen(); screen != NULL; screen = screen->next_screen()) + screen_device_iterator iter(machine().root_device()); + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) screen->update_partial(screen->visible_area().max_y); // now add the quads for all the screens bool anything_changed = false; - for (screen_device *screen = machine().first_screen(); screen != NULL; screen = screen->next_screen()) + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) if (screen->update_quads()) anything_changed = true; @@ -663,12 +666,12 @@ bool video_manager::finish_screen_updates() record_frame(); // iterate over screens and update the burnin for the ones that care - for (screen_device *screen = machine().first_screen(); screen != NULL; screen = screen->next_screen()) + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) screen->update_burnin(); } // draw any crosshairs - for (screen_device *screen = machine().first_screen(); screen != NULL; screen = screen->next_screen()) + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) crosshair_render(*screen); return anything_changed; @@ -950,7 +953,8 @@ void video_manager::update_refresh_speed() // find the screen with the shortest frame period (max refresh rate) // note that we first check the token since this can get called before all screens are created attoseconds_t min_frame_period = ATTOSECONDS_PER_SECOND; - for (screen_device *screen = machine().first_screen(); screen != NULL; screen = screen->next_screen()) + screen_device_iterator iter(machine().root_device()); + for (screen_device *screen = iter.first(); screen != NULL; screen = iter.next()) { attoseconds_t period = screen->frame_period().attoseconds; if (period != 0) @@ -1047,12 +1051,13 @@ void video_manager::recompute_speed(attotime emutime) // given screen //------------------------------------------------- -void video_manager::create_snapshot_bitmap(device_t *screen) +void video_manager::create_snapshot_bitmap(screen_device *screen) { // select the appropriate view in our dummy target if (m_snap_native && screen != NULL) { - int view_index = machine().devicelist().indexof(SCREEN, screen->tag()); + screen_device_iterator iter(machine().root_device()); + int view_index = iter.indexof(*screen); assert(view_index != -1); m_snap_target->set_view(view_index); } @@ -1135,8 +1140,8 @@ file_error video_manager::open_next(emu_file &file, const char *extension) //printf("check template: %s\n", snapdevname.cstr()); // verify that there is such a device for this system - device_image_interface *image = NULL; - for (bool gotone = machine().devicelist().first(image); gotone; gotone = image->next(image)) + image_interface_iterator iter(machine().root_device()); + for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) { // get the device name astring tempdevname(image->brief_instance_name()); diff --git a/src/emu/video.h b/src/emu/video.h index 976274f3835..c6b629dd7d5 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -137,7 +137,7 @@ private: void recompute_speed(attotime emutime); // snapshot/movie helpers - void create_snapshot_bitmap(device_t *screen); + void create_snapshot_bitmap(screen_device *screen); file_error open_next(emu_file &file, const char *extension); void record_frame(); diff --git a/src/emu/video/mc6845.c b/src/emu/video/mc6845.c index de2cc382ee8..b7faa86ca38 100644 --- a/src/emu/video/mc6845.c +++ b/src/emu/video/mc6845.c @@ -766,11 +766,8 @@ void mc6845_device::device_start() /* get the screen device */ if ( m_screen_tag != NULL ) { - m_screen = downcast<screen_device *>(machine().device(m_screen_tag)); - if (m_screen == NULL) { - astring tempstring; - m_screen = downcast<screen_device *>(machine().device(owner()->subtag(tempstring,m_screen_tag))); - } + astring tempstring; + m_screen = downcast<screen_device *>(machine().device(siblingtag(tempstring,m_screen_tag))); assert(m_screen != NULL); } else diff --git a/src/emu/video/ramdac.c b/src/emu/video/ramdac.c index 1eea2e8bbf8..61ae67891e5 100644 --- a/src/emu/video/ramdac.c +++ b/src/emu/video/ramdac.c @@ -100,10 +100,8 @@ void ramdac_device::device_config_complete() // on this device //------------------------------------------------- -bool ramdac_device::device_validity_check(emu_options &options, const game_driver &driver) const +void ramdac_device::device_validity_check(validity_checker &valid) const { - bool error = false; - return error; } //------------------------------------------------- diff --git a/src/emu/video/ramdac.h b/src/emu/video/ramdac.h index 0e53de36b4a..97d28462ce8 100644 --- a/src/emu/video/ramdac.h +++ b/src/emu/video/ramdac.h @@ -61,7 +61,7 @@ public: protected: // device-level overrides - virtual bool device_validity_check(emu_options &options, const game_driver &driver) const; + virtual void device_validity_check(validity_checker &valid) const; virtual void device_start(); virtual void device_reset(); virtual void device_config_complete(); diff --git a/src/emu/video/voodoo.c b/src/emu/video/voodoo.c index 4d554a68909..1e85d8c7617 100644 --- a/src/emu/video/voodoo.c +++ b/src/emu/video/voodoo.c @@ -4910,7 +4910,15 @@ static DEVICE_START( voodoo ) } /* set the type, and initialize the chip mask */ - v->index = device->machine().devicelist().indexof(device->type(), device->tag()); + device_iterator iter(device->machine().root_device()); + v->index = 0; + for (device_t *scan = iter.first(); scan != NULL; scan = iter.next()) + if (scan->type() == device->type()) + { + if (scan == device) + break; + v->index++; + } v->screen = downcast<screen_device *>(device->machine().device(config->screen)); assert_always(v->screen != NULL, "Unable to find screen attached to voodoo"); v->cpu = device->machine().device(config->cputag); |