summaryrefslogtreecommitdiffstats
path: root/src/frontend/mame/audit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/audit.cpp')
-rw-r--r--src/frontend/mame/audit.cpp169
1 files changed, 108 insertions, 61 deletions
diff --git a/src/frontend/mame/audit.cpp b/src/frontend/mame/audit.cpp
index 256f9876f1b..3ff706d2c8a 100644
--- a/src/frontend/mame/audit.cpp
+++ b/src/frontend/mame/audit.cpp
@@ -9,14 +9,19 @@
***************************************************************************/
#include "emu.h"
-#include "emuopts.h"
#include "audit.h"
-#include "chd.h"
+
+#include "sound/samples.h"
+
+#include "emuopts.h"
#include "drivenum.h"
#include "romload.h"
-#include "sound/samples.h"
#include "softlist_dev.h"
+#include "chd.h"
+
+#include <algorithm>
+
//**************************************************************************
// CORE FUNCTIONS
@@ -29,7 +34,6 @@
media_auditor::media_auditor(const driver_enumerator &enumerator)
: m_enumerator(enumerator)
, m_validation(AUDIT_VALIDATE_FULL)
- , m_searchpath()
{
}
@@ -53,22 +57,19 @@ media_auditor::summary media_auditor::audit_media(const char *validation)
std::size_t shared_required = 0;
// iterate over devices and regions
+ std::vector<std::string> searchpath;
for (device_t &device : device_iterator(m_enumerator.config()->root_device()))
{
- // determine the search path for this source and iterate through the regions
- m_searchpath.clear();
- for (const std::string &path : device.searchpath())
- {
- if (!m_searchpath.empty())
- m_searchpath += ';';
- m_searchpath += path;
- }
+ searchpath.clear();
// now iterate over regions and ROMs within
for (const rom_entry *region = rom_first_region(device); region; region = rom_next_region(region))
{
for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
{
+ if (searchpath.empty())
+ searchpath = device.searchpath();
+
char const *const name(ROM_GETNAME(rom));
util::hash_collection const hashes(ROM_GETHASHDATA(rom));
device_t *const shared_device(find_shared_device(device, name, hashes, ROM_GETLENGTH(rom)));
@@ -83,9 +84,9 @@ media_auditor::summary media_auditor::audit_media(const char *validation)
audit_record *record = nullptr;
if (ROMREGION_ISROMDATA(region))
- record = &audit_one_rom(rom);
+ record = &audit_one_rom(searchpath, rom);
else if (ROMREGION_ISDISKDATA(region))
- record = &audit_one_disk(rom, nullptr);
+ record = &audit_one_disk(rom, device);
if (record)
{
@@ -126,12 +127,32 @@ media_auditor::summary media_auditor::audit_device(device_t &device, const char
// store validation for later
m_validation = validation;
- m_searchpath = device.shortname();
std::size_t found = 0;
std::size_t required = 0;
- audit_regions(rom_first_region(device), nullptr, found, required);
+ std::vector<std::string> searchpath;
+ audit_regions(
+ [this, &device, &searchpath] (rom_entry const *region, rom_entry const *rom) -> audit_record const *
+ {
+ if (ROMREGION_ISROMDATA(region))
+ {
+ if (searchpath.empty())
+ searchpath = device.searchpath();
+ return &audit_one_rom(searchpath, rom);
+ }
+ else if (ROMREGION_ISDISKDATA(region))
+ {
+ return &audit_one_disk(rom, device);
+ }
+ else
+ {
+ return nullptr;
+ }
+ },
+ rom_first_region(device),
+ found,
+ required);
if ((found == 0) && (required > 0))
{
@@ -147,7 +168,7 @@ media_auditor::summary media_auditor::audit_device(device_t &device, const char
//-------------------------------------------------
// audit_software
//-------------------------------------------------
-media_auditor::summary media_auditor::audit_software(const std::string &list_name, const software_info *swinfo, const char *validation)
+media_auditor::summary media_auditor::audit_software(software_list_device &swlist, const software_info &swinfo, const char *validation)
{
// start fresh
m_record_list.clear();
@@ -155,21 +176,57 @@ media_auditor::summary media_auditor::audit_software(const std::string &list_nam
// store validation for later
m_validation = validation;
- std::string combinedpath(util::string_format("%s;%s%s%s", swinfo->shortname(), list_name, PATH_SEPARATOR, swinfo->shortname()));
- std::string locationtag(util::string_format("%s%%%s%%", list_name, swinfo->shortname()));
- if (!swinfo->parentname().empty())
- {
- locationtag.append(swinfo->parentname());
- combinedpath.append(util::string_format(";%s;%s%s%s", swinfo->parentname(), list_name, PATH_SEPARATOR, swinfo->parentname()));
- }
- m_searchpath = combinedpath;
-
std::size_t found = 0;
std::size_t required = 0;
// now iterate over software parts
- for (const software_part &part : swinfo->parts())
- audit_regions(part.romdata().data(), locationtag.c_str(), found, required);
+ std::vector<std::string> searchpath;
+ auto const do_audit =
+ [this, &swlist, &swinfo, &searchpath] (rom_entry const *region, rom_entry const *rom) -> audit_record const *
+ {
+ if (ROMREGION_ISROMDATA(region))
+ {
+ if (searchpath.empty())
+ {
+ std::vector<software_info const *> parents;
+
+ // search <rompath>/<list>/<software> following parents
+ searchpath.emplace_back(util::string_format("%s" PATH_SEPARATOR "%s", swlist.list_name(), swinfo.shortname()));
+ for (software_info const *i = &swinfo; i && !i->parentname().empty(); i = swlist.find(i->parentname()))
+ {
+ if (std::find(parents.begin(), parents.end(), i) != parents.end())
+ {
+ osd_printf_warning("WARNING: software parent/clone relationships form a loop (%s:%s)\n", swlist.list_name(), swinfo.shortname());
+ break;
+ }
+ parents.emplace_back(i);
+ searchpath.emplace_back(util::string_format("%s" PATH_SEPARATOR "%s", swlist.list_name(), i->parentname()));
+ }
+
+ // search <rompath>/<software> following parents
+ searchpath.emplace_back(swinfo.shortname());
+ parents.clear();
+ for (software_info const *i = &swinfo; i && !i->parentname().empty(); i = swlist.find(i->parentname()))
+ {
+ if (std::find(parents.begin(), parents.end(), i) != parents.end())
+ break;
+ parents.emplace_back(i);
+ searchpath.emplace_back(i->parentname());
+ }
+ }
+ return &audit_one_rom(searchpath, rom);
+ }
+ else if (ROMREGION_ISDISKDATA(region))
+ {
+ return &audit_one_disk(rom, swlist, swinfo);
+ }
+ else
+ {
+ return nullptr;
+ }
+ };
+ for (const software_part &part : swinfo.parts())
+ audit_regions(do_audit, part.romdata().data(), found, required);
if ((found == 0) && (required > 0))
{
@@ -178,7 +235,7 @@ media_auditor::summary media_auditor::audit_software(const std::string &list_nam
}
// return a summary
- return summarize(list_name.c_str());
+ return summarize(swlist.list_name().c_str());
}
@@ -342,25 +399,22 @@ media_auditor::summary media_auditor::summarize(const char *name, std::ostream *
// audit_regions - validate/count for regions
//-------------------------------------------------
-void media_auditor::audit_regions(const rom_entry *region, const char *locationtag, std::size_t &found, std::size_t &required)
+template <typename T>
+void media_auditor::audit_regions(T do_audit, const rom_entry *region, std::size_t &found, std::size_t &required)
{
// now iterate over regions
+ std::vector<std::string> searchpath;
for ( ; region; region = rom_next_region(region))
{
// now iterate over rom definitions
- for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ for (rom_entry const *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
{
- util::hash_collection const hashes(ROM_GETHASHDATA(rom));
-
// count the number of files with hashes
+ util::hash_collection const hashes(ROM_GETHASHDATA(rom));
if (!hashes.flag(util::hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom))
required++;
- audit_record const *record = nullptr;
- if (ROMREGION_ISROMDATA(region))
- record = &audit_one_rom(rom);
- else if (ROMREGION_ISDISKDATA(region))
- record = &audit_one_disk(rom, locationtag);
+ audit_record const *const record = do_audit(region, rom);
// count the number of files that are found.
if (record && ((record->status() == audit_status::GOOD) || (record->status() == audit_status::FOUND_INVALID)))
@@ -374,7 +428,7 @@ void media_auditor::audit_regions(const rom_entry *region, const char *locationt
// audit_one_rom - validate a single ROM entry
//-------------------------------------------------
-media_auditor::audit_record &media_auditor::audit_one_rom(const rom_entry *rom)
+media_auditor::audit_record &media_auditor::audit_one_rom(const std::vector<std::string> &searchpath, const rom_entry *rom)
{
// allocate and append a new record
audit_record &record = *m_record_list.emplace(m_record_list.end(), *rom, media_type::ROM);
@@ -384,27 +438,19 @@ media_auditor::audit_record &media_auditor::audit_one_rom(const rom_entry *rom)
bool const has_crc = record.expected_hashes().crc(crc);
// find the file and checksum it, getting the file length along the way
- emu_file file(m_enumerator.options().media_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
- file.set_restrict_to_mediapath(true);
- path_iterator path(m_searchpath);
- std::string curpath;
- // FIXME: needs to be adjusted to match ROM loading behaviour
- while (path.next(curpath, record.name()))
- {
- // open the file if we can
- osd_file::error filerr;
- if (has_crc)
- filerr = file.open(curpath, crc);
- else
- filerr = file.open(curpath);
+ emu_file file(m_enumerator.options().media_path(), searchpath, OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
+ file.set_restrict_to_mediapath(1);
- // if it worked, get the actual length and hashes, then stop
- if (filerr == osd_file::error::NONE)
- {
- record.set_actual(file.hashes(m_validation), file.size());
- break;
- }
- }
+ // open the file if we can
+ osd_file::error filerr;
+ if (has_crc)
+ filerr = file.open(record.name(), crc);
+ else
+ filerr = file.open(record.name());
+
+ // if it worked, get the actual length and hashes, then stop
+ if (filerr == osd_file::error::NONE)
+ record.set_actual(file.hashes(m_validation), file.size());
// compute the final status
compute_status(record, rom, record.actual_length() != 0);
@@ -416,14 +462,15 @@ media_auditor::audit_record &media_auditor::audit_one_rom(const rom_entry *rom)
// audit_one_disk - validate a single disk entry
//-------------------------------------------------
-media_auditor::audit_record &media_auditor::audit_one_disk(const rom_entry *rom, const char *locationtag)
+template <typename... T>
+media_auditor::audit_record &media_auditor::audit_one_disk(const rom_entry *rom, T &&... args)
{
// allocate and append a new record
audit_record &record = *m_record_list.emplace(m_record_list.end(), *rom, media_type::DISK);
// open the disk
chd_file source;
- chd_error err = chd_error(open_disk_image(m_enumerator.options(), &m_enumerator.driver(), rom, source, locationtag));
+ const chd_error err = rom_load_manager::open_disk_image(m_enumerator.options(), std::forward<T>(args)..., rom, source);
// if we succeeded, get the hashes
if (err == CHDERR_NONE)