Redo of split of src/emu/softlist.[cpp|h]

This is a redo of the split first submitted in #137, with the following differences:
* The newly refactored rom_entry data structure is used
* I've kept the refactored softlist code in src/emu, in order to defer the mechanical process of moving it
* I've kept includes of softlist[_dev].h out of diimage.h, so that changes to either do not trigger an emu.h recompilation
* Obviously, this goes against the latest master
This commit is contained in:
Nathan Woods 2016-08-02 07:01:29 -04:00
parent 159b73a708
commit f9db568146
79 changed files with 1023 additions and 823 deletions

View File

@ -158,6 +158,8 @@ files {
MAME_DIR .. "src/emu/screen.h",
MAME_DIR .. "src/emu/softlist.cpp",
MAME_DIR .. "src/emu/softlist.h",
MAME_DIR .. "src/emu/softlist_dev.cpp",
MAME_DIR .. "src/emu/softlist_dev.h",
MAME_DIR .. "src/emu/sound.cpp",
MAME_DIR .. "src/emu/sound.h",
MAME_DIR .. "src/emu/speaker.cpp",

View File

@ -3,6 +3,8 @@
#ifndef __A78_SLOT_H
#define __A78_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS

View File

@ -3,6 +3,8 @@
#ifndef __A800_SLOT_H
#define __A800_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS

View File

@ -12,7 +12,7 @@
#define __ADAM_EXPANSION_SLOT__
#include "emu.h"
#include "softlist_dev.h"
//**************************************************************************

View File

@ -3,6 +3,8 @@
#ifndef __APF_SLOT_H
#define __APF_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __ARCADIA_SLOT_H
#define __ARCADIA_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __ASTROCADE_SLOT_H
#define __ASTROCADE_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -37,6 +37,7 @@
#define __C64_EXPANSION_SLOT__
#include "emu.h"
#include "softlist_dev.h"
#include "formats/cbm_crt.h"

View File

@ -30,6 +30,7 @@
#define __CBM2_EXPANSION_SLOT__
#include "emu.h"
#include "softlist_dev.h"

View File

@ -3,6 +3,9 @@
#ifndef __CHANF_SLOT_H
#define __CHANF_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -11,6 +11,8 @@
#ifndef __COCOCART_H__
#define __COCOCART_H__
#include "softlist_dev.h"
/***************************************************************************
CONSTANTS

View File

@ -31,7 +31,7 @@
#define __COLECOVISION_CARTRIDGE_SLOT__
#include "emu.h"
#include "softlist_dev.h"
//**************************************************************************

View File

@ -3,6 +3,9 @@
#ifndef __CRVISION_SLOT_H
#define __CRVISION_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __GB_SLOT_H
#define __GB_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __GBA_SLOT_H
#define __GBA_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __GENERIC_SLOT_H
#define __GENERIC_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -14,6 +14,8 @@
#define _HP_OPTROM_H_
#include "emu.h"
#include "softlist_dev.h"
class hp_optrom_cart_device : public device_t,
public device_slot_card_interface

View File

@ -3,6 +3,9 @@
#ifndef __INTV_SLOT_H
#define __INTV_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -45,6 +45,8 @@
#ifndef __IQ151CART_H__
#define __IQ151CART_H__
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -15,6 +15,8 @@
#include "emu.h"
#include "bus/isa/isa.h"
#include "softlist_dev.h"
//**************************************************************************
// TYPE DEFINITIONS

View File

@ -11,6 +11,8 @@
#ifndef __KCEXP_H__
#define __KCEXP_H__
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __M5_SLOT_H
#define __M5_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,8 @@
#ifndef __MD_SLOT_H
#define __MD_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -5,6 +5,7 @@
#include "slot.h"
#include "bus/msx_cart/cartridge.h"
#include "softlist_dev.h"
extern const device_type MSX_SLOT_CARTRIDGE;

View File

@ -4,6 +4,8 @@
#define __NEOGEO_SLOT_H
#include "emu.h"
#include "softlist_dev.h"
/* PCB */
enum

View File

@ -4,6 +4,7 @@
#define __NES_ALADDIN_H
#include "nxrom.h"
#include "softlist_dev.h"
//----------------------------------

View File

@ -4,6 +4,7 @@
#define __NES_DATACH_H
#include "bandai.h"
#include "softlist_dev.h"
#include "machine/i2cmem.h"
#include "machine/bcreader.h"

View File

@ -4,6 +4,7 @@
#define __NES_KARASTUDIO_H
#include "nxrom.h"
#include "softlist_dev.h"
//-----------------------------------------

View File

@ -3,6 +3,9 @@
#ifndef __NES_SLOT_H__
#define __NES_SLOT_H__
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -4,6 +4,7 @@
#define __NES_SUNSOFT_DCS_H
#include "sunsoft.h"
#include "softlist_dev.h"
//-----------------------------------------------

View File

@ -3,6 +3,9 @@
#ifndef __O2_SLOT_H
#define __O2_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __PCE_SLOT_H
#define __PCE_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -40,7 +40,7 @@
#define __PLUS4_EXPANSION_SLOT__
#include "emu.h"
#include "softlist_dev.h"
//**************************************************************************

View File

@ -31,7 +31,7 @@
#define __QL_ROM_CARTRIDGE_SLOT__
#include "emu.h"
#include "softlist_dev.h"
//**************************************************************************

View File

@ -3,6 +3,9 @@
#ifndef __SAT_SLOT_H
#define __SAT_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __SCV_SLOT_H
#define __SCV_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __SEGA8_SLOT_H
#define __SEGA8_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __SNS_SLOT_H
#define __SNS_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -12,6 +12,8 @@
#include "emu.h"
#include "ti99defs.h"
#include "machine/tmc0430.h"
#include "softlist_dev.h"
extern const device_type GROMPORT;

View File

@ -3,6 +3,9 @@
#ifndef __VBOY_SLOT_H
#define __VBOY_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,9 @@
#ifndef __VC4000_SLOT_H
#define __VC4000_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -3,6 +3,8 @@
#ifndef __VCS_SLOT_H
#define __VCS_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS

View File

@ -3,6 +3,9 @@
#ifndef __VECTREX_SLOT_H
#define __VECTREX_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -37,10 +37,10 @@
#define __VIC10_EXPANSION_SLOT__
#include "emu.h"
#include "softlist_dev.h"
#include "formats/cbm_crt.h"
//**************************************************************************
// CONSTANTS
//**************************************************************************

View File

@ -37,7 +37,7 @@
#define __VIC20_EXPANSION_SLOT__
#include "emu.h"
#include "softlist_dev.h"
//**************************************************************************

View File

@ -40,7 +40,7 @@
#define __VIDEOBRAIN_EXPANSION_SLOT__
#include "emu.h"
#include "softlist_dev.h"
//**************************************************************************

View File

@ -3,6 +3,9 @@
#ifndef __WS_SLOT_H
#define __WS_SLOT_H
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -54,6 +54,9 @@
#ifndef __Z88CART_H__
#define __Z88CART_H__
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/

View File

@ -12,6 +12,7 @@
#define CASSETTE_H
#include "formats/cassimg.h"
#include "softlist_dev.h"
enum cassette_state

View File

@ -12,6 +12,7 @@
#define CHD_CD_H
#include "cdrom.h"
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS

View File

@ -8,6 +8,7 @@
#define _IMAGEDEV_DIABLO_H_
#include "harddisk.h"
#include "softlist_dev.h"
#define DIABLO_TAG(_id) "diablo"#_id

View File

@ -7,6 +7,7 @@
#define __FLOPDRV_H__
#include "formats/flopimg.h"
#include "softlist_dev.h"
#define FLOPPY_TYPE_REGULAR 0
#define FLOPPY_TYPE_APPLE 1

View File

@ -20,6 +20,7 @@
#include "formats/cqm_dsk.h"
#include "formats/dsk_dsk.h"
#include "sound/samples.h"
#include "softlist_dev.h"
#define MCFG_FLOPPY_DRIVE_ADD(_tag, _slot_intf, _def_slot, _formats) \
MCFG_DEVICE_ADD(_tag, FLOPPY_CONNECTOR, 0) \

View File

@ -12,6 +12,7 @@
#define HARDDRIV_H
#include "harddisk.h"
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS

View File

@ -11,6 +11,8 @@
#ifndef __SNAPQUIK_H__
#define __SNAPQUIK_H__
#include "softlist_dev.h"
typedef delegate<image_init_result (device_image_interface &,const char *, int)> snapquick_load_delegate;
// ======================> snapshot_image_device

View File

@ -8,6 +8,7 @@
#define __SMARTMEDIA_H__
#include "formats/imageutl.h"
#include "softlist_dev.h"
//#define SMARTMEDIA_IMAGE_SAVE

View File

@ -15,6 +15,7 @@
#include "ui/uimain.h"
#include "zippath.h"
#include "softlist.h"
#include "softlist_dev.h"
#include "formats/ioprocs.h"
#include <regex>
@ -840,9 +841,9 @@ bool device_image_interface::load_software(software_list_device &swlist, const c
UINT32 supported = swinfo->supported();
if (supported == SOFTWARE_SUPPORTED_PARTIAL)
osd_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name());
osd_printf_error("WARNING: support for software %s (in list %s) is only partial\n", swname, swlist.list_name().c_str());
if (supported == SOFTWARE_SUPPORTED_NO)
osd_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name());
osd_printf_error("WARNING: support for software %s (in list %s) is only preliminary\n", swname, swlist.list_name().c_str());
// attempt reading up the chain through the parents and create a locationtag std::string in the format
// " swlist % clonename % parentname "
@ -1036,7 +1037,8 @@ image_init_result device_image_interface::load_software(const std::string &softl
m_is_loading = true;
// Check if there's a software list defined for this device and use that if we're not creating an image
bool softload = load_software_part(softlist_name.c_str(), m_software_part_ptr);
std::string list_name;
bool softload = load_software_part(softlist_name.c_str(), m_software_part_ptr, &list_name);
if (!softload)
{
m_is_loading = false;
@ -1045,8 +1047,8 @@ image_init_result device_image_interface::load_software(const std::string &softl
// set up softlist stuff
m_software_info_ptr = &m_software_part_ptr->info();
m_software_list_name.assign(m_software_info_ptr->list().list_name());
m_full_software_name.assign(m_software_part_ptr->info().shortname());
m_software_list_name = std::move(list_name);
m_full_software_name = m_software_part_ptr->info().shortname();
// specify image name with softlist-derived names
m_image_name = m_full_software_name;
@ -1301,7 +1303,11 @@ void device_image_interface::software_name_split(const char *swlist_swname, std:
}
const software_part *device_image_interface::find_software_item(const char *path, bool restrict_to_interface) const
//-------------------------------------------------
// find_software_item
//-------------------------------------------------
const software_part *device_image_interface::find_software_item(const char *path, bool restrict_to_interface, software_list_device **dev) const
{
// split full software name into software list name and short software name
std::string swlist_name, swinfo_name, swpart_name;
@ -1322,7 +1328,11 @@ const software_part *device_image_interface::find_software_item(const char *path
{
const software_part *part = info->find_part(swpart_name.c_str(), interface);
if (part != nullptr)
{
if (dev != nullptr)
*dev = &swlistdev;
return part;
}
}
}
@ -1337,16 +1347,32 @@ const software_part *device_image_interface::find_software_item(const char *path
{
const software_part *part = info->find_part(nullptr, interface);
if (part != nullptr)
{
if (dev != nullptr)
*dev = &swlistdev;
return part;
}
}
}
}
// if explicitly specified and not found, just error here
if (dev != nullptr)
*dev = nullptr;
return nullptr;
}
//-------------------------------------------------
// get_software_list_loader
//-------------------------------------------------
const software_list_loader &device_image_interface::get_software_list_loader() const
{
return false_software_list_loader::instance();
}
//-------------------------------------------------
// load_software_part
//
@ -1360,10 +1386,11 @@ const software_part *device_image_interface::find_software_item(const char *path
// sw_info and sw_part are also set.
//-------------------------------------------------
bool device_image_interface::load_software_part(const char *path, const software_part *&swpart)
bool device_image_interface::load_software_part(const char *path, const software_part *&swpart, std::string *list_name)
{
// if no match has been found, we suggest similar shortnames
swpart = find_software_item(path, true);
software_list_device *swlist;
swpart = find_software_item(path, true, &swlist);
if (swpart == nullptr)
{
software_list_device::display_matches(device().machine().config(), image_interface(), path);
@ -1371,11 +1398,10 @@ bool device_image_interface::load_software_part(const char *path, const software
}
// Load the software part
software_list_device &swlist = swpart->info().list();
const char *swname = swpart->info().shortname().c_str();
const rom_entry *start_entry = swpart->romdata();
const rom_entry *start_entry = swpart->romdata().data();
const software_list_loader &loader = get_software_list_loader();
bool result = loader.load_software(*this, swlist, swname, start_entry);
bool result = loader.load_software(*this, *swlist, swname, start_entry);
#ifdef UNUSED_VARIABLE
// Tell the world which part we actually loaded
@ -1383,17 +1409,17 @@ bool device_image_interface::load_software_part(const char *path, const software
#endif
// check compatibility
switch (swpart->is_compatible(swlist))
switch (swlist->is_compatible(*swpart))
{
case SOFTWARE_IS_COMPATIBLE:
break;
case SOFTWARE_IS_INCOMPATIBLE:
swlist.popmessage("WARNING! the set %s might not work on this system due to incompatible filter(s) '%s'\n", swpart->info().shortname(), swlist.filter());
swlist->popmessage("WARNING! the set %s might not work on this system due to incompatible filter(s) '%s'\n", swpart->info().shortname(), swlist->filter());
break;
case SOFTWARE_NOT_COMPATIBLE:
swlist.popmessage("WARNING! the set %s might not work on this system due to missing filter(s) '%s'\n", swpart->info().shortname(), swlist.filter());
swlist->popmessage("WARNING! the set %s might not work on this system due to missing filter(s) '%s'\n", swpart->info().shortname(), swlist->filter());
break;
}
@ -1404,7 +1430,7 @@ bool device_image_interface::load_software_part(const char *path, const software
const software_part *req_swpart = find_software_item(requirement, false);
if (req_swpart != nullptr)
{
device_image_interface *req_image = req_swpart->find_mountable_image(device().mconfig());
device_image_interface *req_image = software_list_device::find_mountable_image(device().mconfig(), *req_swpart);
if (req_image != nullptr)
{
req_image->set_init_phase();
@ -1412,6 +1438,8 @@ bool device_image_interface::load_software_part(const char *path, const software
}
}
}
if (list_name != nullptr)
*list_name = swlist->list_name();
return result;
}

View File

@ -21,8 +21,6 @@
#include <string>
#include <vector>
#include "softlist.h"
//**************************************************************************
// TYPE DEFINITIONS
@ -31,6 +29,7 @@
extern struct io_procs image_ioprocs;
class software_list;
class software_list_loader;
enum iodevice_t
{
@ -252,7 +251,7 @@ public:
bool user_loadable() const { return m_user_loadable; }
protected:
virtual const software_list_loader &get_software_list_loader() const { return false_software_list_loader::instance(); }
virtual const software_list_loader &get_software_list_loader() const;
image_init_result load_internal(const std::string &path, bool is_create, int create_format, util::option_resolution *create_args, bool just_load);
void determine_open_plan(int is_create, UINT32 *open_plan);
@ -273,8 +272,8 @@ protected:
void image_checkhash();
void update_names(const device_type device_type = nullptr, const char *inst = nullptr, const char *brief = nullptr);
const software_part *find_software_item(const char *path, bool restrict_to_interface) const;
bool load_software_part(const char *path, const software_part *&swpart);
const software_part *find_software_item(const char *path, bool restrict_to_interface, software_list_device **device = nullptr) const;
bool load_software_part(const char *path, const software_part *&swpart, std::string *list_name = nullptr);
std::string software_get_default_slot(const char *default_card_slot) const;
void add_format(std::unique_ptr<image_device_format> &&format);

View File

@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
drivenum.c
drivenum.cpp
Driver enumeration helpers.
@ -10,7 +10,7 @@
#include "emu.h"
#include "drivenum.h"
#include "softlist.h"
#include "softlist_dev.h"
#include <ctype.h>

View File

@ -2,7 +2,7 @@
// copyright-holders:Nicola Salmoria,Paul Priest,Aaron Giles
/*********************************************************************
romload.c
romload.cpp
ROM loading functions.
*********************************************************************/
@ -10,7 +10,7 @@
#include "emu.h"
#include "emuopts.h"
#include "drivenum.h"
#include "softlist.h"
#include "softlist_dev.h"
#include "ui/uimain.h"

View File

@ -2,137 +2,16 @@
// copyright-holders:Wilbert Pol
/***************************************************************************
softlist.c
softlist.cpp
Software list construction helpers.
***************************************************************************/
#include "emu.h"
#include "emuopts.h"
#include "softlist.h"
#include "validity.h"
#include "hash.h"
#include "expat.h"
#include <ctype.h>
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
typedef std::unordered_map<std::string,const software_info *> softlist_map;
// ======================> softlist_parser
class softlist_parser
{
public:
// construction (== execution)
softlist_parser(software_list_device &list, std::ostringstream &errors);
private:
enum parse_position
{
POS_ROOT,
POS_MAIN,
POS_SOFT,
POS_PART,
POS_DATA
};
// internal parsing helpers
const char *filename() const { return m_list.filename(); }
const char *infoname() const { return (m_current_info != nullptr) ? m_current_info->shortname().c_str() : "???"; }
int line() const { return XML_GetCurrentLineNumber(m_parser); }
int column() const { return XML_GetCurrentColumnNumber(m_parser); }
const char *parser_error() const { return XML_ErrorString(XML_GetErrorCode(m_parser)); }
// internal error helpers
template <typename Format, typename... Params> void parse_error(Format &&fmt, Params &&... args);
void unknown_tag(const char *tagname) { parse_error("Unknown tag: %s", tagname); }
void unknown_attribute(const char *attrname) { parse_error("Unknown attribute: %s", attrname); }
// internal helpers
template <typename T> std::vector<std::string> parse_attributes(const char **attributes, const T &attrlist);
bool parse_name_and_value(const char **attributes, std::string &name, std::string &value);
void add_rom_entry(std::string &&name, std::string &&hashdata, UINT32 offset, UINT32 length, UINT32 flags);
// expat callbacks
static void start_handler(void *data, const char *tagname, const char **attributes);
static void data_handler(void *data, const XML_Char *s, int len);
static void end_handler(void *data, const char *name);
// internal parsing
void parse_root_start(const char *tagname, const char **attributes);
void parse_main_start(const char *tagname, const char **attributes);
void parse_soft_start(const char *tagname, const char **attributes);
void parse_part_start(const char *tagname, const char **attributes);
void parse_data_start(const char *tagname, const char **attributes);
void parse_soft_end(const char *name);
// internal parsing state
software_list_device & m_list;
std::ostringstream & m_errors;
XML_Parser m_parser;
bool m_done;
bool m_data_accum_expected;
std::string m_data_accum;
software_info * m_current_info;
software_part * m_current_part;
parse_position m_pos;
};
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
const device_type SOFTWARE_LIST = &device_creator<software_list_device>;
false_software_list_loader false_software_list_loader::s_instance;
rom_software_list_loader rom_software_list_loader::s_instance;
image_software_list_loader image_software_list_loader::s_instance;
//**************************************************************************
// SOFTWARE LIST LOADER
//**************************************************************************
//-------------------------------------------------
// false_software_list_loader::load_software
//-------------------------------------------------
bool false_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
{
return false;
}
//-------------------------------------------------
// rom_software_list_loader::load_software
//-------------------------------------------------
bool rom_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
{
swlist.machine().rom_load().load_software_part_region(device, swlist, swname, start_entry);
return true;
}
//-------------------------------------------------
// image_software_list_loader::load_software
//-------------------------------------------------
bool image_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
{
return device.load_software(swlist, swname, start_entry);
}
//**************************************************************************
// FEATURE LIST ITEM
//**************************************************************************
@ -194,56 +73,6 @@ const char *software_part::feature(const std::string &feature_name) const
}
//-------------------------------------------------
// is_compatible - determine if we are compatible
// with the given software_list_device
//-------------------------------------------------
software_compatibility software_part::is_compatible(const software_list_device &swlistdev) const
{
// get the softlist filter; if null, assume compatible
const char *filter = swlistdev.filter();
if (filter == nullptr)
return SOFTWARE_IS_COMPATIBLE;
// copy the comma-delimited string and ensure it ends with a final comma
std::string filt = std::string(filter).append(",");
// get the incompatibility filter and test against it first if it exists
const char *incompatibility = feature("incompatibility");
if (incompatibility != nullptr)
{
// copy the comma-delimited string and ensure it ends with a final comma
std::string incomp = std::string(incompatibility).append(",");
// iterate over filter items and see if they exist in the list; if so, it's incompatible
for (int start = 0, end = filt.find_first_of(',',start); end != -1; start = end + 1, end = filt.find_first_of(',', start))
{
std::string token(filt, start, end - start + 1);
if (incomp.find(token) != -1)
return SOFTWARE_IS_INCOMPATIBLE;
}
}
// get the compatibility feature; if null, assume compatible
const char *compatibility = feature("compatibility");
if (compatibility == nullptr)
return SOFTWARE_IS_COMPATIBLE;
// copy the comma-delimited string and ensure it ends with a final comma
std::string comp = std::string(compatibility).append(",");
// iterate over filter items and see if they exist in the compatibility list; if so, it's compatible
for (int start = 0, end = filt.find_first_of(',',start); end != -1; start = end + 1, end = filt.find_first_of(',', start))
{
std::string token(filt, start, end - start + 1);
if (comp.find(token) != -1)
return SOFTWARE_IS_COMPATIBLE;
}
return SOFTWARE_NOT_COMPATIBLE;
}
//-------------------------------------------------
// matches_interface - determine if we match
// an interface in the provided list
@ -264,35 +93,6 @@ bool software_part::matches_interface(const char *interface_list) const
}
//-------------------------------------------------
// find_mountable_image - find an image interface
// that can automatically mount this software part
//-------------------------------------------------
device_image_interface *software_part::find_mountable_image(const machine_config &mconfig) const
{
// if automount="no", don't bother
const char *mount = feature("automount");
if (mount != nullptr && strcmp(mount, "no") == 0)
return nullptr;
for (device_image_interface &image : image_interface_iterator(mconfig.root_device()))
{
const char *interface = image.image_interface();
if (interface != nullptr && matches_interface(interface))
{
// mount only if not already mounted
const char *option = mconfig.options().value(image.brief_instance_name());
if (*option == '\0' && !image.filename())
return &image;
}
}
return nullptr;
}
//**************************************************************************
// SOFTWARE INFO
//**************************************************************************
@ -301,9 +101,8 @@ device_image_interface *software_part::find_mountable_image(const machine_config
// software_info - constructor
//-------------------------------------------------
software_info::software_info(software_list_device &list, std::string &&name, std::string &&parent, const char *supported)
software_info::software_info(std::string &&name, std::string &&parent, const char *supported)
: m_next(nullptr),
m_list(list),
m_supported(SOFTWARE_SUPPORTED_YES),
m_shortname(std::move(name)),
m_parentname(std::move(parent))
@ -365,383 +164,6 @@ bool software_info::has_multiple_parts(const char *interface) const
}
//**************************************************************************
// SOFTWARE LIST DEVICE
//**************************************************************************
//-------------------------------------------------
// software_list_device - constructor
//-------------------------------------------------
software_list_device::software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SOFTWARE_LIST, "Software list", tag, owner, clock, "software_list", __FILE__),
m_list_type(SOFTWARE_LIST_ORIGINAL_SYSTEM),
m_filter(nullptr),
m_parsed(false),
m_file(mconfig.options().hash_path(), OPEN_FLAG_READ),
m_description("")
{
}
//-------------------------------------------------
// static_set_type - configuration helper
// to set the list type
//-------------------------------------------------
void software_list_device::static_set_type(device_t &device, const char *list, softlist_type list_type)
{
software_list_device &swlistdev = downcast<software_list_device &>(device);
swlistdev.m_list_name.assign(list);
swlistdev.m_list_type = list_type;
}
//-------------------------------------------------
// static_set_custom_handler - configuration
// helper to set a custom callback
//-------------------------------------------------
void software_list_device::static_set_filter(device_t &device, const char *filter)
{
downcast<software_list_device &>(device).m_filter = filter;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void software_list_device::device_start()
{
}
//-------------------------------------------------
// find_approx_matches - search ourselves for
// a list of possible matches of the given name
// and optional interface
//-------------------------------------------------
void software_list_device::find_approx_matches(const char *name, int matches, const software_info **list, const char *interface)
{
// if no name, return
if (name == nullptr || name[0] == 0)
return;
// initialize everyone's states
std::vector<int> penalty(matches);
for (int matchnum = 0; matchnum < matches; matchnum++)
{
penalty[matchnum] = 9999;
list[matchnum] = nullptr;
}
// iterate over our info (will cause a parse if needed)
for (const software_info &swinfo : get_info())
{
const software_part &part = swinfo.parts().front();
if ((interface == nullptr || part.matches_interface(interface)) && part.is_compatible(*this) == SOFTWARE_IS_COMPATIBLE)
{
// pick the best match between driver name and description
int longpenalty = driver_list::penalty_compare(name, swinfo.longname().c_str());
int shortpenalty = driver_list::penalty_compare(name, swinfo.shortname().c_str());
int curpenalty = std::min(longpenalty, shortpenalty);
// insert into the sorted table of matches
for (int matchnum = matches - 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 < matches - 1)
{
penalty[matchnum + 1] = penalty[matchnum];
list[matchnum + 1] = list[matchnum];
}
list[matchnum] = &swinfo;
penalty[matchnum] = curpenalty;
}
}
}
}
//-------------------------------------------------
// release - reset to a pre-parsed state
//-------------------------------------------------
void software_list_device::release()
{
osd_printf_verbose("Resetting %s\n", m_file.filename());
m_parsed = false;
m_description.clear();
m_errors.clear();
m_infolist.clear();
}
//-------------------------------------------------
// find_by_name - find a software list by name
// across all software list devices
//-------------------------------------------------
software_list_device *software_list_device::find_by_name(const machine_config &config, const char *name)
{
// iterate over each device in the system and find a match
for (software_list_device &swlistdev : software_list_device_iterator(config.root_device()))
if (strcmp(swlistdev.list_name(), name) == 0)
return &swlistdev;
return nullptr;
}
//-------------------------------------------------
// software_display_matches - display a list of
// possible matches in the system to the given
// name, across all software list devices
//-------------------------------------------------
void software_list_device::display_matches(const machine_config &config, const char *interface, const char *name)
{
// check if there is at least one software list
software_list_device_iterator deviter(config.root_device());
if (deviter.first() != nullptr)
osd_printf_error("\n\"%s\" approximately matches the following\n"
"supported software items (best match first):\n\n", name);
// iterate through lists
for (software_list_device &swlistdev : deviter)
{
// get the top 16 approximate matches for the selected device interface (i.e. only carts for cartslot, etc.)
const software_info *matches[16] = { nullptr };
swlistdev.find_approx_matches(name, ARRAY_LENGTH(matches), matches, interface);
// if we found some, print them
if (matches[0] != nullptr)
{
// different output depending on original system or compatible
if (swlistdev.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM)
osd_printf_error("* Software list \"%s\" (%s) matches: \n", swlistdev.list_name(), swlistdev.description());
else
osd_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlistdev.list_name(), swlistdev.description());
// print them out
for (auto &match : matches)
{
if (match != nullptr)
osd_printf_error("%-18s%s\n", match->shortname().c_str(), match->longname().c_str());
}
osd_printf_error("\n");
}
}
}
//-------------------------------------------------
// find - find an item by name in the software
// list, using wildcards and optionally starting
// from an intermediate point
//-------------------------------------------------
const software_info *software_list_device::find(const char *look_for)
{
// nullptr search returns nothing
if (look_for == nullptr)
return nullptr;
bool iswild = strchr(look_for, '*') != nullptr || strchr(look_for, '?');
// find a match (will cause a parse if needed when calling get_info)
const auto &info_list = get_info();
auto iter = std::find_if(
info_list.begin(),
info_list.end(),
[&](const software_info &info)
{
const char *shortname = info.shortname().c_str();
return (iswild && core_strwildcmp(look_for, shortname) == 0)
|| core_stricmp(look_for, shortname) == 0;
});
return iter != info_list.end()
? &*iter
: nullptr;
}
//-------------------------------------------------
// parse - parse our softlist file
//-------------------------------------------------
void software_list_device::parse()
{
// skip if done
if (m_parsed)
return;
// reset the errors
m_errors.clear();
// attempt to open the file
osd_file::error filerr = m_file.open(m_list_name.c_str(), ".xml");
if (filerr == osd_file::error::NONE)
{
// parse if no error
std::ostringstream errs;
softlist_parser parser(*this, errs);
m_file.close();
m_errors = errs.str();
}
else
m_errors = string_format("Error opening file: %s\n", filename());
// indicate that we've been parsed
m_parsed = true;
}
//-------------------------------------------------
// device_validity_check - validate the device
// configuration
//-------------------------------------------------
void software_list_device::device_validity_check(validity_checker &valid) const
{
// add to the global map whenever we check a list so we don't re-check
// it in the future
if (valid.already_checked(std::string("softlist/").append(m_list_name).c_str()))
return;
// do device validation only in case of validate command
if (!valid.validate_all())
return;
// actually do the validate
const_cast<software_list_device *>(this)->internal_validity_check(valid);
}
//-------------------------------------------------
// internal_validity_check - internal helper to
// check the list
//-------------------------------------------------
void software_list_device::internal_validity_check(validity_checker &valid)
{
enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 };
softlist_map names;
softlist_map descriptions;
for (const software_info &swinfo : get_info())
{
// first parse and output core errors if any
if (m_errors.length() > 0)
{
osd_printf_error("%s: Errors parsing software list:\n%s", filename(), errors_string());
break;
}
// Now check if the xml data is valid:
// Did we lost any description?
if (swinfo.longname().empty())
{
osd_printf_error("%s: %s has no description\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost any year?
if (swinfo.year().empty())
{
osd_printf_error("%s: %s has no year\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost any publisher?
if (swinfo.publisher().empty())
{
osd_printf_error("%s: %s has no publisher\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost the software parts?
if (swinfo.parts().empty())
{
osd_printf_error("%s: %s has no part\n", filename(), swinfo.shortname().c_str());
break;
}
// Second, since the xml is fine, run additional checks:
// check for duplicate names
if (!names.insert(std::make_pair(swinfo.shortname(), &swinfo)).second)
{
const software_info *match = names.find(swinfo.shortname())->second;
osd_printf_error("%s: %s is a duplicate name (%s)\n", filename(), swinfo.shortname().c_str(), match->shortname().c_str());
}
// check for duplicate descriptions
std::string longname = std::string(swinfo.longname());
if (!descriptions.insert(std::make_pair(strmakelower(longname), &swinfo)).second)
osd_printf_error("%s: %s is a duplicate description (%s)\n", filename(), swinfo.longname().c_str(), swinfo.shortname().c_str());
bool is_clone = false;
if (!swinfo.parentname().empty())
{
is_clone = true;
if (swinfo.parentname() == swinfo.shortname())
{
osd_printf_error("%s: %s is set as a clone of itself\n", filename(), swinfo.shortname().c_str());
break;
}
// make sure the parent exists
const software_info *swinfo2 = find(swinfo.parentname().c_str());
if (swinfo2 == nullptr)
osd_printf_error("%s: parent '%s' software for '%s' not found\n", filename(), swinfo.parentname().c_str(), swinfo.shortname().c_str());
else if (!swinfo2->parentname().empty())
osd_printf_error("%s: %s is a clone of a clone\n", filename(), swinfo.shortname().c_str());
}
// make sure the driver name is 8 chars or less
if ((is_clone && swinfo.shortname().length() > NAME_LEN_CLONE) || (!is_clone && swinfo.shortname().length() > NAME_LEN_PARENT))
osd_printf_error("%s: %s %s driver name must be %d characters or less\n", filename(), swinfo.shortname().c_str(),
is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT);
// make sure the year is only digits, '?' or '+'
for (const char *s = swinfo.year().c_str(); *s != 0; s++)
if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
{
osd_printf_error("%s: %s has an invalid year '%s'\n", filename(), swinfo.shortname().c_str(), swinfo.year().c_str());
break;
}
softlist_map part_names;
for (const software_part &part : swinfo.parts())
{
if (part.interface().empty())
osd_printf_error("%s: %s has a part (%s) without interface\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
if (part.romdata() == nullptr)
osd_printf_error("%s: %s has a part (%s) with no data\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
if (!part_names.insert(std::make_pair(part.name(), &swinfo)).second)
osd_printf_error("%s: %s has a part (%s) whose name is duplicate\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
}
}
// release all the memory
release();
}
//**************************************************************************
// SOFTWARE LIST PARSER
//**************************************************************************
@ -750,8 +172,10 @@ void software_list_device::internal_validity_check(validity_checker &valid)
// softlist_parser - constructor
//-------------------------------------------------
softlist_parser::softlist_parser(software_list_device &list, std::ostringstream &errors)
: m_list(list),
softlist_parser::softlist_parser(util::core_file &file, const std::string &filename, std::list<software_info> &infolist, std::ostringstream &errors)
: m_file(file),
m_filename(filename),
m_infolist(infolist),
m_errors(errors),
m_done(false),
m_data_accum_expected(false),
@ -759,8 +183,6 @@ softlist_parser::softlist_parser(software_list_device &list, std::ostringstream
m_current_part(nullptr),
m_pos(POS_ROOT)
{
osd_printf_verbose("Parsing %s\n", m_list.m_file.filename());
// create the parser
m_parser = XML_ParserCreate_MM(nullptr, nullptr, nullptr);
if (m_parser == nullptr)
@ -772,12 +194,12 @@ softlist_parser::softlist_parser(software_list_device &list, std::ostringstream
XML_SetCharacterDataHandler(m_parser, &softlist_parser::data_handler);
// parse the file contents
m_list.m_file.seek(0, SEEK_SET);
m_file.seek(0, SEEK_SET);
char buffer[1024];
while (!m_done)
{
UINT32 length = m_list.m_file.read(buffer, sizeof(buffer));
m_done = m_list.m_file.eof();
UINT32 length = m_file.read(buffer, sizeof(buffer));
m_done = m_file.eof();
if (XML_Parse(m_parser, buffer, length, m_done) == XML_STATUS_ERROR)
{
parse_error("%s", parser_error());
@ -787,9 +209,39 @@ softlist_parser::softlist_parser(software_list_device &list, std::ostringstream
// free the parser
XML_ParserFree(m_parser);
osd_printf_verbose("Parsing complete\n");
}
//-------------------------------------------------
// line
//-------------------------------------------------
int softlist_parser::line() const
{
return XML_GetCurrentLineNumber(m_parser);
}
//-------------------------------------------------
// column
//-------------------------------------------------
int softlist_parser::column() const
{
return XML_GetCurrentColumnNumber(m_parser);
}
//-------------------------------------------------
// parser_error
//-------------------------------------------------
const char *softlist_parser::parser_error() const
{
return XML_ErrorString(XML_GetErrorCode(m_parser));
}
//-------------------------------------------------
// parse_error - append a parsing error with
// filename, line and column information
@ -799,7 +251,7 @@ template <typename Format, typename... Params>
inline void softlist_parser::parse_error(Format &&fmt, Params &&... args)
{
// always start with filename(line.column):
util::stream_format(m_errors, "%s(%d.%d): ", filename(), line(), column());
util::stream_format(m_errors, "%s(%d.%d): ", m_filename, line(), column());
// append the remainder of the string
util::stream_format(m_errors, std::forward<Format>(fmt), std::forward<Params>(args)...);
@ -894,17 +346,13 @@ void softlist_parser::add_rom_entry(std::string &&name, std::string &&hashdata,
// make sure we don't add duplicate regions
if (!name.empty() && (flags & ROMENTRY_TYPEMASK) == ROMENTRYTYPE_REGION)
{
for (auto &elem : m_current_part->m_romdata)
if (!elem.name().empty() && elem.name() == name)
if (elem.name() == name)
parse_error("Duplicated dataarea %s in software %s", name, infoname());
}
// create the new entry and append it
m_current_part->m_romdata.emplace_back(
std::move(name),
std::move(hashdata),
offset,
length,
flags);
m_current_part->m_romdata.emplace_back(std::move(name), std::move(hashdata), offset, length, flags);
}
@ -986,7 +434,7 @@ void softlist_parser::end_handler(void *data, const char *name)
// data_handler - expat data handler
//-------------------------------------------------
void softlist_parser::data_handler(void *data, const XML_Char *s, int len)
void softlist_parser::data_handler(void *data, const char *s, int len)
{
softlist_parser *state = reinterpret_cast<softlist_parser *>(data);
@ -1018,7 +466,7 @@ void softlist_parser::parse_root_start(const char *tagname, const char **attribu
const auto attrvalues = parse_attributes(attributes, attrnames);
if (!attrvalues[1].empty())
m_list.m_description = attrvalues[1];
m_description = attrvalues[1];
}
else
unknown_tag(tagname);
@ -1040,8 +488,8 @@ void softlist_parser::parse_main_start(const char *tagname, const char **attribu
if (!attrvalues[0].empty())
{
m_list.m_infolist.emplace_back(m_list, std::move(attrvalues[0]), std::move(attrvalues[1]), attrvalues[2].c_str());
m_current_info = &m_list.m_infolist.back();
m_infolist.emplace_back(std::move(attrvalues[0]), std::move(attrvalues[1]), attrvalues[2].c_str());
m_current_info = &m_infolist.back();
}
else
parse_error("No name defined for item");
@ -1354,7 +802,7 @@ void softlist_parser::parse_soft_end(const char *tagname)
return;
// was any dataarea/rom information encountered? if so, add a terminator
if (m_current_part->romdata() != nullptr)
if (!m_current_part->m_romdata.empty())
add_rom_entry("", "", 0, 0, ROMENTRYTYPE_END);
// get the info; if present, copy shared data (we assume name/value strings live
@ -1364,3 +812,4 @@ void softlist_parser::parse_soft_end(const char *tagname)
m_current_part->m_featurelist.emplace_back(item.name(), item.value());
}
}

View File

@ -4,15 +4,16 @@
softlist.h
Software and software list information.
Software list file format.
*********************************************************************/
#ifndef __SOFTLIST_H_
#define __SOFTLIST_H_
#include "cstrpool.h"
#include <list>
#include "romentry.h"
#include "corefile.h"
//**************************************************************************
@ -23,108 +24,13 @@
#define SOFTWARE_SUPPORTED_PARTIAL 1
#define SOFTWARE_SUPPORTED_NO 2
enum softlist_type
{
SOFTWARE_LIST_ORIGINAL_SYSTEM,
SOFTWARE_LIST_COMPATIBLE_SYSTEM
};
enum software_compatibility
{
SOFTWARE_IS_COMPATIBLE,
SOFTWARE_IS_INCOMPATIBLE,
SOFTWARE_NOT_COMPATIBLE
};
//**************************************************************************
// MACROS
//**************************************************************************
#define MCFG_SOFTWARE_LIST_CONFIG(_list,_list_type) \
software_list_device::static_set_type(*device, _list, _list_type);
#define MCFG_SOFTWARE_LIST_ADD( _tag, _list ) \
MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \
MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM)
#define MCFG_SOFTWARE_LIST_COMPATIBLE_ADD( _tag, _list ) \
MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \
MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM)
#define MCFG_SOFTWARE_LIST_MODIFY( _tag, _list ) \
MCFG_DEVICE_MODIFY( _tag ) \
MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM)
#define MCFG_SOFTWARE_LIST_COMPATIBLE_MODIFY( _tag, _list ) \
MCFG_DEVICE_MODIFY( _tag ) \
MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM)
#define MCFG_SOFTWARE_LIST_FILTER( _tag, _filter ) \
MCFG_DEVICE_MODIFY( _tag ) \
software_list_device::static_set_filter(*device, _filter);
#define MCFG_SOFTWARE_LIST_REMOVE( _tag ) \
MCFG_DEVICE_REMOVE( _tag )
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class rom_entry;
struct XML_ParserStruct;
class software_info;
class device_image_interface;
class software_list_device;
// ======================> software_list_loader
class software_list_loader
{
public:
virtual bool load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const = 0;
};
// ======================> false_software_list_loader
class false_software_list_loader : public software_list_loader
{
public:
virtual bool load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const override;
static const software_list_loader &instance() { return s_instance; }
private:
static false_software_list_loader s_instance;
};
// ======================> rom_software_list_loader
class rom_software_list_loader : public software_list_loader
{
public:
virtual bool load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const override;
static const software_list_loader &instance() { return s_instance; }
private:
static rom_software_list_loader s_instance;
};
// ======================> image_software_list_loader
class image_software_list_loader : public software_list_loader
{
public:
virtual bool load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const override;
static const software_list_loader &instance() { return s_instance; }
private:
static image_software_list_loader s_instance;
};
// ======================> feature_list_item
@ -174,13 +80,11 @@ public:
const std::string &name() const { return m_name; }
const std::string &interface() const { return m_interface; }
const std::list<feature_list_item> &featurelist() const { return m_featurelist; }
const rom_entry *romdata(unsigned int index = 0) const { return (index < m_romdata.size()) ? &m_romdata[index] : nullptr; }
const std::vector<rom_entry> &romdata() const { return m_romdata; }
// helpers
software_compatibility is_compatible(const software_list_device &swlist) const;
bool matches_interface(const char *interface) const;
const char *feature(const std::string &feature_name) const;
device_image_interface *find_mountable_image(const machine_config &mconfig) const;
private:
// internal state
@ -202,7 +106,7 @@ class software_info
public:
// construction/destruction
software_info(software_list_device &list, std::string &&name, std::string &&parent, const char *supported);
software_info(std::string &&name, std::string &&parent, const char *supported);
software_info(software_info const &) = delete;
software_info(software_info &&) = delete;
software_info& operator=(software_info const &) = delete;
@ -210,7 +114,6 @@ public:
// getters
software_info *next() const { return m_next; }
software_list_device &list() const { return m_list; }
const std::string &shortname() const { return m_shortname; }
const std::string &longname() const { return m_longname; }
const std::string &parentname() const { return m_parentname; }
@ -228,7 +131,6 @@ public:
private:
// internal state
software_info * m_next;
software_list_device & m_list;
UINT32 m_supported;
std::string m_shortname;
std::string m_longname;
@ -242,74 +144,68 @@ private:
};
// ======================> software_list_device
// ======================> softlist_parser
// device representing a software list
class software_list_device : public device_t
class softlist_parser
{
friend class softlist_parser;
public:
// construction/destruction
software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// construction (== execution)
softlist_parser(util::core_file &file, const std::string &filename, std::list<software_info> &infolist, std::ostringstream &errors);
// inline configuration helpers
static void static_set_type(device_t &device, const char *list, softlist_type list_type);
static void static_set_filter(device_t &device, const char *filter);
private:
enum parse_position
{
POS_ROOT,
POS_MAIN,
POS_SOFT,
POS_PART,
POS_DATA
};
// getters
const char *list_name() const { return m_list_name.c_str(); }
softlist_type list_type() const { return m_list_type; }
const char *filter() const { return m_filter; }
const char *filename() { return m_file.filename(); }
// internal parsing helpers
const char *infoname() const { return (m_current_info != nullptr) ? m_current_info->shortname().c_str() : "???"; }
int line() const;
int column() const;
const char *parser_error() const;
// getters that may trigger a parse
const char *description() { if (!m_parsed) parse(); return m_description.c_str(); }
bool valid() { if (!m_parsed) parse(); return !m_infolist.empty(); }
const char *errors_string() { if (!m_parsed) parse(); return m_errors.c_str(); }
const std::list<software_info> &get_info() { if (!m_parsed) parse(); return m_infolist; }
// internal error helpers
template <typename Format, typename... Params> void parse_error(Format &&fmt, Params &&... args);
void unknown_tag(const char *tagname) { parse_error("Unknown tag: %s", tagname); }
void unknown_attribute(const char *attrname) { parse_error("Unknown attribute: %s", attrname); }
// operations
const software_info *find(const char *look_for);
void find_approx_matches(const char *name, int matches, const software_info **list, const char *interface);
void release();
// string pool helpers
const char *add_string(const char *string) { return m_stringpool.add(string); }
// static helpers
static software_list_device *find_by_name(const machine_config &mconfig, const char *name);
static void display_matches(const machine_config &config, const char *interface, const char *name);
protected:
// internal helpers
void parse();
void internal_validity_check(validity_checker &valid) ATTR_COLD;
template <typename T> std::vector<std::string> parse_attributes(const char **attributes, const T &attrlist);
bool parse_name_and_value(const char **attributes, std::string &name, std::string &value);
void add_rom_entry(std::string &&name, std::string &&hashdata, UINT32 offset, UINT32 length, UINT32 flags);
// device-level overrides
virtual void device_start() override;
virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD;
// expat callbacks
static void start_handler(void *data, const char *tagname, const char **attributes);
static void data_handler(void *data, const char *s, int len);
static void end_handler(void *data, const char *name);
// configuration state
std::string m_list_name;
softlist_type m_list_type;
const char * m_filter;
// internal parsing
void parse_root_start(const char *tagname, const char **attributes);
void parse_main_start(const char *tagname, const char **attributes);
void parse_soft_start(const char *tagname, const char **attributes);
void parse_part_start(const char *tagname, const char **attributes);
void parse_data_start(const char *tagname, const char **attributes);
void parse_soft_end(const char *name);
// internal state
bool m_parsed;
emu_file m_file;
std::string m_description;
std::string m_errors;
std::list<software_info> m_infolist;
const_string_pool m_stringpool;
// internal parsing state
util::core_file & m_file;
const std::string & m_filename;
std::list<software_info> & m_infolist;
std::ostringstream & m_errors;
struct XML_ParserStruct * m_parser;
bool m_done;
std::string m_description;
bool m_data_accum_expected;
std::string m_data_accum;
software_info * m_current_info;
software_part * m_current_part;
parse_position m_pos;
};
// device type definition
extern const device_type SOFTWARE_LIST;
#endif // __SOFTLIST_H_
// device type iterator
typedef device_type_iterator<&device_creator<software_list_device>, software_list_device> software_list_device_iterator;
#endif

523
src/emu/softlist_dev.cpp Normal file
View File

@ -0,0 +1,523 @@
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
/***************************************************************************
softlist_dev.cpp
Software list construction helpers.
***************************************************************************/
#include "emu.h"
#include "emuopts.h"
#include "diimage.h"
#include "softlist_dev.h"
#include "validity.h"
#include <ctype.h>
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
typedef std::unordered_map<std::string, const software_info *> softlist_map;
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
const device_type SOFTWARE_LIST = &device_creator<software_list_device>;
false_software_list_loader false_software_list_loader::s_instance;
rom_software_list_loader rom_software_list_loader::s_instance;
image_software_list_loader image_software_list_loader::s_instance;
//**************************************************************************
// SOFTWARE LIST LOADER
//**************************************************************************
//-------------------------------------------------
// false_software_list_loader::load_software
//-------------------------------------------------
bool false_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
{
return false;
}
//-------------------------------------------------
// rom_software_list_loader::load_software
//-------------------------------------------------
bool rom_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
{
swlist.machine().rom_load().load_software_part_region(device, swlist, swname, start_entry);
return true;
}
//-------------------------------------------------
// image_software_list_loader::load_software
//-------------------------------------------------
bool image_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
{
return device.load_software(swlist, swname, start_entry);
}
//**************************************************************************
// SOFTWARE LIST DEVICE
//**************************************************************************
//-------------------------------------------------
// software_list_device - constructor
//-------------------------------------------------
software_list_device::software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SOFTWARE_LIST, "Software list", tag, owner, clock, "software_list", __FILE__),
m_list_type(SOFTWARE_LIST_ORIGINAL_SYSTEM),
m_filter(nullptr),
m_parsed(false),
m_file(mconfig.options().hash_path(), OPEN_FLAG_READ),
m_description("")
{
}
//-------------------------------------------------
// static_set_type - configuration helper
// to set the list type
//-------------------------------------------------
void software_list_device::static_set_type(device_t &device, const char *list, softlist_type list_type)
{
software_list_device &swlistdev = downcast<software_list_device &>(device);
swlistdev.m_list_name.assign(list);
swlistdev.m_list_type = list_type;
}
//-------------------------------------------------
// static_set_custom_handler - configuration
// helper to set a custom callback
//-------------------------------------------------
void software_list_device::static_set_filter(device_t &device, const char *filter)
{
downcast<software_list_device &>(device).m_filter = filter;
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void software_list_device::device_start()
{
}
//-------------------------------------------------
// find_approx_matches - search ourselves for
// a list of possible matches of the given name
// and optional interface
//-------------------------------------------------
void software_list_device::find_approx_matches(const char *name, int matches, const software_info **list, const char *interface)
{
// if no name, return
if (name == nullptr || name[0] == 0)
return;
// initialize everyone's states
std::vector<int> penalty(matches);
for (int matchnum = 0; matchnum < matches; matchnum++)
{
penalty[matchnum] = 9999;
list[matchnum] = nullptr;
}
// iterate over our info (will cause a parse if needed)
for (const software_info &swinfo : get_info())
{
const software_part &part = swinfo.parts().front();
if ((interface == nullptr || part.matches_interface(interface)) && is_compatible(part) == SOFTWARE_IS_COMPATIBLE)
{
// pick the best match between driver name and description
int longpenalty = driver_list::penalty_compare(name, swinfo.longname().c_str());
int shortpenalty = driver_list::penalty_compare(name, swinfo.shortname().c_str());
int curpenalty = std::min(longpenalty, shortpenalty);
// insert into the sorted table of matches
for (int matchnum = matches - 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 < matches - 1)
{
penalty[matchnum + 1] = penalty[matchnum];
list[matchnum + 1] = list[matchnum];
}
list[matchnum] = &swinfo;
penalty[matchnum] = curpenalty;
}
}
}
}
//-------------------------------------------------
// release - reset to a pre-parsed state
//-------------------------------------------------
void software_list_device::release()
{
osd_printf_verbose("Resetting %s\n", m_file.filename());
m_parsed = false;
m_description.clear();
m_errors.clear();
m_infolist.clear();
}
//-------------------------------------------------
// find_by_name - find a software list by name
// across all software list devices
//-------------------------------------------------
software_list_device *software_list_device::find_by_name(const machine_config &config, const std::string &name)
{
// iterate over each device in the system and find a match
for (software_list_device &swlistdev : software_list_device_iterator(config.root_device()))
if (swlistdev.list_name() == name)
return &swlistdev;
return nullptr;
}
//-------------------------------------------------
// software_display_matches - display a list of
// possible matches in the system to the given
// name, across all software list devices
//-------------------------------------------------
void software_list_device::display_matches(const machine_config &config, const char *interface, const char *name)
{
// check if there is at least one software list
software_list_device_iterator deviter(config.root_device());
if (deviter.first() != nullptr)
osd_printf_error("\n\"%s\" approximately matches the following\n"
"supported software items (best match first):\n\n", name);
// iterate through lists
for (software_list_device &swlistdev : deviter)
{
// get the top 16 approximate matches for the selected device interface (i.e. only carts for cartslot, etc.)
const software_info *matches[16] = { nullptr };
swlistdev.find_approx_matches(name, ARRAY_LENGTH(matches), matches, interface);
// if we found some, print them
if (matches[0] != nullptr)
{
// different output depending on original system or compatible
if (swlistdev.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM)
osd_printf_error("* Software list \"%s\" (%s) matches: \n", swlistdev.list_name().c_str(), swlistdev.description());
else
osd_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlistdev.list_name().c_str(), swlistdev.description());
// print them out
for (auto &match : matches)
{
if (match != nullptr)
osd_printf_error("%-18s%s\n", match->shortname().c_str(), match->longname().c_str());
}
osd_printf_error("\n");
}
}
}
//-------------------------------------------------
// find - find an item by name in the software
// list, using wildcards and optionally starting
// from an intermediate point
//-------------------------------------------------
const software_info *software_list_device::find(const char *look_for)
{
// nullptr search returns nothing
if (look_for == nullptr)
return nullptr;
bool iswild = strchr(look_for, '*') != nullptr || strchr(look_for, '?');
// find a match (will cause a parse if needed when calling get_info)
const auto &info_list = get_info();
auto iter = std::find_if(
info_list.begin(),
info_list.end(),
[&](const software_info &info)
{
const char *shortname = info.shortname().c_str();
return (iswild && core_strwildcmp(look_for, shortname) == 0)
|| core_stricmp(look_for, shortname) == 0;
});
return iter != info_list.end()
? &*iter
: nullptr;
}
//-------------------------------------------------
// parse - parse our softlist file
//-------------------------------------------------
void software_list_device::parse()
{
// skip if done
if (m_parsed)
return;
// reset the errors
m_errors.clear();
// attempt to open the file
osd_file::error filerr = m_file.open(m_list_name.c_str(), ".xml");
if (filerr == osd_file::error::NONE)
{
// parse if no error
std::ostringstream errs;
softlist_parser parser(m_file, m_description, m_infolist, errs);
m_file.close();
m_errors = errs.str();
}
else
m_errors = string_format("Error opening file: %s\n", filename());
// indicate that we've been parsed
m_parsed = true;
}
//-------------------------------------------------
// is_compatible - determine if we are compatible
// with the given software_list_device
//-------------------------------------------------
software_compatibility software_list_device::is_compatible(const software_part &swpart) const
{
// get the softlist filter; if null, assume compatible
if (m_filter == nullptr)
return SOFTWARE_IS_COMPATIBLE;
// copy the comma-delimited string and ensure it ends with a final comma
std::string filt = std::string(m_filter).append(",");
// get the incompatibility filter and test against it first if it exists
const char *incompatibility = swpart.feature("incompatibility");
if (incompatibility != nullptr)
{
// copy the comma-delimited string and ensure it ends with a final comma
std::string incomp = std::string(incompatibility).append(",");
// iterate over filter items and see if they exist in the list; if so, it's incompatible
for (int start = 0, end = filt.find_first_of(',', start); end != -1; start = end + 1, end = filt.find_first_of(',', start))
{
std::string token(filt, start, end - start + 1);
if (incomp.find(token) != -1)
return SOFTWARE_IS_INCOMPATIBLE;
}
}
// get the compatibility feature; if null, assume compatible
const char *compatibility = swpart.feature("compatibility");
if (compatibility == nullptr)
return SOFTWARE_IS_COMPATIBLE;
// copy the comma-delimited string and ensure it ends with a final comma
std::string comp = std::string(compatibility).append(",");
// iterate over filter items and see if they exist in the compatibility list; if so, it's compatible
for (int start = 0, end = filt.find_first_of(',', start); end != -1; start = end + 1, end = filt.find_first_of(',', start))
{
std::string token(filt, start, end - start + 1);
if (comp.find(token) != -1)
return SOFTWARE_IS_COMPATIBLE;
}
return SOFTWARE_NOT_COMPATIBLE;
}
//-------------------------------------------------
// find_mountable_image - find an image interface
// that can automatically mount this software part
//-------------------------------------------------
device_image_interface *software_list_device::find_mountable_image(const machine_config &mconfig, const software_part &part)
{
// if automount="no", don't bother
const char *mount = part.feature("automount");
if (mount != nullptr && strcmp(mount, "no") == 0)
return nullptr;
for (device_image_interface &image : image_interface_iterator(mconfig.root_device()))
{
const char *interface = image.image_interface();
if (interface != nullptr && part.matches_interface(interface))
{
// mount only if not already mounted
const char *option = mconfig.options().value(image.brief_instance_name());
if (*option == '\0' && !image.filename())
return &image;
}
}
return nullptr;
}
//-------------------------------------------------
// device_validity_check - validate the device
// configuration
//-------------------------------------------------
void software_list_device::device_validity_check(validity_checker &valid) const
{
// add to the global map whenever we check a list so we don't re-check
// it in the future
if (valid.already_checked(std::string("softlist/").append(m_list_name).c_str()))
return;
// do device validation only in case of validate command
if (!valid.validate_all())
return;
// actually do the validate
const_cast<software_list_device *>(this)->internal_validity_check(valid);
}
//-------------------------------------------------
// internal_validity_check - internal helper to
// check the list
//-------------------------------------------------
void software_list_device::internal_validity_check(validity_checker &valid)
{
enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 };
softlist_map names;
softlist_map descriptions;
for (const software_info &swinfo : get_info())
{
// first parse and output core errors if any
if (m_errors.length() > 0)
{
osd_printf_error("%s: Errors parsing software list:\n%s", filename(), errors_string());
break;
}
// Now check if the xml data is valid:
// Did we lost any description?
if (swinfo.longname().empty())
{
osd_printf_error("%s: %s has no description\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost any year?
if (swinfo.year().empty())
{
osd_printf_error("%s: %s has no year\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost any publisher?
if (swinfo.publisher().empty())
{
osd_printf_error("%s: %s has no publisher\n", filename(), swinfo.shortname().c_str());
break;
}
// Did we lost the software parts?
if (swinfo.parts().empty())
{
osd_printf_error("%s: %s has no part\n", filename(), swinfo.shortname().c_str());
break;
}
// Second, since the xml is fine, run additional checks:
// check for duplicate names
if (!names.insert(std::make_pair(swinfo.shortname(), &swinfo)).second)
{
const software_info *match = names.find(swinfo.shortname())->second;
osd_printf_error("%s: %s is a duplicate name (%s)\n", filename(), swinfo.shortname().c_str(), match->shortname().c_str());
}
// check for duplicate descriptions
std::string longname = std::string(swinfo.longname());
if (!descriptions.insert(std::make_pair(strmakelower(longname), &swinfo)).second)
osd_printf_error("%s: %s is a duplicate description (%s)\n", filename(), swinfo.longname().c_str(), swinfo.shortname().c_str());
bool is_clone = false;
if (!swinfo.parentname().empty())
{
is_clone = true;
if (swinfo.parentname() == swinfo.shortname())
{
osd_printf_error("%s: %s is set as a clone of itself\n", filename(), swinfo.shortname().c_str());
break;
}
// make sure the parent exists
const software_info *swinfo2 = find(swinfo.parentname().c_str());
if (swinfo2 == nullptr)
osd_printf_error("%s: parent '%s' software for '%s' not found\n", filename(), swinfo.parentname().c_str(), swinfo.shortname().c_str());
else if (!swinfo2->parentname().empty())
osd_printf_error("%s: %s is a clone of a clone\n", filename(), swinfo.shortname().c_str());
}
// make sure the driver name is 8 chars or less
if ((is_clone && swinfo.shortname().length() > NAME_LEN_CLONE) || (!is_clone && swinfo.shortname().length() > NAME_LEN_PARENT))
osd_printf_error("%s: %s %s driver name must be %d characters or less\n", filename(), swinfo.shortname().c_str(),
is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT);
// make sure the year is only digits, '?' or '+'
for (const char *s = swinfo.year().c_str(); *s != 0; s++)
if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
{
osd_printf_error("%s: %s has an invalid year '%s'\n", filename(), swinfo.shortname().c_str(), swinfo.year().c_str());
break;
}
softlist_map part_names;
for (const software_part &part : swinfo.parts())
{
if (part.interface().empty())
osd_printf_error("%s: %s has a part (%s) without interface\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
if (part.romdata().empty())
osd_printf_error("%s: %s has a part (%s) with no data\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
if (!part_names.insert(std::make_pair(part.name(), &swinfo)).second)
osd_printf_error("%s: %s has a part (%s) whose name is duplicate\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
}
}
// release all the memory
release();
}

195
src/emu/softlist_dev.h Normal file
View File

@ -0,0 +1,195 @@
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
/*********************************************************************
softlist_dev.h
Software and software list information.
*********************************************************************/
#ifndef __SOFTLIST_DEV_H_
#define __SOFTLIST_DEV_H_
#include "softlist.h"
//**************************************************************************
// CONSTANTS
//**************************************************************************
#define SOFTWARE_SUPPORTED_YES 0
#define SOFTWARE_SUPPORTED_PARTIAL 1
#define SOFTWARE_SUPPORTED_NO 2
enum softlist_type
{
SOFTWARE_LIST_ORIGINAL_SYSTEM,
SOFTWARE_LIST_COMPATIBLE_SYSTEM
};
enum software_compatibility
{
SOFTWARE_IS_COMPATIBLE,
SOFTWARE_IS_INCOMPATIBLE,
SOFTWARE_NOT_COMPATIBLE
};
//**************************************************************************
// MACROS
//**************************************************************************
#define MCFG_SOFTWARE_LIST_CONFIG(_list,_list_type) \
software_list_device::static_set_type(*device, _list, _list_type);
#define MCFG_SOFTWARE_LIST_ADD( _tag, _list ) \
MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \
MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM)
#define MCFG_SOFTWARE_LIST_COMPATIBLE_ADD( _tag, _list ) \
MCFG_DEVICE_ADD( _tag, SOFTWARE_LIST, 0 ) \
MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM)
#define MCFG_SOFTWARE_LIST_MODIFY( _tag, _list ) \
MCFG_DEVICE_MODIFY( _tag ) \
MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_ORIGINAL_SYSTEM)
#define MCFG_SOFTWARE_LIST_COMPATIBLE_MODIFY( _tag, _list ) \
MCFG_DEVICE_MODIFY( _tag ) \
MCFG_SOFTWARE_LIST_CONFIG(_list, SOFTWARE_LIST_COMPATIBLE_SYSTEM)
#define MCFG_SOFTWARE_LIST_FILTER( _tag, _filter ) \
MCFG_DEVICE_MODIFY( _tag ) \
software_list_device::static_set_filter(*device, _filter);
#define MCFG_SOFTWARE_LIST_REMOVE( _tag ) \
MCFG_DEVICE_REMOVE( _tag )
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class device_image_interface;
class software_list_device;
// ======================> software_list_loader
class software_list_loader
{
public:
virtual bool load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const = 0;
};
// ======================> false_software_list_loader
class false_software_list_loader : public software_list_loader
{
public:
virtual bool load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const override;
static const software_list_loader &instance() { return s_instance; }
private:
static false_software_list_loader s_instance;
};
// ======================> rom_software_list_loader
class rom_software_list_loader : public software_list_loader
{
public:
virtual bool load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const override;
static const software_list_loader &instance() { return s_instance; }
private:
static rom_software_list_loader s_instance;
};
// ======================> image_software_list_loader
class image_software_list_loader : public software_list_loader
{
public:
virtual bool load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const override;
static const software_list_loader &instance() { return s_instance; }
private:
static image_software_list_loader s_instance;
};
// ======================> software_list_device
// device representing a software list
class software_list_device : public device_t
{
friend class softlist_parser;
public:
// construction/destruction
software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// inline configuration helpers
static void static_set_type(device_t &device, const char *list, softlist_type list_type);
static void static_set_filter(device_t &device, const char *filter);
// getters
const std::string &list_name() const { return m_list_name; }
softlist_type list_type() const { return m_list_type; }
const char *filter() const { return m_filter; }
const char *filename() { return m_file.filename(); }
// getters that may trigger a parse
const char *description() { if (!m_parsed) parse(); return m_description.c_str(); }
bool valid() { if (!m_parsed) parse(); return !m_infolist.empty(); }
const char *errors_string() { if (!m_parsed) parse(); return m_errors.c_str(); }
const std::list<software_info> &get_info() { if (!m_parsed) parse(); return m_infolist; }
// operations
const software_info *find(const char *look_for);
void find_approx_matches(const char *name, int matches, const software_info **list, const char *interface);
void release();
software_compatibility is_compatible(const software_part &part) const;
// static helpers
static software_list_device *find_by_name(const machine_config &mconfig, const std::string &name);
static void display_matches(const machine_config &config, const char *interface, const char *name);
static device_image_interface *find_mountable_image(const machine_config &mconfig, const software_part &part);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD;
private:
// internal helpers
void parse();
void internal_validity_check(validity_checker &valid) ATTR_COLD;
// configuration state
std::string m_list_name;
softlist_type m_list_type;
const char * m_filter;
// internal state
bool m_parsed;
emu_file m_file;
std::string m_description;
std::string m_errors;
std::list<software_info> m_infolist;
};
// device type definition
extern const device_type SOFTWARE_LIST;
// device type iterator
typedef device_type_iterator<&device_creator<software_list_device>, software_list_device> software_list_device_iterator;
#endif // __SOFTLIST_DEV_H_

View File

@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
audit.c
audit.cpp
ROM set auditing functions.
@ -14,7 +14,8 @@
#include "chd.h"
#include "drivenum.h"
#include "sound/samples.h"
#include "softlist.h"
#include "softlist_dev.h"
//**************************************************************************
// CORE FUNCTIONS
@ -149,7 +150,7 @@ media_auditor::summary media_auditor::audit_device(device_t &device, const char
//-------------------------------------------------
// audit_software
//-------------------------------------------------
media_auditor::summary media_auditor::audit_software(const char *list_name, const software_info *swinfo, const char *validation)
media_auditor::summary media_auditor::audit_software(const std::string &list_name, const software_info *swinfo, const char *validation)
{
// start fresh
m_record_list.clear();
@ -171,7 +172,7 @@ media_auditor::summary media_auditor::audit_software(const char *list_name, cons
// now iterate over software parts
for (const software_part &part : swinfo->parts())
audit_regions(part.romdata(), locationtag.c_str(), found, required);
audit_regions(part.romdata().data(), locationtag.c_str(), found, required);
if ((found == 0) && (required > 0))
{
@ -180,7 +181,7 @@ media_auditor::summary media_auditor::audit_software(const char *list_name, cons
}
// return a summary
return summarize(list_name);
return summarize(list_name.c_str());
}

View File

@ -158,7 +158,7 @@ public:
// audit operations
summary audit_media(const char *validation = AUDIT_VALIDATE_FULL);
summary audit_device(device_t &device, const char *validation = AUDIT_VALIDATE_FULL);
summary audit_software(const char *list_name, const software_info *swinfo, const char *validation = AUDIT_VALIDATE_FULL);
summary audit_software(const std::string &list_name, const software_info *swinfo, const char *validation = AUDIT_VALIDATE_FULL);
summary audit_samples();
summary summarize(const char *name, std::ostream *output = nullptr) const;

View File

@ -25,7 +25,7 @@
#include "drivenum.h"
#include "osdepend.h"
#include "softlist.h"
#include "softlist_dev.h"
#include "ui/moptions.h"
#include "language.h"
@ -374,7 +374,7 @@ int media_identifier::find_by_hash(const util::hash_collection &hashes, int leng
{
for (const software_info &swinfo : swlistdev.get_info())
for (const software_part &part : swinfo.parts())
for (const rom_entry *region = part.romdata(); region != nullptr; region = rom_next_region(region))
for (const rom_entry *region = part.romdata().data(); region != nullptr; region = rom_next_region(region))
for (const rom_entry *rom = rom_first_file(region); rom != nullptr; rom = rom_next_file(rom))
{
util::hash_collection romhashes(ROM_GETHASHDATA(rom));
@ -385,7 +385,7 @@ int media_identifier::find_by_hash(const util::hash_collection &hashes, int leng
// output information about the match
if (found)
osd_printf_info(" ");
osd_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlistdev.list_name(), swinfo.shortname().c_str(), swinfo.longname().c_str());
osd_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlistdev.list_name().c_str(), swinfo.shortname().c_str(), swinfo.longname().c_str());
found++;
}
}
@ -527,9 +527,9 @@ int cli_frontend::execute(int argc, char **argv)
for (const software_part &swpart : swinfo->parts())
{
// only load compatible software this way
if (swpart.is_compatible(swlistdev) == SOFTWARE_IS_COMPATIBLE)
if (swlistdev.is_compatible(swpart) == SOFTWARE_IS_COMPATIBLE)
{
device_image_interface *image = swpart.find_mountable_image(config);
device_image_interface *image = software_list_device::find_mountable_image(config, swpart);
if (image != nullptr)
{
std::string val = string_format("%s:%s:%s", swlistdev.list_name(), m_options.software_name(), swpart.name());
@ -1387,7 +1387,7 @@ void cli_frontend::verifysamples(const char *gamename)
void cli_frontend::output_single_softlist(FILE *out, software_list_device &swlistdev)
{
fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlistdev.list_name(), xml_normalize_string(swlistdev.description()));
fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlistdev.list_name().c_str(), xml_normalize_string(swlistdev.description()));
for (const software_info &swinfo : swlistdev.get_info())
{
fprintf(out, "\t\t<software name=\"%s\"", swinfo.shortname().c_str());
@ -1417,7 +1417,7 @@ void cli_frontend::output_single_softlist(FILE *out, software_list_device &swlis
fprintf(out, "\t\t\t\t<feature name=\"%s\" value=\"%s\" />\n", flist.name().c_str(), xml_normalize_string(flist.value().c_str()));
/* TODO: display rom region information */
for (const rom_entry *region = part.romdata(); region; region = rom_next_region(region))
for (const rom_entry *region = part.romdata().data(); region; region = rom_next_region(region))
{
int is_disk = ROMREGION_ISDISKDATA(region);
@ -1626,7 +1626,7 @@ void cli_frontend::getsoftlist(const char *gamename)
while (drivlist.next())
{
for (software_list_device &swlistdev : software_list_device_iterator(drivlist.config().root_device()))
if (core_strwildcmp(gamename, swlistdev.list_name()) == 0 && list_map.insert(swlistdev.list_name()).second)
if (core_strwildcmp(gamename, swlistdev.list_name().c_str()) == 0 && list_map.insert(swlistdev.list_name()).second)
if (!swlistdev.get_info().empty())
{
if (isfirst) { fprintf( out, SOFTLIST_XML_BEGIN); isfirst = false; }
@ -1660,7 +1660,7 @@ void cli_frontend::verifysoftlist(const char *gamename)
{
for (software_list_device &swlistdev : software_list_device_iterator(drivlist.config().root_device()))
{
if (core_strwildcmp(gamename, swlistdev.list_name()) == 0 && list_map.insert(swlistdev.list_name()).second)
if (core_strwildcmp(gamename, swlistdev.list_name().c_str()) == 0 && list_map.insert(swlistdev.list_name()).second)
{
if (!swlistdev.get_info().empty())
{

View File

@ -16,7 +16,7 @@
#include "xmlfile.h"
#include "config.h"
#include "drivenum.h"
#include "softlist.h"
#include "softlist_dev.h"
#include <ctype.h>
@ -1561,7 +1561,7 @@ void info_xml_creator::output_software_list()
{
for (const software_list_device &swlist : software_list_device_iterator(m_drivlist.config().root_device()))
{
fprintf(m_output, "\t\t<softwarelist name=\"%s\" ", swlist.list_name());
fprintf(m_output, "\t\t<softwarelist name=\"%s\" ", swlist.list_name().c_str());
fprintf(m_output, "status=\"%s\" ", (swlist.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM) ? "original" : "compatible");
if (swlist.filter())
fprintf(m_output, "filter=\"%s\" ", swlist.filter());

View File

@ -11,7 +11,7 @@
#include "emu.h"
#include "mameopts.h"
#include "drivenum.h"
#include "softlist.h"
#include "softlist_dev.h"
#include <ctype.h>

View File

@ -20,7 +20,7 @@
#include "audit.h"
#include "drivenum.h"
#include "emuopts.h"
#include "softlist.h"
#include "softlist_dev.h"
#include "zippath.h"

View File

@ -11,7 +11,7 @@
#include "emu.h"
#include "ui/moptions.h"
#include "ui/inifile.h"
#include "softlist.h"
#include "softlist_dev.h"
#include "drivenum.h"
//-------------------------------------------------

View File

@ -31,7 +31,7 @@
#include "mame.h"
#include "rendfont.h"
#include "rendutil.h"
#include "softlist.h"
#include "softlist_dev.h"
#include "uiinput.h"
extern const char UI_VERSION_TAG[];

View File

@ -24,7 +24,7 @@
#include "mame.h"
#include "rendfont.h"
#include "rendutil.h"
#include "softlist.h"
#include "softlist_dev.h"
#include "uiinput.h"
@ -528,7 +528,7 @@ void menu_select_software::build_software_list()
for (const software_info &swinfo : swlist.get_info())
{
const software_part &part = swinfo.parts().front();
if (part.is_compatible(swlist) == SOFTWARE_IS_COMPATIBLE)
if (swlist.is_compatible(part) == SOFTWARE_IS_COMPATIBLE)
{
const char *instance_name = nullptr;
const char *type_name = nullptr;
@ -560,7 +560,7 @@ void menu_select_software::build_software_list()
tmpmatches.supported = swinfo.supported();
tmpmatches.part = part.name();
tmpmatches.driver = m_driver;
tmpmatches.listname = strensure(swlist.list_name());
tmpmatches.listname = swlist.list_name();
tmpmatches.interface = part.interface();
tmpmatches.startempty = 0;
tmpmatches.parentlongname.clear();

View File

@ -13,7 +13,7 @@
#include "ui/ui.h"
#include "ui/swlist.h"
#include "softlist.h"
#include "softlist_dev.h"
namespace ui {
@ -173,7 +173,7 @@ void menu_software_list::append_software_entry(const software_info &swinfo)
// check if at least one of the parts has the correct interface and add a menu entry only in this case
for (const software_part &swpart : swinfo.parts())
{
if (swpart.matches_interface(m_interface) && swpart.is_compatible(*m_swlist) == SOFTWARE_IS_COMPATIBLE)
if (swpart.matches_interface(m_interface) && m_swlist->is_compatible(swpart) == SOFTWARE_IS_COMPATIBLE)
{
entry_updated = true;
entry.short_name.assign(swinfo.shortname());

View File

@ -21,7 +21,7 @@ Note:
#include "emu.h"
#include "cpu/m6502/m4510.h"
#include "machine/mos6526.h"
#include "softlist.h"
#include "softlist_dev.h"
#define MAIN_CLOCK XTAL_3_5MHz

View File

@ -25,7 +25,7 @@ http://mamedev.emulab.it/haze/reference/sawatte/cartridge_example.jpg
*/
#include "emu.h"
#include "softlist.h"
#include "softlist_dev.h"
class sawatte_state : public driver_device

View File

@ -12,6 +12,7 @@
#include "machine/at_keybc.h"
#include "bus/pc_kbd/pc_kbdc.h"
#include "sound/dac.h"
#include "softlist_dev.h"
#define LOG_PORT80 0

View File

@ -13,6 +13,7 @@
#ifndef __MICRODRV__
#define __MICRODRV__
#include "softlist_dev.h"
//**************************************************************************

View File

@ -9,6 +9,8 @@
#ifndef __PSION_PACK_H__
#define __PSION_PACK_H__
#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS