summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2016-05-03 23:52:32 -0400
committer AJR <ajrhacker@users.noreply.github.com>2016-05-03 23:52:32 -0400
commit32fbe353867ce66e53964de14624cd9c1e8a779d (patch)
tree8976d99379bd090e7ea43be79ced68c8c6f727b8
parentca9052ccfea75618c7caab7538ebe41c34a1f52c (diff)
Check software parts for incompatibility as well as compatibility
This new softlist feature is now used by genesis_tmss to exclude several entries from megadriv.xml. - Use popmessage instead of osd_printf_warning for incompatibility warnings - Unify some common software loading code, which reduces indentation levels in clifront.cpp
-rw-r--r--hash/megadriv.xml5
-rw-r--r--src/emu/diimage.cpp40
-rw-r--r--src/emu/softlist.cpp72
-rw-r--r--src/emu/softlist.h9
-rw-r--r--src/frontend/mame/clifront.cpp44
-rw-r--r--src/frontend/mame/ui/selsoft.cpp2
-rw-r--r--src/frontend/mame/ui/swlist.cpp2
-rw-r--r--src/mame/drivers/megadriv.cpp5
8 files changed, 116 insertions, 63 deletions
diff --git a/hash/megadriv.xml b/hash/megadriv.xml
index 21c0849b2f7..9f25e53fd43 100644
--- a/hash/megadriv.xml
+++ b/hash/megadriv.xml
@@ -3800,6 +3800,7 @@ Info on Sega chip labels (from Sunbeam / Digital Corruption)
<description>Ishido - The Way of Stones (USA)</description>
<year>1990</year>
<publisher>Accolade</publisher>
+ <sharedfeat name="incompatibility" value="TMSS"/>
<part name="cart" interface="megadriv_cart">
<feature name="pcb" value="ACBWPC1190"/>
<feature name="ic1" value="MB834200A 2M5 BA 9044 T03 ISS0890"/>
@@ -11942,6 +11943,7 @@ but dumps still have to be confirmed.
<description>Budokan - The Martial Spirit (USA)</description>
<year>1990</year>
<publisher>Electronic Arts</publisher>
+ <sharedfeat name="incompatibility" value="TMSS"/>
<part name="cart" interface="megadriv_cart">
<dataarea name="rom" width="16" endianness="big" size="524288">
<rom name="budokan - the martial spirit (usa).bin" size="524288" crc="acd9f5fc" sha1="93bc8242106bc9b2e0a8a974a3f65b559dd2941d" offset="0x000000"/>
@@ -20522,6 +20524,7 @@ Notice that these are not working on real hardware due to bugged code with VDP i
<description>Onslaught (Euro, USA)</description>
<year>1991</year>
<publisher>Ballistic</publisher>
+ <sharedfeat name="incompatibility" value="TMSS"/>
<part name="cart" interface="megadriv_cart">
<dataarea name="rom" width="16" endianness="big" size="524288">
<rom name="onslaught (euro, usa).bin" size="524288" crc="9f19d6df" sha1="dc542ddfa878f2aed3a7fcedc4b0f8d503eb5d70" offset="0x000000"/>
@@ -21578,6 +21581,7 @@ Notice that these are not working on real hardware due to bugged code with VDP i
<description>Populous (USA)</description>
<year>1991</year>
<publisher>Sega</publisher>
+ <sharedfeat name="incompatibility" value="TMSS"/>
<part name="cart" interface="megadriv_cart">
<dataarea name="rom" width="16" endianness="big" size="524288">
<rom name="populous (usa).bin" size="524288" crc="bd74b31e" sha1="89907c4ba4fd9db4e8ef2271c0253bb0e4b6d52d" offset="0x000000"/>
@@ -29417,6 +29421,7 @@ Notice that these are not working on real hardware due to bugged code with VDP i
<description>Zany Golf (Euro, USA)</description>
<year>1990</year>
<publisher>Electronic Arts</publisher>
+ <sharedfeat name="incompatibility" value="TMSS"/>
<part name="cart" interface="megadriv_cart">
<dataarea name="rom" width="16" endianness="big" size="524288">
<rom name="zany golf (euro, usa).bin" size="524288" crc="ed5d12ea" sha1="4f9bea2d8f489bfbc963718a8dca212e033fb5a2" offset="0x000000"/>
diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp
index 198be9d1ac0..3506704d9b5 100644
--- a/src/emu/diimage.cpp
+++ b/src/emu/diimage.cpp
@@ -1288,14 +1288,26 @@ bool device_image_interface::load_software_part(const char *path, software_part
}
// Load the software part
- bool result = call_softlist_load(swpart->info().list(), swpart->info().shortname(), swpart->romdata());
+ software_list_device &swlist = swpart->info().list();
+ bool result = call_softlist_load(swlist, swpart->info().shortname(), swpart->romdata());
// Tell the world which part we actually loaded
- std::string full_sw_name = string_format("%s:%s:%s", swpart->info().list().list_name(), swpart->info().shortname(), swpart->name());
+ std::string full_sw_name = string_format("%s:%s:%s", swlist.list_name(), swpart->info().shortname(), swpart->name());
// check compatibility
- if (!swpart->is_compatible(swpart->info().list()))
- osd_printf_warning("WARNING! the set %s might not work on this system due to missing filter(s) '%s'\n", swpart->info().shortname(), swpart->info().list().filter());
+ switch (swpart->is_compatible(swlist))
+ {
+ 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());
+ 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());
+ break;
+ }
// check requirements and load those images
const char *requirement = swpart->feature("requirement");
@@ -1304,23 +1316,11 @@ bool device_image_interface::load_software_part(const char *path, software_part
software_part *req_swpart = find_software_item(requirement, false);
if (req_swpart != nullptr)
{
- for (device_image_interface &req_image : image_interface_iterator(device().machine().root_device()))
+ device_image_interface *req_image = req_swpart->find_mountable_image(device().mconfig());
+ if (req_image != nullptr)
{
- const char *interface = req_image.image_interface();
- if (interface != nullptr)
- {
- if (req_swpart->matches_interface(interface))
- {
- const char *option = device().mconfig().options().value(req_image.brief_instance_name());
- // mount only if not already mounted
- if (*option == '\0' && !req_image.filename())
- {
- req_image.set_init_phase();
- req_image.load(requirement);
- }
- break;
- }
- }
+ req_image->set_init_phase();
+ req_image->load(requirement);
}
}
}
diff --git a/src/emu/softlist.cpp b/src/emu/softlist.cpp
index 3b57a60c82c..6f4955e61b1 100644
--- a/src/emu/softlist.cpp
+++ b/src/emu/softlist.cpp
@@ -140,26 +140,48 @@ const char *software_part::feature(const char *feature_name) const
// with the given software_list_device
//-------------------------------------------------
-bool software_part::is_compatible(const software_list_device &swlistdev) const
+software_compatibility software_part::is_compatible(const software_list_device &swlistdev) const
{
- // get the compatibility feature and the softlist filter; if either is nullptr, assume compatible
- const char *compatibility = feature("compatibility");
+ // get the softlist filter; if null, assume compatible
const char *filter = swlistdev.filter();
- if (compatibility == nullptr || filter == nullptr)
- return true;
+ if (filter == nullptr)
+ return SOFTWARE_IS_COMPATIBLE;
- // copy the comma-delimited strings and ensure they end with a final comma
- std::string comp = std::string(compatibility).append(",");
+ // copy the comma-delimited string and ensure it ends with a final comma
std::string filt = std::string(filter).append(",");
- // iterate over filter items and see if they exist in the compatibility list; if so, return true
+ // 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 true;
+ return SOFTWARE_IS_COMPATIBLE;
}
- return false;
+ return SOFTWARE_NOT_COMPATIBLE;
}
@@ -183,6 +205,34 @@ 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
@@ -340,7 +390,7 @@ void software_list_device::find_approx_matches(const char *name, int matches, so
for (software_info &swinfo : get_info())
{
software_part *part = swinfo.first_part();
- if ((interface == nullptr || part->matches_interface(interface)) && part->is_compatible(*this))
+ 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());
diff --git a/src/emu/softlist.h b/src/emu/softlist.h
index 09fa6981cd2..536ec9d4754 100644
--- a/src/emu/softlist.h
+++ b/src/emu/softlist.h
@@ -29,6 +29,12 @@ enum softlist_type
SOFTWARE_LIST_COMPATIBLE_SYSTEM
};
+enum software_compatibility
+{
+ SOFTWARE_IS_COMPATIBLE,
+ SOFTWARE_IS_INCOMPATIBLE,
+ SOFTWARE_NOT_COMPATIBLE
+};
//**************************************************************************
@@ -115,9 +121,10 @@ public:
rom_entry *romdata(unsigned int index = 0) { return (index < m_romdata.size()) ? &m_romdata[index] : nullptr; }
// helpers
- bool is_compatible(const software_list_device &swlist) const;
+ software_compatibility is_compatible(const software_list_device &swlist) const;
bool matches_interface(const char *interface) const;
const char *feature(const char *feature_name) const;
+ device_image_interface *find_mountable_image(const machine_config &mconfig) const;
private:
// internal state
diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp
index bbe64537aa2..a03479cde61 100644
--- a/src/frontend/mame/clifront.cpp
+++ b/src/frontend/mame/clifront.cpp
@@ -201,6 +201,7 @@ int cli_frontend::execute(int argc, char **argv)
throw emu_fatalerror(EMU_ERR_FATALERROR, "Error: unknown option: %s\n", m_options.software_name());
bool found = false;
+ bool compatible = false;
for (software_list_device &swlistdev : iter)
{
software_info *swinfo = swlistdev.find(m_options.software_name());
@@ -209,46 +210,33 @@ int cli_frontend::execute(int argc, char **argv)
// loop through all parts
for (software_part &swpart : swinfo->parts())
{
- const char *mount = swpart.feature("automount");
- if (swpart.is_compatible(swlistdev))
+ // only load compatible software this way
+ if (swpart.is_compatible(swlistdev) == SOFTWARE_IS_COMPATIBLE)
{
- if (mount == nullptr || strcmp(mount,"no") != 0)
+ device_image_interface *image = swpart.find_mountable_image(config);
+ if (image != nullptr)
{
- // search for an image device with the right interface
- for (device_image_interface &image : image_interface_iterator(config.root_device()))
- {
- const char *interface = image.image_interface();
- if (interface != nullptr)
- {
- if (swpart.matches_interface(interface))
- {
- const char *option = m_options.value(image.brief_instance_name());
-
- // mount only if not already mounted
- if (*option == 0)
- {
- std::string val = string_format("%s:%s:%s", swlistdev.list_name(), m_options.software_name(), swpart.name());
+ std::string val = string_format("%s:%s:%s", swlistdev.list_name(), m_options.software_name(), swpart.name());
- // call this in order to set slot devices according to mounting
- mame_options::parse_slot_devices(m_options, argc, argv, option_errors, image.instance_name(), val.c_str(), &swpart);
- break;
- }
- }
- }
- }
+ // call this in order to set slot devices according to mounting
+ mame_options::parse_slot_devices(m_options, argc, argv, option_errors, image->instance_name(), val.c_str(), &swpart);
}
- found = true;
+ compatible = true;
}
}
+ found = true;
}
- if (found)
+ if (compatible)
break;
}
- if (!found)
+ if (!compatible)
{
software_list_device::display_matches(config, nullptr, m_options.software_name());
- throw emu_fatalerror(EMU_ERR_FATALERROR, nullptr);
+ if (!found)
+ throw emu_fatalerror(EMU_ERR_FATALERROR, nullptr);
+ else
+ throw emu_fatalerror(EMU_ERR_FATALERROR, "Software '%s' is incompatible with system '%s'\n", m_options.software_name(), m_options.system_name());
}
}
diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp
index 1c0c1460211..c5f33b8c701 100644
--- a/src/frontend/mame/ui/selsoft.cpp
+++ b/src/frontend/mame/ui/selsoft.cpp
@@ -538,7 +538,7 @@ void ui_menu_select_software::build_software_list()
for (software_info &swinfo : swlist.get_info())
{
software_part *part = swinfo.first_part();
- if (part->is_compatible(swlist))
+ if (part->is_compatible(swlist) == SOFTWARE_IS_COMPATIBLE)
{
const char *instance_name = nullptr;
const char *type_name = nullptr;
diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp
index b6dfc318a28..267f07f69d7 100644
--- a/src/frontend/mame/ui/swlist.cpp
+++ b/src/frontend/mame/ui/swlist.cpp
@@ -191,7 +191,7 @@ ui_menu_software_list::entry_info *ui_menu_software_list::append_software_entry(
// 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))
+ if (swpart.matches_interface(m_interface) && swpart.is_compatible(*m_swlist) == SOFTWARE_IS_COMPATIBLE)
{
entry_updated = TRUE;
// allocate a new entry
diff --git a/src/mame/drivers/megadriv.cpp b/src/mame/drivers/megadriv.cpp
index dbbcd3186a2..ce255d3bd69 100644
--- a/src/mame/drivers/megadriv.cpp
+++ b/src/mame/drivers/megadriv.cpp
@@ -406,6 +406,9 @@ static MACHINE_CONFIG_START( ms_megadpal, md_cons_state )
MCFG_SOFTWARE_LIST_ADD("cart_list","megadriv")
MACHINE_CONFIG_END
+static MACHINE_CONFIG_DERIVED( genesis_tmss, ms_megadriv )
+ MCFG_SOFTWARE_LIST_FILTER("cart_list","TMSS")
+MACHINE_CONFIG_END
@@ -1058,7 +1061,7 @@ CONS( 1990, megadriv, genesis, 0, ms_megadpal, md, md_cons_state,
CONS( 1988, megadrij, genesis, 0, ms_megadriv, md, md_cons_state, md_jpn, "Sega", "Mega Drive (Japan, NTSC)", MACHINE_SUPPORTS_SAVE )
// 1990+ models had the TMSS security chip, leave this as a clone, it reduces compatibility and nothing more.
-CONS( 1990, genesis_tmss, genesis, 0, ms_megadriv, md, md_cons_state, genesis, "Sega", "Genesis (USA, NTSC, with TMSS chip)", MACHINE_SUPPORTS_SAVE )
+CONS( 1990, genesis_tmss, genesis, 0, genesis_tmss, md, md_cons_state, genesis, "Sega", "Genesis (USA, NTSC, with TMSS chip)", MACHINE_SUPPORTS_SAVE )
// the 32X plugged in the cart slot, games plugged into the 32x. Maybe it should be handled as an expansion device?