summaryrefslogtreecommitdiffstats
path: root/docs/release/src/frontend/mame/info.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docs/release/src/frontend/mame/info.cpp')
-rw-r--r--docs/release/src/frontend/mame/info.cpp1307
1 files changed, 762 insertions, 545 deletions
diff --git a/docs/release/src/frontend/mame/info.cpp b/docs/release/src/frontend/mame/info.cpp
index fa742dfe2f4..ca6798e0d73 100644
--- a/docs/release/src/frontend/mame/info.cpp
+++ b/docs/release/src/frontend/mame/info.cpp
@@ -25,6 +25,7 @@
#include "xmlfile.h"
#include <ctype.h>
+#include <map>
#define XML_ROOT "mame"
@@ -42,7 +43,7 @@ const char info_xml_creator::s_dtd_string[] =
"\t<!ATTLIST __XML_ROOT__ build CDATA #IMPLIED>\n"
"\t<!ATTLIST __XML_ROOT__ debug (yes|no) \"no\">\n"
"\t<!ATTLIST __XML_ROOT__ mameconfig CDATA #REQUIRED>\n"
-"\t<!ELEMENT __XML_TOP__ (description, year?, manufacturer?, biosset*, rom*, disk*, device_ref*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, port*, adjuster*, driver?, device*, slot*, softwarelist*, ramoption*)>\n"
+"\t<!ELEMENT __XML_TOP__ (description, year?, manufacturer?, biosset*, rom*, disk*, device_ref*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, port*, adjuster*, driver?, feature*, device*, slot*, softwarelist*, ramoption*)>\n"
"\t\t<!ATTLIST __XML_TOP__ name CDATA #REQUIRED>\n"
"\t\t<!ATTLIST __XML_TOP__ sourcefile CDATA #IMPLIED>\n"
"\t\t<!ATTLIST __XML_TOP__ isbios (yes|no) \"no\">\n"
@@ -90,7 +91,7 @@ const char info_xml_creator::s_dtd_string[] =
"\t\t\t<!ATTLIST chip clock CDATA #IMPLIED>\n"
"\t\t<!ELEMENT display EMPTY>\n"
"\t\t\t<!ATTLIST display tag CDATA #IMPLIED>\n"
-"\t\t\t<!ATTLIST display type (raster|vector|lcd|unknown) #REQUIRED>\n"
+"\t\t\t<!ATTLIST display type (raster|vector|lcd|svg|unknown) #REQUIRED>\n"
"\t\t\t<!ATTLIST display rotate (0|90|180|270) #IMPLIED>\n"
"\t\t\t<!ATTLIST display flipx (yes|no) \"no\">\n"
"\t\t\t<!ATTLIST display width CDATA #IMPLIED>\n"
@@ -105,6 +106,11 @@ const char info_xml_creator::s_dtd_string[] =
"\t\t\t<!ATTLIST display vbstart CDATA #IMPLIED>\n"
"\t\t<!ELEMENT sound EMPTY>\n"
"\t\t\t<!ATTLIST sound channels CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT condition EMPTY>\n"
+"\t\t\t<!ATTLIST condition tag CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST condition mask CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST condition relation (eq|ne|gt|le|lt|ge) #REQUIRED>\n"
+"\t\t\t<!ATTLIST condition value CDATA #REQUIRED>\n"
"\t\t<!ELEMENT input (control*)>\n"
"\t\t\t<!ATTLIST input service (yes|no) \"no\">\n"
"\t\t\t<!ATTLIST input tilt (yes|no) \"no\">\n"
@@ -123,19 +129,27 @@ const char info_xml_creator::s_dtd_string[] =
"\t\t\t\t<!ATTLIST control ways CDATA #IMPLIED>\n"
"\t\t\t\t<!ATTLIST control ways2 CDATA #IMPLIED>\n"
"\t\t\t\t<!ATTLIST control ways3 CDATA #IMPLIED>\n"
-"\t\t<!ELEMENT dipswitch (dipvalue*)>\n"
+"\t\t<!ELEMENT dipswitch (condition?, diplocation*, dipvalue*)>\n"
"\t\t\t<!ATTLIST dipswitch name CDATA #REQUIRED>\n"
"\t\t\t<!ATTLIST dipswitch tag CDATA #REQUIRED>\n"
"\t\t\t<!ATTLIST dipswitch mask CDATA #REQUIRED>\n"
-"\t\t\t<!ELEMENT dipvalue EMPTY>\n"
+"\t\t\t<!ELEMENT diplocation EMPTY>\n"
+"\t\t\t\t<!ATTLIST diplocation name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST diplocation number CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST diplocation inverted (yes|no) \"no\">\n"
+"\t\t\t<!ELEMENT dipvalue (condition?)>\n"
"\t\t\t\t<!ATTLIST dipvalue name CDATA #REQUIRED>\n"
"\t\t\t\t<!ATTLIST dipvalue value CDATA #REQUIRED>\n"
"\t\t\t\t<!ATTLIST dipvalue default (yes|no) \"no\">\n"
-"\t\t<!ELEMENT configuration (confsetting*)>\n"
+"\t\t<!ELEMENT configuration (condition?, conflocation*, confsetting*)>\n"
"\t\t\t<!ATTLIST configuration name CDATA #REQUIRED>\n"
"\t\t\t<!ATTLIST configuration tag CDATA #REQUIRED>\n"
"\t\t\t<!ATTLIST configuration mask CDATA #REQUIRED>\n"
-"\t\t\t<!ELEMENT confsetting EMPTY>\n"
+"\t\t\t<!ELEMENT conflocation EMPTY>\n"
+"\t\t\t\t<!ATTLIST conflocation name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST conflocation number CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST conflocation inverted (yes|no) \"no\">\n"
+"\t\t\t<!ELEMENT confsetting (condition?)>\n"
"\t\t\t\t<!ATTLIST confsetting name CDATA #REQUIRED>\n"
"\t\t\t\t<!ATTLIST confsetting value CDATA #REQUIRED>\n"
"\t\t\t\t<!ATTLIST confsetting default (yes|no) \"no\">\n"
@@ -143,19 +157,19 @@ const char info_xml_creator::s_dtd_string[] =
"\t\t\t<!ATTLIST port tag CDATA #REQUIRED>\n"
"\t\t\t<!ELEMENT analog EMPTY>\n"
"\t\t\t\t<!ATTLIST analog mask CDATA #REQUIRED>\n"
-"\t\t<!ELEMENT adjuster EMPTY>\n"
+"\t\t<!ELEMENT adjuster (condition?)>\n"
"\t\t\t<!ATTLIST adjuster name CDATA #REQUIRED>\n"
"\t\t\t<!ATTLIST adjuster default CDATA #REQUIRED>\n"
"\t\t<!ELEMENT driver EMPTY>\n"
"\t\t\t<!ATTLIST driver status (good|imperfect|preliminary) #REQUIRED>\n"
"\t\t\t<!ATTLIST driver emulation (good|imperfect|preliminary) #REQUIRED>\n"
-"\t\t\t<!ATTLIST driver color (good|imperfect|preliminary) #REQUIRED>\n"
-"\t\t\t<!ATTLIST driver sound (good|imperfect|preliminary) #REQUIRED>\n"
-"\t\t\t<!ATTLIST driver graphic (good|imperfect|preliminary) #REQUIRED>\n"
"\t\t\t<!ATTLIST driver cocktail (good|imperfect|preliminary) #IMPLIED>\n"
-"\t\t\t<!ATTLIST driver protection (good|imperfect|preliminary) #IMPLIED>\n"
"\t\t\t<!ATTLIST driver savestate (supported|unsupported) #REQUIRED>\n"
-"\t\t<!ELEMENT device (instance*, extension*)>\n"
+"\t\t<!ELEMENT feature EMPTY>\n"
+"\t\t\t<!ATTLIST feature type (protection|palette|graphics|sound|controls|keyboard|mouse|microphone|camera|disk|printer|lan|wan|timing) #REQUIRED>\n"
+"\t\t\t<!ATTLIST feature status (unemulated|imperfect) #IMPLIED>\n"
+"\t\t\t<!ATTLIST feature overall (unemulated|imperfect) #IMPLIED>\n"
+"\t\t<!ELEMENT device (instance?, extension*)>\n"
"\t\t\t<!ATTLIST device type CDATA #REQUIRED>\n"
"\t\t\t<!ATTLIST device tag CDATA #IMPLIED>\n"
"\t\t\t<!ATTLIST device fixed_image CDATA #IMPLIED>\n"
@@ -189,13 +203,10 @@ const char info_xml_creator::s_dtd_string[] =
// info_xml_creator - constructor
//-------------------------------------------------
-info_xml_creator::info_xml_creator(driver_enumerator &drivlist, bool filter_devices)
- : m_output(nullptr)
- , m_drivlist(drivlist)
- , m_filter_devices(filter_devices)
- , m_lookup_options(m_drivlist.options())
+info_xml_creator::info_xml_creator(emu_options const &options, bool dtd)
+ : m_output(nullptr),
+ m_dtd(dtd)
{
- mame_options::remove_device_options(m_lookup_options);
}
@@ -204,43 +215,164 @@ info_xml_creator::info_xml_creator(driver_enumerator &drivlist, bool filter_devi
// for all known games
//-------------------------------------------------
-void info_xml_creator::output(FILE *out, bool nodevices)
+void info_xml_creator::output(FILE *out, std::vector<std::string> const &patterns)
{
m_output = out;
- // output the DTD
- fprintf(m_output, "<?xml version=\"1.0\"?>\n");
- std::string dtd(s_dtd_string);
- strreplace(dtd, "__XML_ROOT__", XML_ROOT);
- strreplace(dtd, "__XML_TOP__", XML_TOP);
+ std::unique_ptr<device_type_set> devfilter(patterns.empty() ? nullptr : new device_type_set);
- fprintf(m_output, "%s\n\n", dtd.c_str());
+ // 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())
+ return true;
+
+ bool result = false;
+ auto it = matched.begin();
+ for (std::string const &pat : patterns)
+ {
+ if (!core_strwildcmp(pat.c_str(), name))
+ {
+ result = true;
+ if (!*it)
+ {
+ *it = true;
+ if (!core_iswildstr(pat.c_str()))
+ ++exact_matches;
+ }
+ }
+ ++it;
+ }
+ return result;
+ };
+
+ // iterate through the drivers, outputting one at a time
+ bool first = true;
+ while (drivlist.next())
+ {
+ if (included(drivlist.driver().name))
+ {
+ if (first)
+ {
+ output_header();
+ first = false;
+ }
+ output_one(drivlist, devfilter.get());
+
+ // stop looking if we found everything specified
+ if (!patterns.empty() && exact_matches == patterns.size())
+ break;
+ }
+ }
+
+ // iterate through the device types if not everything matches a driver
+ if (!patterns.empty() && exact_matches != patterns.size())
+ {
+ for (device_type type : registered_device_types)
+ {
+ if (included(type.shortname()))
+ {
+ devfilter->insert(&type);
+ if (exact_matches == patterns.size())
+ break;
+ }
+ }
+ }
+
+ // output devices (both devices with roms and slot devices)
+ if (!devfilter || !devfilter->empty())
+ {
+ if (first)
+ {
+ output_header();
+ first = false;
+ }
+ output_devices(devfilter.get());
+ }
+
+ if (!first)
+ 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();
+}
+
+
+//-------------------------------------------------
+// output_header - print the XML DTD and open
+// the root element
+//-------------------------------------------------
+
+void info_xml_creator::output_header()
+{
+ if (m_dtd)
+ {
+ // output the DTD
+ fprintf(m_output, "<?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());
+ }
// top-level tag
fprintf(m_output, "<%s build=\"%s\" debug=\""
#ifdef MAME_DEBUG
- "yes"
+ "yes"
#else
- "no"
+ "no"
#endif
- "\" mameconfig=\"%d\">\n",
- XML_ROOT,
- util::xml::normalize_string(emulator_info::get_build_version()),
- CONFIG_VERSION
- );
-
- std::unique_ptr<device_type_set> devfilter((m_filter_devices && !nodevices) ? new device_type_set : nullptr);
+ "\" mameconfig=\"%d\">\n",
+ XML_ROOT,
+ util::xml::normalize_string(emulator_info::get_build_version()),
+ CONFIG_VERSION);
+}
- // iterate through the drivers, outputting one at a time
- while (m_drivlist.next())
- output_one(devfilter.get());
- // output devices (both devices with roms and slot devices)
- if (!nodevices)
- output_devices(devfilter.get());
+//-------------------------------------------------
+// output_header - close the root element
+//-------------------------------------------------
+void info_xml_creator::output_footer()
+{
// close the top level tag
- fprintf(m_output, "</%s>\n",XML_ROOT);
+ fprintf(m_output, "</%s>\n", XML_ROOT);
}
@@ -249,24 +381,24 @@ void info_xml_creator::output(FILE *out, bool nodevices)
// for one particular game driver
//-------------------------------------------------
-void info_xml_creator::output_one(device_type_set *devtypes)
+void info_xml_creator::output_one(driver_enumerator &drivlist, device_type_set *devtypes)
{
- // no action if not a game
- const game_driver &driver = m_drivlist.driver();
- if (driver.flags & MACHINE_NO_STANDALONE)
- return;
-
- std::shared_ptr<machine_config> const config(m_drivlist.config());
+ const game_driver &driver = drivlist.driver();
+ std::shared_ptr<machine_config> const config(drivlist.config());
device_iterator iter(config->root_device());
- // allocate input ports
+ // allocate input ports and build overall emulation status
ioport_list portlist;
std::string errors;
+ device_t::feature_type overall_unemulated(driver.type.unemulated_features());
+ device_t::feature_type overall_imperfect(driver.type.imperfect_features());
for (device_t &device : iter)
{
portlist.append(device, errors);
+ overall_unemulated |= device.type().unemulated_features();
+ overall_imperfect |= device.type().imperfect_features();
- if (devtypes && device.owner() && device.shortname() && *device.shortname())
+ if (devtypes && device.owner())
devtypes->insert(&device.type());
}
@@ -285,7 +417,8 @@ void info_xml_creator::output_one(device_type_set *devtypes)
{
if (field.type() == IPT_KEYBOARD)
{
- if (!new_kbd) new_kbd = true;
+ if (!new_kbd)
+ new_kbd = true;
field.set_player(field.player() + kbd_offset);
}
else
@@ -299,38 +432,35 @@ void info_xml_creator::output_one(device_type_set *devtypes)
}
// print the header and the machine name
- fprintf(m_output, "\t<%s",XML_TOP);
- fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(driver.name));
+ fprintf(m_output, "\t<%s name=\"%s\"", XML_TOP, util::xml::normalize_string(driver.name));
// strip away any path information from the source_file and output it
- const char *start = strrchr(driver.source_file, '/');
+ const char *start = strrchr(driver.type.source(), '/');
if (!start)
- start = strrchr(driver.source_file, '\\');
- start = start ? (start + 1) : driver.source_file;
+ start = strrchr(driver.type.source(), '\\');
+ start = start ? (start + 1) : driver.type.source();
fprintf(m_output, " sourcefile=\"%s\"", util::xml::normalize_string(start));
// append bios and runnable flags
- if (driver.flags & MACHINE_IS_BIOS_ROOT)
+ if (driver.flags & machine_flags::IS_BIOS_ROOT)
fprintf(m_output, " isbios=\"yes\"");
- if (driver.flags & MACHINE_NO_STANDALONE)
- fprintf(m_output, " runnable=\"no\"");
- if (driver.flags & MACHINE_MECHANICAL)
+ if (driver.flags & machine_flags::MECHANICAL)
fprintf(m_output, " ismechanical=\"yes\"");
// display clone information
- int clone_of = m_drivlist.find(driver.parent);
- if (clone_of != -1 && !(m_drivlist.driver(clone_of).flags & MACHINE_IS_BIOS_ROOT))
- fprintf(m_output, " cloneof=\"%s\"", util::xml::normalize_string(m_drivlist.driver(clone_of).name));
+ 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));
if (clone_of != -1)
- fprintf(m_output, " romof=\"%s\"", util::xml::normalize_string(m_drivlist.driver(clone_of).name));
+ 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());
fprintf(m_output, ">\n");
// output game description
- if (driver.description != nullptr)
- fprintf(m_output, "\t\t<description>%s</description>\n", util::xml::normalize_string(driver.description));
+ if (driver.type.fullname() != nullptr)
+ fprintf(m_output, "\t\t<description>%s</description>\n", util::xml::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))
@@ -341,26 +471,27 @@ void info_xml_creator::output_one(device_type_set *devtypes)
fprintf(m_output, "\t\t<manufacturer>%s</manufacturer>\n", util::xml::normalize_string(driver.manufacturer));
// now print various additional information
- output_bios();
- output_rom(config->root_device());
- output_device_roms();
+ 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(), &m_drivlist.driver().flags, "");
+ output_display(config->root_device(), &drivlist.driver().flags, "");
output_sound(config->root_device());
output_input(portlist);
- output_switches(portlist, "", IPT_DIPSWITCH, "dipswitch", "dipvalue");
- output_switches(portlist, "", IPT_CONFIG, "configuration", "confsetting");
+ output_switches(portlist, "", IPT_DIPSWITCH, "dipswitch", "diplocation", "dipvalue");
+ output_switches(portlist, "", IPT_CONFIG, "configuration", "conflocation", "confsetting");
output_ports(portlist);
output_adjusters(portlist);
- output_driver();
+ 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();
- output_ramoptions();
+ output_software_list(config->root_device());
+ output_ramoptions(config->root_device());
// close the topmost tag
- fprintf(m_output, "\t</%s>\n",XML_TOP);
+ fprintf(m_output, "\t</%s>\n", XML_TOP);
}
@@ -376,14 +507,22 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic
sound_interface_iterator snditer(device);
if (snditer.first() != nullptr)
has_speaker = true;
- // generate input list
+
+ // generate input list and build overall emulation status
ioport_list portlist;
std::string errors;
+ device_t::feature_type overall_unemulated(device.type().unemulated_features());
+ device_t::feature_type overall_imperfect(device.type().imperfect_features());
for (device_t &dev : device_iterator(device))
+ {
portlist.append(dev, errors);
+ overall_unemulated |= dev.type().unemulated_features();
+ overall_imperfect |= dev.type().imperfect_features();
+ }
+
// check if the device adds player inputs (other than dsw and configs) to the system
for (auto &port : portlist)
- for (ioport_field &field : port.second->fields())
+ for (ioport_field const &field : port.second->fields())
if (field.type() >= IPT_START1 && field.type() < IPT_UI_FIRST)
{
has_input = true;
@@ -391,18 +530,16 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic
}
// start to output info
- fprintf(m_output, "\t<%s", XML_TOP);
- fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(device.shortname()));
+ fprintf(m_output, "\t<%s name=\"%s\"", XML_TOP, util::xml::normalize_string(device.shortname()));
std::string src(device.source());
strreplace(src,"../", "");
- fprintf(m_output, " sourcefile=\"%s\"", util::xml::normalize_string(src.c_str()));
- fprintf(m_output, " isdevice=\"yes\"");
- fprintf(m_output, " runnable=\"no\"");
+ fprintf(m_output, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", util::xml::normalize_string(src.c_str()));
output_sampleof(device);
- fprintf(m_output, ">\n");
- fprintf(m_output, "\t\t<description>%s</description>\n", util::xml::normalize_string(device.name()));
+ fprintf(m_output, ">\n\t\t<description>%s</description>\n", util::xml::normalize_string(device.name()));
- output_rom(device);
+ output_bios(device);
+ output_rom(nullptr, device);
+ output_device_refs(device);
if (device.type().type() != typeid(samples_device)) // ignore samples_device itself
output_sample(device);
@@ -413,9 +550,10 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic
output_sound(device);
if (has_input)
output_input(portlist);
- output_switches(portlist, devtag, IPT_DIPSWITCH, "dipswitch", "dipvalue");
- output_switches(portlist, devtag, IPT_CONFIG, "configuration", "confsetting");
+ 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);
@@ -467,14 +605,14 @@ void info_xml_creator::output_devices(device_type_set const *filter)
//------------------------------------------------
-// output_device_roms - when a driver uses roms
-// included in a device set, print a reference
+// output_device_refs - when a machine uses a
+// subdevice, print a reference
//-------------------------------------------------
-void info_xml_creator::output_device_roms()
+void info_xml_creator::output_device_refs(device_t &root)
{
- for (device_t &device : device_iterator(m_drivlist.config()->root_device()))
- if (device.owner() != nullptr && device.shortname() != nullptr && device.shortname()[0] != '\0')
+ 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()));
}
@@ -502,36 +640,30 @@ void info_xml_creator::output_sampleof(device_t &device)
//-------------------------------------------------
-// output_bios - print the BIOS set for a
-// game
+// output_bios - print BIOS sets for a device
//-------------------------------------------------
-void info_xml_creator::output_bios()
+void info_xml_creator::output_bios(device_t const &device)
{
- // skip if no ROMs
- if (m_drivlist.driver().rom == nullptr)
- return;
-
- auto rom_entries = rom_build_entries(m_drivlist.driver().rom);
-
// first determine the default BIOS name
- std::string defaultname;
- for (const rom_entry &rom : rom_entries)
- if (ROMENTRY_ISDEFAULT_BIOS(&rom))
- defaultname = ROM_GETNAME(&rom);
+ char const *defaultname(nullptr);
+ for (tiny_rom_entry const *rom = device.rom_region(); rom && !ROMENTRY_ISEND(rom); ++rom)
+ {
+ if (ROMENTRY_ISDEFAULT_BIOS(rom))
+ defaultname = rom->name;
+ }
// iterate over ROM entries and look for BIOSes
- for (const rom_entry &rom : rom_entries)
- if (ROMENTRY_ISSYSTEM_BIOS(&rom))
- {
- // output extracted name and descriptions
- fprintf(m_output, "\t\t<biosset");
- fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(ROM_GETNAME(&rom)));
- fprintf(m_output, " description=\"%s\"", util::xml::normalize_string(ROM_GETHASHDATA(&rom)));
- if (defaultname == ROM_GETNAME(&rom))
- fprintf(m_output, " default=\"yes\"");
- fprintf(m_output, "/>\n");
- }
+ 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()));
+ if (defaultname && !std::strcmp(defaultname, bios.get_name()))
+ fprintf(m_output, " default=\"yes\"");
+ fprintf(m_output, "/>\n");
+ }
}
@@ -540,99 +672,130 @@ void info_xml_creator::output_bios()
// the XML output
//-------------------------------------------------
-void info_xml_creator::output_rom(device_t &device)
+void info_xml_creator::output_rom(driver_enumerator *drivlist, device_t &device)
{
- // iterate over 3 different ROM "types": BIOS, ROMs, DISKs
- for (int rom_type = 0; rom_type < 3; rom_type++)
- for (const rom_entry *region = rom_first_region(device); region != nullptr; region = rom_next_region(region))
- {
- bool is_disk = ROMREGION_ISDISKDATA(region);
-
- // disk regions only work for disks
- if ((is_disk && rom_type != 2) || (!is_disk && rom_type == 2))
- continue;
-
- // iterate through ROM entries
- for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom))
+ enum class type { BIOS, NORMAL, DISK };
+ std::map<u32, char const *> biosnames;
+ bool bios_scanned(false);
+ auto const get_biosname =
+ [&biosnames, &bios_scanned] (tiny_rom_entry const *rom) -> char const *
{
- bool is_bios = ROM_GETBIOSFLAGS(rom);
- const char *name = ROM_GETNAME(rom);
- int offset = ROM_GETOFFSET(rom);
- const char *merge_name = nullptr;
- char bios_name[100];
-
- // BIOS ROMs only apply to bioses
- if ((is_bios && rom_type != 0) || (!is_bios && rom_type == 0))
- continue;
-
- // if we have a valid ROM and we are a clone, see if we can find the parent ROM
- util::hash_collection hashes(ROM_GETHASHDATA(rom));
- if (dynamic_cast<driver_device *>(&device) &&!hashes.flag(util::hash_collection::FLAG_NO_DUMP))
- merge_name = get_merge_name(hashes);
-
- // scan for a BIOS name
- bios_name[0] = 0;
- if (!is_disk && is_bios)
+ u32 const biosflags(ROM_GETBIOSFLAGS(rom));
+ std::map<u32, char const *>::const_iterator const found(biosnames.find(biosflags));
+ if (biosnames.end() != found)
+ return found->second;
+
+ char const *result(nullptr);
+ if (!bios_scanned)
{
- // scan backwards through the ROM entries
- for (const rom_entry *brom = rom - 1; brom != device.rom_region(); brom--)
- if (ROMENTRY_ISSYSTEM_BIOS(brom))
+ for (++rom; !ROMENTRY_ISEND(rom); ++rom)
+ {
+ if (ROMENTRY_ISSYSTEM_BIOS(rom))
{
- strcpy(bios_name, ROM_GETNAME(brom));
- break;
+ u32 const biosno(ROM_GETBIOSFLAGS(rom));
+ biosnames.emplace(biosno, rom->name);
+ if (biosflags == biosno)
+ result = rom->name;
}
+ }
+ bios_scanned = true;
}
+ return result;
+ };
+ auto const rom_file_size = // FIXME: need a common way to do this without the cost of allocating rom_entry
+ [] (tiny_rom_entry const *romp) -> u32
+ {
+ u32 maxlength = 0;
- std::ostringstream output;
-
- // opening tag
- if (!is_disk)
- output << "\t\t<rom";
- else
- output << "\t\t<disk";
-
- // add name, merge, bios, and size tags */
- if (name != nullptr && name[0] != 0)
- util::stream_format(output, " name=\"%s\"", util::xml::normalize_string(name));
- if (merge_name != nullptr)
- util::stream_format(output, " merge=\"%s\"", util::xml::normalize_string(merge_name));
- if (bios_name[0] != 0)
- util::stream_format(output, " bios=\"%s\"", util::xml::normalize_string(bios_name));
- if (!is_disk)
- util::stream_format(output, " 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))
+ // loop until we run out of reloads
+ do
{
- // iterate over hash function types and print m_output their values
- output << " " << hashes.attribute_string();
+ // loop until we run out of continues/ignores */
+ u32 curlength(ROM_GETLENGTH(romp++));
+ while (ROMENTRY_ISCONTINUE(romp) || ROMENTRY_ISIGNORE(romp))
+ curlength += ROM_GETLENGTH(romp++);
+
+ // track the maximum length
+ maxlength = (std::max)(maxlength, curlength);
}
- else
- output << " status=\"nodump\"";
+ while (ROMENTRY_ISRELOAD(romp));
- // append a region name
- util::stream_format(output, " region=\"%s\"", ROMREGION_GETTAG(region));
+ return maxlength;
+ };
- // for non-disk entries, print offset
- if (!is_disk)
- util::stream_format(output, " offset=\"%x\"", offset);
+ // iterate over 3 different ROM "types": BIOS, ROMs, DISKs
+ bool const do_merge_name = drivlist && dynamic_cast<driver_device *>(&device);
+ for (type pass : { type::BIOS, type::NORMAL, type::DISK })
+ {
+ tiny_rom_entry const *region(nullptr);
+ for (tiny_rom_entry const *rom = device.rom_region(); rom && !ROMENTRY_ISEND(rom); ++rom)
+ {
+ if (ROMENTRY_ISREGION(rom))
+ region = rom;
+ else if (ROMENTRY_ISSYSTEM_BIOS(rom))
+ biosnames.emplace(ROM_GETBIOSFLAGS(rom), rom->name);
- // for disk entries, add the disk index
- else
- {
- util::stream_format(output, " index=\"%x\"", DISK_GETINDEX(rom));
- util::stream_format(output, " writable=\"%s\"", DISK_ISREADONLY(rom) ? "no" : "yes");
- }
+ if (!ROMENTRY_ISFILE(rom))
+ continue;
+
+ // only list disks on the disk pass
+ bool const is_disk = ROMREGION_ISDISKDATA(region);
+ if ((type::DISK == pass) != is_disk)
+ continue;
+
+ // BIOS ROMs only apply to bioses
+ // FIXME: disk images associated with a system BIOS will never be listed
+ u32 const biosno(ROM_GETBIOSFLAGS(rom));
+ if ((type::BIOS == pass) != bool(biosno))
+ continue;
+ char const *const bios_name((!is_disk && biosno) ? get_biosname(rom) : nullptr);
- // add optional flag
- if (ROM_ISOPTIONAL(rom))
- output << " optional=\"yes\"";
+ // 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);
- output << "/>\n";
+ // opening tag
+ fprintf(m_output, is_disk ? "\t\t<disk" : "\t\t<rom");
- fprintf(m_output, "%s", output.str().c_str());
+ // 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));
+ if (merge_name)
+ fprintf(m_output, " merge=\"%s\"", util::xml::normalize_string(merge_name));
+ if (bios_name)
+ fprintf(m_output, " bios=\"%s\"", util::xml::normalize_string(bios_name));
+ if (!is_disk)
+ fprintf(m_output, " 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
+ else
+ fprintf(m_output, " status=\"nodump\"");
+
+ // append a region name
+ fprintf(m_output, " region=\"%s\"", region->name);
+
+ if (!is_disk)
+ {
+ // for non-disk entries, print offset
+ fprintf(m_output, " 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");
}
+
+ // add optional flag
+ if (ROM_ISOPTIONAL(rom))
+ fprintf(m_output, " optional=\"yes\"");
+
+ fprintf(m_output, "/>\n");
}
+ bios_scanned = true;
+ }
}
@@ -710,7 +873,7 @@ void info_xml_creator::output_chips(device_t &device, const char *root_tag)
// displays
//-------------------------------------------------
-void info_xml_creator::output_display(device_t &device, u32 const *flags, const char *root_tag)
+void info_xml_creator::output_display(device_t &device, machine_flags::type const *flags, const char *root_tag)
{
// iterate over screens
for (const screen_device &screendev : screen_device_iterator(device))
@@ -720,21 +883,21 @@ void info_xml_creator::output_display(device_t &device, u32 const *flags, const
std::string newtag(screendev.tag()), oldtag(":");
newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
- fprintf(m_output, "\t\t<display");
- fprintf(m_output, " tag=\"%s\"", util::xml::normalize_string(newtag.c_str()));
+ fprintf(m_output, "\t\t<display tag=\"%s\"", util::xml::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;
}
// output the orientation as a string
if (flags)
{
- switch (*flags & ORIENTATION_MASK)
+ switch (*flags & machine_flags::MASK_ORIENTATION)
{
case ORIENTATION_FLIP_X:
fprintf(m_output, " rotate=\"0\" flipx=\"yes\"");
@@ -814,6 +977,31 @@ void info_xml_creator::output_sound(device_t &device)
//-------------------------------------------------
+// output_ioport_condition - print condition
+// required to use I/O port field/setting
+//-------------------------------------------------
+
+void info_xml_creator::output_ioport_condition(const ioport_condition &condition, unsigned indent)
+{
+ for (unsigned i = 0; indent > i; ++i)
+ fprintf(m_output, "\t");
+
+ char const *rel(nullptr);
+ switch (condition.condition())
+ {
+ case ioport_condition::ALWAYS: throw false;
+ case ioport_condition::EQUALS: rel = "eq"; break;
+ case ioport_condition::NOTEQUALS: rel = "ne"; break;
+ case ioport_condition::GREATERTHAN: rel = "gt"; break;
+ case ioport_condition::NOTGREATERTHAN: rel = "le"; break;
+ case ioport_condition::LESSTHAN: rel = "lt"; break;
+ 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());
+}
+
+//-------------------------------------------------
// output_input - print a summary of a game's
// input
//-------------------------------------------------
@@ -905,272 +1093,272 @@ void info_xml_creator::output_input(const ioport_list &portlist)
// switch off of the type
switch (field.type())
{
- // map joysticks
- case IPT_JOYSTICK_UP:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_UP;
- break;
- case IPT_JOYSTICK_DOWN:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_DOWN;
- break;
- case IPT_JOYSTICK_LEFT:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_LEFT;
- break;
- case IPT_JOYSTICK_RIGHT:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_RIGHT;
- break;
+ // map joysticks
+ case IPT_JOYSTICK_UP:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_UP;
+ break;
+ case IPT_JOYSTICK_DOWN:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_DOWN;
+ break;
+ case IPT_JOYSTICK_LEFT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_LEFT;
+ break;
+ case IPT_JOYSTICK_RIGHT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[0] |= DIR_RIGHT;
+ break;
- case IPT_JOYSTICKLEFT_UP:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_UP;
- break;
- case IPT_JOYSTICKLEFT_DOWN:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_DOWN;
- break;
- case IPT_JOYSTICKLEFT_LEFT:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_LEFT;
- break;
- case IPT_JOYSTICKLEFT_RIGHT:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_RIGHT;
- break;
+ case IPT_JOYSTICKLEFT_UP:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_UP;
+ break;
+ case IPT_JOYSTICKLEFT_DOWN:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_DOWN;
+ break;
+ case IPT_JOYSTICKLEFT_LEFT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_LEFT;
+ break;
+ case IPT_JOYSTICKLEFT_RIGHT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[1] |= DIR_RIGHT;
+ break;
- case IPT_JOYSTICKRIGHT_UP:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_UP;
- break;
- case IPT_JOYSTICKRIGHT_DOWN:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_DOWN;
- break;
- case IPT_JOYSTICKRIGHT_LEFT:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_LEFT;
- break;
- case IPT_JOYSTICKRIGHT_RIGHT:
- ctrl_type = CTRL_DIGITAL_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
- control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_RIGHT;
- break;
+ case IPT_JOYSTICKRIGHT_UP:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_UP;
+ break;
+ case IPT_JOYSTICKRIGHT_DOWN:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_DOWN;
+ break;
+ case IPT_JOYSTICKRIGHT_LEFT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_LEFT;
+ break;
+ case IPT_JOYSTICKRIGHT_RIGHT:
+ ctrl_type = CTRL_DIGITAL_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "joy";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].ways = field.way();
+ control_info[field.player() * CTRL_COUNT + ctrl_type].helper[2] |= DIR_RIGHT;
+ break;
- // map analog inputs
- case IPT_AD_STICK_X:
- case IPT_AD_STICK_Y:
- case IPT_AD_STICK_Z:
- ctrl_analog = true;
- ctrl_type = CTRL_ANALOG_JOYSTICK;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "stick";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
- break;
+ // map analog inputs
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ ctrl_analog = true;
+ ctrl_type = CTRL_ANALOG_JOYSTICK;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "stick";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
+ break;
- case IPT_PADDLE:
- case IPT_PADDLE_V:
- ctrl_analog = true;
- ctrl_type = CTRL_ANALOG_PADDLE;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "paddle";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
- break;
+ case IPT_PADDLE:
+ case IPT_PADDLE_V:
+ ctrl_analog = true;
+ ctrl_type = CTRL_ANALOG_PADDLE;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "paddle";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
+ break;
- case IPT_PEDAL:
- case IPT_PEDAL2:
- case IPT_PEDAL3:
- ctrl_analog = true;
- ctrl_type = CTRL_ANALOG_PEDAL;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "pedal";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
- break;
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ ctrl_analog = true;
+ ctrl_type = CTRL_ANALOG_PEDAL;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "pedal";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
+ break;
- case IPT_LIGHTGUN_X:
- case IPT_LIGHTGUN_Y:
- ctrl_analog = true;
- ctrl_type = CTRL_ANALOG_LIGHTGUN;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "lightgun";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
- break;
+ case IPT_LIGHTGUN_X:
+ case IPT_LIGHTGUN_Y:
+ ctrl_analog = true;
+ ctrl_type = CTRL_ANALOG_LIGHTGUN;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "lightgun";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
+ break;
- case IPT_POSITIONAL:
- case IPT_POSITIONAL_V:
- ctrl_analog = true;
- ctrl_type = CTRL_ANALOG_POSITIONAL;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "positional";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
- break;
+ case IPT_POSITIONAL:
+ case IPT_POSITIONAL_V:
+ ctrl_analog = true;
+ ctrl_type = CTRL_ANALOG_POSITIONAL;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "positional";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
+ break;
- case IPT_DIAL:
- case IPT_DIAL_V:
- ctrl_analog = true;
- ctrl_type = CTRL_ANALOG_DIAL;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "dial";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
- break;
+ case IPT_DIAL:
+ case IPT_DIAL_V:
+ ctrl_analog = true;
+ ctrl_type = CTRL_ANALOG_DIAL;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "dial";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
+ break;
- case IPT_TRACKBALL_X:
- case IPT_TRACKBALL_Y:
- ctrl_analog = true;
- ctrl_type = CTRL_ANALOG_TRACKBALL;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "trackball";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
- break;
+ case IPT_TRACKBALL_X:
+ case IPT_TRACKBALL_Y:
+ ctrl_analog = true;
+ ctrl_type = CTRL_ANALOG_TRACKBALL;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "trackball";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
+ break;
- case IPT_MOUSE_X:
- case IPT_MOUSE_Y:
- ctrl_analog = true;
- ctrl_type = CTRL_ANALOG_MOUSE;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "mouse";
+ case IPT_MOUSE_X:
+ case IPT_MOUSE_Y:
+ ctrl_analog = true;
+ ctrl_type = CTRL_ANALOG_MOUSE;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "mouse";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
+ break;
+
+ // map buttons
+ case IPT_BUTTON1:
+ case IPT_BUTTON2:
+ case IPT_BUTTON3:
+ case IPT_BUTTON4:
+ case IPT_BUTTON5:
+ case IPT_BUTTON6:
+ case IPT_BUTTON7:
+ case IPT_BUTTON8:
+ case IPT_BUTTON9:
+ case IPT_BUTTON10:
+ case IPT_BUTTON11:
+ case IPT_BUTTON12:
+ case IPT_BUTTON13:
+ case IPT_BUTTON14:
+ case IPT_BUTTON15:
+ case IPT_BUTTON16:
+ ctrl_analog = false;
+ if (control_info[field.player() * CTRL_COUNT + ctrl_type].type == nullptr)
+ {
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "only_buttons";
control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = true;
- break;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].analog = false;
+ }
+ control_info[field.player() * CTRL_COUNT + ctrl_type].maxbuttons = std::max(control_info[field.player() * CTRL_COUNT + ctrl_type].maxbuttons, field.type() - IPT_BUTTON1 + 1);
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ if (!field.optional())
+ control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
+ break;
- // map buttons
- case IPT_BUTTON1:
- case IPT_BUTTON2:
- case IPT_BUTTON3:
- case IPT_BUTTON4:
- case IPT_BUTTON5:
- case IPT_BUTTON6:
- case IPT_BUTTON7:
- case IPT_BUTTON8:
- case IPT_BUTTON9:
- case IPT_BUTTON10:
- case IPT_BUTTON11:
- case IPT_BUTTON12:
- case IPT_BUTTON13:
- case IPT_BUTTON14:
- case IPT_BUTTON15:
- case IPT_BUTTON16:
- ctrl_analog = false;
- if (control_info[field.player() * CTRL_COUNT + ctrl_type].type == nullptr)
- {
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "only_buttons";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].analog = false;
- }
- control_info[field.player() * CTRL_COUNT + ctrl_type].maxbuttons = std::max(control_info[field.player() * CTRL_COUNT + ctrl_type].maxbuttons, field.type() - IPT_BUTTON1 + 1);
+ // track maximum coin index
+ case IPT_COIN1:
+ case IPT_COIN2:
+ case IPT_COIN3:
+ case IPT_COIN4:
+ case IPT_COIN5:
+ case IPT_COIN6:
+ case IPT_COIN7:
+ case IPT_COIN8:
+ case IPT_COIN9:
+ case IPT_COIN10:
+ case IPT_COIN11:
+ case IPT_COIN12:
+ ncoin = std::max(ncoin, field.type() - IPT_COIN1 + 1);
+ break;
+
+ // track presence of keypads and keyboards
+ case IPT_KEYPAD:
+ ctrl_type = CTRL_DIGITAL_KEYPAD;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "keypad";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ if (!field.optional())
+ control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
+ break;
+
+ case IPT_KEYBOARD:
+ ctrl_type = CTRL_DIGITAL_KEYBOARD;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "keyboard";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
+ if (!field.optional())
+ control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
+ break;
+
+ // additional types
+ case IPT_SERVICE:
+ service = true;
+ break;
+
+ case IPT_TILT:
+ tilt = true;
+ break;
+
+ default:
+ if (field.type() > IPT_MAHJONG_FIRST && field.type() < IPT_MAHJONG_LAST)
+ {
+ ctrl_type = CTRL_DIGITAL_MAHJONG;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "mahjong";
+ control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
if (!field.optional())
control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
- break;
-
- // track maximum coin index
- case IPT_COIN1:
- case IPT_COIN2:
- case IPT_COIN3:
- case IPT_COIN4:
- case IPT_COIN5:
- case IPT_COIN6:
- case IPT_COIN7:
- case IPT_COIN8:
- case IPT_COIN9:
- case IPT_COIN10:
- case IPT_COIN11:
- case IPT_COIN12:
- ncoin = std::max(ncoin, field.type() - IPT_COIN1 + 1);
- break;
-
- // track presence of keypads and keyboards
- case IPT_KEYPAD:
- ctrl_type = CTRL_DIGITAL_KEYPAD;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "keypad";
+ }
+ else if (field.type() > IPT_HANAFUDA_FIRST && field.type() < IPT_HANAFUDA_LAST)
+ {
+ ctrl_type = CTRL_DIGITAL_HANAFUDA;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "hanafuda";
control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
if (!field.optional())
control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
- break;
-
- case IPT_KEYBOARD:
- ctrl_type = CTRL_DIGITAL_KEYBOARD;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "keyboard";
+ }
+ else if (field.type() > IPT_GAMBLING_FIRST && field.type() < IPT_GAMBLING_LAST)
+ {
+ ctrl_type = CTRL_DIGITAL_GAMBLING;
+ control_info[field.player() * CTRL_COUNT + ctrl_type].type = "gambling";
control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
if (!field.optional())
control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
- break;
-
- // additional types
- case IPT_SERVICE:
- service = true;
- break;
-
- case IPT_TILT:
- tilt = true;
- break;
-
- default:
- if (field.type() > IPT_MAHJONG_FIRST && field.type() < IPT_MAHJONG_LAST)
- {
- ctrl_type = CTRL_DIGITAL_MAHJONG;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "mahjong";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
- if (!field.optional())
- control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
- }
- else if (field.type() > IPT_HANAFUDA_FIRST && field.type() < IPT_HANAFUDA_LAST)
- {
- ctrl_type = CTRL_DIGITAL_HANAFUDA;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "hanafuda";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
- if (!field.optional())
- control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
- }
- else if (field.type() > IPT_GAMBLING_FIRST && field.type() < IPT_GAMBLING_LAST)
- {
- ctrl_type = CTRL_DIGITAL_GAMBLING;
- control_info[field.player() * CTRL_COUNT + ctrl_type].type = "gambling";
- control_info[field.player() * CTRL_COUNT + ctrl_type].player = field.player() + 1;
- control_info[field.player() * CTRL_COUNT + ctrl_type].nbuttons++;
- if (!field.optional())
- control_info[field.player() * CTRL_COUNT + ctrl_type].reqbuttons++;
- }
- break;
+ }
+ break;
}
if (ctrl_analog)
@@ -1239,10 +1427,7 @@ void info_xml_creator::output_input(const ioport_list &portlist)
fprintf(m_output, " reqbuttons=\"%d\"", elem.reqbuttons);
}
if (elem.min != 0 || elem.max != 0)
- {
- fprintf(m_output, " minimum=\"%d\"", elem.min);
- fprintf(m_output, " maximum=\"%d\"", elem.max);
- }
+ fprintf(m_output, " minimum=\"%d\" maximum=\"%d\"", elem.min, elem.max);
if (elem.sensitivity != 0)
fprintf(m_output, " sensitivity=\"%d\"", elem.sensitivity);
if (elem.keydelta != 0)
@@ -1315,33 +1500,52 @@ 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 *innertag)
+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)
{
// iterate looking for DIP switches
for (auto &port : portlist)
- for (ioport_field &field : port.second->fields())
+ for (ioport_field const &field : port.second->fields())
if (field.type() == type)
{
- std::ostringstream output;
-
std::string newtag(port.second->tag()), oldtag(":");
newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
// output the switch name information
- std::string normalized_field_name(util::xml::normalize_string(field.name()));
- std::string normalized_newtag(util::xml::normalize_string(newtag.c_str()));
- util::stream_format(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(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());
+ if (!field.condition().none())
+ output_ioport_condition(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());
+ if (diploc.inverted())
+ fprintf(m_output, " inverted=\"yes\"");
+ fprintf(m_output, "/>\n");
+ }
// loop over settings
- for (ioport_setting &setting : field.settings())
+ for (ioport_setting const &setting : field.settings())
{
- util::stream_format(output,"\t\t\t<%s name=\"%s\" value=\"%u\"%s/>\n", innertag, util::xml::normalize_string(setting.name()), setting.value(), setting.value() == field.defvalue() ? " default=\"yes\"" : "");
+ fprintf(m_output, "\t\t\t<%s name=\"%s\" value=\"%u\"", innertag, util::xml::normalize_string(setting.name()), setting.value());
+ if (setting.value() == field.defvalue())
+ fprintf(m_output, " default=\"yes\"");
+ if (setting.condition().none())
+ {
+ fprintf(m_output, "/>\n");
+ }
+ else
+ {
+ fprintf(m_output, ">\n");
+ output_ioport_condition(setting.condition(), 4);
+ fprintf(m_output, "\t\t\t</%s>\n", innertag);
+ }
}
// terminate the switch entry
- util::stream_format(output,"\t\t</%s>\n", outertag);
-
- fprintf(m_output, "%s", output.str().c_str());
+ fprintf(m_output, "\t\t</%s>\n", outertag);
}
}
@@ -1355,12 +1559,11 @@ void info_xml_creator::output_ports(const ioport_list &portlist)
for (auto &port : portlist)
{
fprintf(m_output,"\t\t<port tag=\"%s\">\n", util::xml::normalize_string(port.second->tag()));
- for (ioport_field &field : port.second->fields())
+ for (ioport_field const &field : port.second->fields())
{
- if(field.is_analog())
+ if (field.is_analog())
fprintf(m_output,"\t\t\t<analog mask=\"%u\"/>\n", field.mask());
}
- // close element
fprintf(m_output,"\t\t</port>\n");
}
@@ -1375,9 +1578,11 @@ void info_xml_creator::output_adjusters(const ioport_list &portlist)
{
// iterate looking for Adjusters
for (auto &port : portlist)
- for (ioport_field &field : port.second->fields())
+ 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());
+ }
}
@@ -1385,57 +1590,40 @@ void info_xml_creator::output_adjusters(const ioport_list &portlist)
// output_driver - print driver status
//-------------------------------------------------
-void info_xml_creator::output_driver()
+void info_xml_creator::output_driver(game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect)
{
fprintf(m_output, "\t\t<driver");
- /* The status entry is an hint for frontend authors */
- /* to select working and not working games without */
- /* the need to know all the other status entries. */
- /* Games marked as status=good are perfectly emulated, games */
- /* marked as status=imperfect are emulated with only */
- /* some minor issues, games marked as status=preliminary */
- /* don't work or have major emulation problems. */
-
- u32 const flags = m_drivlist.driver().flags;
- if (flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_NO_SOUND | MACHINE_WRONG_COLORS | MACHINE_MECHANICAL))
+ /*
+ The status entry is an hint for frontend authors to select working
+ and not working games without the need to know all the other status
+ entries. Games marked as status=good are perfectly emulated, games
+ marked as status=imperfect are emulated with only some minor issues,
+ games marked as status=preliminary don't work or have major
+ emulation problems.
+ */
+
+ u32 const flags = driver.flags;
+ bool const machine_preliminary(flags & (machine_flags::NOT_WORKING | machine_flags::MECHANICAL));
+ bool const unemulated_preliminary(unemulated & (device_t::feature::PALETTE | device_t::feature::GRAPHICS | device_t::feature::SOUND | device_t::feature::KEYBOARD));
+ bool const imperfect_preliminary((unemulated | imperfect) & device_t::feature::PROTECTION);
+
+ if (machine_preliminary || unemulated_preliminary || imperfect_preliminary)
fprintf(m_output, " status=\"preliminary\"");
- else if (flags & (MACHINE_IMPERFECT_COLORS | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS))
+ else if (imperfect)
fprintf(m_output, " status=\"imperfect\"");
else
fprintf(m_output, " status=\"good\"");
- if (flags & MACHINE_NOT_WORKING)
+ if (flags & machine_flags::NOT_WORKING)
fprintf(m_output, " emulation=\"preliminary\"");
else
fprintf(m_output, " emulation=\"good\"");
- if (flags & MACHINE_WRONG_COLORS)
- fprintf(m_output, " color=\"preliminary\"");
- else if (flags & MACHINE_IMPERFECT_COLORS)
- fprintf(m_output, " color=\"imperfect\"");
- else
- fprintf(m_output, " color=\"good\"");
-
- if (flags & MACHINE_NO_SOUND)
- fprintf(m_output, " sound=\"preliminary\"");
- else if (flags & MACHINE_IMPERFECT_SOUND)
- fprintf(m_output, " sound=\"imperfect\"");
- else
- fprintf(m_output, " sound=\"good\"");
-
- if (flags & MACHINE_IMPERFECT_GRAPHICS)
- fprintf(m_output, " graphic=\"imperfect\"");
- else
- fprintf(m_output, " graphic=\"good\"");
-
- if (flags & MACHINE_NO_COCKTAIL)
+ if (flags & machine_flags::NO_COCKTAIL)
fprintf(m_output, " cocktail=\"preliminary\"");
- if (flags & MACHINE_UNEMULATED_PROTECTION)
- fprintf(m_output, " protection=\"preliminary\"");
-
- if (flags & MACHINE_SUPPORTS_SAVE)
+ if (flags & machine_flags::SUPPORTS_SAVE)
fprintf(m_output, " savestate=\"supported\"");
else
fprintf(m_output, " savestate=\"unsupported\"");
@@ -1445,6 +1633,54 @@ void info_xml_creator::output_driver()
//-------------------------------------------------
+// output_features - print emulation features of
+//
+//-------------------------------------------------
+
+void info_xml_creator::output_features(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" },
+ { device_t::feature::PALETTE, "palette" },
+ { device_t::feature::GRAPHICS, "graphics" },
+ { device_t::feature::SOUND, "sound" },
+ { device_t::feature::CONTROLS, "controls" },
+ { device_t::feature::KEYBOARD, "keyboard" },
+ { device_t::feature::MOUSE, "mouse" },
+ { device_t::feature::MICROPHONE, "microphone" },
+ { device_t::feature::CAMERA, "camera" },
+ { device_t::feature::DISK, "disk" },
+ { device_t::feature::PRINTER, "printer" },
+ { device_t::feature::LAN, "lan" },
+ { device_t::feature::WAN, "wan" },
+ { device_t::feature::TIMING, "timing" } };
+
+ device_t::feature_type const flags(type.unemulated_features() | type.imperfect_features() | unemulated | imperfect);
+ for (auto const &feature : features)
+ {
+ if (flags & feature.first)
+ {
+ fprintf(m_output, "\t\t<feature type=\"%s\"", feature.second);
+ if (type.unemulated_features() & feature.first)
+ {
+ fprintf(m_output, " status=\"unemulated\"");
+ }
+ else
+ {
+ if (type.imperfect_features() & feature.first)
+ fprintf(m_output, " status=\"imperfect\"");
+ if (unemulated & feature.first)
+ fprintf(m_output, " overall=\"unemulated\"");
+ else if ((~type.imperfect_features() & imperfect) & feature.first)
+ fprintf(m_output, " overall=\"imperfect\"");
+ }
+ fprintf(m_output, "/>\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
// output_images - prints m_output all info on
// image devices
//-------------------------------------------------
@@ -1495,9 +1731,7 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag)
char *ext = strtok((char *)extensions.c_str(), ",");
while (ext != nullptr)
{
- fprintf(m_output, "\t\t\t<extension");
- fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(ext));
- fprintf(m_output, "/>\n");
+ fprintf(m_output, "\t\t\t<extension name=\"%s\"/>\n", util::xml::normalize_string(ext));
ext = strtok(nullptr, ",");
}
}
@@ -1508,12 +1742,12 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag)
//-------------------------------------------------
-// output_images - prints all info about slots
+// 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)
{
- for (const device_slot_interface &slot : slot_interface_iterator(device))
+ for (device_slot_interface &slot : slot_interface_iterator(device))
{
// shall we list fixed slots as non-configurable?
bool const listed(!slot.fixed() && strcmp(slot.device().tag(), device.tag()));
@@ -1527,33 +1761,27 @@ void info_xml_creator::output_slots(machine_config &config, device_t &device, co
if (listed)
fprintf(m_output, "\t\t<slot name=\"%s\">\n", util::xml::normalize_string(newtag.c_str()));
- /*
- if (listed && slot.slot_interface()[0])
- fprintf(m_output, " interface=\"%s\"", util::xml::normalize_string(slot.slot_interface()));
- */
-
for (auto &option : slot.option_list())
{
if (devtypes || (listed && option.second->selectable()))
{
- device_t *const dev = config.device_add(&device, "_dummy", option.second->devtype(), 0);
+ device_t *const dev = config.device_add(&slot.device(), "_dummy", option.second->devtype(), option.second->clock());
if (!dev->configured())
dev->config_complete();
if (devtypes)
- for (device_t &device : device_iterator(*dev)) devtypes->insert(&device.type());
+ for (device_t &subdevice : device_iterator(*dev)) devtypes->insert(&subdevice.type());
if (listed && option.second->selectable())
{
- fprintf(m_output, "\t\t\t<slotoption");
- fprintf(m_output, " name=\"%s\"", util::xml::normalize_string(option.second->name()));
+ 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()));
if (slot.default_option() != nullptr && strcmp(slot.default_option(), option.second->name())==0)
fprintf(m_output, " default=\"yes\"");
fprintf(m_output, "/>\n");
}
- config.device_remove(&device, "_dummy");
+ config.device_remove(&slot.device(), "_dummy");
}
}
@@ -1569,14 +1797,13 @@ 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()
+void info_xml_creator::output_software_list(device_t &root)
{
- for (const software_list_device &swlist : software_list_device_iterator(m_drivlist.config()->root_device()))
+ for (const software_list_device &swlist : software_list_device_iterator(root))
{
- fprintf(m_output, "\t\t<softwarelist name=\"%s\" ", swlist.list_name().c_str());
- fprintf(m_output, "status=\"%s\" ", (swlist.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible");
+ 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");
if (swlist.filter())
- fprintf(m_output, "filter=\"%s\" ", swlist.filter());
+ fprintf(m_output, " filter=\"%s\"", util::xml::normalize_string(swlist.filter()));
fprintf(m_output, "/>\n");
}
}
@@ -1588,23 +1815,16 @@ void info_xml_creator::output_software_list()
// options for this system
//-------------------------------------------------
-void info_xml_creator::output_ramoptions()
+void info_xml_creator::output_ramoptions(device_t &root)
{
- for (const ram_device &ram : ram_device_iterator(m_drivlist.config()->root_device()))
+ for (const ram_device &ram : ram_device_iterator(root))
{
- fprintf(m_output, "\t\t<ramoption default=\"1\">%u</ramoption>\n", ram.default_size());
-
- if (ram.extra_options() != nullptr)
+ for (uint32_t option : ram.extra_options())
{
- std::string options(ram.extra_options());
- for (int start = 0, end = options.find_first_of(',');; start = end + 1, end = options.find_first_of(',', start))
- {
- std::string option;
- option.assign(options.substr(start, (end == -1) ? -1 : end - start));
- fprintf(m_output, "\t\t<ramoption>%u</ramoption>\n", ram_device::parse_string(option.c_str()));
- if (end == -1)
- break;
- }
+ if (option == ram.default_size())
+ fprintf(m_output, "\t\t<ramoption default=\"1\">%u</ramoption>\n", option);
+ else
+ fprintf(m_output, "\t\t<ramoption>%u</ramoption>\n", option);
}
}
}
@@ -1615,26 +1835,23 @@ void info_xml_creator::output_ramoptions()
// parent set
//-------------------------------------------------
-const char *info_xml_creator::get_merge_name(const util::hash_collection &romhashes)
+const char *info_xml_creator::get_merge_name(driver_enumerator &drivlist, util::hash_collection const &romhashes)
{
// walk the parent chain
- const char *merge_name = nullptr;
- for (int clone_of = m_drivlist.find(m_drivlist.driver().parent); clone_of != -1; clone_of = m_drivlist.find(m_drivlist.driver(clone_of).parent))
+ for (int clone_of = drivlist.find(drivlist.driver().parent); 0 <= clone_of; clone_of = drivlist.find(drivlist.driver(clone_of).parent))
{
// look in the parent's ROMs
- device_t *device = &m_drivlist.config(clone_of, m_lookup_options)->root_device();
- for (const rom_entry *pregion = rom_first_region(*device); pregion != nullptr; pregion = rom_next_region(pregion))
- for (const rom_entry *prom = rom_first_file(pregion); prom != nullptr; prom = rom_next_file(prom))
+ for (romload::region const &pregion : romload::entries(drivlist.driver(clone_of).rom).get_regions())
+ {
+ for (romload::file const &prom : pregion.get_files())
{
- util::hash_collection phashes(ROM_GETHASHDATA(prom));
- if (!phashes.flag(util::hash_collection::FLAG_NO_DUMP) && romhashes == phashes)
- {
- // stop when we find a match
- merge_name = ROM_GETNAME(prom);
- break;
- }
+ // stop when we find a match
+ util::hash_collection const phashes(prom.get_hashdata());
+ if (!phashes.flag(util::hash_collection::FLAG_NO_DUMP) && (romhashes == phashes))
+ return prom.get_name();
}
+ }
}
- return merge_name;
+ return nullptr;
}