summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
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));