summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
authorGravatarGravatar npwoods <npwoods@mess.org>2019-08-03 16:43:45 -0400
committerGravatarGravatar npwoods <npwoods@mess.org>2019-08-03 18:22:41 -0400
commitfc9e5602b6d6221787be8735c208cf62c7f9cb31 (patch)
treec01fab202c00f045fd90f42c4be1f94f7cb9b1a5 /src/frontend
parent78ca6157e403679a5a40037cdbb3d2fd7283477f (diff)
Refactored info_xml_creator::output()
- The two variations of output() no longer duplicate logic - No longer relying on driver_enumerator::config() to create machine_config objects. Because driver_enumerator would cache all objects created, we would needlessly hog memory
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mame/info.cpp222
-rw-r--r--src/frontend/mame/info.h15
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp25
3 files changed, 148 insertions, 114 deletions
diff --git a/src/frontend/mame/info.cpp b/src/frontend/mame/info.cpp
index 1fe65d7ea3c..977ee7cbf4b 100644
--- a/src/frontend/mame/info.cpp
+++ b/src/frontend/mame/info.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles,Paul Priest
/***************************************************************************
- info.c
+ info.cpp
Dumps the MAME internal data as an XML file.
@@ -27,7 +27,6 @@
#include <ctype.h>
#include <cstring>
-#include <map>
#define XML_ROOT "mame"
@@ -214,125 +213,142 @@ info_xml_creator::info_xml_creator(emu_options const &options, bool dtd)
//-------------------------------------------------
-// output_mame_xml - print the XML information
-// for all known games
+// output - print the XML information for all
+// known machines matching a pattern
//-------------------------------------------------
-void info_xml_creator::output(FILE *out, std::vector<std::string> const &patterns)
+void info_xml_creator::output(FILE *out, const std::vector<std::string> &patterns)
{
- m_output = out;
-
- std::unique_ptr<device_type_set> devfilter(patterns.empty() ? nullptr : new device_type_set);
-
- // track which patterns match machines
- driver_enumerator drivlist(m_lookup_options);
- std::vector<bool> matched(patterns.size(), false);
- size_t exact_matches = 0;
- auto const included = [&patterns, &matched, &exact_matches] (char const *const name) -> bool
+ if (patterns.empty())
{
- if (patterns.empty())
+ // no patterns specified - show everything
+ auto filter = [](const char *, bool &) -> bool
+ {
return true;
-
- bool result = false;
- auto it = matched.begin();
- for (std::string const &pat : patterns)
+ };
+ output(out, filter, devices_disposition::ALL);
+ }
+ else
+ {
+ // patterns specified - we have to filter output
+ std::vector<bool> matched(patterns.size(), false);
+ size_t exact_matches = 0;
+ const auto filter = [&patterns, &matched, &exact_matches](const char *shortname, bool &done) -> bool
{
- if (!core_strwildcmp(pat.c_str(), name))
+ bool result = false;
+ auto it = matched.begin();
+ for (const std::string &pat : patterns)
{
- result = true;
- if (!*it)
+ if (!core_strwildcmp(pat.c_str(), shortname))
{
- *it = true;
- if (!core_iswildstr(pat.c_str()))
- ++exact_matches;
+ // this driver matches the pattern - tell the caller
+ result = true;
+
+ // did we see this particular pattern before? if not, track that we have
+ if (!*it)
+ {
+ *it = true;
+ if (!core_iswildstr(pat.c_str()))
+ {
+ exact_matches++;
+
+ // stop looking if we found everything specified
+ if (exact_matches == patterns.size())
+ done = true;
+ }
+ }
}
+ it++;
}
- ++it;
+ return result;
+ };
+ output(out, filter, devices_disposition::FILTERED);
+
+ // throw an error if there were unmatched patterns
+ auto iter = std::find(matched.begin(), matched.end(), false);
+ if (iter != matched.end())
+ {
+ int index = iter - matched.begin();
+ throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching machines found for '%s'", patterns[index].c_str());
}
- return result;
- };
+ }
+}
+
+
+//-------------------------------------------------
+// output - print the XML information for all
+// known (and filtered) machines
+//-------------------------------------------------
+
+void info_xml_creator::output(FILE *out, const std::function<bool(const char *shortname, bool &done)> &filter, devices_disposition devdisp)
+{
+ // sanity checks
+ assert(out);
+ assert(filter);
+
+ // set up output
+ m_output = out;
+
+ // prepare a driver enumerator and the queue
+ driver_enumerator drivlist(m_lookup_options);
+ bool drivlist_done = false;
+ bool filter_done = false;
+ bool header_outputted = false;
+
+ // only keep a device set when we're asked to track it
+ std::unique_ptr<device_type_set> devfilter;
+ if (devdisp == devices_disposition::FILTERED)
+ devfilter = std::make_unique<device_type_set>();
- // iterate through the drivers, outputting one at a time
- bool first = true;
- while (drivlist.next())
+ // try enumerating drivers and outputting them
+ while (!drivlist_done && !filter_done)
{
- if (included(drivlist.driver().name))
+ if (!drivlist.next())
+ {
+ // at this point we are done enumerating through drivlist and it is no
+ // longer safe to call next(), so record that we're done
+ drivlist_done = true;
+ }
+ else if (filter(drivlist.driver().name, filter_done))
{
- if (first)
+ // output the header if we have to
+ if (!header_outputted)
{
output_header();
- first = false;
+ header_outputted = true;
}
- output_one(drivlist, devfilter.get());
- // stop looking if we found everything specified
- if (!patterns.empty() && exact_matches == patterns.size())
- break;
+ // output it
+ output_one(drivlist, devfilter.get());
}
}
// iterate through the device types if not everything matches a driver
- if (!patterns.empty() && exact_matches != patterns.size())
+ if (devfilter && !filter_done)
{
for (device_type type : registered_device_types)
{
- if (included(type.shortname()))
- {
+ if (filter(type.shortname(), filter_done))
devfilter->insert(&type);
- if (exact_matches == patterns.size())
- break;
- }
+
+ if (filter_done)
+ break;
}
}
// output devices (both devices with roms and slot devices)
- if (!devfilter || !devfilter->empty())
+ if (devdisp != devices_disposition::NONE && (!devfilter || !devfilter->empty()))
{
- if (first)
+ if (!header_outputted)
{
output_header();
- first = false;
+ header_outputted = true;
}
output_devices(devfilter.get());
}
- if (!first)
+ if (header_outputted)
output_footer();
-
- // throw an error if there were unmatched patterns
- auto it = matched.begin();
- for (std::string const &pat : patterns)
- {
- if (!*it)
- throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching machines found for '%s'", pat.c_str());
-
- ++it;
- }
-}
-
-
-//-------------------------------------------------
-// output_mame_xml - print the XML information
-// for a subset of games
-//-------------------------------------------------
-
-void info_xml_creator::output(FILE *out, driver_enumerator &drivlist, bool nodevices)
-{
- m_output = out;
-
- device_type_set devfilter;
-
- output_header();
-
- // iterate through the drivers, outputting one at a time
- while (drivlist.next())
- output_one(drivlist, &devfilter);
-
- // output devices (both devices with roms and slot devices)
- if (!nodevices)
- output_devices(&devfilter);
-
- output_footer();
}
@@ -381,14 +397,14 @@ void info_xml_creator::output_footer()
//-------------------------------------------------
// output_one - print the XML information
-// for one particular game driver
+// for one particular machine driver
//-------------------------------------------------
void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set *devtypes)
{
const game_driver &driver = drivlist.driver();
- std::shared_ptr<machine_config> const config(drivlist.config());
- device_iterator iter(config->root_device());
+ machine_config config(driver, drivlist.options());
+ device_iterator iter(config.root_device());
// allocate input ports and build overall emulation status
ioport_list portlist;
@@ -458,7 +474,7 @@ void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set *
fprintf(m_output, " romof=\"%s\"", util::xml::normalize_string(drivlist.driver(clone_of).name));
// display sample information and close the game tag
- output_sampleof(config->root_device());
+ output_sampleof(config.root_device());
fprintf(m_output, ">\n");
// output game description
@@ -474,13 +490,13 @@ void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set *
fprintf(m_output, "\t\t<manufacturer>%s</manufacturer>\n", util::xml::normalize_string(driver.manufacturer));
// now print various additional information
- output_bios(config->root_device());
- output_rom(&drivlist, config->root_device());
- output_device_refs(config->root_device());
- output_sample(config->root_device());
- output_chips(config->root_device(), "");
- output_display(config->root_device(), &drivlist.driver().flags, "");
- output_sound(config->root_device());
+ output_bios(config.root_device());
+ output_rom(&drivlist, &driver, config.root_device());
+ output_device_refs(config.root_device());
+ output_sample(config.root_device());
+ output_chips(config.root_device(), "");
+ output_display(config.root_device(), &driver.flags, "");
+ output_sound(config.root_device());
output_input(portlist);
output_switches(portlist, "", IPT_DIPSWITCH, "dipswitch", "diplocation", "dipvalue");
output_switches(portlist, "", IPT_CONFIG, "configuration", "conflocation", "confsetting");
@@ -488,10 +504,10 @@ void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set *
output_adjusters(portlist);
output_driver(driver, overall_unemulated, overall_imperfect);
output_features(driver.type, overall_unemulated, overall_imperfect);
- output_images(config->root_device(), "");
- output_slots(*config, config->root_device(), "", devtypes);
- output_software_list(config->root_device());
- output_ramoptions(config->root_device());
+ output_images(config.root_device(), "");
+ output_slots(config, config.root_device(), "", devtypes);
+ output_software_list(config.root_device());
+ output_ramoptions(config.root_device());
// close the topmost tag
fprintf(m_output, "\t</%s>\n", XML_TOP);
@@ -541,7 +557,7 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic
fprintf(m_output, ">\n\t\t<description>%s</description>\n", util::xml::normalize_string(device.name()));
output_bios(device);
- output_rom(nullptr, device);
+ output_rom(nullptr, nullptr, device);
output_device_refs(device);
if (device.type().type() != typeid(samples_device)) // ignore samples_device itself
@@ -673,7 +689,7 @@ void info_xml_creator::output_bios(device_t const &device)
// the XML output
//-------------------------------------------------
-void info_xml_creator::output_rom(driver_enumerator *drivlist, device_t &device)
+void info_xml_creator::output_rom(driver_enumerator *drivlist, const game_driver *driver, device_t &device)
{
enum class type { BIOS, NORMAL, DISK };
std::map<u32, char const *> biosnames;
@@ -753,7 +769,7 @@ void info_xml_creator::output_rom(driver_enumerator *drivlist, device_t &device)
// if we have a valid ROM and we are a clone, see if we can find the parent ROM
util::hash_collection const hashes(rom->hashdata);
- char const *const merge_name((do_merge_name && !hashes.flag(util::hash_collection::FLAG_NO_DUMP)) ? get_merge_name(*drivlist, hashes) : nullptr);
+ char const *const merge_name((do_merge_name && !hashes.flag(util::hash_collection::FLAG_NO_DUMP)) ? get_merge_name(*drivlist, *driver, hashes) : nullptr);
// opening tag
fprintf(m_output, is_disk ? "\t\t<disk" : "\t\t<rom");
@@ -1855,10 +1871,10 @@ void info_xml_creator::output_ramoptions(device_t &root)
// parent set
//-------------------------------------------------
-const char *info_xml_creator::get_merge_name(driver_enumerator &drivlist, util::hash_collection const &romhashes)
+const char *info_xml_creator::get_merge_name(driver_enumerator &drivlist, const game_driver &driver, util::hash_collection const &romhashes)
{
// walk the parent chain
- for (int clone_of = drivlist.find(drivlist.driver().parent); 0 <= clone_of; clone_of = drivlist.find(drivlist.driver(clone_of).parent))
+ for (int clone_of = drivlist.find(driver.parent); 0 <= clone_of; clone_of = drivlist.find(drivlist.driver(clone_of).parent))
{
// look in the parent's ROMs
for (romload::region const &pregion : romload::entries(drivlist.driver(clone_of).rom).get_regions())
diff --git a/src/frontend/mame/info.h b/src/frontend/mame/info.h
index 40b3739d895..6fe5fd1d1fb 100644
--- a/src/frontend/mame/info.h
+++ b/src/frontend/mame/info.h
@@ -31,12 +31,19 @@ class driver_enumerator;
class info_xml_creator
{
public:
+ enum class devices_disposition
+ {
+ NONE,
+ FILTERED,
+ ALL
+ };
+
// construction/destruction
info_xml_creator(emu_options const &options, bool dtd = true);
// output
- void output(FILE *out, std::vector<std::string> const &patterns);
- void output(FILE *out, driver_enumerator &drivlist, bool nodevices);
+ void output(FILE *out, const std::vector<std::string> &patterns);
+ void output(FILE *out, const std::function<bool(const char *shortname, bool &done)> &filter, devices_disposition devdisp);
private:
typedef std::unordered_set<std::add_pointer_t<device_type> > device_type_set;
@@ -48,7 +55,7 @@ private:
void output_one(driver_enumerator &drivlist, device_type_set *devtypes);
void output_sampleof(device_t &device);
void output_bios(device_t const &device);
- void output_rom(driver_enumerator *drivlist, device_t &device);
+ void output_rom(driver_enumerator *drivlist, const game_driver *driver, device_t &device);
void output_device_refs(device_t &root);
void output_sample(device_t &device);
void output_chips(device_t &device, const char *root_tag);
@@ -69,7 +76,7 @@ private:
void output_one_device(machine_config &config, device_t &device, const char *devtag);
void output_devices(device_type_set const *filter);
- const char *get_merge_name(driver_enumerator &drivlist, util::hash_collection const &romhashes);
+ const char *get_merge_name(driver_enumerator &drivlist, const game_driver &driver, util::hash_collection const &romhashes);
// internal state
FILE * m_output; // FIXME: this is not reentrancy-safe
diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp
index 3591a2a0ae3..8dea46aab79 100644
--- a/src/frontend/mame/ui/miscmenu.cpp
+++ b/src/frontend/mame/ui/miscmenu.cpp
@@ -590,14 +590,25 @@ void menu_export::handle()
file.close();
pfile = fopen(fullpath.c_str(), "w");
- // create the XML and save to file
- driver_enumerator drvlist(machine().options());
- drvlist.exclude_all();
- for (auto & elem : m_list)
- drvlist.include(driver_list::find(*elem));
-
+ // prepare a filter for the drivers we want to show
+ std::unordered_set<const game_driver *> driver_list(m_list.begin(), m_list.end());
+ auto filter = [&driver_list](const char *shortname, bool &)
+ {
+ auto iter = std::find_if(
+ driver_list.begin(),
+ driver_list.end(),
+ [shortname](const game_driver *driver) { return !strcmp(shortname, driver->name); });
+ return iter != driver_list.end();
+ };
+
+ // do we want to show devices?
+ info_xml_creator::devices_disposition devdisp = (uintptr_t(menu_event->itemref) == 1)
+ ? info_xml_creator::devices_disposition::FILTERED
+ : info_xml_creator::devices_disposition::NONE;
+
+ // and do the dirty work
info_xml_creator creator(machine().options());
- creator.output(pfile, drvlist, (uintptr_t(menu_event->itemref) == 1) ? false : true);
+ creator.output(pfile, filter, devdisp);
fclose(pfile);
machine().popmessage(_("%s.xml saved under ui folder."), filename.c_str());
}