From 9445f1d8311db820dc0984e85c9c1450ce1807cd Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 2 Sep 2020 17:29:21 +1000 Subject: frontend: Added option to skip repeated imperfect emulation warnings. The option is called skip_warnings, and it must be set in ui.ini (it can be set using the internal UI). Red warnings cannot be skipped; yellow warning can be skipped under certain circumstances. For a yellow warning to be skipped, the system must have been launched in a way that allows warnings to be displayed, in a configuration with the same set of devices flagged with unemulated/imperfect features, within the last seven days, and the warning must have been displayed within the past 14 days. Also fixed a bug with display of the MACHINE_NO_COCKTAIL flag in the internal UI, and increased the size of XML integer attributes to 64 bits. --- src/devices/bus/a2bus/uthernet.cpp | 2 +- src/frontend/mame/infoxml.cpp | 475 +++++++++++++++++++------------------ src/frontend/mame/infoxml.h | 2 + src/frontend/mame/ui/filemngr.h | 7 +- src/frontend/mame/ui/info.cpp | 26 +- src/frontend/mame/ui/info.h | 4 +- src/frontend/mame/ui/moptions.cpp | 5 +- src/frontend/mame/ui/moptions.h | 2 + src/frontend/mame/ui/selgame.cpp | 3 +- src/frontend/mame/ui/submenu.cpp | 3 +- src/frontend/mame/ui/ui.cpp | 202 ++++++++++++++-- src/frontend/mame/ui/ui.h | 20 +- src/lib/util/xmlfile.cpp | 17 +- src/lib/util/xmlfile.h | 4 +- 14 files changed, 503 insertions(+), 269 deletions(-) (limited to 'src') diff --git a/src/devices/bus/a2bus/uthernet.cpp b/src/devices/bus/a2bus/uthernet.cpp index 734edadcf1a..d9bfd7e9414 100644 --- a/src/devices/bus/a2bus/uthernet.cpp +++ b/src/devices/bus/a2bus/uthernet.cpp @@ -19,7 +19,7 @@ // GLOBAL VARIABLES //************************************************************************** -DEFINE_DEVICE_TYPE(A2BUS_UTHERNET, a2bus_uthernet_device, "a2uthernet", "Uthernet") +DEFINE_DEVICE_TYPE(A2BUS_UTHERNET, a2bus_uthernet_device, "a2uthernet", "a2RetroSystems Uthernet") //************************************************************************** // LIVE DEVICE diff --git a/src/frontend/mame/infoxml.cpp b/src/frontend/mame/infoxml.cpp index 926feffbc08..59b3a637aee 100644 --- a/src/frontend/mame/infoxml.cpp +++ b/src/frontend/mame/infoxml.cpp @@ -25,234 +25,282 @@ #include "xmlfile.h" +#include #include #include -#include -#include #include +#include +#include +#include +#include #define XML_ROOT "mame" #define XML_TOP "machine" +namespace { + //************************************************************************** // ANONYMOUS NAMESPACE PROTOTYPES //************************************************************************** -namespace +class device_type_compare { - class device_type_compare - { - public: - bool operator()(const std::add_pointer_t &lhs, const std::add_pointer_t &rhs) const; - }; - - typedef std::set, device_type_compare> device_type_set; - - std::string normalize_string(const char *string); - - // internal helper - void output_header(std::ostream &out, bool dtd); - void output_footer(std::ostream &out); - - void output_one(std::ostream &out, driver_enumerator &drivlist, const game_driver &driver, device_type_set *devtypes); - void output_sampleof(std::ostream &out, device_t &device); - void output_bios(std::ostream &out, device_t const &device); - void output_rom(std::ostream &out, driver_enumerator *drivlist, const game_driver *driver, device_t &device); - void output_device_refs(std::ostream &out, device_t &root); - void output_sample(std::ostream &out, device_t &device); - void output_chips(std::ostream &out, device_t &device, const char *root_tag); - void output_display(std::ostream &out, device_t &device, machine_flags::type const *flags, const char *root_tag); - void output_sound(std::ostream &out, device_t &device); - void output_ioport_condition(std::ostream &out, const ioport_condition &condition, unsigned indent); - void output_input(std::ostream &out, const ioport_list &portlist); - void output_switches(std::ostream &out, const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *loctag, const char *innertag); - void output_ports(std::ostream &out, const ioport_list &portlist); - void output_adjusters(std::ostream &out, const ioport_list &portlist); - void output_driver(std::ostream &out, game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect); - void output_features(std::ostream &out, device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect); - void output_images(std::ostream &out, device_t &device, const char *root_tag); - void output_slots(std::ostream &out, machine_config &config, device_t &device, const char *root_tag, device_type_set *devtypes); - void output_software_lists(std::ostream &out, device_t &root, const char *root_tag); - void output_ramoptions(std::ostream &out, device_t &root); - - void output_one_device(std::ostream &out, machine_config &config, device_t &device, const char *devtag); - void output_devices(std::ostream &out, emu_options &lookup_options, device_type_set const *filter); - - const char *get_merge_name(driver_enumerator &drivlist, const game_driver &driver, util::hash_collection const &romhashes); +public: + bool operator()(const std::add_pointer_t &lhs, const std::add_pointer_t &rhs) const; }; +typedef std::set, device_type_compare> device_type_set; + +std::string normalize_string(const char *string); + +// internal helper +void output_header(std::ostream &out, bool dtd); +void output_footer(std::ostream &out); + +void output_one(std::ostream &out, driver_enumerator &drivlist, const game_driver &driver, device_type_set *devtypes); +void output_sampleof(std::ostream &out, device_t &device); +void output_bios(std::ostream &out, device_t const &device); +void output_rom(std::ostream &out, driver_enumerator *drivlist, const game_driver *driver, device_t &device); +void output_device_refs(std::ostream &out, device_t &root); +void output_sample(std::ostream &out, device_t &device); +void output_chips(std::ostream &out, device_t &device, const char *root_tag); +void output_display(std::ostream &out, device_t &device, machine_flags::type const *flags, const char *root_tag); +void output_sound(std::ostream &out, device_t &device); +void output_ioport_condition(std::ostream &out, const ioport_condition &condition, unsigned indent); +void output_input(std::ostream &out, const ioport_list &portlist); +void output_switches(std::ostream &out, const ioport_list &portlist, const char *root_tag, int type, const char *outertag, const char *loctag, const char *innertag); +void output_ports(std::ostream &out, const ioport_list &portlist); +void output_adjusters(std::ostream &out, const ioport_list &portlist); +void output_driver(std::ostream &out, game_driver const &driver, device_t::feature_type unemulated, device_t::feature_type imperfect); +void output_features(std::ostream &out, device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect); +void output_images(std::ostream &out, device_t &device, const char *root_tag); +void output_slots(std::ostream &out, machine_config &config, device_t &device, const char *root_tag, device_type_set *devtypes); +void output_software_lists(std::ostream &out, device_t &root, const char *root_tag); +void output_ramoptions(std::ostream &out, device_t &root); + +void output_one_device(std::ostream &out, machine_config &config, device_t &device, const char *devtag); +void output_devices(std::ostream &out, emu_options &lookup_options, device_type_set const *filter); + +const char *get_merge_name(driver_enumerator &drivlist, const game_driver &driver, util::hash_collection const &romhashes); + //************************************************************************** // GLOBAL VARIABLES //************************************************************************** // DTD string describing the data -static const char s_dtd_string[] = -"\n" -"\t\n" -"\t\n" -"\t\n" -"\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"\t\t\n" -"\t\t\t\n" -"\t\t\t\n" -"]>"; +constexpr char f_dtd_string[] = + "\n" + "\t\n" + "\t\n" + "\t\n" + "\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "\t\t\n" + "\t\t\t\n" + "\t\t\t\n" + "]>"; + + +// XML feature names +constexpr std::pair f_feature_names[] = { + { device_t::feature::PROTECTION, "protection" }, + { device_t::feature::TIMING, "timing" }, + { device_t::feature::GRAPHICS, "graphics" }, + { device_t::feature::PALETTE, "palette" }, + { device_t::feature::SOUND, "sound" }, + { device_t::feature::CAPTURE, "capture" }, + { device_t::feature::CAMERA, "camera" }, + { device_t::feature::MICROPHONE, "microphone" }, + { device_t::feature::CONTROLS, "controls" }, + { device_t::feature::KEYBOARD, "keyboard" }, + { device_t::feature::MOUSE, "mouse" }, + { device_t::feature::MEDIA, "media" }, + { device_t::feature::DISK, "disk" }, + { device_t::feature::PRINTER, "printer" }, + { device_t::feature::TAPE, "tape" }, + { device_t::feature::PUNCH, "punch" }, + { device_t::feature::DRUM, "drum" }, + { device_t::feature::ROM, "rom" }, + { device_t::feature::COMMS, "comms" }, + { device_t::feature::LAN, "lan" }, + { device_t::feature::WAN, "wan" } }; + +} // anonymous namespace //************************************************************************** // INFO XML CREATOR //************************************************************************** + +//------------------------------------------------- +// get_feature_name - get XML name for feature +//------------------------------------------------- + +char const *info_xml_creator::feature_name(device_t::feature_type feature) +{ + auto const found = std::lower_bound( + std::begin(f_feature_names), + std::end(f_feature_names), + std::underlying_type_t(feature), + [] (auto const &a, auto const &b) + { + return std::underlying_type_t(a.first) < b; + }); + return ((std::end(f_feature_names) != found) && (found->first == feature)) ? found->second : nullptr; +} + + //------------------------------------------------- // info_xml_creator - constructor //------------------------------------------------- @@ -478,7 +526,7 @@ void output_header(std::ostream &out, bool dtd) { // output the DTD out << "\n"; - std::string dtd(s_dtd_string); + std::string dtd(f_dtd_string); strreplace(dtd, "__XML_ROOT__", XML_ROOT); strreplace(dtd, "__XML_TOP__", XML_TOP); @@ -1771,31 +1819,8 @@ void output_driver(std::ostream &out, game_driver const &driver, device_t::featu void output_features(std::ostream &out, device_type type, device_t::feature_type unemulated, device_t::feature_type imperfect) { - static constexpr std::pair features[] = { - { device_t::feature::PROTECTION, "protection" }, - { device_t::feature::TIMING, "timing" }, - { device_t::feature::GRAPHICS, "graphics" }, - { device_t::feature::PALETTE, "palette" }, - { device_t::feature::SOUND, "sound" }, - { device_t::feature::CAPTURE, "capture" }, - { device_t::feature::CAMERA, "camera" }, - { device_t::feature::MICROPHONE, "microphone" }, - { device_t::feature::CONTROLS, "controls" }, - { device_t::feature::KEYBOARD, "keyboard" }, - { device_t::feature::MOUSE, "mouse" }, - { device_t::feature::MEDIA, "media" }, - { device_t::feature::DISK, "disk" }, - { device_t::feature::PRINTER, "printer" }, - { device_t::feature::TAPE, "tape" }, - { device_t::feature::PUNCH, "punch" }, - { device_t::feature::DRUM, "drum" }, - { device_t::feature::ROM, "rom" }, - { device_t::feature::COMMS, "comms" }, - { device_t::feature::LAN, "lan" }, - { device_t::feature::WAN, "wan" } }; - device_t::feature_type const flags(type.unemulated_features() | type.imperfect_features() | unemulated | imperfect); - for (auto const &feature : features) + for (auto const &feature : f_feature_names) { if (flags & feature.first) { diff --git a/src/frontend/mame/infoxml.h b/src/frontend/mame/infoxml.h index 690610d1e70..00a614bcd3a 100644 --- a/src/frontend/mame/infoxml.h +++ b/src/frontend/mame/infoxml.h @@ -34,6 +34,8 @@ public: void output(std::ostream &out, const std::vector &patterns); void output(std::ostream &out, const std::function &filter = { }, bool include_devices = true); + static char const *feature_name(device_t::feature_type feature); + private: // internal state emu_options m_lookup_options; diff --git a/src/frontend/mame/ui/filemngr.h b/src/frontend/mame/ui/filemngr.h index 68da54f1d05..d656bb9e692 100644 --- a/src/frontend/mame/ui/filemngr.h +++ b/src/frontend/mame/ui/filemngr.h @@ -7,13 +7,16 @@ MESS's clunky built-in file manager ***************************************************************************/ +#ifndef MAME_FRONTEND_UI_FILEMNGR_H +#define MAME_FRONTEND_UI_FILEMNGR_H #pragma once -#ifndef MAME_FRONTEND_UI_FILEMNGR_H -#define MAME_FRONTEND_UI_FILEMNGR_H +#include "ui/menu.h" + namespace ui { + class menu_file_manager : public menu { public: diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index ec0c6e72700..5b6450412c6 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -138,6 +138,28 @@ machine_static_info::machine_static_info(const ui_options &options, machine_conf } +//------------------------------------------------- +// has_warnings - returns true if the system has +// issues that warrant a yellow/red message +//------------------------------------------------- + +bool machine_static_info::has_warnings() const +{ + return (machine_flags() & (MACHINE_ERRORS | MACHINE_WARNINGS)) || unemulated_features() || imperfect_features(); +} + + +//------------------------------------------------- +// has_severe_warnings - returns true if the +// system has issues that warrant a red message +//------------------------------------------------- + +bool machine_static_info::has_severe_warnings() const +{ + return (machine_flags() & MACHINE_ERRORS) || ((unemulated_features() | imperfect_features()) & device_t::feature::PROTECTION); +} + + //------------------------------------------------- // status_color - returns suitable colour for // driver status box @@ -145,7 +167,7 @@ machine_static_info::machine_static_info(const ui_options &options, machine_conf rgb_t machine_static_info::status_color() const { - if ((machine_flags() & MACHINE_ERRORS) || ((unemulated_features() | imperfect_features()) & device_t::feature::PROTECTION)) + if (has_severe_warnings()) return UI_RED_COLOR; else if ((machine_flags() & MACHINE_WARNINGS & ~::machine_flags::REQUIRES_ARTWORK) || unemulated_features() || imperfect_features()) return UI_YELLOW_COLOR; @@ -161,7 +183,7 @@ rgb_t machine_static_info::status_color() const rgb_t machine_static_info::warnings_color() const { - if ((machine_flags() & MACHINE_ERRORS) || ((unemulated_features() | imperfect_features()) & device_t::feature::PROTECTION)) + if (has_severe_warnings()) return UI_RED_COLOR; else if ((machine_flags() & MACHINE_WARNINGS) || unemulated_features() || imperfect_features()) return UI_YELLOW_COLOR; diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h index 0e6fd7815cd..7acb64c2a38 100644 --- a/src/frontend/mame/ui/info.h +++ b/src/frontend/mame/ui/info.h @@ -38,7 +38,9 @@ public: bool has_test_switch() const { return m_has_test_switch; } bool has_analog() const { return m_has_analog; } - // message colour + // warning severity indications + bool has_warnings() const; + bool has_severe_warnings() const; rgb_t status_color() const; rgb_t warnings_color() const; diff --git a/src/frontend/mame/ui/moptions.cpp b/src/frontend/mame/ui/moptions.cpp index b4da221e18e..911baa66fdf 100644 --- a/src/frontend/mame/ui/moptions.cpp +++ b/src/frontend/mame/ui/moptions.cpp @@ -44,8 +44,9 @@ const options_entry ui_options::s_option_entries[] = // misc options { nullptr, nullptr, OPTION_HEADER, "UI MISC OPTIONS" }, - { OPTION_REMEMBER_LAST, "1", OPTION_BOOLEAN, "reselect in main menu last played game" }, - { OPTION_ENLARGE_SNAPS, "1", OPTION_BOOLEAN, "enlarge arts (snapshot, title, etc...) in right panel (keeping aspect ratio)" }, + { OPTION_SKIP_WARNINGS, "0", OPTION_BOOLEAN, "display fewer repeated warnings about imperfect emulation" }, + { OPTION_REMEMBER_LAST, "1", OPTION_BOOLEAN, "initially select last used system in main menu" }, + { OPTION_ENLARGE_SNAPS, "1", OPTION_BOOLEAN, "enlarge artwork (snapshot, title, etc.) in right panel (keeping aspect ratio)" }, { OPTION_FORCED4X3, "1", OPTION_BOOLEAN, "force the appearance of the snapshot in the list software to 4:3" }, { OPTION_USE_BACKGROUND, "1", OPTION_BOOLEAN, "enable background image in main view" }, { OPTION_SKIP_BIOS_MENU, "0", OPTION_BOOLEAN, "skip bios submenu, start with configured or default" }, diff --git a/src/frontend/mame/ui/moptions.h b/src/frontend/mame/ui/moptions.h index ddfa3971c3b..67ce3eb63f9 100644 --- a/src/frontend/mame/ui/moptions.h +++ b/src/frontend/mame/ui/moptions.h @@ -38,6 +38,7 @@ #define OPTION_UI_PATH "ui_path" // core misc options +#define OPTION_SKIP_WARNINGS "skip_warnings" #define OPTION_REMEMBER_LAST "remember_last" #define OPTION_ENLARGE_SNAPS "enlarge_snaps" #define OPTION_FORCED4X3 "forced4x3" @@ -102,6 +103,7 @@ public: const char *ui_path() const { return value(OPTION_UI_PATH); } // Misc options + bool skip_warnings() const { return bool_value(OPTION_SKIP_WARNINGS); } bool remember_last() const { return bool_value(OPTION_REMEMBER_LAST); } bool enlarge_snaps() const { return bool_value(OPTION_ENLARGE_SNAPS); } bool forced_4x3_snapshot() const { return bool_value(OPTION_FORCED4X3); } diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 1f7603b4f31..6944031e344 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -1159,7 +1159,8 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff str << ((flags.machine_flags() & machine_flags::MECHANICAL) ? _("Mechanical Machine\tYes\n") : _("Mechanical Machine\tNo\n")); str << ((flags.machine_flags() & machine_flags::REQUIRES_ARTWORK) ? _("Requires Artwork\tYes\n") : _("Requires Artwork\tNo\n")); str << ((flags.machine_flags() & machine_flags::CLICKABLE_ARTWORK) ? _("Requires Clickable Artwork\tYes\n") : _("Requires Clickable Artwork\tNo\n")); - str << ((flags.machine_flags() & machine_flags::NO_COCKTAIL) ? _("Support Cocktail\tYes\n") : _("Support Cocktail\tNo\n")); + if (flags.machine_flags() & machine_flags::NO_COCKTAIL) + str << _("Support Cocktail\tNo\n"); str << ((flags.machine_flags() & machine_flags::IS_BIOS_ROOT) ? _("Driver is BIOS\tYes\n") : _("Driver is BIOS\tNo\n")); str << ((flags.machine_flags() & machine_flags::SUPPORTS_SAVE) ? _("Support Save\tYes\n") : _("Support Save\tNo\n")); str << ((flags.machine_flags() & ORIENTATION_SWAP_XY) ? _("Screen Orientation\tVertical\n") : _("Screen Orientation\tHorizontal\n")); diff --git a/src/frontend/mame/ui/submenu.cpp b/src/frontend/mame/ui/submenu.cpp index 207ac56d057..cb1d3e38089 100644 --- a/src/frontend/mame/ui/submenu.cpp +++ b/src/frontend/mame/ui/submenu.cpp @@ -20,7 +20,8 @@ namespace ui { std::vector const submenu::misc_options = { { submenu::option_type::HEAD, __("Miscellaneous Options") }, - { submenu::option_type::UI, __("Re-select last machine played"), OPTION_REMEMBER_LAST }, + { submenu::option_type::UI, __("Skip imperfect emulation warnings"), OPTION_SKIP_WARNINGS }, + { submenu::option_type::UI, __("Re-select last machine launched"), OPTION_REMEMBER_LAST }, { submenu::option_type::UI, __("Enlarge images in the right panel"), OPTION_ENLARGE_SNAPS }, { submenu::option_type::EMU, __("Cheats"), OPTION_CHEAT }, { submenu::option_type::EMU, __("Show mouse pointer"), OPTION_UI_MOUSE }, diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 08fd5a75ce8..40a5651430d 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -9,29 +9,39 @@ *********************************************************************/ #include "emu.h" +#include "ui/ui.h" + +#include "luaengine.h" +#include "infoxml.h" #include "mame.h" +#include "ui/filemngr.h" +#include "ui/info.h" +#include "ui/mainmenu.h" +#include "ui/menu.h" +#include "ui/sliders.h" +#include "ui/state.h" +#include "ui/viewgfx.h" + +#include "imagedev/cassette.h" +#include "machine/laserdsc.h" +#include "video/vector.h" + +#include "config.h" #include "emuopts.h" #include "mameopts.h" -#include "video/vector.h" -#include "machine/laserdsc.h" #include "drivenum.h" #include "natkeyboard.h" #include "render.h" -#include "luaengine.h" #include "cheat.h" #include "rendfont.h" +#include "romload.h" #include "uiinput.h" -#include "ui/ui.h" -#include "ui/info.h" -#include "ui/menu.h" -#include "ui/mainmenu.h" -#include "ui/filemngr.h" -#include "ui/sliders.h" -#include "ui/state.h" -#include "ui/viewgfx.h" -#include "imagedev/cassette.h" + #include "../osd/modules/lib/osdobj_common.h" +#include +#include + /*************************************************************************** CONSTANTS @@ -168,6 +178,11 @@ mame_ui_manager::mame_ui_manager(running_machine &machine) , m_mouse_show(false) , m_target_font_height(0) , m_has_warnings(false) + , m_machine_info() + , m_unemulated_features() + , m_imperfect_features() + , m_last_launch_time(std::time_t(-1)) + , m_last_warning_time(std::time_t(-1)) { } mame_ui_manager::~mame_ui_manager() @@ -177,6 +192,7 @@ mame_ui_manager::~mame_ui_manager() void mame_ui_manager::init() { load_ui_options(); + // initialize the other UI bits ui::menu::init(machine(), options()); ui_gfx_init(machine()); @@ -192,8 +208,12 @@ void mame_ui_manager::init() m_non_char_keys_down = std::make_unique((ARRAY_LENGTH(non_char_keys) + 7) / 8); m_mouse_show = machine().system().flags & machine_flags::CLICKABLE_ARTWORK ? true : false; - // request a callback upon exiting + // request notification callbacks machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&mame_ui_manager::exit, this)); + machine().configuration().config_register( + "ui_warnings", + config_load_delegate(&mame_ui_manager::config_load, this), + config_save_delegate(&mame_ui_manager::config_save, this)); // create mouse bitmap uint32_t *dst = &m_mouse_bitmap.pix32(0); @@ -232,6 +252,78 @@ void mame_ui_manager::exit() } +//------------------------------------------------- +// config_load - load configuration data +//------------------------------------------------- + +void mame_ui_manager::config_load(config_type cfg_type, util::xml::data_node const *parentnode) +{ + // make sure it's relevant and there's data available + if (config_type::GAME == cfg_type) + { + m_unemulated_features.clear(); + m_imperfect_features.clear(); + if (!parentnode) + { + m_last_launch_time = std::time_t(-1); + m_last_warning_time = std::time_t(-1); + } + else + { + m_last_launch_time = std::time_t(parentnode->get_attribute_int("launched", -1)); + m_last_warning_time = std::time_t(parentnode->get_attribute_int("warned", -1)); + for (util::xml::data_node const *node = parentnode->get_first_child(); node; node = node->get_next_sibling()) + { + if (!std::strcmp(node->get_name(), "feature")) + { + char const *const device = node->get_attribute_string("device", nullptr); + char const *const feature = node->get_attribute_string("type", nullptr); + char const *const status = node->get_attribute_string("status", nullptr); + if (device && *device && feature && *feature && status && *status) + { + if (!std::strcmp(status, "unemulated")) + m_unemulated_features.emplace(device, feature); + else if (!std::strcmp(status, "imperfect")) + m_imperfect_features.emplace(device, feature); + } + } + } + } + } +} + + +//------------------------------------------------- +// config_save - save configuration data +//------------------------------------------------- + +void mame_ui_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode) +{ + // only save system-level configuration when times are valid + if ((config_type::GAME == cfg_type) && (std::time_t(-1) != m_last_launch_time) && (std::time_t(-1) != m_last_warning_time)) + { + parentnode->set_attribute_int("launched", static_cast(m_last_launch_time)); + parentnode->set_attribute_int("warned", static_cast(m_last_warning_time)); + + for (auto const &feature : m_unemulated_features) + { + util::xml::data_node *const feature_node = parentnode->add_child("feature", nullptr); + feature_node->set_attribute("device", feature.first.c_str()); + feature_node->set_attribute("type", feature.second.c_str()); + feature_node->set_attribute("status", "unemulated"); + } + + for (auto const &feature : m_imperfect_features) + { + util::xml::data_node *const feature_node = parentnode->add_child("feature", nullptr); + feature_node->set_attribute("device", feature.first.c_str()); + feature_node->set_attribute("type", feature.second.c_str()); + feature_node->set_attribute("status", "imperfect"); + } + } +} + + //------------------------------------------------- // initialize - initialize ui lists //------------------------------------------------- @@ -335,7 +427,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) messagebox_text = machine_info().game_info_string(); if (!messagebox_text.empty()) { - messagebox_text.append("\n\nPress any key to continue"); + messagebox_text.append(_("\n\nPress any key to continue")); set_handler(ui_callback_type::MODAL, std::bind(&mame_ui_manager::handler_messagebox_anykey, this, _1)); } break; @@ -343,11 +435,75 @@ void mame_ui_manager::display_startup_screens(bool first_time) case 1: messagebox_text = machine_info().warnings_string(); m_has_warnings = !messagebox_text.empty(); - if (m_has_warnings && show_warnings) + if (show_warnings) { - messagebox_text.append("\n\nPress any key to continue"); - set_handler(ui_callback_type::MODAL, std::bind(&mame_ui_manager::handler_messagebox_anykey, this, _1)); - messagebox_backcolor = machine_info().warnings_color(); + bool need_warning = m_has_warnings; + if (machine_info().has_severe_warnings() || !m_has_warnings) + { + // critical warnings - no need to persist stuff + m_unemulated_features.clear(); + m_imperfect_features.clear(); + m_last_launch_time = std::time_t(-1); + m_last_warning_time = std::time_t(-1); + } + else + { + // non-critical warnings - map current unemulated/imperfect features + device_feature_set unemulated_features, imperfect_features; + for (device_t &device : device_iterator(machine().root_device())) + { + device_t::feature_type unemulated = device.type().unemulated_features(); + for (std::underlying_type_t feature = 1U; unemulated; feature <<= 1) + { + if (unemulated & feature) + { + char const *const name = info_xml_creator::feature_name(device_t::feature_type(feature)); + if (name) + unemulated_features.emplace(device.type().shortname(), name); + unemulated &= device_t::feature_type(~feature); + } + } + device_t::feature_type imperfect = device.type().imperfect_features(); + for (std::underlying_type_t feature = 1U; imperfect; feature <<= 1) + { + if (imperfect & feature) + { + char const *const name = info_xml_creator::feature_name(device_t::feature_type(feature)); + if (name) + imperfect_features.emplace(device.type().shortname(), name); + imperfect &= device_t::feature_type(~feature); + } + } + } + + // machine flags can cause warnings, too + if (machine_info().machine_flags() & machine_flags::NO_COCKTAIL) + unemulated_features.emplace(machine().root_device().type().shortname(), "cocktail"); + + // if the warnings match what was shown sufficiently recently, it's skippable + if ((unemulated_features != m_unemulated_features) || (imperfect_features != m_imperfect_features)) + { + m_last_launch_time = std::time_t(-1); + } + else if (!machine().rom_load().warnings() && (std::time_t(-1) != m_last_launch_time) && (std::time_t(-1) != m_last_warning_time) && options().skip_warnings()) + { + auto const now = std::chrono::system_clock::now(); + if (((std::chrono::system_clock::from_time_t(m_last_launch_time) + std::chrono::hours(7 * 24)) >= now) && ((std::chrono::system_clock::from_time_t(m_last_warning_time) + std::chrono::hours(14 * 24)) >= now)) + need_warning = false; + } + + // update the information to save out + m_unemulated_features = std::move(unemulated_features); + m_imperfect_features = std::move(imperfect_features); + if (need_warning) + m_last_warning_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + } + if (need_warning) + { + messagebox_text.append(_("\n\nPress any key to continue")); + set_handler(ui_callback_type::MODAL, std::bind(&mame_ui_manager::handler_messagebox_anykey, this, _1)); + messagebox_backcolor = machine_info().warnings_color(); + } } break; @@ -359,8 +515,8 @@ void mame_ui_manager::display_startup_screens(bool first_time) warning << _("This driver requires images to be loaded in the following device(s): "); output_joined_collection(mandatory_images, - [&warning](const std::reference_wrapper &img) { warning << "\"" << img.get() << "\""; }, - [&warning]() { warning << ","; }); + [&warning](const std::reference_wrapper &img) { warning << "\"" << img.get() << "\""; }, + [&warning]() { warning << ","; }); ui::menu_file_manager::force_file_manager(*this, machine().render().ui_container(), warning.str().c_str()); } @@ -382,6 +538,10 @@ void mame_ui_manager::display_startup_screens(bool first_time) machine().video().frame_update(); } + // update last launch time if this was a run that was eligible for emulation warnings + if (m_has_warnings && show_warnings && !machine().scheduled_event_pending()) + m_last_launch_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + // if we're the empty driver, force the menus on if (ui::menu::stack_has_special_main_menu(machine())) show_menu(); @@ -2107,7 +2267,7 @@ void mame_ui_manager::load_ui_options() { try { - options().parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, true); + options().parse_ini_file((util::core_file &)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, true); } catch (options_exception &) { diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index d62b8b15d1a..8c0504464d3 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -21,14 +21,21 @@ #include "ui/slider.h" #include "ui/text.h" +#include #include +#include +#include #include + namespace ui { + class menu_item; class machine_info; + } // namespace ui + /*************************************************************************** CONSTANTS ***************************************************************************/ @@ -260,9 +267,12 @@ public: virtual void menu_reset() override; private: + using handler_callback_func = std::function; + using device_feature_set = std::set >; + // instance variables render_font * m_font; - std::function m_handler_callback; + handler_callback_func m_handler_callback; ui_callback_type m_handler_callback_type; uint32_t m_handler_param; bool m_single_step; @@ -270,7 +280,7 @@ private: osd_ticks_t m_showfps_end; bool m_show_profiler; osd_ticks_t m_popup_text_end; - std::unique_ptr m_non_char_keys_down; + std::unique_ptr m_non_char_keys_down; bitmap_argb32 m_mouse_bitmap; render_texture * m_mouse_arrow_texture; bool m_mouse_show; @@ -280,6 +290,10 @@ private: bool m_has_warnings; std::unique_ptr m_machine_info; + device_feature_set m_unemulated_features; + device_feature_set m_imperfect_features; + std::time_t m_last_launch_time; + std::time_t m_last_warning_time; // static variables static std::string messagebox_text; @@ -298,6 +312,8 @@ private: // private methods void exit(); + void config_load(config_type cfg_type, util::xml::data_node const *parentnode); + void config_save(config_type cfg_type, util::xml::data_node *parentnode); std::unique_ptr slider_alloc(int id, const char *title, int32_t minval, int32_t defval, int32_t maxval, int32_t incval, void *arg); // slider controls diff --git a/src/lib/util/xmlfile.cpp b/src/lib/util/xmlfile.cpp index 445c3fbb4f7..2ef0acfcf0c 100644 --- a/src/lib/util/xmlfile.cpp +++ b/src/lib/util/xmlfile.cpp @@ -8,13 +8,12 @@ ***************************************************************************/ -#include - #include "xmlfile.h" #include #include +#include #include #include #include @@ -582,7 +581,7 @@ const char *data_node::get_attribute_string(const char *attribute, const char *d found, return = the provided default -------------------------------------------------*/ -int data_node::get_attribute_int(const char *attribute, int defvalue) const +long long data_node::get_attribute_int(const char *attribute, long long defvalue) const { char const *const string = get_attribute_string(attribute, nullptr); if (!string) @@ -590,20 +589,20 @@ int data_node::get_attribute_int(const char *attribute, int defvalue) const std::istringstream stream; stream.imbue(f_portable_locale); - int result; + long long result; if (string[0] == '$') { stream.str(&string[1]); - unsigned uvalue; + unsigned long long uvalue; stream >> std::hex >> uvalue; - result = int(uvalue); + result = static_cast(uvalue); } else if ((string[0] == '0') && ((string[1] == 'x') || (string[1] == 'X'))) { stream.str(&string[2]); - unsigned uvalue; + unsigned long long uvalue; stream >> std::hex >> uvalue; - result = int(uvalue); + result = static_cast(uvalue); } else if (string[0] == '#') { @@ -690,7 +689,7 @@ void data_node::set_attribute(const char *name, const char *value) integer value on the node -------------------------------------------------*/ -void data_node::set_attribute_int(const char *name, int value) +void data_node::set_attribute_int(const char *name, long long value) { set_attribute(name, string_format(f_portable_locale, "%d", value).c_str()); } diff --git a/src/lib/util/xmlfile.h b/src/lib/util/xmlfile.h index 8d09b2b7e1e..0780172b0c2 100644 --- a/src/lib/util/xmlfile.h +++ b/src/lib/util/xmlfile.h @@ -138,7 +138,7 @@ public: const char *get_attribute_string(const char *attribute, const char *defvalue) const; // return the integer value of an attribute, or the specified default if not present - int get_attribute_int(const char *attribute, int defvalue) const; + long long get_attribute_int(const char *attribute, long long defvalue) const; // return the format of the given integer attribute int_format get_attribute_int_format(const char *attribute) const; @@ -150,7 +150,7 @@ public: void set_attribute(const char *name, const char *value); // set the integer value of an attribute - void set_attribute_int(const char *name, int value); + void set_attribute_int(const char *name, long long value); // set the float value of an attribute void set_attribute_float(const char *name, float value); -- cgit v1.2.3