mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +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>
|
<description>Ishido - The Way of Stones (USA)</description>
|
||||||
<year>1990</year>
|
<year>1990</year>
|
||||||
<publisher>Accolade</publisher>
|
<publisher>Accolade</publisher>
|
||||||
|
<sharedfeat name="incompatibility" value="TMSS"/>
|
||||||
<part name="cart" interface="megadriv_cart">
|
<part name="cart" interface="megadriv_cart">
|
||||||
<feature name="pcb" value="ACBWPC1190"/>
|
<feature name="pcb" value="ACBWPC1190"/>
|
||||||
<feature name="ic1" value="MB834200A 2M5 BA 9044 T03 ISS0890"/>
|
<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>
|
<description>Budokan - The Martial Spirit (USA)</description>
|
||||||
<year>1990</year>
|
<year>1990</year>
|
||||||
<publisher>Electronic Arts</publisher>
|
<publisher>Electronic Arts</publisher>
|
||||||
|
<sharedfeat name="incompatibility" value="TMSS"/>
|
||||||
<part name="cart" interface="megadriv_cart">
|
<part name="cart" interface="megadriv_cart">
|
||||||
<dataarea name="rom" width="16" endianness="big" size="524288">
|
<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"/>
|
<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>
|
<description>Onslaught (Euro, USA)</description>
|
||||||
<year>1991</year>
|
<year>1991</year>
|
||||||
<publisher>Ballistic</publisher>
|
<publisher>Ballistic</publisher>
|
||||||
|
<sharedfeat name="incompatibility" value="TMSS"/>
|
||||||
<part name="cart" interface="megadriv_cart">
|
<part name="cart" interface="megadriv_cart">
|
||||||
<dataarea name="rom" width="16" endianness="big" size="524288">
|
<dataarea name="rom" width="16" endianness="big" size="524288">
|
||||||
<rom name="onslaught (euro, usa).bin" size="524288" crc="9f19d6df" sha1="dc542ddfa878f2aed3a7fcedc4b0f8d503eb5d70" offset="0x000000"/>
|
<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>
|
<description>Populous (USA)</description>
|
||||||
<year>1991</year>
|
<year>1991</year>
|
||||||
<publisher>Sega</publisher>
|
<publisher>Sega</publisher>
|
||||||
|
<sharedfeat name="incompatibility" value="TMSS"/>
|
||||||
<part name="cart" interface="megadriv_cart">
|
<part name="cart" interface="megadriv_cart">
|
||||||
<dataarea name="rom" width="16" endianness="big" size="524288">
|
<dataarea name="rom" width="16" endianness="big" size="524288">
|
||||||
<rom name="populous (usa).bin" size="524288" crc="bd74b31e" sha1="89907c4ba4fd9db4e8ef2271c0253bb0e4b6d52d" offset="0x000000"/>
|
<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>
|
<description>Zany Golf (Euro, USA)</description>
|
||||||
<year>1990</year>
|
<year>1990</year>
|
||||||
<publisher>Electronic Arts</publisher>
|
<publisher>Electronic Arts</publisher>
|
||||||
|
<sharedfeat name="incompatibility" value="TMSS"/>
|
||||||
<part name="cart" interface="megadriv_cart">
|
<part name="cart" interface="megadriv_cart">
|
||||||
<dataarea name="rom" width="16" endianness="big" size="524288">
|
<dataarea name="rom" width="16" endianness="big" size="524288">
|
||||||
<rom name="zany golf (euro, usa).bin" size="524288" crc="ed5d12ea" sha1="4f9bea2d8f489bfbc963718a8dca212e033fb5a2" offset="0x000000"/>
|
<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
|
// 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
|
// 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
|
// check compatibility
|
||||||
if (!swpart->is_compatible(swpart->info().list()))
|
switch (swpart->is_compatible(swlist))
|
||||||
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());
|
{
|
||||||
|
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
|
// check requirements and load those images
|
||||||
const char *requirement = swpart->feature("requirement");
|
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);
|
software_part *req_swpart = find_software_item(requirement, false);
|
||||||
if (req_swpart != nullptr)
|
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();
|
req_image->set_init_phase();
|
||||||
if (interface != nullptr)
|
req_image->load(requirement);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,26 +140,48 @@ const char *software_part::feature(const char *feature_name) const
|
|||||||
// with the given software_list_device
|
// 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
|
// get the softlist filter; if null, assume compatible
|
||||||
const char *compatibility = feature("compatibility");
|
|
||||||
const char *filter = swlistdev.filter();
|
const char *filter = swlistdev.filter();
|
||||||
if (compatibility == nullptr || filter == nullptr)
|
if (filter == nullptr)
|
||||||
return true;
|
return SOFTWARE_IS_COMPATIBLE;
|
||||||
|
|
||||||
// copy the comma-delimited strings and ensure they end with a final comma
|
// copy the comma-delimited string and ensure it ends with a final comma
|
||||||
std::string comp = std::string(compatibility).append(",");
|
|
||||||
std::string filt = std::string(filter).append(",");
|
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))
|
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);
|
std::string token(filt, start, end - start + 1);
|
||||||
if (comp.find(token) != -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
|
// 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())
|
for (software_info &swinfo : get_info())
|
||||||
{
|
{
|
||||||
software_part *part = swinfo.first_part();
|
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
|
// pick the best match between driver name and description
|
||||||
int longpenalty = driver_list::penalty_compare(name, swinfo.longname());
|
int longpenalty = driver_list::penalty_compare(name, swinfo.longname());
|
||||||
|
@ -29,6 +29,12 @@ enum softlist_type
|
|||||||
SOFTWARE_LIST_COMPATIBLE_SYSTEM
|
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; }
|
rom_entry *romdata(unsigned int index = 0) { return (index < m_romdata.size()) ? &m_romdata[index] : nullptr; }
|
||||||
|
|
||||||
// helpers
|
// 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;
|
bool matches_interface(const char *interface) const;
|
||||||
const char *feature(const char *feature_name) const;
|
const char *feature(const char *feature_name) const;
|
||||||
|
device_image_interface *find_mountable_image(const machine_config &mconfig) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// internal state
|
// 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());
|
throw emu_fatalerror(EMU_ERR_FATALERROR, "Error: unknown option: %s\n", m_options.software_name());
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
bool compatible = false;
|
||||||
for (software_list_device &swlistdev : iter)
|
for (software_list_device &swlistdev : iter)
|
||||||
{
|
{
|
||||||
software_info *swinfo = swlistdev.find(m_options.software_name());
|
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
|
// loop through all parts
|
||||||
for (software_part &swpart : swinfo->parts())
|
for (software_part &swpart : swinfo->parts())
|
||||||
{
|
{
|
||||||
const char *mount = swpart.feature("automount");
|
// only load compatible software this way
|
||||||
if (swpart.is_compatible(swlistdev))
|
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
|
// 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);
|
mame_options::parse_slot_devices(m_options, argc, argv, option_errors, image->instance_name(), val.c_str(), &swpart);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
compatible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found)
|
if (compatible)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!compatible)
|
||||||
{
|
{
|
||||||
software_list_device::display_matches(config, nullptr, m_options.software_name());
|
software_list_device::display_matches(config, nullptr, m_options.software_name());
|
||||||
|
if (!found)
|
||||||
throw emu_fatalerror(EMU_ERR_FATALERROR, nullptr);
|
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())
|
for (software_info &swinfo : swlist.get_info())
|
||||||
{
|
{
|
||||||
software_part *part = swinfo.first_part();
|
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 *instance_name = nullptr;
|
||||||
const char *type_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
|
// 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())
|
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;
|
entry_updated = TRUE;
|
||||||
// allocate a new entry
|
// allocate a new entry
|
||||||
|
@ -406,6 +406,9 @@ static MACHINE_CONFIG_START( ms_megadpal, md_cons_state )
|
|||||||
MCFG_SOFTWARE_LIST_ADD("cart_list","megadriv")
|
MCFG_SOFTWARE_LIST_ADD("cart_list","megadriv")
|
||||||
MACHINE_CONFIG_END
|
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 )
|
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.
|
// 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?
|
// 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