diff options
Diffstat (limited to 'docs/release/src/frontend/mame/info.cpp')
-rw-r--r-- | docs/release/src/frontend/mame/info.cpp | 785 |
1 files changed, 465 insertions, 320 deletions
diff --git a/docs/release/src/frontend/mame/info.cpp b/docs/release/src/frontend/mame/info.cpp index 91669110961..e14fe63cdd8 100644 --- a/docs/release/src/frontend/mame/info.cpp +++ b/docs/release/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,9 @@ #include <ctype.h> #include <cstring> -#include <map> +#include <unordered_set> +#include <queue> +#include <future> #define XML_ROOT "mame" @@ -35,11 +37,59 @@ //************************************************************************** +// ANONYMOUS NAMESPACE PROTOTYPES +//************************************************************************** + +namespace +{ + class device_type_compare + { + public: + bool operator()(const std::add_pointer_t<device_type> &lhs, const std::add_pointer_t<device_type> &rhs) const; + }; + + typedef std::set<std::add_pointer_t<device_type>, device_type_compare> device_type_set; + + std::string normalize_string(const char *string); + + // internal helper + void output_header(std::ostream &out, bool dtd); + void output_footer(std::ostream &out); + + void output_one(std::ostream &out, driver_enumerator &drivlist, const game_driver &driver, device_type_set *devtypes); + void output_sampleof(std::ostream &out, device_t &device); + void output_bios(std::ostream &out, device_t const &device); + void output_rom(std::ostream &out, driver_enumerator *drivlist, const game_driver *driver, device_t &device); + void output_device_refs(std::ostream &out, device_t &root); + void output_sample(std::ostream &out, device_t &device); + void output_chips(std::ostream &out, device_t &device, const char *root_tag); + void output_display(std::ostream &out, device_t &device, machine_flags::type const *flags, const char *root_tag); + void output_sound(std::ostream &out, device_t &device); + void output_ioport_condition(std::ostream &out, const ioport_condition &condition, unsigned indent); + void output_input(std::ostream &out, const ioport_list &portlist); + void output_switches(std::ostream &out, const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *loctag, const char *innertag); + void output_ports(std::ostream &out, const ioport_list &portlist); + void output_adjusters(std::ostream &out, const ioport_list &portlist); + void output_driver(std::ostream &out, game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect); + void output_features(std::ostream &out, device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect); + void output_images(std::ostream &out, device_t &device, const char *root_tag); + void output_slots(std::ostream &out, machine_config &config, device_t &device, const char *root_tag, device_type_set *devtypes); + void output_software_list(std::ostream &out, device_t &root); + void output_ramoptions(std::ostream &out, device_t &root); + + void output_one_device(std::ostream &out, machine_config &config, device_t &device, const char *devtag); + void output_devices(std::ostream &out, emu_options &lookup_options, device_type_set const *filter); + + const char *get_merge_name(driver_enumerator &drivlist, const game_driver &driver, util::hash_collection const &romhashes); +}; + + +//************************************************************************** // GLOBAL VARIABLES //************************************************************************** // DTD string describing the data -const char info_xml_creator::s_dtd_string[] = +static const char s_dtd_string[] = "<!DOCTYPE __XML_ROOT__ [\n" "<!ELEMENT __XML_ROOT__ (__XML_TOP__+)>\n" "\t<!ATTLIST __XML_ROOT__ build CDATA #IMPLIED>\n" @@ -212,132 +262,212 @@ const char info_xml_creator::s_dtd_string[] = //------------------------------------------------- info_xml_creator::info_xml_creator(emu_options const &options, bool dtd) - : m_output(nullptr) - , m_dtd(dtd) + : m_dtd(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(std::ostream &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()) - return true; - - bool result = false; - auto it = matched.begin(); - for (std::string const &pat : patterns) + // no patterns specified - show everything + output(out); + } + 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); + + // 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()); + } + } +} + + +//------------------------------------------------- +// output - print the XML information for all +// known (and filtered) machines +//------------------------------------------------- + +void info_xml_creator::output(std::ostream &out, const std::function<bool(const char *shortname, bool &done)> &filter, bool include_devices) +{ + struct prepared_info + { + std::string m_xml_snippet; + device_type_set m_dev_set; + }; + + // 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; + + auto output_header_if_necessary = [this, &header_outputted](std::ostream &out) + { + if (!header_outputted) + { + output_header(out, m_dtd); + header_outputted = true; } - return result; }; - // iterate through the drivers, outputting one at a time - bool first = true; - while (drivlist.next()) + // only keep a device set when we're asked to track it + std::unique_ptr<device_type_set> devfilter; + if (include_devices && filter) + devfilter = std::make_unique<device_type_set>(); + + // prepare a queue of futures + std::queue<std::future<prepared_info>> queue; + + // try enumerating drivers and outputting them + while (!queue.empty() || (!drivlist_done && !filter_done)) { - if (included(drivlist.driver().name)) + // try populating the queue + while (queue.size() < 20 && !drivlist_done && !filter_done) { - if (first) + if (!drivlist.next()) { - output_header(); - first = false; + // 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 || filter(drivlist.driver().name, filter_done)) + { + const game_driver &driver(drivlist.driver()); + std::future<prepared_info> future_pi = std::async(std::launch::async, [&drivlist, &driver, &devfilter] + { + prepared_info result; + std::ostringstream stream; + + output_one(stream, drivlist, driver, devfilter ? &result.m_dev_set : nullptr); + result.m_xml_snippet = stream.str(); + return result; + }); + queue.push(std::move(future_pi)); } - output_one(drivlist, devfilter.get()); + } - // stop looking if we found everything specified - if (!patterns.empty() && exact_matches == patterns.size()) - break; + // now that we have the queue populated, try grabbing one (assuming that it is not empty) + if (!queue.empty()) + { + // wait for the future to complete and get the info + prepared_info pi = queue.front().get(); + queue.pop(); + + // emit the XML + output_header_if_necessary(out); + out << pi.m_xml_snippet; + + // merge devices into devfilter, if appropriate + if (devfilter) + { + for (const auto &x : pi.m_dev_set) + devfilter->insert(x); + } } } // 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 || 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 (include_devices && (!devfilter || !devfilter->empty())) { - if (first) - { - output_header(); - first = false; - } - output_devices(devfilter.get()); + output_header_if_necessary(out); + output_devices(out, m_lookup_options, devfilter.get()); } - if (!first) - output_footer(); + if (header_outputted) + output_footer(out); +} - // 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; - } -} +//************************************************************************** +// ANONYMOUS NAMESPACE IMPLEMENTATION +//************************************************************************** +namespace +{ //------------------------------------------------- -// output_mame_xml - print the XML information -// for a subset of games +// normalize_string //------------------------------------------------- -void info_xml_creator::output(FILE *out, driver_enumerator &drivlist, bool nodevices) +std::string normalize_string(const char *string) { - m_output = out; - - device_type_set devfilter; - - output_header(); + std::ostringstream stream; - // 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(); + if (string != nullptr) + { + while (*string) + { + switch (*string) + { + case '\"': stream << """; break; + case '&': stream << "&"; break; + case '<': stream << "<"; break; + case '>': stream << ">"; break; + default: + stream << *string; + break; + } + ++string; + } + } + return stream.str(); } @@ -346,21 +476,21 @@ void info_xml_creator::output(FILE *out, driver_enumerator &drivlist, bool nodev // the root element //------------------------------------------------- -void info_xml_creator::output_header() +void output_header(std::ostream &out, bool dtd) { - if (m_dtd) + if (dtd) { // output the DTD - fprintf(m_output, "<?xml version=\"1.0\"?>\n"); + out << "<?xml version=\"1.0\"?>\n"; std::string dtd(s_dtd_string); strreplace(dtd, "__XML_ROOT__", XML_ROOT); strreplace(dtd, "__XML_TOP__", XML_TOP); - fprintf(m_output, "%s\n\n", dtd.c_str()); + out << dtd << "\n\n"; } // top-level tag - fprintf(m_output, "<%s build=\"%s\" debug=\"" + out << util::string_format("<%s build=\"%s\" debug=\"" #ifdef MAME_DEBUG "yes" #else @@ -368,7 +498,7 @@ void info_xml_creator::output_header() #endif "\" mameconfig=\"%d\">\n", XML_ROOT, - util::xml::normalize_string(emulator_info::get_build_version()), + normalize_string(emulator_info::get_build_version()), CONFIG_VERSION); } @@ -377,23 +507,22 @@ void info_xml_creator::output_header() // output_header - close the root element //------------------------------------------------- -void info_xml_creator::output_footer() +void output_footer(std::ostream &out) { // close the top level tag - fprintf(m_output, "</%s>\n", XML_ROOT); + out << util::string_format("</%s>\n", XML_ROOT); } //------------------------------------------------- // 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) +void output_one(std::ostream &out, driver_enumerator &drivlist, const game_driver &driver, 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; @@ -440,66 +569,66 @@ void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set * } // print the header and the machine name - fprintf(m_output, "\t<%s name=\"%s\"", XML_TOP, util::xml::normalize_string(driver.name)); + out << util::string_format("\t<%s name=\"%s\"", XML_TOP, normalize_string(driver.name)); // strip away any path information from the source_file and output it const char *start = strrchr(driver.type.source(), '/'); if (!start) start = strrchr(driver.type.source(), '\\'); start = start ? (start + 1) : driver.type.source(); - fprintf(m_output, " sourcefile=\"%s\"", util::xml::normalize_string(start)); + out << util::string_format(" sourcefile=\"%s\"", normalize_string(start)); // append bios and runnable flags if (driver.flags & machine_flags::IS_BIOS_ROOT) - fprintf(m_output, " isbios=\"yes\""); + out << " isbios=\"yes\""; if (driver.flags & machine_flags::MECHANICAL) - fprintf(m_output, " ismechanical=\"yes\""); + out << " ismechanical=\"yes\""; // display clone information int clone_of = drivlist.find(driver.parent); if (clone_of != -1 && !(drivlist.driver(clone_of).flags & machine_flags::IS_BIOS_ROOT)) - fprintf(m_output, " cloneof=\"%s\"", util::xml::normalize_string(drivlist.driver(clone_of).name)); + out << util::string_format(" cloneof=\"%s\"", normalize_string(drivlist.driver(clone_of).name)); if (clone_of != -1) - fprintf(m_output, " romof=\"%s\"", util::xml::normalize_string(drivlist.driver(clone_of).name)); + out << util::string_format(" romof=\"%s\"", normalize_string(drivlist.driver(clone_of).name)); // display sample information and close the game tag - output_sampleof(config->root_device()); - fprintf(m_output, ">\n"); + output_sampleof(out, config.root_device()); + out << ">\n"; // output game description if (driver.type.fullname() != nullptr) - fprintf(m_output, "\t\t<description>%s</description>\n", util::xml::normalize_string(driver.type.fullname())); + out << util::string_format("\t\t<description>%s</description>\n", normalize_string(driver.type.fullname())); // print the year only if is a number or another allowed character (? or +) if (driver.year != nullptr && strspn(driver.year, "0123456789?+") == strlen(driver.year)) - fprintf(m_output, "\t\t<year>%s</year>\n", util::xml::normalize_string(driver.year)); + out << util::string_format("\t\t<year>%s</year>\n", normalize_string(driver.year)); // print the manufacturer information if (driver.manufacturer != nullptr) - fprintf(m_output, "\t\t<manufacturer>%s</manufacturer>\n", util::xml::normalize_string(driver.manufacturer)); + out << util::string_format("\t\t<manufacturer>%s</manufacturer>\n", 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_input(portlist); - output_switches(portlist, "", IPT_DIPSWITCH, "dipswitch", "diplocation", "dipvalue"); - output_switches(portlist, "", IPT_CONFIG, "configuration", "conflocation", "confsetting"); - output_ports(portlist); - 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_bios(out, config.root_device()); + output_rom(out, &drivlist, &driver, config.root_device()); + output_device_refs(out, config.root_device()); + output_sample(out, config.root_device()); + output_chips(out, config.root_device(), ""); + output_display(out, config.root_device(), &driver.flags, ""); + output_sound(out, config.root_device()); + output_input(out, portlist); + output_switches(out, portlist, "", IPT_DIPSWITCH, "dipswitch", "diplocation", "dipvalue"); + output_switches(out, portlist, "", IPT_CONFIG, "configuration", "conflocation", "confsetting"); + output_ports(out, portlist); + output_adjusters(out, portlist); + output_driver(out, driver, overall_unemulated, overall_imperfect); + output_features(out, driver.type, overall_unemulated, overall_imperfect); + output_images(out, config.root_device(), ""); + output_slots(out, config, config.root_device(), "", devtypes); + output_software_list(out, config.root_device()); + output_ramoptions(out, config.root_device()); // close the topmost tag - fprintf(m_output, "\t</%s>\n", XML_TOP); + out << util::string_format("\t</%s>\n", XML_TOP); } @@ -508,7 +637,7 @@ void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set * // a single device //------------------------------------------------- -void info_xml_creator::output_one_device(machine_config &config, device_t &device, const char *devtag) +void output_one_device(std::ostream &out, machine_config &config, device_t &device, const char *devtag) { bool has_speaker = false, has_input = false; // check if the device adds speakers to the system @@ -538,33 +667,33 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic } // start to output info - fprintf(m_output, "\t<%s name=\"%s\"", XML_TOP, util::xml::normalize_string(device.shortname())); + out << util::string_format("\t<%s name=\"%s\"", XML_TOP, normalize_string(device.shortname())); std::string src(device.source()); strreplace(src,"../", ""); - fprintf(m_output, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", util::xml::normalize_string(src.c_str())); - output_sampleof(device); - fprintf(m_output, ">\n\t\t<description>%s</description>\n", util::xml::normalize_string(device.name())); + out << util::string_format(" sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(src.c_str())); + output_sampleof(out, device); + out << ">\n" << util::string_format("\t\t<description>%s</description>\n", normalize_string(device.name())); - output_bios(device); - output_rom(nullptr, device); - output_device_refs(device); + output_bios(out, device); + output_rom(out, nullptr, nullptr, device); + output_device_refs(out, device); if (device.type().type() != typeid(samples_device)) // ignore samples_device itself - output_sample(device); + output_sample(out, device); - output_chips(device, devtag); - output_display(device, nullptr, devtag); + output_chips(out, device, devtag); + output_display(out, device, nullptr, devtag); if (has_speaker) - output_sound(device); + output_sound(out, device); if (has_input) - output_input(portlist); - output_switches(portlist, devtag, IPT_DIPSWITCH, "dipswitch", "diplocation", "dipvalue"); - output_switches(portlist, devtag, IPT_CONFIG, "configuration", "conflocation", "confsetting"); - output_adjusters(portlist); - output_features(device.type(), overall_unemulated, overall_imperfect); - output_images(device, devtag); - output_slots(config, device, devtag, nullptr); - fprintf(m_output, "\t</%s>\n", XML_TOP); + output_input(out, portlist); + output_switches(out, portlist, devtag, IPT_DIPSWITCH, "dipswitch", "diplocation", "dipvalue"); + output_switches(out, portlist, devtag, IPT_CONFIG, "configuration", "conflocation", "confsetting"); + output_adjusters(out, portlist); + output_features(out, device.type(), overall_unemulated, overall_imperfect); + output_images(out, device, devtag); + output_slots(out, config, device, devtag, nullptr); + out << util::string_format("\t</%s>\n", XML_TOP); } @@ -573,12 +702,12 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic // registered device types //------------------------------------------------- -void info_xml_creator::output_devices(device_type_set const *filter) +void output_devices(std::ostream &out, emu_options &lookup_options, device_type_set const *filter) { // get config for empty machine - machine_config config(GAME_NAME(___empty), m_lookup_options); + machine_config config(GAME_NAME(___empty), lookup_options); - auto const action = [this, &config] (device_type type) + auto const action = [&config, &out] (device_type type) { // add it at the root of the machine config device_t *dev; @@ -593,7 +722,7 @@ void info_xml_creator::output_devices(device_type_set const *filter) device.config_complete(); // print details and remove it - output_one_device(config, *dev, dev->tag()); + output_one_device(out, config, *dev, dev->tag()); machine_config::token const tok(config.begin_configuration(config.root_device())); config.device_remove("_tmp"); }; @@ -615,11 +744,11 @@ void info_xml_creator::output_devices(device_type_set const *filter) // subdevice, print a reference //------------------------------------------------- -void info_xml_creator::output_device_refs(device_t &root) +void output_device_refs(std::ostream &out, device_t &root) { for (device_t &device : device_iterator(root)) if (&device != &root) - fprintf(m_output, "\t\t<device_ref name=\"%s\"/>\n", util::xml::normalize_string(device.shortname())); + out << util::string_format("\t\t<device_ref name=\"%s\"/>\n", normalize_string(device.shortname())); } @@ -628,7 +757,7 @@ void info_xml_creator::output_device_refs(device_t &root) // attribute, if appropriate //------------------------------------------------- -void info_xml_creator::output_sampleof(device_t &device) +void output_sampleof(std::ostream &out, device_t &device) { // iterate over sample devices for (samples_device &samples : samples_device_iterator(device)) @@ -636,7 +765,7 @@ void info_xml_creator::output_sampleof(device_t &device) samples_iterator sampiter(samples); if (sampiter.altbasename() != nullptr) { - fprintf(m_output, " sampleof=\"%s\"", util::xml::normalize_string(sampiter.altbasename())); + out << util::string_format(" sampleof=\"%s\"", normalize_string(sampiter.altbasename())); // must stop here, as there can only be one attribute of the same name return; @@ -649,7 +778,7 @@ void info_xml_creator::output_sampleof(device_t &device) // output_bios - print BIOS sets for a device //------------------------------------------------- -void info_xml_creator::output_bios(device_t const &device) +void output_bios(std::ostream &out, device_t const &device) { // first determine the default BIOS name char const *defaultname(nullptr); @@ -662,13 +791,13 @@ void info_xml_creator::output_bios(device_t const &device) // iterate over ROM entries and look for BIOSes for (romload::system_bios const &bios : romload::entries(device.rom_region()).get_system_bioses()) { - // output extracted name and descriptions - fprintf(m_output, "\t\t<biosset"); - fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(bios.get_name())); - fprintf(m_output, " description=\"%s\"", util::xml::normalize_string(bios.get_description())); + // output extracted name and descriptions' + out << "\t\t<biosset"; + out << util::string_format(" name=\"%s\"", normalize_string(bios.get_name())); + out << util::string_format(" description=\"%s\"", normalize_string(bios.get_description())); if (defaultname && !std::strcmp(defaultname, bios.get_name())) - fprintf(m_output, " default=\"yes\""); - fprintf(m_output, "/>\n"); + out << " default=\"yes\""; + out << "/>\n"; } } @@ -678,7 +807,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 output_rom(std::ostream &out, driver_enumerator *drivlist, const game_driver *driver, device_t &device) { enum class type { BIOS, NORMAL, DISK }; std::map<u32, char const *> biosnames; @@ -758,47 +887,50 @@ 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"); + if (is_disk) + out << "\t\t<disk"; + else + out << "\t\t<rom"; // add name, merge, bios, and size tags */ char const *const name(rom->name); if (name && name[0]) - fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(name)); + out << util::string_format(" name=\"%s\"", normalize_string(name)); if (merge_name) - fprintf(m_output, " merge=\"%s\"", util::xml::normalize_string(merge_name)); + out << util::string_format(" merge=\"%s\"", normalize_string(merge_name)); if (bios_name) - fprintf(m_output, " bios=\"%s\"", util::xml::normalize_string(bios_name)); + out << util::string_format(" bios=\"%s\"", normalize_string(bios_name)); if (!is_disk) - fprintf(m_output, " size=\"%u\"", rom_file_size(rom)); + out << util::string_format(" size=\"%u\"", rom_file_size(rom)); // dump checksum information only if there is a known dump if (!hashes.flag(util::hash_collection::FLAG_NO_DUMP)) - fprintf(m_output, " %s", hashes.attribute_string().c_str()); // iterate over hash function types and print m_output their values + out << ' ' << hashes.attribute_string(); // iterate over hash function types and print m_output their values else - fprintf(m_output, " status=\"nodump\""); + out << " status=\"nodump\""; // append a region name - fprintf(m_output, " region=\"%s\"", region->name); + out << util::string_format(" region=\"%s\"", region->name); if (!is_disk) { // for non-disk entries, print offset - fprintf(m_output, " offset=\"%x\"", ROM_GETOFFSET(rom)); + out << util::string_format(" offset=\"%x\"", ROM_GETOFFSET(rom)); } else { // for disk entries, add the disk index - fprintf(m_output, " index=\"%x\" writable=\"%s\"", DISK_GETINDEX(rom), DISK_ISREADONLY(rom) ? "no" : "yes"); + out << util::string_format(" index=\"%x\" writable=\"%s\"", DISK_GETINDEX(rom), DISK_ISREADONLY(rom) ? "no" : "yes"); } // add optional flag if (ROM_ISOPTIONAL(rom)) - fprintf(m_output, " optional=\"yes\""); + out << " optional=\"yes\""; - fprintf(m_output, "/>\n"); + out << "/>\n"; } bios_scanned = true; } @@ -810,7 +942,7 @@ void info_xml_creator::output_rom(driver_enumerator *drivlist, device_t &device) // samples referenced by a game_driver //------------------------------------------------- -void info_xml_creator::output_sample(device_t &device) +void output_sample(std::ostream &out, device_t &device) { // iterate over sample devices for (samples_device &samples : samples_device_iterator(device)) @@ -824,7 +956,7 @@ void info_xml_creator::output_sample(device_t &device) continue; // output the sample name - fprintf(m_output, "\t\t<sample name=\"%s\"/>\n", util::xml::normalize_string(samplename)); + out << util::string_format("\t\t<sample name=\"%s\"/>\n", normalize_string(samplename)); } } } @@ -835,7 +967,7 @@ void info_xml_creator::output_sample(device_t &device) sound chips used by a game -------------------------------------------------*/ -void info_xml_creator::output_chips(device_t &device, const char *root_tag) +void output_chips(std::ostream &out, device_t &device, const char *root_tag) { // iterate over executable devices for (device_execute_interface &exec : execute_interface_iterator(device)) @@ -845,12 +977,12 @@ void info_xml_creator::output_chips(device_t &device, const char *root_tag) std::string newtag(exec.device().tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); - fprintf(m_output, "\t\t<chip"); - fprintf(m_output, " type=\"cpu\""); - fprintf(m_output, " tag=\"%s\"", util::xml::normalize_string(newtag.c_str())); - fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(exec.device().name())); - fprintf(m_output, " clock=\"%d\"", exec.device().clock()); - fprintf(m_output, "/>\n"); + out << "\t\t<chip"; + out << " type=\"cpu\""; + out << util::string_format(" tag=\"%s\"", normalize_string(newtag.c_str())); + out << util::string_format(" name=\"%s\"", normalize_string(exec.device().name())); + out << util::string_format(" clock=\"%d\"", exec.device().clock()); + out << "/>\n"; } } @@ -862,13 +994,13 @@ void info_xml_creator::output_chips(device_t &device, const char *root_tag) std::string newtag(sound.device().tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); - fprintf(m_output, "\t\t<chip"); - fprintf(m_output, " type=\"audio\""); - fprintf(m_output, " tag=\"%s\"", util::xml::normalize_string(newtag.c_str())); - fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(sound.device().name())); + out << "\t\t<chip"; + out << " type=\"audio\""; + out << util::string_format(" tag=\"%s\"", normalize_string(newtag.c_str())); + out << util::string_format(" name=\"%s\"", normalize_string(sound.device().name())); if (sound.device().clock() != 0) - fprintf(m_output, " clock=\"%d\"", sound.device().clock()); - fprintf(m_output, "/>\n"); + out << util::string_format(" clock=\"%d\"", sound.device().clock()); + out << "/>\n"; } } } @@ -879,7 +1011,7 @@ void info_xml_creator::output_chips(device_t &device, const char *root_tag) // displays //------------------------------------------------- -void info_xml_creator::output_display(device_t &device, machine_flags::type const *flags, const char *root_tag) +void output_display(std::ostream &out, device_t &device, machine_flags::type const *flags, const char *root_tag) { // iterate over screens for (const screen_device &screendev : screen_device_iterator(device)) @@ -889,43 +1021,43 @@ void info_xml_creator::output_display(device_t &device, machine_flags::type cons std::string newtag(screendev.tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); - fprintf(m_output, "\t\t<display tag=\"%s\"", util::xml::normalize_string(newtag.c_str())); + out << util::string_format("\t\t<display tag=\"%s\"", normalize_string(newtag.c_str())); switch (screendev.screen_type()) { - case SCREEN_TYPE_RASTER: fprintf(m_output, " type=\"raster\""); break; - case SCREEN_TYPE_VECTOR: fprintf(m_output, " type=\"vector\""); break; - case SCREEN_TYPE_LCD: fprintf(m_output, " type=\"lcd\""); break; - case SCREEN_TYPE_SVG: fprintf(m_output, " type=\"svg\""); break; - default: fprintf(m_output, " type=\"unknown\""); break; + case SCREEN_TYPE_RASTER: out << " type=\"raster\""; break; + case SCREEN_TYPE_VECTOR: out << " type=\"vector\""; break; + case SCREEN_TYPE_LCD: out << " type=\"lcd\""; break; + case SCREEN_TYPE_SVG: out << " type=\"svg\""; break; + default: out << " type=\"unknown\""; break; } // output the orientation as a string switch (screendev.orientation()) { case ORIENTATION_FLIP_X: - fprintf(m_output, " rotate=\"0\" flipx=\"yes\""); + out << " rotate=\"0\" flipx=\"yes\""; break; case ORIENTATION_FLIP_Y: - fprintf(m_output, " rotate=\"180\" flipx=\"yes\""); + out << " rotate=\"180\" flipx=\"yes\""; break; case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y: - fprintf(m_output, " rotate=\"180\""); + out << " rotate=\"180\""; break; case ORIENTATION_SWAP_XY: - fprintf(m_output, " rotate=\"90\" flipx=\"yes\""); + out << " rotate=\"90\" flipx=\"yes\""; break; case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X: - fprintf(m_output, " rotate=\"90\""); + out << " rotate=\"90\""; break; case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y: - fprintf(m_output, " rotate=\"270\""); + out << " rotate=\"270\""; break; case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y: - fprintf(m_output, " rotate=\"270\" flipx=\"yes\""); + out << " rotate=\"270\" flipx=\"yes\""; break; default: - fprintf(m_output, " rotate=\"0\""); + out << " rotate=\"0\""; break; } @@ -933,12 +1065,12 @@ void info_xml_creator::output_display(device_t &device, machine_flags::type cons if (screendev.screen_type() != SCREEN_TYPE_VECTOR) { const rectangle &visarea = screendev.visible_area(); - fprintf(m_output, " width=\"%d\"", visarea.width()); - fprintf(m_output, " height=\"%d\"", visarea.height()); + out << util::string_format(" width=\"%d\"", visarea.width()); + out << util::string_format(" height=\"%d\"", visarea.height()); } // output refresh rate - fprintf(m_output, " refresh=\"%f\"", ATTOSECONDS_TO_HZ(screendev.refresh_attoseconds())); + out << util::string_format(" refresh=\"%f\"", ATTOSECONDS_TO_HZ(screendev.refresh_attoseconds())); // output raw video parameters only for games that are not vector // and had raw parameters specified @@ -946,15 +1078,15 @@ void info_xml_creator::output_display(device_t &device, machine_flags::type cons { int pixclock = screendev.width() * screendev.height() * ATTOSECONDS_TO_HZ(screendev.refresh_attoseconds()); - fprintf(m_output, " pixclock=\"%d\"", pixclock); - fprintf(m_output, " htotal=\"%d\"", screendev.width()); - fprintf(m_output, " hbend=\"%d\"", screendev.visible_area().min_x); - fprintf(m_output, " hbstart=\"%d\"", screendev.visible_area().max_x+1); - fprintf(m_output, " vtotal=\"%d\"", screendev.height()); - fprintf(m_output, " vbend=\"%d\"", screendev.visible_area().min_y); - fprintf(m_output, " vbstart=\"%d\"", screendev.visible_area().max_y+1); + out << util::string_format(" pixclock=\"%d\"", pixclock); + out << util::string_format(" htotal=\"%d\"", screendev.width()); + out << util::string_format(" hbend=\"%d\"", screendev.visible_area().min_x); + out << util::string_format(" hbstart=\"%d\"", screendev.visible_area().max_x+1); + out << util::string_format(" vtotal=\"%d\"", screendev.height()); + out << util::string_format(" vbend=\"%d\"", screendev.visible_area().min_y); + out << util::string_format(" vbstart=\"%d\"", screendev.visible_area().max_y+1); } - fprintf(m_output, " />\n"); + out << " />\n"; } } } @@ -965,7 +1097,7 @@ void info_xml_creator::output_display(device_t &device, machine_flags::type cons // speakers //------------------------------------------------ -void info_xml_creator::output_sound(device_t &device) +void output_sound(std::ostream &out, device_t &device) { speaker_device_iterator spkiter(device); int speakers = spkiter.count(); @@ -975,7 +1107,7 @@ void info_xml_creator::output_sound(device_t &device) if (snditer.first() == nullptr) speakers = 0; - fprintf(m_output, "\t\t<sound channels=\"%d\"/>\n", speakers); + out << util::string_format("\t\t<sound channels=\"%d\"/>\n", speakers); } @@ -984,10 +1116,10 @@ void info_xml_creator::output_sound(device_t &device) // required to use I/O port field/setting //------------------------------------------------- -void info_xml_creator::output_ioport_condition(const ioport_condition &condition, unsigned indent) +void output_ioport_condition(std::ostream &out, const ioport_condition &condition, unsigned indent) { for (unsigned i = 0; indent > i; ++i) - fprintf(m_output, "\t"); + out << '\t'; char const *rel(nullptr); switch (condition.condition()) @@ -1001,7 +1133,7 @@ void info_xml_creator::output_ioport_condition(const ioport_condition &condition case ioport_condition::NOTLESSTHAN: rel = "ge"; break; } - fprintf(m_output,"<condition tag=\"%s\" mask=\"%u\" relation=\"%s\" value=\"%u\"/>\n", util::xml::normalize_string(condition.tag()), condition.mask(), rel, condition.value()); + out << util::string_format("<condition tag=\"%s\" mask=\"%u\" relation=\"%s\" value=\"%u\"/>\n", normalize_string(condition.tag()), condition.mask(), rel, condition.value()); } //------------------------------------------------- @@ -1009,7 +1141,7 @@ void info_xml_creator::output_ioport_condition(const ioport_condition &condition // input //------------------------------------------------- -void info_xml_creator::output_input(const ioport_list &portlist) +void output_input(std::ostream &out, const ioport_list &portlist) { // enumerated list of control types // NOTE: the order is chosen so that 'spare' button inputs are assigned to the @@ -1403,15 +1535,15 @@ void info_xml_creator::output_input(const ioport_list &portlist) // Output the input info // First basic info - fprintf(m_output, "\t\t<input"); - fprintf(m_output, " players=\"%d\"", nplayer); + out << "\t\t<input"; + out << util::string_format(" players=\"%d\"", nplayer); if (ncoin != 0) - fprintf(m_output, " coins=\"%d\"", ncoin); + out << util::string_format(" coins=\"%d\"", ncoin); if (service) - fprintf(m_output, " service=\"yes\""); + out << util::string_format(" service=\"yes\""); if (tilt) - fprintf(m_output, " tilt=\"yes\""); - fprintf(m_output, ">\n"); + out << util::string_format(" tilt=\"yes\""); + out << ">\n"; // Then controller specific ones for (auto & elem : control_info) @@ -1420,25 +1552,25 @@ void info_xml_creator::output_input(const ioport_list &portlist) //printf("type %s - player %d - buttons %d\n", elem.type, elem.player, elem.nbuttons); if (elem.analog) { - fprintf(m_output, "\t\t\t<control type=\"%s\"", util::xml::normalize_string(elem.type)); + out << util::string_format("\t\t\t<control type=\"%s\"", normalize_string(elem.type)); if (nplayer > 1) - fprintf(m_output, " player=\"%d\"", elem.player); + out << util::string_format(" player=\"%d\"", elem.player); if (elem.nbuttons > 0) { - fprintf(m_output, " buttons=\"%d\"", strcmp(elem.type, "stick") ? elem.nbuttons : elem.maxbuttons); + out << util::string_format(" buttons=\"%d\"", strcmp(elem.type, "stick") ? elem.nbuttons : elem.maxbuttons); if (elem.reqbuttons < elem.nbuttons) - fprintf(m_output, " reqbuttons=\"%d\"", elem.reqbuttons); + out << util::string_format(" reqbuttons=\"%d\"", elem.reqbuttons); } if (elem.min != 0 || elem.max != 0) - fprintf(m_output, " minimum=\"%d\" maximum=\"%d\"", elem.min, elem.max); + out << util::string_format(" minimum=\"%d\" maximum=\"%d\"", elem.min, elem.max); if (elem.sensitivity != 0) - fprintf(m_output, " sensitivity=\"%d\"", elem.sensitivity); + out << util::string_format(" sensitivity=\"%d\"", elem.sensitivity); if (elem.keydelta != 0) - fprintf(m_output, " keydelta=\"%d\"", elem.keydelta); + out << util::string_format(" keydelta=\"%d\"", elem.keydelta); if (elem.reverse) - fprintf(m_output, " reverse=\"yes\""); + out << " reverse=\"yes\""; - fprintf(m_output, "/>\n"); + out << "/>\n"; } else { @@ -1446,14 +1578,14 @@ void info_xml_creator::output_input(const ioport_list &portlist) if (elem.helper[0] == 0 && elem.helper[1] != 0) { elem.helper[0] = elem.helper[1]; elem.helper[1] = 0; } if (elem.helper[1] == 0 && elem.helper[2] != 0) { elem.helper[1] = elem.helper[2]; elem.helper[2] = 0; } const char *joys = (elem.helper[2] != 0) ? "triple" : (elem.helper[1] != 0) ? "double" : ""; - fprintf(m_output, "\t\t\t<control type=\"%s%s\"", joys, util::xml::normalize_string(elem.type)); + out << util::string_format("\t\t\t<control type=\"%s%s\"", joys, normalize_string(elem.type)); if (nplayer > 1) - fprintf(m_output, " player=\"%d\"", elem.player); + out << util::string_format(" player=\"%d\"", elem.player); if (elem.nbuttons > 0) { - fprintf(m_output, " buttons=\"%d\"", strcmp(elem.type, "joy") ? elem.nbuttons : elem.maxbuttons); + out << util::string_format(" buttons=\"%d\"", strcmp(elem.type, "joy") ? elem.nbuttons : elem.maxbuttons); if (elem.reqbuttons < elem.nbuttons) - fprintf(m_output, " reqbuttons=\"%d\"", elem.reqbuttons); + out << util::string_format(" reqbuttons=\"%d\"", elem.reqbuttons); } for (int lp = 0; lp < 3 && elem.helper[lp] != 0; lp++) { @@ -1488,13 +1620,13 @@ void info_xml_creator::output_input(const ioport_list &portlist) ways = "strange2"; break; } - fprintf(m_output, " ways%s=\"%s\"", plural, ways); + out << util::string_format(" ways%s=\"%s\"", plural, ways); } - fprintf(m_output, "/>\n"); + out << "/>\n"; } } - fprintf(m_output, "\t\t</input>\n"); + out << "\t\t</input>\n"; } @@ -1503,7 +1635,7 @@ void info_xml_creator::output_input(const ioport_list &portlist) // DIP switch settings //------------------------------------------------- -void info_xml_creator::output_switches(const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *loctag, const char *innertag) +void output_switches(std::ostream &out, const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *loctag, const char *innertag) { // iterate looking for DIP switches for (auto &port : portlist) @@ -1514,41 +1646,41 @@ void info_xml_creator::output_switches(const ioport_list &portlist, const char * newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); // output the switch name information - std::string const normalized_field_name(util::xml::normalize_string(field.name())); - std::string const normalized_newtag(util::xml::normalize_string(newtag.c_str())); - fprintf(m_output, "\t\t<%s name=\"%s\" tag=\"%s\" mask=\"%u\">\n", outertag, normalized_field_name.c_str(), normalized_newtag.c_str(), field.mask()); + std::string const normalized_field_name(normalize_string(field.name())); + std::string const normalized_newtag(normalize_string(newtag.c_str())); + out << util::string_format("\t\t<%s name=\"%s\" tag=\"%s\" mask=\"%u\">\n", outertag, normalized_field_name.c_str(), normalized_newtag.c_str(), field.mask()); if (!field.condition().none()) - output_ioport_condition(field.condition(), 3); + output_ioport_condition(out, field.condition(), 3); // loop over locations for (ioport_diplocation const &diploc : field.diplocations()) { - fprintf(m_output, "\t\t\t<%s name=\"%s\" number=\"%u\"", loctag, util::xml::normalize_string(diploc.name()), diploc.number()); + out << util::string_format("\t\t\t<%s name=\"%s\" number=\"%u\"", loctag, normalize_string(diploc.name()), diploc.number()); if (diploc.inverted()) - fprintf(m_output, " inverted=\"yes\""); - fprintf(m_output, "/>\n"); + out << " inverted=\"yes\""; + out << "/>\n"; } // loop over settings for (ioport_setting const &setting : field.settings()) { - fprintf(m_output, "\t\t\t<%s name=\"%s\" value=\"%u\"", innertag, util::xml::normalize_string(setting.name()), setting.value()); + out << util::string_format("\t\t\t<%s name=\"%s\" value=\"%u\"", innertag, normalize_string(setting.name()), setting.value()); if (setting.value() == field.defvalue()) - fprintf(m_output, " default=\"yes\""); + out << " default=\"yes\""; if (setting.condition().none()) { - fprintf(m_output, "/>\n"); + out << "/>\n"; } else { - fprintf(m_output, ">\n"); - output_ioport_condition(setting.condition(), 4); - fprintf(m_output, "\t\t\t</%s>\n", innertag); + out << ">\n"; + output_ioport_condition(out, setting.condition(), 4); + out << util::string_format("\t\t\t</%s>\n", innertag); } } // terminate the switch entry - fprintf(m_output, "\t\t</%s>\n", outertag); + out << util::string_format("\t\t</%s>\n", outertag); } } @@ -1556,18 +1688,18 @@ void info_xml_creator::output_switches(const ioport_list &portlist, const char * // output_ports - print the structure of input // ports in the driver //------------------------------------------------- -void info_xml_creator::output_ports(const ioport_list &portlist) +void output_ports(std::ostream &out, const ioport_list &portlist) { // cycle through ports for (auto &port : portlist) { - fprintf(m_output,"\t\t<port tag=\"%s\">\n", util::xml::normalize_string(port.second->tag())); + out << util::string_format("\t\t<port tag=\"%s\">\n", normalize_string(port.second->tag())); for (ioport_field const &field : port.second->fields()) { if (field.is_analog()) - fprintf(m_output,"\t\t\t<analog mask=\"%u\"/>\n", field.mask()); + out << util::string_format("\t\t\t<analog mask=\"%u\"/>\n", field.mask()); } - fprintf(m_output,"\t\t</port>\n"); + out << util::string_format("\t\t</port>\n"); } } @@ -1577,14 +1709,14 @@ void info_xml_creator::output_ports(const ioport_list &portlist) // Adjusters for a game //------------------------------------------------- -void info_xml_creator::output_adjusters(const ioport_list &portlist) +void output_adjusters(std::ostream &out, const ioport_list &portlist) { // iterate looking for Adjusters for (auto &port : portlist) for (ioport_field const &field : port.second->fields()) if (field.type() == IPT_ADJUSTER) { - fprintf(m_output, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", util::xml::normalize_string(field.name()), field.defvalue()); + out << util::string_format("\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", normalize_string(field.name()), field.defvalue()); } } @@ -1593,9 +1725,9 @@ void info_xml_creator::output_adjusters(const ioport_list &portlist) // output_driver - print driver status //------------------------------------------------- -void info_xml_creator::output_driver(game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect) +void output_driver(std::ostream &out, game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect) { - fprintf(m_output, "\t\t<driver"); + out << "\t\t<driver"; /* The status entry is an hint for frontend authors to select working @@ -1612,26 +1744,26 @@ void info_xml_creator::output_driver(game_driver const &driver, device_t::featur bool const imperfect_preliminary((unemulated | imperfect) & device_t::feature::PROTECTION); if (machine_preliminary || unemulated_preliminary || imperfect_preliminary) - fprintf(m_output, " status=\"preliminary\""); + out << " status=\"preliminary\""; else if (imperfect) - fprintf(m_output, " status=\"imperfect\""); + out << " status=\"imperfect\""; else - fprintf(m_output, " status=\"good\""); + out << " status=\"good\""; if (flags & machine_flags::NOT_WORKING) - fprintf(m_output, " emulation=\"preliminary\""); + out << " emulation=\"preliminary\""; else - fprintf(m_output, " emulation=\"good\""); + out << " emulation=\"good\""; if (flags & machine_flags::NO_COCKTAIL) - fprintf(m_output, " cocktail=\"preliminary\""); + out << " cocktail=\"preliminary\""; if (flags & machine_flags::SUPPORTS_SAVE) - fprintf(m_output, " savestate=\"supported\""); + out << " savestate=\"supported\""; else - fprintf(m_output, " savestate=\"unsupported\""); + out << " savestate=\"unsupported\""; - fprintf(m_output, "/>\n"); + out << "/>\n"; } @@ -1640,7 +1772,7 @@ void info_xml_creator::output_driver(game_driver const &driver, device_t::featur // //------------------------------------------------- -void info_xml_creator::output_features(device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect) +void output_features(std::ostream &out, device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect) { static constexpr std::pair<device_t::feature_type, char const *> features[] = { { device_t::feature::PROTECTION, "protection" }, @@ -1670,21 +1802,21 @@ void info_xml_creator::output_features(device_type type, device_t::feature_type { if (flags & feature.first) { - fprintf(m_output, "\t\t<feature type=\"%s\"", feature.second); + out << util::string_format("\t\t<feature type=\"%s\"", feature.second); if (type.unemulated_features() & feature.first) { - fprintf(m_output, " status=\"unemulated\""); + out << " status=\"unemulated\""; } else { if (type.imperfect_features() & feature.first) - fprintf(m_output, " status=\"imperfect\""); + out << " status=\"imperfect\""; if (unemulated & feature.first) - fprintf(m_output, " overall=\"unemulated\""); + out << " overall=\"unemulated\""; else if ((~type.imperfect_features() & imperfect) & feature.first) - fprintf(m_output, " overall=\"imperfect\""); + out << " overall=\"imperfect\""; } - fprintf(m_output, "/>\n"); + out << "/>\n"; } } } @@ -1695,7 +1827,7 @@ void info_xml_creator::output_features(device_type type, device_t::feature_type // image devices //------------------------------------------------- -void info_xml_creator::output_images(device_t &device, const char *root_tag) +void output_images(std::ostream &out, device_t &device, const char *root_tag) { for (const device_image_interface &imagedev : image_interface_iterator(device)) { @@ -1706,46 +1838,47 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag) newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); // print m_output device type - fprintf(m_output, "\t\t<device type=\"%s\"", util::xml::normalize_string(imagedev.image_type_name())); + out << util::string_format("\t\t<device type=\"%s\"", normalize_string(imagedev.image_type_name())); // does this device have a tag? if (imagedev.device().tag()) - fprintf(m_output, " tag=\"%s\"", util::xml::normalize_string(newtag.c_str())); + out << util::string_format(" tag=\"%s\"", normalize_string(newtag.c_str())); // is this device available as media switch? if (!loadable) - fprintf(m_output, " fixed_image=\"1\""); + out << " fixed_image=\"1\""; // is this device mandatory? if (imagedev.must_be_loaded()) - fprintf(m_output, " mandatory=\"1\""); + out << " mandatory=\"1\""; if (imagedev.image_interface() && imagedev.image_interface()[0]) - fprintf(m_output, " interface=\"%s\"", util::xml::normalize_string(imagedev.image_interface())); + out << util::string_format(" interface=\"%s\"", normalize_string(imagedev.image_interface())); // close the XML tag - fprintf(m_output, ">\n"); + out << ">\n"; if (loadable) { - const char *name = imagedev.instance_name().c_str(); - const char *shortname = imagedev.brief_instance_name().c_str(); - - fprintf(m_output, "\t\t\t<instance"); - fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(name)); - fprintf(m_output, " briefname=\"%s\"", util::xml::normalize_string(shortname)); - fprintf(m_output, "/>\n"); + char const *const name = imagedev.instance_name().c_str(); + char const *const shortname = imagedev.brief_instance_name().c_str(); - std::string extensions(imagedev.file_extensions()); + out << "\t\t\t<instance"; + out << util::string_format(" name=\"%s\"", normalize_string(name)); + out << util::string_format(" briefname=\"%s\"", normalize_string(shortname)); + out << "/>\n"; - char *ext = strtok((char *)extensions.c_str(), ","); - while (ext != nullptr) + char const *extensions(imagedev.file_extensions()); + while (extensions) { - fprintf(m_output, "\t\t\t<extension name=\"%s\"/>\n", util::xml::normalize_string(ext)); - ext = strtok(nullptr, ","); + char const *end(extensions); + while (*end && (',' != *end)) + ++end; + out << util::string_format("\t\t\t<extension name=\"%s\"/>\n", normalize_string(std::string(extensions, end).c_str())); + extensions = *end ? (end + 1) : nullptr; } } - fprintf(m_output, "\t\t</device>\n"); + out << "\t\t</device>\n"; } } } @@ -1755,7 +1888,7 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag) // output_slots - prints all info about slots //------------------------------------------------- -void info_xml_creator::output_slots(machine_config &config, device_t &device, const char *root_tag, device_type_set *devtypes) +void output_slots(std::ostream &out, machine_config &config, device_t &device, const char *root_tag, device_type_set *devtypes) { for (device_slot_interface &slot : slot_interface_iterator(device)) { @@ -1770,7 +1903,7 @@ void info_xml_creator::output_slots(machine_config &config, device_t &device, co // print m_output device type if (listed) - fprintf(m_output, "\t\t<slot name=\"%s\">\n", util::xml::normalize_string(newtag.c_str())); + out << util::string_format("\t\t<slot name=\"%s\">\n", normalize_string(newtag.c_str())); for (auto &option : slot.option_list()) { @@ -1785,11 +1918,11 @@ void info_xml_creator::output_slots(machine_config &config, device_t &device, co if (listed && option.second->selectable()) { - fprintf(m_output, "\t\t\t<slotoption name=\"%s\"", util::xml::normalize_string(option.second->name())); - fprintf(m_output, " devname=\"%s\"", util::xml::normalize_string(dev->shortname())); + out << util::string_format("\t\t\t<slotoption name=\"%s\"", normalize_string(option.second->name())); + out << util::string_format(" devname=\"%s\"", normalize_string(dev->shortname())); if (slot.default_option() != nullptr && strcmp(slot.default_option(), option.second->name())==0) - fprintf(m_output, " default=\"yes\""); - fprintf(m_output, "/>\n"); + out << " default=\"yes\""; + out << "/>\n"; } config.device_remove("_dummy"); @@ -1797,7 +1930,7 @@ void info_xml_creator::output_slots(machine_config &config, device_t &device, co } if (listed) - fprintf(m_output, "\t\t</slot>\n"); + out << "\t\t</slot>\n"; } } } @@ -1808,14 +1941,14 @@ void info_xml_creator::output_slots(machine_config &config, device_t &device, co // for all known software lists for this system //------------------------------------------------- -void info_xml_creator::output_software_list(device_t &root) +void output_software_list(std::ostream &out, device_t &root) { for (const software_list_device &swlist : software_list_device_iterator(root)) { - fprintf(m_output, "\t\t<softwarelist name=\"%s\" status=\"%s\"", util::xml::normalize_string(swlist.list_name().c_str()), (swlist.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible"); + out << util::string_format("\t\t<softwarelist name=\"%s\" status=\"%s\"", normalize_string(swlist.list_name().c_str()), (swlist.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible"); if (swlist.filter()) - fprintf(m_output, " filter=\"%s\"", util::xml::normalize_string(swlist.filter())); - fprintf(m_output, "/>\n"); + out << util::string_format(" filter=\"%s\"", normalize_string(swlist.filter())); + out << "/>\n"; } } @@ -1826,7 +1959,7 @@ void info_xml_creator::output_software_list(device_t &root) // options for this system //------------------------------------------------- -void info_xml_creator::output_ramoptions(device_t &root) +void output_ramoptions(std::ostream &out, device_t &root) { for (const ram_device &ram : ram_device_iterator(root, 1)) { @@ -1840,15 +1973,15 @@ void info_xml_creator::output_ramoptions(device_t &root) { assert(!havedefault); havedefault = true; - fprintf(m_output, "\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", util::xml::normalize_string(option.first.c_str()), option.second); + out << util::string_format("\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", normalize_string(option.first.c_str()), option.second); } else { - fprintf(m_output, "\t\t<ramoption name=\"%s\">%u</ramoption>\n", util::xml::normalize_string(option.first.c_str()), option.second); + out << util::string_format("\t\t<ramoption name=\"%s\">%u</ramoption>\n", normalize_string(option.first.c_str()), option.second); } } if (!havedefault) - fprintf(m_output, "\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", ram.default_size_string(), defsize); + out << util::string_format("\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", ram.default_size_string(), defsize); break; } } @@ -1860,10 +1993,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 *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()) @@ -1880,3 +2013,15 @@ const char *info_xml_creator::get_merge_name(driver_enumerator &drivlist, util:: return nullptr; } + + +//------------------------------------------------- +// device_type_compare::operator() +//------------------------------------------------- + +bool device_type_compare::operator()(const std::add_pointer_t<device_type> &lhs, const std::add_pointer_t<device_type> &rhs) const +{ + return strcmp(lhs->shortname(), rhs->shortname()) < 0; +} + +} |