diff options
Diffstat (limited to 'src/frontend/mame/ui/ui.cpp')
-rw-r--r-- | src/frontend/mame/ui/ui.cpp | 1198 |
1 files changed, 566 insertions, 632 deletions
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 90efcb04b7c..09a8d24bdd1 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -11,15 +11,18 @@ #include "emu.h" #include "ui/ui.h" -#include "luaengine.h" #include "infoxml.h" +#include "iptseqpoll.h" +#include "luaengine.h" #include "mame.h" #include "ui/filemngr.h" #include "ui/info.h" #include "ui/mainmenu.h" #include "ui/menu.h" +#include "ui/quitmenu.h" #include "ui/sliders.h" #include "ui/state.h" +#include "ui/systemlist.h" #include "ui/viewgfx.h" #include "imagedev/cassette.h" @@ -30,32 +33,26 @@ #include "emuopts.h" #include "mameopts.h" #include "drivenum.h" +#include "fileio.h" #include "natkeyboard.h" #include "render.h" #include "cheat.h" #include "rendfont.h" #include "romload.h" +#include "screen.h" +#include "speaker.h" #include "uiinput.h" +// FIXME: allow OSD module headers to be included in a less ugly way +#include "../osd/modules/lib/osdlib.h" #include "../osd/modules/lib/osdobj_common.h" #include <chrono> +#include <functional> #include <type_traits> /*************************************************************************** - CONSTANTS -***************************************************************************/ - -enum -{ - LOADSAVE_NONE, - LOADSAVE_LOAD, - LOADSAVE_SAVE -}; - - -/*************************************************************************** LOCAL VARIABLES ***************************************************************************/ @@ -110,11 +107,9 @@ static input_item_id const non_char_keys[] = // messagebox buffer std::string mame_ui_manager::messagebox_text; std::string mame_ui_manager::messagebox_poptext; -rgb_t mame_ui_manager::messagebox_backcolor; // slider info std::vector<ui::menu_item> mame_ui_manager::slider_list; -slider_state *mame_ui_manager::slider_current; /*************************************************************************** @@ -165,9 +160,9 @@ static uint32_t const mouse_bitmap[32*32] = mame_ui_manager::mame_ui_manager(running_machine &machine) : ui_manager(machine) , m_font() - , m_handler_callback(nullptr) + , m_handler_callback() , m_handler_callback_type(ui_callback_type::GENERAL) - , m_handler_param(0) + , m_ui_active(true) , m_single_step(false) , m_showfps(false) , m_showfps_end(0) @@ -176,8 +171,12 @@ mame_ui_manager::mame_ui_manager(running_machine &machine) , m_mouse_bitmap(32, 32) , m_mouse_arrow_texture(nullptr) , m_mouse_show(false) + , m_mouse_target(-1) + , m_mouse_position(0, 0) , m_target_font_height(0) , m_has_warnings(false) + , m_unthrottle_mute(false) + , m_image_display_enabled(true) , m_machine_info() , m_unemulated_features() , m_imperfect_features() @@ -193,27 +192,33 @@ void mame_ui_manager::init() { load_ui_options(); - // initialize the other UI bits - ui::menu::init(machine(), options()); - ui_gfx_init(machine()); + // start loading system names as early as possible + ui::system_list::instance().cache_data(options()); + // initialize the other UI bits m_ui_colors.refresh(options()); // update font row info from setting update_target_font_height(); // more initialization - using namespace std::placeholders; - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_messagebox, this, _1)); - m_non_char_keys_down = std::make_unique<uint8_t[]>((ARRAY_LENGTH(non_char_keys) + 7) / 8); + set_handler( + ui_callback_type::GENERAL, + handler_callback_func( + [this] (render_container &container) -> uint32_t + { + draw_text_box(container, messagebox_text, ui::text_layout::text_justify::LEFT, 0.5f, 0.5f, colors().background_color()); + return 0; + })); + m_non_char_keys_down = std::make_unique<uint8_t[]>((std::size(non_char_keys) + 7) / 8); m_mouse_show = machine().system().flags & machine_flags::CLICKABLE_ARTWORK ? true : false; // 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)); + configuration_manager::load_delegate(&mame_ui_manager::config_load, this), + configuration_manager::save_delegate(&mame_ui_manager::config_save, this)); // create mouse bitmap uint32_t *dst = &m_mouse_bitmap.pix(0); @@ -245,6 +250,9 @@ void mame_ui_manager::exit() // free the font m_font.reset(); + + // free persistent data for other classes + m_session_data.clear(); } @@ -252,10 +260,10 @@ 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) +void mame_ui_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode) { // make sure it's relevant and there's data available - if (config_type::GAME == cfg_type) + if (config_type::SYSTEM == cfg_type) { m_unemulated_features.clear(); m_imperfect_features.clear(); @@ -296,7 +304,7 @@ void mame_ui_manager::config_load(config_type cfg_type, util::xml::data_node con 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)) + if ((config_type::SYSTEM == 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)); @@ -327,17 +335,10 @@ void mame_ui_manager::config_save(config_type cfg_type, util::xml::data_node *pa void mame_ui_manager::initialize(running_machine &machine) { m_machine_info = std::make_unique<ui::machine_info>(machine); + set_ui_active(!machine_info().has_keyboard() || machine.options().ui_active()); // initialize the on-screen display system slider_list = slider_init(machine); - if (slider_list.size() > 0) - { - slider_current = reinterpret_cast<slider_state *>(slider_list[0].ref); - } - else - { - slider_current = nullptr; - } // if no test switch found, assign its input sequence to a service mode DIP if (!m_machine_info->has_test_switch() && m_machine_info->has_dips()) @@ -345,9 +346,16 @@ void mame_ui_manager::initialize(running_machine &machine) const char *const service_mode_dipname = ioport_configurer::string_from_token(DEF_STR(Service_Mode)); for (auto &port : machine.ioport().ports()) for (ioport_field &field : port.second->fields()) - if (field.type() == IPT_DIPSWITCH && strcmp(field.name(), service_mode_dipname) == 0) + if ((field.type() == IPT_DIPSWITCH) && (field.name() == service_mode_dipname)) // FIXME: probably breaks with localisation, also issues with multiple devices field.set_defseq(machine.ioport().type_seq(IPT_SERVICE)); } + + // handle throttle-related options and initial muting state now that the sound manager has been brought up + const bool starting_throttle = machine.options().throttle(); + machine.video().set_throttled(starting_throttle); + m_unthrottle_mute = options().unthrottle_mute(); + if (!starting_throttle && m_unthrottle_mute) + machine.sound().ui_mute(true); } @@ -356,7 +364,7 @@ void mame_ui_manager::initialize(running_machine &machine) // pair for the current UI handler //------------------------------------------------- -void mame_ui_manager::set_handler(ui_callback_type callback_type, const std::function<uint32_t (render_container &)> &&callback) +void mame_ui_manager::set_handler(ui_callback_type callback_type, handler_callback_func &&callback) { m_handler_callback = std::move(callback); m_handler_callback_type = callback_type; @@ -406,31 +414,61 @@ void mame_ui_manager::display_startup_screens(bool first_time) show_gameinfo = show_warnings = false; #endif + // set up event handlers + switch_code_poller poller(machine().input()); + std::string warning_text; + rgb_t warning_color; + bool config_menu = false; + auto handler_messagebox_anykey = + [this, &poller, &warning_text, &warning_color, &config_menu] (render_container &container) -> uint32_t + { + // draw a standard message window + draw_text_box(container, warning_text, ui::text_layout::text_justify::LEFT, 0.5f, 0.5f, warning_color); + + if (machine().ui_input().pressed(IPT_UI_CANCEL)) + { + // if the user cancels, exit out completely + machine().schedule_exit(); + return HANDLER_CANCEL; + } + else if (machine().ui_input().pressed(IPT_UI_MENU)) + { + config_menu = true; + return HANDLER_CANCEL; + } + else if (poller.poll() != INPUT_CODE_INVALID) + { + // if any key is pressed, just exit + return HANDLER_CANCEL; + } + + return 0; + }; + set_handler(ui_callback_type::GENERAL, handler_callback_func(&mame_ui_manager::handler_ingame, this)); + // loop over states - using namespace std::placeholders; - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_ingame, this, _1)); - for (int state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(machine()); state++) + for (int state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(*this); state++) { // default to standard colors - messagebox_backcolor = colors().background_color(); - messagebox_text.clear(); + warning_color = colors().background_color(); + warning_text.clear(); // pick the next state switch (state) { case 0: if (show_gameinfo) - messagebox_text = machine_info().game_info_string(); - if (!messagebox_text.empty()) + warning_text = machine_info().game_info_string(); + if (!warning_text.empty()) { - 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)); + warning_text.append(_("\n\nPress any key to continue")); + set_handler(ui_callback_type::MODAL, handler_callback_func(handler_messagebox_anykey)); } break; case 1: - messagebox_text = machine_info().warnings_string(); - m_has_warnings = !messagebox_text.empty(); + warning_text = machine_info().warnings_string(); + m_has_warnings = !warning_text.empty(); if (show_warnings) { bool need_warning = m_has_warnings; @@ -446,7 +484,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) { // non-critical warnings - map current unemulated/imperfect features device_feature_set unemulated_features, imperfect_features; - for (device_t &device : device_iterator(machine().root_device())) + for (device_t &device : device_enumerator(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) @@ -496,9 +534,9 @@ void mame_ui_manager::display_startup_screens(bool first_time) } 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(); + warning_text.append(_("\n\nPress any key to continue")); + set_handler(ui_callback_type::MODAL, handler_callback_func(handler_messagebox_anykey)); + warning_color = machine_info().warnings_color(); } } break; @@ -508,7 +546,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) if (!mandatory_images.empty() && show_mandatory_fileman) { std::ostringstream warning; - warning << _("This driver requires images to be loaded in the following device(s): "); + warning << _("This system requires media images to be mounted for the following device(s): "); output_joined_collection(mandatory_images, [&warning](const std::reference_wrapper<const std::string> &img) { warning << "\"" << img.get() << "\""; }, @@ -519,18 +557,21 @@ void mame_ui_manager::display_startup_screens(bool first_time) break; } - // clear the input memory - machine().input().reset_polling(); - while (machine().input().poll_switches() != INPUT_CODE_INVALID) { } + // clear the input memory and wait for all keys to be released + poller.reset(); + while (poller.poll() != INPUT_CODE_INVALID) { } - // loop while we have a handler - while (m_handler_callback_type == ui_callback_type::MODAL && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(machine())) + if (m_handler_callback_type == ui_callback_type::MODAL) { - machine().video().frame_update(); + config_menu = false; + + // loop while we have a handler + while (m_handler_callback_type == ui_callback_type::MODAL && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(*this)) + machine().video().frame_update(); } // clear the handler and force an update - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_ingame, this, _1)); + set_handler(ui_callback_type::GENERAL, handler_callback_func(&mame_ui_manager::handler_ingame, this)); machine().video().frame_update(); } @@ -539,8 +580,18 @@ void mame_ui_manager::display_startup_screens(bool first_time) 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())) + if (ui::menu::stack_has_special_main_menu(*this)) + { + show_menu(); + } + else if (config_menu) + { show_menu(); + + // loop while we have a handler + while (m_handler_callback_type != ui_callback_type::GENERAL && !machine().scheduled_event_pending()) + machine().video().frame_update(); + } } @@ -556,7 +607,6 @@ void mame_ui_manager::set_startup_text(const char *text, bool force) // copy in the new text messagebox_text.assign(text); - messagebox_backcolor = colors().background_color(); // don't update more than 4 times/second if (force || (curtime - lastupdatetime) > osd_ticks_per_second() / 4) @@ -572,7 +622,7 @@ void mame_ui_manager::set_startup_text(const char *text, bool force) // render it; called by video.c //------------------------------------------------- -void mame_ui_manager::update_and_render(render_container &container) +bool mame_ui_manager::update_and_render(render_container &container) { // always start clean container.empty(); @@ -581,7 +631,7 @@ void mame_ui_manager::update_and_render(render_container &container) if (machine().phase() >= machine_phase::RESET && (single_step() || machine().paused())) { int alpha = (1.0f - machine().options().pause_brightness()) * 255.0f; - if (ui::menu::stack_has_special_main_menu(machine())) + if (ui::menu::stack_has_special_main_menu(*this)) alpha = 255; if (alpha > 255) alpha = 255; @@ -589,43 +639,70 @@ void mame_ui_manager::update_and_render(render_container &container) container.add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(alpha,0x00,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); } + // show red if overdriving sound + if (machine().options().speaker_report() != 0 && machine().phase() == machine_phase::RUNNING) + { + auto compressor = machine().sound().compressor_scale(); + if (compressor < 1.0) + { + float width = 0.05f + std::min(0.15f, (1.0f - compressor) * 0.4f); + container.add_rect(0.0f, 0.0f, 1.0f, width, rgb_t(0xc0,0xff,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container.add_rect(0.0f, 1.0f - width, 1.0f, 1.0f, rgb_t(0xc0,0xff,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container.add_rect(0.0f, width, width, 1.0f - width, rgb_t(0xc0,0xff,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + container.add_rect(1.0f - width, width, 1.0f, 1.0f - width, rgb_t(0xc0,0xff,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + } + } + // render any cheat stuff at the bottom if (machine().phase() >= machine_phase::RESET) mame_machine_manager::instance()->cheat().render_text(*this, container); // call the current UI handler - m_handler_param = m_handler_callback(container); + uint32_t const handler_result = m_handler_callback(container); // display any popup messages if (osd_ticks() < m_popup_text_end) - draw_text_box(container, messagebox_poptext.c_str(), ui::text_layout::CENTER, 0.5f, 0.9f, messagebox_backcolor); + draw_text_box(container, messagebox_poptext, ui::text_layout::text_justify::CENTER, 0.5f, 0.9f, colors().background_color()); else m_popup_text_end = 0; // display the internal mouse cursor + bool mouse_moved = false; if (m_mouse_show || (is_menu_active() && machine().options().ui_mouse())) { int32_t mouse_target_x, mouse_target_y; bool mouse_button; - render_target *mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); + render_target *const mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); - if (mouse_target != nullptr) + float mouse_y = -1, mouse_x = -1; + if (mouse_target && mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)) { - float mouse_y=-1,mouse_x=-1; - if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)) + const float cursor_size = 0.6 * get_line_height(); + container.add_quad(mouse_x, mouse_y, mouse_x + cursor_size * container.manager().ui_aspect(&container), mouse_y + cursor_size, colors().text_color(), m_mouse_arrow_texture, PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + if ((m_mouse_target != mouse_target->index()) || (std::make_pair(mouse_x, mouse_y) != m_mouse_position)) { - const float cursor_size = 0.6 * get_line_height(); - container.add_quad(mouse_x, mouse_y, mouse_x + cursor_size * container.manager().ui_aspect(&container), mouse_y + cursor_size, colors().text_color(), m_mouse_arrow_texture, PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + m_mouse_target = mouse_target->index(); + m_mouse_position = std::make_pair(mouse_x, mouse_y); + mouse_moved = true; } } + else if (0 <= m_mouse_target) + { + m_mouse_target = -1; + mouse_moved = true; + } } - - // cancel takes us back to the ingame handler - if (m_handler_param == UI_HANDLER_CANCEL) + else if (0 <= m_mouse_target) { - using namespace std::placeholders; - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_ingame, this, _1)); + m_mouse_target = -1; + mouse_moved = true; } + + // cancel takes us back to the in-game handler + if (handler_result & HANDLER_CANCEL) + set_handler(ui_callback_type::GENERAL, handler_callback_func(&mame_ui_manager::handler_ingame, this)); + + return mouse_moved || (handler_result & HANDLER_UPDATE); } @@ -647,19 +724,16 @@ render_font *mame_ui_manager::get_font() // of a line //------------------------------------------------- -float mame_ui_manager::get_line_height() +float mame_ui_manager::get_line_height(float scale) { - int32_t raw_font_pixel_height = get_font()->pixel_height(); - render_target &ui_target = machine().render().ui_target(); - int32_t target_pixel_height = ui_target.height(); - float one_to_one_line_height; - float scale_factor; + int32_t const raw_font_pixel_height = get_font()->pixel_height(); + float target_pixel_height = machine().render().ui_target().height(); // compute the font pixel height at the nominal size - one_to_one_line_height = (float)raw_font_pixel_height / (float)target_pixel_height; + float const one_to_one_line_height = float(raw_font_pixel_height) / target_pixel_height; // determine the scale factor - scale_factor = target_font_height() / one_to_one_line_height; + float scale_factor = target_font_height() * scale / one_to_one_line_height; // if our font is small-ish, do integral scaling if (raw_font_pixel_height < 24) @@ -670,17 +744,17 @@ float mame_ui_manager::get_line_height() if (one_to_one_line_height < UI_MAX_FONT_HEIGHT || raw_font_pixel_height < 12) scale_factor = 1.0f; } - - // otherwise, just ensure an integral scale factor else - scale_factor = floor(scale_factor); + { + // otherwise, just ensure an integral scale factor + scale_factor = floorf(scale_factor); + } } - - // otherwise, just make sure we hit an even number of pixels else { - int32_t height = scale_factor * one_to_one_line_height * (float)target_pixel_height; - scale_factor = (float)height / (one_to_one_line_height * (float)target_pixel_height); + // otherwise, just make sure we hit an even number of pixels + int32_t height = scale_factor * one_to_one_line_height * target_pixel_height; + scale_factor = float(height) / (one_to_one_line_height * target_pixel_height); } return scale_factor * one_to_one_line_height; @@ -703,9 +777,14 @@ float mame_ui_manager::get_char_width(char32_t ch) // character string //------------------------------------------------- -float mame_ui_manager::get_string_width(const char *s, float text_size) +float mame_ui_manager::get_string_width(std::string_view s) { - return get_font()->utf8string_width(get_line_height() * text_size, machine().render().ui_aspect(), s); + return get_string_width(s, get_line_height()); +} + +float mame_ui_manager::get_string_width(std::string_view s, float text_size) +{ + return get_font()->utf8string_width(text_size, machine().render().ui_aspect(), s); } @@ -741,9 +820,14 @@ void mame_ui_manager::draw_outlined_box(render_container &container, float x0, f // draw_text - simple text renderer //------------------------------------------------- -void mame_ui_manager::draw_text(render_container &container, const char *buf, float x, float y) +void mame_ui_manager::draw_text(render_container &container, std::string_view buf, float x, float y) { - draw_text_full(container, buf, x, y, 1.0f - x, ui::text_layout::LEFT, ui::text_layout::WORD, mame_ui_manager::NORMAL, colors().text_color(), colors().text_bg_color(), nullptr, nullptr); + draw_text_full( + container, + buf, + x, y, 1.0f - x, + ui::text_layout::text_justify::LEFT, ui::text_layout::word_wrapping::WORD, + mame_ui_manager::NORMAL, colors().text_color(), colors().text_bg_color(), nullptr, nullptr); } @@ -753,17 +837,43 @@ void mame_ui_manager::draw_text(render_container &container, const char *buf, fl // and full size computation //------------------------------------------------- -void mame_ui_manager::draw_text_full(render_container &container, const char *origs, float x, float y, float origwrapwidth, ui::text_layout::text_justify justify, ui::text_layout::word_wrapping wrap, draw_mode draw, rgb_t fgcolor, rgb_t bgcolor, float *totalwidth, float *totalheight, float text_size) +void mame_ui_manager::draw_text_full( + render_container &container, + std::string_view origs, + float x, float y, float origwrapwidth, + ui::text_layout::text_justify justify, ui::text_layout::word_wrapping wrap, + draw_mode draw, rgb_t fgcolor, rgb_t bgcolor, + float *totalwidth, float *totalheight) +{ + draw_text_full( + container, + origs, + x, y, origwrapwidth, + justify, wrap, + draw, fgcolor, bgcolor, + totalwidth, totalheight, + get_line_height()); +} + +void mame_ui_manager::draw_text_full( + render_container &container, + std::string_view origs, + float x, float y, float origwrapwidth, + ui::text_layout::text_justify justify, ui::text_layout::word_wrapping wrap, + draw_mode draw, rgb_t fgcolor, rgb_t bgcolor, + float *totalwidth, float *totalheight, + float text_size) { // create the layout - auto layout = create_layout(container, origwrapwidth, justify, wrap); + ui::text_layout layout( + *get_font(), machine().render().ui_aspect(&container) * text_size, text_size, + origwrapwidth, justify, wrap); // append text to it layout.add_text( origs, fgcolor, - draw == OPAQUE_ ? bgcolor : rgb_t::transparent(), - text_size); + (draw == OPAQUE_) ? bgcolor : rgb_t::transparent()); // and emit it (if we are asked to do so) if (draw != NONE) @@ -782,10 +892,10 @@ void mame_ui_manager::draw_text_full(render_container &container, const char *or // message with a box around it //------------------------------------------------- -void mame_ui_manager::draw_text_box(render_container &container, const char *text, ui::text_layout::text_justify justify, float xpos, float ypos, rgb_t backcolor) +void mame_ui_manager::draw_text_box(render_container &container, std::string_view text, ui::text_layout::text_justify justify, float xpos, float ypos, rgb_t backcolor) { // cap the maximum width - float maximum_width = 1.0f - box_lr_border() * 2; + float maximum_width = 1.0f - (box_lr_border() * machine().render().ui_aspect(&container) * 2.0f); // create a layout ui::text_layout layout = create_layout(container, maximum_width, justify); @@ -806,18 +916,19 @@ void mame_ui_manager::draw_text_box(render_container &container, const char *tex void mame_ui_manager::draw_text_box(render_container &container, ui::text_layout &layout, float xpos, float ypos, rgb_t backcolor) { // xpos and ypos are where we want to "pin" the layout, but we need to adjust for the actual size of the payload - auto actual_left = layout.actual_left(); - auto actual_width = layout.actual_width(); - auto actual_height = layout.actual_height(); - auto x = std::min(std::max(xpos - actual_width / 2, box_lr_border()), 1.0f - actual_width - box_lr_border()); - auto y = std::min(std::max(ypos - actual_height / 2, box_tb_border()), 1.0f - actual_height - box_tb_border()); + auto const lrborder = box_lr_border() * machine().render().ui_aspect(&container); + auto const actual_left = layout.actual_left(); + auto const actual_width = layout.actual_width(); + auto const actual_height = layout.actual_height(); + auto const x = std::clamp(xpos - actual_width / 2, lrborder, 1.0f - actual_width - lrborder); + auto const y = std::clamp(ypos - actual_height / 2, box_tb_border(), 1.0f - actual_height - box_tb_border()); // add a box around that - draw_outlined_box(container, - x - box_lr_border(), - y - box_tb_border(), - x + actual_width + box_lr_border(), - y + actual_height + box_tb_border(), backcolor); + draw_outlined_box( + container, + x - lrborder, y - box_tb_border(), + x + actual_width + lrborder, y + actual_height + box_tb_border(), + backcolor); // emit the text layout.emit(container, x - actual_left, y); @@ -829,7 +940,7 @@ void mame_ui_manager::draw_text_box(render_container &container, ui::text_layout // message with a box around it //------------------------------------------------- -void mame_ui_manager::draw_message_window(render_container &container, const char *text) +void mame_ui_manager::draw_message_window(render_container &container, std::string_view text) { draw_text_box(container, text, ui::text_layout::text_justify::LEFT, 0.5f, 0.5f, colors().background_color()); } @@ -914,8 +1025,7 @@ bool mame_ui_manager::show_profiler() const void mame_ui_manager::show_menu() { - using namespace std::placeholders; - set_handler(ui_callback_type::MENU, std::bind(&ui::menu::ui_handler, _1, std::ref(*this))); + set_handler(ui_callback_type::MENU, ui::menu::get_ui_handler(*this)); } @@ -947,46 +1057,6 @@ bool mame_ui_manager::is_menu_active(void) ***************************************************************************/ //------------------------------------------------- -// handler_messagebox - displays the current -// messagebox_text string but handles no input -//------------------------------------------------- - -uint32_t mame_ui_manager::handler_messagebox(render_container &container) -{ - draw_text_box(container, messagebox_text.c_str(), ui::text_layout::LEFT, 0.5f, 0.5f, messagebox_backcolor); - return 0; -} - - -//------------------------------------------------- -// handler_messagebox_anykey - displays the -// current messagebox_text string and waits for -// any keypress -//------------------------------------------------- - -uint32_t mame_ui_manager::handler_messagebox_anykey(render_container &container) -{ - uint32_t state = 0; - - // draw a standard message window - draw_text_box(container, messagebox_text.c_str(), ui::text_layout::LEFT, 0.5f, 0.5f, messagebox_backcolor); - - // if the user cancels, exit out completely - if (machine().ui_input().pressed(IPT_UI_CANCEL)) - { - machine().schedule_exit(); - state = UI_HANDLER_CANCEL; - } - - // if any key is pressed, just exit - else if (machine().input().poll_switches() != INPUT_CODE_INVALID) - state = UI_HANDLER_CANCEL; - - return state; -} - - -//------------------------------------------------- // process_natural_keyboard - processes any // natural keyboard input //------------------------------------------------- @@ -994,33 +1064,28 @@ uint32_t mame_ui_manager::handler_messagebox_anykey(render_container &container) void mame_ui_manager::process_natural_keyboard() { ui_event event; - int i, pressed; - input_item_id itemid; - input_code code; - uint8_t *key_down_ptr; - uint8_t key_down_mask; // loop while we have interesting events while (machine().ui_input().pop_event(&event)) { // if this was a UI_EVENT_CHAR event, post it if (event.event_type == ui_event::type::IME_CHAR) - machine().ioport().natkeyboard().post_char(event.ch); + machine().natkeyboard().post_char(event.ch); } // process natural keyboard keys that don't get UI_EVENT_CHARs - for (i = 0; i < ARRAY_LENGTH(non_char_keys); i++) + for (int i = 0; i < std::size(non_char_keys); i++) { // identify this keycode - itemid = non_char_keys[i]; - code = machine().input().code_from_itemid(itemid); + input_item_id itemid = non_char_keys[i]; + input_code code = machine().input().code_from_itemid(itemid); // ...and determine if it is pressed - pressed = machine().input().code_pressed(code); + bool pressed = machine().input().code_pressed(code); // figure out whey we are in the key_down map - key_down_ptr = &m_non_char_keys_down[i / 8]; - key_down_mask = 1 << (i % 8); + uint8_t *key_down_ptr = &m_non_char_keys_down[i / 8]; + uint8_t key_down_mask = 1 << (i % 8); if (pressed && !(*key_down_ptr & key_down_mask)) { @@ -1028,7 +1093,7 @@ void mame_ui_manager::process_natural_keyboard() *key_down_ptr |= key_down_mask; // post the key - machine().ioport().natkeyboard().post_char(UCHAR_MAMEKEY_BEGIN + code.item_id()); + machine().natkeyboard().post_char(UCHAR_MAMEKEY_BEGIN + code.item_id()); } else if (!pressed && (*key_down_ptr & key_down_mask)) { @@ -1080,6 +1145,7 @@ void mame_ui_manager::decrease_frameskip() bool mame_ui_manager::can_paste() { // check to see if the clipboard is not empty + // FIXME: this is expensive - need a cheaper way to check if clipboard contains suitable content return !osd_get_clipboard_text().empty(); } @@ -1090,32 +1156,12 @@ bool mame_ui_manager::can_paste() void mame_ui_manager::draw_fps_counter(render_container &container) { - draw_text_full(container, machine().video().speed_text().c_str(), 0.0f, 0.0f, 1.0f, - ui::text_layout::RIGHT, ui::text_layout::WORD, OPAQUE_, rgb_t::white(), rgb_t::black(), nullptr, nullptr); -} - - -//------------------------------------------------- -// draw_timecode_counter -//------------------------------------------------- - -void mame_ui_manager::draw_timecode_counter(render_container &container) -{ - std::string tempstring; - draw_text_full(container, machine().video().timecode_text(tempstring).c_str(), 0.0f, 0.0f, 1.0f, - ui::text_layout::RIGHT, ui::text_layout::WORD, OPAQUE_, rgb_t(0xf0, 0xf0, 0x10, 0x10), rgb_t::black(), nullptr, nullptr); -} - - -//------------------------------------------------- -// draw_timecode_total -//------------------------------------------------- - -void mame_ui_manager::draw_timecode_total(render_container &container) -{ - std::string tempstring; - draw_text_full(container, machine().video().timecode_total_text(tempstring).c_str(), 0.0f, 0.0f, 1.0f, - ui::text_layout::LEFT, ui::text_layout::WORD, OPAQUE_, rgb_t(0xf0, 0x10, 0xf0, 0x10), rgb_t::black(), nullptr, nullptr); + draw_text_full( + container, + machine().video().speed_text(), + 0.0f, 0.0f, 1.0f, + ui::text_layout::text_justify::RIGHT, ui::text_layout::word_wrapping::WORD, + OPAQUE_, rgb_t::white(), rgb_t::black(), nullptr, nullptr); } @@ -1125,32 +1171,13 @@ void mame_ui_manager::draw_timecode_total(render_container &container) void mame_ui_manager::draw_profiler(render_container &container) { - const char *text = g_profiler.text(machine()); - draw_text_full(container, text, 0.0f, 0.0f, 1.0f, ui::text_layout::LEFT, ui::text_layout::WORD, OPAQUE_, rgb_t::white(), rgb_t::black(), nullptr, nullptr); -} - - -//------------------------------------------------- -// start_save_state -//------------------------------------------------- - -void mame_ui_manager::start_save_state() -{ - ui::menu::stack_reset(machine()); - show_menu(); - ui::menu::stack_push<ui::menu_save_state>(*this, machine().render().ui_container()); -} - - -//------------------------------------------------- -// start_load_state -//------------------------------------------------- - -void mame_ui_manager::start_load_state() -{ - ui::menu::stack_reset(machine()); - show_menu(); - ui::menu::stack_push<ui::menu_load_state>(*this, machine().render().ui_container()); + std::string_view text = g_profiler.text(machine()); + draw_text_full( + container, + text, + 0.0f, 0.0f, 1.0f, + ui::text_layout::text_justify::LEFT, ui::text_layout::word_wrapping::WORD, + OPAQUE_, rgb_t::white(), rgb_t::black(), nullptr, nullptr); } @@ -1162,17 +1189,17 @@ void mame_ui_manager::start_load_state() void mame_ui_manager::image_handler_ingame() { // run display routine for devices - if (machine().phase() == machine_phase::RUNNING) + if (m_image_display_enabled && machine().phase() == machine_phase::RUNNING) { auto layout = create_layout(machine().render().ui_container()); // loop through all devices, build their text into the layout - for (device_image_interface &image : image_interface_iterator(machine().root_device())) + for (device_image_interface &image : image_interface_enumerator(machine().root_device())) { std::string str = image.call_display(); if (!str.empty()) { - layout.add_text(str.c_str()); + layout.add_text(str); layout.add_text("\n"); } } @@ -1194,20 +1221,15 @@ void mame_ui_manager::image_handler_ingame() uint32_t mame_ui_manager::handler_ingame(render_container &container) { + // let the OSD do its thing first + machine().osd().check_osd_inputs(); + bool is_paused = machine().paused(); // first draw the FPS counter if (show_fps_counter()) draw_fps_counter(container); - // Show the duration of current part (intro or gameplay or extra) - if (show_timecode_counter()) - draw_timecode_counter(container); - - // Show the total time elapsed for the video preview (all parts intro, gameplay, extras) - if (show_timecode_total()) - draw_timecode_total(container); - // draw the profiler if visible if (show_profiler()) draw_profiler(container); @@ -1220,8 +1242,8 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) } // determine if we should disable the rest of the UI - bool has_keyboard = machine_info().has_keyboard(); - bool ui_disabled = (has_keyboard && !machine().ui_active()); + bool const has_keyboard = machine_info().has_keyboard(); + bool const ui_disabled = !ui_active(); // is ScrLk UI toggling applicable here? if (has_keyboard) @@ -1230,50 +1252,32 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) if (machine().ui_input().pressed(IPT_UI_TOGGLE_UI)) { // toggle the UI - machine().set_ui_active(!machine().ui_active()); + set_ui_active(!ui_active()); // display a popup indicating the new status - if (machine().ui_active()) - { - popup_time(2, "%s\n%s\n%s\n%s\n%s\n%s\n", - _("Keyboard Emulation Status"), - "-------------------------", - _("Mode: PARTIAL Emulation"), - _("UI: Enabled"), - "-------------------------", - _("**Use ScrLock to toggle**")); - } + std::string const name = get_general_input_setting(IPT_UI_TOGGLE_UI); + if (ui_active()) + popup_time(2, _("UI controls enabled\nUse %1$s to toggle"), name); else - { - popup_time(2, "%s\n%s\n%s\n%s\n%s\n%s\n", - _("Keyboard Emulation Status"), - "-------------------------", - _("Mode: FULL Emulation"), - _("UI: Disabled"), - "-------------------------", - _("**Use ScrLock to toggle**")); - } + popup_time(2, _("UI controls disabled\nUse %1$s to toggle"), name); } } // is the natural keyboard enabled? - if (machine().ioport().natkeyboard().in_use() && (machine().phase() == machine_phase::RUNNING)) + if (machine().natkeyboard().in_use() && (machine().phase() == machine_phase::RUNNING)) process_natural_keyboard(); if (!ui_disabled) { // paste command if (machine().ui_input().pressed(IPT_UI_PASTE)) - machine().ioport().natkeyboard().paste(); + machine().natkeyboard().paste(); } image_handler_ingame(); - // handle a save input timecode request - if (machine().ui_input().pressed(IPT_UI_TIMECODE)) - machine().video().save_input_timecode(); - - if (ui_disabled) return ui_disabled; + if (ui_disabled) + return 0; if (machine().ui_input().pressed(IPT_UI_CANCEL)) { @@ -1282,18 +1286,18 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) } // turn on menus if requested - if (machine().ui_input().pressed(IPT_UI_CONFIGURE)) + if (machine().ui_input().pressed(IPT_UI_MENU)) { show_menu(); return 0; } // if the on-screen display isn't up and the user has toggled it, turn it on - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0 && machine().ui_input().pressed(IPT_UI_ON_SCREEN_DISPLAY)) + if (!(machine().debug_flags & DEBUG_FLAG_ENABLED) && machine().ui_input().pressed(IPT_UI_ON_SCREEN_DISPLAY)) { - using namespace std::placeholders; - set_handler(ui_callback_type::MENU, std::bind(&ui::menu_sliders::ui_handler, _1, std::ref(*this))); - return 1; + ui::menu::stack_push<ui::menu_sliders>(*this, machine().render().ui_container(), true); + show_menu(); + return 0; } // handle a reset request @@ -1308,14 +1312,20 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) if (!is_paused) machine().pause(); using namespace std::placeholders; - set_handler(ui_callback_type::VIEWER, std::bind(&ui_gfx_ui_handler, _1, std::ref(*this), is_paused)); - return is_paused ? 1 : 0; + set_handler( + ui_callback_type::VIEWER, + handler_callback_func( + [this, is_paused] (render_container &container) -> uint32_t + { + return ui_gfx_ui_handler(container, *this, is_paused); + })); + return 0; } // handle a tape control key if (machine().ui_input().pressed(IPT_UI_TAPE_START)) { - for (cassette_image_device &cass : cassette_device_iterator(machine().root_device())) + for (cassette_image_device &cass : cassette_device_enumerator(machine().root_device())) { cass.change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); return 0; @@ -1323,7 +1333,7 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) } if (machine().ui_input().pressed(IPT_UI_TAPE_STOP)) { - for (cassette_image_device &cass : cassette_device_iterator(machine().root_device())) + for (cassette_image_device &cass : cassette_device_enumerator(machine().root_device())) { cass.change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); return 0; @@ -1333,15 +1343,31 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) // handle a save state request if (machine().ui_input().pressed(IPT_UI_SAVE_STATE)) { - start_save_state(); - return LOADSAVE_SAVE; + ui::menu::stack_push<ui::menu_save_state>(*this, machine().render().ui_container(), true); + show_menu(); + return 0; } // handle a load state request if (machine().ui_input().pressed(IPT_UI_LOAD_STATE)) { - start_load_state(); - return LOADSAVE_LOAD; + ui::menu::stack_push<ui::menu_load_state>(*this, machine().render().ui_container(), true); + show_menu(); + return 0; + } + + // handle a quick save state request + if (machine().ui_input().pressed(IPT_UI_SAVE_STATE_QUICK)) + { + machine().schedule_save("quick"); + return 0; + } + + // handle a quick load state request + if (machine().ui_input().pressed(IPT_UI_LOAD_STATE_QUICK)) + { + machine().schedule_load("quick"); + return 0; } // handle a save snapshot request @@ -1366,7 +1392,7 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) // handle a toggle cheats request if (machine().ui_input().pressed(IPT_UI_TOGGLE_CHEAT)) - mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled()); + mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled(), true); // toggle MNG recording if (machine().ui_input().pressed(IPT_UI_RECORD_MNG)) @@ -1394,7 +1420,12 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) // toggle throttle? if (machine().ui_input().pressed(IPT_UI_THROTTLE)) - machine().video().toggle_throttle(); + { + const bool new_throttle_state = !machine().video().throttled(); + machine().video().set_throttled(new_throttle_state); + if (m_unthrottle_mute) + machine().sound().ui_mute(!new_throttle_state); + } // check for fast forward if (machine().ioport().type_pressed(IPT_UI_FAST_FORWARD)) @@ -1415,51 +1446,15 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) void mame_ui_manager::request_quit() { - using namespace std::placeholders; if (!machine().options().confirm_quit()) + { machine().schedule_exit(); + } else - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_confirm_quit, this, _1)); -} - - -//------------------------------------------------- -// handler_confirm_quit - leads the user through -// confirming quit emulation -//------------------------------------------------- - -uint32_t mame_ui_manager::handler_confirm_quit(render_container &container) -{ - uint32_t state = 0; - - // get the text for 'UI Select' - std::string ui_select_text = machine().input().seq_name(machine().ioport().type_seq(IPT_UI_SELECT, 0, SEQ_TYPE_STANDARD)); - - // get the text for 'UI Cancel' - std::string ui_cancel_text = machine().input().seq_name(machine().ioport().type_seq(IPT_UI_CANCEL, 0, SEQ_TYPE_STANDARD)); - - // assemble the quit message - std::string quit_message = string_format(_("Are you sure you want to quit?\n\n" - "Press ''%1$s'' to quit,\n" - "Press ''%2$s'' to return to emulation."), - ui_select_text, - ui_cancel_text); - - draw_text_box(container, quit_message.c_str(), ui::text_layout::CENTER, 0.5f, 0.5f, UI_RED_COLOR); - machine().pause(); - - // if the user press ENTER, quit the game - if (machine().ui_input().pressed(IPT_UI_SELECT)) - machine().schedule_exit(); - - // if the user press ESC, just continue - else if (machine().ui_input().pressed(IPT_UI_CANCEL)) { - machine().resume(); - state = UI_HANDLER_CANCEL; + ui::menu::stack_push<ui::menu_confirm_quit>(*this, machine().render().ui_container()); + show_menu(); } - - return state; } @@ -1471,36 +1466,12 @@ uint32_t mame_ui_manager::handler_confirm_quit(render_container &container) // ui_get_slider_list - get the list of sliders //------------------------------------------------- -std::vector<ui::menu_item>& mame_ui_manager::get_slider_list(void) +std::vector<ui::menu_item> &mame_ui_manager::get_slider_list() { return slider_list; } -//------------------------------------------------- -// slider_alloc - allocate a new slider entry -//------------------------------------------------- - -std::unique_ptr<slider_state> mame_ui_manager::slider_alloc(int id, const char *title, int32_t minval, int32_t defval, int32_t maxval, int32_t incval, void *arg) -{ - auto state = std::make_unique<slider_state>(); - - state->minval = minval; - state->defval = defval; - state->maxval = maxval; - state->incval = incval; - - using namespace std::placeholders; - state->update = std::bind(&mame_ui_manager::slider_changed, this, _1, _2, _3, _4, _5); - - state->arg = arg; - state->id = id; - state->description = title; - - return state; -} - - //---------------------------------------------------------- // mame_ui_manager::slider_init - initialize the list of slider // controls @@ -1508,140 +1479,134 @@ std::unique_ptr<slider_state> mame_ui_manager::slider_alloc(int id, const char * std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine) { + using namespace std::placeholders; + m_sliders.clear(); // add overall volume - m_sliders.push_back(slider_alloc(SLIDER_ID_VOLUME, _("Master Volume"), -32, 0, 0, 1, nullptr)); + slider_alloc(_("Master Volume"), -32, 0, 0, 1, std::bind(&mame_ui_manager::slider_volume, this, _1, _2)); // add per-channel volume mixer_input info; for (int item = 0; machine.sound().indexed_mixer_input(item, info); item++) { - int32_t maxval = 2000; - int32_t defval = 1000; - std::string str = string_format(_("%1$s Volume"), info.stream->input(info.inputnum).name()); - m_sliders.push_back(slider_alloc(SLIDER_ID_MIXERVOL + item, str.c_str(), 0, defval, maxval, 20, (void *)(uintptr_t)item)); + slider_alloc(std::move(str), 0, 1000, 4000, 20, std::bind(&mame_ui_manager::slider_mixervol, this, item, _1, _2)); + } + + // add speaker panning + for (speaker_device &speaker : speaker_device_enumerator(machine.root_device())) + { + int defpan = floorf(speaker.defpan() * 1000.0f + 0.5f); + std::string str = string_format(_("%s '%s' Panning"), speaker.name(), speaker.tag()); + slider_alloc(std::move(str), -1000, defpan, 1000, 20, std::bind(&mame_ui_manager::slider_panning, this, std::ref(speaker), _1, _2)); } // add analog adjusters - int slider_index = 0; for (auto &port : machine.ioport().ports()) { for (ioport_field &field : port.second->fields()) { if (field.type() == IPT_ADJUSTER) { - m_sliders.push_back(slider_alloc(SLIDER_ID_ADJUSTER + slider_index++, field.name(), field.minval(), field.defvalue(), field.maxval(), 1, (void *)&field)); + slider_alloc(field.name(), field.minval(), field.defvalue(), field.maxval(), 1, std::bind(&mame_ui_manager::slider_adjuster, this, std::ref(field), _1, _2)); } } } // add CPU overclocking (cheat only) - slider_index = 0; if (machine.options().cheat()) { - for (device_execute_interface &exec : execute_interface_iterator(machine.root_device())) + for (device_execute_interface &exec : execute_interface_enumerator(machine.root_device())) { - void *param = (void *)&exec.device(); std::string str = string_format(_("Overclock CPU %1$s"), exec.device().tag()); - m_sliders.push_back(slider_alloc(SLIDER_ID_OVERCLOCK + slider_index++, str.c_str(), 100, 1000, 4000, 10, param)); + slider_alloc(std::move(str), 100, 1000, 4000, 10, std::bind(&mame_ui_manager::slider_overclock, this, std::ref(exec.device()), _1, _2)); } - for (device_sound_interface &snd : sound_interface_iterator(machine.root_device())) + for (device_sound_interface &snd : sound_interface_enumerator(machine.root_device())) { device_execute_interface *exec; if (!snd.device().interface(exec) && snd.device().unscaled_clock() != 0) { - void *param = (void *)&snd.device(); std::string str = string_format(_("Overclock %1$s sound"), snd.device().tag()); - m_sliders.push_back(slider_alloc(SLIDER_ID_OVERCLOCK + slider_index++, str.c_str(), 100, 1000, 4000, 10, param)); + slider_alloc(std::move(str), 100, 1000, 4000, 10, std::bind(&mame_ui_manager::slider_overclock, this, std::ref(snd.device()), _1, _2)); } } } // add screen parameters - screen_device_iterator scriter(machine.root_device()); - slider_index = 0; + screen_device_enumerator scriter(machine.root_device()); for (screen_device &screen : scriter) { - int defxscale = floor(screen.xscale() * 1000.0f + 0.5f); - int defyscale = floor(screen.yscale() * 1000.0f + 0.5f); - int defxoffset = floor(screen.xoffset() * 1000.0f + 0.5f); - int defyoffset = floor(screen.yoffset() * 1000.0f + 0.5f); - void *param = (void *)&screen; + int defxscale = floorf(screen.xscale() * 1000.0f + 0.5f); + int defyscale = floorf(screen.yscale() * 1000.0f + 0.5f); + int defxoffset = floorf(screen.xoffset() * 1000.0f + 0.5f); + int defyoffset = floorf(screen.yoffset() * 1000.0f + 0.5f); std::string screen_desc = machine_info().get_screen_desc(screen); // add refresh rate tweaker if (machine.options().cheat()) { std::string str = string_format(_("%1$s Refresh Rate"), screen_desc); - m_sliders.push_back(slider_alloc(SLIDER_ID_REFRESH + slider_index, str.c_str(), -10000, 0, 10000, 1000, param)); + slider_alloc(std::move(str), -10000, 0, 10000, 1000, std::bind(&mame_ui_manager::slider_refresh, this, std::ref(screen), _1, _2)); } // add standard brightness/contrast/gamma controls per-screen std::string str = string_format(_("%1$s Brightness"), screen_desc); - m_sliders.push_back(slider_alloc(SLIDER_ID_BRIGHTNESS + slider_index, str.c_str(), 100, 1000, 2000, 10, param)); + slider_alloc(std::move(str), 100, 1000, 2000, 10, std::bind(&mame_ui_manager::slider_brightness, this, std::ref(screen), _1, _2)); str = string_format(_("%1$s Contrast"), screen_desc); - m_sliders.push_back(slider_alloc(SLIDER_ID_CONTRAST + slider_index, str.c_str(), 100, 1000, 2000, 50, param)); + slider_alloc(std::move(str), 100, 1000, 2000, 50, std::bind(&mame_ui_manager::slider_contrast, this, std::ref(screen), _1, _2)); str = string_format(_("%1$s Gamma"), screen_desc); - m_sliders.push_back(slider_alloc(SLIDER_ID_GAMMA + slider_index, str.c_str(), 100, 1000, 3000, 50, param)); + slider_alloc(std::move(str), 100, 1000, 3000, 50, std::bind(&mame_ui_manager::slider_gamma, this, std::ref(screen), _1, _2)); // add scale and offset controls per-screen str = string_format(_("%1$s Horiz Stretch"), screen_desc); - m_sliders.push_back(slider_alloc(SLIDER_ID_XSCALE + slider_index, str.c_str(), 500, defxscale, 1500, 2, param)); + slider_alloc(std::move(str), 500, defxscale, 1500, 2, std::bind(&mame_ui_manager::slider_xscale, this, std::ref(screen), _1, _2)); str = string_format(_("%1$s Horiz Position"), screen_desc); - m_sliders.push_back(slider_alloc(SLIDER_ID_XOFFSET + slider_index, str.c_str(), -500, defxoffset, 500, 2, param)); + slider_alloc(std::move(str), -500, defxoffset, 500, 2, std::bind(&mame_ui_manager::slider_xoffset, this, std::ref(screen), _1, _2)); str = string_format(_("%1$s Vert Stretch"), screen_desc); - m_sliders.push_back(slider_alloc(SLIDER_ID_YSCALE + slider_index, str.c_str(), 500, defyscale, 1500, 2, param)); + slider_alloc(std::move(str), 500, defyscale, 1500, 2, std::bind(&mame_ui_manager::slider_yscale, this, std::ref(screen), _1, _2)); str = string_format(_("%1$s Vert Position"), screen_desc); - m_sliders.push_back(slider_alloc(SLIDER_ID_YOFFSET + slider_index, str.c_str(), -500, defyoffset, 500, 2, param)); - slider_index++; + slider_alloc(std::move(str), -500, defyoffset, 500, 2, std::bind(&mame_ui_manager::slider_yoffset, this, std::ref(screen), _1, _2)); } - slider_index = 0; - for (laserdisc_device &laserdisc : laserdisc_device_iterator(machine.root_device())) + for (laserdisc_device &laserdisc : laserdisc_device_enumerator(machine.root_device())) { if (laserdisc.overlay_configured()) { laserdisc_overlay_config config; laserdisc.get_overlay_config(config); - int defxscale = floor(config.m_overscalex * 1000.0f + 0.5f); - int defyscale = floor(config.m_overscaley * 1000.0f + 0.5f); - int defxoffset = floor(config.m_overposx * 1000.0f + 0.5f); - int defyoffset = floor(config.m_overposy * 1000.0f + 0.5f); - void *param = (void *)&laserdisc; + int defxscale = floorf(config.m_overscalex * 1000.0f + 0.5f); + int defyscale = floorf(config.m_overscaley * 1000.0f + 0.5f); + int defxoffset = floorf(config.m_overposx * 1000.0f + 0.5f); + int defyoffset = floorf(config.m_overposy * 1000.0f + 0.5f); // add scale and offset controls per-overlay std::string str = string_format(_("Laserdisc '%1$s' Horiz Stretch"), laserdisc.tag()); - m_sliders.push_back(slider_alloc(SLIDER_ID_OVERLAY_XSCALE + slider_index, str.c_str(), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, param)); + slider_alloc(std::move(str), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, std::bind(&mame_ui_manager::slider_overxscale, this, std::ref(laserdisc), _1, _2)); str = string_format(_("Laserdisc '%1$s' Horiz Position"), laserdisc.tag()); - m_sliders.push_back(slider_alloc(SLIDER_ID_OVERLAY_YSCALE + slider_index, str.c_str(), -500, defxoffset, 500, 2, param)); + slider_alloc(std::move(str), -500, defxoffset, 500, 2, std::bind(&mame_ui_manager::slider_overxoffset, this, std::ref(laserdisc), _1, _2)); str = string_format(_("Laserdisc '%1$s' Vert Stretch"), laserdisc.tag()); - m_sliders.push_back(slider_alloc(SLIDER_ID_OVERLAY_XOFFSET + slider_index, str.c_str(), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, param)); + slider_alloc(std::move(str), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, std::bind(&mame_ui_manager::slider_overyscale, this, std::ref(laserdisc), _1, _2)); str = string_format(_("Laserdisc '%1$s' Vert Position"), laserdisc.tag()); - m_sliders.push_back(slider_alloc(SLIDER_ID_OVERLAY_YOFFSET + slider_index, str.c_str(), -500, defyoffset, 500, 2, param)); - slider_index++; + slider_alloc(std::move(str), -500, defyoffset, 500, 2, std::bind(&mame_ui_manager::slider_overyoffset, this, std::ref(laserdisc), _1, _2)); } } - slider_index = 0; for (screen_device &screen : scriter) { if (screen.screen_type() == SCREEN_TYPE_VECTOR) { - // add vector control - m_sliders.push_back(slider_alloc(SLIDER_ID_FLICKER + slider_index, _("Vector Flicker"), 0, 0, 1000, 10, nullptr)); - m_sliders.push_back(slider_alloc(SLIDER_ID_BEAM_WIDTH_MIN + slider_index, _("Beam Width Minimum"), 100, 100, 1000, 1, nullptr)); - m_sliders.push_back(slider_alloc(SLIDER_ID_BEAM_WIDTH_MAX + slider_index, _("Beam Width Maximum"), 100, 100, 1000, 1, nullptr)); - m_sliders.push_back(slider_alloc(SLIDER_ID_BEAM_DOT_SIZE + slider_index, _("Beam Dot Size"), 100, 100, 1000, 1, nullptr)); - m_sliders.push_back(slider_alloc(SLIDER_ID_BEAM_INTENSITY + slider_index, _("Beam Intensity Weight"), -1000, 0, 1000, 10, nullptr)); - slider_index++; + // add vector control (FIXME: these should all be per-screen rather than global) + slider_alloc(_("Vector Flicker"), 0, 0, 1000, 10, std::bind(&mame_ui_manager::slider_flicker, this, std::ref(screen), _1, _2)); + slider_alloc(_("Beam Width Minimum"), 100, 100, 1000, 1, std::bind(&mame_ui_manager::slider_beam_width_min, this, std::ref(screen), _1, _2)); + slider_alloc(_("Beam Width Maximum"), 100, 100, 1000, 1, std::bind(&mame_ui_manager::slider_beam_width_max, this, std::ref(screen), _1, _2)); + slider_alloc(_("Beam Dot Size"), 100, 100, 1000, 1, std::bind(&mame_ui_manager::slider_beam_dot_size, this, std::ref(screen), _1, _2)); + slider_alloc(_("Beam Intensity Weight"), -1000, 0, 1000, 10, std::bind(&mame_ui_manager::slider_beam_intensity_weight, this, std::ref(screen), _1, _2)); break; } } #ifdef MAME_DEBUG - slider_index = 0; // add crosshair adjusters for (auto &port : machine.ioport().ports()) { @@ -1650,9 +1615,9 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine if (field.crosshair_axis() != CROSSHAIR_AXIS_NONE && field.player() == 0) { std::string str = string_format(_("Crosshair Scale %1$s"), (field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("X") : _("Y")); - m_sliders.push_back(slider_alloc(SLIDER_ID_CROSSHAIR_SCALE + slider_index, str.c_str(), -3000, 1000, 3000, 100, (void *)&field)); + slider_alloc(std::move(str), -3000, 1000, 3000, 100, std::bind(&mame_ui_manager::slider_crossscale, this, std::ref(field), _1, _2)); str = string_format(_("Crosshair Offset %1$s"), (field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("X") : _("Y")); - m_sliders.push_back(slider_alloc(SLIDER_ID_CROSSHAIR_OFFSET + slider_index, str.c_str(), -3000, 0, 3000, 100, (void *)&field)); + slider_alloc(std::move(str), -3000, 0, 3000, 100, std::bind(&mame_ui_manager::slider_crossoffset, this, std::ref(field), _1, _2)); } } } @@ -1661,88 +1626,29 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine std::vector<ui::menu_item> items; for (auto &slider : m_sliders) { - ui::menu_item item; - item.text = slider->description; - item.subtext = ""; - item.flags = 0; - item.ref = slider.get(); - item.type = ui::menu_item_type::SLIDER; - items.push_back(item); + ui::menu_item item(ui::menu_item_type::SLIDER, slider.get()); + item.set_text(slider->description); + items.emplace_back(std::move(item)); } return items; } -//---------------------------------------------------- -// slider_changed - global slider-modified callback -//---------------------------------------------------- - -int32_t mame_ui_manager::slider_changed(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) -{ - if (id == SLIDER_ID_VOLUME) - return slider_volume(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_MIXERVOL && id <= SLIDER_ID_MIXERVOL_LAST) - return slider_mixervol(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_ADJUSTER && id <= SLIDER_ID_ADJUSTER_LAST) - return slider_adjuster(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_OVERCLOCK && id <= SLIDER_ID_OVERCLOCK_LAST) - return slider_overclock(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_REFRESH && id <= SLIDER_ID_REFRESH_LAST) - return slider_refresh(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_BRIGHTNESS && id <= SLIDER_ID_BRIGHTNESS_LAST) - return slider_brightness(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_CONTRAST && id <= SLIDER_ID_CONTRAST_LAST) - return slider_contrast(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_GAMMA && id <= SLIDER_ID_GAMMA_LAST) - return slider_gamma(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_XSCALE && id <= SLIDER_ID_XSCALE_LAST) - return slider_xscale(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_YSCALE && id <= SLIDER_ID_YSCALE_LAST) - return slider_yscale(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_XOFFSET && id <= SLIDER_ID_XOFFSET_LAST) - return slider_xoffset(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_YOFFSET && id <= SLIDER_ID_YOFFSET_LAST) - return slider_yoffset(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_OVERLAY_XSCALE && id <= SLIDER_ID_OVERLAY_XSCALE_LAST) - return slider_overxscale(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_OVERLAY_YSCALE && id <= SLIDER_ID_OVERLAY_YSCALE_LAST) - return slider_overyscale(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_OVERLAY_XOFFSET && id <= SLIDER_ID_OVERLAY_XOFFSET_LAST) - return slider_overxoffset(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_OVERLAY_YOFFSET && id <= SLIDER_ID_OVERLAY_YOFFSET_LAST) - return slider_overyoffset(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_FLICKER && id <= SLIDER_ID_FLICKER_LAST) - return slider_flicker(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_BEAM_WIDTH_MIN && id <= SLIDER_ID_BEAM_WIDTH_MIN_LAST) - return slider_beam_width_min(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_BEAM_WIDTH_MAX && id <= SLIDER_ID_BEAM_WIDTH_MAX_LAST) - return slider_beam_width_max(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_BEAM_DOT_SIZE && id <= SLIDER_ID_BEAM_DOT_SIZE_LAST) - return slider_beam_dot_size(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_BEAM_INTENSITY && id <= SLIDER_ID_BEAM_INTENSITY_LAST) - return slider_beam_intensity_weight(machine, arg, id, str, newval); -#ifdef MAME_DEBUG - else if (id >= SLIDER_ID_CROSSHAIR_SCALE && id <= SLIDER_ID_CROSSHAIR_SCALE_LAST) - return slider_crossscale(machine, arg, id, str, newval); - else if (id >= SLIDER_ID_CROSSHAIR_OFFSET && id <= SLIDER_ID_CROSSHAIR_OFFSET_LAST) - return slider_crossoffset(machine, arg, id, str, newval); -#endif - - return 0; -} - //------------------------------------------------- // slider_volume - global volume slider callback //------------------------------------------------- -int32_t mame_ui_manager::slider_volume(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_volume(std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - machine.sound().set_attenuation(newval); + machine().sound().set_attenuation(newval); + + int32_t curval = machine().sound().attenuation(); if (str) - *str = string_format(_("%1$3ddB"), machine.sound().attenuation()); - return machine.sound().attenuation(); + *str = string_format(_(u8"%1$3d\u00a0dB"), curval); + + return curval; } @@ -1751,20 +1657,66 @@ int32_t mame_ui_manager::slider_volume(running_machine &machine, void *arg, int // slider callback //------------------------------------------------- -int32_t mame_ui_manager::slider_mixervol(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_mixervol(int item, std::string *str, int32_t newval) { mixer_input info; - if (!machine.sound().indexed_mixer_input((uintptr_t)arg, info)) + if (!machine().sound().indexed_mixer_input(item, info)) return 0; + if (newval != SLIDER_NOCHANGE) + info.stream->input(info.inputnum).set_user_gain(float(newval) * 0.001f); + + int32_t curval = floorf(info.stream->input(info.inputnum).user_gain() * 1000.0f + 0.5f); + if (str) { - int32_t curval = floor(info.stream->input(info.inputnum).user_gain() * 1000.0f + 0.5f); - if (newval > curval && (newval - curval) <= 4) newval += 4; // round up on increment - info.stream->input(info.inputnum).set_user_gain((float)newval * 0.001f); + if (curval == 0) + *str = _("Mute"); + else if (curval % 10) + *str = string_format(_("%1$.1f%%"), float(curval) * 0.1f); + else + *str = string_format(_("%1$3d%%"), curval / 10); } + + return curval; +} + + +//------------------------------------------------- +// slider_panning - speaker panning slider +// callback +//------------------------------------------------- + +int32_t mame_ui_manager::slider_panning(speaker_device &speaker, std::string *str, int32_t newval) +{ + if (newval != SLIDER_NOCHANGE) + speaker.set_pan(float(newval) * 0.001f); + + int32_t curval = floorf(speaker.pan() * 1000.0f + 0.5f); if (str) - *str = string_format("%4.2f", info.stream->input(info.inputnum).user_gain()); - return floorf(info.stream->input(info.inputnum).user_gain() * 1000.0f + 0.5f); + { + switch (curval) + { + // preset strings for exact center/left/right + case 0: + *str = _("Center"); + break; + + case -1000: + *str = _("Left"); + break; + + case 1000: + *str = _("Right"); + break; + + // otherwise show as floating point + default: + *str = string_format(_("%1$.3f"), float(curval) * 0.001f); + break; + } + } + + return curval; } @@ -1773,19 +1725,18 @@ int32_t mame_ui_manager::slider_mixervol(running_machine &machine, void *arg, in // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_adjuster(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_adjuster(ioport_field &field, std::string *str, int32_t newval) { - ioport_field *field = (ioport_field *)arg; ioport_field::user_settings settings; - field->get_user_settings(settings); + field.get_user_settings(settings); if (newval != SLIDER_NOCHANGE) { settings.value = newval; - field->set_user_settings(settings); + field.set_user_settings(settings); } if (str) - *str = string_format(_("%1$d%%"), settings.value); + *str = string_format(_("%1$3d%%"), settings.value); return settings.value; } @@ -1795,14 +1746,21 @@ int32_t mame_ui_manager::slider_adjuster(running_machine &machine, void *arg, in // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_overclock(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_overclock(device_t &device, std::string *str, int32_t newval) { - device_t *cpu = (device_t *)arg; if (newval != SLIDER_NOCHANGE) - cpu->set_clock_scale((float)newval * 0.001f); + device.set_clock_scale(double(newval) * 0.001); + + int32_t curval = floor(device.clock_scale() * 1000.0 + 0.5); if (str) - *str = string_format(_("%1$3.0f%%"), floor(cpu->clock_scale() * 100.0 + 0.5)); - return floor(cpu->clock_scale() * 1000.0 + 0.5); + { + if (curval % 10) + *str = string_format(_("%1$.1f%%"), float(curval) * 0.1f); + else + *str = string_format(_("%1$3d%%"), curval / 10); + } + + return curval; } @@ -1810,23 +1768,22 @@ int32_t mame_ui_manager::slider_overclock(running_machine &machine, void *arg, i // slider_refresh - refresh rate slider callback //------------------------------------------------- -int32_t mame_ui_manager::slider_refresh(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_refresh(screen_device &screen, std::string *str, int32_t newval) { - screen_device *screen = reinterpret_cast<screen_device *>(arg); - double defrefresh = ATTOSECONDS_TO_HZ(screen->refresh_attoseconds()); + double defrefresh = ATTOSECONDS_TO_HZ(screen.refresh_attoseconds()); double refresh; if (newval != SLIDER_NOCHANGE) { - int width = screen->width(); - int height = screen->height(); - const rectangle &visarea = screen->visible_area(); - screen->configure(width, height, visarea, HZ_TO_ATTOSECONDS(defrefresh + (double)newval * 0.001)); + int width = screen.width(); + int height = screen.height(); + const rectangle &visarea = screen.visible_area(); + screen.configure(width, height, visarea, HZ_TO_ATTOSECONDS(defrefresh + double(newval) * 0.001)); } if (str) - *str = string_format(_("%1$.3f" UTF8_NBSP "Hz"), screen->frame_period().as_hz()); - refresh = screen->frame_period().as_hz(); + *str = string_format(_(u8"%1$.3f\u00a0Hz"), screen.frame_period().as_hz()); + refresh = screen.frame_period().as_hz(); return floor((refresh - defrefresh) * 1000.0 + 0.5); } @@ -1836,20 +1793,17 @@ int32_t mame_ui_manager::slider_refresh(running_machine &machine, void *arg, int // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_brightness(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_brightness(screen_device &screen, std::string *str, int32_t newval) { - screen_device *screen = reinterpret_cast<screen_device *>(arg); - render_container::user_settings settings; - - screen->container().get_user_settings(settings); + render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_brightness = (float)newval * 0.001f; - screen->container().set_user_settings(settings); + settings.m_brightness = float(newval) * 0.001f; + screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_brightness); - return floor(settings.m_brightness * 1000.0f + 0.5f); + return floorf(settings.m_brightness * 1000.0f + 0.5f); } @@ -1858,20 +1812,17 @@ int32_t mame_ui_manager::slider_brightness(running_machine &machine, void *arg, // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_contrast(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_contrast(screen_device &screen, std::string *str, int32_t newval) { - screen_device *screen = reinterpret_cast<screen_device *>(arg); - render_container::user_settings settings; - - screen->container().get_user_settings(settings); + render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_contrast = (float)newval * 0.001f; - screen->container().set_user_settings(settings); + settings.m_contrast = float(newval) * 0.001f; + screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_contrast); - return floor(settings.m_contrast * 1000.0f + 0.5f); + return floorf(settings.m_contrast * 1000.0f + 0.5f); } @@ -1879,20 +1830,17 @@ int32_t mame_ui_manager::slider_contrast(running_machine &machine, void *arg, in // slider_gamma - screen gamma slider callback //------------------------------------------------- -int32_t mame_ui_manager::slider_gamma(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_gamma(screen_device &screen, std::string *str, int32_t newval) { - screen_device *screen = reinterpret_cast<screen_device *>(arg); - render_container::user_settings settings; - - screen->container().get_user_settings(settings); + render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_gamma = (float)newval * 0.001f; - screen->container().set_user_settings(settings); + settings.m_gamma = float(newval) * 0.001f; + screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_gamma); - return floor(settings.m_gamma * 1000.0f + 0.5f); + return floorf(settings.m_gamma * 1000.0f + 0.5f); } @@ -1901,20 +1849,17 @@ int32_t mame_ui_manager::slider_gamma(running_machine &machine, void *arg, int i // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_xscale(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_xscale(screen_device &screen, std::string *str, int32_t newval) { - screen_device *screen = reinterpret_cast<screen_device *>(arg); - render_container::user_settings settings; - - screen->container().get_user_settings(settings); + render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_xscale = (float)newval * 0.001f; - screen->container().set_user_settings(settings); + settings.m_xscale = float(newval) * 0.001f; + screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_xscale); - return floor(settings.m_xscale * 1000.0f + 0.5f); + return floorf(settings.m_xscale * 1000.0f + 0.5f); } @@ -1923,20 +1868,17 @@ int32_t mame_ui_manager::slider_xscale(running_machine &machine, void *arg, int // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_yscale(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_yscale(screen_device &screen, std::string *str, int32_t newval) { - screen_device *screen = reinterpret_cast<screen_device *>(arg); - render_container::user_settings settings; - - screen->container().get_user_settings(settings); + render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_yscale = (float)newval * 0.001f; - screen->container().set_user_settings(settings); + settings.m_yscale = float(newval) * 0.001f; + screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_yscale); - return floor(settings.m_yscale * 1000.0f + 0.5f); + return floorf(settings.m_yscale * 1000.0f + 0.5f); } @@ -1945,20 +1887,17 @@ int32_t mame_ui_manager::slider_yscale(running_machine &machine, void *arg, int // slider callback //------------------------------------------------- -int32_t mame_ui_manager::slider_xoffset(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_xoffset(screen_device &screen, std::string *str, int32_t newval) { - screen_device *screen = reinterpret_cast<screen_device *>(arg); - render_container::user_settings settings; - - screen->container().get_user_settings(settings); + render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_xoffset = (float)newval * 0.001f; - screen->container().set_user_settings(settings); + settings.m_xoffset = float(newval) * 0.001f; + screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_xoffset); - return floor(settings.m_xoffset * 1000.0f + 0.5f); + return floorf(settings.m_xoffset * 1000.0f + 0.5f); } @@ -1967,20 +1906,17 @@ int32_t mame_ui_manager::slider_xoffset(running_machine &machine, void *arg, int // slider callback //------------------------------------------------- -int32_t mame_ui_manager::slider_yoffset(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_yoffset(screen_device &screen, std::string *str, int32_t newval) { - screen_device *screen = reinterpret_cast<screen_device *>(arg); - render_container::user_settings settings; - - screen->container().get_user_settings(settings); + render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_yoffset = (float)newval * 0.001f; - screen->container().set_user_settings(settings); + settings.m_yoffset = float(newval) * 0.001f; + screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_yoffset); - return floor(settings.m_yoffset * 1000.0f + 0.5f); + return floorf(settings.m_yoffset * 1000.0f + 0.5f); } @@ -1989,20 +1925,19 @@ int32_t mame_ui_manager::slider_yoffset(running_machine &machine, void *arg, int // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_overxscale(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_overxscale(laserdisc_device &laserdisc, std::string *str, int32_t newval) { - laserdisc_device *laserdisc = (laserdisc_device *)arg; laserdisc_overlay_config settings; - laserdisc->get_overlay_config(settings); + laserdisc.get_overlay_config(settings); if (newval != SLIDER_NOCHANGE) { - settings.m_overscalex = (float)newval * 0.001f; - laserdisc->set_overlay_config(settings); + settings.m_overscalex = float(newval) * 0.001f; + laserdisc.set_overlay_config(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_overscalex); - return floor(settings.m_overscalex * 1000.0f + 0.5f); + return floorf(settings.m_overscalex * 1000.0f + 0.5f); } @@ -2011,20 +1946,19 @@ int32_t mame_ui_manager::slider_overxscale(running_machine &machine, void *arg, // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_overyscale(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_overyscale(laserdisc_device &laserdisc, std::string *str, int32_t newval) { - laserdisc_device *laserdisc = (laserdisc_device *)arg; laserdisc_overlay_config settings; - laserdisc->get_overlay_config(settings); + laserdisc.get_overlay_config(settings); if (newval != SLIDER_NOCHANGE) { - settings.m_overscaley = (float)newval * 0.001f; - laserdisc->set_overlay_config(settings); + settings.m_overscaley = float(newval) * 0.001f; + laserdisc.set_overlay_config(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_overscaley); - return floor(settings.m_overscaley * 1000.0f + 0.5f); + return floorf(settings.m_overscaley * 1000.0f + 0.5f); } @@ -2033,20 +1967,19 @@ int32_t mame_ui_manager::slider_overyscale(running_machine &machine, void *arg, // slider callback //------------------------------------------------- -int32_t mame_ui_manager::slider_overxoffset(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_overxoffset(laserdisc_device &laserdisc, std::string *str, int32_t newval) { - laserdisc_device *laserdisc = (laserdisc_device *)arg; laserdisc_overlay_config settings; - laserdisc->get_overlay_config(settings); + laserdisc.get_overlay_config(settings); if (newval != SLIDER_NOCHANGE) { - settings.m_overposx = (float)newval * 0.001f; - laserdisc->set_overlay_config(settings); + settings.m_overposx = float(newval) * 0.001f; + laserdisc.set_overlay_config(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_overposx); - return floor(settings.m_overposx * 1000.0f + 0.5f); + return floorf(settings.m_overposx * 1000.0f + 0.5f); } @@ -2055,20 +1988,19 @@ int32_t mame_ui_manager::slider_overxoffset(running_machine &machine, void *arg, // slider callback //------------------------------------------------- -int32_t mame_ui_manager::slider_overyoffset(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_overyoffset(laserdisc_device &laserdisc, std::string *str, int32_t newval) { - laserdisc_device *laserdisc = (laserdisc_device *)arg; laserdisc_overlay_config settings; - laserdisc->get_overlay_config(settings); + laserdisc.get_overlay_config(settings); if (newval != SLIDER_NOCHANGE) { - settings.m_overposy = (float)newval * 0.001f; - laserdisc->set_overlay_config(settings); + settings.m_overposy = float(newval) * 0.001f; + laserdisc.set_overlay_config(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_overposy); - return floor(settings.m_overposy * 1000.0f + 0.5f); + return floorf(settings.m_overposy * 1000.0f + 0.5f); } @@ -2077,13 +2009,13 @@ int32_t mame_ui_manager::slider_overyoffset(running_machine &machine, void *arg, // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_flicker(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_flicker([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_flicker = (float)newval * 0.001f; + vector_options::s_flicker = float(newval) * 0.001f; if (str) *str = string_format(_("%1$1.2f"), vector_options::s_flicker); - return floor(vector_options::s_flicker * 1000.0f + 0.5f); + return floorf(vector_options::s_flicker * 1000.0f + 0.5f); } @@ -2092,13 +2024,13 @@ int32_t mame_ui_manager::slider_flicker(running_machine &machine, void *arg, int // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_beam_width_min(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_beam_width_min([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_beam_width_min = std::min((float)newval * 0.01f, vector_options::s_beam_width_max); + vector_options::s_beam_width_min = std::min(float(newval) * 0.01f, vector_options::s_beam_width_max); if (str != nullptr) *str = string_format(_("%1$1.2f"), vector_options::s_beam_width_min); - return floor(vector_options::s_beam_width_min * 100.0f + 0.5f); + return floorf(vector_options::s_beam_width_min * 100.0f + 0.5f); } @@ -2107,13 +2039,13 @@ int32_t mame_ui_manager::slider_beam_width_min(running_machine &machine, void *a // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_beam_width_max(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_beam_width_max([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_beam_width_max = std::max((float)newval * 0.01f, vector_options::s_beam_width_min); + vector_options::s_beam_width_max = std::max(float(newval) * 0.01f, vector_options::s_beam_width_min); if (str != nullptr) *str = string_format(_("%1$1.2f"), vector_options::s_beam_width_max); - return floor(vector_options::s_beam_width_max * 100.0f + 0.5f); + return floorf(vector_options::s_beam_width_max * 100.0f + 0.5f); } @@ -2122,13 +2054,13 @@ int32_t mame_ui_manager::slider_beam_width_max(running_machine &machine, void *a // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_beam_dot_size(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_beam_dot_size([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_beam_dot_size = std::max((float)newval * 0.01f, 0.1f); + vector_options::s_beam_dot_size = std::max(float(newval) * 0.01f, 0.1f); if (str != nullptr) *str = string_format(_("%1$1.2f"), vector_options::s_beam_dot_size); - return floor(vector_options::s_beam_dot_size * 100.0f + 0.5f); + return floorf(vector_options::s_beam_dot_size * 100.0f + 0.5f); } @@ -2137,13 +2069,13 @@ int32_t mame_ui_manager::slider_beam_dot_size(running_machine &machine, void *ar // callback //------------------------------------------------- -int32_t mame_ui_manager::slider_beam_intensity_weight(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_beam_intensity_weight([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_beam_intensity_weight = (float)newval * 0.001f; + vector_options::s_beam_intensity_weight = float(newval) * 0.001f; if (str != nullptr) *str = string_format(_("%1$1.2f"), vector_options::s_beam_intensity_weight); - return floor(vector_options::s_beam_intensity_weight * 1000.0f + 0.5f); + return floorf(vector_options::s_beam_intensity_weight * 1000.0f + 0.5f); } @@ -2153,15 +2085,13 @@ int32_t mame_ui_manager::slider_beam_intensity_weight(running_machine &machine, //------------------------------------------------- #ifdef MAME_DEBUG -int32_t mame_ui_manager::slider_crossscale(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_crossscale(ioport_field &field, std::string *str, int32_t newval) { - ioport_field *field = (ioport_field *)arg; - if (newval != SLIDER_NOCHANGE) - field->set_crosshair_scale(float(newval) * 0.001); + field.set_crosshair_scale(float(newval) * 0.001); if (str) - *str = string_format((field->crosshair_axis() == CROSSHAIR_AXIS_X) ? _("Crosshair Scale X %1$1.3f") : _("Crosshair Scale Y %1$1.3f"), float(newval) * 0.001f); - return floor(field->crosshair_scale() * 1000.0f + 0.5f); + *str = string_format((field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("Crosshair Scale X %1$1.3f") : _("Crosshair Scale Y %1$1.3f"), float(newval) * 0.001f); + return floorf(field.crosshair_scale() * 1000.0f + 0.5f); } #endif @@ -2172,15 +2102,13 @@ int32_t mame_ui_manager::slider_crossscale(running_machine &machine, void *arg, //------------------------------------------------- #ifdef MAME_DEBUG -int32_t mame_ui_manager::slider_crossoffset(running_machine &machine, void *arg, int id, std::string *str, int32_t newval) +int32_t mame_ui_manager::slider_crossoffset(ioport_field &field, std::string *str, int32_t newval) { - ioport_field *field = (ioport_field *)arg; - if (newval != SLIDER_NOCHANGE) - field->set_crosshair_offset(float(newval) * 0.001f); + field.set_crosshair_offset(float(newval) * 0.001f); if (str) - *str = string_format((field->crosshair_axis() == CROSSHAIR_AXIS_X) ? _("Crosshair Offset X %1$1.3f") : _("Crosshair Offset Y %1$1.3f"), float(newval) * 0.001f); - return field->crosshair_offset(); + *str = string_format((field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("Crosshair Offset X %1$1.3f") : _("Crosshair Offset Y %1$1.3f"), float(newval) * 0.001f); + return field.crosshair_offset(); } #endif @@ -2192,8 +2120,8 @@ int32_t mame_ui_manager::slider_crossoffset(running_machine &machine, void *arg, ui::text_layout mame_ui_manager::create_layout(render_container &container, float width, ui::text_layout::text_justify justify, ui::text_layout::word_wrapping wrap) { // determine scale factors - float yscale = get_line_height(); - float xscale = yscale * machine().render().ui_aspect(&container); + float const yscale = get_line_height(); + float const xscale = yscale * machine().render().ui_aspect(&container); // create the layout return ui::text_layout(*get_font(), xscale, yscale, width, justify, wrap); @@ -2201,26 +2129,6 @@ ui::text_layout mame_ui_manager::create_layout(render_container &container, floa //------------------------------------------------- -// wrap_text -//------------------------------------------------- - -int mame_ui_manager::wrap_text(render_container &container, const char *origs, float x, float y, float origwrapwidth, std::vector<int> &xstart, std::vector<int> &xend, float text_size) -{ - // create the layout - auto layout = create_layout(container, origwrapwidth, ui::text_layout::LEFT, ui::text_layout::WORD); - - // add the text - layout.add_text( - origs, - rgb_t::black(), - rgb_t::black(), - text_size); - - // and get the wrapping info - return layout.get_wrap_info(xstart, xend); -} - -//------------------------------------------------- // draw_textured_box - add primitives to // draw an outlined box with the given // textured background and line color @@ -2239,7 +2147,6 @@ void mame_ui_manager::popup_time_string(int seconds, std::string message) { // extract the text messagebox_poptext = message; - messagebox_backcolor = colors().background_color(); // set a timer m_popup_text_end = osd_ticks() + osd_ticks_per_second() * seconds; @@ -2259,7 +2166,7 @@ void mame_ui_manager::load_ui_options() // parse the file // attempt to open the output file emu_file file(machine().options().ini_path(), OPEN_FLAG_READ); - if (file.open("ui.ini") == osd_file::error::NONE) + if (!file.open("ui.ini")) { try { @@ -2280,11 +2187,10 @@ void mame_ui_manager::save_ui_options() { // attempt to open the output file emu_file file(machine().options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open("ui.ini") == osd_file::error::NONE) + if (!file.open("ui.ini")) { // generate the updated INI - std::string initext = options().output_ini(); - file.puts(initext.c_str()); + file.puts(options().output_ini()); file.close(); } else @@ -2309,13 +2215,13 @@ void mame_ui_manager::save_main_option() // attempt to open the main ini file { emu_file file(machine().options().ini_path(), OPEN_FLAG_READ); - if (file.open(std::string(emulator_info::get_configname()) + ".ini") == osd_file::error::NONE) + if (!file.open(std::string(emulator_info::get_configname()) + ".ini")) { try { options.parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, true); } - catch(options_error_exception &) + catch (options_error_exception &) { osd_printf_error("**Error loading %s.ini**\n", emulator_info::get_configname()); return; @@ -2330,7 +2236,7 @@ void mame_ui_manager::save_main_option() for (const auto &f_entry : machine().options().entries()) { const char *value = f_entry->value(); - if (value && options.exists(f_entry->name()) && strcmp(value, options.value(f_entry->name().c_str()))) + if (value && options.exists(f_entry->name()) && strcmp(value, options.value(f_entry->name()))) { options.set_value(f_entry->name(), *f_entry->value(), OPTION_PRIORITY_CMDLINE); } @@ -2339,26 +2245,54 @@ void mame_ui_manager::save_main_option() // attempt to open the output file { emu_file file(machine().options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(std::string(emulator_info::get_configname()) + ".ini") == osd_file::error::NONE) + if (!file.open(std::string(emulator_info::get_configname()) + ".ini")) { // generate the updated INI - std::string initext = options.output_ini(); - file.puts(initext.c_str()); + file.puts(options.output_ini()); file.close(); } - else { + else + { machine().popmessage(_("**Error saving %s.ini**"), emulator_info::get_configname()); return; } } - popup_time(3, "%s", _("\n Configuration saved \n\n")); + popup_time(3, "%s", _("\n Settings saved \n\n")); } void mame_ui_manager::menu_reset() { - ui::menu::stack_reset(machine()); + ui::menu::stack_reset(*this); } + +//------------------------------------------------- +// get_general_input_setting - get the current +// default setting for an input type (useful for +// prompting the user) +//------------------------------------------------- + +std::string mame_ui_manager::get_general_input_setting(ioport_type type, int player, input_seq_type seqtype) +{ + input_seq seq(machine().ioport().type_seq(type, player, seqtype)); + input_code codes[16]; // TODO: remove magic number + unsigned len(0U); + for (unsigned i = 0U; std::size(codes) > i; ++i) + { + if (input_seq::not_code == seq[i]) + ++i; + else + codes[len++] = seq[i]; + if (input_seq::end_code == seq[i]) + break; + } + seq.reset(); + for (unsigned i = 0U; len > i; ++i) + seq += codes[i]; + return machine().input().seq_name(seq); +} + + void ui_colors::refresh(const ui_options &options) { m_border_color = options.border_color(); |