mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
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:
parent
159b73a708
commit
f9db568146
@ -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",
|
||||
|
@ -3,6 +3,8 @@
|
||||
#ifndef __A78_SLOT_H
|
||||
#define __A78_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
|
@ -3,6 +3,8 @@
|
||||
#ifndef __A800_SLOT_H
|
||||
#define __A800_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define __ADAM_EXPANSION_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -3,6 +3,8 @@
|
||||
#ifndef __APF_SLOT_H
|
||||
#define __APF_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __ARCADIA_SLOT_H
|
||||
#define __ARCADIA_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __ASTROCADE_SLOT_H
|
||||
#define __ASTROCADE_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define __C64_EXPANSION_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "formats/cbm_crt.h"
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define __CBM2_EXPANSION_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __CHANF_SLOT_H
|
||||
#define __CHANF_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -11,6 +11,8 @@
|
||||
#ifndef __COCOCART_H__
|
||||
#define __COCOCART_H__
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
|
@ -31,7 +31,7 @@
|
||||
#define __COLECOVISION_CARTRIDGE_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __CRVISION_SLOT_H
|
||||
#define __CRVISION_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __GB_SLOT_H
|
||||
#define __GB_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __GBA_SLOT_H
|
||||
#define __GBA_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __GENERIC_SLOT_H
|
||||
#define __GENERIC_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -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
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __INTV_SLOT_H
|
||||
#define __INTV_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -45,6 +45,8 @@
|
||||
#ifndef __IQ151CART_H__
|
||||
#define __IQ151CART_H__
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "bus/isa/isa.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
|
@ -11,6 +11,8 @@
|
||||
#ifndef __KCEXP_H__
|
||||
#define __KCEXP_H__
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __M5_SLOT_H
|
||||
#define __M5_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,8 @@
|
||||
#ifndef __MD_SLOT_H
|
||||
#define __MD_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "slot.h"
|
||||
#include "bus/msx_cart/cartridge.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
extern const device_type MSX_SLOT_CARTRIDGE;
|
||||
|
@ -4,6 +4,8 @@
|
||||
#define __NEOGEO_SLOT_H
|
||||
|
||||
#include "emu.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/* PCB */
|
||||
enum
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define __NES_ALADDIN_H
|
||||
|
||||
#include "nxrom.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//----------------------------------
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define __NES_DATACH_H
|
||||
|
||||
#include "bandai.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "machine/i2cmem.h"
|
||||
#include "machine/bcreader.h"
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define __NES_KARASTUDIO_H
|
||||
|
||||
#include "nxrom.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __NES_SLOT_H__
|
||||
#define __NES_SLOT_H__
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define __NES_SUNSOFT_DCS_H
|
||||
|
||||
#include "sunsoft.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//-----------------------------------------------
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __O2_SLOT_H
|
||||
#define __O2_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __PCE_SLOT_H
|
||||
#define __PCE_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -40,7 +40,7 @@
|
||||
#define __PLUS4_EXPANSION_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -31,7 +31,7 @@
|
||||
#define __QL_ROM_CARTRIDGE_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __SAT_SLOT_H
|
||||
#define __SAT_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __SCV_SLOT_H
|
||||
#define __SCV_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __SEGA8_SLOT_H
|
||||
#define __SEGA8_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __SNS_SLOT_H
|
||||
#define __SNS_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "emu.h"
|
||||
#include "ti99defs.h"
|
||||
#include "machine/tmc0430.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
extern const device_type GROMPORT;
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __VBOY_SLOT_H
|
||||
#define __VBOY_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __VC4000_SLOT_H
|
||||
#define __VC4000_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -3,6 +3,8 @@
|
||||
#ifndef __VCS_SLOT_H
|
||||
#define __VCS_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __VECTREX_SLOT_H
|
||||
#define __VECTREX_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -37,10 +37,10 @@
|
||||
#define __VIC10_EXPANSION_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "formats/cbm_crt.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
//**************************************************************************
|
||||
|
@ -37,7 +37,7 @@
|
||||
#define __VIC20_EXPANSION_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -40,7 +40,7 @@
|
||||
#define __VIDEOBRAIN_EXPANSION_SLOT__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -3,6 +3,9 @@
|
||||
#ifndef __WS_SLOT_H
|
||||
#define __WS_SLOT_H
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -54,6 +54,9 @@
|
||||
#ifndef __Z88CART_H__
|
||||
#define __Z88CART_H__
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
@ -12,6 +12,7 @@
|
||||
#define CASSETTE_H
|
||||
|
||||
#include "formats/cassimg.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
enum cassette_state
|
||||
|
@ -12,6 +12,7 @@
|
||||
#define CHD_CD_H
|
||||
|
||||
#include "cdrom.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define _IMAGEDEV_DIABLO_H_
|
||||
|
||||
#include "harddisk.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
#define DIABLO_TAG(_id) "diablo"#_id
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -12,6 +12,7 @@
|
||||
#define HARDDRIV_H
|
||||
|
||||
#include "harddisk.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
|
@ -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
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define __SMARTMEDIA_H__
|
||||
|
||||
#include "formats/imageutl.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
//#define SMARTMEDIA_IMAGE_SAVE
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
||||
|
@ -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 ℑ
|
||||
}
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
523
src/emu/softlist_dev.cpp
Normal 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 ℑ
|
||||
}
|
||||
}
|
||||
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
195
src/emu/softlist_dev.h
Normal 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_
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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());
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "emu.h"
|
||||
#include "mameopts.h"
|
||||
#include "drivenum.h"
|
||||
#include "softlist.h"
|
||||
#include "softlist_dev.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "audit.h"
|
||||
#include "drivenum.h"
|
||||
#include "emuopts.h"
|
||||
#include "softlist.h"
|
||||
#include "softlist_dev.h"
|
||||
#include "zippath.h"
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
||||
//-------------------------------------------------
|
||||
|
@ -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[];
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#ifndef __MICRODRV__
|
||||
#define __MICRODRV__
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
|
@ -9,6 +9,8 @@
|
||||
#ifndef __PSION_PACK_H__
|
||||
#define __PSION_PACK_H__
|
||||
|
||||
#include "softlist_dev.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
|
Loading…
Reference in New Issue
Block a user