summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/info.c
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2011-04-13 20:31:00 +0000
committer Aaron Giles <aaron@aarongiles.com>2011-04-13 20:31:00 +0000
commit00d745ca7752d2f96e842a7f23e157c0d2c40bdf (patch)
tree9b6a3dcda7d0ff05b098fe0823fe4d09f6d0e6b4 /src/emu/info.c
parentf99e1a5da63f996cd07fae98d42c2e5ff389adef (diff)
(Big tangle of changes that all happened as I was looking into the ROM
loader rewrite, which is still in progress....) Replaced mamedriv.c with a new driver list mechanism that is generated by the build tools. The emulator core now expects the presence of a file called src/$(TARGET)/$(SUBTARGET).lst which is just a raw list of driver names, one per line. C and C++ comments are still permitted. This file is parsed by a new build tool makelist which extracts the driver names, sorts them, and generates a file called drivlist.c, which is consumed by the core. [Aaron Giles] Added new osdcore function osd_malloc_array() which is identical to osd_malloc() but obviously hints that the underlying allocation is for an array. Updated all callers to use the appropriate form. Modified the Windows allocator to only use guard pages for array-style allocations, allowing us to enable them once again in debug builds. [Aaron Giles] Created new static class driver_list to wrap accesses to the list of available drivers. Improved speed of driver lookups by relying on the presorting done by makelist. [Aaron Giles] Created helper class driver_enumerator as a helper for iterating through the list of drivers. This class supports basic filtering and iteration, and also serves as a temporary cache of machine_configs. [Aaron Giles] Created cli_frontend object to wrap all the CLI handling code in clifront.c. Updated/simplified all the code to take advantage of the driver_enumerator. [Aaron Giles] Created media_auditor object to wrap all the auditing functions in audit.c. Updated all users to the new interface. Note that the new auditing mechanism is slightly out of sync with the romload code in terms of finding ROMs owned by devices, so it may mis-report some issues until the new ROM loading code is in. [Aaron Giles] Added concept of a per-device searchpath. For most devices, their searchpath is just the short name of the device. For driver_devices, the searchpath is driver[;parent[;bios]]. This searchpath will eventually be used by the rom loader to find ROMs. For now it is used by the media auditor only. [Aaron Giles] Created info_xml_creator object to wrap all the info generation functions in info.c. Converted the file to C++ and cleaned up the input processing code. [Aaron Giles] (not for whatsnew ... Known issues: auditing of CHDs appears busted, and debug builds report unfreed memory if you use the built-in game picker)
Diffstat (limited to 'src/emu/info.c')
-rw-r--r--src/emu/info.c1862
1 files changed, 875 insertions, 987 deletions
diff --git a/src/emu/info.c b/src/emu/info.c
index d0e39604249..7ee5c261500 100644
--- a/src/emu/info.c
+++ b/src/emu/info.c
@@ -4,8 +4,36 @@
Dumps the MAME internal data as an XML file.
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
@@ -19,7 +47,8 @@
#include <ctype.h>
-/* MESS/MAME configuration */
+
+// MAME vs MESS configuration
#ifdef MESS
#define XML_ROOT "mess"
#define XML_TOP "machine"
@@ -30,522 +59,375 @@
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-class parent_info
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// DTD string describing the data
+const char info_xml_creator::s_dtd_string[] =
+"<!DOCTYPE " XML_ROOT " [\n"
+"<!ELEMENT " XML_ROOT " (" XML_TOP "+)>\n"
+"\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*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, category*, adjuster*, driver?, device*, 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"
+"\t\t<!ATTLIST " XML_TOP " ismechanical (yes|no) \"no\">\n"
+"\t\t<!ATTLIST " XML_TOP " runnable (yes|no) \"yes\">\n"
+"\t\t<!ATTLIST " XML_TOP " cloneof CDATA #IMPLIED>\n"
+"\t\t<!ATTLIST " XML_TOP " romof CDATA #IMPLIED>\n"
+"\t\t<!ATTLIST " XML_TOP " sampleof CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT description (#PCDATA)>\n"
+"\t\t<!ELEMENT year (#PCDATA)>\n"
+"\t\t<!ELEMENT manufacturer (#PCDATA)>\n"
+"\t\t<!ELEMENT biosset EMPTY>\n"
+"\t\t\t<!ATTLIST biosset name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST biosset description CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST biosset default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT rom EMPTY>\n"
+"\t\t\t<!ATTLIST rom name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST rom bios CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom size CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST rom crc CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom md5 CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom sha1 CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom merge CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom region CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom offset CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST rom status (baddump|nodump|good) \"good\">\n"
+"\t\t\t<!ATTLIST rom optional (yes|no) \"no\">\n"
+"\t\t<!ELEMENT disk EMPTY>\n"
+"\t\t\t<!ATTLIST disk name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST disk md5 CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk sha1 CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk merge CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk region CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk index CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST disk status (baddump|nodump|good) \"good\">\n"
+"\t\t\t<!ATTLIST disk optional (yes|no) \"no\">\n"
+"\t\t<!ELEMENT sample EMPTY>\n"
+"\t\t\t<!ATTLIST sample name CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT chip EMPTY>\n"
+"\t\t\t<!ATTLIST chip name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST chip tag CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST chip type (cpu|audio) #REQUIRED>\n"
+"\t\t\t<!ATTLIST chip clock CDATA #IMPLIED>\n"
+"\t\t<!ELEMENT display EMPTY>\n"
+"\t\t\t<!ATTLIST display type (raster|vector|lcd|unknown) #REQUIRED>\n"
+"\t\t\t<!ATTLIST display rotate (0|90|180|270) #REQUIRED>\n"
+"\t\t\t<!ATTLIST display flipx (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST display width CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display height CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display refresh CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST display pixclock CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display htotal CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display hbend CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display hbstart CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display vtotal CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST display vbend CDATA #IMPLIED>\n"
+"\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<!ELEMENT input (control*)>\n"
+"\t\t\t<!ATTLIST input service (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST input tilt (yes|no) \"no\">\n"
+"\t\t\t<!ATTLIST input players CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST input buttons CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST input coins CDATA #IMPLIED>\n"
+"\t\t\t<!ELEMENT control EMPTY>\n"
+"\t\t\t\t<!ATTLIST control type CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST control minimum CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control maximum CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control sensitivity CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control keydelta CDATA #IMPLIED>\n"
+"\t\t\t\t<!ATTLIST control reverse (yes|no) \"no\">\n"
+"\t\t<!ELEMENT dipswitch (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\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\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\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"
+"\t\t<!ELEMENT category (item*)>\n"
+"\t\t\t<!ATTLIST category name CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT item EMPTY>\n"
+"\t\t\t\t<!ATTLIST item name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST item default (yes|no) \"no\">\n"
+"\t\t<!ELEMENT adjuster EMPTY>\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\t<!ATTLIST driver palettesize CDATA #REQUIRED>\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 mandatory CDATA #IMPLIED>\n"
+"\t\t\t<!ATTLIST device interface CDATA #IMPLIED>\n"
+"\t\t\t<!ELEMENT instance EMPTY>\n"
+"\t\t\t\t<!ATTLIST instance name CDATA #REQUIRED>\n"
+"\t\t\t\t<!ATTLIST instance briefname CDATA #REQUIRED>\n"
+"\t\t\t<!ELEMENT extension EMPTY>\n"
+"\t\t\t\t<!ATTLIST extension name CDATA #REQUIRED>\n"
+"\t\t<!ELEMENT softwarelist EMPTY>\n"
+"\t\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n"
+"\t\t\t<!ATTLIST softwarelist status (original|compatible) #REQUIRED>\n"
+"\t\t<!ELEMENT ramoption (#PCDATA)>\n"
+"\t\t\t<!ATTLIST ramoption default CDATA #IMPLIED>\n"
+"]>";
+
+
+
+//**************************************************************************
+// INFO XML CREATOR
+//**************************************************************************
+
+//-------------------------------------------------
+// info_xml_creator - constructor
+//-------------------------------------------------
+
+info_xml_creator::info_xml_creator(driver_enumerator &drivlist)
+ : m_output(NULL),
+ m_drivlist(drivlist)
{
-public:
- const game_driver *drv;
- machine_config mconfig;
-
- parent_info(const game_driver *drv, emu_options &options) : mconfig(*drv, options)
- {
- this->drv = drv;
- }
-};
-
+}
-/***************************************************************************
- CORE IMPLEMENTATION
-***************************************************************************/
-
-/*-------------------------------------------------
- print_game_switches - print the DIP switch
- settings for a game
--------------------------------------------------*/
+//-------------------------------------------------
+// output_mame_xml - print the XML information
+// for all known games
+//-------------------------------------------------
-static void print_game_switches(FILE *out, const game_driver *game, const ioport_list &portlist)
+void info_xml_creator::output(FILE *out)
{
- const input_port_config *port;
- const input_field_config *field;
-
- /* iterate looking for DIP switches */
- for (port = portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist; field != NULL; field = field->next)
- if (field->type == IPT_DIPSWITCH)
- {
- const input_setting_config *setting;
-
- /* output the switch name information */
- fprintf(out, "\t\t<dipswitch name=\"%s\"", xml_normalize_string(input_field_name(field)));
- fprintf(out, " tag=\"%s\"", xml_normalize_string(field->port->tag));
- fprintf(out, " mask=\"%u\"", field->mask);
- fprintf(out, ">\n");
+ m_output = out;
+
+ // output the DTD
+ fprintf(m_output, "<?xml version=\"1.0\"?>\n");
+ fprintf(m_output, "%s\n\n", s_dtd_string);
+
+ // top-level tag
+ fprintf(m_output, "<" XML_ROOT " build=\"%s\" debug=\""
+#ifdef MAME_DEBUG
+ "yes"
+#else
+ "no"
+#endif
+ "\" mameconfig=\"%d\">\n",
+ xml_normalize_string(build_version),
+ CONFIG_VERSION
+ );
- /* loop over settings */
- for (setting = field->settinglist; setting != NULL; setting = setting->next)
- {
- fprintf(out, "\t\t\t<dipvalue name=\"%s\"", xml_normalize_string(setting->name));
- fprintf(out, " value=\"%u\"", setting->value);
- if (setting->value == field->defvalue)
- fprintf(out, " default=\"yes\"");
- fprintf(out, "/>\n");
- }
+ // iterate through the drivers, outputting one at a time
+ while (m_drivlist.next())
+ output_one();
- /* terminate the switch entry */
- fprintf(out, "\t\t</dipswitch>\n");
- }
+ // close the top level tag
+ fprintf(m_output, "</" XML_ROOT ">\n");
}
-/*-------------------------------------------------
- print_game_configs - print the Configuration
- settings for a game
--------------------------------------------------*/
-static void print_game_configs(FILE *out, const game_driver *game, const ioport_list &portlist)
-{
- const input_port_config *port;
- const input_field_config *field;
+//-------------------------------------------------
+// output_one - print the XML information
+// for one particular game driver
+//-------------------------------------------------
- /* iterate looking for configurations */
- for (port = portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist; field != NULL; field = field->next)
- if (field->type == IPT_CONFIG)
- {
- const input_setting_config *setting;
+void info_xml_creator::output_one()
+{
+ // no action if not a game
+ const game_driver &driver = m_drivlist.driver();
+ if (driver.flags & GAME_NO_STANDALONE)
+ return;
- /* output the configuration name information */
- fprintf(out, "\t\t<configuration name=\"%s\"", xml_normalize_string(input_field_name(field)));
- fprintf(out, " tag=\"%s\"", xml_normalize_string(field->port->tag));
- fprintf(out, " mask=\"%u\"", field->mask);
- fprintf(out, ">\n");
+ // allocate input ports
+ machine_config &config = m_drivlist.config();
+ ioport_list portlist;
+ input_port_list_init(portlist, driver.ipt, NULL, 0, FALSE, NULL);
+ for (device_config *cfg = config.m_devicelist.first(); cfg != NULL; cfg = cfg->next())
+ if (cfg->input_ports() != NULL)
+ input_port_list_init(portlist, cfg->input_ports(), NULL, 0, FALSE, cfg);
- /* loop over settings */
- for (setting = field->settinglist; setting != NULL; setting = setting->next)
- {
- fprintf(out, "\t\t\t<confsetting name=\"%s\"", xml_normalize_string(setting->name));
- fprintf(out, " value=\"%u\"", setting->value);
- if (setting->value == field->defvalue)
- fprintf(out, " default=\"yes\"");
- fprintf(out, "/>\n");
- }
+ // print the header and the game name
+ fprintf(m_output, "\t<" XML_TOP);
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(driver.name));
- /* terminate the configuration entry */
- fprintf(out, "\t\t</configuration>\n");
- }
+ // strip away any path information from the source_file and output it
+ const char *start = strrchr(driver.source_file, '/');
+ if (start == NULL)
+ start = strrchr(driver.source_file, '\\');
+ if (start == NULL)
+ start = driver.source_file - 1;
+ fprintf(m_output, " sourcefile=\"%s\"", xml_normalize_string(start + 1));
+
+ // append bios and runnable flags
+ if (driver.flags & GAME_IS_BIOS_ROOT)
+ fprintf(m_output, " isbios=\"yes\"");
+ if (driver.flags & GAME_NO_STANDALONE)
+ fprintf(m_output, " runnable=\"no\"");
+ if (driver.flags & GAME_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 & GAME_IS_BIOS_ROOT))
+ fprintf(m_output, " cloneof=\"%s\"", xml_normalize_string(m_drivlist.driver(clone_of).name));
+ if (clone_of != -1)
+ fprintf(m_output, " romof=\"%s\"", xml_normalize_string(m_drivlist.driver(clone_of).name));
+
+ // display sample information and close the game tag
+ output_sampleof();
+ fprintf(m_output, ">\n");
+
+ // output game description
+ if (driver.description != NULL)
+ fprintf(m_output, "\t\t<description>%s</description>\n", xml_normalize_string(driver.description));
+
+ // print the year only if is a number or another allowed character (? or +)
+ if (driver.year != NULL && strspn(driver.year, "0123456789?+") == strlen(driver.year))
+ fprintf(m_output, "\t\t<year>%s</year>\n", xml_normalize_string(driver.year));
+
+ // print the manufacturer information
+ if (driver.manufacturer != NULL)
+ fprintf(m_output, "\t\t<manufacturer>%s</manufacturer>\n", xml_normalize_string(driver.manufacturer));
+
+ // now print various additional information
+ output_bios();
+ output_rom();
+ output_sample();
+ output_chips();
+ output_display();
+ output_sound();
+ output_input(portlist);
+ output_switches(portlist, IPT_DIPSWITCH, "dipswitch", "dipvalue");
+ output_switches(portlist, IPT_CONFIG, "configuration", "confsetting");
+ output_categories(portlist);
+ output_adjusters(portlist);
+ output_driver();
+ output_images();
+ output_software_list();
+ output_ramoptions();
+
+ // close the topmost tag
+ fprintf(m_output, "\t</" XML_TOP ">\n");
}
-/*-------------------------------------------------
- print_game_adjusters - print the Analog
- Adjusters for a game
--------------------------------------------------*/
-
-static void print_game_adjusters(FILE *out, const game_driver *game, const ioport_list &portlist)
-{
- const input_port_config *port;
- const input_field_config *field;
- /* iterate looking for Adjusters */
- for (port = portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist; field != NULL; field = field->next)
- if (field->type == IPT_ADJUSTER)
- {
- /* output the adjuster information */
- fprintf(out, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", xml_normalize_string(input_field_name(field)), field->defvalue);
- }
-}
+//------------------------------------------------
+// output_sampleof - print the 'sampleof'
+// attribute, if appropriate
+//-------------------------------------------------
-/*-------------------------------------------------
- print_game_input - print a summary of a game's
- input
--------------------------------------------------*/
-
-static void print_game_input(FILE *out, const game_driver *game, const ioport_list &portlist)
+void info_xml_creator::output_sampleof()
{
- /* fix me -- this needs to be cleaned up to match the core style */
-
-enum {cjoy, cdoublejoy, cAD_stick, cdial, ctrackball, cpaddle, clightgun, cpedal, ckeypad, ckeyboard, ENDCONTROLTYPES};
- int nplayer = 0;
- int nbutton = 0;
- int ncoin = 0;
- //int controlsyes = 0;
- int analogcontrol = 0;
- int i;
- const char* service = 0;
- const char* tilt = 0;
- const char* const control_types[] = {"joy", "doublejoy", "stick", "dial", "trackball", "paddle", "lightgun", "pedal", "keypad", "keyboard"};
- static struct _input_info
- {
- const char * type; /* general type of input */
- const char * Xway; /* 2, 4, or 8 way */
- int analog;
- int keyb;
- int min; /* analog minimum value */
- int max; /* analog maximum value */
- int sensitivity; /* default analog sensitivity */
- int keydelta; /* default analog keydelta */
- int reverse; /* default analog reverse setting */
- } control[ENDCONTROLTYPES];
- const input_port_config *port;
- const input_field_config *field;
-
- for (i = 0; i < ENDCONTROLTYPES; i++)
+ // iterate over sample devices
+ for (const device_config *devconfig = m_drivlist.config().m_devicelist.first(SAMPLES); devconfig != NULL; devconfig = devconfig->typenext())
{
- control[i].type = control_types[i];
- control[i].Xway = NULL;
- control[i].analog = 0;
- control[i].keyb = 0;
- control[i].min = 0;
- control[i].max = 0;
- control[i].sensitivity = 0;
- control[i].keydelta = 0;
- control[i].reverse = 0;
- }
-
- for (port = portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist; field != NULL; field = field->next)
- {
+ const char *const *samplenames = ((const samples_interface *)devconfig->static_config())->samplenames;
+ if (samplenames != NULL)
- if (nplayer < field->player + 1)
- nplayer = field->player + 1;
-
- switch (field->type)
+ // iterate over sample names
+ for (int sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
{
- case IPT_JOYSTICK_LEFT:
- case IPT_JOYSTICK_RIGHT:
-
- /* if control not defined, start it off as horizontal 2-way */
- if (control[cjoy].Xway == NULL)
- control[cjoy].Xway = "joy2way";
- else if (strcmp(control[cjoy].Xway,"joy2way") == 0)
- ;
- /* if already defined as vertical, make it 4 or 8 way */
- else if (strcmp(control[cjoy].Xway,"vjoy2way") == 0)
- {
- if (field->way == 4)
- control[cjoy].Xway = "joy4way";
- else
- control[cjoy].Xway = "joy8way";
- }
- //controlsyes = 1;
- break;
-
- case IPT_JOYSTICK_UP:
- case IPT_JOYSTICK_DOWN:
+ // only output sampleof if different from the game name
+ const char *cursampname = samplenames[sampnum];
+ if (cursampname[0] == '*' && strcmp(cursampname + 1, m_drivlist.driver().name) != 0)
+ fprintf(m_output, " sampleof=\"%s\"", xml_normalize_string(cursampname + 1));
- /* if control not defined, start it off as vertical 2-way */
- if (control[cjoy].Xway == NULL)
- control[cjoy].Xway = "vjoy2way";
- else if (strcmp(control[cjoy].Xway,"vjoy2way") == 0)
- ;
- /* if already defined as horiz, make it 4 or 8way */
- else if (strcmp(control[cjoy].Xway,"joy2way") == 0)
- {
- if (field->way == 4)
- control[cjoy].Xway = "joy4way";
- else
- control[cjoy].Xway = "joy8way";
- }
- //controlsyes = 1;
- break;
-
- case IPT_JOYSTICKRIGHT_UP:
- case IPT_JOYSTICKRIGHT_DOWN:
- case IPT_JOYSTICKLEFT_UP:
- case IPT_JOYSTICKLEFT_DOWN:
-
- /* if control not defined, start it off as vertical 2way */
- if (control[cdoublejoy].Xway == NULL)
- control[cdoublejoy].Xway = "vdoublejoy2way";
- else if (strcmp(control[cdoublejoy].Xway,"vdoublejoy2way") == 0)
- ;
- /* if already defined as horiz, make it 4 or 8 way */
- else if (strcmp(control[cdoublejoy].Xway,"doublejoy2way") == 0)
- {
- if (field->way == 4)
- control[cdoublejoy].Xway = "doublejoy4way";
- else
- control[cdoublejoy].Xway = "doublejoy8way";
- }
- //controlsyes = 1;
- break;
-
- case IPT_JOYSTICKRIGHT_LEFT:
- case IPT_JOYSTICKRIGHT_RIGHT:
- case IPT_JOYSTICKLEFT_LEFT:
- case IPT_JOYSTICKLEFT_RIGHT:
-
- /* if control not defined, start it off as horiz 2-way */
- if (control[cdoublejoy].Xway == NULL)
- control[cdoublejoy].Xway = "doublejoy2way";
- else if (strcmp(control[cdoublejoy].Xway,"doublejoy2way") == 0)
- ;
- /* if already defined as vertical, make it 4 or 8 way */
- else if (strcmp(control[cdoublejoy].Xway,"vdoublejoy2way") == 0)
- {
- if (field->way == 4)
- control[cdoublejoy].Xway = "doublejoy4way";
- else
- control[cdoublejoy].Xway = "doublejoy8way";
- }
- //controlsyes = 1;
- break;
-
- /* mark as an analog input, and get analog stats after switch */
- case IPT_PADDLE:
- analogcontrol = cpaddle;
- break;
- case IPT_DIAL:
- analogcontrol = cdial;
- break;
- case IPT_TRACKBALL_X:
- case IPT_TRACKBALL_Y:
- analogcontrol = ctrackball;
- break;
- case IPT_AD_STICK_X:
- case IPT_AD_STICK_Y:
- analogcontrol = cAD_stick;
- break;
- case IPT_LIGHTGUN_X:
- case IPT_LIGHTGUN_Y:
- analogcontrol = clightgun;
- break;
- case IPT_PEDAL:
- case IPT_PEDAL2:
- case IPT_PEDAL3:
- analogcontrol = cpedal;
- break;
-
- 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:
- nbutton = MAX(nbutton, field->type - IPT_BUTTON1 + 1);
- break;
-
- case IPT_COIN1:
- case IPT_COIN2:
- case IPT_COIN3:
- case IPT_COIN4:
- case IPT_COIN5:
- case IPT_COIN6:
- case IPT_COIN7:
- case IPT_COIN8:
- ncoin = MAX(ncoin, field->type - IPT_COIN1 + 1);
-
- case IPT_SERVICE :
- service = "yes";
- break;
-
- case IPT_TILT :
- tilt = "yes";
- break;
-
- case IPT_KEYPAD:
- control[ckeypad].keyb = 1;
- break;
-
- case IPT_KEYBOARD:
- control[ckeyboard].keyb = 1;
- break;
- }
-
- /* get the analog stats */
- if (analogcontrol)
- {
- //controlsyes = 1;
- control[analogcontrol].analog = 1;
-
- if (field->min)
- control[analogcontrol].min = field->min;
- if (field->max)
- control[analogcontrol].max = field->max;
- if (field->sensitivity)
- control[analogcontrol].sensitivity = field->sensitivity;
- if (field->delta)
- control[analogcontrol].keydelta = field->delta;
- if (field->flags & ANALOG_FLAG_REVERSE)
- control[analogcontrol].reverse = 1;
-
- analogcontrol = 0;
- }
- }
-
- fprintf(out, "\t\t<input");
- fprintf(out, " players=\"%d\"", nplayer);
- if (nbutton != 0)
- fprintf(out, " buttons=\"%d\"", nbutton);
- if (ncoin != 0)
- fprintf(out, " coins=\"%d\"", ncoin);
- if (service != NULL)
- fprintf(out, " service=\"%s\"", xml_normalize_string(service));
- if (tilt != NULL)
- fprintf(out, " tilt=\"%s\"", xml_normalize_string(tilt));
- fprintf(out, ">\n");
-
- for (i = 0; i < ENDCONTROLTYPES; i++)
- {
- if (control[i].Xway != NULL)
- fprintf(out, "\t\t\t<control type=\"%s\"/>\n", xml_normalize_string(control[i].Xway));
- if (control[i].analog)
- {
- fprintf(out, "\t\t\t<control type=\"%s\"", xml_normalize_string(control_types[i]));
- if (control[i].min || control[i].max)
- {
- fprintf(out, " minimum=\"%d\"", control[i].min);
- fprintf(out, " maximum=\"%d\"", control[i].max);
+ // must stop here, as there can only be one attribute of the same name
+ return;
}
- if (control[i].sensitivity)
- fprintf(out, " sensitivity=\"%d\"", control[i].sensitivity);
- if (control[i].keydelta)
- fprintf(out, " keydelta=\"%d\"", control[i].keydelta);
- if (control[i].reverse)
- fprintf(out, " reverse=\"yes\"");
-
- fprintf(out, "/>\n");
- }
- if (control[i].keyb)
- {
- fprintf(out, "\t\t\t<control type=\"%s\"/>\n", xml_normalize_string(control_types[i]));
- }
}
- fprintf(out, "\t\t</input>\n");
}
-/*-------------------------------------------------
- print_game_bios - print the BIOS set for a
- game
--------------------------------------------------*/
+//-------------------------------------------------
+// output_bios - print the BIOS set for a
+// game
+//-------------------------------------------------
-static void print_game_bios(FILE *out, const game_driver *game)
+void info_xml_creator::output_bios()
{
- const rom_entry *rom;
-
- /* skip if no ROMs */
- if (game->rom == NULL)
+ // skip if no ROMs
+ if (m_drivlist.driver().rom == NULL)
return;
- /* iterate over ROM entries and look for BIOSes */
- for (rom = game->rom; !ROMENTRY_ISEND(rom); rom++)
+ // iterate over ROM entries and look for BIOSes
+ for (const rom_entry *rom = m_drivlist.driver().rom; !ROMENTRY_ISEND(rom); rom++)
if (ROMENTRY_ISSYSTEM_BIOS(rom))
{
- const char *name = ROM_GETNAME(rom);
- const char *description = ROM_GETHASHDATA(rom);
-
- /* output extracted name and descriptions */
- fprintf(out, "\t\t<biosset");
- fprintf(out, " name=\"%s\"", xml_normalize_string(name));
- fprintf(out, " description=\"%s\"", xml_normalize_string(description));
+ // output extracted name and descriptions
+ fprintf(m_output, "\t\t<biosset");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom)));
+ fprintf(m_output, " description=\"%s\"", xml_normalize_string(ROM_GETHASHDATA(rom)));
if (ROM_GETBIOSFLAGS(rom) == 1)
- fprintf(out, " default=\"yes\"");
- fprintf(out, "/>\n");
+ fprintf(m_output, " default=\"yes\"");
+ fprintf(m_output, "/>\n");
}
}
-/*-------------------------------------------------
- get_merge_name - get the rom name from a
- parent set
--------------------------------------------------*/
-
-static const char *get_merge_name(const hash_collection &romhashes, int parents, const parent_info **pinfoarray)
-{
- int parent;
- const char *merge_name = NULL;
-
- for (parent = 0; parent < parents; ++parent)
- {
- const machine_config *pconfig = &pinfoarray[parent]->mconfig;
- const rom_source *psource;
- const rom_entry *pregion, *prom;
-
- /* scan the clone_of ROM for a matching ROM entry */
- for (psource = rom_first_source(*pconfig); psource != NULL; psource = rom_next_source(*psource))
- for (pregion = rom_first_region(*psource); pregion != NULL; pregion = rom_next_region(pregion))
- for (prom = rom_first_file(pregion); prom != NULL; prom = rom_next_file(prom))
- {
- hash_collection phashes(ROM_GETHASHDATA(prom));
- if (!phashes.flag(hash_collection::FLAG_NO_DUMP) && romhashes == phashes)
- {
- merge_name = ROM_GETNAME(prom);
- break;
- }
- }
- }
-
- return merge_name;
-}
+//-------------------------------------------------
+// output_rom - print the roms section of
+// the XML output
+//-------------------------------------------------
-
-/*-------------------------------------------------
- print_game_rom - print the roms section of
- the XML output
--------------------------------------------------*/
-
-static void print_game_rom(FILE *out, const game_driver *game, const machine_config &config)
+void info_xml_creator::output_rom()
{
- const game_driver *clone_of = driver_get_clone(game);
- int rom_type;
- int parents = 0;
- const parent_info *pinfoarray[4];
-
- for (; clone_of != NULL; clone_of = driver_get_clone(clone_of))
- {
- assert_always(parents < ARRAY_LENGTH(pinfoarray), "too many parents");
- pinfoarray[parents++] = global_alloc(parent_info(clone_of, config.options()));
- }
-
- /* iterate over 3 different ROM "types": BIOS, ROMs, DISKs */
- for (rom_type = 0; rom_type < 3; rom_type++)
+ // iterate over 3 different ROM "types": BIOS, ROMs, DISKs
+ for (int rom_type = 0; rom_type < 3; rom_type++)
{
- const rom_source *source;
- const rom_entry *region;
-
- /* iterate over ROM sources: first the game, then any devices */
- for (source = rom_first_source(config); source != NULL; source = rom_next_source(*source))
- for (region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
+ // iterate over ROM sources: first the game, then any devices
+ for (const rom_source *source = rom_first_source(m_drivlist.config()); source != NULL; source = rom_next_source(*source))
+ for (const rom_entry *region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
{
- int is_disk = ROMREGION_ISDISKDATA(region);
- const rom_entry *rom;
+ bool is_disk = ROMREGION_ISDISKDATA(region);
- /* disk regions only work for disks */
+ // disk regions only work for disks
if ((is_disk && rom_type != 2) || (!is_disk && rom_type == 2))
continue;
- /* iterate through ROM entries */
- for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
+ // iterate through ROM entries
+ for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
{
- int is_bios = ROM_GETBIOSFLAGS(rom);
+ bool is_bios = ROM_GETBIOSFLAGS(rom);
const char *name = ROM_GETNAME(rom);
int offset = ROM_GETOFFSET(rom);
const char *merge_name = NULL;
char bios_name[100];
- /* BIOS ROMs only apply to bioses */
+ // 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 */
+ // if we have a valid ROM and we are a clone, see if we can find the parent ROM
hash_collection hashes(ROM_GETHASHDATA(rom));
- if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && parents > 0)
- {
- merge_name = get_merge_name(hashes, parents, pinfoarray);
- }
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ merge_name = get_merge_name(hashes);
- /* scan for a BIOS name */
+ // scan for a BIOS name
bios_name[0] = 0;
if (!is_disk && is_bios)
{
- const rom_entry *brom;
-
- /* scan backwards through the ROM entries */
- for (brom = rom - 1; brom != game->rom; brom--)
+ // scan backwards through the ROM entries
+ for (const rom_entry *brom = rom - 1; brom != m_drivlist.driver().rom; brom--)
if (ROMENTRY_ISSYSTEM_BIOS(brom))
{
strcpy(bios_name, ROM_GETNAME(brom));
@@ -553,281 +435,521 @@ static void print_game_rom(FILE *out, const game_driver *game, const machine_con
}
}
- /* opening tag */
+ // opening tag
if (!is_disk)
- fprintf(out, "\t\t<rom");
+ fprintf(m_output, "\t\t<rom");
else
- fprintf(out, "\t\t<disk");
+ fprintf(m_output, "\t\t<disk");
- /* add name, merge, bios, and size tags */
+ // add name, merge, bios, and size tags */
if (name != NULL && name[0] != 0)
- fprintf(out, " name=\"%s\"", xml_normalize_string(name));
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(name));
if (merge_name != NULL)
- fprintf(out, " merge=\"%s\"", xml_normalize_string(merge_name));
+ fprintf(m_output, " merge=\"%s\"", xml_normalize_string(merge_name));
if (bios_name[0] != 0)
- fprintf(out, " bios=\"%s\"", xml_normalize_string(bios_name));
+ fprintf(m_output, " bios=\"%s\"", xml_normalize_string(bios_name));
if (!is_disk)
- fprintf(out, " size=\"%d\"", rom_file_size(rom));
+ fprintf(m_output, " size=\"%d\"", rom_file_size(rom));
- /* dump checksum information only if there is a known dump */
+ // dump checksum information only if there is a known dump
if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
{
- /* iterate over hash function types and print out their values */
+ // iterate over hash function types and print m_output their values
astring tempstr;
for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next())
- fprintf(out, " %s=\"%s\"", hash->name(), hash->string(tempstr));
+ fprintf(m_output, " %s=\"%s\"", hash->name(), hash->string(tempstr));
}
- /* append a region name */
- fprintf(out, " region=\"%s\"", ROMREGION_GETTAG(region));
+ // append a region name
+ fprintf(m_output, " region=\"%s\"", ROMREGION_GETTAG(region));
- /* add nodump/baddump flags */
+ // add nodump/baddump flags
if (hashes.flag(hash_collection::FLAG_NO_DUMP))
- fprintf(out, " status=\"nodump\"");
+ fprintf(m_output, " status=\"nodump\"");
if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
- fprintf(out, " status=\"baddump\"");
+ fprintf(m_output, " status=\"baddump\"");
- /* for non-disk entries, print offset */
+ // for non-disk entries, print offset
if (!is_disk)
- fprintf(out, " offset=\"%x\"", offset);
- /* for disk entries, add the disk index */
+ fprintf(m_output, " offset=\"%x\"", offset);
+
+ // for disk entries, add the disk index
else
- fprintf(out, " index=\"%x\"", DISK_GETINDEX(rom));
+ fprintf(m_output, " index=\"%x\"", DISK_GETINDEX(rom));
- /* add optional flag */
+ // add optional flag
if ((!is_disk && ROM_ISOPTIONAL(rom)) || (is_disk && DISK_ISOPTIONAL(rom)))
- fprintf(out, " optional=\"yes\"");
+ fprintf(m_output, " optional=\"yes\"");
- fprintf(out, "/>\n");
+ fprintf(m_output, "/>\n");
}
}
}
-
- for (; parents > 0; parents--)
- global_free(pinfoarray[parents - 1]);
-}
-
-
-/*-------------------------------------------------
- print_game_sampleof - print the 'sampleof'
- attribute, if appropriate
--------------------------------------------------*/
-
-static void print_game_sampleof(FILE *out, const game_driver *game, const machine_config &config)
-{
- const device_config_sound_interface *sound = NULL;
-
- for (bool gotone = config.m_devicelist.first(sound); gotone; gotone = sound->next(sound))
- if (sound->devconfig().type() == SAMPLES)
- {
- const char *const *samplenames = ((const samples_interface *)sound->devconfig().static_config())->samplenames;
- if (samplenames != NULL)
- {
- int sampnum;
-
- /* iterate over sample names */
- for (sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
- {
- const char *cursampname = samplenames[sampnum];
-
- /* only output sampleof if different from the game name */
- if (cursampname[0] == '*' && strcmp(cursampname + 1, game->name) != 0)
- fprintf(out, " sampleof=\"%s\"", xml_normalize_string(cursampname + 1));
-
- /* must stop here, as there can only be one attribute of the same name */
- return;
- }
- }
- }
}
-/*-------------------------------------------------
- print_game_sample - print a list of all
- samples referenced by a game_driver
--------------------------------------------------*/
+//-------------------------------------------------
+// output_sample - print a list of all
+// samples referenced by a game_driver
+//-------------------------------------------------
-static void print_game_sample(FILE *out, const game_driver *game, const machine_config &config)
+void info_xml_creator::output_sample()
{
- const device_config_sound_interface *sound = NULL;
+ // iterate over sample devices
+ for (const device_config *devconfig = m_drivlist.config().m_devicelist.first(SAMPLES); devconfig != NULL; devconfig = devconfig->typenext())
+ {
+ const char *const *samplenames = ((const samples_interface *)devconfig->static_config())->samplenames;
+ if (samplenames != NULL)
- /* iterate over sound chips looking for samples */
- for (bool gotone = config.m_devicelist.first(sound); gotone; gotone = sound->next(sound))
- if (sound->devconfig().type() == SAMPLES)
- {
- const char *const *samplenames = ((const samples_interface *)sound->devconfig().static_config())->samplenames;
- if (samplenames != NULL)
+ // iterate over sample names
+ for (int sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
{
- int sampnum;
-
- /* iterate over sample names */
- for (sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
- {
- const char *cursampname = samplenames[sampnum];
- int dupnum;
-
- /* ignore the special '*' samplename */
- if (sampnum == 0 && cursampname[0] == '*')
- continue;
+ // ignore the special '*' samplename
+ const char *cursampname = samplenames[sampnum];
+ if (sampnum == 0 && cursampname[0] == '*')
+ continue;
- /* filter out duplicates */
- for (dupnum = 0; dupnum < sampnum; dupnum++)
- if (strcmp(samplenames[dupnum], cursampname) == 0)
- break;
- if (dupnum < sampnum)
- continue;
+ // filter m_output duplicates
+ int dupnum;
+ for (dupnum = 0; dupnum < sampnum; dupnum++)
+ if (strcmp(samplenames[dupnum], cursampname) == 0)
+ break;
+ if (dupnum < sampnum)
+ continue;
- /* output the sample name */
- fprintf(out, "\t\t<sample name=\"%s\"/>\n", xml_normalize_string(cursampname));
- }
+ // output the sample name
+ fprintf(m_output, "\t\t<sample name=\"%s\"/>\n", xml_normalize_string(cursampname));
}
- }
+ }
}
/*-------------------------------------------------
- print_game_chips - print a list of CPU and
+ output_chips - print a list of CPU and
sound chips used by a game
-------------------------------------------------*/
-static void print_game_chips(FILE *out, const game_driver *game, const machine_config &config)
+void info_xml_creator::output_chips()
{
- /* iterate over CPUs */
+ // iterate over executable devices
const device_config_execute_interface *exec = NULL;
- for (bool gotone = config.m_devicelist.first(exec); gotone; gotone = exec->next(exec))
+ for (bool gotone = m_drivlist.config().m_devicelist.first(exec); gotone; gotone = exec->next(exec))
{
- fprintf(out, "\t\t<chip");
- fprintf(out, " type=\"cpu\"");
- fprintf(out, " tag=\"%s\"", xml_normalize_string(exec->devconfig().tag()));
- fprintf(out, " name=\"%s\"", xml_normalize_string(exec->devconfig().name()));
- fprintf(out, " clock=\"%d\"", exec->devconfig().clock());
- fprintf(out, "/>\n");
+ fprintf(m_output, "\t\t<chip");
+ fprintf(m_output, " type=\"cpu\"");
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(exec->devconfig().tag()));
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(exec->devconfig().name()));
+ fprintf(m_output, " clock=\"%d\"", exec->devconfig().clock());
+ fprintf(m_output, "/>\n");
}
- /* iterate over sound chips */
+ // iterate over sound devices
const device_config_sound_interface *sound = NULL;
- for (bool gotone = config.m_devicelist.first(sound); gotone; gotone = sound->next(sound))
+ for (bool gotone = m_drivlist.config().m_devicelist.first(sound); gotone; gotone = sound->next(sound))
{
- fprintf(out, "\t\t<chip");
- fprintf(out, " type=\"audio\"");
- fprintf(out, " tag=\"%s\"", xml_normalize_string(sound->devconfig().tag()));
- fprintf(out, " name=\"%s\"", xml_normalize_string(sound->devconfig().name()));
+ fprintf(m_output, "\t\t<chip");
+ fprintf(m_output, " type=\"audio\"");
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(sound->devconfig().tag()));
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(sound->devconfig().name()));
if (sound->devconfig().clock() != 0)
- fprintf(out, " clock=\"%d\"", sound->devconfig().clock());
- fprintf(out, "/>\n");
+ fprintf(m_output, " clock=\"%d\"", sound->devconfig().clock());
+ fprintf(m_output, "/>\n");
}
}
-/*-------------------------------------------------
- print_game_display - print a list of all the
- displays
--------------------------------------------------*/
+//-------------------------------------------------
+// output_display - print a list of all the
+// displays
+//-------------------------------------------------
-static void print_game_display(FILE *out, const game_driver *game, const machine_config &config)
+void info_xml_creator::output_display()
{
- const screen_device_config *devconfig;
-
- /* iterate over screens */
- for (devconfig = config.first_screen(); devconfig != NULL; devconfig = devconfig->next_screen())
+ // iterate over screens
+ for (const screen_device_config *devconfig = m_drivlist.config().first_screen(); devconfig != NULL; devconfig = devconfig->next_screen())
{
- fprintf(out, "\t\t<display");
+ fprintf(m_output, "\t\t<display");
switch (devconfig->screen_type())
{
- case SCREEN_TYPE_RASTER: fprintf(out, " type=\"raster\""); break;
- case SCREEN_TYPE_VECTOR: fprintf(out, " type=\"vector\""); break;
- case SCREEN_TYPE_LCD: fprintf(out, " type=\"lcd\""); break;
- default: fprintf(out, " type=\"unknown\""); break;
+ 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;
+ default: fprintf(m_output, " type=\"unknown\""); break;
}
- /* output the orientation as a string */
- switch (game->flags & ORIENTATION_MASK)
+ // output the orientation as a string
+ switch (m_drivlist.driver().flags & ORIENTATION_MASK)
{
case ORIENTATION_FLIP_X:
- fprintf(out, " rotate=\"0\" flipx=\"yes\"");
+ fprintf(m_output, " rotate=\"0\" flipx=\"yes\"");
break;
case ORIENTATION_FLIP_Y:
- fprintf(out, " rotate=\"180\" flipx=\"yes\"");
+ fprintf(m_output, " rotate=\"180\" flipx=\"yes\"");
break;
case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
- fprintf(out, " rotate=\"180\"");
+ fprintf(m_output, " rotate=\"180\"");
break;
case ORIENTATION_SWAP_XY:
- fprintf(out, " rotate=\"90\" flipx=\"yes\"");
+ fprintf(m_output, " rotate=\"90\" flipx=\"yes\"");
break;
case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X:
- fprintf(out, " rotate=\"90\"");
+ fprintf(m_output, " rotate=\"90\"");
break;
case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y:
- fprintf(out, " rotate=\"270\"");
+ fprintf(m_output, " rotate=\"270\"");
break;
case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
- fprintf(out, " rotate=\"270\" flipx=\"yes\"");
+ fprintf(m_output, " rotate=\"270\" flipx=\"yes\"");
break;
default:
- fprintf(out, " rotate=\"0\"");
+ fprintf(m_output, " rotate=\"0\"");
break;
}
- /* output width and height only for games that are not vector */
+ // output width and height only for games that are not vector
if (devconfig->screen_type() != SCREEN_TYPE_VECTOR)
{
const rectangle &visarea = devconfig->visible_area();
- int dx = visarea.max_x - visarea.min_x + 1;
- int dy = visarea.max_y - visarea.min_y + 1;
-
- fprintf(out, " width=\"%d\"", dx);
- fprintf(out, " height=\"%d\"", dy);
+ fprintf(m_output, " width=\"%d\"", visarea.max_x - visarea.min_x + 1);
+ fprintf(m_output, " height=\"%d\"", visarea.max_y - visarea.min_y + 1);
}
- /* output refresh rate */
- fprintf(out, " refresh=\"%f\"", ATTOSECONDS_TO_HZ(devconfig->refresh()));
+ // output refresh rate
+ fprintf(m_output, " refresh=\"%f\"", ATTOSECONDS_TO_HZ(devconfig->refresh()));
- /* output raw video parameters only for games that are not vector */
- /* and had raw parameters specified */
+ // output raw video parameters only for games that are not vector
+ // and had raw parameters specified
if (devconfig->screen_type() != SCREEN_TYPE_VECTOR && !devconfig->oldstyle_vblank_supplied())
{
int pixclock = devconfig->width() * devconfig->height() * ATTOSECONDS_TO_HZ(devconfig->refresh());
- fprintf(out, " pixclock=\"%d\"", pixclock);
- fprintf(out, " htotal=\"%d\"", devconfig->width());
- fprintf(out, " hbend=\"%d\"", devconfig->visible_area().min_x);
- fprintf(out, " hbstart=\"%d\"", devconfig->visible_area().max_x+1);
- fprintf(out, " vtotal=\"%d\"", devconfig->height());
- fprintf(out, " vbend=\"%d\"", devconfig->visible_area().min_y);
- fprintf(out, " vbstart=\"%d\"", devconfig->visible_area().max_y+1);
+ fprintf(m_output, " pixclock=\"%d\"", pixclock);
+ fprintf(m_output, " htotal=\"%d\"", devconfig->width());
+ fprintf(m_output, " hbend=\"%d\"", devconfig->visible_area().min_x);
+ fprintf(m_output, " hbstart=\"%d\"", devconfig->visible_area().max_x+1);
+ fprintf(m_output, " vtotal=\"%d\"", devconfig->height());
+ fprintf(m_output, " vbend=\"%d\"", devconfig->visible_area().min_y);
+ fprintf(m_output, " vbstart=\"%d\"", devconfig->visible_area().max_y+1);
}
- fprintf(out, " />\n");
+ fprintf(m_output, " />\n");
}
}
-/*-------------------------------------------------
- print_game_sound - print a list of all the
- displays
--------------------------------------------------*/
+//-------------------------------------------------
+// output_sound - print a list of all the
+// displays
+//------------------------------------------------
-static void print_game_sound(FILE *out, const game_driver *game, const machine_config &config)
+void info_xml_creator::output_sound()
{
- int speakers = config.m_devicelist.count(SPEAKER);
+ int speakers = m_drivlist.config().m_devicelist.count(SPEAKER);
- /* if we have no sound, zero out the speaker count */
+ // if we have no sound, zero m_output the speaker count
const device_config_sound_interface *sound = NULL;
- if (!config.m_devicelist.first(sound))
+ if (!m_drivlist.config().m_devicelist.first(sound))
speakers = 0;
- fprintf(out, "\t\t<sound channels=\"%d\"/>\n", speakers);
+ fprintf(m_output, "\t\t<sound channels=\"%d\"/>\n", speakers);
}
-/*-------------------------------------------------
- print_game_driver - print driver status
--------------------------------------------------*/
+//-------------------------------------------------
+// output_input - print a summary of a game's
+// input
+//-------------------------------------------------
-static void print_game_driver(FILE *out, const game_driver *game, const machine_config &config)
+void info_xml_creator::output_input(const ioport_list &portlist)
{
- fprintf(out, "\t\t<driver");
+ // enumerated list of control types
+ enum
+ {
+ ANALOG_TYPE_JOYSTICK,
+ ANALOG_TYPE_DIAL,
+ ANALOG_TYPE_TRACKBALL,
+ ANALOG_TYPE_PADDLE,
+ ANALOG_TYPE_LIGHTGUN,
+ ANALOG_TYPE_PEDAL,
+ ANALOG_TYPE_COUNT
+ };
+
+ // directions
+ const UINT8 DIR_LEFTRIGHT = 0x01;
+ const UINT8 DIR_UPDOWN = 0x02;
+ const UINT8 DIR_4WAY = 0x04;
+ const UINT8 DIR_DUAL = 0x08;
+
+ // initialize the list of control types
+ struct
+ {
+ const char * type; /* general type of input */
+ bool analog;
+ bool keyb;
+ INT32 min; /* analog minimum value */
+ INT32 max; /* analog maximum value */
+ INT32 sensitivity; /* default analog sensitivity */
+ INT32 keydelta; /* default analog keydelta */
+ bool reverse; /* default analog reverse setting */
+ } control_info[ANALOG_TYPE_COUNT];
+
+ memset(&control_info, 0, sizeof(control_info));
+
+ // tracking info as we iterate
+ int nplayer = 0;
+ int nbutton = 0;
+ int ncoin = 0;
+ UINT8 joytype = 0;
+ bool service = false;
+ bool tilt = false;
+ bool keypad = false;
+ bool keyboard = false;
+
+ // iterate over the ports
+ for (const input_port_config *port = portlist.first(); port != NULL; port = port->next())
+ for (const input_field_config *field = port->fieldlist; field != NULL; field = field->next)
+ {
+ int analogtype = -1;
+
+ // track the highest player number
+ if (nplayer < field->player + 1)
+ nplayer = field->player + 1;
+
+ // switch off of the type
+ switch (field->type)
+ {
+ // map which joystick directions are present
+ case IPT_JOYSTICKRIGHT_LEFT:
+ case IPT_JOYSTICKRIGHT_RIGHT:
+ case IPT_JOYSTICKLEFT_LEFT:
+ case IPT_JOYSTICKLEFT_RIGHT:
+ joytype |= DIR_DUAL;
+ // fall through...
+
+ case IPT_JOYSTICK_LEFT:
+ case IPT_JOYSTICK_RIGHT:
+ joytype |= DIR_LEFTRIGHT | ((field->way == 4) ? DIR_4WAY : 0);
+ break;
+
+ case IPT_JOYSTICKRIGHT_UP:
+ case IPT_JOYSTICKRIGHT_DOWN:
+ case IPT_JOYSTICKLEFT_UP:
+ case IPT_JOYSTICKLEFT_DOWN:
+ joytype |= DIR_DUAL;
+ // fall through...
+
+ case IPT_JOYSTICK_UP:
+ case IPT_JOYSTICK_DOWN:
+ joytype |= DIR_UPDOWN | ((field->way == 4) ? DIR_4WAY : 0);
+ break;
+
+ // mark as an analog input, and get analog stats after switch
+ case IPT_PADDLE:
+ control_info[analogtype = ANALOG_TYPE_PADDLE].type = "paddle";
+ break;
+
+ case IPT_DIAL:
+ control_info[analogtype = ANALOG_TYPE_DIAL].type = "dial";
+ analogtype = ANALOG_TYPE_DIAL;
+ break;
+
+ case IPT_TRACKBALL_X:
+ case IPT_TRACKBALL_Y:
+ control_info[analogtype = ANALOG_TYPE_TRACKBALL].type = "trackball";
+ analogtype = ANALOG_TYPE_TRACKBALL;
+ break;
+
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ control_info[analogtype = ANALOG_TYPE_JOYSTICK].type = "stick";
+ break;
+
+ case IPT_LIGHTGUN_X:
+ case IPT_LIGHTGUN_Y:
+ control_info[analogtype = ANALOG_TYPE_LIGHTGUN].type = "lightgun";
+ break;
+
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ control_info[analogtype = ANALOG_TYPE_PEDAL].type = "pedal";
+ break;
+
+ // track maximum button index
+ 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:
+ nbutton = MAX(nbutton, field->type - IPT_BUTTON1 + 1);
+ 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:
+ ncoin = MAX(ncoin, field->type - IPT_COIN1 + 1);
+ break;
+
+ // track presence of these guys
+ case IPT_KEYPAD:
+ keypad = true;
+ break;
+
+ case IPT_KEYBOARD:
+ keyboard = true;
+ break;
+
+ // additional types
+ case IPT_SERVICE:
+ service = true;
+ break;
+
+ case IPT_TILT:
+ tilt = true;
+ break;
+ }
+
+ // get the analog stats
+ if (analogtype != -1)
+ {
+ if (field->min != 0)
+ control_info[analogtype].min = field->min;
+ if (field->max != 0)
+ control_info[analogtype].max = field->max;
+ if (field->sensitivity != 0)
+ control_info[analogtype].sensitivity = field->sensitivity;
+ if (field->delta != 0)
+ control_info[analogtype].keydelta = field->delta;
+ if ((field->flags & ANALOG_FLAG_REVERSE) != 0)
+ control_info[analogtype].reverse = true;
+ }
+ }
+
+ // output the basic info
+ fprintf(m_output, "\t\t<input");
+ fprintf(m_output, " players=\"%d\"", nplayer);
+ if (nbutton != 0)
+ fprintf(m_output, " buttons=\"%d\"", nbutton);
+ if (ncoin != 0)
+ fprintf(m_output, " coins=\"%d\"", ncoin);
+ if (service)
+ fprintf(m_output, " service=\"yes\"");
+ if (tilt)
+ fprintf(m_output, " tilt=\"yes\"");
+ fprintf(m_output, ">\n");
+
+ // output the joystick types
+ if (joytype != 0)
+ {
+ const char *vertical = ((joytype & DIR_LEFTRIGHT) == 0) ? "v" : "";
+ const char *doubletype = ((joytype & DIR_DUAL) != 0) ? "doublejoy" : "joy";
+ const char *way = ((joytype & DIR_LEFTRIGHT) == 0 || (joytype & DIR_UPDOWN) == 0) ? "2way" : ((joytype & DIR_4WAY) != 0) ? "4way" : "8way";
+ fprintf(m_output, "\t\t\t<control type=\"%s%s%s\"/>\n", vertical, doubletype, way);
+ }
+
+ // output analog types
+ for (int type = 0; type < ANALOG_TYPE_COUNT; type++)
+ if (control_info[type].type != NULL)
+ {
+ fprintf(m_output, "\t\t\t<control type=\"%s\"", xml_normalize_string(control_info[type].type));
+ if (control_info[type].min != 0 || control_info[type].max != 0)
+ {
+ fprintf(m_output, " minimum=\"%d\"", control_info[type].min);
+ fprintf(m_output, " maximum=\"%d\"", control_info[type].max);
+ }
+ if (control_info[type].sensitivity != 0)
+ fprintf(m_output, " sensitivity=\"%d\"", control_info[type].sensitivity);
+ if (control_info[type].keydelta != 0)
+ fprintf(m_output, " keydelta=\"%d\"", control_info[type].keydelta);
+ if (control_info[type].reverse)
+ fprintf(m_output, " reverse=\"yes\"");
+
+ fprintf(m_output, "/>\n");
+ }
+
+ // output keypad and keyboard
+ if (keypad)
+ fprintf(m_output, "\t\t\t<control type=\"keypad\"/>\n");
+ if (keyboard)
+ fprintf(m_output, "\t\t\t<control type=\"keyboard\"/>\n");
+
+ fprintf(m_output, "\t\t</input>\n");
+}
+
+
+//-------------------------------------------------
+// output_switches - print the configurations or
+// DIP switch settings
+//-------------------------------------------------
+
+void info_xml_creator::output_switches(const ioport_list &portlist, int type, const char *outertag, const char *innertag)
+{
+ // iterate looking for DIP switches
+ for (const input_port_config *port = portlist.first(); port != NULL; port = port->next())
+ for (const input_field_config *field = port->fieldlist; field != NULL; field = field->next)
+ if (field->type == type)
+ {
+ // output the switch name information
+ fprintf(m_output, "\t\t<%s name=\"%s\"", outertag, xml_normalize_string(input_field_name(field)));
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(field->port->tag));
+ fprintf(m_output, " mask=\"%u\"", field->mask);
+ fprintf(m_output, ">\n");
+
+ // loop over settings
+ for (const input_setting_config *setting = field->settinglist; setting != NULL; setting = setting->next)
+ {
+ fprintf(m_output, "\t\t\t<%s name=\"%s\"", innertag, xml_normalize_string(setting->name));
+ fprintf(m_output, " value=\"%u\"", setting->value);
+ if (setting->value == field->defvalue)
+ fprintf(m_output, " default=\"yes\"");
+ fprintf(m_output, "/>\n");
+ }
+
+ // terminate the switch entry
+ fprintf(m_output, "\t\t</%s>\n", outertag);
+ }
+}
+
+
+//-------------------------------------------------
+// output_adjusters - print the Analog
+// Adjusters for a game
+//-------------------------------------------------
+
+void info_xml_creator::output_adjusters(const ioport_list &portlist)
+{
+ // iterate looking for Adjusters
+ for (const input_port_config *port = portlist.first(); port != NULL; port = port->next())
+ for (const input_field_config *field = port->fieldlist; field != NULL; field = field->next)
+ if (field->type == IPT_ADJUSTER)
+ fprintf(m_output, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", xml_normalize_string(input_field_name(field)), field->defvalue);
+}
+
+
+//-------------------------------------------------
+// output_driver - print driver status
+//-------------------------------------------------
+
+void info_xml_creator::output_driver()
+{
+ fprintf(m_output, "\t\t<driver");
/* The status entry is an hint for frontend authors */
/* to select working and not working games without */
@@ -837,444 +959,210 @@ static void print_game_driver(FILE *out, const game_driver *game, const machine_
/* some minor issues, games marked as status=preliminary */
/* don't work or have major emulation problems. */
- if (game->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_NO_SOUND | GAME_WRONG_COLORS))
- fprintf(out, " status=\"preliminary\"");
- else if (game->flags & (GAME_IMPERFECT_COLORS | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS))
- fprintf(out, " status=\"imperfect\"");
+ if (m_drivlist.driver().flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_NO_SOUND | GAME_WRONG_COLORS))
+ fprintf(m_output, " status=\"preliminary\"");
+ else if (m_drivlist.driver().flags & (GAME_IMPERFECT_COLORS | GAME_IMPERFECT_SOUND | GAME_IMPERFECT_GRAPHICS))
+ fprintf(m_output, " status=\"imperfect\"");
else
- fprintf(out, " status=\"good\"");
+ fprintf(m_output, " status=\"good\"");
- if (game->flags & GAME_NOT_WORKING)
- fprintf(out, " emulation=\"preliminary\"");
+ if (m_drivlist.driver().flags & GAME_NOT_WORKING)
+ fprintf(m_output, " emulation=\"preliminary\"");
else
- fprintf(out, " emulation=\"good\"");
+ fprintf(m_output, " emulation=\"good\"");
- if (game->flags & GAME_WRONG_COLORS)
- fprintf(out, " color=\"preliminary\"");
- else if (game->flags & GAME_IMPERFECT_COLORS)
- fprintf(out, " color=\"imperfect\"");
+ if (m_drivlist.driver().flags & GAME_WRONG_COLORS)
+ fprintf(m_output, " color=\"preliminary\"");
+ else if (m_drivlist.driver().flags & GAME_IMPERFECT_COLORS)
+ fprintf(m_output, " color=\"imperfect\"");
else
- fprintf(out, " color=\"good\"");
+ fprintf(m_output, " color=\"good\"");
- if (game->flags & GAME_NO_SOUND)
- fprintf(out, " sound=\"preliminary\"");
- else if (game->flags & GAME_IMPERFECT_SOUND)
- fprintf(out, " sound=\"imperfect\"");
+ if (m_drivlist.driver().flags & GAME_NO_SOUND)
+ fprintf(m_output, " sound=\"preliminary\"");
+ else if (m_drivlist.driver().flags & GAME_IMPERFECT_SOUND)
+ fprintf(m_output, " sound=\"imperfect\"");
else
- fprintf(out, " sound=\"good\"");
+ fprintf(m_output, " sound=\"good\"");
- if (game->flags & GAME_IMPERFECT_GRAPHICS)
- fprintf(out, " graphic=\"imperfect\"");
+ if (m_drivlist.driver().flags & GAME_IMPERFECT_GRAPHICS)
+ fprintf(m_output, " graphic=\"imperfect\"");
else
- fprintf(out, " graphic=\"good\"");
+ fprintf(m_output, " graphic=\"good\"");
- if (game->flags & GAME_NO_COCKTAIL)
- fprintf(out, " cocktail=\"preliminary\"");
+ if (m_drivlist.driver().flags & GAME_NO_COCKTAIL)
+ fprintf(m_output, " cocktail=\"preliminary\"");
- if (game->flags & GAME_UNEMULATED_PROTECTION)
- fprintf(out, " protection=\"preliminary\"");
+ if (m_drivlist.driver().flags & GAME_UNEMULATED_PROTECTION)
+ fprintf(m_output, " protection=\"preliminary\"");
- if (game->flags & GAME_SUPPORTS_SAVE)
- fprintf(out, " savestate=\"supported\"");
+ if (m_drivlist.driver().flags & GAME_SUPPORTS_SAVE)
+ fprintf(m_output, " savestate=\"supported\"");
else
- fprintf(out, " savestate=\"unsupported\"");
+ fprintf(m_output, " savestate=\"unsupported\"");
- fprintf(out, " palettesize=\"%d\"", config.m_total_colors);
+ fprintf(m_output, " palettesize=\"%d\"", m_drivlist.config().m_total_colors);
- fprintf(out, "/>\n");
+ fprintf(m_output, "/>\n");
}
-/*-------------------------------------------------
- print_game_categories - print the Categories
- settings for a system
--------------------------------------------------*/
-static void print_game_categories(FILE *out, const game_driver *game, const ioport_list &portlist)
-{
- const input_port_config *port;
- const input_field_config *field;
+//-------------------------------------------------
+// output_categories - print the Categories
+// settings for a system
+//-------------------------------------------------
- /* iterate looking for Categories */
- for (port = portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist; field != NULL; field = field->next)
+void info_xml_creator::output_categories(const ioport_list &portlist)
+{
+ // iterate looking for Categories
+ for (const input_port_config *port = portlist.first(); port != NULL; port = port->next())
+ for (const input_field_config *field = port->fieldlist; field != NULL; field = field->next)
if (field->type == IPT_CATEGORY)
{
- const input_setting_config *setting;
-
- /* output the category name information */
- fprintf(out, "\t\t<category name=\"%s\">\n", xml_normalize_string(input_field_name(field)));
+ // output the category name information
+ fprintf(m_output, "\t\t<category name=\"%s\">\n", xml_normalize_string(input_field_name(field)));
- /* loop over item settings */
- for (setting = field->settinglist; setting != NULL; setting = setting->next)
+ // loop over item settings
+ for (const input_setting_config *setting = field->settinglist; setting != NULL; setting = setting->next)
{
- fprintf(out, "\t\t\t<item name=\"%s\"", xml_normalize_string(setting->name));
+ fprintf(m_output, "\t\t\t<item name=\"%s\"", xml_normalize_string(setting->name));
if (setting->value == field->defvalue)
- fprintf(out, " default=\"yes\"");
- fprintf(out, "/>\n");
+ fprintf(m_output, " default=\"yes\"");
+ fprintf(m_output, "/>\n");
}
- /* terminate the category entry */
- fprintf(out, "\t\t</category>\n");
+ // terminate the category entry
+ fprintf(m_output, "\t\t</category>\n");
}
}
-/*-------------------------------------------------
- print_game_images - prints out all info on
- image devices
--------------------------------------------------*/
-static void print_game_images(FILE *out, const game_driver *game, const machine_config &config)
+//-------------------------------------------------
+// output_images - prints m_output all info on
+// image devices
+//-------------------------------------------------
+
+void info_xml_creator::output_images()
{
const device_config_image_interface *dev = NULL;
- const char *name;
- const char *shortname;
-
- for (bool gotone = config.m_devicelist.first(dev); gotone; gotone = dev->next(dev))
+ for (bool gotone = m_drivlist.config().m_devicelist.first(dev); gotone; gotone = dev->next(dev))
{
- /* print out device type */
- fprintf(out, "\t\t<device type=\"%s\"", xml_normalize_string(dev->image_type_name()));
+ // print m_output device type
+ fprintf(m_output, "\t\t<device type=\"%s\"", xml_normalize_string(dev->image_type_name()));
- /* does this device have a tag? */
+ // does this device have a tag?
if (dev->devconfig().tag())
- fprintf(out, " tag=\"%s\"", xml_normalize_string(dev->devconfig().tag()));
+ fprintf(m_output, " tag=\"%s\"", xml_normalize_string(dev->devconfig().tag()));
- /* is this device mandatory? */
+ // is this device mandatory?
if (dev->must_be_loaded())
- fprintf(out, " mandatory=\"1\"");
+ fprintf(m_output, " mandatory=\"1\"");
- if (dev->image_interface()[0] )
- fprintf(out, " interface=\"%s\"", xml_normalize_string(dev->image_interface()));
+ if (dev->image_interface()[0])
+ fprintf(m_output, " interface=\"%s\"", xml_normalize_string(dev->image_interface()));
- /* close the XML tag */
- fprintf(out, ">\n");
+ // close the XML tag
+ fprintf(m_output, ">\n");
- name = dev->instance_name();
- shortname = dev->brief_instance_name();
+ const char *name = dev->instance_name();
+ const char *shortname = dev->brief_instance_name();
- fprintf(out, "\t\t\t<instance");
- fprintf(out, " name=\"%s\"", xml_normalize_string(name));
- fprintf(out, " briefname=\"%s\"", xml_normalize_string(shortname));
- fprintf(out, "/>\n");
+ fprintf(m_output, "\t\t\t<instance");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(name));
+ fprintf(m_output, " briefname=\"%s\"", xml_normalize_string(shortname));
+ fprintf(m_output, "/>\n");
astring extensions(dev->file_extensions());
- char *ext = strtok((char*)extensions.cstr(),",");
+ char *ext = strtok((char *)extensions.cstr(), ",");
while (ext != NULL)
{
- fprintf(out, "\t\t\t<extension");
- fprintf(out, " name=\"%s\"", xml_normalize_string(ext));
- fprintf(out, "/>\n");
- ext = strtok (NULL, ",");
+ fprintf(m_output, "\t\t\t<extension");
+ fprintf(m_output, " name=\"%s\"", xml_normalize_string(ext));
+ fprintf(m_output, "/>\n");
+ ext = strtok(NULL, ",");
}
- fprintf(out, "\t\t</device>\n");
+ fprintf(m_output, "\t\t</device>\n");
}
}
-/*-------------------------------------------------
- print_game_software_list - print the information
- for all known software lists for this system
--------------------------------------------------*/
-static void print_game_software_list(FILE *out, const game_driver *game, const machine_config &config)
+//-------------------------------------------------
+// output_software_list - print the information
+// for all known software lists for this system
+//-------------------------------------------------
+
+void info_xml_creator::output_software_list()
{
- for (const device_config *dev = config.m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
+ for (const device_config *dev = m_drivlist.config().m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
{
software_list_config *swlist = (software_list_config *)downcast<const legacy_device_config_base *>(dev)->inline_config();
- for ( int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++ )
- {
- if ( swlist->list_name[i] )
+ for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++)
+ if (swlist->list_name[i])
{
- fprintf(out, "\t\t<softwarelist name=\"%s\" ", swlist->list_name[i] );
- fprintf(out, "status=\"%s\" />\n", (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible" );
+ fprintf(m_output, "\t\t<softwarelist name=\"%s\" ", swlist->list_name[i]);
+ fprintf(m_output, "status=\"%s\" />\n", (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible");
}
- }
}
}
-/* device iteration helpers */
-#define ram_first(config) (config).m_devicelist.first(RAM)
-#define ram_next(previous) ((previous)->typenext())
-/*-------------------------------------------------
- print_game_ramoptions - prints out all RAM
- options for this system
--------------------------------------------------*/
-static void print_game_ramoptions(FILE *out, const game_driver *game, const machine_config &config)
-{
- const device_config *device;
- for (device = ram_first(config); device != NULL; device = ram_next(device))
+//-------------------------------------------------
+// output_ramoptions - prints m_output all RAM
+// options for this system
+//-------------------------------------------------
+
+void info_xml_creator::output_ramoptions()
+{
+ for (const device_config *device = m_drivlist.config().m_devicelist.first(RAM); device != NULL; device = device->typenext())
{
ram_config *ram = (ram_config *)downcast<const legacy_device_config_base *>(device)->inline_config();
- fprintf(out, "\t\t<ramoption default=\"1\">%u</ramoption>\n", ram_parse_string(ram->default_size));
+ fprintf(m_output, "\t\t<ramoption default=\"1\">%u</ramoption>\n", ram_parse_string(ram->default_size));
+
if (ram->extra_options != NULL)
{
- int j;
- int size = strlen(ram->extra_options);
- char * const s = mame_strdup(ram->extra_options);
- char * const e = s + size;
- char *p = s;
- for (j=0;j<size;j++) {
- if (p[j]==',') p[j]=0;
- }
- /* try to parse each option */
- while(p <= e)
+ astring options(ram->extra_options);
+ for (int start, end = options.chr(0, ','); ; start = end + 1, end = options.chr(start, ','))
{
- fprintf(out, "\t\t<ramoption>%u</ramoption>\n", ram_parse_string(p));
- p += strlen(p);
- if (p == e)
+ astring option;
+ option.cpysubstr(options, start, (end == -1) ? -1 : end - start);
+ fprintf(m_output, "\t\t<ramoption>%u</ramoption>\n", ram_parse_string(option));
+ if (end == -1)
break;
- p += 1;
}
-
- osd_free(s);
}
}
}
-/*-------------------------------------------------
- print_game_info - print the XML information
- for one particular game driver
--------------------------------------------------*/
-
-static void print_game_info(FILE *out, const game_driver *game, emu_options &options)
-{
- const game_driver *clone_of;
- machine_config config(*game, options);
- ioport_list portlist;
- const char *start;
-
- /* no action if not a game */
- if (game->flags & GAME_NO_STANDALONE)
- return;
- /* start tracking resources and allocate the machine and input configs */
- input_port_list_init(portlist, game->ipt, NULL, 0, FALSE, NULL);
- for (device_config *cfg = config.m_devicelist.first(); cfg != NULL; cfg = cfg->next())
- {
- if (cfg->input_ports() != NULL)
- input_port_list_init(portlist, cfg->input_ports(), NULL, 0, FALSE, cfg);
- }
-
- /* print the header and the game name */
- fprintf(out, "\t<" XML_TOP);
- fprintf(out, " name=\"%s\"", xml_normalize_string(game->name) );
+//-------------------------------------------------
+// get_merge_name - get the rom name from a
+// parent set
+//-------------------------------------------------
- /* strip away any path information from the source_file and output it */
- start = strrchr(game->source_file, '/');
- if (start == NULL)
- start = strrchr(game->source_file, '\\');
- if (start == NULL)
- start = game->source_file - 1;
- fprintf(out, " sourcefile=\"%s\"", xml_normalize_string(start + 1));
-
- /* append bios and runnable flags */
- if (game->flags & GAME_IS_BIOS_ROOT)
- fprintf(out, " isbios=\"yes\"");
- if (game->flags & GAME_NO_STANDALONE)
- fprintf(out, " runnable=\"no\"");
- if (game->flags & GAME_MECHANICAL)
- fprintf(out, " ismechanical=\"yes\"");
-
- /* display clone information */
- clone_of = driver_get_clone(game);
- if (clone_of != NULL && !(clone_of->flags & GAME_IS_BIOS_ROOT))
- fprintf(out, " cloneof=\"%s\"", xml_normalize_string(clone_of->name));
- if (clone_of != NULL)
- fprintf(out, " romof=\"%s\"", xml_normalize_string(clone_of->name));
-
- /* display sample information and close the game tag */
- print_game_sampleof(out, game, config);
- fprintf(out, ">\n");
-
- /* output game description */
- if (game->description != NULL)
- fprintf(out, "\t\t<description>%s</description>\n", xml_normalize_string(game->description));
-
- /* print the year only if is a number or another allowed character (? or +) */
- if (game->year != NULL && strspn(game->year, "0123456789?+") == strlen(game->year))
- fprintf(out, "\t\t<year>%s</year>\n", xml_normalize_string(game->year));
-
- /* print the manufacturer information */
- if (game->manufacturer != NULL)
- fprintf(out, "\t\t<manufacturer>%s</manufacturer>\n", xml_normalize_string(game->manufacturer));
-
- /* now print various additional information */
- print_game_bios(out, game);
- print_game_rom(out, game, config);
- print_game_sample(out, game, config);
- print_game_chips(out, game, config);
- print_game_display(out, game, config);
- print_game_sound(out, game, config);
- print_game_input(out, game, portlist);
- print_game_switches(out, game, portlist);
- print_game_configs(out, game, portlist);
- print_game_categories(out, game, portlist);
- print_game_adjusters(out, game, portlist);
- print_game_driver(out, game, config);
- print_game_images( out, game, config );
- print_game_software_list( out, game, config );
- print_game_ramoptions( out, game, config );
- /* close the topmost tag */
- fprintf(out, "\t</" XML_TOP ">\n");
-}
-
-
-/*-------------------------------------------------
- print_mame_xml - print the XML information
- for all known games
--------------------------------------------------*/
-
-void print_mame_xml(FILE *out, const game_driver *const games[], const char *gamename, emu_options &options)
+const char *info_xml_creator::get_merge_name(const hash_collection &romhashes)
{
- int drvnum;
-
- fprintf(out,
- "<?xml version=\"1.0\"?>\n"
- "<!DOCTYPE " XML_ROOT " [\n"
- "<!ELEMENT " XML_ROOT " (" XML_TOP "+)>\n"
- "\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*, sample*, chip*, display*, sound?, input?, dipswitch*, configuration*, category*, adjuster*, driver?, device*, 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"
- "\t\t<!ATTLIST " XML_TOP " ismechanical (yes|no) \"no\">\n"
- "\t\t<!ATTLIST " XML_TOP " runnable (yes|no) \"yes\">\n"
- "\t\t<!ATTLIST " XML_TOP " cloneof CDATA #IMPLIED>\n"
- "\t\t<!ATTLIST " XML_TOP " romof CDATA #IMPLIED>\n"
- "\t\t<!ATTLIST " XML_TOP " sampleof CDATA #IMPLIED>\n"
- "\t\t<!ELEMENT description (#PCDATA)>\n"
- "\t\t<!ELEMENT year (#PCDATA)>\n"
- "\t\t<!ELEMENT manufacturer (#PCDATA)>\n"
- "\t\t<!ELEMENT biosset EMPTY>\n"
- "\t\t\t<!ATTLIST biosset name CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST biosset description CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST biosset default (yes|no) \"no\">\n"
- "\t\t<!ELEMENT rom EMPTY>\n"
- "\t\t\t<!ATTLIST rom name CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST rom bios CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST rom size CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST rom crc CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST rom md5 CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST rom sha1 CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST rom merge CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST rom region CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST rom offset CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST rom status (baddump|nodump|good) \"good\">\n"
- "\t\t\t<!ATTLIST rom optional (yes|no) \"no\">\n"
- "\t\t<!ELEMENT disk EMPTY>\n"
- "\t\t\t<!ATTLIST disk name CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST disk md5 CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST disk sha1 CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST disk merge CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST disk region CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST disk index CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST disk status (baddump|nodump|good) \"good\">\n"
- "\t\t\t<!ATTLIST disk optional (yes|no) \"no\">\n"
- "\t\t<!ELEMENT sample EMPTY>\n"
- "\t\t\t<!ATTLIST sample name CDATA #REQUIRED>\n"
- "\t\t<!ELEMENT chip EMPTY>\n"
- "\t\t\t<!ATTLIST chip name CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST chip tag CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST chip type (cpu|audio) #REQUIRED>\n"
- "\t\t\t<!ATTLIST chip clock CDATA #IMPLIED>\n"
- "\t\t<!ELEMENT display EMPTY>\n"
- "\t\t\t<!ATTLIST display type (raster|vector|lcd|unknown) #REQUIRED>\n"
- "\t\t\t<!ATTLIST display rotate (0|90|180|270) #REQUIRED>\n"
- "\t\t\t<!ATTLIST display flipx (yes|no) \"no\">\n"
- "\t\t\t<!ATTLIST display width CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST display height CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST display refresh CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST display pixclock CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST display htotal CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST display hbend CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST display hbstart CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST display vtotal CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST display vbend CDATA #IMPLIED>\n"
- "\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<!ELEMENT input (control*)>\n"
- "\t\t\t<!ATTLIST input service (yes|no) \"no\">\n"
- "\t\t\t<!ATTLIST input tilt (yes|no) \"no\">\n"
- "\t\t\t<!ATTLIST input players CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST input buttons CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST input coins CDATA #IMPLIED>\n"
- "\t\t\t<!ELEMENT control EMPTY>\n"
- "\t\t\t\t<!ATTLIST control type CDATA #REQUIRED>\n"
- "\t\t\t\t<!ATTLIST control minimum CDATA #IMPLIED>\n"
- "\t\t\t\t<!ATTLIST control maximum CDATA #IMPLIED>\n"
- "\t\t\t\t<!ATTLIST control sensitivity CDATA #IMPLIED>\n"
- "\t\t\t\t<!ATTLIST control keydelta CDATA #IMPLIED>\n"
- "\t\t\t\t<!ATTLIST control reverse (yes|no) \"no\">\n"
- "\t\t<!ELEMENT dipswitch (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\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\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\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"
- "\t\t<!ELEMENT category (item*)>\n"
- "\t\t\t<!ATTLIST category name CDATA #REQUIRED>\n"
- "\t\t\t<!ELEMENT item EMPTY>\n"
- "\t\t\t\t<!ATTLIST item name CDATA #REQUIRED>\n"
- "\t\t\t\t<!ATTLIST item default (yes|no) \"no\">\n"
- "\t\t<!ELEMENT adjuster EMPTY>\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\t<!ATTLIST driver palettesize CDATA #REQUIRED>\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 mandatory CDATA #IMPLIED>\n"
- "\t\t\t<!ATTLIST device interface CDATA #IMPLIED>\n"
- "\t\t\t<!ELEMENT instance EMPTY>\n"
- "\t\t\t\t<!ATTLIST instance name CDATA #REQUIRED>\n"
- "\t\t\t\t<!ATTLIST instance briefname CDATA #REQUIRED>\n"
- "\t\t\t<!ELEMENT extension EMPTY>\n"
- "\t\t\t\t<!ATTLIST extension name CDATA #REQUIRED>\n"
- "\t\t<!ELEMENT softwarelist EMPTY>\n"
- "\t\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n"
- "\t\t\t<!ATTLIST softwarelist status (original|compatible) #REQUIRED>\n"
- "\t\t<!ELEMENT ramoption (#PCDATA)>\n"
- "\t\t\t<!ATTLIST ramoption default CDATA #IMPLIED>\n"
- "]>\n\n"
- "<" XML_ROOT " build=\"%s\" debug=\""
-#ifdef MAME_DEBUG
- "yes"
-#else
- "no"
-#endif
- "\" mameconfig=\"%d\">\n",
- xml_normalize_string(build_version),
- CONFIG_VERSION
- );
-
- for (drvnum = 0; games[drvnum] != NULL; drvnum++)
- if (mame_strwildcmp(gamename, games[drvnum]->name) == 0)
- print_game_info(out, games[drvnum], options);
+ const char *merge_name = NULL;
+
+ // walk the parent chain
+ 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))
+
+ // look in the parent's ROMs
+ for (const rom_source *psource = rom_first_source(m_drivlist.config(clone_of)); psource != NULL; psource = rom_next_source(*psource))
+ for (const rom_entry *pregion = rom_first_region(*psource); pregion != NULL; pregion = rom_next_region(pregion))
+ for (const rom_entry *prom = rom_first_file(pregion); prom != NULL; prom = rom_next_file(prom))
+ {
+ hash_collection phashes(ROM_GETHASHDATA(prom));
+ if (!phashes.flag(hash_collection::FLAG_NO_DUMP) && romhashes == phashes)
+ {
+ // stop when we find a match
+ merge_name = ROM_GETNAME(prom);
+ break;
+ }
+ }
- fprintf(out, "</" XML_ROOT ">\n");
+ return merge_name;
}