diff options
author | Vas Crabb <vas@vastheman.com> | 2020-09-02 17:29:21 +1000 |
---|---|---|
committer | Vas Crabb <vas@vastheman.com> | 2020-09-02 17:41:34 +1000 |
commit | 9445f1d8311db820dc0984e85c9c1450ce1807cd (patch) | |
tree | 43ecc4e298615b8b8388dbe9df4440b53f461b32 /src/frontend/mame/ui/ui.cpp | |
parent | 654b118ff985a4011bc0caf5ce8160fa80c4b9bf (diff) |
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.
Diffstat (limited to 'src/frontend/mame/ui/ui.cpp')
-rw-r--r-- | src/frontend/mame/ui/ui.cpp | 202 |
1 files changed, 181 insertions, 21 deletions
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 <chrono> +#include <type_traits> + /*************************************************************************** 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<uint8_t[]>((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); @@ -233,6 +253,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<long long>(m_last_launch_time)); + parentnode->set_attribute_int("warned", static_cast<long long>(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<device_t::feature_type> 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<device_t::feature_type> 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<const std::string> &img) { warning << "\"" << img.get() << "\""; }, - [&warning]() { warning << ","; }); + [&warning](const std::reference_wrapper<const std::string> &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 &) { |