mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
Merge pull request #854 from ajrhacker/incompatibility
Check software parts for incompatibility as well as compatibility
This commit is contained in:
commit
ea1863db53
@ -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"/>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 ℑ
|
||||
}
|
||||
}
|
||||
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());
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
std::string val = string_format("%s:%s:%s", swlistdev.list_name(), m_options.software_name(), swpart.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());
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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?
|
||||
|
Loading…
Reference in New Issue
Block a user