summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Nathan Woods <npwoods@mess.org>2016-08-02 07:01:29 -0400
committer Nathan Woods <npwoods@mess.org>2016-08-02 17:40:49 -0400
commitf9db568146503c253230295ace2deba8433f6754 (patch)
tree57a1b43f5c967e17f0461f9d5be9abf88c2e27ae
parent159b73a708fb67ca2d39e1d4f8cee9987fdc3f8b (diff)
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
-rw-r--r--scripts/src/emu.lua2
-rw-r--r--src/devices/bus/a7800/a78_slot.h2
-rw-r--r--src/devices/bus/a800/a800_slot.h2
-rw-r--r--src/devices/bus/adam/exp.h2
-rw-r--r--src/devices/bus/apf/slot.h2
-rw-r--r--src/devices/bus/arcadia/slot.h3
-rw-r--r--src/devices/bus/astrocde/slot.h3
-rw-r--r--src/devices/bus/c64/exp.h1
-rw-r--r--src/devices/bus/cbm2/exp.h1
-rw-r--r--src/devices/bus/chanf/slot.h3
-rw-r--r--src/devices/bus/coco/cococart.h2
-rw-r--r--src/devices/bus/coleco/exp.h2
-rw-r--r--src/devices/bus/crvision/slot.h3
-rw-r--r--src/devices/bus/gameboy/gb_slot.h3
-rw-r--r--src/devices/bus/gba/gba_slot.h3
-rw-r--r--src/devices/bus/generic/slot.h3
-rw-r--r--src/devices/bus/hp_optroms/hp_optrom.h2
-rw-r--r--src/devices/bus/intv/slot.h3
-rw-r--r--src/devices/bus/iq151/iq151.h2
-rw-r--r--src/devices/bus/isa/sc499.h2
-rw-r--r--src/devices/bus/kc/kc.h2
-rw-r--r--src/devices/bus/m5/slot.h3
-rw-r--r--src/devices/bus/megadrive/md_slot.h2
-rw-r--r--src/devices/bus/msx_slot/cartridge.h1
-rw-r--r--src/devices/bus/neogeo/slot.h2
-rw-r--r--src/devices/bus/nes/aladdin.h1
-rw-r--r--src/devices/bus/nes/datach.h1
-rw-r--r--src/devices/bus/nes/karastudio.h1
-rw-r--r--src/devices/bus/nes/nes_slot.h3
-rw-r--r--src/devices/bus/nes/sunsoft_dcs.h1
-rw-r--r--src/devices/bus/odyssey2/slot.h3
-rw-r--r--src/devices/bus/pce/pce_slot.h3
-rw-r--r--src/devices/bus/plus4/exp.h2
-rw-r--r--src/devices/bus/ql/rom.h2
-rw-r--r--src/devices/bus/saturn/sat_slot.h3
-rw-r--r--src/devices/bus/scv/slot.h3
-rw-r--r--src/devices/bus/sega8/sega8_slot.h3
-rw-r--r--src/devices/bus/snes/snes_slot.h3
-rw-r--r--src/devices/bus/ti99x/gromport.h2
-rw-r--r--src/devices/bus/vboy/slot.h3
-rw-r--r--src/devices/bus/vc4000/slot.h3
-rwxr-xr-xsrc/devices/bus/vcs/vcs_slot.h2
-rw-r--r--src/devices/bus/vectrex/slot.h3
-rw-r--r--src/devices/bus/vic10/exp.h2
-rw-r--r--src/devices/bus/vic20/exp.h2
-rw-r--r--src/devices/bus/vidbrain/exp.h2
-rw-r--r--src/devices/bus/wswan/slot.h3
-rw-r--r--src/devices/bus/z88/z88.h3
-rw-r--r--src/devices/imagedev/cassette.h1
-rw-r--r--src/devices/imagedev/chd_cd.h1
-rw-r--r--src/devices/imagedev/diablo.h1
-rw-r--r--src/devices/imagedev/flopdrv.h1
-rw-r--r--src/devices/imagedev/floppy.h1
-rw-r--r--src/devices/imagedev/harddriv.h1
-rw-r--r--src/devices/imagedev/snapquik.h2
-rw-r--r--src/devices/machine/smartmed.h1
-rw-r--r--src/emu/diimage.cpp58
-rw-r--r--src/emu/diimage.h9
-rw-r--r--src/emu/drivenum.cpp4
-rw-r--r--src/emu/romload.cpp4
-rw-r--r--src/emu/softlist.cpp655
-rw-r--r--src/emu/softlist.h228
-rw-r--r--src/emu/softlist_dev.cpp523
-rw-r--r--src/emu/softlist_dev.h195
-rw-r--r--src/frontend/mame/audit.cpp11
-rw-r--r--src/frontend/mame/audit.h2
-rw-r--r--src/frontend/mame/clifront.cpp18
-rw-r--r--src/frontend/mame/info.cpp4
-rw-r--r--src/frontend/mame/mameopts.cpp2
-rw-r--r--src/frontend/mame/ui/imgcntrl.cpp2
-rw-r--r--src/frontend/mame/ui/inifile.cpp2
-rw-r--r--src/frontend/mame/ui/selgame.cpp2
-rw-r--r--src/frontend/mame/ui/selsoft.cpp6
-rw-r--r--src/frontend/mame/ui/swlist.cpp4
-rw-r--r--src/mame/drivers/c65.cpp2
-rw-r--r--src/mame/drivers/sega_sawatte.cpp2
-rw-r--r--src/mame/machine/at.cpp1
-rw-r--r--src/mame/machine/microdrv.h1
-rw-r--r--src/mame/machine/psion_pack.h2
79 files changed, 1028 insertions, 828 deletions
diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua
index 2302811a058..78b61d03d54 100644
--- a/scripts/src/emu.lua
+++ b/scripts/src/emu.lua
@@ -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",
diff --git a/src/devices/bus/a7800/a78_slot.h b/src/devices/bus/a7800/a78_slot.h
index d6a635b1a82..0f4fd9d2e92 100644
--- a/src/devices/bus/a7800/a78_slot.h
+++ b/src/devices/bus/a7800/a78_slot.h
@@ -3,6 +3,8 @@
#ifndef __A78_SLOT_H
#define __A78_SLOT_H
+#include "softlist_dev.h"
+
/***************************************************************************
TYPE DEFINITIONS
diff --git a/src/devices/bus/a800/a800_slot.h b/src/devices/bus/a800/a800_slot.h
index 0d1bf674bd5..d1cf620bdc4 100644
--- a/src/devices/bus/a800/a800_slot.h
+++ b/src/devices/bus/a800/a800_slot.h
@@ -3,6 +3,8 @@
#ifndef __A800_SLOT_H
#define __A800_SLOT_H
+#include "softlist_dev.h"
+
/***************************************************************************
TYPE DEFINITIONS
diff --git a/src/devices/bus/adam/exp.h b/src/devices/bus/adam/exp.h
index c7bd5abc12a..f1b004d67a8 100644
--- a/src/devices/bus/adam/exp.h
+++ b/src/devices/bus/adam/exp.h
@@ -12,7 +12,7 @@
#define __ADAM_EXPANSION_SLOT__
#include "emu.h"
-
+#include "softlist_dev.h"
//**************************************************************************
diff --git a/src/devices/bus/apf/slot.h b/src/devices/bus/apf/slot.h
index 076759e18b3..c2dba02fc08 100644
--- a/src/devices/bus/apf/slot.h
+++ b/src/devices/bus/apf/slot.h
@@ -3,6 +3,8 @@
#ifndef __APF_SLOT_H
#define __APF_SLOT_H
+#include "softlist_dev.h"
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/arcadia/slot.h b/src/devices/bus/arcadia/slot.h
index abc95db625f..2f7f2dbc67a 100644
--- a/src/devices/bus/arcadia/slot.h
+++ b/src/devices/bus/arcadia/slot.h
@@ -3,6 +3,9 @@
#ifndef __ARCADIA_SLOT_H
#define __ARCADIA_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/astrocde/slot.h b/src/devices/bus/astrocde/slot.h
index 6866f787655..edd94af5ca1 100644
--- a/src/devices/bus/astrocde/slot.h
+++ b/src/devices/bus/astrocde/slot.h
@@ -3,6 +3,9 @@
#ifndef __ASTROCADE_SLOT_H
#define __ASTROCADE_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/c64/exp.h b/src/devices/bus/c64/exp.h
index 3522942e823..4e4555173fa 100644
--- a/src/devices/bus/c64/exp.h
+++ b/src/devices/bus/c64/exp.h
@@ -37,6 +37,7 @@
#define __C64_EXPANSION_SLOT__
#include "emu.h"
+#include "softlist_dev.h"
#include "formats/cbm_crt.h"
diff --git a/src/devices/bus/cbm2/exp.h b/src/devices/bus/cbm2/exp.h
index 2a9fa80d051..ad66454a746 100644
--- a/src/devices/bus/cbm2/exp.h
+++ b/src/devices/bus/cbm2/exp.h
@@ -30,6 +30,7 @@
#define __CBM2_EXPANSION_SLOT__
#include "emu.h"
+#include "softlist_dev.h"
diff --git a/src/devices/bus/chanf/slot.h b/src/devices/bus/chanf/slot.h
index 68599ffad1c..f1d3f0d2c88 100644
--- a/src/devices/bus/chanf/slot.h
+++ b/src/devices/bus/chanf/slot.h
@@ -3,6 +3,9 @@
#ifndef __CHANF_SLOT_H
#define __CHANF_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/coco/cococart.h b/src/devices/bus/coco/cococart.h
index 7ba1e301d50..9415b5956c8 100644
--- a/src/devices/bus/coco/cococart.h
+++ b/src/devices/bus/coco/cococart.h
@@ -11,6 +11,8 @@
#ifndef __COCOCART_H__
#define __COCOCART_H__
+#include "softlist_dev.h"
+
/***************************************************************************
CONSTANTS
diff --git a/src/devices/bus/coleco/exp.h b/src/devices/bus/coleco/exp.h
index 25f503b378e..19fa5b5e69c 100644
--- a/src/devices/bus/coleco/exp.h
+++ b/src/devices/bus/coleco/exp.h
@@ -31,7 +31,7 @@
#define __COLECOVISION_CARTRIDGE_SLOT__
#include "emu.h"
-
+#include "softlist_dev.h"
//**************************************************************************
diff --git a/src/devices/bus/crvision/slot.h b/src/devices/bus/crvision/slot.h
index 47fed8c1583..7643ca7fb1b 100644
--- a/src/devices/bus/crvision/slot.h
+++ b/src/devices/bus/crvision/slot.h
@@ -3,6 +3,9 @@
#ifndef __CRVISION_SLOT_H
#define __CRVISION_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/gameboy/gb_slot.h b/src/devices/bus/gameboy/gb_slot.h
index 67db3cda7f0..75a8b4e7cde 100644
--- a/src/devices/bus/gameboy/gb_slot.h
+++ b/src/devices/bus/gameboy/gb_slot.h
@@ -3,6 +3,9 @@
#ifndef __GB_SLOT_H
#define __GB_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/gba/gba_slot.h b/src/devices/bus/gba/gba_slot.h
index 5cbc103e8dc..f9918744d97 100644
--- a/src/devices/bus/gba/gba_slot.h
+++ b/src/devices/bus/gba/gba_slot.h
@@ -3,6 +3,9 @@
#ifndef __GBA_SLOT_H
#define __GBA_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/generic/slot.h b/src/devices/bus/generic/slot.h
index 6ba2e1a1fd5..a3e07f68ef4 100644
--- a/src/devices/bus/generic/slot.h
+++ b/src/devices/bus/generic/slot.h
@@ -3,6 +3,9 @@
#ifndef __GENERIC_SLOT_H
#define __GENERIC_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/hp_optroms/hp_optrom.h b/src/devices/bus/hp_optroms/hp_optrom.h
index d82f8962f4f..6ca5440cce5 100644
--- a/src/devices/bus/hp_optroms/hp_optrom.h
+++ b/src/devices/bus/hp_optroms/hp_optrom.h
@@ -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
diff --git a/src/devices/bus/intv/slot.h b/src/devices/bus/intv/slot.h
index ced41e71fd0..11d88aed25c 100644
--- a/src/devices/bus/intv/slot.h
+++ b/src/devices/bus/intv/slot.h
@@ -3,6 +3,9 @@
#ifndef __INTV_SLOT_H
#define __INTV_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/iq151/iq151.h b/src/devices/bus/iq151/iq151.h
index 1c75ff6c9a0..684aa00b8fd 100644
--- a/src/devices/bus/iq151/iq151.h
+++ b/src/devices/bus/iq151/iq151.h
@@ -45,6 +45,8 @@
#ifndef __IQ151CART_H__
#define __IQ151CART_H__
+#include "softlist_dev.h"
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/isa/sc499.h b/src/devices/bus/isa/sc499.h
index 7bbdaedfb8b..ad536a66df0 100644
--- a/src/devices/bus/isa/sc499.h
+++ b/src/devices/bus/isa/sc499.h
@@ -15,6 +15,8 @@
#include "emu.h"
#include "bus/isa/isa.h"
+#include "softlist_dev.h"
+
//**************************************************************************
// TYPE DEFINITIONS
diff --git a/src/devices/bus/kc/kc.h b/src/devices/bus/kc/kc.h
index 7f9ed65f7d0..6f5e30f4943 100644
--- a/src/devices/bus/kc/kc.h
+++ b/src/devices/bus/kc/kc.h
@@ -11,6 +11,8 @@
#ifndef __KCEXP_H__
#define __KCEXP_H__
+#include "softlist_dev.h"
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/m5/slot.h b/src/devices/bus/m5/slot.h
index cd12d43f3a8..27345e34a99 100644
--- a/src/devices/bus/m5/slot.h
+++ b/src/devices/bus/m5/slot.h
@@ -3,6 +3,9 @@
#ifndef __M5_SLOT_H
#define __M5_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/megadrive/md_slot.h b/src/devices/bus/megadrive/md_slot.h
index 4a86749d991..008ae917fb5 100644
--- a/src/devices/bus/megadrive/md_slot.h
+++ b/src/devices/bus/megadrive/md_slot.h
@@ -3,6 +3,8 @@
#ifndef __MD_SLOT_H
#define __MD_SLOT_H
+#include "softlist_dev.h"
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/msx_slot/cartridge.h b/src/devices/bus/msx_slot/cartridge.h
index b9e1ca5e4f7..63530699b2b 100644
--- a/src/devices/bus/msx_slot/cartridge.h
+++ b/src/devices/bus/msx_slot/cartridge.h
@@ -5,6 +5,7 @@
#include "slot.h"
#include "bus/msx_cart/cartridge.h"
+#include "softlist_dev.h"
extern const device_type MSX_SLOT_CARTRIDGE;
diff --git a/src/devices/bus/neogeo/slot.h b/src/devices/bus/neogeo/slot.h
index 158ff77e706..83de22b0a4b 100644
--- a/src/devices/bus/neogeo/slot.h
+++ b/src/devices/bus/neogeo/slot.h
@@ -4,6 +4,8 @@
#define __NEOGEO_SLOT_H
#include "emu.h"
+#include "softlist_dev.h"
+
/* PCB */
enum
diff --git a/src/devices/bus/nes/aladdin.h b/src/devices/bus/nes/aladdin.h
index b49ecbf964e..1ef34502618 100644
--- a/src/devices/bus/nes/aladdin.h
+++ b/src/devices/bus/nes/aladdin.h
@@ -4,6 +4,7 @@
#define __NES_ALADDIN_H
#include "nxrom.h"
+#include "softlist_dev.h"
//----------------------------------
diff --git a/src/devices/bus/nes/datach.h b/src/devices/bus/nes/datach.h
index 80157a83a5c..980be7a6492 100644
--- a/src/devices/bus/nes/datach.h
+++ b/src/devices/bus/nes/datach.h
@@ -4,6 +4,7 @@
#define __NES_DATACH_H
#include "bandai.h"
+#include "softlist_dev.h"
#include "machine/i2cmem.h"
#include "machine/bcreader.h"
diff --git a/src/devices/bus/nes/karastudio.h b/src/devices/bus/nes/karastudio.h
index e2b5ef874b5..8af386d9e33 100644
--- a/src/devices/bus/nes/karastudio.h
+++ b/src/devices/bus/nes/karastudio.h
@@ -4,6 +4,7 @@
#define __NES_KARASTUDIO_H
#include "nxrom.h"
+#include "softlist_dev.h"
//-----------------------------------------
diff --git a/src/devices/bus/nes/nes_slot.h b/src/devices/bus/nes/nes_slot.h
index d9b64cfa30a..27790c208e0 100644
--- a/src/devices/bus/nes/nes_slot.h
+++ b/src/devices/bus/nes/nes_slot.h
@@ -3,6 +3,9 @@
#ifndef __NES_SLOT_H__
#define __NES_SLOT_H__
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/nes/sunsoft_dcs.h b/src/devices/bus/nes/sunsoft_dcs.h
index 04f8011d29a..bc56a5a2079 100644
--- a/src/devices/bus/nes/sunsoft_dcs.h
+++ b/src/devices/bus/nes/sunsoft_dcs.h
@@ -4,6 +4,7 @@
#define __NES_SUNSOFT_DCS_H
#include "sunsoft.h"
+#include "softlist_dev.h"
//-----------------------------------------------
diff --git a/src/devices/bus/odyssey2/slot.h b/src/devices/bus/odyssey2/slot.h
index 88dde833dca..50f04e74b7e 100644
--- a/src/devices/bus/odyssey2/slot.h
+++ b/src/devices/bus/odyssey2/slot.h
@@ -3,6 +3,9 @@
#ifndef __O2_SLOT_H
#define __O2_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/pce/pce_slot.h b/src/devices/bus/pce/pce_slot.h
index c6cb11096e1..579945229bf 100644
--- a/src/devices/bus/pce/pce_slot.h
+++ b/src/devices/bus/pce/pce_slot.h
@@ -3,6 +3,9 @@
#ifndef __PCE_SLOT_H
#define __PCE_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/plus4/exp.h b/src/devices/bus/plus4/exp.h
index c63d2b618f1..2d18efaa207 100644
--- a/src/devices/bus/plus4/exp.h
+++ b/src/devices/bus/plus4/exp.h
@@ -40,7 +40,7 @@
#define __PLUS4_EXPANSION_SLOT__
#include "emu.h"
-
+#include "softlist_dev.h"
//**************************************************************************
diff --git a/src/devices/bus/ql/rom.h b/src/devices/bus/ql/rom.h
index 606ffe4e67b..5649804df66 100644
--- a/src/devices/bus/ql/rom.h
+++ b/src/devices/bus/ql/rom.h
@@ -31,7 +31,7 @@
#define __QL_ROM_CARTRIDGE_SLOT__
#include "emu.h"
-
+#include "softlist_dev.h"
//**************************************************************************
diff --git a/src/devices/bus/saturn/sat_slot.h b/src/devices/bus/saturn/sat_slot.h
index af16ecbdeaa..f87ce9bf0d3 100644
--- a/src/devices/bus/saturn/sat_slot.h
+++ b/src/devices/bus/saturn/sat_slot.h
@@ -3,6 +3,9 @@
#ifndef __SAT_SLOT_H
#define __SAT_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/scv/slot.h b/src/devices/bus/scv/slot.h
index 1d921f8d607..cbf87dd7d06 100644
--- a/src/devices/bus/scv/slot.h
+++ b/src/devices/bus/scv/slot.h
@@ -3,6 +3,9 @@
#ifndef __SCV_SLOT_H
#define __SCV_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/sega8/sega8_slot.h b/src/devices/bus/sega8/sega8_slot.h
index d27e993f0f7..5a0ce0af010 100644
--- a/src/devices/bus/sega8/sega8_slot.h
+++ b/src/devices/bus/sega8/sega8_slot.h
@@ -3,6 +3,9 @@
#ifndef __SEGA8_SLOT_H
#define __SEGA8_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/snes/snes_slot.h b/src/devices/bus/snes/snes_slot.h
index 7ebfefaa7f2..f6d4208eb1c 100644
--- a/src/devices/bus/snes/snes_slot.h
+++ b/src/devices/bus/snes/snes_slot.h
@@ -3,6 +3,9 @@
#ifndef __SNS_SLOT_H
#define __SNS_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/ti99x/gromport.h b/src/devices/bus/ti99x/gromport.h
index 81fa024f995..11727076ffb 100644
--- a/src/devices/bus/ti99x/gromport.h
+++ b/src/devices/bus/ti99x/gromport.h
@@ -12,6 +12,8 @@
#include "emu.h"
#include "ti99defs.h"
#include "machine/tmc0430.h"
+#include "softlist_dev.h"
+
extern const device_type GROMPORT;
diff --git a/src/devices/bus/vboy/slot.h b/src/devices/bus/vboy/slot.h
index cf031e75f85..71adadd6a2a 100644
--- a/src/devices/bus/vboy/slot.h
+++ b/src/devices/bus/vboy/slot.h
@@ -3,6 +3,9 @@
#ifndef __VBOY_SLOT_H
#define __VBOY_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/vc4000/slot.h b/src/devices/bus/vc4000/slot.h
index 069593208bc..ed3425d0ddc 100644
--- a/src/devices/bus/vc4000/slot.h
+++ b/src/devices/bus/vc4000/slot.h
@@ -3,6 +3,9 @@
#ifndef __VC4000_SLOT_H
#define __VC4000_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/vcs/vcs_slot.h b/src/devices/bus/vcs/vcs_slot.h
index 142c30f9622..b8532dc216d 100755
--- a/src/devices/bus/vcs/vcs_slot.h
+++ b/src/devices/bus/vcs/vcs_slot.h
@@ -3,6 +3,8 @@
#ifndef __VCS_SLOT_H
#define __VCS_SLOT_H
+#include "softlist_dev.h"
+
/***************************************************************************
TYPE DEFINITIONS
diff --git a/src/devices/bus/vectrex/slot.h b/src/devices/bus/vectrex/slot.h
index 5c0183327ae..261574556cd 100644
--- a/src/devices/bus/vectrex/slot.h
+++ b/src/devices/bus/vectrex/slot.h
@@ -3,6 +3,9 @@
#ifndef __VECTREX_SLOT_H
#define __VECTREX_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/vic10/exp.h b/src/devices/bus/vic10/exp.h
index 4221991e124..a3ff118c891 100644
--- a/src/devices/bus/vic10/exp.h
+++ b/src/devices/bus/vic10/exp.h
@@ -37,10 +37,10 @@
#define __VIC10_EXPANSION_SLOT__
#include "emu.h"
+#include "softlist_dev.h"
#include "formats/cbm_crt.h"
-
//**************************************************************************
// CONSTANTS
//**************************************************************************
diff --git a/src/devices/bus/vic20/exp.h b/src/devices/bus/vic20/exp.h
index 1bd6092e400..9f161fb5c28 100644
--- a/src/devices/bus/vic20/exp.h
+++ b/src/devices/bus/vic20/exp.h
@@ -37,7 +37,7 @@
#define __VIC20_EXPANSION_SLOT__
#include "emu.h"
-
+#include "softlist_dev.h"
//**************************************************************************
diff --git a/src/devices/bus/vidbrain/exp.h b/src/devices/bus/vidbrain/exp.h
index f662dd7cfa7..c9cd6677b55 100644
--- a/src/devices/bus/vidbrain/exp.h
+++ b/src/devices/bus/vidbrain/exp.h
@@ -40,7 +40,7 @@
#define __VIDEOBRAIN_EXPANSION_SLOT__
#include "emu.h"
-
+#include "softlist_dev.h"
//**************************************************************************
diff --git a/src/devices/bus/wswan/slot.h b/src/devices/bus/wswan/slot.h
index 72036eab9ca..bd9d74fbe85 100644
--- a/src/devices/bus/wswan/slot.h
+++ b/src/devices/bus/wswan/slot.h
@@ -3,6 +3,9 @@
#ifndef __WS_SLOT_H
#define __WS_SLOT_H
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/bus/z88/z88.h b/src/devices/bus/z88/z88.h
index 60dfa2f924c..73d64575976 100644
--- a/src/devices/bus/z88/z88.h
+++ b/src/devices/bus/z88/z88.h
@@ -54,6 +54,9 @@
#ifndef __Z88CART_H__
#define __Z88CART_H__
+#include "softlist_dev.h"
+
+
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
diff --git a/src/devices/imagedev/cassette.h b/src/devices/imagedev/cassette.h
index 1e6198ddeed..036fc77c534 100644
--- a/src/devices/imagedev/cassette.h
+++ b/src/devices/imagedev/cassette.h
@@ -12,6 +12,7 @@
#define CASSETTE_H
#include "formats/cassimg.h"
+#include "softlist_dev.h"
enum cassette_state
diff --git a/src/devices/imagedev/chd_cd.h b/src/devices/imagedev/chd_cd.h
index 02d39071604..9e2ec9f9a29 100644
--- a/src/devices/imagedev/chd_cd.h
+++ b/src/devices/imagedev/chd_cd.h
@@ -12,6 +12,7 @@
#define CHD_CD_H
#include "cdrom.h"
+#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
diff --git a/src/devices/imagedev/diablo.h b/src/devices/imagedev/diablo.h
index 806a825a1fe..8ab2ac1addc 100644
--- a/src/devices/imagedev/diablo.h
+++ b/src/devices/imagedev/diablo.h
@@ -8,6 +8,7 @@
#define _IMAGEDEV_DIABLO_H_
#include "harddisk.h"
+#include "softlist_dev.h"
#define DIABLO_TAG(_id) "diablo"#_id
diff --git a/src/devices/imagedev/flopdrv.h b/src/devices/imagedev/flopdrv.h
index 9d571c9f390..34e54100364 100644
--- a/src/devices/imagedev/flopdrv.h
+++ b/src/devices/imagedev/flopdrv.h
@@ -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
diff --git a/src/devices/imagedev/floppy.h b/src/devices/imagedev/floppy.h
index ec5e4b983e2..5e93da56c69 100644
--- a/src/devices/imagedev/floppy.h
+++ b/src/devices/imagedev/floppy.h
@@ -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) \
diff --git a/src/devices/imagedev/harddriv.h b/src/devices/imagedev/harddriv.h
index 583a5f53e9f..d2ce6aeaef9 100644
--- a/src/devices/imagedev/harddriv.h
+++ b/src/devices/imagedev/harddriv.h
@@ -12,6 +12,7 @@
#define HARDDRIV_H
#include "harddisk.h"
+#include "softlist_dev.h"
/***************************************************************************
TYPE DEFINITIONS
diff --git a/src/devices/imagedev/snapquik.h b/src/devices/imagedev/snapquik.h
index e14b1d6da6a..1c1a9a3b3df 100644
--- a/src/devices/imagedev/snapquik.h
+++ b/src/devices/imagedev/snapquik.h
@@ -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
diff --git a/src/devices/machine/smartmed.h b/src/devices/machine/smartmed.h
index 0b69fd05886..f1da965c4e9 100644
--- a/src/devices/machine/smartmed.h
+++ b/src/devices/machine/smartmed.h
@@ -8,6 +8,7 @@
#define __SMARTMEDIA_H__
#include "formats/imageutl.h"
+#include "softlist_dev.h"
//#define SMARTMEDIA_IMAGE_SAVE
diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp
index 34a64ddf0f8..8e3d6d04da3 100644
--- a/src/emu/diimage.cpp
+++ b/src/emu/diimage.cpp
@@ -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,17 +1347,33 @@ 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
//
// Load a software part for a device. The part to
@@ -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;
}
diff --git a/src/emu/diimage.h b/src/emu/diimage.h
index 1d066527b49..0f12c2169ba 100644
--- a/src/emu/diimage.h
+++ b/src/emu/diimage.h
@@ -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);
diff --git a/src/emu/drivenum.cpp b/src/emu/drivenum.cpp
index 1d2f6d79f06..450790eb55a 100644
--- a/src/emu/drivenum.cpp
+++ b/src/emu/drivenum.cpp
@@ -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>
diff --git a/src/emu/romload.cpp b/src/emu/romload.cpp
index 989539259cc..0a54658c926 100644
--- a/src/emu/romload.cpp
+++ b/src/emu/romload.cpp
@@ -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"
diff --git a/src/emu/softlist.cpp b/src/emu/softlist.cpp
index 2d6793db3af..67178a1b4bb 100644
--- a/src/emu/softlist.cpp
+++ b/src/emu/softlist.cpp
@@ -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
//**************************************************************************
@@ -195,56 +74,6 @@ const char *software_part::feature(const std::string &feature_name) const
//-------------------------------------------------
-// is_compatible - determine if we are compatible
-// with the given software_list_device
-//-------------------------------------------------
-
-software_compatibility software_part::is_compatible(const software_list_device &swlistdev) const
-{
- // get the softlist filter; if null, assume compatible
- const char *filter = swlistdev.filter();
- if (filter == nullptr)
- return SOFTWARE_IS_COMPATIBLE;
-
- // copy the comma-delimited string and ensure it ends with a final comma
- std::string filt = std::string(filter).append(",");
-
- // get the incompatibility filter and test against it first if it exists
- const char *incompatibility = feature("incompatibility");
- if (incompatibility != nullptr)
- {
- // copy the comma-delimited string and ensure it ends with a final comma
- std::string incomp = std::string(incompatibility).append(",");
-
- // iterate over filter items and see if they exist in the list; if so, it's incompatible
- for (int start = 0, end = filt.find_first_of(',',start); end != -1; start = end + 1, end = filt.find_first_of(',', start))
- {
- std::string token(filt, start, end - start + 1);
- if (incomp.find(token) != -1)
- return SOFTWARE_IS_INCOMPATIBLE;
- }
- }
-
- // get the compatibility feature; if null, assume compatible
- const char *compatibility = feature("compatibility");
- if (compatibility == nullptr)
- return SOFTWARE_IS_COMPATIBLE;
-
- // copy the comma-delimited string and ensure it ends with a final comma
- std::string comp = std::string(compatibility).append(",");
-
- // iterate over filter items and see if they exist in the compatibility list; if so, it's compatible
- for (int start = 0, end = filt.find_first_of(',',start); end != -1; start = end + 1, end = filt.find_first_of(',', start))
- {
- std::string token(filt, start, end - start + 1);
- if (comp.find(token) != -1)
- return SOFTWARE_IS_COMPATIBLE;
- }
- return SOFTWARE_NOT_COMPATIBLE;
-}
-
-
-//-------------------------------------------------
// matches_interface - determine if we match
// an interface in the provided list
//-------------------------------------------------
@@ -264,35 +93,6 @@ bool software_part::matches_interface(const char *interface_list) const
}
-//-------------------------------------------------
-// find_mountable_image - find an image interface
-// that can automatically mount this software part
-//-------------------------------------------------
-
-device_image_interface *software_part::find_mountable_image(const machine_config &mconfig) const
-{
- // if automount="no", don't bother
- const char *mount = feature("automount");
- if (mount != nullptr && strcmp(mount, "no") == 0)
- return nullptr;
-
- for (device_image_interface &image : image_interface_iterator(mconfig.root_device()))
- {
- const char *interface = image.image_interface();
- if (interface != nullptr && matches_interface(interface))
- {
- // mount only if not already mounted
- const char *option = mconfig.options().value(image.brief_instance_name());
- if (*option == '\0' && !image.filename())
-
- return &image;
- }
- }
- return nullptr;
-}
-
-
-
//**************************************************************************
// SOFTWARE INFO
//**************************************************************************
@@ -301,9 +101,8 @@ device_image_interface *software_part::find_mountable_image(const machine_config
// software_info - constructor
//-------------------------------------------------
-software_info::software_info(software_list_device &list, std::string &&name, std::string &&parent, const char *supported)
+software_info::software_info(std::string &&name, std::string &&parent, const char *supported)
: m_next(nullptr),
- m_list(list),
m_supported(SOFTWARE_SUPPORTED_YES),
m_shortname(std::move(name)),
m_parentname(std::move(parent))
@@ -365,383 +164,6 @@ bool software_info::has_multiple_parts(const char *interface) const
}
-
-//**************************************************************************
-// SOFTWARE LIST DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// software_list_device - constructor
-//-------------------------------------------------
-
-software_list_device::software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : device_t(mconfig, SOFTWARE_LIST, "Software list", tag, owner, clock, "software_list", __FILE__),
- m_list_type(SOFTWARE_LIST_ORIGINAL_SYSTEM),
- m_filter(nullptr),
- m_parsed(false),
- m_file(mconfig.options().hash_path(), OPEN_FLAG_READ),
- m_description("")
-{
-}
-
-
-//-------------------------------------------------
-// static_set_type - configuration helper
-// to set the list type
-//-------------------------------------------------
-
-void software_list_device::static_set_type(device_t &device, const char *list, softlist_type list_type)
-{
- software_list_device &swlistdev = downcast<software_list_device &>(device);
- swlistdev.m_list_name.assign(list);
- swlistdev.m_list_type = list_type;
-}
-
-
-//-------------------------------------------------
-// static_set_custom_handler - configuration
-// helper to set a custom callback
-//-------------------------------------------------
-
-void software_list_device::static_set_filter(device_t &device, const char *filter)
-{
- downcast<software_list_device &>(device).m_filter = filter;
-}
-
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void software_list_device::device_start()
-{
-}
-
-
-//-------------------------------------------------
-// find_approx_matches - search ourselves for
-// a list of possible matches of the given name
-// and optional interface
-//-------------------------------------------------
-
-void software_list_device::find_approx_matches(const char *name, int matches, const software_info **list, const char *interface)
-{
- // if no name, return
- if (name == nullptr || name[0] == 0)
- return;
-
- // initialize everyone's states
- std::vector<int> penalty(matches);
- for (int matchnum = 0; matchnum < matches; matchnum++)
- {
- penalty[matchnum] = 9999;
- list[matchnum] = nullptr;
- }
-
- // iterate over our info (will cause a parse if needed)
- for (const software_info &swinfo : get_info())
- {
- const software_part &part = swinfo.parts().front();
- if ((interface == nullptr || part.matches_interface(interface)) && part.is_compatible(*this) == SOFTWARE_IS_COMPATIBLE)
- {
- // pick the best match between driver name and description
- int longpenalty = driver_list::penalty_compare(name, swinfo.longname().c_str());
- int shortpenalty = driver_list::penalty_compare(name, swinfo.shortname().c_str());
- int curpenalty = std::min(longpenalty, shortpenalty);
-
- // insert into the sorted table of matches
- for (int matchnum = matches - 1; matchnum >= 0; matchnum--)
- {
- // stop if we're worse than the current entry
- if (curpenalty >= penalty[matchnum])
- break;
-
- // as long as this isn't the last entry, bump this one down
- if (matchnum < matches - 1)
- {
- penalty[matchnum + 1] = penalty[matchnum];
- list[matchnum + 1] = list[matchnum];
- }
- list[matchnum] = &swinfo;
- penalty[matchnum] = curpenalty;
- }
- }
- }
-}
-
-
-//-------------------------------------------------
-// release - reset to a pre-parsed state
-//-------------------------------------------------
-
-void software_list_device::release()
-{
- osd_printf_verbose("Resetting %s\n", m_file.filename());
- m_parsed = false;
- m_description.clear();
- m_errors.clear();
- m_infolist.clear();
-}
-
-
-//-------------------------------------------------
-// find_by_name - find a software list by name
-// across all software list devices
-//-------------------------------------------------
-
-software_list_device *software_list_device::find_by_name(const machine_config &config, const char *name)
-{
- // iterate over each device in the system and find a match
- for (software_list_device &swlistdev : software_list_device_iterator(config.root_device()))
- if (strcmp(swlistdev.list_name(), name) == 0)
- return &swlistdev;
- return nullptr;
-}
-
-
-//-------------------------------------------------
-// software_display_matches - display a list of
-// possible matches in the system to the given
-// name, across all software list devices
-//-------------------------------------------------
-
-void software_list_device::display_matches(const machine_config &config, const char *interface, const char *name)
-{
- // check if there is at least one software list
- software_list_device_iterator deviter(config.root_device());
- if (deviter.first() != nullptr)
- osd_printf_error("\n\"%s\" approximately matches the following\n"
- "supported software items (best match first):\n\n", name);
-
- // iterate through lists
- for (software_list_device &swlistdev : deviter)
- {
- // get the top 16 approximate matches for the selected device interface (i.e. only carts for cartslot, etc.)
- const software_info *matches[16] = { nullptr };
- swlistdev.find_approx_matches(name, ARRAY_LENGTH(matches), matches, interface);
-
- // if we found some, print them
- if (matches[0] != nullptr)
- {
- // different output depending on original system or compatible
- if (swlistdev.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM)
- osd_printf_error("* Software list \"%s\" (%s) matches: \n", swlistdev.list_name(), swlistdev.description());
- else
- osd_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlistdev.list_name(), swlistdev.description());
-
- // print them out
- for (auto &match : matches)
- {
- if (match != nullptr)
- osd_printf_error("%-18s%s\n", match->shortname().c_str(), match->longname().c_str());
- }
-
- osd_printf_error("\n");
- }
- }
-}
-
-
-//-------------------------------------------------
-// find - find an item by name in the software
-// list, using wildcards and optionally starting
-// from an intermediate point
-//-------------------------------------------------
-
-const software_info *software_list_device::find(const char *look_for)
-{
- // nullptr search returns nothing
- if (look_for == nullptr)
- return nullptr;
-
- bool iswild = strchr(look_for, '*') != nullptr || strchr(look_for, '?');
-
- // find a match (will cause a parse if needed when calling get_info)
- const auto &info_list = get_info();
- auto iter = std::find_if(
- info_list.begin(),
- info_list.end(),
- [&](const software_info &info)
- {
- const char *shortname = info.shortname().c_str();
- return (iswild && core_strwildcmp(look_for, shortname) == 0)
- || core_stricmp(look_for, shortname) == 0;
- });
-
- return iter != info_list.end()
- ? &*iter
- : nullptr;
-}
-
-
-//-------------------------------------------------
-// parse - parse our softlist file
-//-------------------------------------------------
-
-void software_list_device::parse()
-{
- // skip if done
- if (m_parsed)
- return;
-
- // reset the errors
- m_errors.clear();
-
- // attempt to open the file
- osd_file::error filerr = m_file.open(m_list_name.c_str(), ".xml");
- if (filerr == osd_file::error::NONE)
- {
- // parse if no error
- std::ostringstream errs;
- softlist_parser parser(*this, errs);
- m_file.close();
- m_errors = errs.str();
- }
- else
- m_errors = string_format("Error opening file: %s\n", filename());
-
- // indicate that we've been parsed
- m_parsed = true;
-}
-
-
-//-------------------------------------------------
-// device_validity_check - validate the device
-// configuration
-//-------------------------------------------------
-
-void software_list_device::device_validity_check(validity_checker &valid) const
-{
- // add to the global map whenever we check a list so we don't re-check
- // it in the future
- if (valid.already_checked(std::string("softlist/").append(m_list_name).c_str()))
- return;
-
- // do device validation only in case of validate command
- if (!valid.validate_all())
- return;
-
- // actually do the validate
- const_cast<software_list_device *>(this)->internal_validity_check(valid);
-}
-
-
-//-------------------------------------------------
-// internal_validity_check - internal helper to
-// check the list
-//-------------------------------------------------
-
-void software_list_device::internal_validity_check(validity_checker &valid)
-{
- enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 };
-
- softlist_map names;
- softlist_map descriptions;
- for (const software_info &swinfo : get_info())
- {
- // first parse and output core errors if any
- if (m_errors.length() > 0)
- {
- osd_printf_error("%s: Errors parsing software list:\n%s", filename(), errors_string());
- break;
- }
-
- // Now check if the xml data is valid:
-
- // Did we lost any description?
- if (swinfo.longname().empty())
- {
- osd_printf_error("%s: %s has no description\n", filename(), swinfo.shortname().c_str());
- break;
- }
-
- // Did we lost any year?
- if (swinfo.year().empty())
- {
- osd_printf_error("%s: %s has no year\n", filename(), swinfo.shortname().c_str());
- break;
- }
-
- // Did we lost any publisher?
- if (swinfo.publisher().empty())
- {
- osd_printf_error("%s: %s has no publisher\n", filename(), swinfo.shortname().c_str());
- break;
- }
-
- // Did we lost the software parts?
- if (swinfo.parts().empty())
- {
- osd_printf_error("%s: %s has no part\n", filename(), swinfo.shortname().c_str());
- break;
- }
-
- // Second, since the xml is fine, run additional checks:
-
- // check for duplicate names
- if (!names.insert(std::make_pair(swinfo.shortname(), &swinfo)).second)
- {
- const software_info *match = names.find(swinfo.shortname())->second;
- osd_printf_error("%s: %s is a duplicate name (%s)\n", filename(), swinfo.shortname().c_str(), match->shortname().c_str());
- }
-
- // check for duplicate descriptions
- std::string longname = std::string(swinfo.longname());
- if (!descriptions.insert(std::make_pair(strmakelower(longname), &swinfo)).second)
- osd_printf_error("%s: %s is a duplicate description (%s)\n", filename(), swinfo.longname().c_str(), swinfo.shortname().c_str());
-
- bool is_clone = false;
- if (!swinfo.parentname().empty())
- {
- is_clone = true;
- if (swinfo.parentname() == swinfo.shortname())
- {
- osd_printf_error("%s: %s is set as a clone of itself\n", filename(), swinfo.shortname().c_str());
- break;
- }
-
- // make sure the parent exists
- const software_info *swinfo2 = find(swinfo.parentname().c_str());
-
- if (swinfo2 == nullptr)
- osd_printf_error("%s: parent '%s' software for '%s' not found\n", filename(), swinfo.parentname().c_str(), swinfo.shortname().c_str());
- else if (!swinfo2->parentname().empty())
- osd_printf_error("%s: %s is a clone of a clone\n", filename(), swinfo.shortname().c_str());
- }
-
- // make sure the driver name is 8 chars or less
- if ((is_clone && swinfo.shortname().length() > NAME_LEN_CLONE) || (!is_clone && swinfo.shortname().length() > NAME_LEN_PARENT))
- osd_printf_error("%s: %s %s driver name must be %d characters or less\n", filename(), swinfo.shortname().c_str(),
- is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT);
-
- // make sure the year is only digits, '?' or '+'
- for (const char *s = swinfo.year().c_str(); *s != 0; s++)
- if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
- {
- osd_printf_error("%s: %s has an invalid year '%s'\n", filename(), swinfo.shortname().c_str(), swinfo.year().c_str());
- break;
- }
-
- softlist_map part_names;
- for (const software_part &part : swinfo.parts())
- {
- if (part.interface().empty())
- osd_printf_error("%s: %s has a part (%s) without interface\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
-
- if (part.romdata() == nullptr)
- osd_printf_error("%s: %s has a part (%s) with no data\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
-
- if (!part_names.insert(std::make_pair(part.name(), &swinfo)).second)
- osd_printf_error("%s: %s has a part (%s) whose name is duplicate\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
- }
- }
-
- // release all the memory
- release();
-}
-
-
-
//**************************************************************************
// SOFTWARE LIST PARSER
//**************************************************************************
@@ -750,8 +172,10 @@ void software_list_device::internal_validity_check(validity_checker &valid)
// softlist_parser - constructor
//-------------------------------------------------
-softlist_parser::softlist_parser(software_list_device &list, std::ostringstream &errors)
- : m_list(list),
+softlist_parser::softlist_parser(util::core_file &file, const std::string &filename, std::list<software_info> &infolist, std::ostringstream &errors)
+ : m_file(file),
+ m_filename(filename),
+ m_infolist(infolist),
m_errors(errors),
m_done(false),
m_data_accum_expected(false),
@@ -759,8 +183,6 @@ softlist_parser::softlist_parser(software_list_device &list, std::ostringstream
m_current_part(nullptr),
m_pos(POS_ROOT)
{
- osd_printf_verbose("Parsing %s\n", m_list.m_file.filename());
-
// create the parser
m_parser = XML_ParserCreate_MM(nullptr, nullptr, nullptr);
if (m_parser == nullptr)
@@ -772,12 +194,12 @@ softlist_parser::softlist_parser(software_list_device &list, std::ostringstream
XML_SetCharacterDataHandler(m_parser, &softlist_parser::data_handler);
// parse the file contents
- m_list.m_file.seek(0, SEEK_SET);
+ m_file.seek(0, SEEK_SET);
char buffer[1024];
while (!m_done)
{
- UINT32 length = m_list.m_file.read(buffer, sizeof(buffer));
- m_done = m_list.m_file.eof();
+ UINT32 length = m_file.read(buffer, sizeof(buffer));
+ m_done = m_file.eof();
if (XML_Parse(m_parser, buffer, length, m_done) == XML_STATUS_ERROR)
{
parse_error("%s", parser_error());
@@ -787,9 +209,39 @@ softlist_parser::softlist_parser(software_list_device &list, std::ostringstream
// free the parser
XML_ParserFree(m_parser);
- osd_printf_verbose("Parsing complete\n");
}
+
+//-------------------------------------------------
+// line
+//-------------------------------------------------
+
+int softlist_parser::line() const
+{
+ return XML_GetCurrentLineNumber(m_parser);
+}
+
+
+//-------------------------------------------------
+// column
+//-------------------------------------------------
+
+int softlist_parser::column() const
+{
+ return XML_GetCurrentColumnNumber(m_parser);
+}
+
+
+//-------------------------------------------------
+// parser_error
+//-------------------------------------------------
+
+const char *softlist_parser::parser_error() const
+{
+ return XML_ErrorString(XML_GetErrorCode(m_parser));
+}
+
+
//-------------------------------------------------
// parse_error - append a parsing error with
// filename, line and column information
@@ -799,7 +251,7 @@ template <typename Format, typename... Params>
inline void softlist_parser::parse_error(Format &&fmt, Params &&... args)
{
// always start with filename(line.column):
- util::stream_format(m_errors, "%s(%d.%d): ", filename(), line(), column());
+ util::stream_format(m_errors, "%s(%d.%d): ", m_filename, line(), column());
// append the remainder of the string
util::stream_format(m_errors, std::forward<Format>(fmt), std::forward<Params>(args)...);
@@ -894,17 +346,13 @@ void softlist_parser::add_rom_entry(std::string &&name, std::string &&hashdata,
// make sure we don't add duplicate regions
if (!name.empty() && (flags & ROMENTRY_TYPEMASK) == ROMENTRYTYPE_REGION)
+ {
for (auto &elem : m_current_part->m_romdata)
- if (!elem.name().empty() && elem.name() == name)
+ if (elem.name() == name)
parse_error("Duplicated dataarea %s in software %s", name, infoname());
+ }
- // create the new entry and append it
- m_current_part->m_romdata.emplace_back(
- std::move(name),
- std::move(hashdata),
- offset,
- length,
- flags);
+ m_current_part->m_romdata.emplace_back(std::move(name), std::move(hashdata), offset, length, flags);
}
@@ -986,7 +434,7 @@ void softlist_parser::end_handler(void *data, const char *name)
// data_handler - expat data handler
//-------------------------------------------------
-void softlist_parser::data_handler(void *data, const XML_Char *s, int len)
+void softlist_parser::data_handler(void *data, const char *s, int len)
{
softlist_parser *state = reinterpret_cast<softlist_parser *>(data);
@@ -1018,7 +466,7 @@ void softlist_parser::parse_root_start(const char *tagname, const char **attribu
const auto attrvalues = parse_attributes(attributes, attrnames);
if (!attrvalues[1].empty())
- m_list.m_description = attrvalues[1];
+ m_description = attrvalues[1];
}
else
unknown_tag(tagname);
@@ -1040,8 +488,8 @@ void softlist_parser::parse_main_start(const char *tagname, const char **attribu
if (!attrvalues[0].empty())
{
- m_list.m_infolist.emplace_back(m_list, std::move(attrvalues[0]), std::move(attrvalues[1]), attrvalues[2].c_str());
- m_current_info = &m_list.m_infolist.back();
+ m_infolist.emplace_back(std::move(attrvalues[0]), std::move(attrvalues[1]), attrvalues[2].c_str());
+ m_current_info = &m_infolist.back();
}
else
parse_error("No name defined for item");
@@ -1354,7 +802,7 @@ void softlist_parser::parse_soft_end(const char *tagname)
return;
// was any dataarea/rom information encountered? if so, add a terminator
- if (m_current_part->romdata() != nullptr)
+ if (!m_current_part->m_romdata.empty())
add_rom_entry("", "", 0, 0, ROMENTRYTYPE_END);
// get the info; if present, copy shared data (we assume name/value strings live
@@ -1364,3 +812,4 @@ void softlist_parser::parse_soft_end(const char *tagname)
m_current_part->m_featurelist.emplace_back(item.name(), item.value());
}
}
+
diff --git a/src/emu/softlist.h b/src/emu/softlist.h
index 9b6cfd829bf..19ebc73e973 100644
--- a/src/emu/softlist.h
+++ b/src/emu/softlist.h
@@ -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
+ };
+
+ // 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;
+
+ // 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); }
- // 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(); }
-
- // 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();
-
- // 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;
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_validity_check(validity_checker &valid) const override 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;
- const_string_pool m_stringpool;
+ 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 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
+ 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;
-
-// device type iterator
-typedef device_type_iterator<&device_creator<software_list_device>, software_list_device> software_list_device_iterator;
-
+#endif // __SOFTLIST_H_
-#endif
diff --git a/src/emu/softlist_dev.cpp b/src/emu/softlist_dev.cpp
new file mode 100644
index 00000000000..eac92c08939
--- /dev/null
+++ b/src/emu/softlist_dev.cpp
@@ -0,0 +1,523 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***************************************************************************
+
+ softlist_dev.cpp
+
+ Software list construction helpers.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "diimage.h"
+#include "softlist_dev.h"
+#include "validity.h"
+
+#include <ctype.h>
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+typedef std::unordered_map<std::string, const software_info *> softlist_map;
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+const device_type SOFTWARE_LIST = &device_creator<software_list_device>;
+false_software_list_loader false_software_list_loader::s_instance;
+rom_software_list_loader rom_software_list_loader::s_instance;
+image_software_list_loader image_software_list_loader::s_instance;
+
+
+//**************************************************************************
+// SOFTWARE LIST LOADER
+//**************************************************************************
+
+//-------------------------------------------------
+// false_software_list_loader::load_software
+//-------------------------------------------------
+
+bool false_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
+{
+ return false;
+}
+
+
+//-------------------------------------------------
+// rom_software_list_loader::load_software
+//-------------------------------------------------
+
+bool rom_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
+{
+ swlist.machine().rom_load().load_software_part_region(device, swlist, swname, start_entry);
+ return true;
+}
+
+
+//-------------------------------------------------
+// image_software_list_loader::load_software
+//-------------------------------------------------
+
+bool image_software_list_loader::load_software(device_image_interface &device, software_list_device &swlist, const char *swname, const rom_entry *start_entry) const
+{
+ return device.load_software(swlist, swname, start_entry);
+}
+
+
+//**************************************************************************
+// SOFTWARE LIST DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// software_list_device - constructor
+//-------------------------------------------------
+
+software_list_device::software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, SOFTWARE_LIST, "Software list", tag, owner, clock, "software_list", __FILE__),
+ m_list_type(SOFTWARE_LIST_ORIGINAL_SYSTEM),
+ m_filter(nullptr),
+ m_parsed(false),
+ m_file(mconfig.options().hash_path(), OPEN_FLAG_READ),
+ m_description("")
+{
+}
+
+
+//-------------------------------------------------
+// static_set_type - configuration helper
+// to set the list type
+//-------------------------------------------------
+
+void software_list_device::static_set_type(device_t &device, const char *list, softlist_type list_type)
+{
+ software_list_device &swlistdev = downcast<software_list_device &>(device);
+ swlistdev.m_list_name.assign(list);
+ swlistdev.m_list_type = list_type;
+}
+
+
+//-------------------------------------------------
+// static_set_custom_handler - configuration
+// helper to set a custom callback
+//-------------------------------------------------
+
+void software_list_device::static_set_filter(device_t &device, const char *filter)
+{
+ downcast<software_list_device &>(device).m_filter = filter;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void software_list_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// find_approx_matches - search ourselves for
+// a list of possible matches of the given name
+// and optional interface
+//-------------------------------------------------
+
+void software_list_device::find_approx_matches(const char *name, int matches, const software_info **list, const char *interface)
+{
+ // if no name, return
+ if (name == nullptr || name[0] == 0)
+ return;
+
+ // initialize everyone's states
+ std::vector<int> penalty(matches);
+ for (int matchnum = 0; matchnum < matches; matchnum++)
+ {
+ penalty[matchnum] = 9999;
+ list[matchnum] = nullptr;
+ }
+
+ // iterate over our info (will cause a parse if needed)
+ for (const software_info &swinfo : get_info())
+ {
+ const software_part &part = swinfo.parts().front();
+ if ((interface == nullptr || part.matches_interface(interface)) && is_compatible(part) == SOFTWARE_IS_COMPATIBLE)
+ {
+ // pick the best match between driver name and description
+ int longpenalty = driver_list::penalty_compare(name, swinfo.longname().c_str());
+ int shortpenalty = driver_list::penalty_compare(name, swinfo.shortname().c_str());
+ int curpenalty = std::min(longpenalty, shortpenalty);
+
+ // insert into the sorted table of matches
+ for (int matchnum = matches - 1; matchnum >= 0; matchnum--)
+ {
+ // stop if we're worse than the current entry
+ if (curpenalty >= penalty[matchnum])
+ break;
+
+ // as long as this isn't the last entry, bump this one down
+ if (matchnum < matches - 1)
+ {
+ penalty[matchnum + 1] = penalty[matchnum];
+ list[matchnum + 1] = list[matchnum];
+ }
+ list[matchnum] = &swinfo;
+ penalty[matchnum] = curpenalty;
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// release - reset to a pre-parsed state
+//-------------------------------------------------
+
+void software_list_device::release()
+{
+ osd_printf_verbose("Resetting %s\n", m_file.filename());
+ m_parsed = false;
+ m_description.clear();
+ m_errors.clear();
+ m_infolist.clear();
+}
+
+
+//-------------------------------------------------
+// find_by_name - find a software list by name
+// across all software list devices
+//-------------------------------------------------
+
+software_list_device *software_list_device::find_by_name(const machine_config &config, const std::string &name)
+{
+ // iterate over each device in the system and find a match
+ for (software_list_device &swlistdev : software_list_device_iterator(config.root_device()))
+ if (swlistdev.list_name() == name)
+ return &swlistdev;
+ return nullptr;
+}
+
+
+//-------------------------------------------------
+// software_display_matches - display a list of
+// possible matches in the system to the given
+// name, across all software list devices
+//-------------------------------------------------
+
+void software_list_device::display_matches(const machine_config &config, const char *interface, const char *name)
+{
+ // check if there is at least one software list
+ software_list_device_iterator deviter(config.root_device());
+ if (deviter.first() != nullptr)
+ osd_printf_error("\n\"%s\" approximately matches the following\n"
+ "supported software items (best match first):\n\n", name);
+
+ // iterate through lists
+ for (software_list_device &swlistdev : deviter)
+ {
+ // get the top 16 approximate matches for the selected device interface (i.e. only carts for cartslot, etc.)
+ const software_info *matches[16] = { nullptr };
+ swlistdev.find_approx_matches(name, ARRAY_LENGTH(matches), matches, interface);
+
+ // if we found some, print them
+ if (matches[0] != nullptr)
+ {
+ // different output depending on original system or compatible
+ if (swlistdev.list_type() == SOFTWARE_LIST_ORIGINAL_SYSTEM)
+ osd_printf_error("* Software list \"%s\" (%s) matches: \n", swlistdev.list_name().c_str(), swlistdev.description());
+ else
+ osd_printf_error("* Compatible software list \"%s\" (%s) matches: \n", swlistdev.list_name().c_str(), swlistdev.description());
+
+ // print them out
+ for (auto &match : matches)
+ {
+ if (match != nullptr)
+ osd_printf_error("%-18s%s\n", match->shortname().c_str(), match->longname().c_str());
+ }
+
+ osd_printf_error("\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// find - find an item by name in the software
+// list, using wildcards and optionally starting
+// from an intermediate point
+//-------------------------------------------------
+
+const software_info *software_list_device::find(const char *look_for)
+{
+ // nullptr search returns nothing
+ if (look_for == nullptr)
+ return nullptr;
+
+ bool iswild = strchr(look_for, '*') != nullptr || strchr(look_for, '?');
+
+ // find a match (will cause a parse if needed when calling get_info)
+ const auto &info_list = get_info();
+ auto iter = std::find_if(
+ info_list.begin(),
+ info_list.end(),
+ [&](const software_info &info)
+ {
+ const char *shortname = info.shortname().c_str();
+ return (iswild && core_strwildcmp(look_for, shortname) == 0)
+ || core_stricmp(look_for, shortname) == 0;
+ });
+
+ return iter != info_list.end()
+ ? &*iter
+ : nullptr;
+}
+
+
+//-------------------------------------------------
+// parse - parse our softlist file
+//-------------------------------------------------
+
+void software_list_device::parse()
+{
+ // skip if done
+ if (m_parsed)
+ return;
+
+ // reset the errors
+ m_errors.clear();
+
+ // attempt to open the file
+ osd_file::error filerr = m_file.open(m_list_name.c_str(), ".xml");
+ if (filerr == osd_file::error::NONE)
+ {
+ // parse if no error
+ std::ostringstream errs;
+ softlist_parser parser(m_file, m_description, m_infolist, errs);
+ m_file.close();
+ m_errors = errs.str();
+ }
+ else
+ m_errors = string_format("Error opening file: %s\n", filename());
+
+ // indicate that we've been parsed
+ m_parsed = true;
+}
+
+
+//-------------------------------------------------
+// is_compatible - determine if we are compatible
+// with the given software_list_device
+//-------------------------------------------------
+
+software_compatibility software_list_device::is_compatible(const software_part &swpart) const
+{
+ // get the softlist filter; if null, assume compatible
+ if (m_filter == nullptr)
+ return SOFTWARE_IS_COMPATIBLE;
+
+ // copy the comma-delimited string and ensure it ends with a final comma
+ std::string filt = std::string(m_filter).append(",");
+
+ // get the incompatibility filter and test against it first if it exists
+ const char *incompatibility = swpart.feature("incompatibility");
+ if (incompatibility != nullptr)
+ {
+ // copy the comma-delimited string and ensure it ends with a final comma
+ std::string incomp = std::string(incompatibility).append(",");
+
+ // iterate over filter items and see if they exist in the list; if so, it's incompatible
+ for (int start = 0, end = filt.find_first_of(',', start); end != -1; start = end + 1, end = filt.find_first_of(',', start))
+ {
+ std::string token(filt, start, end - start + 1);
+ if (incomp.find(token) != -1)
+ return SOFTWARE_IS_INCOMPATIBLE;
+ }
+ }
+
+ // get the compatibility feature; if null, assume compatible
+ const char *compatibility = swpart.feature("compatibility");
+ if (compatibility == nullptr)
+ return SOFTWARE_IS_COMPATIBLE;
+
+ // copy the comma-delimited string and ensure it ends with a final comma
+ std::string comp = std::string(compatibility).append(",");
+
+ // iterate over filter items and see if they exist in the compatibility list; if so, it's compatible
+ for (int start = 0, end = filt.find_first_of(',', start); end != -1; start = end + 1, end = filt.find_first_of(',', start))
+ {
+ std::string token(filt, start, end - start + 1);
+ if (comp.find(token) != -1)
+ return SOFTWARE_IS_COMPATIBLE;
+ }
+ return SOFTWARE_NOT_COMPATIBLE;
+}
+
+
+//-------------------------------------------------
+// find_mountable_image - find an image interface
+// that can automatically mount this software part
+//-------------------------------------------------
+
+device_image_interface *software_list_device::find_mountable_image(const machine_config &mconfig, const software_part &part)
+{
+ // if automount="no", don't bother
+ const char *mount = part.feature("automount");
+ if (mount != nullptr && strcmp(mount, "no") == 0)
+ return nullptr;
+
+ for (device_image_interface &image : image_interface_iterator(mconfig.root_device()))
+ {
+ const char *interface = image.image_interface();
+ if (interface != nullptr && part.matches_interface(interface))
+ {
+ // mount only if not already mounted
+ const char *option = mconfig.options().value(image.brief_instance_name());
+ if (*option == '\0' && !image.filename())
+ return &image;
+ }
+ }
+ return nullptr;
+}
+
+
+//-------------------------------------------------
+// device_validity_check - validate the device
+// configuration
+//-------------------------------------------------
+
+void software_list_device::device_validity_check(validity_checker &valid) const
+{
+ // add to the global map whenever we check a list so we don't re-check
+ // it in the future
+ if (valid.already_checked(std::string("softlist/").append(m_list_name).c_str()))
+ return;
+
+ // do device validation only in case of validate command
+ if (!valid.validate_all())
+ return;
+
+ // actually do the validate
+ const_cast<software_list_device *>(this)->internal_validity_check(valid);
+}
+
+
+//-------------------------------------------------
+// internal_validity_check - internal helper to
+// check the list
+//-------------------------------------------------
+
+void software_list_device::internal_validity_check(validity_checker &valid)
+{
+ enum { NAME_LEN_PARENT = 8, NAME_LEN_CLONE = 16 };
+
+ softlist_map names;
+ softlist_map descriptions;
+ for (const software_info &swinfo : get_info())
+ {
+ // first parse and output core errors if any
+ if (m_errors.length() > 0)
+ {
+ osd_printf_error("%s: Errors parsing software list:\n%s", filename(), errors_string());
+ break;
+ }
+
+ // Now check if the xml data is valid:
+
+ // Did we lost any description?
+ if (swinfo.longname().empty())
+ {
+ osd_printf_error("%s: %s has no description\n", filename(), swinfo.shortname().c_str());
+ break;
+ }
+
+ // Did we lost any year?
+ if (swinfo.year().empty())
+ {
+ osd_printf_error("%s: %s has no year\n", filename(), swinfo.shortname().c_str());
+ break;
+ }
+
+ // Did we lost any publisher?
+ if (swinfo.publisher().empty())
+ {
+ osd_printf_error("%s: %s has no publisher\n", filename(), swinfo.shortname().c_str());
+ break;
+ }
+
+ // Did we lost the software parts?
+ if (swinfo.parts().empty())
+ {
+ osd_printf_error("%s: %s has no part\n", filename(), swinfo.shortname().c_str());
+ break;
+ }
+
+ // Second, since the xml is fine, run additional checks:
+
+ // check for duplicate names
+ if (!names.insert(std::make_pair(swinfo.shortname(), &swinfo)).second)
+ {
+ const software_info *match = names.find(swinfo.shortname())->second;
+ osd_printf_error("%s: %s is a duplicate name (%s)\n", filename(), swinfo.shortname().c_str(), match->shortname().c_str());
+ }
+
+ // check for duplicate descriptions
+ std::string longname = std::string(swinfo.longname());
+ if (!descriptions.insert(std::make_pair(strmakelower(longname), &swinfo)).second)
+ osd_printf_error("%s: %s is a duplicate description (%s)\n", filename(), swinfo.longname().c_str(), swinfo.shortname().c_str());
+
+ bool is_clone = false;
+ if (!swinfo.parentname().empty())
+ {
+ is_clone = true;
+ if (swinfo.parentname() == swinfo.shortname())
+ {
+ osd_printf_error("%s: %s is set as a clone of itself\n", filename(), swinfo.shortname().c_str());
+ break;
+ }
+
+ // make sure the parent exists
+ const software_info *swinfo2 = find(swinfo.parentname().c_str());
+
+ if (swinfo2 == nullptr)
+ osd_printf_error("%s: parent '%s' software for '%s' not found\n", filename(), swinfo.parentname().c_str(), swinfo.shortname().c_str());
+ else if (!swinfo2->parentname().empty())
+ osd_printf_error("%s: %s is a clone of a clone\n", filename(), swinfo.shortname().c_str());
+ }
+
+ // make sure the driver name is 8 chars or less
+ if ((is_clone && swinfo.shortname().length() > NAME_LEN_CLONE) || (!is_clone && swinfo.shortname().length() > NAME_LEN_PARENT))
+ osd_printf_error("%s: %s %s driver name must be %d characters or less\n", filename(), swinfo.shortname().c_str(),
+ is_clone ? "clone" : "parent", is_clone ? NAME_LEN_CLONE : NAME_LEN_PARENT);
+
+ // make sure the year is only digits, '?' or '+'
+ for (const char *s = swinfo.year().c_str(); *s != 0; s++)
+ if (!isdigit((UINT8)*s) && *s != '?' && *s != '+')
+ {
+ osd_printf_error("%s: %s has an invalid year '%s'\n", filename(), swinfo.shortname().c_str(), swinfo.year().c_str());
+ break;
+ }
+
+ softlist_map part_names;
+ for (const software_part &part : swinfo.parts())
+ {
+ if (part.interface().empty())
+ osd_printf_error("%s: %s has a part (%s) without interface\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
+
+ if (part.romdata().empty())
+ osd_printf_error("%s: %s has a part (%s) with no data\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
+
+ if (!part_names.insert(std::make_pair(part.name(), &swinfo)).second)
+ osd_printf_error("%s: %s has a part (%s) whose name is duplicate\n", filename(), swinfo.shortname().c_str(), part.name().c_str());
+ }
+ }
+
+ // release all the memory
+ release();
+}
+
+
diff --git a/src/emu/softlist_dev.h b/src/emu/softlist_dev.h
new file mode 100644
index 00000000000..49ab4fad1ff
--- /dev/null
+++ b/src/emu/softlist_dev.h
@@ -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_
diff --git a/src/frontend/mame/audit.cpp b/src/frontend/mame/audit.cpp
index 9dfc99940f2..6adb5539747 100644
--- a/src/frontend/mame/audit.cpp
+++ b/src/frontend/mame/audit.cpp
@@ -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());
}
diff --git a/src/frontend/mame/audit.h b/src/frontend/mame/audit.h
index 1999fb229fa..9e0e131e2ca 100644
--- a/src/frontend/mame/audit.h
+++ b/src/frontend/mame/audit.h
@@ -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;
diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp
index 2ce5a6a5581..bc98768242a 100644
--- a/src/frontend/mame/clifront.cpp
+++ b/src/frontend/mame/clifront.cpp
@@ -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())
{
diff --git a/src/frontend/mame/info.cpp b/src/frontend/mame/info.cpp
index 918cd07f673..a278288defb 100644
--- a/src/frontend/mame/info.cpp
+++ b/src/frontend/mame/info.cpp
@@ -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());
diff --git a/src/frontend/mame/mameopts.cpp b/src/frontend/mame/mameopts.cpp
index c64b8fd7ebc..9b1150a9590 100644
--- a/src/frontend/mame/mameopts.cpp
+++ b/src/frontend/mame/mameopts.cpp
@@ -11,7 +11,7 @@
#include "emu.h"
#include "mameopts.h"
#include "drivenum.h"
-#include "softlist.h"
+#include "softlist_dev.h"
#include <ctype.h>
diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp
index b046acbe66c..a0ab3a99359 100644
--- a/src/frontend/mame/ui/imgcntrl.cpp
+++ b/src/frontend/mame/ui/imgcntrl.cpp
@@ -20,7 +20,7 @@
#include "audit.h"
#include "drivenum.h"
#include "emuopts.h"
-#include "softlist.h"
+#include "softlist_dev.h"
#include "zippath.h"
diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp
index fd93bb6d1f7..fc56ca18dc4 100644
--- a/src/frontend/mame/ui/inifile.cpp
+++ b/src/frontend/mame/ui/inifile.cpp
@@ -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"
//-------------------------------------------------
diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp
index 3019bff9d0f..9fa2e466360 100644
--- a/src/frontend/mame/ui/selgame.cpp
+++ b/src/frontend/mame/ui/selgame.cpp
@@ -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[];
diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp
index 1a6b6842df5..e3848e31691 100644
--- a/src/frontend/mame/ui/selsoft.cpp
+++ b/src/frontend/mame/ui/selsoft.cpp
@@ -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();
diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp
index b9a25a18535..4ac67f607dd 100644
--- a/src/frontend/mame/ui/swlist.cpp
+++ b/src/frontend/mame/ui/swlist.cpp
@@ -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());
diff --git a/src/mame/drivers/c65.cpp b/src/mame/drivers/c65.cpp
index fb9f882ead7..1f007bd15f0 100644
--- a/src/mame/drivers/c65.cpp
+++ b/src/mame/drivers/c65.cpp
@@ -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
diff --git a/src/mame/drivers/sega_sawatte.cpp b/src/mame/drivers/sega_sawatte.cpp
index 9ef349c81e4..04dd9fa432e 100644
--- a/src/mame/drivers/sega_sawatte.cpp
+++ b/src/mame/drivers/sega_sawatte.cpp
@@ -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
diff --git a/src/mame/machine/at.cpp b/src/mame/machine/at.cpp
index 8096b50e289..14508efb797 100644
--- a/src/mame/machine/at.cpp
+++ b/src/mame/machine/at.cpp
@@ -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
diff --git a/src/mame/machine/microdrv.h b/src/mame/machine/microdrv.h
index 5e1547b9dc5..e7d98d8e838 100644
--- a/src/mame/machine/microdrv.h
+++ b/src/mame/machine/microdrv.h
@@ -13,6 +13,7 @@
#ifndef __MICRODRV__
#define __MICRODRV__
+#include "softlist_dev.h"
//**************************************************************************
diff --git a/src/mame/machine/psion_pack.h b/src/mame/machine/psion_pack.h
index 1c0cd8189d8..f0358844e93 100644
--- a/src/mame/machine/psion_pack.h
+++ b/src/mame/machine/psion_pack.h
@@ -9,6 +9,8 @@
#ifndef __PSION_PACK_H__
#define __PSION_PACK_H__
+#include "softlist_dev.h"
+
/***************************************************************************
TYPE DEFINITIONS