summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
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
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')
-rw-r--r--src/emu/audit.c693
-rw-r--r--src/emu/audit.h221
-rw-r--r--src/emu/clifront.c1936
-rw-r--r--src/emu/clifront.h84
-rw-r--r--src/emu/config.c6
-rw-r--r--src/emu/cpu/mips/dismips.c6
-rw-r--r--src/emu/debug/textbuf.c4
-rw-r--r--src/emu/devcpu.c1
-rw-r--r--src/emu/devintrf.c24
-rw-r--r--src/emu/devintrf.h6
-rw-r--r--src/emu/devlegcy.c1
-rw-r--r--src/emu/devlegcy.h2
-rw-r--r--src/emu/diimage.c7
-rw-r--r--src/emu/driver.c482
-rw-r--r--src/emu/driver.h156
-rw-r--r--src/emu/drivers/empty.c12
-rw-r--r--src/emu/emu.mak1
-rw-r--r--src/emu/emualloc.c51
-rw-r--r--src/emu/emualloc.h30
-rw-r--r--src/emu/emuopts.c15
-rw-r--r--src/emu/emutempl.h31
-rw-r--r--src/emu/hash.c4
-rw-r--r--src/emu/hash.h2
-rw-r--r--src/emu/info.c1862
-rw-r--r--src/emu/info.h77
-rw-r--r--src/emu/layout/pinball.lay19
-rw-r--r--src/emu/machine.c13
-rw-r--r--src/emu/mame.c2
-rw-r--r--src/emu/render.c8
-rw-r--r--src/emu/rendlay.c4
-rw-r--r--src/emu/romload.c19
-rw-r--r--src/emu/sound/bsmt2000.c3
-rw-r--r--src/emu/sound/wavwrite.c6
-rw-r--r--src/emu/ui.c28
-rw-r--r--src/emu/uimenu.c102
-rw-r--r--src/emu/validity.c74
36 files changed, 3139 insertions, 2853 deletions
diff --git a/src/emu/audit.c b/src/emu/audit.c
index 76b9ab5dbee..1393a335737 100644
--- a/src/emu/audit.c
+++ b/src/emu/audit.c
@@ -4,8 +4,36 @@
ROM set auditing functions.
- 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.
***************************************************************************/
@@ -17,510 +45,419 @@
#include "sound/samples.h"
+//**************************************************************************
+// CORE FUNCTIONS
+//**************************************************************************
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static void audit_one_rom(emu_options &options, const rom_entry *rom, const char *regiontag, const game_driver *gamedrv, const char *validation, audit_record *record);
-static void audit_one_disk(emu_options &options, const rom_entry *rom, const game_driver *gamedrv, const char *validation, audit_record *record);
-static int rom_used_by_parent(emu_options &options, const game_driver *gamedrv, const hash_collection &romhashes, const game_driver **parent);
-
-
-
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
+//-------------------------------------------------
+// media_auditor - constructor
+//-------------------------------------------------
-/*-------------------------------------------------
- set_status - shortcut for setting status and
- substatus values
--------------------------------------------------*/
-
-INLINE void set_status(audit_record *record, UINT8 status, UINT8 substatus)
+media_auditor::media_auditor(const driver_enumerator &enumerator)
+ : m_enumerator(enumerator),
+ m_validation(AUDIT_VALIDATE_FULL),
+ m_searchpath(NULL)
{
- record->status = status;
- record->substatus = substatus;
}
+//-------------------------------------------------
+// audit_media - audit the media described by the
+// currently-enumerated driver
+//-------------------------------------------------
-/***************************************************************************
- CORE FUNCTIONS
-***************************************************************************/
-
-/*-------------------------------------------------
- audit_images - validate the ROM and disk
- images for a game
--------------------------------------------------*/
-
-int audit_images(emu_options &options, const game_driver *gamedrv, const char *validation, audit_record **audit)
+media_auditor::summary media_auditor::audit_media(const char *validation)
{
- machine_config config(*gamedrv, options);
- const rom_entry *region, *rom;
- const rom_source *source;
- audit_record *record;
- int anyfound = FALSE;
- int anyrequired = FALSE;
- int allshared = TRUE;
- int records;
-
- /* determine the number of records we will generate */
- records = 0;
- bool source_is_gamedrv = true;
- 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))
- for (rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
- if (ROMREGION_ISROMDATA(region) || ROMREGION_ISDISKDATA(region))
- {
- if (source_is_gamedrv && !ROM_ISOPTIONAL(rom))
- {
- hash_collection hashes(ROM_GETHASHDATA(rom));
- if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
- {
- anyrequired = TRUE;
- if (allshared && !rom_used_by_parent(options, gamedrv, hashes, NULL))
- allshared = FALSE;
- }
- }
- records++;
- }
+ // start fresh
+ m_record_list.reset();
- source_is_gamedrv = false;
- }
+ // store validation for later
+ m_validation = validation;
- if (records > 0)
+ // iterate over ROM sources and regions
+ bool anyfound = false;
+ bool anyrequired = false;
+ for (const rom_source *source = rom_first_source(m_enumerator.config()); source != NULL; source = rom_next_source(*source))
{
- /* allocate memory for the records */
- *audit = global_alloc_array_clear(audit_record, records);
- record = *audit;
-
- /* iterate over ROM sources and regions */
- bool source_is_gamedrv = true;
- 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))
+ // determine the search path for this source and iterate through the regions
+ m_searchpath = source->searchpath();
+
+ // also determine if this is the driver's specific ROMs or not
+ bool source_is_gamedrv = (dynamic_cast<const driver_device_config_base *>(source) != NULL);
+
+ // now iterate over regions and ROMs within
+ for (const rom_entry *region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
{
- const char *regiontag = ROMREGION_ISLOADBYNAME(region) ? ROM_GETNAME(region) : NULL;
- for (rom = rom_first_file(region); rom; rom = rom_next_file(rom))
- {
- /* audit a file */
- if (ROMREGION_ISROMDATA(region))
- {
- audit_one_rom(options, rom, regiontag, gamedrv, validation, record);
- }
-
- /* audit a disk */
- else if (ROMREGION_ISDISKDATA(region))
- {
- audit_one_disk(options, rom, gamedrv, validation, record);
- }
-
- else
- {
- continue;
- }
-
- if (source_is_gamedrv && record->status != AUDIT_STATUS_NOT_FOUND && (allshared || !rom_used_by_parent(options, gamedrv, record->exphashes, NULL)))
- anyfound = TRUE;
-
- record++;
- }
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+
+ // if a dump exists, then at least one entry is required
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ anyrequired = true;
+
+ // audit a file
+ audit_record *record = NULL;
+ if (ROMREGION_ISROMDATA(region))
+ record = audit_one_rom(rom);
+
+ // audit a disk
+ else if (ROMREGION_ISDISKDATA(region))
+ record = audit_one_disk(rom);
+
+ // skip if no record
+ if (record == NULL)
+ continue;
+
+ // if we got a record back,
+ if (record->status() != audit_record::STATUS_NOT_FOUND && source_is_gamedrv && also_used_by_parent(hashes) == -1)
+ anyfound = true;
}
- source_is_gamedrv = false;
- }
}
- /* if we found nothing, we don't have the set at all */
+ // if we found nothing, we don't have the set at all
if (!anyfound && anyrequired)
- {
- global_free(*audit);
- *audit = NULL;
- records = 0;
- }
-
- return records;
+ m_record_list.reset();
+
+ // return a summary
+ return summarize();
}
-/*-------------------------------------------------
- audit_samples - validate the samples for a
- game
--------------------------------------------------*/
+//-------------------------------------------------
+// audit_samples - validate the samples for the
+// currently-enumerated driver
+//-------------------------------------------------
-int audit_samples(emu_options &options, const game_driver *gamedrv, audit_record **audit)
+media_auditor::summary media_auditor::audit_samples()
{
- machine_config config(*gamedrv, options);
- audit_record *record;
- int records = 0;
- int sampnum;
-
- /* count the number of sample records attached to this driver */
- 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 samples_interface *intf = (const samples_interface *)sound->devconfig().static_config();
-
- if (intf->samplenames != NULL)
- {
- /* iterate over samples in this entry */
- for (sampnum = 0; intf->samplenames[sampnum] != NULL; sampnum++)
- if (intf->samplenames[sampnum][0] != '*')
- records++;
- }
- }
-
- /* if no records, just quit now */
- if (records == 0)
- goto skip;
-
- /* allocate memory for the records */
- *audit = global_alloc_array_clear(audit_record, records);
- record = *audit;
+ // start fresh
+ m_record_list.reset();
- /* now iterate over sample entries */
- for (bool gotone = config.m_devicelist.first(sound); gotone; gotone = sound->next(sound))
- if (sound->devconfig().type() == SAMPLES)
+ // iterate over sample entries
+ for (const device_config *devconfig = m_enumerator.config().first_device(); devconfig != NULL; devconfig = devconfig->next())
+ if (devconfig->type() == SAMPLES)
{
- const samples_interface *intf = (const samples_interface *)sound->devconfig().static_config();
- const char *sharedname = NULL;
-
+ const samples_interface *intf = reinterpret_cast<const samples_interface *>(devconfig->static_config());
if (intf->samplenames != NULL)
{
- /* iterate over samples in this entry */
- for (sampnum = 0; intf->samplenames[sampnum] != NULL; sampnum++)
+ // by default we just search using the driver name
+ astring searchpath(m_enumerator.driver().name);
+
+ // iterate over samples in this entry
+ for (int sampnum = 0; intf->samplenames[sampnum] != NULL; sampnum++)
+ {
+ // starred entries indicate an additional searchpath
if (intf->samplenames[sampnum][0] == '*')
- sharedname = &intf->samplenames[sampnum][1];
- else
{
- /* attempt to access the file from the game driver name */
- emu_file file(options.sample_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
- file_error filerr = file.open(gamedrv->name, PATH_SEPARATOR, intf->samplenames[sampnum]);
-
- /* attempt to access the file from the shared driver name */
- if (filerr != FILERR_NONE && sharedname != NULL)
- filerr = file.open(sharedname, PATH_SEPARATOR, intf->samplenames[sampnum]);
-
- /* fill in the record */
- record->type = AUDIT_FILE_SAMPLE;
- record->name = intf->samplenames[sampnum];
+ searchpath.cat(";").cat(&intf->samplenames[sampnum][1]);
+ continue;
+ }
+
+ // create a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(intf->samplenames[sampnum], audit_record::MEDIA_SAMPLE)));
+
+ // look for the files
+ emu_file file(m_enumerator.options().sample_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
+ path_iterator path(searchpath);
+ astring curpath;
+ while (path.next(curpath, intf->samplenames[sampnum]))
+ {
+ // attempt to access the file
+ file_error filerr = file.open(curpath);
if (filerr == FILERR_NONE)
- set_status(record++, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD);
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD);
else
- set_status(record++, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND);
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND);
}
+ }
}
}
-
-skip:
- return records;
+
+ // return a summary
+ return summarize();
}
-/*-------------------------------------------------
- audit_summary - output a summary given a
- list of audit records
--------------------------------------------------*/
+//-------------------------------------------------
+// summary - generate a summary, with an optional
+// string format
+//-------------------------------------------------
-int audit_summary(const game_driver *gamedrv, int count, const audit_record *records, int output)
+media_auditor::summary media_auditor::summarize(astring *string)
{
- int overall_status = CORRECT;
- int recnum;
-
- /* no count AND no records means not found */
- if (count == 0 && records == NULL)
+ // no count AND no records means not found
+ if (m_record_list.count() == 0)
return NOTFOUND;
- /* loop over records */
- for (recnum = 0; recnum < count; recnum++)
+ // loop over records
+ summary overall_status = CORRECT;
+ for (audit_record *record = m_record_list.first(); record != NULL; record = record->next())
{
- const audit_record *record = &records[recnum];
- int best_new_status = INCORRECT;
+ summary best_new_status = INCORRECT;
- /* skip anything that's fine */
- if (record->substatus == SUBSTATUS_GOOD)
+ // skip anything that's fine
+ if (record->substatus() == audit_record::SUBSTATUS_GOOD)
continue;
- /* output the game name, file name, and length (if applicable) */
- if (output)
+ // output the game name, file name, and length (if applicable)
+ if (string != NULL)
{
- mame_printf_info("%-8s: %s", gamedrv->name, record->name);
- if (record->explength > 0)
- mame_printf_info(" (%d bytes)", record->explength);
- mame_printf_info(" - ");
+ string->catprintf("%-12s: %s", m_enumerator.driver().name, record->name());
+ if (record->expected_length() > 0)
+ string->catprintf(" (%d bytes)", record->expected_length());
+ string->catprintf(" - ");
}
- /* use the substatus for finer details */
- switch (record->substatus)
+ // use the substatus for finer details
+ switch (record->substatus())
{
- case SUBSTATUS_GOOD_NEEDS_REDUMP:
- if (output) mame_printf_info("NEEDS REDUMP\n");
+ case audit_record::SUBSTATUS_GOOD_NEEDS_REDUMP:
+ if (string != NULL) string->catprintf("NEEDS REDUMP\n");
best_new_status = BEST_AVAILABLE;
break;
- case SUBSTATUS_FOUND_NODUMP:
- if (output) mame_printf_info("NO GOOD DUMP KNOWN\n");
+ case audit_record::SUBSTATUS_FOUND_NODUMP:
+ if (string != NULL) string->catprintf("NO GOOD DUMP KNOWN\n");
best_new_status = BEST_AVAILABLE;
break;
- case SUBSTATUS_FOUND_BAD_CHECKSUM:
- if (output)
+ case audit_record::SUBSTATUS_FOUND_BAD_CHECKSUM:
+ if (string != NULL)
{
astring tempstr;
- mame_printf_info("INCORRECT CHECKSUM:\n");
- mame_printf_info("EXPECTED: %s\n", record->exphashes.macro_string(tempstr));
- mame_printf_info(" FOUND: %s\n", record->hashes.macro_string(tempstr));
+ string->catprintf("INCORRECT CHECKSUM:\n");
+ string->catprintf("EXPECTED: %s\n", record->expected_hashes().macro_string(tempstr));
+ string->catprintf(" FOUND: %s\n", record->actual_hashes().macro_string(tempstr));
}
break;
- case SUBSTATUS_FOUND_WRONG_LENGTH:
- if (output) mame_printf_info("INCORRECT LENGTH: %d bytes\n", record->length);
+ case audit_record::SUBSTATUS_FOUND_WRONG_LENGTH:
+ if (string != NULL) string->catprintf("INCORRECT LENGTH: %d bytes\n", record->actual_length());
break;
- case SUBSTATUS_NOT_FOUND:
- if (output) mame_printf_info("NOT FOUND\n");
+ case audit_record::SUBSTATUS_NOT_FOUND:
+ if (string != NULL) string->catprintf("NOT FOUND\n");
break;
- case SUBSTATUS_NOT_FOUND_NODUMP:
- if (output) mame_printf_info("NOT FOUND - NO GOOD DUMP KNOWN\n");
+ case audit_record::SUBSTATUS_NOT_FOUND_NODUMP:
+ if (string != NULL) string->catprintf("NOT FOUND - NO GOOD DUMP KNOWN\n");
best_new_status = BEST_AVAILABLE;
break;
- case SUBSTATUS_NOT_FOUND_OPTIONAL:
- if (output) mame_printf_info("NOT FOUND BUT OPTIONAL\n");
+ case audit_record::SUBSTATUS_NOT_FOUND_OPTIONAL:
+ if (string != NULL) string->catprintf("NOT FOUND BUT OPTIONAL\n");
best_new_status = BEST_AVAILABLE;
break;
- case SUBSTATUS_NOT_FOUND_PARENT:
- if (output) mame_printf_info("NOT FOUND (shared with parent)\n");
+ case audit_record::SUBSTATUS_NOT_FOUND_PARENT:
+ if (string != NULL) string->catprintf("NOT FOUND (shared with parent)\n");
break;
- case SUBSTATUS_NOT_FOUND_BIOS:
- if (output) mame_printf_info("NOT FOUND (BIOS)\n");
+ case audit_record::SUBSTATUS_NOT_FOUND_BIOS:
+ if (string != NULL) string->catprintf("NOT FOUND (BIOS)\n");
break;
+
+ default:
+ assert(false);
}
- /* downgrade the overall status if necessary */
+ // downgrade the overall status if necessary
overall_status = MAX(overall_status, best_new_status);
}
-
return overall_status;
}
+//-------------------------------------------------
+// audit_one_rom - validate a single ROM entry
+//-------------------------------------------------
-/***************************************************************************
- UTILITIES
-***************************************************************************/
-
-/*-------------------------------------------------
- audit_one_rom - validate a single ROM entry
--------------------------------------------------*/
-
-static void audit_one_rom(emu_options &options, const rom_entry *rom, const char *regiontag, const game_driver *gamedrv, const char *validation, audit_record *record)
+audit_record *media_auditor::audit_one_rom(const rom_entry *rom)
{
- const game_driver *drv;
- UINT32 crc = 0;
+ // allocate and append a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(*rom, audit_record::MEDIA_ROM)));
- /* fill in the record basics */
- record->type = AUDIT_FILE_ROM;
- record->name = ROM_GETNAME(rom);
- record->exphashes.from_internal_string(ROM_GETHASHDATA(rom));
- record->length = 0;
- record->explength = rom_file_size(rom);
-
- /* see if we have a CRC and extract it if so */
- bool has_crc = record->exphashes.crc(crc);
+ // see if we have a CRC and extract it if so
+ UINT32 crc = 0;
+ bool has_crc = record.expected_hashes().crc(crc);
- /* find the file and checksum it, getting the file length along the way */
- for (drv = gamedrv; drv != NULL; drv = driver_get_clone(drv))
+ // find the file and checksum it, getting the file length along the way
+ emu_file file(m_enumerator.options().media_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
+ path_iterator path(m_searchpath);
+ astring curpath;
+ while (path.next(curpath, record.name()))
{
- emu_file file(options.media_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
-
- /* open the file if we can */
+ // open the file if we can
file_error filerr;
if (has_crc)
- filerr = file.open(drv->name, PATH_SEPARATOR, ROM_GETNAME(rom), crc);
+ filerr = file.open(curpath, crc);
else
- filerr = file.open(drv->name, PATH_SEPARATOR, ROM_GETNAME(rom));
+ filerr = file.open(curpath);
+
+ // if it worked, get the actual length and hashes, then stop
if (filerr == FILERR_NONE)
{
- record->hashes = file.hashes(validation);
- record->length = (UINT32)file.size();
+ record.set_actual(file.hashes(m_validation), file.size());
break;
}
}
+
+ // compute the final status
+ compute_status(record, rom, record.actual_length() != 0);
+ return &record;
+}
- /* if not found, check the region as a backup */
- if (record->length == 0 && regiontag != NULL)
- {
- emu_file file(options.media_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
-
- /* open the file if we can */
- file_error filerr;
- if (has_crc)
- filerr = file.open(regiontag, PATH_SEPARATOR, ROM_GETNAME(rom), crc);
- else
- filerr = file.open(regiontag, PATH_SEPARATOR, ROM_GETNAME(rom));
- if (filerr == FILERR_NONE)
- {
- record->hashes = file.hashes(validation);
- record->length = (UINT32)file.size();
- }
- }
-
- /* if we failed to find the file, set the appropriate status */
- if (record->length == 0)
- {
- const game_driver *parent;
-
- /* no good dump */
- if (record->exphashes.flag(hash_collection::FLAG_NO_DUMP))
- set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND_NODUMP);
-
- /* optional ROM */
- else if (ROM_ISOPTIONAL(rom))
- set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND_OPTIONAL);
- /* not found and used by parent */
- else if (rom_used_by_parent(options, gamedrv, record->exphashes, &parent))
- set_status(record, AUDIT_STATUS_NOT_FOUND, (parent->flags & GAME_IS_BIOS_ROOT) ? SUBSTATUS_NOT_FOUND_BIOS : SUBSTATUS_NOT_FOUND_PARENT);
+//-------------------------------------------------
+// audit_one_disk - validate a single disk entry
+//-------------------------------------------------
- /* just plain old not found */
- else
- set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND);
- }
+audit_record *media_auditor::audit_one_disk(const rom_entry *rom)
+{
+ // allocate and append a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(*rom, audit_record::MEDIA_DISK)));
- /* if we did find the file, do additional verification */
- else
+ // open the disk
+ emu_file *source_file;
+ chd_file *source;
+ chd_error err = open_disk_image(m_enumerator.options(), &m_enumerator.driver(), rom, &source_file, &source, NULL);
+
+ // if we succeeded, get the hashes
+ if (err == CHDERR_NONE)
{
- /* length mismatch */
- if (record->explength != record->length)
- set_status(record, AUDIT_STATUS_FOUND_INVALID, SUBSTATUS_FOUND_WRONG_LENGTH);
-
- /* found but needs a dump */
- else if (record->exphashes.flag(hash_collection::FLAG_NO_DUMP))
- set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_FOUND_NODUMP);
-
- /* incorrect hash */
- else if (record->exphashes != record->hashes)
- set_status(record, AUDIT_STATUS_FOUND_INVALID, SUBSTATUS_FOUND_BAD_CHECKSUM);
+ static const UINT8 nullhash[20] = { 0 };
+ chd_header header = *chd_get_header(source);
+ hash_collection hashes;
- /* correct hash but needs a redump */
- else if (record->exphashes.flag(hash_collection::FLAG_BAD_DUMP))
- set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD_NEEDS_REDUMP);
+ // if there's an MD5 or SHA1 hash, add them to the output hash
+ if (memcmp(nullhash, header.md5, sizeof(header.md5)) != 0)
+ hashes.add_from_buffer(hash_collection::HASH_MD5, header.md5, sizeof(header.md5));
+ if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0)
+ hashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1));
+
+ // update the actual values
+ record.set_actual(hashes);
- /* just plain old good */
- else
- set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD);
+ // close the file and release the source
+ chd_close(source);
+ global_free(source_file);
}
+
+ // compute the final status
+ compute_status(record, rom, record.actual_length() != 0);
+ return &record;
}
-/*-------------------------------------------------
- audit_one_disk - validate a single disk entry
--------------------------------------------------*/
+//-------------------------------------------------
+// compute_status - compute a detailed status
+// based on the information we have
+//-------------------------------------------------
-static void audit_one_disk(emu_options &options, const rom_entry *rom, const game_driver *gamedrv, const char *validation, audit_record *record)
+void media_auditor::compute_status(audit_record &record, const rom_entry *rom, bool found)
{
- emu_file *source_file;
- chd_file *source;
- chd_error err;
-
- /* fill in the record basics */
- record->type = AUDIT_FILE_DISK;
- record->name = ROM_GETNAME(rom);
- record->exphashes.from_internal_string(ROM_GETHASHDATA(rom));
-
- /* open the disk */
- err = open_disk_image(options, gamedrv, rom, &source_file, &source, NULL);
-
- /* if we failed, report the error */
- if (err != CHDERR_NONE)
+ // if not found, provide more details
+ if (!found)
{
- /* out of memory */
- if (err == CHDERR_OUT_OF_MEMORY)
- set_status(record, AUDIT_STATUS_ERROR, SUBSTATUS_ERROR);
+ int parent;
+
+ // no good dump
+ if (record.expected_hashes().flag(hash_collection::FLAG_NO_DUMP))
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND_NODUMP);
- /* not found but it's not good anyway */
- else if (record->exphashes.flag(hash_collection::FLAG_NO_DUMP))
- set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND_NODUMP);
+ // optional ROM
+ else if (ROM_ISOPTIONAL(rom))
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND_OPTIONAL);
- /* not found but optional */
- else if (DISK_ISOPTIONAL(rom))
- set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND_OPTIONAL);
+ // not found and used by parent
+ else if ((parent = also_used_by_parent(record.expected_hashes())) != -1)
+ {
+ if (m_enumerator.driver(parent).flags & GAME_IS_BIOS_ROOT)
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND_BIOS);
+ else
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND_PARENT);
+ }
- /* not found at all */
+ // just plain old not found
else
- set_status(record, AUDIT_STATUS_NOT_FOUND, SUBSTATUS_NOT_FOUND);
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND);
}
-
- /* if we succeeded, validate it */
+
+ // if found, provide more details
else
{
- static const UINT8 nullhash[20] = { 0 };
- chd_header header = *chd_get_header(source);
-
- /* if there's an MD5 or SHA1 hash, add them to the output hash */
- if (memcmp(nullhash, header.md5, sizeof(header.md5)) != 0)
- record->hashes.add_from_buffer(hash_collection::HASH_MD5, header.md5, sizeof(header.md5));
- if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0)
- record->hashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1));
+ // length mismatch
+ if (record.expected_length() != record.actual_length())
+ record.set_status(audit_record::STATUS_FOUND_INVALID, audit_record::SUBSTATUS_FOUND_WRONG_LENGTH);
- /* found but needs a dump */
- if (record->exphashes.flag(hash_collection::FLAG_NO_DUMP))
- set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_FOUND_NODUMP);
+ // found but needs a dump
+ else if (record.expected_hashes().flag(hash_collection::FLAG_NO_DUMP))
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_FOUND_NODUMP);
- /* incorrect hash */
- else if (record->exphashes != record->hashes)
- set_status(record, AUDIT_STATUS_FOUND_INVALID, SUBSTATUS_FOUND_BAD_CHECKSUM);
+ // incorrect hash
+ else if (record.expected_hashes() != record.actual_hashes())
+ record.set_status(audit_record::STATUS_FOUND_INVALID, audit_record::SUBSTATUS_FOUND_BAD_CHECKSUM);
- /* correct hash but needs a redump */
- else if (record->exphashes.flag(hash_collection::FLAG_BAD_DUMP))
- set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD_NEEDS_REDUMP);
+ // correct hash but needs a redump
+ else if (record.expected_hashes().flag(hash_collection::FLAG_BAD_DUMP))
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD_NEEDS_REDUMP);
- /* just plain good */
+ // just plain old good
else
- set_status(record, AUDIT_STATUS_GOOD, SUBSTATUS_GOOD);
-
- chd_close(source);
- global_free(source_file);
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD);
}
}
-/*-------------------------------------------------
- rom_used_by_parent - determine if a given
- ROM is also used by the parent
--------------------------------------------------*/
+//-------------------------------------------------
+// also_used_by_parent - return the index in the
+// enumerator of the parent who also owns a media
+// entry with the same hashes
+//-------------------------------------------------
-static int rom_used_by_parent(emu_options &options, const game_driver *gamedrv, const hash_collection &romhashes, const game_driver **parent)
+int media_auditor::also_used_by_parent(const hash_collection &romhashes)
{
- const game_driver *drv;
+ // iterate up the parent chain
+ for (int drvindex = m_enumerator.find(m_enumerator.driver().parent); drvindex != -1; drvindex = m_enumerator.find(m_enumerator.driver(drvindex).parent))
- /* iterate up the parent chain */
- for (drv = driver_get_clone(gamedrv); drv != NULL; drv = driver_get_clone(drv))
- {
- machine_config config(*drv, options);
- const rom_entry *region;
- const rom_entry *rom;
-
- /* see if the parent has the same ROM or not */
- for (const rom_source *source = rom_first_source(config); source != NULL; source = rom_next_source(*source))
- for (region = rom_first_region(*source); region; region = rom_next_region(region))
- for (rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ // see if the parent has the same ROM or not
+ for (const rom_source *source = rom_first_source(m_enumerator.config(drvindex)); source != NULL; source = rom_next_source(*source))
+ for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
{
hash_collection hashes(ROM_GETHASHDATA(rom));
if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && hashes == romhashes)
- {
- if (parent != NULL)
- *parent = drv;
- return TRUE;
- }
+ return drvindex;
}
- }
- return FALSE;
+ // nope, return -1
+ return -1;
+}
+
+
+//-------------------------------------------------
+// audit_record - constructor
+//-------------------------------------------------
+
+audit_record::audit_record(const rom_entry &media, media_type type)
+ : m_next(NULL),
+ m_type(type),
+ m_status(STATUS_ERROR),
+ m_substatus(SUBSTATUS_ERROR),
+ m_name(ROM_GETNAME(&media)),
+ m_explength(rom_file_size(&media)),
+ m_length(0)
+{
+ m_exphashes.from_internal_string(ROM_GETHASHDATA(&media));
+}
+
+audit_record::audit_record(const char *name, media_type type)
+ : m_next(NULL),
+ m_type(type),
+ m_status(STATUS_ERROR),
+ m_substatus(SUBSTATUS_ERROR),
+ m_name(name),
+ m_explength(0),
+ m_length(0)
+{
}
diff --git a/src/emu/audit.h b/src/emu/audit.h
index 3b6eaffd4a2..00964e91417 100644
--- a/src/emu/audit.h
+++ b/src/emu/audit.h
@@ -4,8 +4,36 @@
ROM, disk, and sample auditing functions.
- 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.
***************************************************************************/
@@ -18,84 +46,145 @@
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
-/* hashes to use for validation */
+// hashes to use for validation
#define AUDIT_VALIDATE_FAST "R" /* CRC only */
#define AUDIT_VALIDATE_FULL "RS" /* CRC + SHA1 */
-/* return values from audit_verify_roms and audit_verify_samples */
-enum
-{
- CORRECT = 0,
- BEST_AVAILABLE,
- INCORRECT,
- NOTFOUND
-};
-/* image types for audit_record.type */
-enum
-{
- AUDIT_FILE_ROM = 0,
- AUDIT_FILE_DISK,
- AUDIT_FILE_SAMPLE
-};
-/* status values for audit_record.status */
-enum
-{
- AUDIT_STATUS_GOOD = 0,
- AUDIT_STATUS_FOUND_INVALID,
- AUDIT_STATUS_NOT_FOUND,
- AUDIT_STATUS_ERROR
-};
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
-/* substatus values for audit_record.substatus */
-enum
-{
- SUBSTATUS_GOOD = 0,
- SUBSTATUS_GOOD_NEEDS_REDUMP,
- SUBSTATUS_FOUND_NODUMP,
- SUBSTATUS_FOUND_BAD_CHECKSUM,
- SUBSTATUS_FOUND_WRONG_LENGTH,
- SUBSTATUS_NOT_FOUND,
- SUBSTATUS_NOT_FOUND_NODUMP,
- SUBSTATUS_NOT_FOUND_OPTIONAL,
- SUBSTATUS_NOT_FOUND_PARENT,
- SUBSTATUS_NOT_FOUND_BIOS,
- SUBSTATUS_ERROR = 100
-};
+// ======================> audit_record
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-typedef struct _audit_record audit_record;
-struct _audit_record
+// holds the result of auditing a single item
+class audit_record
{
- UINT8 type; /* type of item that was audited */
- UINT8 status; /* status of audit on this item */
- UINT8 substatus; /* finer-detail status */
- const char * name; /* name of item */
- UINT32 explength; /* expected length of item */
- UINT32 length; /* actual length of item */
- hash_collection exphashes; /* expected hash data */
- hash_collection hashes; /* actual hash information */
+ friend class simple_list<audit_record>;
+
+public:
+ // media types
+ enum media_type
+ {
+ MEDIA_ROM = 0,
+ MEDIA_DISK,
+ MEDIA_SAMPLE
+ };
+
+ // status values
+ enum audit_status
+ {
+ STATUS_GOOD = 0,
+ STATUS_FOUND_INVALID,
+ STATUS_NOT_FOUND,
+ STATUS_ERROR
+ };
+
+ // substatus values
+ enum audit_substatus
+ {
+ SUBSTATUS_GOOD = 0,
+ SUBSTATUS_GOOD_NEEDS_REDUMP,
+ SUBSTATUS_FOUND_NODUMP,
+ SUBSTATUS_FOUND_BAD_CHECKSUM,
+ SUBSTATUS_FOUND_WRONG_LENGTH,
+ SUBSTATUS_NOT_FOUND,
+ SUBSTATUS_NOT_FOUND_NODUMP,
+ SUBSTATUS_NOT_FOUND_OPTIONAL,
+ SUBSTATUS_NOT_FOUND_PARENT,
+ SUBSTATUS_NOT_FOUND_BIOS,
+ SUBSTATUS_ERROR = 100
+ };
+
+ // construction/destruction
+ audit_record(const rom_entry &media, media_type type);
+ audit_record(const char *name, media_type type);
+
+ // getters
+ audit_record *next() const { return m_next; }
+ media_type type() const { return m_type; }
+ audit_status status() const { return m_status; }
+ audit_substatus substatus() const { return m_substatus; }
+ const char *name() const { return m_name; }
+ UINT64 expected_length() const { return m_explength; }
+ UINT64 actual_length() const { return m_length; }
+ const hash_collection &expected_hashes() const { return m_exphashes; }
+ const hash_collection &actual_hashes() const { return m_hashes; }
+
+ // setters
+ void set_status(audit_status status, audit_substatus substatus)
+ {
+ m_status = status;
+ m_substatus = substatus;
+ }
+
+ void set_actual(const hash_collection &hashes, UINT64 length = 0)
+ {
+ m_hashes = hashes;
+ m_length = length;
+ }
+
+private:
+ // internal state
+ audit_record * m_next;
+ media_type m_type; /* type of item that was audited */
+ audit_status m_status; /* status of audit on this item */
+ audit_substatus m_substatus; /* finer-detail status */
+ const char * m_name; /* name of item */
+ UINT64 m_explength; /* expected length of item */
+ UINT64 m_length; /* actual length of item */
+ hash_collection m_exphashes; /* expected hash data */
+ hash_collection m_hashes; /* actual hash information */
};
+// ======================> media_auditor
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-int audit_images(emu_options &options, const game_driver *gamedrv, const char *validation, audit_record **audit);
-int audit_samples(emu_options &options, const game_driver *gamedrv, audit_record **audit);
-int audit_summary(const game_driver *gamedrv, int count, const audit_record *records, int output);
+// class which manages auditing of items
+class media_auditor
+{
+public:
+ // summary values
+ enum summary
+ {
+ CORRECT = 0,
+ NONE_NEEDED,
+ BEST_AVAILABLE,
+ INCORRECT,
+ NOTFOUND
+ };
+
+ // construction/destruction
+ media_auditor(const driver_enumerator &enumerator);
+
+ // getters
+ audit_record *first() const { return m_record_list.first(); }
+ int count() const { return m_record_list.count(); }
+
+ // audit operations
+ summary audit_media(const char *validation = AUDIT_VALIDATE_FULL);
+ summary audit_samples();
+ summary summarize(astring *output = NULL);
+
+private:
+ // internal helpers
+ audit_record *audit_one_rom(const rom_entry *rom);
+ audit_record *audit_one_disk(const rom_entry *rom);
+ void compute_status(audit_record &record, const rom_entry *rom, bool found);
+ int also_used_by_parent(const hash_collection &romhashes);
+
+ // internal state
+ simple_list<audit_record> m_record_list;
+ const driver_enumerator & m_enumerator;
+ const char * m_validation;
+ const char * m_searchpath;
+};
#endif /* __AUDIT_H__ */
diff --git a/src/emu/clifront.c b/src/emu/clifront.c
index 81435650c34..6035aa0e77f 100644
--- a/src/emu/clifront.c
+++ b/src/emu/clifront.c
@@ -56,42 +56,6 @@
#endif
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-struct romident_status
-{
- int total; /* total files processed */
- int matches; /* number of matches found */
- int nonroms; /* number of non-ROM files found */
-};
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static void execute_commands(cli_options &options, const char *exename);
-static void display_help(void);
-
-/* informational functions */
-static void info_verifyroms(emu_options &options, const char *gamename);
-static void info_verifysamples(emu_options &options, const char *gamename);
-static void info_romident(emu_options &options, const char *gamename);
-static void info_listmedia(emu_options &options, const char *gamename);
-static void info_listsoftware(emu_options &options, const char *gamename);
-
-/* utilities */
-static void romident(emu_options &options, const char *filename, romident_status *status);
-static void identify_file(emu_options &options, const char *name, romident_status *status);
-static void identify_data(emu_options &options, const char *name, const UINT8 *data, int length, romident_status *status);
-static void match_roms(emu_options &options, const hash_collection &hashes, int length, int *found);
-static void display_suggestions(const char *gamename);
-
-
-
//**************************************************************************
// COMMAND-LINE OPTIONS
//**************************************************************************
@@ -146,45 +110,55 @@ cli_options::cli_options()
-/***************************************************************************
- CORE IMPLEMENTATION
-***************************************************************************/
+//**************************************************************************
+// CLI FRONTEND
+//**************************************************************************
+
+//-------------------------------------------------
+// cli_frontend - constructor
+//-------------------------------------------------
+
+cli_frontend::cli_frontend(cli_options &options, osd_interface &osd)
+ : m_options(options),
+ m_osd(osd),
+ m_result(MAMERR_NONE)
+{
+ // begin tracking memory
+ track_memory(true);
+}
+
+
+//-------------------------------------------------
+// ~cli_frontend - destructor
+//-------------------------------------------------
-static void display_suggestions(const char *gamename)
+cli_frontend::~cli_frontend()
{
- const game_driver *matches[10];
- int drvnum;
-
- /* get the top 10 approximate matches */
- driver_list_get_approx_matches(drivers, gamename, ARRAY_LENGTH(matches), matches);
-
- /* print them out */
- fprintf(stderr, "\n\"%s\" approximately matches the following\n"
- "supported " GAMESNOUN " (best match first):\n\n", gamename);
- for (drvnum = 0; drvnum < ARRAY_LENGTH(matches); drvnum++)
- if (matches[drvnum] != NULL)
- fprintf(stderr, "%-18s%s\n", matches[drvnum]->name, matches[drvnum]->description);
+ // report any unfreed memory on clean exits
+ track_memory(false);
+ if (m_result == MAMERR_NONE)
+ dump_unfreed_mem();
}
//-------------------------------------------------
-// cli_execute - execute a game via the standard
+// execute - execute a game via the standard
// command line interface
//-------------------------------------------------
-int cli_execute(cli_options &options, osd_interface &osd, int argc, char **argv)
+int cli_frontend::execute(int argc, char **argv)
{
// wrap the core execution in a try/catch to field all fatal errors
- int result = MAMERR_NONE;
+ m_result = MAMERR_NONE;
try
{
// parse the command line, adding any system-specific options
astring option_errors;
- if (!options.parse_command_line(argc, argv, option_errors))
+ if (!m_options.parse_command_line(argc, argv, option_errors))
{
// if we failed, check for no command and a system name first; in that case error on the name
- if (strlen(options.command()) == 0 && options.system() == NULL && strlen(options.system_name()) > 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "Unknown system '%s'", options.system_name());
+ if (strlen(m_options.command()) == 0 && m_options.system() == NULL && strlen(m_options.system_name()) > 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
// otherwise, error on the options
throw emu_fatalerror(MAMERR_INVALID_CONFIG, "%s", option_errors.trimspace().cstr());
@@ -197,19 +171,19 @@ int cli_execute(cli_options &options, osd_interface &osd, int argc, char **argv)
core_filename_extract_base(&exename, argv[0], TRUE);
// if we have a command, execute that
- if (strlen(options.command()) != 0)
- execute_commands(options, exename);
+ if (strlen(m_options.command()) != 0)
+ execute_commands(exename);
// otherwise, check for a valid system
else
{
// if we can't find it, give an appropriate error
- const game_driver *system = options.system();
- if (system == NULL && strlen(options.system_name()) > 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "Unknown system '%s'", options.system_name());
+ const game_driver *system = m_options.system();
+ if (system == NULL && strlen(m_options.system_name()) > 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
// otherwise just run the game
- result = mame_execute(options, osd);
+ m_result = mame_execute(m_options, m_osd);
}
}
@@ -218,577 +192,605 @@ int cli_execute(cli_options &options, osd_interface &osd, int argc, char **argv)
{
astring string(fatal.string());
fprintf(stderr, "%s\n", string.trimspace().cstr());
- result = (fatal.exitcode() != 0) ? fatal.exitcode() : MAMERR_FATALERROR;
+ m_result = (fatal.exitcode() != 0) ? fatal.exitcode() : MAMERR_FATALERROR;
// if a game was specified, wasn't a wildcard, and our error indicates this was the
// reason for failure, offer some suggestions
- if (result == MAMERR_NO_SUCH_GAME && strlen(options.system_name()) > 0 && strchr(options.system_name(), '*') == NULL && options.system() == NULL)
- display_suggestions(options.system_name());
+ if (m_result == MAMERR_NO_SUCH_GAME && strlen(m_options.system_name()) > 0 && strchr(m_options.system_name(), '*') == NULL && m_options.system() == NULL)
+ {
+ // get the top 10 approximate matches
+ driver_enumerator drivlist(m_options);
+ int matches[10];
+ drivlist.find_approximate_matches(m_options.system_name(), ARRAY_LENGTH(matches), matches);
+
+ // print them out
+ fprintf(stderr, "\n\"%s\" approximately matches the following\n"
+ "supported " GAMESNOUN " (best match first):\n\n", m_options.system_name());
+ for (int matchnum = 0; matchnum < ARRAY_LENGTH(matches); matchnum++)
+ if (matches[matchnum] != -1)
+ fprintf(stderr, "%-18s%s\n", drivlist.driver(matches[matchnum]).name, drivlist.driver(matches[matchnum]).description);
+ }
}
catch (emu_exception &)
{
fprintf(stderr, "Caught unhandled emulator exception\n");
- result = MAMERR_FATALERROR;
+ m_result = MAMERR_FATALERROR;
}
catch (std::bad_alloc &)
{
fprintf(stderr, "Out of memory!\n");
- result = MAMERR_FATALERROR;
+ m_result = MAMERR_FATALERROR;
}
// handle any other exceptions
catch (...)
{
fprintf(stderr, "Caught unhandled exception\n");
- result = MAMERR_FATALERROR;
+ m_result = MAMERR_FATALERROR;
}
- // report any unfreed memory on clean exits
- if (result == MAMERR_NONE)
- dump_unfreed_mem();
- return result;
+ return m_result;
}
//-------------------------------------------------
-// execute_commands - execute various frontend
-// commands
+// listxml - output the XML data for one or more
+// games
//-------------------------------------------------
-static void execute_commands(cli_options &options, const char *exename)
+void cli_frontend::listxml(const char *gamename)
{
- // help?
- if (strcmp(options.command(), CLICOMMAND_HELP) == 0)
- {
- display_help();
- return;
- }
-
- // showusage?
- if (strcmp(options.command(), CLICOMMAND_SHOWUSAGE) == 0)
- {
- astring helpstring;
-#ifndef MESS
- mame_printf_info("Usage: %s [%s] [options]\n\nOptions:\n%s", exename, GAMENOUN, options.output_help(helpstring));
-#else
- mame_printf_info("Usage: %s [%s] [media] [software] [options]\n\nOptions:\n%s", exename, GAMENOUN, options.output_help(helpstring));
-#endif
- return;
- }
-
- // validate?
- if (strcmp(options.command(), CLICOMMAND_VALIDATE) == 0)
- {
- validate_drivers(options);
- return;
- }
-
- // other commands need the INIs parsed
- astring option_errors;
- options.parse_standard_inis(option_errors);
- if (option_errors)
- printf("%s\n", option_errors.cstr());
-
- // createconfig?
- if (strcmp(options.command(), CLICOMMAND_CREATECONFIG) == 0)
- {
- // attempt to open the output file
- emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(CONFIGNAME ".ini") != FILERR_NONE)
- throw emu_fatalerror("Unable to create file " CONFIGNAME ".ini\n");
-
- // generate the updated INI
- astring initext;
- file.puts(options.output_ini(initext));
- return;
- }
-
- // showconfig?
- if (strcmp(options.command(), CLICOMMAND_SHOWCONFIG) == 0)
- {
- // print the INI text
- astring initext;
- printf("%s\n", options.output_ini(initext));
- return;
- }
-
- // all other commands call out to one of these helpers
- static const struct
- {
- const char *option;
- void (*function)(emu_options &options, const char *gamename);
- } info_commands[] =
- {
- { CLICOMMAND_LISTXML, cli_info_listxml },
- { CLICOMMAND_LISTFULL, cli_info_listfull },
- { CLICOMMAND_LISTSOURCE, cli_info_listsource },
- { CLICOMMAND_LISTCLONES, cli_info_listclones },
- { CLICOMMAND_LISTBROTHERS, cli_info_listbrothers },
- { CLICOMMAND_LISTCRC, cli_info_listcrc },
- { CLICOMMAND_LISTDEVICES, cli_info_listdevices },
- { CLICOMMAND_LISTROMS, cli_info_listroms },
- { CLICOMMAND_LISTSAMPLES, cli_info_listsamples },
- { CLICOMMAND_VERIFYROMS, info_verifyroms },
- { CLICOMMAND_VERIFYSAMPLES, info_verifysamples },
- { CLICOMMAND_LISTMEDIA, info_listmedia },
- { CLICOMMAND_LISTSOFTWARE, info_listsoftware },
- { CLICOMMAND_ROMIDENT, info_romident }
- };
-
- // find the command
- for (int cmdindex = 0; cmdindex < ARRAY_LENGTH(info_commands); cmdindex++)
- if (strcmp(options.command(), info_commands[cmdindex].option) == 0)
- {
- // parse any relevant INI files before proceeding
- const char *sysname = options.system_name();
- (*info_commands[cmdindex].function)(options, (sysname[0] == 0) ? "*" : sysname);
- return;
- }
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- // if we get here, we don't know what has been requested
- throw emu_fatalerror(MAMERR_INVALID_CONFIG, "Unknown command '%s' specified", options.command());
+ // create the XML and print it to stdout
+ info_xml_creator creator(drivlist);
+ creator.output(stdout);
}
-/*-------------------------------------------------
- display_help - display help to standard
- output
--------------------------------------------------*/
-
-static void display_help(void)
+//-------------------------------------------------
+// listfull - output the name and description of
+// one or more games
+//-------------------------------------------------
+
+void cli_frontend::listfull(const char *gamename)
{
-#ifndef MESS
- mame_printf_info("M.A.M.E. v%s - Multiple Arcade Machine Emulator\n"
- "Copyright Nicola Salmoria and the MAME Team\n\n", build_version);
- mame_printf_info("%s\n", mame_disclaimer);
- mame_printf_info("Usage: MAME gamename [options]\n\n"
- " MAME -showusage for a brief list of options\n"
- " MAME -showconfig for a list of configuration options\n"
- " MAME -createconfig to create a " CONFIGNAME ".ini\n\n"
- "For usage instructions, please consult the file windows.txt\n");
-#else
- mess_display_help();
-#endif
-}
-
-
-
-/***************************************************************************
- INFORMATIONAL FUNCTIONS
-***************************************************************************/
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
-/*-------------------------------------------------
- cli_info_listxml - output the XML data for one
- or more games
--------------------------------------------------*/
+ // print the header
+ mame_printf_info("Name: Description:\n");
-void cli_info_listxml(emu_options &options, const char *gamename)
-{
- print_mame_xml(stdout, drivers, gamename, options);
+ // iterate through drivers and output the info
+ while (drivlist.next())
+ if ((drivlist.driver().flags & GAME_NO_STANDALONE) == 0)
+ mame_printf_info("%-18s\"%s\"\n", drivlist.driver().name, drivlist.driver().description);
}
-/*-------------------------------------------------
- cli_info_listfull - output the name and
- description of one or more games
--------------------------------------------------*/
+//-------------------------------------------------
+// listsource - output the name and source
+// filename of one or more games
+//-------------------------------------------------
-void cli_info_listfull(emu_options &options, const char *gamename)
+void cli_frontend::listsource(const char *gamename)
{
- int count = 0;
-
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if ((drivers[drvindex]->flags & GAME_NO_STANDALONE) == 0 && mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- /* print the header on the first one */
- if (count == 0)
- mame_printf_info("Name: Description:\n");
-
- /* output the remaining information */
- mame_printf_info("%-18s\"%s\"\n", drivers[drvindex]->name, drivers[drvindex]->description);
- count++;
- }
-
- /* return an error if none found */
- if (count == 0)
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate through drivers and output the info
+ astring filename;
+ while (drivlist.next())
+ mame_printf_info("%-16s %s\n", drivlist.driver().name, core_filename_extract_base(&filename, drivlist.driver().source_file, FALSE)->cstr());
}
-/*-------------------------------------------------
- cli_info_listsource - output the name and source
- filename of one or more games
--------------------------------------------------*/
+//-------------------------------------------------
+// listclones - output the name and parent of all
+// clones matching the given pattern
+//-------------------------------------------------
-void cli_info_listsource(emu_options &options, const char *gamename)
+void cli_frontend::listclones(const char *gamename)
{
- int count = 0;
- astring filename;
+ // start with a filtered list of drivers
+ driver_enumerator drivlist(m_options, gamename);
+ int original_count = drivlist.count();
+
+ // iterate through the remaining ones to see if their parent matches
+ while (drivlist.next_excluded())
+ {
+ // if we have a non-bios clone and it matches, keep it
+ int clone_of = drivlist.clone();
+ if (clone_of != -1 && (drivlist.driver(clone_of).flags & GAME_IS_BIOS_ROOT) == 0)
+ if (drivlist.matches(gamename, drivlist.driver(clone_of).name))
+ drivlist.include();
+ }
+
+ // return an error if none found
+ if (drivlist.count() == 0)
+ {
+ // see if we match but just weren't a clone
+ if (original_count == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+ else
+ mame_printf_info("Found %d matches for '%s' but none were clones\n", drivlist.count(), gamename);
+ return;
+ }
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- /* output the remaining information */
- mame_printf_info("%-16s %s\n", drivers[drvindex]->name, core_filename_extract_base(&filename, drivers[drvindex]->source_file, FALSE)->cstr());
- count++;
- }
+ // print the header
+ mame_printf_info("Name: Clone of:\n");
- /* return an error if none found */
- if (count == 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+ // iterate through drivers and output the info
+ drivlist.reset();
+ while (drivlist.next())
+ {
+ int clone_of = drivlist.clone();
+ if (clone_of != -1)
+ mame_printf_info("%-16s %-8s\n", drivlist.driver().name, drivlist.driver(clone_of).name);
+ }
}
-/*-------------------------------------------------
- cli_info_listclones - output the name and source
- filename of one or more games
--------------------------------------------------*/
+//-------------------------------------------------
+// listbrothers - for each matching game, output
+// the list of other games that share the same
+// source file
+//-------------------------------------------------
-void cli_info_listclones(emu_options &options, const char *gamename)
+void cli_frontend::listbrothers(const char *gamename)
{
- int count = 0, drvcnt = 0;
-
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- drvcnt++;
-
- if (drvcnt == 0)
+ // start with a filtered list of drivers; return an error if none found
+ driver_enumerator initial_drivlist(m_options, gamename);
+ if (initial_drivlist.count() == 0)
throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- {
- const game_driver *clone_of = driver_get_clone(drivers[drvindex]);
+ // for the final list, start with an empty driver list
+ driver_enumerator drivlist(m_options);
+ drivlist.exclude_all();
- /* if we are a clone, and either our name matches the gamename, or the clone's name matches, display us */
- if (clone_of != NULL && (clone_of->flags & GAME_IS_BIOS_ROOT) == 0)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0 || mame_strwildcmp(gamename, clone_of->name) == 0)
- {
- /* print the header on the first one */
- if (count == 0)
- mame_printf_info("Name: Clone of:\n");
+ // scan through the initially-selected drivers
+ while (initial_drivlist.next())
+ {
+ // if we are already marked in the final list, we don't need to do anything
+ if (drivlist.included(initial_drivlist.current()))
+ continue;
+
+ // otherwise, walk excluded items in the final list and mark any that match
+ drivlist.reset();
+ while (drivlist.next_excluded())
+ if (strcmp(drivlist.driver().source_file, initial_drivlist.driver().source_file) == 0)
+ drivlist.include();
+ }
+
+ // print the header
+ mame_printf_info("Source file: Name: Parent:\n");
- /* output the remaining information */
- mame_printf_info("%-16s %-8s\n", drivers[drvindex]->name, clone_of->name);
- count++;
- }
+ // output the entries found
+ drivlist.reset();
+ astring filename;
+ while (drivlist.next())
+ {
+ int clone_of = drivlist.clone();
+ mame_printf_info("%-16s %-16s %-16s\n", core_filename_extract_base(&filename, drivlist.driver().source_file, FALSE)->cstr(), drivlist.driver().name, (clone_of == -1 ? "" : drivlist.driver(clone_of).name));
}
}
-/*-------------------------------------------------
- cli_info_listbrothers - output the name and
- source filename of one or more games
--------------------------------------------------*/
+//-------------------------------------------------
+// listcrc - output the CRC and name of all ROMs
+// referenced by the emulator
+//-------------------------------------------------
-void cli_info_listbrothers(emu_options &options, const char *gamename)
+void cli_frontend::listcrc(const char *gamename)
{
- UINT8 *didit = global_alloc_array_clear(UINT8, driver_list_get_count(drivers));
- int count = 0;
- astring filename;
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (!didit[drvindex] && mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- didit[drvindex] = TRUE;
- if (count > 0)
- mame_printf_info("\n");
- mame_printf_info("%s ... other drivers in %s:\n", drivers[drvindex]->name, core_filename_extract_base(&filename, drivers[drvindex]->source_file, FALSE)->cstr());
-
- /* now iterate again over drivers, finding those with the same source file */
- for (int matchindex = 0; drivers[matchindex]; matchindex++)
- if (matchindex != drvindex && strcmp(drivers[drvindex]->source_file, drivers[matchindex]->source_file) == 0)
+ // iterate through matches, and then through ROMs
+ while (drivlist.next())
+ for (const rom_source *source = rom_first_source(drivlist.config()); source != NULL; source = rom_next_source(*source))
+ for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
{
- const char *matchstring = (mame_strwildcmp(gamename, drivers[matchindex]->name) == 0) ? "-> " : " ";
- const game_driver *clone_of = driver_get_clone(drivers[matchindex]);
-
- if (clone_of != NULL && (clone_of->flags & GAME_IS_BIOS_ROOT) == 0)
- mame_printf_info("%s%-16s [%s]\n", matchstring, drivers[matchindex]->name, clone_of->name);
- else
- mame_printf_info("%s%s\n", matchstring, drivers[matchindex]->name);
- didit[matchindex] = TRUE;
+ // if we have a CRC, display it
+ UINT32 crc;
+ if (hash_collection(ROM_GETHASHDATA(rom)).crc(crc))
+ mame_printf_info("%08x %-16s %s\n", crc, ROM_GETNAME(rom), drivlist.driver().description);
}
-
- count++;
- }
-
- /* return an error if none found */
- global_free(didit);
- if (count == 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
}
-/*-------------------------------------------------
- cli_info_listcrc - output the CRC and name of
- all ROMs referenced by MAME
--------------------------------------------------*/
+//-------------------------------------------------
+// listroms - output the list of ROMs referenced
+// by a given game or set of games
+//-------------------------------------------------
-void cli_info_listcrc(emu_options &options, const char *gamename)
+void cli_frontend::listroms(const char *gamename)
{
- int count = 0;
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- machine_config config(*drivers[drvindex], options);
- const rom_entry *region, *rom;
- const rom_source *source;
-
- /* iterate over sources, regions, and then ROMs within the region */
- for (source = rom_first_source(config); source != NULL; source = rom_next_source(*source))
- for (region = rom_first_region(*source); region; region = rom_next_region(region))
- for (rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ // iterate through matches
+ astring tempstr;
+ bool first = true;
+ while (drivlist.next())
+ {
+ // print a header
+ if (!first)
+ mame_printf_info("\n");
+ first = false;
+ mame_printf_info("ROMs required for driver \"%s\".\n"
+ "Name Size Checksum\n", drivlist.driver().name);
+
+ // iterate through roms
+ for (const rom_source *source = rom_first_source(drivlist.config()); source != NULL; source = rom_next_source(*source))
+ for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ // accumulate the total length of all chunks
+ int length = -1;
+ if (ROMREGION_ISROMDATA(region))
+ length = rom_file_size(rom);
+
+ // start with the name
+ const char *name = ROM_GETNAME(rom);
+ mame_printf_info("%-20s ", name);
+
+ // output the length next
+ if (length >= 0)
+ mame_printf_info("%7d", length);
+ else
+ mame_printf_info(" ");
+
+ // output the hash data
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
{
- /* if we have a CRC, display it */
- UINT32 crc;
- if (hash_collection(ROM_GETHASHDATA(rom)).crc(crc))
- mame_printf_info("%08x %-12s %s\n", crc, ROM_GETNAME(rom), drivers[drvindex]->description);
+ if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
+ mame_printf_info(" BAD");
+ mame_printf_info(" %s", hashes.macro_string(tempstr));
}
+ else
+ mame_printf_info(" NO GOOD DUMP KNOWN");
- count++;
- }
-
- /* return an error if none found */
- if (count == 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+ // end with a CR
+ mame_printf_info("\n");
+ }
+ }
}
-/*-------------------------------------------------
- cli_info_listroms - output the list of ROMs
- referenced by a given game or set of games
--------------------------------------------------*/
+//-------------------------------------------------
+// listsamples - output the list of samples
+// referenced by a given game or set of games
+//-------------------------------------------------
-void cli_info_listroms(emu_options &options, const char *gamename)
+void cli_frontend::listsamples(const char *gamename)
{
- int count = 0;
- astring tempstr;
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- machine_config config(*drivers[drvindex], options);
-
- /* print the header */
- if (count > 0)
- mame_printf_info("\n");
- mame_printf_info("This is the list of the ROMs required for driver \"%s\".\n"
- "Name Size Checksum\n", drivers[drvindex]->name);
-
- /* iterate over sources, regions and then ROMs within the region */
- for (const rom_source *source = rom_first_source(config); source != NULL; source = rom_next_source(*source))
- for (const rom_entry *region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
- for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
- {
- /* accumulate the total length of all chunks */
- int length = -1;
- if (ROMREGION_ISROMDATA(region))
- length = rom_file_size(rom);
-
- /* start with the name */
- const char *name = ROM_GETNAME(rom);
- mame_printf_info("%-20s ", name);
-
- /* output the length next */
- if (length >= 0)
- mame_printf_info("%7d", length);
- else
- mame_printf_info(" ");
-
- /* output the hash data */
- hash_collection hashes(ROM_GETHASHDATA(rom));
- if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
- {
- if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
- mame_printf_info(" BAD");
- mame_printf_info(" %s", hashes.macro_string(tempstr));
- }
- else
- mame_printf_info(" NO GOOD DUMP KNOWN");
+ // iterate over drivers, looking for SAMPLES devices
+ bool first = true;
+ while (drivlist.next())
+ {
+ // see if we have samples
+ const device_config *devconfig;
+ for (devconfig = drivlist.config().first_device(); devconfig != NULL; devconfig = devconfig->next())
+ if (devconfig->type() == SAMPLES)
+ break;
+ if (devconfig == NULL)
+ continue;
+
+ // print a header
+ if (!first)
+ mame_printf_info("\n");
+ first = false;
+ mame_printf_info("Samples required for driver \"%s\".\n", drivlist.driver().name);
+
+ // iterate over samples devices
+ for ( ; devconfig != NULL; devconfig = devconfig->next())
+ if (devconfig->type() == SAMPLES)
+ {
+ // if the list is legit, walk it and print the sample info
+ const char *const *samplenames = reinterpret_cast<const samples_interface *>(devconfig->static_config())->samplenames;
+ if (samplenames != NULL)
+ for (int sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
+ if (samplenames[sampnum][0] != '*')
+ mame_printf_info("%s\n", samplenames[sampnum]);
+ }
+ }
+}
- /* end with a CR */
- mame_printf_info("\n");
- }
- count++;
- }
+//-------------------------------------------------
+// listdevices - output the list of devices
+// referenced by a given game or set of games
+//-------------------------------------------------
- if (count == 0)
+void cli_frontend::listdevices(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate over drivers, looking for SAMPLES devices
+ bool first = true;
+ while (drivlist.next())
+ {
+ // print a header
+ if (!first)
+ printf("\n");
+ first = false;
+ printf("Driver %s (%s):\n", drivlist.driver().name, drivlist.driver().description);
+
+ // iterate through devices
+ for (const device_config *devconfig = drivlist.config().first_device(); devconfig != NULL; devconfig = devconfig->next())
+ {
+ printf(" %s ('%s')", devconfig->name(), devconfig->tag());
+
+ UINT32 clock = devconfig->clock();
+ if (clock >= 1000000000)
+ printf(" @ %d.%02d GHz\n", clock / 1000000000, (clock / 10000000) % 100);
+ else if (clock >= 1000000)
+ printf(" @ %d.%02d MHz\n", clock / 1000000, (clock / 10000) % 100);
+ else if (clock >= 1000)
+ printf(" @ %d.%02d kHz\n", clock / 1000, (clock / 10) % 100);
+ else if (clock > 0)
+ printf(" @ %d Hz\n", clock);
+ else
+ printf("\n");
+ }
+ }
}
-/*-------------------------------------------------
- cli_info_listsamples - output the list of samples
- referenced by a given game or set of games
--------------------------------------------------*/
+//-------------------------------------------------
+// listmedia - output the list of image devices
+// referenced by a given game or set of games
+//-------------------------------------------------
-void cli_info_listsamples(emu_options &options, const char *gamename)
+void cli_frontend::listmedia(const char *gamename)
{
- int count = 0;
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- machine_config config(*drivers[drvindex], options);
- const device_config_sound_interface *sound = NULL;
+ // print header
+ printf(" SYSTEM MEDIA NAME (brief) IMAGE FILE EXTENSIONS SUPPORTED \n");
+ printf("---------- -------------------- ------------------------------------\n");
- /* find samples interfaces */
- 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;
- int sampnum;
+ // iterate over drivers
+ while (drivlist.next())
+ {
+ // iterate
+ const device_config_image_interface *imagedev = NULL;
+ bool first = true;
+ for (bool gotone = drivlist.config().m_devicelist.first(imagedev); gotone; gotone = imagedev->next(imagedev))
+ {
+ // extract the shortname with parentheses
+ astring paren_shortname;
+ paren_shortname.format("(%s)", imagedev->brief_instance_name());
- /* if the list is legit, walk it and print the sample info */
- if (samplenames != NULL)
- for (sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
- mame_printf_info("%s\n", samplenames[sampnum]);
- }
+ // output the line, up to the list of extensions
+ printf("%-13s%-12s%-8s ", first ? drivlist.driver().name : "", imagedev->instance_name(), paren_shortname.cstr());
- count++;
+ // get the extensions and print them
+ astring extensions(imagedev->file_extensions());
+ for (int start = 0, end = extensions.chr(0, ','); ; start = end + 1, end = extensions.chr(start, ','))
+ {
+ astring curext(extensions, start, (end == -1) ? -1 : end - 1);
+ printf(".%-5s", curext.cstr());
+ if (end == -1)
+ break;
+ }
+
+ // end the line
+ printf("\n");
+ first = false;
}
-
- if (count == 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // if we didn't get any at all, just print a none line
+ if (first)
+ printf("%-13s(none)\n", drivlist.driver().name);
+ }
}
-/*-------------------------------------------------
- cli_info_listdevices - output the list of
- devices referenced by a given game or set of
- games
--------------------------------------------------*/
+//-------------------------------------------------
+// verifyroms - verify the ROM sets of one or
+// more games
+//-------------------------------------------------
-void cli_info_listdevices(emu_options &options, const char *gamename)
+void cli_frontend::verifyroms(const char *gamename)
{
- int count = 0;
-
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- machine_config config(*drivers[drvindex], options);
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- if (count != 0)
- printf("\n");
- printf("Driver %s (%s):\n", drivers[drvindex]->name, drivers[drvindex]->description);
+ int correct = 0;
+ int incorrect = 0;
+ int notfound = 0;
- /* iterate through devices */
- for (const device_config *devconfig = config.m_devicelist.first(); devconfig != NULL; devconfig = devconfig->next())
+ // iterate over drivers
+ media_auditor auditor(drivlist);
+ while (drivlist.next())
+ {
+ // audit the ROMs in this set
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // output the summary of the audit
+ astring summary_string;
+ auditor.summarize(&summary_string);
+ mame_printf_info("%s", summary_string.cstr());
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ notfound++;
+
+ // else display information about what we discovered
+ else
+ {
+ // output the name of the driver and its clone
+ mame_printf_info("romset %s ", drivlist.driver().name);
+ int clone_of = drivlist.clone();
+ if (clone_of != -1)
+ mame_printf_info("[%s] ", drivlist.driver(clone_of).name);
+
+ // switch off of the result
+ switch (summary)
{
- printf(" %s ('%s')", devconfig->name(), devconfig->tag());
-
- UINT32 clock = devconfig->clock();
- if (clock >= 1000000000)
- printf(" @ %d.%02d GHz\n", clock / 1000000000, (clock / 10000000) % 100);
- else if (clock >= 1000000)
- printf(" @ %d.%02d MHz\n", clock / 1000000, (clock / 10000) % 100);
- else if (clock >= 1000)
- printf(" @ %d.%02d kHz\n", clock / 1000, (clock / 10) % 100);
- else if (clock > 0)
- printf(" @ %d Hz\n", clock);
- else
- printf("\n");
+ case media_auditor::INCORRECT:
+ mame_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ mame_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ mame_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
}
-
- count++;
}
+ }
- if (count == 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+ // clear out any cached files
+ zip_file_cache_clear();
+
+ // if we didn't get anything at all, display a generic end message
+ if (correct + incorrect == 0)
+ {
+ if (notfound > 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "romset \"%s\" not found!\n", gamename);
+ else
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "romset \"%s\" not supported!\n", gamename);
+ }
+
+ // otherwise, print a summary
+ else
+ {
+ if (incorrect > 0)
+ throw emu_fatalerror(MAMERR_MISSING_FILES, "%d romsets found, %d were OK.\n", correct + incorrect, correct);
+ mame_printf_info("%d romsets found, %d were OK.\n", correct, correct);
+ }
}
-/*-------------------------------------------------
- info_verifyroms - verify the ROM sets of
- one or more games
--------------------------------------------------*/
+//-------------------------------------------------
+// info_verifysamples - verify the sample sets of
+// one or more games
+//-------------------------------------------------
-static void info_verifyroms(emu_options &options, const char *gamename)
+void cli_frontend::verifysamples(const char *gamename)
{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
int correct = 0;
int incorrect = 0;
int notfound = 0;
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
+ // iterate over drivers
+ media_auditor auditor(drivlist);
+ while (drivlist.next())
+ {
+ // audit the samples in this set
+ media_auditor::summary summary = auditor.audit_samples();
+
+ // output the summary of the audit
+ astring summary_string;
+ auditor.summarize(&summary_string);
+ mame_printf_info("%s", summary_string.cstr());
+
+ // if not found, print a message and set the flag
+ if (summary == media_auditor::NOTFOUND)
{
- audit_record *audit;
- int audit_records;
- int res;
-
- /* audit the ROMs in this set */
- audit_records = audit_images(options, drivers[drvindex], AUDIT_VALIDATE_FAST, &audit);
- res = audit_summary(drivers[drvindex], audit_records, audit, TRUE);
- if (audit_records > 0)
- global_free(audit);
-
- /* if not found, count that and leave it at that */
- if (res == NOTFOUND)
- notfound++;
+ mame_printf_error("sampleset \"%s\" not found!\n", drivlist.driver().name);
+ notfound++;
+ }
- /* else display information about what we discovered */
- else
+ // else display information about what we discovered
+ else
+ {
+ // output the name of the driver and its clone
+ mame_printf_info("sampleset %s ", drivlist.driver().name);
+ int clone_of = drivlist.clone();
+ if (clone_of != -1)
+ mame_printf_info("[%s] ", drivlist.driver(clone_of).name);
+
+ // switch off of the result
+ switch (summary)
{
- const game_driver *clone_of;
-
- /* output the name of the driver and its clone */
- mame_printf_info("romset %s ", drivers[drvindex]->name);
- clone_of = driver_get_clone(drivers[drvindex]);
- if (clone_of != NULL)
- mame_printf_info("[%s] ", clone_of->name);
-
- /* switch off of the result */
- switch (res)
- {
- case INCORRECT:
- mame_printf_info("is bad\n");
- incorrect++;
- break;
-
- case CORRECT:
- mame_printf_info("is good\n");
- correct++;
- break;
-
- case BEST_AVAILABLE:
- mame_printf_info("is best available\n");
- correct++;
- break;
- }
+ case media_auditor::INCORRECT:
+ mame_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ mame_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ mame_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
}
}
+ }
- /* clear out any cached files */
+ // clear out any cached files
zip_file_cache_clear();
- /* if we didn't get anything at all, display a generic end message */
+ // if we didn't get anything at all, display a generic end message
if (correct + incorrect == 0)
{
if (notfound > 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "romset \"%s\" not found!\n", gamename);
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "sampleset \"%s\" not found!\n", gamename);
else
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "romset \"%s\" not supported!\n", gamename);
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "sampleset \"%s\" not supported!\n", gamename);
}
- /* otherwise, print a summary */
+ // otherwise, print a summary
else
{
if (incorrect > 0)
- throw emu_fatalerror(MAMERR_MISSING_FILES, "%d romsets found, %d were OK.\n", correct + incorrect, correct);
- mame_printf_info("%d romsets found, %d were OK.\n", correct, correct);
+ throw emu_fatalerror(MAMERR_MISSING_FILES, "%d samplesets found, %d were OK.\n", correct + incorrect, correct);
+ mame_printf_info("%d samplesets found, %d were OK.\n", correct, correct);
}
}
+
+
+#if 0
/*-------------------------------------------------
info_listsoftware - output the list of
software supported by a given game or set of
@@ -798,37 +800,31 @@ static void info_verifyroms(emu_options &options, const char *gamename)
identifying duplicate lists.
-------------------------------------------------*/
-static void info_listsoftware(emu_options &options, const char *gamename)
+static void info_listsoftware(const char *gamename)
{
FILE *out = stdout;
- int nr_lists = 0;
- char ** lists = NULL;
- int list_idx = 0;
- /* First determine the maximum number of lists we might encounter */
- for ( int drvindex = 0; drivers[drvindex] != NULL; drvindex++ )
- {
- if ( mame_strwildcmp( gamename, drivers[drvindex]->name ) == 0 )
- {
- /* allocate the machine config */
- machine_config config(*drivers[drvindex], options);
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- for (const device_config *dev = 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();
+ // first determine the maximum number of lists we might encounter
+ int list_count = 0;
+ while (drivlist.next())
+ for (const device_config *dev = 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] && *swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM))
- nr_lists++;
- }
- }
+ for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++)
+ if (swlist->list_name[listnum] && *swlist->list_name[listnum] && swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)
+ list_count++;
}
- }
- lists = global_alloc_array( char *, nr_lists );
+ // allocate a list
+ astring *lists = global_alloc_array(astring, list_count);
- if (nr_lists)
+ if (list_count)
{
fprintf( out,
"<?xml version=\"1.0\"?>\n"
@@ -902,664 +898,602 @@ static void info_listsoftware(emu_options &options, const char *gamename)
);
}
- for ( int drvindex = 0; drivers[drvindex] != NULL; drvindex++ )
- {
- if ( mame_strwildcmp( gamename, drivers[drvindex]->name ) == 0 )
+ drivlist.reset();
+ list_count = 0;
+ while (drivlist.next())
+ for (const device_config *dev = drivlist.config().m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
{
- /* allocate the machine config */
- machine_config config(*drivers[drvindex], options);
+ software_list_config *swlist = (software_list_config *)downcast<const legacy_device_config_base *>(dev)->inline_config();
- for (const device_config *dev = config.m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
+ for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++)
{
- 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[listnum] && *swlist->list_name[listnum] && swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)
{
- if ( swlist->list_name[i] && *swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM))
+ software_list *list = software_list_open(m_options, swlist->list_name[listnum], FALSE, NULL);
+
+ if ( list )
{
- software_list *list = software_list_open( options, swlist->list_name[i], FALSE, NULL );
+ /* Verify if we have encountered this list before */
+ bool seen_before = false;
+ for (int seen_index = 0; seen_index < list_count && !seen_before; seen_index++)
+ if (lists[seen_index] == swlist->list_name[listnum])
+ seen_before = true;
- if ( list )
+ if (!seen_before)
{
- /* Verify if we have encountered this list before */
- bool seen_before = false;
- for ( int l = 0; l < list_idx && !seen_before; l++ )
- {
- if ( ! strcmp( swlist->list_name[i], lists[l] ) )
- {
- seen_before = true;
- }
- }
+ lists[list_count++] = swlist->list_name[i];
+ software_list_parse( list, NULL, NULL );
+
+ fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlist->list_name[i], xml_normalize_string(software_list_get_description(list)) );
- if ( ! seen_before )
+ for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) )
{
- lists[list_idx] = core_strdup( swlist->list_name[i] );
- list_idx++;
- software_list_parse( list, NULL, NULL );
+ fprintf( out, "\t\t<software name=\"%s\"", swinfo->shortname );
+ if ( swinfo->parentname != NULL )
+ fprintf( out, " cloneof=\"%s\"", swinfo->parentname );
+ if ( swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL )
+ fprintf( out, " supported=\"partial\"" );
+ if ( swinfo->supported == SOFTWARE_SUPPORTED_NO )
+ fprintf( out, " supported=\"no\"" );
+ fprintf( out, ">\n" );
+ fprintf( out, "\t\t\t<description>%s</description>\n", xml_normalize_string(swinfo->longname) );
+ fprintf( out, "\t\t\t<year>%s</year>\n", xml_normalize_string( swinfo->year ) );
+ fprintf( out, "\t\t\t<publisher>%s</publisher>\n", xml_normalize_string( swinfo->publisher ) );
+
+ for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) )
+ {
+ fprintf( out, "\t\t\t<part name=\"%s\"", part->name );
+ if ( part->interface_ )
+ fprintf( out, " interface=\"%s\"", part->interface_ );
- fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlist->list_name[i], xml_normalize_string(software_list_get_description(list)) );
+ fprintf( out, ">\n");
- for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) )
- {
- fprintf( out, "\t\t<software name=\"%s\"", swinfo->shortname );
- if ( swinfo->parentname != NULL )
- fprintf( out, " cloneof=\"%s\"", swinfo->parentname );
- if ( swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL )
- fprintf( out, " supported=\"partial\"" );
- if ( swinfo->supported == SOFTWARE_SUPPORTED_NO )
- fprintf( out, " supported=\"no\"" );
- fprintf( out, ">\n" );
- fprintf( out, "\t\t\t<description>%s</description>\n", xml_normalize_string(swinfo->longname) );
- fprintf( out, "\t\t\t<year>%s</year>\n", xml_normalize_string( swinfo->year ) );
- fprintf( out, "\t\t\t<publisher>%s</publisher>\n", xml_normalize_string( swinfo->publisher ) );
-
- for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) )
+ if ( part->featurelist )
{
- fprintf( out, "\t\t\t<part name=\"%s\"", part->name );
- if ( part->interface_ )
- fprintf( out, " interface=\"%s\"", part->interface_ );
+ feature_list *list = part->featurelist;
- fprintf( out, ">\n");
-
- if ( part->featurelist )
+ while( list )
{
- feature_list *list = part->featurelist;
-
- while( list )
- {
- fprintf( out, "\t\t\t\t<feature name=\"%s\" value=\"%s\" />\n", list->name, list->value );
- list = list->next;
- }
+ fprintf( out, "\t\t\t\t<feature name=\"%s\" value=\"%s\" />\n", list->name, list->value );
+ list = list->next;
}
+ }
- /* TODO: display rom region information */
- for ( const rom_entry *region = part->romdata; region; region = rom_next_region( region ) )
- {
- int is_disk = ROMREGION_ISDISKDATA(region);
+ /* TODO: display rom region information */
+ for ( const rom_entry *region = part->romdata; region; region = rom_next_region( region ) )
+ {
+ int is_disk = ROMREGION_ISDISKDATA(region);
- if (!is_disk)
- fprintf( out, "\t\t\t\t<dataarea name=\"%s\" size=\"%d\">\n", ROMREGION_GETTAG(region), ROMREGION_GETLENGTH(region) );
- else
- fprintf( out, "\t\t\t\t<diskarea name=\"%s\">\n", ROMREGION_GETTAG(region) );
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t<dataarea name=\"%s\" size=\"%d\">\n", ROMREGION_GETTAG(region), ROMREGION_GETLENGTH(region) );
+ else
+ fprintf( out, "\t\t\t\t<diskarea name=\"%s\">\n", ROMREGION_GETTAG(region) );
- for ( const rom_entry *rom = rom_first_file( region ); rom && !ROMENTRY_ISREGIONEND(rom); rom++ )
+ for ( const rom_entry *rom = rom_first_file( region ); rom && !ROMENTRY_ISREGIONEND(rom); rom++ )
+ {
+ if ( ROMENTRY_ISFILE(rom) )
{
- if ( ROMENTRY_ISFILE(rom) )
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t\t<rom name=\"%s\" size=\"%d\"", xml_normalize_string(ROM_GETNAME(rom)), rom_file_size(rom) );
+ else
+ fprintf( out, "\t\t\t\t\t<disk name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom)) );
+
+ /* dump checksum information only if there is a known dump */
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
{
- if (!is_disk)
- fprintf( out, "\t\t\t\t\t<rom name=\"%s\" size=\"%d\"", xml_normalize_string(ROM_GETNAME(rom)), rom_file_size(rom) );
- else
- fprintf( out, "\t\t\t\t\t<disk name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom)) );
-
- /* dump checksum information only if there is a known dump */
- hash_collection hashes(ROM_GETHASHDATA(rom));
- if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
- {
- astring tempstr;
- for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next())
- fprintf(out, " %s=\"%s\"", hash->name(), hash->string(tempstr));
- }
-
- if (!is_disk)
- fprintf( out, " offset=\"0x%x\"", ROM_GETOFFSET(rom) );
-
- if ( hashes.flag(hash_collection::FLAG_BAD_DUMP) )
- fprintf( out, " status=\"baddump\"" );
- if ( hashes.flag(hash_collection::FLAG_NO_DUMP) )
- fprintf( out, " status=\"nodump\"" );
-
- if (is_disk)
- fprintf( out, " writeable=\"%s\"", (ROM_GETFLAGS(rom) & DISK_READONLYMASK) ? "no" : "yes");
-
- if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(1))
- fprintf( out, " loadflag=\"load16_byte\"" );
-
- if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(3))
- fprintf( out, " loadflag=\"load32_byte\"" );
-
- if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(2)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
- {
- if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
- fprintf( out, " loadflag=\"load32_word\"" );
- else
- fprintf( out, " loadflag=\"load32_word_swap\"" );
- }
-
- if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(6)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
- {
- if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
- fprintf( out, " loadflag=\"load64_word\"" );
- else
- fprintf( out, " loadflag=\"load64_word_swap\"" );
- }
-
- if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_NOSKIP) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
- {
- if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
- fprintf( out, " loadflag=\"load32_dword\"" );
- else
- fprintf( out, " loadflag=\"load16_word_swap\"" );
- }
-
- fprintf( out, "/>\n" );
+ astring tempstr;
+ for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next())
+ fprintf(out, " %s=\"%s\"", hash->name(), hash->string(tempstr));
}
- else if ( ROMENTRY_ISRELOAD(rom) )
+
+ if (!is_disk)
+ fprintf( out, " offset=\"0x%x\"", ROM_GETOFFSET(rom) );
+
+ if ( hashes.flag(hash_collection::FLAG_BAD_DUMP) )
+ fprintf( out, " status=\"baddump\"" );
+ if ( hashes.flag(hash_collection::FLAG_NO_DUMP) )
+ fprintf( out, " status=\"nodump\"" );
+
+ if (is_disk)
+ fprintf( out, " writeable=\"%s\"", (ROM_GETFLAGS(rom) & DISK_READONLYMASK) ? "no" : "yes");
+
+ if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(1))
+ fprintf( out, " loadflag=\"load16_byte\"" );
+
+ if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(3))
+ fprintf( out, " loadflag=\"load32_byte\"" );
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(2)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
{
- fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"reload\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load32_word\"" );
+ else
+ fprintf( out, " loadflag=\"load32_word_swap\"" );
}
- else if ( ROMENTRY_ISCONTINUE(rom) )
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(6)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
{
- fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"continue\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load64_word\"" );
+ else
+ fprintf( out, " loadflag=\"load64_word_swap\"" );
}
- else if ( ROMENTRY_ISFILL(rom) )
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_NOSKIP) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
{
- fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"fill\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load32_dword\"" );
+ else
+ fprintf( out, " loadflag=\"load16_word_swap\"" );
}
- }
- if (!is_disk)
- fprintf( out, "\t\t\t\t</dataarea>\n" );
- else
- fprintf( out, "\t\t\t\t</diskarea>\n" );
+ fprintf( out, "/>\n" );
+ }
+ else if ( ROMENTRY_ISRELOAD(rom) )
+ {
+ fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"reload\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ }
+ else if ( ROMENTRY_ISCONTINUE(rom) )
+ {
+ fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"continue\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ }
+ else if ( ROMENTRY_ISFILL(rom) )
+ {
+ fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"fill\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ }
}
- fprintf( out, "\t\t\t</part>\n" );
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t</dataarea>\n" );
+ else
+ fprintf( out, "\t\t\t\t</diskarea>\n" );
}
- fprintf( out, "\t\t</software>\n" );
+ fprintf( out, "\t\t\t</part>\n" );
}
- fprintf(out, "\t</softwarelist>\n" );
+ fprintf( out, "\t\t</software>\n" );
}
- software_list_close( list );
+ fprintf(out, "\t</softwarelist>\n" );
}
+
+ software_list_close( list );
}
}
}
}
- }
- if (nr_lists)
+ if (list_count > 0)
fprintf( out, "</softwarelists>\n" );
else
fprintf( out, "No software lists found for this system\n" );
global_free( lists );
}
+#endif
-/*-------------------------------------------------
- softlist_match_roms - scan for a matching
- software ROM by hash
--------------------------------------------------*/
-void softlist_match_roms(machine_config &config, const hash_collection &hashes, int length, int *found)
-{
- for (const device_config *dev = 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] )
- {
- software_list *list = software_list_open( config.options(), swlist->list_name[i], FALSE, NULL );
-
- for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) )
- {
- for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) )
- {
- for ( const rom_entry *region = part->romdata; region != NULL; region = rom_next_region(region) )
- {
- for ( const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom) )
- {
- hash_collection romhashes(ROM_GETHASHDATA(rom));
- if ( hashes == romhashes )
- {
- bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP);
-
- /* output information about the match */
- if (*found != 0)
- mame_printf_info(" ");
- mame_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlist->list_name[i], swinfo->shortname, swinfo->longname);
- (*found)++;
- }
- }
- }
- }
- }
-
- software_list_close( list );
- }
- }
- }
-}
-
-/*-------------------------------------------------
- info_listmedia - output the list of image
- devices referenced by a given game or set of
- games
--------------------------------------------------*/
+//-------------------------------------------------
+// romident - identify ROMs by looking for
+// matches in our internal database
+//-------------------------------------------------
-static void info_listmedia(emu_options &options, const char *gamename)
+void cli_frontend::romident(const char *filename)
{
- int count = 0, devcount;
- const device_config_image_interface *dev = NULL;
- const char *src;
- const char *driver_name;
- const char *name;
- const char *shortname;
- char paren_shortname[16];
+ media_identifier ident(m_options);
- printf(" SYSTEM MEDIA NAME (brief) IMAGE FILE EXTENSIONS SUPPORTED \n");
- printf("---------- -------------------- ------------------------------------\n");
-
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- /* allocate the machine config */
- machine_config config(*drivers[drvindex], options);
+ // identify the file, then output results
+ mame_printf_info("Identifying %s....\n", filename);
+ ident.identify(filename);
+ mame_printf_info("%s\n", ident.result());
- driver_name = drivers[drvindex]->name;
-
- devcount = 0;
-
- for (bool gotone = config.m_devicelist.first(dev); gotone; gotone = dev->next(dev))
- {
- src = downcast<const legacy_image_device_config_base *>(dev)->file_extensions();
- name = downcast<const legacy_image_device_config_base *>(dev)->instance_name();
- shortname = downcast<const legacy_image_device_config_base *>(dev)->brief_instance_name();
-
- sprintf(paren_shortname, "(%s)", shortname);
-
- printf("%-13s%-12s%-8s ", driver_name, name, paren_shortname);
- driver_name = " ";
-
- astring extensions(src);
- char *ext = strtok((char*)extensions.cstr(),",");
- while (ext != NULL)
- {
- printf(".%-5s",ext);
- ext = strtok (NULL, ",");
- devcount++;
- }
- printf("\n");
- }
- if (!devcount)
- printf("%-13s(none)\n",driver_name);
-
- count++;
- }
-
- if (!count)
- printf("There are no Computers or Consoles named %s\n", gamename);
-
- if (count == 0)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+ // return the appropriate error code
+ if (ident.matches() == ident.total())
+ return;
+ else if (ident.matches() == ident.total() - ident.nonroms())
+ throw emu_fatalerror(MAMERR_IDENT_NONROMS, "");
+ else if (ident.matches() > 0)
+ throw emu_fatalerror(MAMERR_IDENT_PARTIAL, "");
+ else
+ throw emu_fatalerror(MAMERR_IDENT_NONE, "");
}
-/*-------------------------------------------------
- info_verifysamples - verify the sample sets of
- one or more games
--------------------------------------------------*/
+//-------------------------------------------------
+// execute_commands - execute various frontend
+// commands
+//-------------------------------------------------
-static void info_verifysamples(emu_options &options, const char *gamename)
+void cli_frontend::execute_commands(const char *exename)
{
- int correct = 0;
- int incorrect = 0;
- int notfound = FALSE;
+ // help?
+ if (strcmp(m_options.command(), CLICOMMAND_HELP) == 0)
+ {
+ display_help();
+ return;
+ }
- /* now iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- if (mame_strwildcmp(gamename, drivers[drvindex]->name) == 0)
- {
- audit_record *audit;
- int audit_records;
- int res;
-
- /* audit the samples in this set */
- audit_records = audit_samples(options, drivers[drvindex], &audit);
- res = audit_summary(drivers[drvindex], audit_records, audit, TRUE);
- if (audit_records > 0)
- global_free(audit);
- else
- continue;
+ // showusage?
+ if (strcmp(m_options.command(), CLICOMMAND_SHOWUSAGE) == 0)
+ {
+ astring helpstring;
+#ifndef MESS
+ mame_printf_info("Usage: %s [%s] [options]\n\nOptions:\n%s", exename, GAMENOUN, m_options.output_help(helpstring));
+#else
+ mame_printf_info("Usage: %s [%s] [media] [software] [options]\n\nOptions:\n%s", exename, GAMENOUN, m_options.output_help(helpstring));
+#endif
+ return;
+ }
- /* if not found, print a message and set the flag */
- if (res == NOTFOUND)
- {
- mame_printf_error("sampleset \"%s\" not found!\n", drivers[drvindex]->name);
- notfound = TRUE;
- }
+ // validate?
+ if (strcmp(m_options.command(), CLICOMMAND_VALIDATE) == 0)
+ {
+ validate_drivers(m_options);
+ return;
+ }
- /* else display information about what we discovered */
- else
- {
- mame_printf_info("sampleset %s ", drivers[drvindex]->name);
+ // other commands need the INIs parsed
+ astring option_errors;
+ m_options.parse_standard_inis(option_errors);
+ if (option_errors)
+ printf("%s\n", option_errors.cstr());
- /* switch off of the result */
- switch (res)
- {
- case INCORRECT:
- mame_printf_info("is bad\n");
- incorrect++;
- break;
-
- case CORRECT:
- mame_printf_info("is good\n");
- correct++;
- break;
-
- case BEST_AVAILABLE:
- mame_printf_info("is best available\n");
- correct++;
- break;
- }
- }
- }
+ // createconfig?
+ if (strcmp(m_options.command(), CLICOMMAND_CREATECONFIG) == 0)
+ {
+ // attempt to open the output file
+ emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(CONFIGNAME ".ini") != FILERR_NONE)
+ throw emu_fatalerror("Unable to create file " CONFIGNAME ".ini\n");
- /* clear out any cached files */
- zip_file_cache_clear();
+ // generate the updated INI
+ astring initext;
+ file.puts(m_options.output_ini(initext));
+ return;
+ }
- /* if we didn't get anything at all because of an unsupported set, display message */
- if (correct + incorrect == 0)
+ // showconfig?
+ if (strcmp(m_options.command(), CLICOMMAND_SHOWCONFIG) == 0)
{
- if (!notfound)
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
- else
- throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No sample sets found for '%s'", gamename);
+ // print the INI text
+ astring initext;
+ printf("%s\n", m_options.output_ini(initext));
+ return;
}
- /* otherwise, print a summary */
- else
+ // all other commands call out to one of these helpers
+ static const struct
{
- if (incorrect > 0)
- throw emu_fatalerror(MAMERR_MISSING_FILES, "%d sample sets found, %d were OK.\n", correct + incorrect, correct);
- mame_printf_info("%d sample sets found, %d were OK.\n", correct, correct);
- }
+ const char *option;
+ void (cli_frontend::*function)(const char *gamename);
+ } info_commands[] =
+ {
+ { CLICOMMAND_LISTXML, &cli_frontend::listxml },
+ { CLICOMMAND_LISTFULL, &cli_frontend::listfull },
+ { CLICOMMAND_LISTSOURCE, &cli_frontend::listsource },
+ { CLICOMMAND_LISTCLONES, &cli_frontend::listclones },
+ { CLICOMMAND_LISTBROTHERS, &cli_frontend::listbrothers },
+ { CLICOMMAND_LISTCRC, &cli_frontend::listcrc },
+ { CLICOMMAND_LISTDEVICES, &cli_frontend::listdevices },
+ { CLICOMMAND_LISTROMS, &cli_frontend::listroms },
+ { CLICOMMAND_LISTSAMPLES, &cli_frontend::listsamples },
+ { CLICOMMAND_VERIFYROMS, &cli_frontend::verifyroms },
+ { CLICOMMAND_VERIFYSAMPLES, &cli_frontend::verifysamples },
+ { CLICOMMAND_LISTMEDIA, &cli_frontend::listmedia },
+// { CLICOMMAND_LISTSOFTWARE, &cli_frontend::listsoftware },
+ { CLICOMMAND_ROMIDENT, &cli_frontend::romident }
+ };
+
+ // find the command
+ for (int cmdindex = 0; cmdindex < ARRAY_LENGTH(info_commands); cmdindex++)
+ if (strcmp(m_options.command(), info_commands[cmdindex].option) == 0)
+ {
+ // parse any relevant INI files before proceeding
+ const char *sysname = m_options.system_name();
+ (this->*info_commands[cmdindex].function)((sysname[0] == 0) ? "*" : sysname);
+ return;
+ }
+
+ // if we get here, we don't know what has been requested
+ throw emu_fatalerror(MAMERR_INVALID_CONFIG, "Unknown command '%s' specified", m_options.command());
}
-/*-------------------------------------------------
- info_romident - identify ROMs by looking for
- matches in our internal database
--------------------------------------------------*/
+//-------------------------------------------------
+// display_help - display help to standard
+// output
+//-------------------------------------------------
-static void info_romident(emu_options &options, const char *gamename)
+void cli_frontend::display_help()
{
- romident_status status;
+#ifndef MESS
+ mame_printf_info("M.A.M.E. v%s - Multiple Arcade Machine Emulator\n"
+ "Copyright Nicola Salmoria and the MAME Team\n\n", build_version);
+ mame_printf_info("%s\n", mame_disclaimer);
+ mame_printf_info("Usage: MAME gamename [options]\n\n"
+ " MAME -showusage for a brief list of options\n"
+ " MAME -showconfig for a list of configuration options\n"
+ " MAME -createconfig to create a " CONFIGNAME ".ini\n\n"
+ "For usage instructions, please consult the file windows.txt\n");
+#else
+ mess_display_help();
+#endif
+}
- /* do the identification */
- romident(options, gamename, &status);
- /* clear out any cached files */
- zip_file_cache_clear();
+//-------------------------------------------------
+// display_suggestions - display 10 possible
+// matches for a given invalid gamename
+//-------------------------------------------------
- /* return the appropriate error code */
- if (status.matches == status.total)
- return;
- else if (status.matches == status.total - status.nonroms)
- throw emu_fatalerror(MAMERR_IDENT_NONROMS, "");
- else if (status.matches > 0)
- throw emu_fatalerror(MAMERR_IDENT_PARTIAL, "");
- else
- throw emu_fatalerror(MAMERR_IDENT_NONE, "");
+void cli_frontend::display_suggestions(const char *gamename)
+{
}
+//**************************************************************************
+// MEDIA IDENTIFIER
+//**************************************************************************
-/***************************************************************************
- UTILITIES
-***************************************************************************/
-
-/*-------------------------------------------------
- romident - identify files
--------------------------------------------------*/
+//-------------------------------------------------
+// media_identifier - constructor
+//-------------------------------------------------
-static void romident(emu_options &options, const char *filename, romident_status *status)
+media_identifier::media_identifier(cli_options &options)
+ : m_drivlist(options),
+ m_total(0),
+ m_matches(0),
+ m_nonroms(0)
{
- osd_directory *directory;
+}
- /* reset the status */
- memset(status, 0, sizeof(*status));
- /* first try to open as a directory */
- directory = osd_opendir(filename);
+//-------------------------------------------------
+// identify - identify a directory, ZIP file,
+// or raw file
+//-------------------------------------------------
+
+void media_identifier::identify(const char *filename)
+{
+ // first try to open as a directory
+ osd_directory *directory = osd_opendir(filename);
if (directory != NULL)
{
- const osd_directory_entry *entry;
-
- /* iterate over all files in the directory */
- while ((entry = osd_readdir(directory)) != NULL)
+ // iterate over all files in the directory
+ for (const osd_directory_entry *entry = osd_readdir(directory); entry != NULL; entry = osd_readdir(directory))
if (entry->type == ENTTYPE_FILE)
{
astring curfile(filename, PATH_SEPARATOR, entry->name);
- identify_file(options, curfile, status);
+ identify_file(curfile);
}
+
+ // close the directory and be done
osd_closedir(directory);
}
- /* if that failed, and the filename ends with .zip, identify as a ZIP file */
+ // if that failed, and the filename ends with .zip, identify as a ZIP file
else if (core_filename_ends_with(filename, ".zip"))
{
- /* first attempt to examine it as a valid ZIP file */
+ // first attempt to examine it as a valid ZIP file
zip_file *zip = NULL;
zip_error ziperr = zip_file_open(filename, &zip);
if (ziperr == ZIPERR_NONE && zip != NULL)
{
- const zip_file_header *entry;
-
- /* loop over entries in the ZIP, skipping empty files and directories */
- for (entry = zip_file_first_file(zip); entry; entry = zip_file_next_file(zip))
+ // loop over entries in the ZIP, skipping empty files and directories
+ for (const zip_file_header *entry = zip_file_first_file(zip); entry != NULL; entry = zip_file_next_file(zip))
if (entry->uncompressed_length != 0)
{
UINT8 *data = global_alloc_array(UINT8, entry->uncompressed_length);
if (data != NULL)
{
- /* decompress data into RAM and identify it */
+ // decompress data into RAM and identify it
ziperr = zip_file_decompress(zip, data, entry->uncompressed_length);
if (ziperr == ZIPERR_NONE)
- identify_data(options, entry->filename, data, entry->uncompressed_length, status);
+ identify_data(entry->filename, data, entry->uncompressed_length);
global_free(data);
}
}
- /* close up */
+ // close up
zip_file_close(zip);
}
+
+ // clear out any cached files
+ zip_file_cache_clear();
}
- /* otherwise, identify as a raw file */
+ // otherwise, identify as a raw file
else
- identify_file(options, filename, status);
+ identify_file(filename);
}
-/*-------------------------------------------------
- identify_file - identify a file; if it is a
- ZIP file, scan it and identify all enclosed
- files
--------------------------------------------------*/
+//-------------------------------------------------
+// identify_file - identify a file
+//-------------------------------------------------
-static void identify_file(emu_options &options, const char *name, romident_status *status)
+void media_identifier::identify_file(const char *name)
{
- file_error filerr;
- osd_file *file;
- UINT64 length;
-
+ // CHD files need to be parsed and their hashes extracted from the header
if (core_filename_ends_with(name, ".chd"))
{
- chd_file *chd;
- chd_error err;
+ // output the name
astring basename;
- int found = 0;
-
- core_filename_extract_base(&basename, name, FALSE);
- mame_printf_info("%-20s", basename.cstr());
+ m_result.catprintf("%-20s", core_filename_extract_base(&basename, name, FALSE)->cstr());
+ m_total++;
- status->total++;
-
- err = chd_open(name, CHD_OPEN_READ, NULL, &chd);
+ // attempt to open as a CHD; fail if not
+ chd_file *chd;
+ chd_error err = chd_open(name, CHD_OPEN_READ, NULL, &chd);
if (err != CHDERR_NONE)
{
- mame_printf_info("NOT A CHD\n");
- status->nonroms++;
+ m_result.catprintf("NOT A CHD\n");
+ m_nonroms++;
+ return;
}
- else
- {
- chd_header header;
-
- header = *chd_get_header(chd);
- if (header.flags & CHDFLAGS_IS_WRITEABLE)
- {
- mame_printf_info("is a writeable CHD\n");
- }
- else
- {
- static const UINT8 nullhash[20] = { 0 };
- hash_collection hashes;
-
- /* if there's an MD5 or SHA1 hash, add them to the output hash */
- if (memcmp(nullhash, header.md5, sizeof(header.md5)) != 0)
- hashes.add_from_buffer(hash_collection::HASH_MD5, header.md5, sizeof(header.md5));
- if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0)
- hashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1));
- length = header.logicalbytes;
+ // fetch the header and close the file
+ chd_header header = *chd_get_header(chd);
+ chd_close(chd);
- match_roms(options, hashes, length, &found);
-
- if (found == 0)
- {
- mame_printf_info("NO MATCH\n");
- }
-
- /* if we did find it, count it as a match */
- else
- status->matches++;
- }
-
- chd_close(chd);
+ // error on writable CHDs
+ if (header.flags & CHDFLAGS_IS_WRITEABLE)
+ {
+ m_result.catprintf("is a writeable CHD\n");
+ return;
}
+
+ // otherwise, get the hash collection for this CHD
+ static const UINT8 nullhash[20] = { 0 };
+ hash_collection hashes;
+
+ if (memcmp(nullhash, header.md5, sizeof(header.md5)) != 0)
+ hashes.add_from_buffer(hash_collection::HASH_MD5, header.md5, sizeof(header.md5));
+ if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0)
+ hashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1));
+
+ // determine whether this file exists
+ int found = find_by_hash(hashes, header.logicalbytes);
+ if (found == 0)
+ m_result.catprintf("NO MATCH\n");
+ else
+ m_matches++;
}
+
+ // all other files have their hashes computed directly
else
{
- /* open for read and process if it opens and has a valid length */
- filerr = osd_open(name, OPEN_FLAG_READ, &file, &length);
- if (filerr == FILERR_NONE && length > 0 && (UINT32)length == length)
- {
- UINT8 *data = global_alloc_array(UINT8, length);
- if (data != NULL)
- {
- UINT32 bytes;
-
- /* read file data into RAM and identify it */
- filerr = osd_read(file, data, 0, length, &bytes);
- if (filerr == FILERR_NONE)
- identify_data(options, name, data, bytes, status);
- global_free(data);
- }
- osd_close(file);
- }
+ // load the file and process if it opens and has a valid length
+ UINT32 length;
+ void *data;
+ file_error filerr = core_fload(name, &data, &length);
+ if (filerr == FILERR_NONE && length > 0)
+ identify_data(name, reinterpret_cast<UINT8 *>(data), length);
}
}
-/*-------------------------------------------------
- identify_data - identify a buffer full of
- data; if it comes from a .JED file, parse the
- fusemap into raw data first
--------------------------------------------------*/
+//-------------------------------------------------
+// identify_data - identify a buffer full of
+// data; if it comes from a .JED file, parse the
+// fusemap into raw data first
+//-------------------------------------------------
-static void identify_data(emu_options &options, const char *name, const UINT8 *data, int length, romident_status *status)
+void media_identifier::identify_data(const char *name, const UINT8 *data, int length)
{
+ // if this is a '.jed' file, process it into raw bits first
UINT8 *tempjed = NULL;
- astring basename;
- int found = 0;
jed_data jed;
-
- /* if this is a '.jed' file, process it into raw bits first */
if (core_filename_ends_with(name, ".jed") && jed_parse(data, length, &jed) == JEDERR_NONE)
{
- /* now determine the new data length and allocate temporary memory for it */
+ // now determine the new data length and allocate temporary memory for it
length = jedbin_output(&jed, NULL, 0);
tempjed = global_alloc_array(UINT8, length);
- if (tempjed == NULL)
- return;
-
- /* create a binary output of the JED data and use that instead */
jedbin_output(&jed, tempjed, length);
data = tempjed;
}
- /* compute the hash of the data */
+ // compute the hash of the data
hash_collection hashes;
hashes.compute(data, length, hash_collection::HASH_TYPES_CRC_SHA1);
- /* output the name */
- status->total++;
- core_filename_extract_base(&basename, name, FALSE);
- mame_printf_info("%-20s", basename.cstr());
+ // output the name
+ m_total++;
+ astring basename;
+ m_result.catprintf("%-20s", core_filename_extract_base(&basename, name, FALSE)->cstr());
- /* see if we can find a match in the ROMs */
- match_roms(options, hashes, length, &found);
+ // see if we can find a match in the ROMs
+ int found = find_by_hash(hashes, length);
- /* if we didn't find it, try to guess what it might be */
+ // if we didn't find it, try to guess what it might be
if (found == 0)
{
- /* if not a power of 2, assume it is a non-ROM file */
+ // if not a power of 2, assume it is a non-ROM file
if ((length & (length - 1)) != 0)
{
- mame_printf_info("NOT A ROM\n");
- status->nonroms++;
+ m_result.catprintf("NOT A ROM\n");
+ m_nonroms++;
}
- /* otherwise, it's just not a match */
+ // otherwise, it's just not a match
else
- mame_printf_info("NO MATCH\n");
+ m_result.catprintf("NO MATCH\n");
}
- /* if we did find it, count it as a match */
+ // if we did find it, count it as a match
else
- status->matches++;
+ m_matches++;
- /* free any temporary JED data */
+ // free any temporary JED data
global_free(tempjed);
}
-/*-------------------------------------------------
- match_roms - scan for a matching ROM by hash
--------------------------------------------------*/
+//-------------------------------------------------
+// find_by_hash - scan for a file in the list
+// of drivers by hash
+//-------------------------------------------------
-static void match_roms(emu_options &options, const hash_collection &hashes, int length, int *found)
+int media_identifier::find_by_hash(const hash_collection &hashes, int length)
{
- /* iterate over drivers */
- for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
- {
- machine_config config(*drivers[drvindex], options);
+ int found = 0;
- /* iterate over sources, regions and files within the region */
- for (const rom_source *source = rom_first_source(config); source != NULL; source = rom_next_source(*source))
- for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
- for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ // iterate over drivers
+ m_drivlist.reset();
+ while (m_drivlist.next())
+ {
+ // iterate over sources, regions and files within the region */
+ 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))
+ for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
{
hash_collection romhashes(ROM_GETHASHDATA(rom));
if (!romhashes.flag(hash_collection::FLAG_NO_DUMP) && hashes == romhashes)
{
bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP);
- /* output information about the match */
- if (*found != 0)
+ // output information about the match
+ if (!found)
mame_printf_info(" ");
- mame_printf_info("= %s%-20s %-10s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), drivers[drvindex]->name, drivers[drvindex]->description);
- (*found)++;
+ mame_printf_info("= %s%-20s %-10s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), m_drivlist.driver().name, m_drivlist.driver().description);
+ found++;
}
}
- // also check any softlists
- softlist_match_roms( config, hashes, length, found );
+ // next iterate over softlists
+ 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 listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++)
+ if (swlist->list_name[listnum] != NULL)
+ {
+ software_list *list = software_list_open(m_drivlist.options(), swlist->list_name[listnum], FALSE, NULL);
+
+ for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo))
+ for (software_part *part = software_find_part(swinfo, NULL, NULL); part != NULL; part = software_part_next(part))
+ for (const rom_entry *region = part->romdata; region != NULL; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
+ {
+ hash_collection romhashes(ROM_GETHASHDATA(rom));
+ if (hashes == romhashes)
+ {
+ bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP);
+
+ // output information about the match
+ if (!found)
+ mame_printf_info(" ");
+ mame_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlist->list_name[listnum], swinfo->shortname, swinfo->longname);
+ found++;
+ }
+ }
+
+ software_list_close(list);
+ }
+ }
}
+
+ return found;
}
diff --git a/src/emu/clifront.h b/src/emu/clifront.h
index d240fdf160f..2870309c7a4 100644
--- a/src/emu/clifront.h
+++ b/src/emu/clifront.h
@@ -80,6 +80,7 @@
// TYPE DEFINITIONS
//**************************************************************************
+// cli_options wraps the general emu options with CLI-specific additions
class cli_options : public emu_options
{
public:
@@ -91,22 +92,75 @@ private:
};
+// cli_frontend handles command-line processing and emulator execution
+class cli_frontend
+{
+public:
+ // construction/destruction
+ cli_frontend(cli_options &options, osd_interface &osd);
+ ~cli_frontend();
+
+ // execute based on the incoming argc/argv
+ int execute(int argc, char **argv);
+
+ // direct access to the command operations
+ void listxml(const char *gamename = "*");
+ void listfull(const char *gamename = "*");
+ void listsource(const char *gamename = "*");
+ void listclones(const char *gamename = "*");
+ void listbrothers(const char *gamename = "*");
+ void listcrc(const char *gamename = "*");
+ void listroms(const char *gamename = "*");
+ void listsamples(const char *gamename = "*");
+ void listdevices(const char *gamename = "*");
+ void listmedia(const char *gamename = "*");
+ void verifyroms(const char *gamename = "*");
+ void verifysamples(const char *gamename = "*");
+ void romident(const char *filename);
+
+private:
+ // internal helpers
+ void execute_commands(const char *exename);
+ void display_help();
+ void display_suggestions(const char *gamename);
+
+ // internal state
+ cli_options & m_options;
+ osd_interface & m_osd;
+ int m_result;
+};
+
+
+// media_identifier class identifies media by hash via a search in
+// the driver database
+class media_identifier
+{
+public:
+ // construction/destruction
+ media_identifier(cli_options &options);
+
+ // getters
+ const char *result() const { return m_result; }
+ int total() const { return m_total; }
+ int matches() const { return m_matches; }
+ int nonroms() const { return m_nonroms; }
+
+ // operations
+ void reset() { m_total = m_matches = m_nonroms = 0; m_result.reset(); }
+ void identify(const char *name);
+ void identify_file(const char *name);
+ void identify_data(const char *name, const UINT8 *data, int length);
+ int find_by_hash(const hash_collection &hashes, int length);
+
+private:
+ // internal state
+ driver_enumerator m_drivlist;
+ astring m_result;
+ int m_total;
+ int m_matches;
+ int m_nonroms;
+};
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-int cli_execute(cli_options &options, osd_interface &osd, int argc, char **argv);
-
-/* informational functions */
-void cli_info_listxml(emu_options &options, const char *gamename);
-void cli_info_listfull(emu_options &options, const char *gamename);
-void cli_info_listsource(emu_options &options, const char *gamename);
-void cli_info_listclones(emu_options &options, const char *gamename);
-void cli_info_listbrothers(emu_options &options, const char *gamename);
-void cli_info_listcrc(emu_options &options, const char *gamename);
-void cli_info_listroms(emu_options &options, const char *gamename);
-void cli_info_listsamples(emu_options &options, const char *gamename);
-void cli_info_listdevices(emu_options &options, const char *gamename);
#endif /* __CLIFRONT_H__ */
diff --git a/src/emu/config.c b/src/emu/config.c
index 3f1b7e18d93..070f3cd4cc7 100644
--- a/src/emu/config.c
+++ b/src/emu/config.c
@@ -235,13 +235,13 @@ static int config_load_xml(running_machine &machine, emu_file &file, int which_t
case CONFIG_TYPE_CONTROLLER:
{
- const game_driver *clone_of;
+ int clone_of;
/* match on: default, game name, source file name, parent name, grandparent name */
if (strcmp(name, "default") != 0 &&
strcmp(name, machine.system().name) != 0 &&
strcmp(name, srcfile) != 0 &&
- ((clone_of = driver_get_clone(&machine.system())) == NULL || strcmp(name, clone_of->name) != 0) &&
- (clone_of == NULL || ((clone_of = driver_get_clone(clone_of)) == NULL) || strcmp(name, clone_of->name) != 0))
+ ((clone_of = driver_list::clone(machine.system())) == -1 || strcmp(name, driver_list::driver(clone_of).name) != 0) &&
+ (clone_of == -1 || ((clone_of = driver_list::clone(clone_of)) == -1) || strcmp(name, driver_list::driver(clone_of).name) != 0))
continue;
break;
}
diff --git a/src/emu/cpu/mips/dismips.c b/src/emu/cpu/mips/dismips.c
index c549cc1b6a5..339ff26ff3b 100644
--- a/src/emu/cpu/mips/dismips.c
+++ b/src/emu/cpu/mips/dismips.c
@@ -336,6 +336,12 @@ void *malloc_file_line(size_t size, const char *file, int line)
return osd_malloc(size);
}
+void *malloc_array_file_line(size_t size, const char *file, int line)
+{
+ // allocate the memory and fail if we can't
+ return osd_malloc_array(size);
+}
+
void free_file_line( void *memory, const char *file, int line )
{
osd_free( memory );
diff --git a/src/emu/debug/textbuf.c b/src/emu/debug/textbuf.c
index 828887f6b66..08b8fb2214e 100644
--- a/src/emu/debug/textbuf.c
+++ b/src/emu/debug/textbuf.c
@@ -93,7 +93,7 @@ text_buffer *text_buffer_alloc(UINT32 bytes, UINT32 lines)
return NULL;
/* allocate memory for the buffer itself */
- text->buffer = (char *)osd_malloc(bytes);
+ text->buffer = (char *)osd_malloc_array(bytes);
if (!text->buffer)
{
osd_free(text);
@@ -101,7 +101,7 @@ text_buffer *text_buffer_alloc(UINT32 bytes, UINT32 lines)
}
/* allocate memory for the lines array */
- text->lineoffs = (INT32 *)osd_malloc(lines * sizeof(text->lineoffs[0]));
+ text->lineoffs = (INT32 *)osd_malloc_array(lines * sizeof(text->lineoffs[0]));
if (!text->lineoffs)
{
osd_free(text->buffer);
diff --git a/src/emu/devcpu.c b/src/emu/devcpu.c
index 4793308c966..cddecf11f7a 100644
--- a/src/emu/devcpu.c
+++ b/src/emu/devcpu.c
@@ -88,6 +88,7 @@ legacy_cpu_device_config::legacy_cpu_device_config(const machine_config &mconfig
// set the real name
m_name = get_legacy_config_string(DEVINFO_STR_NAME);
m_shortname = get_legacy_config_string(DEVINFO_STR_SHORTNAME);
+ m_searchpath = m_shortname;
}
diff --git a/src/emu/devintrf.c b/src/emu/devintrf.c
index fa221c86d46..6e424c3f9f8 100644
--- a/src/emu/devintrf.c
+++ b/src/emu/devintrf.c
@@ -307,6 +307,30 @@ device_config::device_config(const machine_config &mconfig, device_type type, co
}
+device_config::device_config(const machine_config &mconfig, device_type type, const char *name, const char *shortname, const char *tag, const device_config *owner, UINT32 clock, UINT32 param)
+ : m_next(NULL),
+ m_owner(const_cast<device_config *>(owner)),
+ m_interface_list(NULL),
+ m_type(type),
+ m_clock(clock),
+ m_machine_config(mconfig),
+ m_static_config(NULL),
+ m_input_defaults(NULL),
+ m_name(name),
+ m_shortname(shortname),
+ m_searchpath(shortname),
+ m_tag(tag),
+ m_config_complete(false)
+{
+ // derive the clock from our owner if requested
+ if ((m_clock & 0xff000000) == 0xff000000)
+ {
+ assert(m_owner != NULL);
+ m_clock = m_owner->m_clock * ((m_clock >> 12) & 0xfff) / ((m_clock >> 0) & 0xfff);
+ }
+}
+
+
//-------------------------------------------------
// ~device_config - destructor
//-------------------------------------------------
diff --git a/src/emu/devintrf.h b/src/emu/devintrf.h
index f0996ea47fe..3e05c742089 100644
--- a/src/emu/devintrf.h
+++ b/src/emu/devintrf.h
@@ -262,6 +262,7 @@ class device_config
protected:
// construction/destruction
device_config(const machine_config &mconfig, device_type type, const char *name, const char *tag, const device_config *owner, UINT32 clock, UINT32 param = 0);
+ device_config(const machine_config &mconfig, device_type type, const char *name, const char *shortname, const char *tag, const device_config *owner, UINT32 clock, UINT32 param = 0);
virtual ~device_config();
public:
@@ -289,6 +290,7 @@ public:
UINT32 clock() const { return m_clock; }
const char *name() const { return m_name; }
const char *shortname() const { return m_shortname; }
+ const char *searchpath() const { return m_searchpath; }
const char *tag() const { return m_tag; }
const void *static_config() const { return m_static_config; }
const machine_config &mconfig() const { return m_machine_config; }
@@ -336,7 +338,9 @@ protected:
const input_device_default *m_input_defaults; // devices input ports default overrides
astring m_name; // name of the device
- astring m_shortname; // short name of the device, used for potential romload
+ astring m_shortname; // short name of the device
+ astring m_searchpath; // search path, used for media loading
+
private:
astring m_tag; // tag for this instance
bool m_config_complete; // have we completed our configuration?
diff --git a/src/emu/devlegcy.c b/src/emu/devlegcy.c
index 638153683e6..0b72a5aeb72 100644
--- a/src/emu/devlegcy.c
+++ b/src/emu/devlegcy.c
@@ -62,6 +62,7 @@ legacy_device_config_base::legacy_device_config_base(const machine_config &mconf
// set the proper name
m_name = get_legacy_config_string(DEVINFO_STR_NAME);
m_shortname = get_legacy_config_string(DEVINFO_STR_SHORTNAME);
+ m_searchpath = m_shortname;
}
diff --git a/src/emu/devlegcy.h b/src/emu/devlegcy.h
index f956614bf0c..fc7e2ddd0fb 100644
--- a/src/emu/devlegcy.h
+++ b/src/emu/devlegcy.h
@@ -126,7 +126,7 @@ enum
DEVINFO_STR_FIRST = 0x30000,
DEVINFO_STR_NAME = DEVINFO_STR_FIRST, // R/O: name of the device
- DEVINFO_STR_SHORTNAME, // R/O: short name of device, used in case of romload
+ DEVINFO_STR_SHORTNAME, // R/O: search path of device, used for media loading
DEVINFO_STR_FAMILY, // R/O: family of the device
DEVINFO_STR_VERSION, // R/O: version of the device
DEVINFO_STR_SOURCE_FILE, // R/O: file containing the device implementation
diff --git a/src/emu/diimage.c b/src/emu/diimage.c
index d6200729608..d3c31bb503f 100644
--- a/src/emu/diimage.c
+++ b/src/emu/diimage.c
@@ -383,7 +383,6 @@ bool device_image_interface::try_change_working_directory(const char *subdir)
void device_image_interface::setup_working_directory()
{
- const game_driver *gamedrv;
char *dst = NULL;
osd_get_full_path(&dst,".");
@@ -394,10 +393,10 @@ void device_image_interface::setup_working_directory()
if (try_change_working_directory("software"))
{
/* now down to a directory for this computer */
- gamedrv = &device().machine().system();
- while(gamedrv && !try_change_working_directory(gamedrv->name))
+ int gamedrv = driver_list::find(device().machine().system());
+ while(gamedrv != -1 && !try_change_working_directory(driver_list::driver(gamedrv).name))
{
- gamedrv = driver_get_compatible(gamedrv);
+ gamedrv = driver_list::compatible_with(gamedrv);
}
}
osd_free(dst);
diff --git a/src/emu/driver.c b/src/emu/driver.c
index 582d643168c..d39633d649a 100644
--- a/src/emu/driver.c
+++ b/src/emu/driver.c
@@ -2,10 +2,38 @@
driver.c
- Driver construction helpers.
-
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
+ Driver enumeration helpers.
+
+****************************************************************************
+
+ 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.
***************************************************************************/
@@ -14,264 +42,332 @@
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define DRIVER_LRU_SIZE 10
+//**************************************************************************
+// DRIVER LIST
+//**************************************************************************
+//-------------------------------------------------
+// driver_list - constructor
+//-------------------------------------------------
+driver_list::driver_list()
+{
+}
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
-static int driver_lru[DRIVER_LRU_SIZE];
+//-------------------------------------------------
+// find - find a driver by name
+//-------------------------------------------------
+int driver_list::find(const char *name)
+{
+ // if no name, bail
+ if (name == NULL)
+ return -1;
+
+ // create a dummy item for comparison purposes
+ game_driver driver;
+ driver.name = name;
+ game_driver *driverptr = &driver;
+
+ // binary search to find it
+ const game_driver **result = reinterpret_cast<const game_driver **>(bsearch(&driverptr, s_drivers_sorted, s_driver_count, sizeof(*s_drivers_sorted), driver_sort_callback));
+ return (result == NULL) ? -1 : result - s_drivers_sorted;
+}
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+//-------------------------------------------------
+// driver_sort_callback - compare two items in
+// an array of game_driver pointers
+//-------------------------------------------------
-static int penalty_compare(const char *source, const char *target);
+int driver_list::driver_sort_callback(const void *elem1, const void *elem2)
+{
+ const game_driver * const *item1 = reinterpret_cast<const game_driver * const *>(elem1);
+ const game_driver * const *item2 = reinterpret_cast<const game_driver * const *>(elem2);
+ return mame_stricmp((*item1)->name, (*item2)->name);
+}
+//-------------------------------------------------
+// penalty_compare - compare two strings for
+// closeness and assign a score.
+//-------------------------------------------------
-/***************************************************************************
- MISC FUNCTIONS
-***************************************************************************/
+int driver_list::penalty_compare(const char *source, const char *target)
+{
+ int gaps = 1;
+ bool last = true;
-/*-------------------------------------------------
- driver_get_name - return a pointer to a
- driver given its name
--------------------------------------------------*/
+ // scan the strings
+ for ( ; *source && *target; target++)
+ {
+ // do a case insensitive match
+ bool match = (tolower((UINT8)*source) == tolower((UINT8)*target));
-const game_driver *driver_get_name(const char *name)
-{
- int lurnum, drvnum;
+ // if we matched, advance the source
+ if (match)
+ source++;
- /* scan the LRU list first */
- for (lurnum = 0; lurnum < DRIVER_LRU_SIZE; lurnum++)
- if (mame_stricmp(drivers[driver_lru[lurnum]]->name, name) == 0)
+ // if the match state changed, count gaps
+ if (match != last)
{
- /* if not first, swap with the head */
- if (lurnum != 0)
- {
- int temp = driver_lru[0];
- driver_lru[0] = driver_lru[lurnum];
- driver_lru[lurnum] = temp;
- }
- return drivers[driver_lru[0]];
+ last = match;
+ if (!match)
+ gaps++;
}
+ }
- /* scan for a match in the drivers -- slow! */
- for (drvnum = 0; drivers[drvnum] != NULL; drvnum++)
- if (mame_stricmp(drivers[drvnum]->name, name) == 0)
- {
- memmove((void *)&driver_lru[1], (void *)&driver_lru[0], sizeof(driver_lru[0]) * (DRIVER_LRU_SIZE - 1));
- driver_lru[0] = drvnum;
- return drivers[drvnum];
- }
+ // penalty if short string does not completely fit in
+ for ( ; *source; source++)
+ gaps++;
+
+ // if we matched perfectly, gaps == 0
+ if (gaps == 1 && *source == 0 && *target == 0)
+ gaps = 0;
- return NULL;
+ return gaps;
}
-/*-------------------------------------------------
- driver_get_clone - return a pointer to the
- clone of a game driver.
--------------------------------------------------*/
-const game_driver *driver_get_clone(const game_driver *driver)
-{
- /* if no clone, easy out */
- if (driver->parent == NULL || (driver->parent[0] == '0' && driver->parent[1] == 0))
- return NULL;
+//**************************************************************************
+// DRIVER ENUMERATOR
+//**************************************************************************
- /* convert the name to a game_driver */
- return driver_get_name(driver->parent);
+//-------------------------------------------------
+// driver_enumerator - constructor
+//-------------------------------------------------
+
+driver_enumerator::driver_enumerator(emu_options &options)
+ : m_current(-1),
+ m_filtered_count(0),
+ m_options(options),
+ m_included(global_alloc_array(UINT8, s_driver_count)),
+ m_config(global_alloc_array_clear(machine_config *, s_driver_count))
+{
+ include_all();
}
-/*-------------------------------------------------
- driver_get_searchpath - return a search path
- for a given driver
--------------------------------------------------*/
+driver_enumerator::driver_enumerator(emu_options &options, const char *string)
+ : m_current(-1),
+ m_filtered_count(0),
+ m_options(options),
+ m_included(global_alloc_array(UINT8, s_driver_count)),
+ m_config(global_alloc_array_clear(machine_config *, s_driver_count))
+{
+ filter(string);
+}
+
-const char *driver_get_searchpath(const game_driver &driver, astring &string)
+driver_enumerator::driver_enumerator(emu_options &options, const game_driver &driver)
+ : m_current(-1),
+ m_filtered_count(0),
+ m_options(options),
+ m_included(global_alloc_array(UINT8, s_driver_count)),
+ m_config(global_alloc_array_clear(machine_config *, s_driver_count))
{
- // create the search path consisting of gamedrv[;parent[;...]]
- string = driver.name;
- for (const game_driver *parent = driver_get_clone(&driver); parent != NULL; parent = driver_get_clone(parent))
- string.cat(";").cat(parent->name);
- return string;
+ filter(driver);
}
-/*-------------------------------------------------
- driver_list_get_approx_matches - find the best
- n matches to a driver name.
--------------------------------------------------*/
+//-------------------------------------------------
+// ~driver_enumerator - destructor
+//-------------------------------------------------
-void driver_list_get_approx_matches(const game_driver * const driverlist[], const char *name, int matches, const game_driver **list)
+driver_enumerator::~driver_enumerator()
{
-#undef rand
+ // free any configs
+ for (int index = 0; index < s_driver_count; index++)
+ global_free(m_config[index]);
- int matchnum, drvnum;
- int *penalty;
+ // free the arrays
+ global_free(m_included);
+ global_free(m_config);
+}
- /* if no name, pick random entries */
- if (name == NULL || name[0] == 0)
- {
- const game_driver **templist;
- int driver_count;
- int shufnum;
- /* allocate a temporary list */
- templist = global_alloc_array(const game_driver *, driver_list_get_count(driverlist));
+//-------------------------------------------------
+// config - return a machine_config for the given
+// driver, allocating on demand if needed
+//-------------------------------------------------
- /* build up a list of valid entries */
- for (drvnum = driver_count = 0; driverlist[drvnum] != NULL; drvnum++)
- if ((driverlist[drvnum]->flags & GAME_NO_STANDALONE) == 0)
- templist[driver_count++] = driverlist[drvnum];
+machine_config &driver_enumerator::config(int index) const
+{
+ assert(index >= 0 && index < s_driver_count);
+ if (m_config[index] == NULL)
+ m_config[index] = global_alloc(machine_config(*s_drivers_sorted[index], m_options));
+ return *m_config[index];
+}
- /* seed the RNG first */
- srand(osd_ticks());
- /* shuffle */
- for (shufnum = 0; shufnum < 4 * driver_count; shufnum++)
- {
- int item1 = rand() % driver_count;
- int item2 = rand() % driver_count;
- const game_driver *temp;
+//-------------------------------------------------
+// filter - filter the driver list against the
+// given string
+//-------------------------------------------------
- temp = templist[item1];
- templist[item1] = templist[item2];
- templist[item2] = temp;
- }
+int driver_enumerator::filter(const char *filterstring)
+{
+ // reset the count
+ exclude_all();
+
+ // match name against each driver in the list
+ for (int index = 0; index < s_driver_count; index++)
+ if (matches(filterstring, s_drivers_sorted[index]->name))
+ include(index);
+
+ return m_filtered_count;
+}
- /* copy out the first few entries */
- for (matchnum = 0; matchnum < matches; matchnum++)
- list[matchnum] = templist[matchnum % driver_count];
- global_free(templist);
- return;
- }
+//-------------------------------------------------
+// filter - filter the driver list against the
+// given driver
+//-------------------------------------------------
- /* allocate some temp memory */
- penalty = global_alloc_array(int, matches);
+int driver_enumerator::filter(const game_driver &driver)
+{
+ // reset the count
+ exclude_all();
+
+ // match name against each driver in the list
+ for (int index = 0; index < s_driver_count; index++)
+ if (s_drivers_sorted[index] == &driver)
+ include(index);
+
+ return m_filtered_count;
+}
- /* initialize everyone's states */
- for (matchnum = 0; matchnum < matches; matchnum++)
- {
- penalty[matchnum] = 9999;
- list[matchnum] = NULL;
- }
- /* scan the entire drivers array */
- for (drvnum = 0; driverlist[drvnum] != NULL; drvnum++)
+//-------------------------------------------------
+// next - get the next driver matching the given
+// filter
+//-------------------------------------------------
+
+bool driver_enumerator::next()
+{
+ // always advance one
+ m_current++;
+
+ // if we have a filter, scan forward to the next match
+ while (m_current < s_driver_count)
{
- int curpenalty, tmp;
+ if (m_included[m_current])
+ break;
+ m_current++;
+ }
- /* skip things that can't run */
- if ((driverlist[drvnum]->flags & GAME_NO_STANDALONE) != 0)
- continue;
+ // return true if we end up in range
+ return (m_current >= 0 && m_current < s_driver_count);
+}
- /* pick the best match between driver name and description */
- curpenalty = penalty_compare(name, driverlist[drvnum]->description);
- tmp = penalty_compare(name, driverlist[drvnum]->name);
- curpenalty = MIN(curpenalty, tmp);
- /* insert into the sorted table of matches */
- for (matchnum = matches - 1; matchnum >= 0; matchnum--)
- {
- /* stop if we're worse than the current entry */
- if (curpenalty >= penalty[matchnum])
- break;
+//-------------------------------------------------
+// next_excluded - get the next driver that is
+// not currently included in the list
+//-------------------------------------------------
- /* as lng as this isn't the last entry, bump this one down */
- if (matchnum < matches - 1)
- {
- penalty[matchnum + 1] = penalty[matchnum];
- list[matchnum + 1] = list[matchnum];
- }
- list[matchnum] = driverlist[drvnum];
- penalty[matchnum] = curpenalty;
- }
+bool driver_enumerator::next_excluded()
+{
+ // always advance one
+ m_current++;
+
+ // if we have a filter, scan forward to the next match
+ while (m_current < s_driver_count)
+ {
+ if (!m_included[m_current])
+ break;
+ m_current++;
}
- /* free our temp memory */
- global_free(penalty);
+ // return true if we end up in range
+ return (m_current >= 0 && m_current < s_driver_count);
}
-/*-------------------------------------------------
- penalty_compare - compare two strings for
- closeness and assign a score.
--------------------------------------------------*/
+//-------------------------------------------------
+// driver_sort_callback - compare two items in
+// an array of game_driver pointers
+//-------------------------------------------------
-static int penalty_compare(const char *source, const char *target)
+void driver_enumerator::find_approximate_matches(const char *string, int count, int *results)
{
- int gaps = 1;
- int last = TRUE;
+#undef rand
- /* scan the strings */
- for ( ; *source && *target; target++)
+ // if no name, pick random entries
+ if (string == NULL || string[0] == 0)
{
- /* do a case insensitive match */
- int match = (tolower((UINT8)*source) == tolower((UINT8)*target));
+ // seed the RNG first
+ srand(osd_ticks());
- /* if we matched, advance the source */
- if (match)
- source++;
+ // allocate a temporary list
+ int *templist = global_alloc_array(int, m_filtered_count);
+ int arrayindex = 0;
+ for (int index = 0; index < s_driver_count; index++)
+ if (m_included[index])
+ templist[arrayindex++] = index;
+ assert(arrayindex == m_filtered_count);
- /* if the match state changed, count gaps */
- if (match != last)
+ // shuffle
+ for (int shufnum = 0; shufnum < 4 * s_driver_count; shufnum++)
{
- last = match;
- if (!match)
- gaps++;
+ int item1 = rand() % m_filtered_count;
+ int item2 = rand() % m_filtered_count;
+ int temp = templist[item1];
+ templist[item1] = templist[item2];
+ templist[item2] = temp;
}
- }
-
- /* penalty if short string does not completely fit in */
- for ( ; *source; source++)
- gaps++;
- /* if we matched perfectly, gaps == 0 */
- if (gaps == 1 && *source == 0 && *target == 0)
- gaps = 0;
+ // copy out the first few entries
+ for (int matchnum = 0; matchnum < count; matchnum++)
+ results[matchnum] = templist[matchnum % m_filtered_count];
- return gaps;
-}
+ global_free(templist);
+ return;
+ }
+ // allocate memory to track the penalty value
+ int *penalty = global_alloc_array(int, count);
-/*-------------------------------------------------
- driver_list_get_count - returns the amount of
- drivers
--------------------------------------------------*/
+ // initialize everyone's states
+ for (int matchnum = 0; matchnum < count; matchnum++)
+ {
+ penalty[matchnum] = 9999;
+ results[matchnum] = -1;
+ }
-int driver_list_get_count(const game_driver * const driverlist[])
-{
- int count;
+ // scan the entire drivers array
+ for (int index = 0; index < s_driver_count; index++)
+ if (m_included[index])
+ {
+ // skip things that can't run
+ if ((s_drivers_sorted[index]->flags & GAME_NO_STANDALONE) != 0)
+ continue;
- for (count = 0; driverlist[count] != NULL; count++) ;
- return count;
-}
+ // pick the best match between driver name and description
+ int curpenalty = penalty_compare(string, s_drivers_sorted[index]->description);
+ int tmp = penalty_compare(string, s_drivers_sorted[index]->name);
+ curpenalty = MIN(curpenalty, tmp);
-/*-------------------------------------------------
- driver_get_compatible - return a pointer to the
- compatible driver.
--------------------------------------------------*/
+ // insert into the sorted table of matches
+ for (int matchnum = count - 1; matchnum >= 0; matchnum--)
+ {
+ // stop if we're worse than the current entry
+ if (curpenalty >= penalty[matchnum])
+ break;
+
+ // as long as this isn't the last entry, bump this one down
+ if (matchnum < count - 1)
+ {
+ penalty[matchnum + 1] = penalty[matchnum];
+ results[matchnum + 1] = results[matchnum];
+ }
+ results[matchnum] = index;
+ penalty[matchnum] = curpenalty;
+ }
+ }
-const game_driver *driver_get_compatible(const game_driver *drv)
-{
- if (driver_get_clone(drv))
- drv = driver_get_clone(drv);
- else if (drv->compatible_with)
- drv = driver_get_name(drv->compatible_with);
- else
- drv = NULL;
- return drv;
+ // free our temp memory
+ global_free(penalty);
}
diff --git a/src/emu/driver.h b/src/emu/driver.h
index 47e64ef6564..c920c0ca5e6 100644
--- a/src/emu/driver.h
+++ b/src/emu/driver.h
@@ -2,10 +2,38 @@
driver.h
- Definitions relating to game drivers.
-
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
+ Driver enumeration helpers.
+
+****************************************************************************
+
+ 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.
***************************************************************************/
@@ -81,6 +109,108 @@ struct game_driver
};
+// driver_list is a purely static class that wraps the global driver list
+class driver_list
+{
+ DISABLE_COPYING(driver_list);
+
+protected:
+ // construction/destruction
+ driver_list();
+
+public:
+ // getters
+ static int total() { return s_driver_count; }
+
+ // any item by index
+ static const game_driver &driver(int index) { assert(index >= 0 && index < s_driver_count); return *s_drivers_sorted[index]; }
+ static int clone(int index) { return find(driver(index).parent); }
+ static int non_bios_clone(int index) { int result = find(driver(index).parent); return (result != -1 && (driver(result).flags & GAME_IS_BIOS_ROOT) == 0) ? result : -1; }
+ static int compatible_with(int index) { int result = clone(index); return (result != -1) ? result : find(driver(index).compatible_with); }
+
+ // any item by driver
+ static int clone(const game_driver &driver) { int index = find(driver); assert(index != -1); return clone(index); }
+ static int non_bios_clone(const game_driver &driver) { int index = find(driver); assert(index != -1); return non_bios_clone(index); }
+ static int compatible_with(const game_driver &driver) { int index = find(driver); assert(index != -1); return compatible_with(index); }
+
+ // general helpers
+ static int find(const char *name);
+ static int find(const game_driver &driver) { return find(driver.name); }
+
+ // static helpers
+ static bool matches(const char *wildstring, const char *string) { return (wildstring == NULL || mame_strwildcmp(wildstring, string) == 0); }
+
+protected:
+ // internal helpers
+ static int driver_sort_callback(const void *elem1, const void *elem2);
+ static int penalty_compare(const char *source, const char *target);
+
+ // internal state
+ static int s_driver_count;
+ static const game_driver * const s_drivers_sorted[];
+};
+
+
+// driver_enumerator enables efficient iteration through the driver list
+class driver_enumerator : public driver_list
+{
+ DISABLE_COPYING(driver_enumerator);
+
+public:
+ // construction/destruction
+ driver_enumerator(emu_options &options);
+ driver_enumerator(emu_options &options, const char *filter);
+ driver_enumerator(emu_options &options, const game_driver &filter);
+ ~driver_enumerator();
+
+ // getters
+ int count() const { return m_filtered_count; }
+ int current() const { return m_current; }
+ emu_options &options() const { return m_options; }
+
+ // current item
+ const game_driver &driver() const { return driver_list::driver(m_current); }
+ machine_config &config() const { return config(m_current); }
+ int clone() { return driver_list::clone(m_current); }
+ int non_bios_clone() { return driver_list::non_bios_clone(m_current); }
+ int compatible_with() { return driver_list::compatible_with(m_current); }
+ void include() { include(m_current); }
+ void exclude() { exclude(m_current); }
+
+ // any item by index
+ bool included(int index) const { assert(index >= 0 && index < s_driver_count); return m_included[index]; }
+ bool excluded(int index) const { assert(index >= 0 && index < s_driver_count); return !m_included[index]; }
+ machine_config &config(int index) const;
+ void include(int index) { assert(index >= 0 && index < s_driver_count); if (!m_included[index]) { m_included[index] = true; m_filtered_count++; } }
+ void exclude(int index) { assert(index >= 0 && index < s_driver_count); if (m_included[index]) { m_included[index] = false; m_filtered_count--; } }
+ using driver_list::driver;
+ using driver_list::clone;
+ using driver_list::non_bios_clone;
+ using driver_list::compatible_with;
+
+ // filtering/iterating
+ int filter(const char *string = NULL);
+ int filter(const game_driver &driver);
+ void include_all() { memset(m_included, 1, sizeof(m_included[0]) * s_driver_count); m_filtered_count = s_driver_count; }
+ void exclude_all() { memset(m_included, 0, sizeof(m_included[0]) * s_driver_count); m_filtered_count = 0; }
+ void reset() { m_current = -1; }
+ bool next();
+ bool next_excluded();
+
+ // general helpers
+ void set_current(int index) { assert(index >= -1 && index <= s_driver_count); m_current = index; }
+ void find_approximate_matches(const char *string, int count, int *results);
+
+private:
+ // internal state
+ int m_current;
+ int m_filtered_count;
+ emu_options & m_options;
+ UINT8 * m_included;
+ machine_config ** m_config;
+};
+
+
/***************************************************************************
MACROS FOR BUILDING GAME DRIVERS
@@ -176,24 +306,8 @@ extern const game_driver GAME_NAME(NAME) = \
GLOBAL VARIABLES
***************************************************************************/
-extern const game_driver * const drivers[];
-
-GAME_EXTERN(empty);
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-const game_driver *driver_get_name(const char *name);
-const game_driver *driver_get_clone(const game_driver *driver);
-const game_driver *driver_get_compatible(const game_driver *drv);
-
-const char *driver_get_searchpath(const game_driver &driver, astring &string);
+GAME_EXTERN(___empty);
-void driver_list_get_approx_matches(const game_driver * const driverlist[], const char *name, int matches, const game_driver **list);
-int driver_list_get_count(const game_driver * const driverlist[]);
#endif
diff --git a/src/emu/drivers/empty.c b/src/emu/drivers/empty.c
index bea3c2231ab..d4ce7079f31 100644
--- a/src/emu/drivers/empty.c
+++ b/src/emu/drivers/empty.c
@@ -20,7 +20,7 @@
*
*************************************/
-static MACHINE_START( empty )
+static MACHINE_START( ___empty )
{
/* force the UI to show the game select screen */
ui_menu_force_game_select(machine, &machine.render().ui_container());
@@ -34,9 +34,9 @@ static MACHINE_START( empty )
*
*************************************/
-static MACHINE_CONFIG_START( empty, driver_device )
+static MACHINE_CONFIG_START( ___empty, driver_device )
- MCFG_MACHINE_START(empty)
+ MCFG_MACHINE_START(___empty)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
@@ -54,8 +54,8 @@ MACHINE_CONFIG_END
*
*************************************/
-ROM_START( empty )
- ROM_REGION( 0x10, "user1", 0 )
+ROM_START( ___empty )
+ ROM_REGION( 0x10, "user1", ROMREGION_ERASEFF )
ROM_END
@@ -66,4 +66,4 @@ ROM_END
*
*************************************/
-GAME( 2007, empty, 0, empty, 0, 0, ROT0, "MAME", "No Driver Loaded", 0 )
+GAME( 2007, ___empty, 0, ___empty, 0, 0, ROT0, "MAME", "No Driver Loaded", GAME_NO_SOUND )
diff --git a/src/emu/emu.mak b/src/emu/emu.mak
index d336f113876..73663d48c86 100644
--- a/src/emu/emu.mak
+++ b/src/emu/emu.mak
@@ -338,5 +338,6 @@ $(EMUOBJ)/rendlay.o: $(EMULAYOUT)/dualhovu.lh \
$(EMULAYOUT)/voffff20.lh \
$(EMULAYOUT)/lcd.lh \
$(EMULAYOUT)/lcd_rot.lh \
+ $(EMULAYOUT)/pinball.lh \
$(EMUOBJ)/video.o: $(EMULAYOUT)/snap.lh
diff --git a/src/emu/emualloc.c b/src/emu/emualloc.c
index 75b972e0eeb..a3164e8e913 100644
--- a/src/emu/emualloc.c
+++ b/src/emu/emualloc.c
@@ -92,6 +92,7 @@ public:
static UINT64 s_curid; // current ID
static osd_lock * s_lock; // lock for managing the list
static bool s_lock_alloc; // set to true temporarily during lock allocation
+ static bool s_tracking; // set to true when tracking is live
static memory_entry *s_hash[k_hash_prime];// hash table based on pointer
static memory_entry *s_freehead; // pointer to the head of the free list
@@ -118,9 +119,10 @@ resource_pool global_resource_pool;
const zeromem_t zeromem = { };
// globals for memory_entry
-UINT64 memory_entry::s_curid = 0;
+UINT64 memory_entry::s_curid = 1;
osd_lock *memory_entry::s_lock = NULL;
bool memory_entry::s_lock_alloc = false;
+bool memory_entry::s_tracking = false;
memory_entry *memory_entry::s_hash[memory_entry::k_hash_prime] = { NULL };
memory_entry *memory_entry::s_freehead = NULL;
@@ -155,6 +157,31 @@ void *malloc_file_line(size_t size, const char *file, int line)
//-------------------------------------------------
+// malloc_array_file_line - allocate memory with
+// file and line number information, and a hint
+// that this object is an array
+//-------------------------------------------------
+
+void *malloc_array_file_line(size_t size, const char *file, int line)
+{
+ // allocate the memory and fail if we can't
+ void *result = osd_malloc_array(size);
+ if (result == NULL)
+ return NULL;
+
+ // add a new entry
+ memory_entry::allocate(size, result, file, line);
+
+#ifdef MAME_DEBUG
+ // randomize the memory
+ rand_memory(result, size);
+#endif
+
+ return result;
+}
+
+
+//-------------------------------------------------
// free_file_line - free memory with file
// and line number information
//-------------------------------------------------
@@ -189,7 +216,19 @@ void free_file_line(void *memory, const char *file, int line)
// memory
//-------------------------------------------------
-void dump_unfreed_mem(void)
+void track_memory(bool track)
+{
+ memory_entry::s_tracking = track;
+}
+
+
+//-------------------------------------------------
+// dump_unfreed_mem - called from the exit path
+// of any code that wants to check for unfreed
+// memory
+//-------------------------------------------------
+
+void dump_unfreed_mem()
{
#ifdef MAME_DEBUG
memory_entry::report_unfreed();
@@ -446,7 +485,7 @@ memory_entry *memory_entry::allocate(size_t size, void *base, const char *file,
if (s_freehead == NULL)
{
// create a new chunk, and fail if we can't
- memory_entry *entry = reinterpret_cast<memory_entry *>(osd_malloc(memory_block_alloc_chunk * sizeof(memory_entry)));
+ memory_entry *entry = reinterpret_cast<memory_entry *>(osd_malloc_array(memory_block_alloc_chunk * sizeof(memory_entry)));
if (entry == NULL)
{
release_lock();
@@ -468,8 +507,8 @@ memory_entry *memory_entry::allocate(size_t size, void *base, const char *file,
// populate it
entry->m_size = size;
entry->m_base = base;
- entry->m_file = file;
- entry->m_line = line;
+ entry->m_file = s_tracking ? file : NULL;
+ entry->m_line = s_tracking ? line : 0;
entry->m_id = s_curid++;
if (LOG_ALLOCS)
fprintf(stderr, "#%06d, alloc %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), entry->m_file, (int)entry->m_line);
@@ -561,5 +600,5 @@ void memory_entry::report_unfreed()
release_lock();
if (total > 0)
- fprintf(stderr, "a total of %d bytes were not free()'d\n", total);
+ fprintf(stderr, "a total of %d bytes were not freed\n", total);
}
diff --git a/src/emu/emualloc.h b/src/emu/emualloc.h
index 0a26fcad3ec..e4da24c52a5 100644
--- a/src/emu/emualloc.h
+++ b/src/emu/emualloc.h
@@ -47,9 +47,25 @@
//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+// set to 1 to track memory allocated by emualloc.h itself as well
+#define TRACK_SELF_MEMORY (0)
+
+
+
+//**************************************************************************
// MACROS
//**************************************************************************
+// self-allocation helpers
+#if TRACK_SELF_MEMORY
+#define EMUALLOC_SELF_NEW new(__FILE__, __LINE__)
+#else
+#define EMUALLOC_SELF_NEW new
+#endif
+
// pool allocation helpers
#define pool_alloc(_pool, _type) (_pool).add_object(new(__FILE__, __LINE__) _type)
#define pool_alloc_clear(_pool, _type) (_pool).add_object(new(__FILE__, __LINE__, zeromem) _type)
@@ -72,11 +88,13 @@
// allocate memory with file and line number information
void *malloc_file_line(size_t size, const char *file, int line);
+void *malloc_array_file_line(size_t size, const char *file, int line);
// free memory with file and line number information
void free_file_line(void *memory, const char *file, int line);
// called from the exit path of any code that wants to check for unfreed memory
+void track_memory(bool track);
void dump_unfreed_mem();
@@ -100,7 +118,7 @@ ATTR_FORCE_INLINE inline void *operator new(std::size_t size) throw (std::bad_al
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size) throw (std::bad_alloc)
{
- void *result = malloc_file_line(size, NULL, 0);
+ void *result = malloc_array_file_line(size, NULL, 0);
if (result == NULL)
throw std::bad_alloc();
return result;
@@ -130,7 +148,7 @@ ATTR_FORCE_INLINE inline void *operator new(std::size_t size, const char *file,
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size, const char *file, int line) throw (std::bad_alloc)
{
- void *result = malloc_file_line(size, file, line);
+ void *result = malloc_array_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
return result;
@@ -161,7 +179,7 @@ ATTR_FORCE_INLINE inline void *operator new(std::size_t size, const char *file,
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc)
{
- void *result = malloc_file_line(size, file, line);
+ void *result = malloc_array_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
memset(result, 0, size);
@@ -270,8 +288,8 @@ public:
bool contains(void *ptrstart, void *ptrend);
void clear();
- template<class T> T *add_object(T* object) { add(*new(__FILE__, __LINE__) resource_pool_object<T>(object)); return object; }
- template<class T> T *add_array(T* array, int count) { add(*new(__FILE__, __LINE__) resource_pool_array<T>(array, count)); return array; }
+ template<class T> T *add_object(T* object) { add(*EMUALLOC_SELF_NEW resource_pool_object<T>(object)); return object; }
+ template<class T> T *add_array(T* array, int count) { add(*EMUALLOC_SELF_NEW resource_pool_array<T>(array, count)); return array; }
private:
static const int k_hash_prime = 193;
@@ -306,7 +324,7 @@ extern const zeromem_t zeromem;
#undef realloc
#undef free
-#define malloc(x) malloc_file_line(x, __FILE__, __LINE__)
+#define malloc(x) malloc_array_file_line(x, __FILE__, __LINE__)
#define calloc(x,y) __error_use_auto_alloc_clear_or_global_alloc_clear_instead__
#define realloc(x,y) __error_realloc_is_dangerous__
#define free(x) free_file_line(x, __FILE__, __LINE__)
diff --git a/src/emu/emuopts.c b/src/emu/emuopts.c
index 69cca4f8b87..7753b8e83ac 100644
--- a/src/emu/emuopts.c
+++ b/src/emu/emuopts.c
@@ -349,12 +349,12 @@ void emu_options::parse_standard_inis(astring &error_string)
}
// then parse the grandparent, parent, and system-specific INIs
- const game_driver *parent = driver_get_clone(cursystem);
- const game_driver *gparent = (parent != NULL) ? driver_get_clone(parent) : NULL;
- if (gparent != NULL)
- parse_one_ini(gparent->name, OPTION_PRIORITY_GPARENT_INI, &error_string);
- if (parent != NULL)
- parse_one_ini(parent->name, OPTION_PRIORITY_PARENT_INI, &error_string);
+ int parent = driver_list::clone(*cursystem);
+ int gparent = (parent != -1) ? driver_list::clone(parent) : -1;
+ if (gparent != -1)
+ parse_one_ini(driver_list::driver(gparent).name, OPTION_PRIORITY_GPARENT_INI, &error_string);
+ if (parent != -1)
+ parse_one_ini(driver_list::driver(parent).name, OPTION_PRIORITY_PARENT_INI, &error_string);
parse_one_ini(cursystem->name, OPTION_PRIORITY_DRIVER_INI, &error_string);
}
@@ -367,7 +367,8 @@ void emu_options::parse_standard_inis(astring &error_string)
const game_driver *emu_options::system() const
{
astring tempstr;
- return driver_get_name(*core_filename_extract_base(&tempstr, system_name(), TRUE));
+ int index = driver_list::find(*core_filename_extract_base(&tempstr, system_name(), TRUE));
+ return (index != -1) ? &driver_list::driver(index) : NULL;
}
diff --git a/src/emu/emutempl.h b/src/emu/emutempl.h
index 74fe8501f6c..c4fd064c155 100644
--- a/src/emu/emutempl.h
+++ b/src/emu/emutempl.h
@@ -245,6 +245,37 @@ private:
};
+// ======================> simple_list_wrapper
+
+// a simple_list_wrapper wraps an existing object with a next pointer so it
+// can live in a simple_list without requiring the object to have a next
+// pointer
+template<class T>
+class simple_list_wrapper
+{
+public:
+ // construction/destruction
+ simple_list_wrapper(T *object)
+ : m_next(NULL),
+ m_object(object) { }
+
+ // operators
+ operator T *() { return m_object; }
+ operator T *() const { return m_object; }
+ T *operator *() { return m_object; }
+ T *operator *() const { return m_object; }
+
+ // getters
+ simple_list_wrapper *next() const { return m_next; }
+ T *object() const { return m_object; }
+
+private:
+ // internal state
+ simple_list_wrapper * m_next;
+ T * m_object;
+};
+
+
// ======================> fixed_allocator
// a fixed_allocator is a simple class that maintains a free pool of objects
diff --git a/src/emu/hash.c b/src/emu/hash.c
index 5d55f26d642..12f94dd1f5f 100644
--- a/src/emu/hash.c
+++ b/src/emu/hash.c
@@ -593,7 +593,7 @@ bool hash_collection::remove(char type)
// crc - return the CRC hash if present
//-------------------------------------------------
-bool hash_collection::crc(UINT32 &result)
+bool hash_collection::crc(UINT32 &result) const
{
// attempt to find the CRC hash; if we fail, return false
hash_base *crchash = hash(HASH_CRC);
@@ -601,7 +601,7 @@ bool hash_collection::crc(UINT32 &result)
return false;
// downcast to a hash_crc and convert to a UINT32
- result = *downcast<hash_crc *>(crchash);
+ result = *downcast<const hash_crc *>(crchash);
return true;
}
diff --git a/src/emu/hash.h b/src/emu/hash.h
index a89c7cee4b2..3f5995edb51 100644
--- a/src/emu/hash.h
+++ b/src/emu/hash.h
@@ -161,7 +161,7 @@ public:
bool remove(char type);
// CRC-specific helpers
- bool crc(UINT32 &result);
+ bool crc(UINT32 &result) const;
hash_base *add_crc(UINT32 crc);
// string conversion
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;
}
diff --git a/src/emu/info.h b/src/emu/info.h
index 327354e2d6f..5fd260d05bf 100644
--- a/src/emu/info.h
+++ b/src/emu/info.h
@@ -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.
***************************************************************************/
@@ -15,12 +43,47 @@
#define __INFO_H__
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+//**************************************************************************
+// FUNCTION PROTOTYPES
+//**************************************************************************
+
+// helper class to putput
+class info_xml_creator
+{
+public:
+ // construction/destruction
+ info_xml_creator(driver_enumerator &drivlist);
+
+ // output
+ void output(FILE *out);
+
+private:
+ // internal helper
+ void output_one();
+ void output_sampleof();
+ void output_bios();
+ void output_rom();
+ void output_sample();
+ void output_chips();
+ void output_display();
+ void output_sound();
+ void output_input(const ioport_list &portlist);
+ void output_switches(const ioport_list &portlist, int type, const char *outertag, const char *innertag);
+ void output_adjusters(const ioport_list &portlist);
+ void output_categories(const ioport_list &portlist);
+ void output_driver();
+ void output_images();
+ void output_software_list();
+ void output_ramoptions();
+
+ const char *get_merge_name(const hash_collection &romhashes);
+
+ // internal state
+ FILE * m_output;
+ driver_enumerator & m_drivlist;
-/* print the MAME database in XML format */
-void print_mame_xml(FILE* out, const game_driver* const games[], const char *gamename, emu_options &options);
+ static const char s_dtd_string[];
+};
#endif /* __INFO_H__ */
diff --git a/src/emu/layout/pinball.lay b/src/emu/layout/pinball.lay
new file mode 100644
index 00000000000..0372a828ac0
--- /dev/null
+++ b/src/emu/layout/pinball.lay
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<mamelayout version="2">
+ <element name="digit" defstate="0">
+ <led7seg>
+ <color red="0.75" green="0" blue="0.0" />
+ </led7seg>
+ </element>
+ <element name="dummy_str" defstate="0">
+ <text string="Pinball">
+ <color red="1.0" green="1.0" blue="1.0" />
+ <bounds x="0" y="0" width="25" height="5" />
+ </text>
+ </element>
+ <view name="Standard">
+ <bezel name="dummy_txt" element="dummy_str">
+ <bounds x="0" y="0" width="25" height="5" />
+ </bezel>
+ </view>
+</mamelayout>
diff --git a/src/emu/machine.c b/src/emu/machine.c
index a0ed6794f14..7707468d556 100644
--- a/src/emu/machine.c
+++ b/src/emu/machine.c
@@ -943,8 +943,17 @@ driver_device_config_base::driver_device_config_base(const machine_config &mconf
void driver_device_config_base::static_set_game(device_config *device, const game_driver *game)
{
- downcast<driver_device_config_base *>(device)->m_system = game;
- downcast<driver_device_config_base *>(device)->m_shortname = game->name;
+ driver_device_config_base *base = downcast<driver_device_config_base *>(device);
+
+ base->m_system = game;
+
+ // set the short name to the game's name
+ base->m_shortname = game->name;
+
+ // and set the search path to include all parents
+ base->m_searchpath = game->name;
+ for (int parent = driver_list::clone(*game); parent != -1; parent = driver_list::clone(parent))
+ base->m_searchpath.cat(";").cat(driver_list::driver(parent).name);
}
diff --git a/src/emu/mame.c b/src/emu/mame.c
index 65d671b32ef..ea9452ac2de 100644
--- a/src/emu/mame.c
+++ b/src/emu/mame.c
@@ -157,7 +157,7 @@ int mame_execute(emu_options &options, osd_interface &osd)
const game_driver *system = options.system();
if (system == NULL)
{
- system = &GAME_NAME(empty);
+ system = &GAME_NAME(___empty);
if (firstgame)
started_empty = true;
}
diff --git a/src/emu/render.c b/src/emu/render.c
index 654534d3a52..5ca15bd77da 100644
--- a/src/emu/render.c
+++ b/src/emu/render.c
@@ -1642,10 +1642,10 @@ void render_target::load_layout_files(const char *layoutfile, bool singlefile)
load_layout_file(NULL, m_manager.machine().config().m_default_layout);
// try to load another file based on the parent driver name
- const game_driver *cloneof = driver_get_clone(&system);
- if (cloneof != NULL)
- if (!load_layout_file(cloneof->name, cloneof->name))
- load_layout_file(cloneof->name, "default");
+ int cloneof = driver_list::clone(system);
+ if (cloneof != -1)
+ if (!load_layout_file(driver_list::driver(cloneof).name, driver_list::driver(cloneof).name))
+ load_layout_file(driver_list::driver(cloneof).name, "default");
// now do the built-in layouts for single-screen games
if (m_manager.machine().m_devicelist.count(SCREEN) == 1)
diff --git a/src/emu/rendlay.c b/src/emu/rendlay.c
index c6e03f1c1d6..c3df4c94c9c 100644
--- a/src/emu/rendlay.c
+++ b/src/emu/rendlay.c
@@ -117,6 +117,10 @@
#include "lcd.lh"
#include "lcd_rot.lh"
+// generic dummy pinball layout
+#include "pinball.lh"
+
+
//**************************************************************************
// CONSTANTS
diff --git a/src/emu/romload.c b/src/emu/romload.c
index 760cfc46ac0..46cf9c09d81 100644
--- a/src/emu/romload.c
+++ b/src/emu/romload.c
@@ -614,7 +614,6 @@ static int open_rom_file(rom_load_data *romdata, const char *regiontag, const ro
{
file_error filerr = FILERR_NOT_FOUND;
UINT32 romsize = rom_file_size(romp);
- const game_driver *drv;
/* update status display */
display_loading_rom_message(romdata, ROM_GETNAME(romp));
@@ -626,9 +625,8 @@ static int open_rom_file(rom_load_data *romdata, const char *regiontag, const ro
/* attempt reading up the chain through the parents. It automatically also
attempts any kind of load by checksum supported by the archives. */
romdata->file = NULL;
- for (drv = &romdata->machine().system(); romdata->file == NULL && drv != NULL; drv = driver_get_clone(drv))
- if (drv->name != NULL && *drv->name != 0)
- filerr = common_process_file(romdata->machine().options(), drv->name, has_crc, crc, romp, &romdata->file);
+ for (int drv = driver_list::find(romdata->machine().system()); romdata->file == NULL && drv != -1; drv = driver_list::clone(drv))
+ filerr = common_process_file(romdata->machine().options(), driver_list::driver(drv).name, has_crc, crc, romp, &romdata->file);
/* if the region is load by name, load the ROM from there */
if (romdata->file == NULL && regiontag != NULL)
@@ -1007,7 +1005,6 @@ static void process_rom_entries(rom_load_data *romdata, const char *regiontag, c
chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, emu_file **image_file, chd_file **image_chd, const char *locationtag)
{
- const game_driver *drv, *searchdrv;
const rom_entry *region, *rom;
const rom_source *source;
file_error filerr;
@@ -1018,8 +1015,8 @@ chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, cons
/* attempt to open the properly named file, scanning up through parent directories */
filerr = FILERR_NOT_FOUND;
- for (searchdrv = gamedrv; searchdrv != NULL && filerr != FILERR_NONE; searchdrv = driver_get_clone(searchdrv))
- filerr = common_process_file(options, searchdrv->name, ".chd", romp, image_file);
+ for (int searchdrv = driver_list::find(*gamedrv); searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv))
+ filerr = common_process_file(options, driver_list::driver(searchdrv).name, ".chd", romp, image_file);
if (filerr != FILERR_NONE)
filerr = common_process_file(options, NULL, ".chd", romp, image_file);
@@ -1114,9 +1111,9 @@ chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, cons
/* otherwise, look at our parents for a CHD with an identical checksum */
/* and try to open that */
hash_collection romphashes(ROM_GETHASHDATA(romp));
- for (drv = gamedrv; drv != NULL; drv = driver_get_clone(drv))
+ for (int drv = driver_list::find(*gamedrv); drv != -1; drv = driver_list::clone(drv))
{
- machine_config config(*drv, options);
+ machine_config config(driver_list::driver(drv), options);
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))
if (ROMREGION_ISDISKDATA(region))
@@ -1128,8 +1125,8 @@ chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, cons
{
/* attempt to open the properly named file, scanning up through parent directories */
filerr = FILERR_NOT_FOUND;
- for (searchdrv = drv; searchdrv != NULL && filerr != FILERR_NONE; searchdrv = driver_get_clone(searchdrv))
- filerr = common_process_file(options, searchdrv->name, ".chd", rom, image_file);
+ for (int searchdrv = drv; searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv))
+ filerr = common_process_file(options, driver_list::driver(searchdrv).name, ".chd", rom, image_file);
if (filerr != FILERR_NONE)
filerr = common_process_file(options, NULL, ".chd", rom, image_file);
diff --git a/src/emu/sound/bsmt2000.c b/src/emu/sound/bsmt2000.c
index 6293b8b38bd..7e172fc6a98 100644
--- a/src/emu/sound/bsmt2000.c
+++ b/src/emu/sound/bsmt2000.c
@@ -107,13 +107,12 @@ ROM_END
//-------------------------------------------------
bsmt2000_device_config::bsmt2000_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
- : device_config(mconfig, static_alloc_device_config, "BSMT2000", tag, owner, clock),
+ : device_config(mconfig, static_alloc_device_config, "BSMT2000", "bsmt2000", tag, owner, clock),
device_config_sound_interface(mconfig, *this),
device_config_memory_interface(mconfig, *this),
m_space_config("samples", ENDIANNESS_LITTLE, 8, 32, 0, NULL, *ADDRESS_MAP_NAME(bsmt2000)),
m_ready_callback(NULL)
{
- m_shortname = "bsmt2000";
}
diff --git a/src/emu/sound/wavwrite.c b/src/emu/sound/wavwrite.c
index 1d318a08b9e..5cd884d7417 100644
--- a/src/emu/sound/wavwrite.c
+++ b/src/emu/sound/wavwrite.c
@@ -126,7 +126,7 @@ void wav_add_data_32(wav_file *wav, INT32 *data, int samples, int shift)
if (!wav) return;
/* allocate temp memory */
- temp = (INT16 *)osd_malloc(samples * sizeof(temp[0]));
+ temp = (INT16 *)osd_malloc_array(samples * sizeof(temp[0]));
if (!temp)
return;
@@ -154,7 +154,7 @@ void wav_add_data_16lr(wav_file *wav, INT16 *left, INT16 *right, int samples)
if (!wav) return;
/* allocate temp memory */
- temp = (INT16 *)osd_malloc(samples * 2 * sizeof(temp[0]));
+ temp = (INT16 *)osd_malloc_array(samples * 2 * sizeof(temp[0]));
if (!temp)
return;
@@ -179,7 +179,7 @@ void wav_add_data_32lr(wav_file *wav, INT32 *left, INT32 *right, int samples, in
if (!wav) return;
/* allocate temp memory */
- temp = (INT16 *)osd_malloc(samples * 2 * sizeof(temp[0]));
+ temp = (INT16 *)osd_malloc_array(samples * 2 * sizeof(temp[0]));
if (!temp)
return;
diff --git a/src/emu/ui.c b/src/emu/ui.c
index 61110734aca..b29ebddc89d 100644
--- a/src/emu/ui.c
+++ b/src/emu/ui.c
@@ -280,7 +280,7 @@ int ui_display_startup_screens(running_machine &machine, int first_time, int sho
/* disable everything if we are using -str for 300 or fewer seconds, or if we're the empty driver,
or if we are debugging */
- if (!first_time || (str > 0 && str < 60*5) || &machine.system() == &GAME_NAME(empty) || (machine.debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (!first_time || (str > 0 && str < 60*5) || &machine.system() == &GAME_NAME(___empty) || (machine.debug_flags & DEBUG_FLAG_ENABLED) != 0)
show_gameinfo = show_warnings = show_disclaimer = FALSE;
/* initialize the on-screen display system */
@@ -907,8 +907,6 @@ static astring &warnings_string(running_machine &machine, astring &string)
GAME_IMPERFECT_GRAPHICS | \
GAME_NO_COCKTAIL)
- int i;
-
string.reset();
/* if no warnings, nothing to return */
@@ -955,10 +953,6 @@ static astring &warnings_string(running_machine &machine, astring &string)
/* if there's a NOT WORKING, UNEMULATED PROTECTION or GAME MECHANICAL warning, make it stronger */
if (machine.system().flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_MECHANICAL))
{
- const game_driver *maindrv;
- const game_driver *clone_of;
- int foundworking;
-
/* add the strings for these warnings */
if (machine.system().flags & GAME_UNEMULATED_PROTECTION)
string.cat("The game has protection which isn't fully emulated.\n");
@@ -970,25 +964,25 @@ static astring &warnings_string(running_machine &machine, astring &string)
"It is not possible to fully play this " GAMENOUN ".\n");
/* find the parent of this driver */
- clone_of = driver_get_clone(&machine.system());
- if (clone_of != NULL && !(clone_of->flags & GAME_IS_BIOS_ROOT))
+ driver_enumerator drivlist(machine.options());
+ int maindrv = drivlist.find(machine.system());
+ int clone_of = drivlist.non_bios_clone(maindrv);
+ if (clone_of != -1)
maindrv = clone_of;
- else
- maindrv = &machine.system();
/* scan the driver list for any working clones and add them */
- foundworking = FALSE;
- for (i = 0; drivers[i] != NULL; i++)
- if (drivers[i] == maindrv || driver_get_clone(drivers[i]) == maindrv)
- if ((drivers[i]->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_MECHANICAL)) == 0)
+ bool foundworking = false;
+ while (drivlist.next())
+ if (drivlist.current() == maindrv || drivlist.clone() == maindrv)
+ if ((drivlist.driver().flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_MECHANICAL)) == 0)
{
/* this one works, add a header and display the name of the clone */
if (!foundworking)
string.cat("\n\nThere are working clones of this game: ");
else
string.cat(", ");
- string.cat(drivers[i]->name);
- foundworking = TRUE;
+ string.cat(drivlist.driver().name);
+ foundworking = true;
}
if (foundworking)
diff --git a/src/emu/uimenu.c b/src/emu/uimenu.c
index efd14614b1b..91addf9ba55 100644
--- a/src/emu/uimenu.c
+++ b/src/emu/uimenu.c
@@ -208,7 +208,7 @@ struct _select_game_state
UINT8 error;
UINT8 rerandomize;
char search[40];
- const game_driver * matchlist[VISIBLE_GAMES_IN_LIST];
+ int matchlist[VISIBLE_GAMES_IN_LIST];
const game_driver * driverlist[1];
};
@@ -245,6 +245,9 @@ static const char priortext[] = "Return to Prior Menu";
static const char backtext[] = "Return to " CAPSTARTGAMENOUN;
static const char exittext[] = "Exit";
+// temporary hack until this is C++-ified
+static driver_enumerator *drivlist;
+
/***************************************************************************
@@ -299,7 +302,6 @@ static void menu_crosshair_populate(running_machine &machine, ui_menu *menu);
static void menu_quit_game(running_machine &machine, ui_menu *menu, void *parameter, void *state);
static void menu_select_game(running_machine &machine, ui_menu *menu, void *parameter, void *state);
static void menu_select_game_populate(running_machine &machine, ui_menu *menu, select_game_state *menustate);
-static int CLIB_DECL menu_select_game_driver_compare(const void *elem1, const void *elem2);
static void menu_select_game_build_driver_list(ui_menu *menu, select_game_state *menustate);
static void menu_select_game_custom_render(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
@@ -3426,9 +3428,10 @@ static void menu_select_game(running_machine &machine, ui_menu *menu, void *para
/* if no state, allocate some */
if (state == NULL)
{
- state = ui_menu_alloc_state(menu, sizeof(*menustate) + sizeof(menustate->driverlist) * driver_list_get_count(drivers), NULL);
+ state = ui_menu_alloc_state(menu, sizeof(*menustate) + sizeof(menustate->driverlist) * driver_list::total(), NULL);
if (parameter != NULL)
strcpy(((select_game_state *)state)->search, (const char *)parameter);
+ ((select_game_state *)state)->matchlist[0] = -1;
}
menustate = (select_game_state *)state;
@@ -3459,24 +3462,20 @@ static void menu_select_game(running_machine &machine, ui_menu *menu, void *para
/* anything else is a driver */
else
{
- audit_record *audit;
- int audit_records;
- int audit_result;
-
- /* audit the game first to see if we're going to work */
- audit_records = audit_images(menu->machine().options(), driver, AUDIT_VALIDATE_FAST, &audit);
- audit_result = audit_summary(driver, audit_records, audit, FALSE);
- if (audit_records > 0)
- global_free(audit);
-
- /* if everything looks good, schedule the new driver */
- if (audit_result == CORRECT || audit_result == BEST_AVAILABLE)
+ // audit the game first to see if we're going to work
+ driver_enumerator enumerator(machine.options(), *driver);
+ enumerator.next();
+ media_auditor auditor(enumerator);
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if everything looks good, schedule the new driver
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE)
{
machine.schedule_new_driver(*driver);
ui_menu_stack_reset(machine);
}
- /* otherwise, display an error */
+ // otherwise, display an error
else
{
ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
@@ -3551,18 +3550,19 @@ static void menu_select_game_populate(running_machine &machine, ui_menu *menu, s
}
/* otherwise, rebuild the match list */
- if (menustate->search[0] != 0 || menustate->matchlist[0] == NULL || menustate->rerandomize)
- driver_list_get_approx_matches(menustate->driverlist, menustate->search, matchcount, menustate->matchlist);
+ assert(drivlist != NULL);
+ if (menustate->search[0] != 0 || menustate->matchlist[0] == -1 || menustate->rerandomize)
+ drivlist->find_approximate_matches(menustate->search, matchcount, menustate->matchlist);
menustate->rerandomize = FALSE;
/* iterate over entries */
for (curitem = 0; curitem < matchcount; curitem++)
{
- const game_driver *driver = menustate->matchlist[curitem];
- if (driver != NULL)
+ int curmatch = menustate->matchlist[curitem];
+ if (curmatch != -1)
{
- const game_driver *cloneof = driver_get_clone(driver);
- ui_menu_item_append(menu, driver->name, driver->description, (cloneof == NULL || (cloneof->flags & GAME_IS_BIOS_ROOT)) ? 0 : MENU_FLAG_INVERT, (void *)driver);
+ int cloneof = drivlist->non_bios_clone(curmatch);
+ ui_menu_item_append(menu, drivlist->driver(curmatch).name, drivlist->driver(curmatch).description, (cloneof == -1) ? 0 : MENU_FLAG_INVERT, (void *)&drivlist->driver(curmatch));
}
}
@@ -3579,41 +3579,17 @@ static void menu_select_game_populate(running_machine &machine, ui_menu *menu, s
/*-------------------------------------------------
- menu_select_game_driver_compare - compare the
- names of two drivers
--------------------------------------------------*/
-
-static int CLIB_DECL menu_select_game_driver_compare(const void *elem1, const void *elem2)
-{
- const game_driver **driver1_ptr = (const game_driver **)elem1;
- const game_driver **driver2_ptr = (const game_driver **)elem2;
- const char *driver1 = (*driver1_ptr)->name;
- const char *driver2 = (*driver2_ptr)->name;
-
- while (*driver1 == *driver2 && *driver1 != 0)
- driver1++, driver2++;
- return *driver1 - *driver2;
-}
-
-
-/*-------------------------------------------------
menu_select_game_build_driver_list - build a
list of available drivers
-------------------------------------------------*/
static void menu_select_game_build_driver_list(ui_menu *menu, select_game_state *menustate)
{
- int driver_count = driver_list_get_count(drivers);
- int drivnum, listnum;
- UINT8 *found;
-
- /* create a sorted copy of the main driver list */
- memcpy((void *)menustate->driverlist, drivers, driver_count * sizeof(menustate->driverlist[0]));
- qsort((void *)menustate->driverlist, driver_count, sizeof(menustate->driverlist[0]), menu_select_game_driver_compare);
-
- /* allocate a temporary array to track which ones we found */
- found = (UINT8 *)ui_menu_pool_alloc(menu, (driver_count + 7) / 8);
- memset(found, 0, (driver_count + 7) / 8);
+ // start with an empty list
+ // hack alert: use new directly here to avoid reporting this one-time static memory as unfreed
+ if (drivlist == NULL)
+ drivlist = new driver_enumerator(menu->machine().options());
+ drivlist->exclude_all();
/* open a path to the ROMs and find them in the array */
file_enumerator path(menu->machine().options().media_path());
@@ -3622,9 +3598,6 @@ static void menu_select_game_build_driver_list(ui_menu *menu, select_game_state
/* iterate while we get new objects */
while ((dir = path.next()) != NULL)
{
- game_driver tempdriver;
- game_driver *tempdriver_ptr;
- const game_driver **found_driver;
char drivername[50];
char *dst = drivername;
const char *src;
@@ -3634,23 +3607,16 @@ static void menu_select_game_build_driver_list(ui_menu *menu, select_game_state
*dst++ = tolower((UINT8)*src);
*dst = 0;
- /* find it in the array */
- tempdriver.name = drivername;
- tempdriver_ptr = &tempdriver;
- found_driver = (const game_driver **)bsearch(&tempdriver_ptr, menustate->driverlist, driver_count, sizeof(*menustate->driverlist), menu_select_game_driver_compare);
-
- /* if found, mark the corresponding entry in the array */
- if (found_driver != NULL)
- {
- int index = found_driver - menustate->driverlist;
- found[index / 8] |= 1 << (index % 8);
- }
+ int drivnum = drivlist->find(drivername);
+ if (drivnum != -1)
+ drivlist->include(drivnum);
}
/* now build the final list */
- for (drivnum = listnum = 0; drivnum < driver_count; drivnum++)
- if (found[drivnum / 8] & (1 << (drivnum % 8)))
- menustate->driverlist[listnum++] = menustate->driverlist[drivnum];
+ drivlist->reset();
+ int listnum = 0;
+ while (drivlist->next())
+ menustate->driverlist[listnum++] = &drivlist->driver();
/* NULL-terminate */
menustate->driverlist[listnum] = NULL;
diff --git a/src/emu/validity.c b/src/emu/validity.c
index e15082da3c4..2e0fbbb84d1 100644
--- a/src/emu/validity.c
+++ b/src/emu/validity.c
@@ -314,12 +314,11 @@ static bool validate_inlines(void)
information
-------------------------------------------------*/
-static bool validate_driver(const machine_config &config, game_driver_map &names, game_driver_map &descriptions)
+static bool validate_driver(driver_enumerator &drivlist, game_driver_map &names, game_driver_map &descriptions)
{
- const game_driver &driver = config.gamedrv();
- const game_driver *clone_of;
+ const game_driver &driver = drivlist.driver();
+ const machine_config &config = drivlist.config();
const char *compatible_with;
- const game_driver *other_drv;
bool error = FALSE, is_clone;
const char *s;
@@ -343,27 +342,27 @@ static bool validate_driver(const machine_config &config, game_driver_map &names
/* determine the clone */
is_clone = (strcmp(driver.parent, "0") != 0);
- clone_of = driver_get_clone(&driver);
- if (clone_of && (clone_of->flags & GAME_IS_BIOS_ROOT))
+ int clone_of = drivlist.clone(driver);
+ if (clone_of != -1 && (drivlist.driver(clone_of).flags & GAME_IS_BIOS_ROOT))
is_clone = false;
/* if we have at least 100 drivers, validate the clone */
/* (100 is arbitrary, but tries to avoid tiny.mak dependencies) */
- if (driver_list_get_count(drivers) > 100 && !clone_of && is_clone)
+ if (driver_list::total() > 100 && clone_of == -1 && is_clone)
{
mame_printf_error("%s: %s is a non-existant clone\n", driver.source_file, driver.parent);
error = true;
}
/* look for recursive cloning */
- if (clone_of == &driver)
+ if (clone_of != -1 && &drivlist.driver(clone_of) == &driver)
{
mame_printf_error("%s: %s is set as a clone of itself\n", driver.source_file, driver.name);
error = true;
}
/* look for clones that are too deep */
- if (clone_of != NULL && (clone_of = driver_get_clone(clone_of)) != NULL && (clone_of->flags & GAME_IS_BIOS_ROOT) == 0)
+ if (clone_of != -1 && (clone_of = drivlist.non_bios_clone(clone_of)) != -1)
{
mame_printf_error("%s: %s is a clone of a clone\n", driver.source_file, driver.name);
error = true;
@@ -392,23 +391,23 @@ static bool validate_driver(const machine_config &config, game_driver_map &names
compatible_with = NULL;
/* check for this driver being compatible with a non-existant driver */
- if ((compatible_with != NULL) && (driver_get_name(driver.compatible_with) == NULL))
+ if ((compatible_with != NULL) && (drivlist.find(driver.compatible_with) == -1))
{
mame_printf_error("%s: is compatible with %s, which is not in drivers[]\n", driver.name, driver.compatible_with);
error = true;
}
/* check for clone_of and compatible_with being specified at the same time */
- if ((driver_get_clone(&driver) != NULL) && (compatible_with != NULL))
+ if ((drivlist.clone(driver) != -1) && (compatible_with != NULL))
{
mame_printf_error("%s: both compatible_with and clone_of are specified\n", driver.name);
error = true;
}
/* find any recursive dependencies on the current driver */
- for (other_drv = driver_get_compatible(&driver); other_drv != NULL; other_drv = driver_get_compatible(other_drv))
+ for (int other_drv = drivlist.compatible_with(driver); other_drv != -1; other_drv = drivlist.compatible_with(other_drv))
{
- if (&driver == other_drv)
+ if (&driver == &drivlist.driver(other_drv))
{
mame_printf_error("%s: recursive compatibility\n", driver.name);
error = true;
@@ -432,9 +431,10 @@ static bool validate_driver(const machine_config &config, game_driver_map &names
validate_roms - validate ROM definitions
-------------------------------------------------*/
-static bool validate_roms(const machine_config &config, region_array *rgninfo, game_driver_map &roms)
+static bool validate_roms(driver_enumerator &drivlist, region_array *rgninfo, game_driver_map &roms)
{
- const game_driver &driver = config.gamedrv();
+ const game_driver &driver = drivlist.driver();
+ const machine_config &config = drivlist.config();
int bios_flags = 0, last_bios = 0;
const char *last_rgnname = "???";
const char *last_name = "???";
@@ -579,9 +579,10 @@ static bool validate_roms(const machine_config &config, region_array *rgninfo, g
configurations
-------------------------------------------------*/
-static bool validate_display(const machine_config &config)
+static bool validate_display(driver_enumerator &drivlist)
{
- const game_driver &driver = config.gamedrv();
+ const game_driver &driver = drivlist.driver();
+ const machine_config &config = drivlist.config();
bool palette_modes = false;
bool error = false;
@@ -605,9 +606,10 @@ static bool validate_display(const machine_config &config)
configuration
-------------------------------------------------*/
-static bool validate_gfx(const machine_config &config, region_array *rgninfo)
+static bool validate_gfx(driver_enumerator &drivlist, region_array *rgninfo)
{
- const game_driver &driver = config.gamedrv();
+ const game_driver &driver = drivlist.driver();
+ const machine_config &config = drivlist.config();
bool error = false;
int gfxnum;
@@ -939,12 +941,13 @@ static void validate_dip_settings(const input_field_config *field, const game_dr
validate_inputs - validate input configuration
-------------------------------------------------*/
-static bool validate_inputs(const machine_config &config, int_map &defstr_map, ioport_list &portlist)
+static bool validate_inputs(driver_enumerator &drivlist, int_map &defstr_map, ioport_list &portlist)
{
const input_port_config *scanport;
const input_port_config *port;
const input_field_config *field;
- const game_driver &driver = config.gamedrv();
+ const game_driver &driver = drivlist.driver();
+ const machine_config &config = drivlist.config();
int empty_string_found = FALSE;
char errorbuf[1024];
bool error = false;
@@ -1088,10 +1091,11 @@ static bool validate_inputs(const machine_config &config, int_map &defstr_map, i
checks
-------------------------------------------------*/
-static bool validate_devices(const machine_config &config, const ioport_list &portlist, region_array *rgninfo)
+static bool validate_devices(driver_enumerator &drivlist, const ioport_list &portlist, region_array *rgninfo)
{
bool error = false;
- const game_driver &driver = config.gamedrv();
+ const game_driver &driver = drivlist.driver();
+ const machine_config &config = drivlist.config();
for (const device_config *devconfig = config.m_devicelist.first(); devconfig != NULL; devconfig = devconfig->next())
{
@@ -1126,7 +1130,6 @@ static bool validate_devices(const machine_config &config, const ioport_list &po
void validate_drivers(emu_options &options, const game_driver *curdriver)
{
osd_ticks_t prep = 0;
- osd_ticks_t expansion = 0;
osd_ticks_t driver_checks = 0;
osd_ticks_t rom_checks = 0;
osd_ticks_t gfx_checks = 0;
@@ -1186,9 +1189,10 @@ void validate_drivers(emu_options &options, const game_driver *curdriver)
prep += get_profile_ticks();
/* iterate over all drivers */
- for (int drivnum = 0; drivers[drivnum]; drivnum++)
+ driver_enumerator drivlist(options);
+ while (drivlist.next())
{
- const game_driver &driver = *drivers[drivnum];
+ const game_driver &driver = drivlist.driver();
ioport_list portlist;
region_array rgninfo;
@@ -1198,39 +1202,34 @@ void validate_drivers(emu_options &options, const game_driver *curdriver)
try
{
- /* expand the machine driver */
- expansion -= get_profile_ticks();
- machine_config config(driver, options);
- expansion += get_profile_ticks();
-
/* validate the driver entry */
driver_checks -= get_profile_ticks();
- error = validate_driver(config, names, descriptions) || error;
+ error = validate_driver(drivlist, names, descriptions) || error;
driver_checks += get_profile_ticks();
/* validate the ROM information */
rom_checks -= get_profile_ticks();
- error = validate_roms(config, &rgninfo, roms) || error;
+ error = validate_roms(drivlist, &rgninfo, roms) || error;
rom_checks += get_profile_ticks();
/* validate input ports */
input_checks -= get_profile_ticks();
- error = validate_inputs(config, defstr, portlist) || error;
+ error = validate_inputs(drivlist, defstr, portlist) || error;
input_checks += get_profile_ticks();
/* validate the display */
display_checks -= get_profile_ticks();
- error = validate_display(config) || error;
+ error = validate_display(drivlist) || error;
display_checks += get_profile_ticks();
/* validate the graphics decoding */
gfx_checks -= get_profile_ticks();
- error = validate_gfx(config, &rgninfo) || error;
+ error = validate_gfx(drivlist, &rgninfo) || error;
gfx_checks += get_profile_ticks();
/* validate devices */
device_checks -= get_profile_ticks();
- error = validate_devices(config, portlist, &rgninfo) || error;
+ error = validate_devices(drivlist, portlist, &rgninfo) || error;
device_checks += get_profile_ticks();
}
catch (emu_fatalerror &err)
@@ -1241,7 +1240,6 @@ void validate_drivers(emu_options &options, const game_driver *curdriver)
#if (REPORT_TIMES)
mame_printf_info("Prep: %8dm\n", (int)(prep / 1000000));
- mame_printf_info("Expansion: %8dm\n", (int)(expansion / 1000000));
mame_printf_info("Driver: %8dm\n", (int)(driver_checks / 1000000));
mame_printf_info("ROM: %8dm\n", (int)(rom_checks / 1000000));
mame_printf_info("CPU: %8dm\n", (int)(cpu_checks / 1000000));