summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui/info.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2017-07-27 09:56:53 +1000
committer Vas Crabb <vas@vastheman.com>2017-07-27 09:56:53 +1000
commit22d80b35290491e041122708b0482826ba3a89c9 (patch)
treef9b39d9aa70ab6573c2f5559b6ef06be27512e51 /src/frontend/mame/ui/info.cpp
parent6cf16fde31232e3081a7ec2d2db9bcece9f8b95d (diff)
Move unemulated/imperfect flags from machines into devices.
Right now, flags for unemulated/imperfect features apply at system level. This falls over quickly with systems that have slot devices. For example you can plug in a broken sound card or keyboard on a PC or Amiga driver and get no warnings. There's also no way to propagate these flags from a device to all systems using it. This changeset addresses these issues. It's now possible to report unemulated/imperfect features on a device level with static unemulated_feeatures() and imperfect_features() member functions. So far the only thing using this is the votrax device. To support front-ends, this is exposed in -listxml output as a new "feature" element that can appear in system/device descriptions. It has a "type" attribute indicating which feature it is, potentially a "status" attribute if the device itself declares that the feature is unemulated/imperfect, and potentially an "overall" attribute if the device inherits a more severe indication from a subdevice. The embedded DTD describes possible values. Example: device/machine declares imperfect sound: <feature type="sound" status="imperfect"/> Example: device/machine declares unemulated keyboard: <feature type="keyboard" status="unemulated"/> Example: device declares imperfect controls but inherits unemulated controls from a subdevice: <feature type="controls" status="imperfect" overall="unemulated"/> Example: device doesn't declare imperfect LAN but inherits it from a subdevice: <feature type="lan" overall="imperfect"/> It's still possible to add these flags to machines in the GAME/COMP/CONS macro. If the state class declares them with static member functions, the two sources will be combined. If you subclass a device, you inherit its flags if you don't redefine the relevant static member functions (no override qualifier is necessary since they're static). The UI has been updated to display appropriate warnings for the overall machine configuration, including selected slot devices, at launch time. The menus don't display overall status, only status for the machine itself. We can make it scan subdevices if we decide that's desirable, it just needs caching to enure we don't take a huge performance hit.
Diffstat (limited to 'src/frontend/mame/ui/info.cpp')
-rw-r--r--src/frontend/mame/ui/info.cpp275
1 files changed, 155 insertions, 120 deletions
diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp
index e4abb6ce94d..1c792f1eaa3 100644
--- a/src/frontend/mame/ui/info.cpp
+++ b/src/frontend/mame/ui/info.cpp
@@ -18,40 +18,78 @@
#include "emuopts.h"
namespace ui {
+
+namespace {
+
+constexpr machine_flags::type MACHINE_ERRORS = machine_flags::NOT_WORKING | machine_flags::MECHANICAL;
+constexpr machine_flags::type MACHINE_WARNINGS = machine_flags::NO_COCKTAIL | machine_flags::REQUIRES_ARTWORK;
+constexpr machine_flags::type MACHINE_BTANB = machine_flags::NO_SOUND_HW | machine_flags::IS_INCOMPLETE;
+
+constexpr std::pair<device_t::feature_type, char const *> FEATURE_NAMES[] = {
+ { device_t::feature::PROTECTION, __("protection") },
+ { device_t::feature::PALETTE, __("color palette") },
+ { device_t::feature::GRAPHICS, __("graphics") },
+ { device_t::feature::SOUND, __("sound") },
+ { device_t::feature::CONTROLS, __("controls") },
+ { device_t::feature::KEYBOARD, __("keyboard") },
+ { device_t::feature::MOUSE, __("mouse") },
+ { device_t::feature::MICROPHONE, __("microphone") },
+ { device_t::feature::CAMERA, __("camera") },
+ { device_t::feature::DISK, __("disk") },
+ { device_t::feature::PRINTER, __("printer") },
+ { device_t::feature::LAN, __("LAN") },
+ { device_t::feature::WAN, __("WAN") } };
+
+} // anonymous namespace
+
+
//-------------------------------------------------
// machine_info - constructor
//-------------------------------------------------
machine_info::machine_info(running_machine &machine)
: m_machine(machine)
+ , m_flags(m_machine.system().flags)
+ , m_unemulated_features(m_machine.system().type.unemulated_features())
+ , m_imperfect_features(m_machine.system().type.imperfect_features())
+ , m_has_configs(false)
+ , m_has_analog(false)
+ , m_has_dips(false)
+ , m_has_bioses(false)
+ , m_has_keyboard(false)
+ , m_has_test_switch(false)
{
- // calculate "has..." values
- m_has_configs = false;
- m_has_analog = false;
- m_has_dips = false;
- m_has_bioses = false;
- m_has_keyboard = false;
- m_has_test_switch = false;
-
// scan the input port array to see what options we need to enable
for (auto &port : machine.ioport().ports())
+ {
for (ioport_field &field : port.second->fields())
{
- if (field.type() == IPT_DIPSWITCH)
- m_has_dips = true;
- if (field.type() == IPT_CONFIG)
- m_has_configs = true;
+ switch (field.type())
+ {
+ case IPT_DIPSWITCH: m_has_dips = true; break;
+ case IPT_CONFIG: m_has_configs = true; break;
+ case IPT_KEYBOARD: m_has_keyboard = true; break;
+ case IPT_SERVICE: m_has_test_switch = true; break;
+ default: break;
+ }
if (field.is_analog())
m_has_analog = true;
- if (field.type() == IPT_KEYBOARD)
- m_has_keyboard = true;
- if (field.type() == IPT_SERVICE)
- m_has_test_switch = true;
}
+ }
+ // build overall emulation status and look for BIOS options
for (device_t &device : device_iterator(machine.root_device()))
+ {
+ if (dynamic_cast<device_sound_interface *>(&device))
+ m_flags &= ~machine_flags::NO_SOUND_HW;
+
+ m_unemulated_features |= device.type().unemulated_features();
+ m_imperfect_features |= device.type().imperfect_features();
+
for (const rom_entry &rom : device.rom_region_vector())
if (ROMENTRY_ISSYSTEM_BIOS(&rom)) { m_has_bioses = true; break; }
+ }
+ m_imperfect_features &= ~m_unemulated_features;
}
@@ -64,132 +102,112 @@ machine_info::machine_info(running_machine &machine)
// text to the given buffer
//-------------------------------------------------
-std::string machine_info::warnings_string()
+std::string machine_info::warnings_string() const
{
- constexpr uint32_t warning_flags = ( MACHINE_FATAL_FLAGS | MACHINE_WARNING_FLAGS | MACHINE_BTANB_FLAGS );
-
- // if no warnings, nothing to return
- if (m_machine.rom_load().warnings() == 0 && m_machine.rom_load().knownbad() == 0 && !(m_machine.system().flags & warning_flags) && m_machine.rom_load().software_load_warnings_message().length() == 0)
- return std::string();
-
std::ostringstream buf;
// add a warning if any ROMs were loaded with warnings
if (m_machine.rom_load().warnings() > 0)
- {
buf << _("One or more ROMs/CHDs for this machine are incorrect. The machine may not run correctly.\n");
- if (m_machine.system().flags & warning_flags)
- buf << "\n";
- }
- if (m_machine.rom_load().software_load_warnings_message().length()>0) {
+ if (!m_machine.rom_load().software_load_warnings_message().empty())
buf << m_machine.rom_load().software_load_warnings_message();
- if (m_machine.system().flags & warning_flags)
- buf << "\n";
- }
+
// if we have at least one warning flag, print the general header
- if ((m_machine.system().flags & warning_flags) || m_machine.rom_load().knownbad() > 0)
+ if ((m_machine.rom_load().knownbad() > 0) || (m_flags & (MACHINE_WARNINGS | MACHINE_BTANB)) || m_unemulated_features || m_imperfect_features)
{
+ if (!buf.str().empty())
+ buf << '\n';
buf << _("There are known problems with this machine\n\n");
+ }
- // add a warning if any ROMs are flagged BAD_DUMP/NO_DUMP
- if (m_machine.rom_load().knownbad() > 0) {
- buf << _("One or more ROMs/CHDs for this machine have not been correctly dumped.\n");
- }
- // add one line per warning flag
- if (m_machine.system().flags & MACHINE_IMPERFECT_KEYBOARD)
- buf << _("The keyboard emulation may not be 100% accurate.\n");
- if (m_machine.system().flags & MACHINE_IMPERFECT_COLORS)
- buf << _("The colors aren't 100% accurate.\n");
- if (m_machine.system().flags & MACHINE_WRONG_COLORS)
- buf << _("The colors are completely wrong.\n");
- if (m_machine.system().flags & MACHINE_IMPERFECT_GRAPHICS)
- buf << _("The video emulation isn't 100% accurate.\n");
- if (m_machine.system().flags & MACHINE_IMPERFECT_SOUND)
- buf << _("The sound emulation isn't 100% accurate.\n");
- if (m_machine.system().flags & MACHINE_NO_SOUND) {
- buf << _("The machine lacks sound.\n");
- }
- if (m_machine.system().flags & MACHINE_NO_COCKTAIL)
- buf << _("Screen flipping in cocktail mode is not supported.\n");
+ // add a warning if any ROMs are flagged BAD_DUMP/NO_DUMP
+ if (m_machine.rom_load().knownbad() > 0)
+ buf << _("One or more ROMs/CHDs for this machine have not been correctly dumped.\n");
- // check if external artwork is present before displaying this warning?
- if (m_machine.system().flags & MACHINE_REQUIRES_ARTWORK) {
- buf << _("The machine requires external artwork files.\n");
- }
-
- if (m_machine.system().flags & MACHINE_IS_INCOMPLETE )
+ // add line for unemulated features
+ if (m_unemulated_features)
+ {
+ buf << _("Completely unemulated features: ");
+ bool first = false;
+ for (auto const &feature : FEATURE_NAMES)
{
- buf << _("This machine was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n");
+ if (m_unemulated_features & feature.first)
+ {
+ util::stream_format(buf, first ? _("%s") : _(", %s"), _(feature.second));
+ first = false;
+ }
}
+ buf << '\n';
+ }
- if (m_machine.system().flags & MACHINE_NODEVICE_MICROPHONE )
- buf << _("This machine has unemulated microphone device.\n");
-
- if (m_machine.system().flags & MACHINE_NODEVICE_CAMERA )
- buf << _("This machine has unemulated camera device.\n");
-
- if (m_machine.system().flags & MACHINE_NODEVICE_PRINTER )
- buf << _("This machine has unemulated printer device.\n");
-
- if (m_machine.system().flags & MACHINE_NODEVICE_LAN )
- buf << _("This machine has unemulated linking capabilities.\n");
-
- if (m_machine.system().flags & MACHINE_NODEVICE_WAN )
- buf << _("This machine has unemulated networking capabilities.\n");
-
- if (m_machine.system().flags & MACHINE_NO_SOUND_HW )
+ // add line for imperfect features
+ if (m_imperfect_features)
+ {
+ buf << _("Imperfectly emulated features: ");
+ bool first = false;
+ for (auto const &feature : FEATURE_NAMES)
{
- buf << _("This machine has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n");
+ if (m_imperfect_features & feature.first)
+ {
+ util::stream_format(buf, first ? _("%s") : _(", %s"), _(feature.second));
+ first = false;
+ }
}
+ buf << '\n';
+ }
-
- // if there's a NOT WORKING, UNEMULATED PROTECTION or GAME MECHANICAL warning, make it stronger
- if (m_machine.system().flags & (MACHINE_FATAL_FLAGS))
+ // add one line per machine warning flag
+ if (m_flags & machine_flags::NO_COCKTAIL)
+ buf << _("Screen flipping in cocktail mode is not supported.\n");
+ if (m_flags & machine_flags::REQUIRES_ARTWORK) // check if external artwork is present before displaying this warning?
+ buf << _("This machine requires external artwork files.\n");
+ if (m_flags & machine_flags::IS_INCOMPLETE )
+ buf << _("This machine was never completed. It may exhibit strange behavior or missing elements that are not bugs in the emulation.\n");
+ if (m_flags & machine_flags::NO_SOUND_HW )
+ buf << _("This machine has no sound hardware, MAME will produce no sounds, this is expected behaviour.\n");
+
+ // these are more severe warnings
+ if (m_flags & machine_flags::NOT_WORKING)
+ buf << _("\nTHIS MACHINE DOESN'T WORK. The emulation for this machine is not yet complete. There is nothing you can do to fix this problem except wait for the developers to improve the emulation.\n");
+ if (m_flags & machine_flags::MECHANICAL)
+ buf << _("\nElements of this machine cannot be emulated as they requires physical interaction or consist of mechanical devices. It is not possible to fully experience this machine.\n");
+
+ if ((m_flags & MACHINE_ERRORS) || ((m_machine.system().type.unemulated_features() | m_machine.system().type.imperfect_features()) & device_t::feature::PROTECTION))
+ {
+ // find the parent of this driver
+ driver_enumerator drivlist(m_machine.options());
+ int maindrv = drivlist.find(m_machine.system());
+ int clone_of = drivlist.non_bios_clone(maindrv);
+ if (clone_of != -1)
+ maindrv = clone_of;
+
+ // scan the driver list for any working clones and add them
+ bool foundworking = false;
+ while (drivlist.next())
{
- // add the strings for these warnings
- if (m_machine.system().flags & MACHINE_UNEMULATED_PROTECTION) {
- buf << _("The machine has protection which isn't fully emulated.\n");
- }
- if (m_machine.system().flags & MACHINE_NOT_WORKING) {
- buf << _("\nTHIS MACHINE DOESN'T WORK. The emulation for this machine is not yet complete. "
- "There is nothing you can do to fix this problem except wait for the developers to improve the emulation.\n");
- }
- if (m_machine.system().flags & MACHINE_MECHANICAL) {
- buf << _("\nCertain elements of this machine cannot be emulated as it requires actual physical interaction or consists of mechanical devices. "
- "It is not possible to fully play this machine.\n");
+ if (drivlist.current() == maindrv || drivlist.clone() == maindrv)
+ {
+ game_driver const &driver(drivlist.driver());
+ if (!(driver.flags & MACHINE_ERRORS) && !((driver.type.unemulated_features() | driver.type.imperfect_features()) & device_t::feature::PROTECTION))
+ {
+ // this one works, add a header and display the name of the clone
+ if (!foundworking)
+ util::stream_format(buf, _("\n\nThere are working clones of this machine: %s"), driver.name);
+ else
+ util::stream_format(buf, _(", %s"), driver.name);
+ foundworking = true;
+ }
}
-
- // find the parent of this driver
- driver_enumerator drivlist(m_machine.options());
- int maindrv = drivlist.find(m_machine.system());
- int clone_of = drivlist.non_bios_clone(maindrv);
- if (clone_of != -1)
- maindrv = clone_of;
-
- // scan the driver list for any working clones and add them
- bool foundworking = false;
- while (drivlist.next())
- if (drivlist.current() == maindrv || drivlist.clone() == maindrv)
- if ((drivlist.driver().flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_MECHANICAL)) == 0)
- {
- // this one works, add a header and display the name of the clone
- if (!foundworking) {
- buf << _("\n\nThere are working clones of this machine: ");
- }
- else
- buf << ", ";
- buf << drivlist.driver().name;
- foundworking = true;
- }
-
- if (foundworking)
- buf << "\n";
}
+ if (foundworking)
+ buf << '\n';
}
// add the 'press OK' string
- buf << _("\n\nPress any key to continue");
+ if (!buf.str().empty())
+ buf << _("\n\nPress any key to continue");
+
return buf.str();
}
@@ -198,7 +216,7 @@ std::string machine_info::warnings_string()
// game_info_string - return the game info text
//-------------------------------------------------
-std::string machine_info::game_info_string()
+std::string machine_info::game_info_string() const
{
std::ostringstream buf;
@@ -316,7 +334,7 @@ std::string machine_info::game_info_string()
// need an image to be loaded
//-------------------------------------------------
-std::string machine_info::mandatory_images()
+std::string machine_info::mandatory_images() const
{
std::ostringstream buf;
bool is_first = true;
@@ -345,7 +363,7 @@ std::string machine_info::mandatory_images()
// a given screen
//-------------------------------------------------
-std::string machine_info::get_screen_desc(screen_device &screen)
+std::string machine_info::get_screen_desc(screen_device &screen) const
{
if (screen_device_iterator(m_machine.root_device()).count() > 1)
return string_format(_("Screen '%1$s'"), screen.tag());
@@ -354,6 +372,23 @@ std::string machine_info::get_screen_desc(screen_device &screen)
}
+//-------------------------------------------------
+// warnings_color - returns suitable colour for
+// warning message based on severity
+//-------------------------------------------------
+
+rgb_t machine_info::warnings_color() const
+{
+ if ((m_flags & MACHINE_ERRORS) || ((m_unemulated_features | m_imperfect_features) & device_t::feature::PROTECTION))
+ return UI_RED_COLOR;
+ else if ((m_flags & MACHINE_WARNINGS) || m_unemulated_features || m_imperfect_features)
+ return UI_YELLOW_COLOR;
+ else
+ return UI_BACKGROUND_COLOR;
+}
+
+
+
/*-------------------------------------------------
menu_game_info - handle the game information
menu