filter devices when a driver pattern is supplied to -listxml

This commit is contained in:
Vas Crabb 2017-03-03 13:12:17 +11:00
parent 3ad77eae8a
commit 08443793c6
5 changed files with 84 additions and 52 deletions

View File

@ -327,7 +327,7 @@ void cli_frontend::listxml(const char *gamename)
throw emu_fatalerror(EMU_ERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
// create the XML and print it to stdout
info_xml_creator creator(drivlist);
info_xml_creator creator(drivlist, gamename && *gamename);
creator.output(stdout);
}

View File

@ -30,6 +30,7 @@
#define XML_ROOT "mame"
#define XML_TOP "machine"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@ -188,9 +189,10 @@ const char info_xml_creator::s_dtd_string[] =
// info_xml_creator - constructor
//-------------------------------------------------
info_xml_creator::info_xml_creator(driver_enumerator &drivlist)
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())
{
mame_options::remove_device_options(m_lookup_options);
@ -227,13 +229,15 @@ void info_xml_creator::output(FILE *out, bool nodevices)
CONFIG_VERSION
);
std::unique_ptr<device_type_set> devfilter((m_filter_devices && !nodevices) ? new device_type_set : nullptr);
// iterate through the drivers, outputting one at a time
while (m_drivlist.next())
output_one();
output_one(devfilter.get());
// output devices (both devices with roms and slot devices)
if (!nodevices)
output_devices();
output_devices(devfilter.get());
// close the top level tag
fprintf(m_output, "</%s>\n",XML_ROOT);
@ -245,21 +249,27 @@ void info_xml_creator::output(FILE *out, bool nodevices)
// for one particular game driver
//-------------------------------------------------
void info_xml_creator::output_one()
void info_xml_creator::output_one(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());
device_iterator iter(config->root_device());
// allocate input ports
std::shared_ptr<machine_config> config = m_drivlist.config();
ioport_list portlist;
std::string errors;
device_iterator iter(config->root_device());
for (device_t &device : iter)
{
portlist.append(device, errors);
if (devtypes && device.owner() && device.shortname() && *device.shortname())
devtypes->insert(&device.type());
}
// renumber player numbers for controller ports
int player_offset = 0;
// but treat keyboard count separately from players' number
@ -288,17 +298,16 @@ void info_xml_creator::output_one()
if (new_kbd) kbd_offset++;
}
// print the header and the game name
// 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));
// strip away any path information from the source_file and output it
const char *start = strrchr(driver.source_file, '/');
if (start == nullptr)
if (!start)
start = strrchr(driver.source_file, '\\');
if (start == nullptr)
start = driver.source_file - 1;
fprintf(m_output, " sourcefile=\"%s\"", util::xml::normalize_string(start + 1));
start = start ? (start + 1) : driver.source_file;
fprintf(m_output, " sourcefile=\"%s\"", util::xml::normalize_string(start));
// append bios and runnable flags
if (driver.flags & MACHINE_IS_BIOS_ROOT)
@ -346,7 +355,7 @@ void info_xml_creator::output_one()
output_adjusters(portlist);
output_driver();
output_images(config->root_device(), "");
output_slots(*config, config->root_device(), "");
output_slots(*config, config->root_device(), "", devtypes);
output_software_list();
output_ramoptions();
@ -408,7 +417,7 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic
output_switches(portlist, devtag, IPT_CONFIG, "configuration", "confsetting");
output_adjusters(portlist);
output_images(device, devtag);
output_slots(config, device, devtag);
output_slots(config, device, devtag, nullptr);
fprintf(m_output, "\t</%s>\n", XML_TOP);
}
@ -425,25 +434,34 @@ void info_xml_creator::output_one_device(machine_config &config, device_t &devic
// directly to a driver as device or sub-device)
//-------------------------------------------------
void info_xml_creator::output_devices()
void info_xml_creator::output_devices(device_type_set const *filter)
{
// get config for empty machine
machine_config config(GAME_NAME(___empty), m_drivlist.options());
machine_config config(GAME_NAME(___empty), m_lookup_options);
auto const action = [this, &config] (device_type type)
{
// add it at the root of the machine config
device_t *const dev = config.device_add(&config.root_device(), "_tmp", type, 0);
// notify this device and all its subdevices that they are now configured
for (device_t &device : device_iterator(*dev))
if (!device.configured())
device.config_complete();
// print details and remove it
output_one_device(config, *dev, dev->tag());
config.device_remove(&config.root_device(), "_tmp");
};
// run through devices
for (device_type type : registered_device_types)
if (filter)
{
// add it at the root of the machine config
device_t *const dev = config.device_add(&config.root_device(), "_tmp", type, 0);
// notify this device and all its subdevices that they are now configured
for (device_t &device : device_iterator(*dev))
if (!device.configured())
device.config_complete();
// print details and remove it
output_one_device(config, *dev, dev->tag());
config.device_remove(&config.root_device(), "_tmp");
for (std::add_pointer_t<device_type> type : *filter) action(*type);
}
else
{
for (device_type type : registered_device_types) action(type);
}
}
@ -1493,44 +1511,54 @@ void info_xml_creator::output_images(device_t &device, const char *root_tag)
// output_images - prints all info about slots
//-------------------------------------------------
void info_xml_creator::output_slots(machine_config &config, device_t &device, const char *root_tag)
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))
{
if (slot.fixed()) continue; // or shall we list these as non-configurable?
// shall we list fixed slots as non-configurable?
bool const listed(!slot.fixed() && strcmp(slot.device().tag(), device.tag()));
if (strcmp(slot.device().tag(), device.tag()))
if (devtypes || listed)
{
std::string newtag(slot.device().tag()), oldtag(":");
newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length());
// print m_output device type
fprintf(m_output, "\t\t<slot name=\"%s\">\n", util::xml::normalize_string(newtag.c_str()));
if (listed)
fprintf(m_output, "\t\t<slot name=\"%s\">\n", util::xml::normalize_string(newtag.c_str()));
/*
if (slot.slot_interface()[0])
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 (option.second->selectable())
if (devtypes || (listed && option.second->selectable()))
{
device_t *const dev = config.device_add(&device, "_dummy", option.second->devtype(), 0);
if (!dev->configured())
dev->config_complete();
fprintf(m_output, "\t\t\t<slotoption");
fprintf(m_output, " 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");
if (devtypes)
for (device_t &device : device_iterator(*dev)) devtypes->insert(&device.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, " 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");
}
}
fprintf(m_output, "\t\t</slot>\n");
if (listed)
fprintf(m_output, "\t\t</slot>\n");
}
}
}

View File

@ -8,13 +8,16 @@
***************************************************************************/
#ifndef __INFO_H__
#define __INFO_H__
#ifndef MAME_FRONTEND_MAME_INFO_H
#define MAME_FRONTEND_MAME_INFO_H
#pragma once
#include "emuopts.h"
#include <type_traits>
#include <unordered_set>
class driver_enumerator;
@ -28,14 +31,16 @@ class info_xml_creator
{
public:
// construction/destruction
info_xml_creator(driver_enumerator &drivlist);
info_xml_creator(driver_enumerator &drivlist, bool filter_devices);
// output
void output(FILE *out, bool nodevices = false);
private:
typedef std::unordered_set<std::add_pointer_t<device_type> > device_type_set;
// internal helper
void output_one();
void output_one(device_type_set *devtypes);
void output_sampleof(device_t &device);
void output_bios();
void output_rom(device_t &device);
@ -50,22 +55,23 @@ private:
void output_adjusters(const ioport_list &portlist);
void output_driver();
void output_images(device_t &device, const char *root_tag);
void output_slots(machine_config &config, device_t &device, const char *root_tag);
void output_slots(machine_config &config, device_t &device, const char *root_tag, device_type_set *devtypes);
void output_software_list();
void output_ramoptions();
void output_one_device(machine_config &config, device_t &device, const char *devtag);
void output_devices();
void output_devices(device_type_set const *filter);
const char *get_merge_name(const util::hash_collection &romhashes);
// internal state
FILE * m_output;
driver_enumerator & m_drivlist;
bool m_filter_devices;
emu_options m_lookup_options;
static const char s_dtd_string[];
};
#endif /* __INFO_H__ */
#endif // MAME_FRONTEND_MAME_INFO_H

View File

@ -185,9 +185,7 @@ void mame_options::remove_device_options(emu_options &options)
bool mame_options::parse_slot_devices(emu_options &options, std::function<void(emu_options &options, const std::string &)> value_specifier)
{
// keep adding slot options until we stop seeing new stuff
while (add_slot_options(options, value_specifier))
{
}
while (add_slot_options(options, value_specifier)) { }
// add device options
add_device_options(options, value_specifier);

View File

@ -603,7 +603,7 @@ void menu_export::handle()
for (auto & elem : m_list)
drvlist.include(driver_list::find(*elem));
info_xml_creator creator(drvlist);
info_xml_creator creator(drvlist, true);
creator.output(pfile, ((uintptr_t)menu_event->itemref == 1) ? false : true);
fclose(pfile);
machine().popmessage(_("%s.xml saved under ui folder."), filename.c_str());