diff options
92 files changed, 1881 insertions, 658 deletions
diff --git a/docs/source/commandline/commandline-all.rst b/docs/source/commandline/commandline-all.rst index aa91bd6307c..91c69ab8bc1 100644 --- a/docs/source/commandline/commandline-all.rst +++ b/docs/source/commandline/commandline-all.rst @@ -899,22 +899,24 @@ Example: - dinput - xinput - none - - sdl + - sdljoy + - sdlgame * - **SDL** - auto [#JIPAutoSDL]_. - - - - none - - sdl + - sdljoy + - sdlgame .. rubric:: Footnotes .. [#JIPAutoWindows] On Windows, auto will default to ``dinput``. -.. [#JIPAutoSDL] On SDL, auto will default to ``sdl``. +.. [#JIPAutoSDL] On SDL, auto will default to ``sdljoy``. -.. Tip:: Note that Microsoft XBox 360 and XBox One controllers connected to +.. Tip:: Note that Microsoft Xbox 360 and Xbox One controllers connected to Windows will work best with ``winhybrid`` or ``xinput``. The ``winhybrid`` option supports a mix of DirectInput and XInput controllers at the same time. diff --git a/docs/source/commandline/sdlconfig.rst b/docs/source/commandline/sdlconfig.rst index 0b52739e4c3..84f31bf89b9 100644 --- a/docs/source/commandline/sdlconfig.rst +++ b/docs/source/commandline/sdlconfig.rst @@ -70,8 +70,9 @@ SDL Joystick Mapping **-sixaxis** - Use special handling for PlayStation 3 SixAxis controllers. Default is OFF - (**-nosixaxis**) + Use special handling for PlayStation 3 SixAxis controllers. May cause + undesirable behaviour with other controllers. Only affects the ``sdljoy`` + joystick provider. Default is OFF (**-nosixaxis**) SDL Lightgun Mapping diff --git a/docs/source/conf.py b/docs/source/conf.py index 81385340ed9..15884fc9ff9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -63,9 +63,9 @@ copyright = u'1997-2023, MAMEdev and contributors' # built documents. # # The short X.Y version. -version = '0.251' +version = '0.252' # The full version, including alpha/beta/rc tags. -release = '0.251' +release = '0.252' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 32aebcf8eb7..89281b11dd2 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -1013,9 +1013,9 @@ void render_target::set_bounds(s32 width, s32 height, float pixel_aspect) m_width = width; m_height = height; m_bounds.x0 = m_bounds.y0 = 0; - m_bounds.x1 = (float)width; - m_bounds.y1 = (float)height; - m_pixel_aspect = pixel_aspect != 0.0? pixel_aspect : 1.0; + m_bounds.x1 = float(width); + m_bounds.y1 = float(height); + m_pixel_aspect = pixel_aspect != 0.0F ? pixel_aspect : 1.0F; } diff --git a/src/frontend/mame/ui/about.cpp b/src/frontend/mame/ui/about.cpp index 715815399f9..62d0a1c5241 100644 --- a/src/frontend/mame/ui/about.cpp +++ b/src/frontend/mame/ui/about.cpp @@ -64,6 +64,19 @@ menu_about::~menu_about() //------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_about::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu_textbox::recompute_metrics(width, height, aspect); + + // make space for the title and revision + set_custom_space((line_height() * m_header.size()) + (tb_border() * 3.0F), 0.0F); +} + + +//------------------------------------------------- // perform our special rendering //------------------------------------------------- @@ -103,10 +116,8 @@ void menu_about::populate_text(std::optional<text_layout> &layout, float &width, // populate - populates the about modal //------------------------------------------------- -void menu_about::populate(float &customtop, float &custombottom) +void menu_about::populate() { - // make space for the title and revision - customtop = (line_height() * m_header.size()) + (tb_border() * 3.0f); } diff --git a/src/frontend/mame/ui/about.h b/src/frontend/mame/ui/about.h index 13fc8e3e84f..5e394ba5d9e 100644 --- a/src/frontend/mame/ui/about.h +++ b/src/frontend/mame/ui/about.h @@ -29,12 +29,13 @@ public: virtual ~menu_about() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::vector<std::string> const m_header; diff --git a/src/frontend/mame/ui/analogipt.cpp b/src/frontend/mame/ui/analogipt.cpp index 4e3b15aecc8..520026ea479 100644 --- a/src/frontend/mame/ui/analogipt.cpp +++ b/src/frontend/mame/ui/analogipt.cpp @@ -66,6 +66,15 @@ menu_analog::~menu_analog() } +void menu_analog::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + // space for live display + set_custom_space(0.0f, (line_height() * m_visible_fields) + (tb_border() * 3.0f)); +} + + void menu_analog::custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) { // work out how much space to use for field names @@ -331,7 +340,7 @@ void menu_analog::handle(event const *ev) } -void menu_analog::populate(float &customtop, float &custombottom) +void menu_analog::populate() { // loop over input ports if (m_item_data.empty()) @@ -401,7 +410,7 @@ void menu_analog::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); // space for live display - custombottom = (line_height() * m_visible_fields) + (tb_border() * 3.0f); + set_custom_space(0.0f, (line_height() * m_visible_fields) + (tb_border() * 3.0f)); } diff --git a/src/frontend/mame/ui/analogipt.h b/src/frontend/mame/ui/analogipt.h index f6807947ce6..26f2580318a 100644 --- a/src/frontend/mame/ui/analogipt.h +++ b/src/frontend/mame/ui/analogipt.h @@ -27,6 +27,7 @@ public: virtual ~menu_analog() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void menu_activated() override; @@ -66,7 +67,7 @@ private: using item_data_vector = std::vector<item_data>; using field_data_vector = std::vector<field_data>; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void find_fields(); diff --git a/src/frontend/mame/ui/auditmenu.cpp b/src/frontend/mame/ui/auditmenu.cpp index b8656d3163c..bc01cbc4a2a 100644 --- a/src/frontend/mame/ui/auditmenu.cpp +++ b/src/frontend/mame/ui/auditmenu.cpp @@ -74,6 +74,14 @@ menu_audit::~menu_audit() } +void menu_audit::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + set_custom_space(0.0F, (line_height() * 1.0F) + (tb_border() * 3.0F)); +} + + void menu_audit::custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) { switch (m_phase) @@ -107,7 +115,7 @@ void menu_audit::custom_render(void *selectedref, float top, float bottom, float container(), std::move(text).str(), text_layout::text_justify::CENTER, - 0.5f, 0.5f, + 0.5F, 0.5F, ui().colors().background_color()); } break; @@ -120,7 +128,7 @@ void menu_audit::custom_render(void *selectedref, float top, float bottom, float ui().get_general_input_setting(IPT_UI_SELECT), ui().get_general_input_setting(IPT_UI_CANCEL)), text_layout::text_justify::CENTER, - 0.5f, 0.5f, + 0.5F, 0.5F, UI_RED_COLOR); break; } @@ -133,13 +141,12 @@ bool menu_audit::custom_ui_cancel() } -void menu_audit::populate(float &customtop, float &custombottom) +void menu_audit::populate() { if (m_unavailable && (m_availablesorted.size() != m_unavailable)) item_append(util::string_format(_("Audit media for %1$u systems marked unavailable"), m_unavailable), 0, ITEMREF_START_FAST); item_append(util::string_format(_("Audit media for all %1$u systems"), m_availablesorted.size()), 0, ITEMREF_START_FULL); item_append(menu_item_type::SEPARATOR, 0); - custombottom = (line_height() * 1.0f) + (tb_border() * 3.0f); } void menu_audit::handle(event const *ev) diff --git a/src/frontend/mame/ui/auditmenu.h b/src/frontend/mame/ui/auditmenu.h index de42c33b6d1..040316edb5b 100644 --- a/src/frontend/mame/ui/auditmenu.h +++ b/src/frontend/mame/ui/auditmenu.h @@ -29,13 +29,14 @@ public: virtual ~menu_audit() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool custom_ui_cancel() override; private: enum class phase { CONFIRMATION, AUDIT, CANCELLATION }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; bool do_audit(); diff --git a/src/frontend/mame/ui/barcode.cpp b/src/frontend/mame/ui/barcode.cpp index a0e4791dfb6..31dcf768e78 100644 --- a/src/frontend/mame/ui/barcode.cpp +++ b/src/frontend/mame/ui/barcode.cpp @@ -54,7 +54,7 @@ menu_barcode_reader::~menu_barcode_reader() // populate - populates the barcode input menu //------------------------------------------------- -void menu_barcode_reader::populate(float &customtop, float &custombottom) +void menu_barcode_reader::populate() { if (current_device()) { diff --git a/src/frontend/mame/ui/barcode.h b/src/frontend/mame/ui/barcode.h index e171485cf79..5f70fe65276 100644 --- a/src/frontend/mame/ui/barcode.h +++ b/src/frontend/mame/ui/barcode.h @@ -24,7 +24,7 @@ public: virtual ~menu_barcode_reader() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::string m_barcode_buffer; diff --git a/src/frontend/mame/ui/cheatopt.cpp b/src/frontend/mame/ui/cheatopt.cpp index 9aae81134ef..193a3c9efd6 100644 --- a/src/frontend/mame/ui/cheatopt.cpp +++ b/src/frontend/mame/ui/cheatopt.cpp @@ -111,7 +111,7 @@ menu_cheat::menu_cheat(mame_ui_manager &mui, render_container &container) : menu set_process_flags(PROCESS_LR_REPEAT); } -void menu_cheat::populate(float &customtop, float &custombottom) +void menu_cheat::populate() { /* iterate over cheats */ std::string text; diff --git a/src/frontend/mame/ui/cheatopt.h b/src/frontend/mame/ui/cheatopt.h index c01ec151189..ba0f144dbaf 100644 --- a/src/frontend/mame/ui/cheatopt.h +++ b/src/frontend/mame/ui/cheatopt.h @@ -24,7 +24,7 @@ public: virtual ~menu_cheat() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; diff --git a/src/frontend/mame/ui/confswitch.cpp b/src/frontend/mame/ui/confswitch.cpp index f267d7fa725..ffeae2fff38 100644 --- a/src/frontend/mame/ui/confswitch.cpp +++ b/src/frontend/mame/ui/confswitch.cpp @@ -89,7 +89,7 @@ void menu_confswitch::menu_activated() } -void menu_confswitch::populate(float &customtop, float &custombottom) +void menu_confswitch::populate() { // locate relevant fields if necessary if (m_fields.empty()) @@ -320,6 +320,18 @@ menu_settings_dip_switches::~menu_settings_dip_switches() } +void menu_settings_dip_switches::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu_confswitch::recompute_metrics(width, height, aspect); + + set_custom_space( + 0.0f, + m_visible_switch_groups + ? ((m_visible_switch_groups * (DIP_SWITCH_HEIGHT * line_height())) + ((m_visible_switch_groups - 1) * (DIP_SWITCH_SPACING * line_height())) + (tb_border() * 3.0f)) + : 0.0f); +} + + void menu_settings_dip_switches::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) { // catch if no DIP locations have to be drawn @@ -470,10 +482,10 @@ bool menu_settings_dip_switches::custom_mouse_down() } -void menu_settings_dip_switches::populate(float &customtop, float &custombottom) +void menu_settings_dip_switches::populate() { // let the base class add items - menu_confswitch::populate(customtop, custombottom); + menu_confswitch::populate(); // use up to about 70% of height for DIP switch display if (active_switch_groups()) @@ -485,12 +497,12 @@ void menu_settings_dip_switches::populate(float &customtop, float &custombottom) m_visible_switch_groups = unsigned(0.7f / (groupheight + groupspacing)); else m_visible_switch_groups = active_switch_groups(); - custombottom = (m_visible_switch_groups * groupheight) + ((m_visible_switch_groups - 1) * groupspacing) + (tb_border() * 3.0f); + set_custom_space(0.0f, (m_visible_switch_groups * groupheight) + ((m_visible_switch_groups - 1) * groupspacing) + (tb_border() * 3.0f)); } else { m_visible_switch_groups = 0U; - custombottom = 0.0f; + set_custom_space(0.0f, 0.0f); } } diff --git a/src/frontend/mame/ui/confswitch.h b/src/frontend/mame/ui/confswitch.h index 598b0208085..9094fb2dc22 100644 --- a/src/frontend/mame/ui/confswitch.h +++ b/src/frontend/mame/ui/confswitch.h @@ -57,7 +57,7 @@ protected: menu_confswitch(mame_ui_manager &mui, render_container &container, uint32_t type); virtual void menu_activated() override; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; field_vector const &fields() { return m_fields; } switch_group_vector const &switch_groups() { return m_switch_groups; } @@ -82,11 +82,12 @@ public: virtual ~menu_settings_dip_switches() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool custom_mouse_down() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; std::vector<float> m_switch_group_y; unsigned m_visible_switch_groups; diff --git a/src/frontend/mame/ui/custui.cpp b/src/frontend/mame/ui/custui.cpp index 35c8bd29bd1..22740412ff9 100644 --- a/src/frontend/mame/ui/custui.cpp +++ b/src/frontend/mame/ui/custui.cpp @@ -209,7 +209,7 @@ void menu_custom_ui::handle(event const *ev) // populate //------------------------------------------------- -void menu_custom_ui::populate(float &customtop, float &custombottom) +void menu_custom_ui::populate() { uint32_t arrow_flags; item_append(_("Fonts"), 0, (void *)(uintptr_t)FONT_MENU); @@ -498,7 +498,7 @@ void menu_font_ui::handle(event const *ev) // populate //------------------------------------------------- -void menu_font_ui::populate(float &customtop, float &custombottom) +void menu_font_ui::populate() { // set filter arrow uint32_t arrow_flags; @@ -523,8 +523,17 @@ void menu_font_ui::populate(float &customtop, float &custombottom) item_append(_("Infos text size"), string_format("%.2f", m_info_size), arrow_flags, (void *)(uintptr_t)INFOS_SIZE); item_append(menu_item_type::SEPARATOR); +} - custombottom = line_height() + 3.0f * tb_border(); +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_font_ui::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + set_custom_space(0.0f, line_height() + 3.0f * tb_border()); } //------------------------------------------------- @@ -612,7 +621,7 @@ void menu_colors_ui::handle(event const *ev) // populate //------------------------------------------------- -void menu_colors_ui::populate(float &customtop, float &custombottom) +void menu_colors_ui::populate() { item_append(_("color-option", "Normal text"), 0, (void *)(uintptr_t)MUI_TEXT_COLOR); item_append(_("color-option", "Selected color"), 0, (void *)(uintptr_t)MUI_SELECTED_COLOR); @@ -634,8 +643,17 @@ void menu_colors_ui::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); item_append(_("Restore default colors"), 0, (void *)(uintptr_t)MUI_RESTORE); +} + +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_colors_ui::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); - custombottom = line_height() + 3.0f * tb_border(); + set_custom_space(0.0f, line_height() + 3.0f * tb_border()); } //------------------------------------------------- @@ -876,7 +894,7 @@ void menu_rgb_ui::handle(event const *ev) // populate //------------------------------------------------- -void menu_rgb_ui::populate(float &customtop, float &custombottom) +void menu_rgb_ui::populate() { // set filter arrow std::string s_text = std::string(m_search).append("_"); @@ -917,8 +935,17 @@ void menu_rgb_ui::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); item_append(_("Choose from palette"), 0, (void *)(uintptr_t)PALETTE_CHOOSE); item_append(menu_item_type::SEPARATOR); +} + +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_rgb_ui::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); - custombottom = line_height() + 3.0f * tb_border(); + set_custom_space(0.0f, line_height() + 3.0f * tb_border()); } //------------------------------------------------- @@ -1065,7 +1092,7 @@ void menu_palette_sel::handle(event const *ev) // populate //------------------------------------------------- -void menu_palette_sel::populate(float &customtop, float &custombottom) +void menu_palette_sel::populate() { for (unsigned x = 0; x < std::size(s_palette); ++x) item_append(_("color-preset", s_palette[x].first), s_palette[x].second, FLAG_COLOR_BOX, (void *)(uintptr_t)(x + 1)); diff --git a/src/frontend/mame/ui/custui.h b/src/frontend/mame/ui/custui.h index f720318d854..c009a4eccf0 100644 --- a/src/frontend/mame/ui/custui.h +++ b/src/frontend/mame/ui/custui.h @@ -33,7 +33,7 @@ protected: virtual void menu_dismissed() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void find_languages(); @@ -57,11 +57,12 @@ public: menu_font_ui(mame_ui_manager &mui, render_container &container, std::function<void (bool)> &&handler); protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void menu_dismissed() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void list(); @@ -92,6 +93,7 @@ public: menu_colors_ui(mame_ui_manager &mui, render_container &container); protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void menu_dismissed() override; @@ -123,7 +125,7 @@ private: const char *option; }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; s_color_table m_color_table[MUI_RESTORE]; @@ -140,6 +142,7 @@ public: menu_rgb_ui(mame_ui_manager &mui, render_container &container, rgb_t *color, std::string &&title); protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; private: @@ -152,7 +155,7 @@ private: PALETTE_CHOOSE }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void inkey_special(const event *menu_event); @@ -174,7 +177,7 @@ public: menu_palette_sel(mame_ui_manager &mui, render_container &container, rgb_t &_color); private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; static std::pair<const char *, const char *> const s_palette[]; diff --git a/src/frontend/mame/ui/datmenu.cpp b/src/frontend/mame/ui/datmenu.cpp index 2d65f2a8484..47ed1f2ca8f 100644 --- a/src/frontend/mame/ui/datmenu.cpp +++ b/src/frontend/mame/ui/datmenu.cpp @@ -198,10 +198,19 @@ void menu_dats_view::handle(event const *ev) // populate //------------------------------------------------- -void menu_dats_view::populate(float &customtop, float &custombottom) +void menu_dats_view::populate() { - customtop = 2.0f * line_height() + 4.0f * tb_border(); - custombottom = line_height() + 3.0f * tb_border(); +} + +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_dats_view::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu_textbox::recompute_metrics(width, height, aspect); + + set_custom_space(2.0F * line_height() + 4.0F * tb_border(), line_height() + 3.0F * tb_border()); } //------------------------------------------------- @@ -219,10 +228,10 @@ void menu_dats_view::custom_render(void *selectedref, float top, float bottom, f maxwidth = std::max(maxwidth, width); // compute our bounds - float x1 = 0.5f - 0.5f * maxwidth; + float x1 = 0.5F - 0.5F * maxwidth; float x2 = x1 + maxwidth; float y1 = origy1 - top; - float y2 = origy1 - 2.0f * tb_border() - line_height(); + float y2 = origy1 - 2.0F * tb_border() - line_height(); // draw a box ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); @@ -245,13 +254,13 @@ void menu_dats_view::custom_render(void *selectedref, float top, float bottom, f maxwidth += width; } - float space = (1.0f - maxwidth) / (m_items_list.size() * 2); + float space = (1.0F - maxwidth) / (m_items_list.size() * 2); // compute our bounds x1 -= lr_border(); x2 += lr_border(); y1 = y2 + tb_border(); - y2 += line_height() + 2.0f * tb_border(); + y2 += line_height() + 2.0F * tb_border(); // draw a box ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); @@ -283,7 +292,7 @@ void menu_dats_view::custom_render(void *selectedref, float top, float bottom, f ui().draw_text_full( container(), elem.label, - x1, y1, 1.0f, + x1, y1, 1.0F, text_layout::text_justify::LEFT, text_layout::word_wrapping::NEVER, mame_ui_manager::NORMAL, fcolor, bcolor, &width, nullptr, @@ -298,13 +307,13 @@ void menu_dats_view::custom_render(void *selectedref, float top, float bottom, f std::string const revision(util::string_format(_("Revision: %1$s"), m_items_list[m_actual].revision)); width = get_text_width( revision, - 0.0f, 0.0f, 1.0f, + 0.0F, 0.0F, 1.0F, text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE); width += 2 * lr_border(); maxwidth = std::max(origx2 - origx1, width); // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; + x1 = 0.5F - 0.5F * maxwidth; x2 = x1 + maxwidth; y1 = origy2 + tb_border(); y2 = origy2 + bottom; diff --git a/src/frontend/mame/ui/datmenu.h b/src/frontend/mame/ui/datmenu.h index 79b9bd8c1f6..680e4f0f37a 100644 --- a/src/frontend/mame/ui/datmenu.h +++ b/src/frontend/mame/ui/datmenu.h @@ -43,6 +43,7 @@ public: static void add_info_text(text_layout &layout, std::string_view text, rgb_t color, float size = 1.0f); protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool custom_mouse_down() override; @@ -58,7 +59,7 @@ private: std::string revision; }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void get_data(std::string &buffer); diff --git a/src/frontend/mame/ui/devopt.cpp b/src/frontend/mame/ui/devopt.cpp index e03b8da9042..9886c4e941d 100644 --- a/src/frontend/mame/ui/devopt.cpp +++ b/src/frontend/mame/ui/devopt.cpp @@ -355,7 +355,7 @@ void menu_device_config::populate_text(std::optional<text_layout> &layout, float width = layout->actual_width(); } -void menu_device_config::populate(float &customtop, float &custombottom) +void menu_device_config::populate() { } diff --git a/src/frontend/mame/ui/devopt.h b/src/frontend/mame/ui/devopt.h index 74c81a75809..05fef63240b 100644 --- a/src/frontend/mame/ui/devopt.h +++ b/src/frontend/mame/ui/devopt.h @@ -28,7 +28,7 @@ protected: virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; device_slot_interface::slot_option const *const m_option; diff --git a/src/frontend/mame/ui/dirmenu.cpp b/src/frontend/mame/ui/dirmenu.cpp index 252b53a5aae..2f77e98433c 100644 --- a/src/frontend/mame/ui/dirmenu.cpp +++ b/src/frontend/mame/ui/dirmenu.cpp @@ -82,7 +82,7 @@ public: menu_remove_folder(mame_ui_manager &mui, render_container &container, int ref); private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::string m_searchpath; @@ -145,7 +145,7 @@ void menu_remove_folder::handle(event const *ev) // populate menu //------------------------------------------------- -void menu_remove_folder::populate(float &customtop, float &custombottom) +void menu_remove_folder::populate() { int folders_count = 0; for (auto & elem : m_folders) @@ -165,12 +165,13 @@ public: menu_add_change_folder(mame_ui_manager &mui, render_container &container, int ref, bool multipath); protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool custom_ui_cancel() override { return !m_search.empty(); } private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void update_search(); @@ -296,7 +297,7 @@ void menu_add_change_folder::handle(event const *ev) // populate //------------------------------------------------- -void menu_add_change_folder::populate(float &customtop, float &custombottom) +void menu_add_change_folder::populate() { int folders_count = 0; @@ -331,10 +332,18 @@ void menu_add_change_folder::populate(float &customtop, float &custombottom) item_append(name, "[DIR]", 0, (void *)(uintptr_t)++folders_count); item_append(menu_item_type::SEPARATOR); +} + +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_add_change_folder::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); // configure the custom rendering - customtop = 2.0f * line_height() + 3.0f * tb_border(); - custombottom = 1.0f * line_height() + 3.0f * tb_border(); + set_custom_space(2.0f * line_height() + 3.0f * tb_border(), 1.0f * line_height() + 3.0f * tb_border()); } //------------------------------------------------- @@ -431,6 +440,7 @@ public: } protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; private: @@ -440,7 +450,7 @@ private: REMOVE, }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; bool is_multipath(std::string_view folder) const; @@ -492,7 +502,7 @@ void menu_display_actual::handle(event const *ev) // populate //------------------------------------------------- -void menu_display_actual::populate(float &customtop, float &custombottom) +void menu_display_actual::populate() { auto const &folder = f_folders[m_ref]; auto option = ui().options().get_entry(folder.option); @@ -522,7 +532,18 @@ void menu_display_actual::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); - customtop = (m_folders.size() + 1) * line_height() + 6.0f * tb_border(); + set_custom_space((m_folders.size() + 1) * line_height() + 6.0f * tb_border(), 0.0f); +} + +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_display_actual::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + set_custom_space((m_folders.size() + 1) * line_height() + 6.0f * tb_border(), 0.0f); } //------------------------------------------------- @@ -579,7 +600,7 @@ void menu_directory::handle(event const *ev) // populate //------------------------------------------------- -void menu_directory::populate(float &customtop, float &custombottom) +void menu_directory::populate() { for (auto & elem : f_folders) item_append(_("path-option", elem.name), 0, this); // need a non-null reference pointer - value is immaterial diff --git a/src/frontend/mame/ui/dirmenu.h b/src/frontend/mame/ui/dirmenu.h index 644a71ba564..209fb7953fe 100644 --- a/src/frontend/mame/ui/dirmenu.h +++ b/src/frontend/mame/ui/dirmenu.h @@ -31,7 +31,7 @@ public: virtual ~menu_directory() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; diff --git a/src/frontend/mame/ui/filecreate.cpp b/src/frontend/mame/ui/filecreate.cpp index 21622d3d179..341c19545ba 100644 --- a/src/frontend/mame/ui/filecreate.cpp +++ b/src/frontend/mame/ui/filecreate.cpp @@ -74,7 +74,7 @@ menu_confirm_save_as::~menu_confirm_save_as() // populate //------------------------------------------------- -void menu_confirm_save_as::populate(float &customtop, float &custombottom) +void menu_confirm_save_as::populate() { item_append(_("File Already Exists - Override?"), FLAG_DISABLE, nullptr); item_append(menu_item_type::SEPARATOR); @@ -134,14 +134,26 @@ menu_file_create::~menu_file_create() //------------------------------------------------- +// recompute_metrics - recompute metrics +//------------------------------------------------- + +void menu_file_create::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + set_custom_space(line_height() + 3.0F * tb_border(), 0.0F); +} + + +//------------------------------------------------- // custom_render - perform our special rendering //------------------------------------------------- void menu_file_create::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { extra_text_render(top, bottom, origx1, origy1, origx2, origy2, - m_current_directory, - std::string_view()); + m_current_directory, + std::string_view()); } @@ -149,7 +161,7 @@ void menu_file_create::custom_render(void *selectedref, float top, float bottom, // populate - populates the file creator menu //------------------------------------------------- -void menu_file_create::populate(float &customtop, float &custombottom) +void menu_file_create::populate() { std::string buffer; const image_device_format *format; @@ -178,8 +190,6 @@ void menu_file_create::populate(float &customtop, float &custombottom) // finish up the menu item_append(menu_item_type::SEPARATOR); item_append(_("Create"), 0, ITEMREF_CREATE); - - customtop = line_height() + 3.0f * tb_border(); } @@ -263,7 +273,7 @@ menu_select_format::~menu_select_format() // populate //------------------------------------------------- -void menu_select_format::populate(float &customtop, float &custombottom) +void menu_select_format::populate() { item_append(_("Select image format"), FLAG_DISABLE, nullptr); for (unsigned int i = 0; i != m_formats.size(); i++) @@ -322,7 +332,7 @@ menu_select_floppy_init::~menu_select_floppy_init() // populate //------------------------------------------------- -void menu_select_floppy_init::populate(float &customtop, float &custombottom) +void menu_select_floppy_init::populate() { item_append(_("Select initial contents"), FLAG_DISABLE, nullptr); int id = 0; diff --git a/src/frontend/mame/ui/filecreate.h b/src/frontend/mame/ui/filecreate.h index 9d47605f5a7..629bd24f3ec 100644 --- a/src/frontend/mame/ui/filecreate.h +++ b/src/frontend/mame/ui/filecreate.h @@ -31,7 +31,7 @@ public: virtual ~menu_confirm_save_as() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; bool *m_yes; @@ -47,10 +47,11 @@ public: virtual ~menu_file_create() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; bool & m_ok; @@ -71,7 +72,7 @@ public: virtual ~menu_select_format() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // internal state @@ -90,7 +91,7 @@ public: virtual ~menu_select_floppy_init() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // internal state diff --git a/src/frontend/mame/ui/filemngr.cpp b/src/frontend/mame/ui/filemngr.cpp index bbd38a9a411..81540b568b0 100644 --- a/src/frontend/mame/ui/filemngr.cpp +++ b/src/frontend/mame/ui/filemngr.cpp @@ -54,6 +54,18 @@ menu_file_manager::~menu_file_manager() //------------------------------------------------- +// recompute_metrics - recompute metrics +//------------------------------------------------- + +void menu_file_manager::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + set_custom_space(0.0F, line_height() + 3.0F * tb_border()); +} + + +//------------------------------------------------- // custom_render - perform our special rendering //------------------------------------------------- @@ -101,7 +113,7 @@ void menu_file_manager::fill_image_line(device_image_interface *img, std::string // populate //------------------------------------------------- -void menu_file_manager::populate(float &customtop, float &custombottom) +void menu_file_manager::populate() { std::string tmp_inst, tmp_name; @@ -152,8 +164,6 @@ void menu_file_manager::populate(float &customtop, float &custombottom) if (m_warnings.empty() || !missing_mandatory) item_append(m_warnings.empty() ? _("Reset System") : _("Start System"), 0, (void *)1); - - custombottom = line_height() + 3.0f * tb_border(); } diff --git a/src/frontend/mame/ui/filemngr.h b/src/frontend/mame/ui/filemngr.h index 379912c8dfb..a2368e5a959 100644 --- a/src/frontend/mame/ui/filemngr.h +++ b/src/frontend/mame/ui/filemngr.h @@ -30,10 +30,11 @@ public: virtual ~menu_file_manager(); protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void fill_image_line(device_image_interface *img, std::string &instance, std::string &filename); diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp index 182e130dc61..e12beadb8eb 100644 --- a/src/frontend/mame/ui/filesel.cpp +++ b/src/frontend/mame/ui/filesel.cpp @@ -73,6 +73,19 @@ menu_file_selector::~menu_file_selector() //------------------------------------------------- +// recompute_metrics - recompute metrics +//------------------------------------------------- + +void menu_file_selector::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + // set up custom render proc + set_custom_space(line_height() + 3.0F * tb_border(), 0.0F); +} + + +//------------------------------------------------- // custom_render - perform our special rendering //------------------------------------------------- @@ -347,7 +360,7 @@ void menu_file_selector::update_search() // populate //------------------------------------------------- -void menu_file_selector::populate(float &customtop, float &custombottom) +void menu_file_selector::populate() { const file_selector_entry *selected_entry = nullptr; @@ -426,9 +439,6 @@ void menu_file_selector::populate(float &customtop, float &custombottom) // set the selection (if we have one) if (selected_entry) set_selection((void *)selected_entry); - - // set up custom render proc - customtop = line_height() + 3.0f * tb_border(); } @@ -504,7 +514,7 @@ menu_select_rw::~menu_select_rw() // populate //------------------------------------------------- -void menu_select_rw::populate(float &customtop, float &custombottom) +void menu_select_rw::populate() { item_append(_("Select access mode"), FLAG_DISABLE, nullptr); item_append(_("Read-only"), 0, itemref_from_result(result::READONLY)); diff --git a/src/frontend/mame/ui/filesel.h b/src/frontend/mame/ui/filesel.h index 8fa309c2fb9..71b2b17e3ad 100644 --- a/src/frontend/mame/ui/filesel.h +++ b/src/frontend/mame/ui/filesel.h @@ -44,6 +44,7 @@ public: virtual ~menu_file_selector() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool custom_ui_cancel() override { return !m_filename.empty(); } virtual bool custom_mouse_down() override; @@ -82,7 +83,7 @@ private: std::string m_hover_directory; std::string m_filename; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // methods @@ -119,7 +120,7 @@ public: static result result_from_itemref(void *itemref); private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // internal state diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp index 5708a4a832a..174b8bab9e6 100644 --- a/src/frontend/mame/ui/imgcntrl.cpp +++ b/src/frontend/mame/ui/imgcntrl.cpp @@ -184,7 +184,7 @@ void menu_control_device_image::hook_load(const std::string &name) // populate //------------------------------------------------- -void menu_control_device_image::populate(float &customtop, float &custombottom) +void menu_control_device_image::populate() { throw emu_fatalerror("menu_control_device_image::populate: Shouldn't get here!"); } diff --git a/src/frontend/mame/ui/imgcntrl.h b/src/frontend/mame/ui/imgcntrl.h index 66a5ee5f81a..80b4548686a 100644 --- a/src/frontend/mame/ui/imgcntrl.h +++ b/src/frontend/mame/ui/imgcntrl.h @@ -68,7 +68,7 @@ private: std::string m_software_info_name; // methods - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; void test_create(bool &can_create, bool &need_confirm); void load_software_part(); }; diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index ce4999bb0fa..32575133a24 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -548,7 +548,7 @@ void menu_game_info::populate_text(std::optional<text_layout> &layout, float &wi width = layout->actual_width(); } -void menu_game_info::populate(float &customtop, float &custombottom) +void menu_game_info::populate() { } @@ -613,7 +613,7 @@ void menu_warn_info::populate_text(std::optional<text_layout> &layout, float &wi width = layout->actual_width(); } -void menu_warn_info::populate(float &customtop, float &custombottom) +void menu_warn_info::populate() { } @@ -642,7 +642,7 @@ void menu_image_info::menu_activated() reset(reset_options::REMEMBER_POSITION); } -void menu_image_info::populate(float &customtop, float &custombottom) +void menu_image_info::populate() { for (device_image_interface &image : image_interface_enumerator(machine().root_device())) image_info(&image); diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h index 5c8f153d6ae..d36c476c7b5 100644 --- a/src/frontend/mame/ui/info.h +++ b/src/frontend/mame/ui/info.h @@ -100,7 +100,7 @@ protected: virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; @@ -115,7 +115,7 @@ protected: virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; @@ -130,7 +130,7 @@ protected: virtual void menu_activated() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void image_info(device_image_interface *image); }; diff --git a/src/frontend/mame/ui/info_pty.cpp b/src/frontend/mame/ui/info_pty.cpp index 1aadb85deb9..018c3bc9b61 100644 --- a/src/frontend/mame/ui/info_pty.cpp +++ b/src/frontend/mame/ui/info_pty.cpp @@ -26,7 +26,7 @@ menu_pty_info::~menu_pty_info() { } -void menu_pty_info::populate(float &customtop, float &custombottom) +void menu_pty_info::populate() { for (device_pty_interface &pty : pty_interface_enumerator(machine().root_device())) { diff --git a/src/frontend/mame/ui/info_pty.h b/src/frontend/mame/ui/info_pty.h index 16f65435be2..af384a5a92d 100644 --- a/src/frontend/mame/ui/info_pty.h +++ b/src/frontend/mame/ui/info_pty.h @@ -24,7 +24,7 @@ public: virtual ~menu_pty_info() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; diff --git a/src/frontend/mame/ui/inputdevices.cpp b/src/frontend/mame/ui/inputdevices.cpp index 5c1a7a8931a..71d09a0b280 100644 --- a/src/frontend/mame/ui/inputdevices.cpp +++ b/src/frontend/mame/ui/inputdevices.cpp @@ -27,6 +27,7 @@ public: menu_input_device(mame_ui_manager &mui, render_container &container, input_device &device) : menu(mui, container) , m_device(device) + , m_have_analog(false) { set_heading( util::string_format(_("menu-inputdev", "%1$s (%2$s %3$d)"), @@ -36,25 +37,54 @@ public: } protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override + { + menu::recompute_metrics(width, height, aspect); + + set_custom_space(0.0F, (line_height() * (m_have_analog ? 2.0F : 1.0F)) + (tb_border() * 3.0F)); + } + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override { if (selectedref) { + // get the complete token for the highlighted input input_device_item &input = *reinterpret_cast<input_device_item *>(selectedref); + input_code code = input.code(); + if (!machine().input().device_class(m_device.devclass()).multi()) + code.set_device_index(0); + std::string const token = machine().input().code_to_token(code); + + // measure the name of the token string + float const tokenwidth = (std::min)(get_string_width(token) + (gutter_width() * 2.0F), 1.0F); + float const boxwidth = (std::max)(tokenwidth, x2 - x); + rgb_t const fgcolor(ui().colors().text_color()); + + // draw the outer box + ui().draw_outlined_box( + container(), + (1.0F - boxwidth) * 0.5F, y2 + tb_border(), + (1.0F + boxwidth) * 0.5F, y2 + bottom, + ui().colors().background_color()); + + // show the token + draw_text_normal( + token, + (1.0F - boxwidth) * 0.5F, y2 + (tb_border() * 2.0F), boxwidth, + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, + fgcolor); + + // first show the token switch (input.itemclass()) { case ITEM_CLASS_ABSOLUTE: case ITEM_CLASS_RELATIVE: { - // draw the outer box - ui().draw_outlined_box(container(), x, y2 + tb_border(), x2, y2 + bottom, ui().colors().background_color()); - // draw the indicator - rgb_t const fgcolor(ui().colors().text_color()); - float const indleft = x + lr_border(); - float const indright = x2 - lr_border(); - float const indtop = y2 + (tb_border() * 2.0F) + (line_height() * 0.2F); - float const indbottom = y2 + (tb_border() * 2.0F) + (line_height() * 0.8F); + float const indleft = x + gutter_width(); + float const indright = x2 - gutter_width(); + float const indtop = y2 + (tb_border() * 2.0F) + (line_height() * 1.2F); + float const indbottom = y2 + (tb_border() * 2.0F) + (line_height() * 1.8F); float const indcentre = (x + x2) * 0.5F; s32 const value = (input.itemclass() == ITEM_CLASS_ABSOLUTE) ? input.read_as_absolute(ITEM_MODIFIER_NONE) : input.read_as_relative(ITEM_MODIFIER_NONE); if (0 < value) @@ -81,12 +111,11 @@ protected: } private: - virtual void populate(float &customtop, float &custombottom) override + virtual void populate() override { item_append(_("menu-inputdev", "Copy Device ID"), 0U, nullptr); item_append(menu_item_type::SEPARATOR); - bool haveanalog = false; for (input_item_id itemid = ITEM_ID_FIRST_VALID; m_device.maxitem() >= itemid; ++itemid) { input_device_item *const input = m_device.item(itemid); @@ -96,7 +125,7 @@ private: { case ITEM_CLASS_ABSOLUTE: case ITEM_CLASS_RELATIVE: - haveanalog = true; + m_have_analog = true; break; default: break; @@ -107,8 +136,7 @@ private: item_append(menu_item_type::SEPARATOR); - if (haveanalog) - custombottom = line_height() + (tb_border() * 3.0F); + set_custom_space(0.0F, (line_height() * (m_have_analog ? 2.0F : 1.0F)) + (tb_border() * 3.0F)); } virtual void handle(event const *ev) override @@ -148,6 +176,7 @@ private: } input_device &m_device; + bool m_have_analog; }; } // anonymous namespace @@ -166,7 +195,7 @@ menu_input_devices::~menu_input_devices() } -void menu_input_devices::populate(float &customtop, float &custombottom) +void menu_input_devices::populate() { // iterate input device classes and devices within each class bool found = false; diff --git a/src/frontend/mame/ui/inputdevices.h b/src/frontend/mame/ui/inputdevices.h index cb81caaaf47..39d2afda4e5 100644 --- a/src/frontend/mame/ui/inputdevices.h +++ b/src/frontend/mame/ui/inputdevices.h @@ -25,7 +25,7 @@ public: virtual ~menu_input_devices(); private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp index 2fbc8aeb95d..387d3db7423 100644 --- a/src/frontend/mame/ui/inputmap.cpp +++ b/src/frontend/mame/ui/inputmap.cpp @@ -33,7 +33,7 @@ menu_input_groups::~menu_input_groups() { } -void menu_input_groups::populate(float &customtop, float &custombottom) +void menu_input_groups::populate() { // build up the menu item_append(_("User Interface"), 0, (void *)uintptr_t(IPG_UI + 1)); @@ -82,7 +82,7 @@ void menu_input_general::menu_activated() reset(reset_options::REMEMBER_POSITION); } -void menu_input_general::populate(float &customtop, float &custombottom) +void menu_input_general::populate() { if (data.empty()) { @@ -130,7 +130,7 @@ void menu_input_general::populate(float &customtop, float &custombottom) } // populate the menu in a standard fashion - populate_sorted(customtop, custombottom); + populate_sorted(); item_append(menu_item_type::SEPARATOR); } @@ -164,7 +164,7 @@ void menu_input_specific::menu_activated() reset(reset_options::REMEMBER_POSITION); } -void menu_input_specific::populate(float &customtop, float &custombottom) +void menu_input_specific::populate() { if (data.empty()) { @@ -249,7 +249,7 @@ void menu_input_specific::populate(float &customtop, float &custombottom) // populate the menu in a standard fashion if (!data.empty()) - populate_sorted(customtop, custombottom); + populate_sorted(); else item_append(_("[no assignable inputs are enabled]"), FLAG_DISABLE, nullptr); @@ -311,6 +311,16 @@ void menu_input::toggle_none_default(input_seq &selected_seq, input_seq &origina selected_seq.reset(); } + +void menu_input::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + // leave space for showing the input sequence below the menu + set_custom_space(0.0F, 2.0F * line_height() + 3.0F * tb_border()); +} + + void menu_input::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) { if (pollingitem) @@ -554,7 +564,7 @@ void menu_input::handle(event const *ev) // menu from them //------------------------------------------------- -void menu_input::populate_sorted(float &customtop, float &custombottom) +void menu_input::populate_sorted() { const char *nameformat[INPUT_TYPE_TOTAL] = { nullptr }; @@ -608,9 +618,6 @@ void menu_input::populate_sorted(float &customtop, float &custombottom) appendprompt = util::string_format(_("Press %1$s to append\n"), ui().get_general_input_setting(IPT_UI_SELECT)); clearprompt = util::string_format(_("Press %1$s to clear\n"), ui().get_general_input_setting(IPT_UI_CLEAR)); defaultprompt = util::string_format(_("Press %1$s to restore default\n"), ui().get_general_input_setting(IPT_UI_CLEAR)); - - // leave space for showing the input sequence below the menu - custombottom = 2.0f * line_height() + 3.0f * tb_border(); } } // namespace ui diff --git a/src/frontend/mame/ui/inputmap.h b/src/frontend/mame/ui/inputmap.h index c651a8cc3d3..d512b670345 100644 --- a/src/frontend/mame/ui/inputmap.h +++ b/src/frontend/mame/ui/inputmap.h @@ -28,7 +28,7 @@ public: virtual ~menu_input_groups() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; @@ -64,7 +64,10 @@ protected: menu_input(mame_ui_manager &mui, render_container &container); - void populate_sorted(float &customtop, float &custombottom); + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; + virtual void custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) override; + + void populate_sorted(); void toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq); data_vector data; @@ -81,7 +84,6 @@ private: osd_ticks_t modified_ticks; input_seq starting_seq; - virtual void custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) override; virtual void handle(event const *ev) override; virtual void update_input(input_item_data &seqchangeditem) = 0; }; @@ -97,7 +99,7 @@ protected: virtual void menu_activated() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void update_input(input_item_data &seqchangeditem) override; const int group; @@ -114,7 +116,7 @@ protected: virtual void menu_activated() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void update_input(input_item_data &seqchangeditem) override; }; diff --git a/src/frontend/mame/ui/inputopts.cpp b/src/frontend/mame/ui/inputopts.cpp index ff433e72e7e..e4802e8de8f 100644 --- a/src/frontend/mame/ui/inputopts.cpp +++ b/src/frontend/mame/ui/inputopts.cpp @@ -87,7 +87,7 @@ void menu_input_options::menu_activated() } -void menu_input_options::populate(float &customtop, float &custombottom) +void menu_input_options::populate() { bool inputmap, analog, toggle; scan_inputs(machine(), inputmap, analog, toggle); diff --git a/src/frontend/mame/ui/inputopts.h b/src/frontend/mame/ui/inputopts.h index 11432ce5035..7cff7713537 100644 --- a/src/frontend/mame/ui/inputopts.h +++ b/src/frontend/mame/ui/inputopts.h @@ -28,7 +28,7 @@ protected: virtual void menu_activated() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; diff --git a/src/frontend/mame/ui/inputtoggle.cpp b/src/frontend/mame/ui/inputtoggle.cpp index b21cd572c1d..e86d41b7031 100644 --- a/src/frontend/mame/ui/inputtoggle.cpp +++ b/src/frontend/mame/ui/inputtoggle.cpp @@ -35,7 +35,7 @@ void menu_input_toggles::menu_activated() } -void menu_input_toggles::populate(float &customtop, float &custombottom) +void menu_input_toggles::populate() { // find toggle fields if (m_fields.empty()) diff --git a/src/frontend/mame/ui/inputtoggle.h b/src/frontend/mame/ui/inputtoggle.h index 7a3016f6254..b4d48908d96 100644 --- a/src/frontend/mame/ui/inputtoggle.h +++ b/src/frontend/mame/ui/inputtoggle.h @@ -31,7 +31,7 @@ protected: virtual void menu_activated() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::vector<std::reference_wrapper<ioport_field> > m_fields; diff --git a/src/frontend/mame/ui/keyboard.cpp b/src/frontend/mame/ui/keyboard.cpp index 7efebefd64c..931ff96f046 100644 --- a/src/frontend/mame/ui/keyboard.cpp +++ b/src/frontend/mame/ui/keyboard.cpp @@ -35,7 +35,7 @@ void menu_keyboard_mode::menu_activated() reset(reset_options::REMEMBER_POSITION); } -void menu_keyboard_mode::populate(float &customtop, float &custombottom) +void menu_keyboard_mode::populate() { natural_keyboard &natkbd(machine().natkeyboard()); diff --git a/src/frontend/mame/ui/keyboard.h b/src/frontend/mame/ui/keyboard.h index 36371f5711c..478d97a5a11 100644 --- a/src/frontend/mame/ui/keyboard.h +++ b/src/frontend/mame/ui/keyboard.h @@ -27,7 +27,7 @@ protected: virtual void menu_activated() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index 0ef893dfd1c..7d53266e65b 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -108,7 +108,7 @@ void menu_main::menu_activated() populate - populate main menu items -------------------------------------------------*/ -void menu_main::populate(float &customtop, float &custombottom) +void menu_main::populate() { m_phase = machine().phase(); diff --git a/src/frontend/mame/ui/mainmenu.h b/src/frontend/mame/ui/mainmenu.h index 6671dd9f554..de596716da6 100644 --- a/src/frontend/mame/ui/mainmenu.h +++ b/src/frontend/mame/ui/mainmenu.h @@ -28,7 +28,7 @@ protected: virtual void menu_activated() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; machine_phase m_phase; diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp index ba5767c794a..69e75563985 100644 --- a/src/frontend/mame/ui/menu.cpp +++ b/src/frontend/mame/ui/menu.cpp @@ -374,6 +374,18 @@ void menu::item_append_on_off(const std::string &text, bool state, uint32_t flag //------------------------------------------------- +// set_custom_space - set space required for +// custom rendering above and below menu +//------------------------------------------------- + +void menu::set_custom_space(float top, float bottom) +{ + m_customtop = top; + m_custombottom = bottom; +} + + +//------------------------------------------------- // process - process a menu, drawing it // and returning any interesting events //------------------------------------------------- @@ -1260,7 +1272,7 @@ void menu::do_handle() item_append(_("Return to Previous Menu"), 0, nullptr); // let implementation add other items - populate(m_customtop, m_custombottom); + populate(); } catch (...) { diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h index 85a2f935d86..4126fa66cb5 100644 --- a/src/frontend/mame/ui/menu.h +++ b/src/frontend/mame/ui/menu.h @@ -70,6 +70,9 @@ public: void item_append(menu_item_type type, uint32_t flags = 0); void item_append_on_off(const std::string &text, bool state, uint32_t flags, void *ref, menu_item_type type = menu_item_type::UNKNOWN); + // set space required for drawing extra content + void set_custom_space(float top, float bottom); + // reset the menus, clearing everything static void stack_reset(mame_ui_manager &ui) { get_global_state(ui).stack_reset(); } @@ -422,7 +425,7 @@ private: void set_special_main_menu(bool disable); // to be implemented in derived classes - virtual void populate(float &customtop, float &custombottom) = 0; + virtual void populate() = 0; // to be implemented in derived classes virtual void handle(event const *ev) = 0; diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index 057df11e17d..9839d59a966 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -54,7 +54,7 @@ menu_bios_selection::menu_bios_selection(mame_ui_manager &mui, render_container set_heading(_("BIOS Selection")); } -void menu_bios_selection::populate(float &customtop, float &custombottom) +void menu_bios_selection::populate() { // cycle through all devices for this system for (device_t &device : device_enumerator(machine().root_device())) @@ -159,7 +159,7 @@ menu_network_devices::~menu_network_devices() network device menu -------------------------------------------------*/ -void menu_network_devices::populate(float &customtop, float &custombottom) +void menu_network_devices::populate() { /* cycle through all devices for this system */ for (device_network_interface &network : network_interface_enumerator(machine().root_device())) @@ -268,7 +268,7 @@ void menu_bookkeeping::populate_text(std::optional<text_layout> &layout, float & width = layout->actual_width(); } -void menu_bookkeeping::populate(float &customtop, float &custombottom) +void menu_bookkeeping::populate() { } @@ -397,7 +397,7 @@ menu_crosshair::menu_crosshair(mame_ui_manager &mui, render_container &container set_heading(_("menu-crosshair", "Crosshair Options")); } -void menu_crosshair::populate(float &customtop, float &custombottom) +void menu_crosshair::populate() { if (m_data.empty()) { @@ -701,7 +701,7 @@ void menu_export::handle(event const *ev) // populate //------------------------------------------------- -void menu_export::populate(float &customtop, float &custombottom) +void menu_export::populate() { // add options items item_append(_("Export list in XML format (like -listxml)"), 0, (void *)(uintptr_t)1); @@ -811,7 +811,7 @@ void menu_machine_configure::handle(event const *ev) // populate //------------------------------------------------- -void menu_machine_configure::populate(float &customtop, float &custombottom) +void menu_machine_configure::populate() { // add options items item_append(_("BIOS"), FLAG_DISABLE | FLAG_UI_HEADING, nullptr); @@ -930,7 +930,7 @@ void menu_plugins_configure::handle(event const *ev) // populate //------------------------------------------------- -void menu_plugins_configure::populate(float &customtop, float &custombottom) +void menu_plugins_configure::populate() { plugin_options const &plugins = mame_machine_manager::instance()->plugins(); diff --git a/src/frontend/mame/ui/miscmenu.h b/src/frontend/mame/ui/miscmenu.h index 22a2d1dc135..ab763b7ed26 100644 --- a/src/frontend/mame/ui/miscmenu.h +++ b/src/frontend/mame/ui/miscmenu.h @@ -33,7 +33,7 @@ public: virtual ~menu_network_devices(); private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; @@ -48,7 +48,7 @@ protected: virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; attotime prevtime; @@ -81,7 +81,7 @@ private: std::string next_name; }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::vector<crosshair_item_data> m_data; @@ -96,7 +96,7 @@ public: virtual ~menu_bios_selection(); private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; @@ -112,7 +112,7 @@ public: virtual ~menu_export(); private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::vector<const game_driver*> m_list; @@ -148,7 +148,7 @@ private: LAST = ADVANCED }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void setup_bios(); @@ -174,7 +174,7 @@ public: virtual ~menu_plugins_configure(); protected: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; diff --git a/src/frontend/mame/ui/optsmenu.cpp b/src/frontend/mame/ui/optsmenu.cpp index bc9757a44a4..91e5fb52adb 100644 --- a/src/frontend/mame/ui/optsmenu.cpp +++ b/src/frontend/mame/ui/optsmenu.cpp @@ -71,7 +71,7 @@ void menu_simple_game_options::handle(event const *ev) // populate //------------------------------------------------- -void menu_simple_game_options::populate(float &customtop, float &custombottom) +void menu_simple_game_options::populate() { item_append(_(submenu::video_options()[0].description), 0, (void *)(uintptr_t)DISPLAY_MENU); item_append(_("Sound Options"), 0, (void *)(uintptr_t)SOUND_MENU); @@ -85,8 +85,6 @@ void menu_simple_game_options::populate(float &customtop, float &custombottom) item_append(_("Input Devices"), 0, (void *)(uintptr_t)INPUTDEV_MENU); item_append(menu_item_type::SEPARATOR); item_append(_("Save Settings"), 0, (void *)(uintptr_t)SAVE_CONFIG); - - custombottom = 2.0f * line_height() + 3.0f * tb_border(); } //------------------------------------------------- @@ -174,7 +172,7 @@ void menu_game_options::handle(event const *ev) // populate //------------------------------------------------- -void menu_game_options::populate(float &customtop, float &custombottom) +void menu_game_options::populate() { // set filter arrow std::string fbuff; @@ -198,7 +196,7 @@ void menu_game_options::populate(float &customtop, float &custombottom) item_append(_("Configure Folders"), 0, (void *)(uintptr_t)CONF_DIR); // add the options that don't relate to the UI - menu_simple_game_options::populate(customtop, custombottom); + menu_simple_game_options::populate(); } //------------------------------------------------- diff --git a/src/frontend/mame/ui/optsmenu.h b/src/frontend/mame/ui/optsmenu.h index b10d6601926..d1779ede52a 100644 --- a/src/frontend/mame/ui/optsmenu.h +++ b/src/frontend/mame/ui/optsmenu.h @@ -29,7 +29,7 @@ public: protected: virtual void handle(event const *ev) override; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; void handle_item_event(event const &menu_event); @@ -63,7 +63,7 @@ public: protected: virtual void handle(event const *ev) override; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; void handle_item_event(event const &menu_event); diff --git a/src/frontend/mame/ui/pluginopt.cpp b/src/frontend/mame/ui/pluginopt.cpp index 08f7f84a752..3ad7a2ec2c3 100644 --- a/src/frontend/mame/ui/pluginopt.cpp +++ b/src/frontend/mame/ui/pluginopt.cpp @@ -35,7 +35,7 @@ menu_plugin::menu_plugin(mame_ui_manager &mui, render_container &container) : set_heading(_("Plugin Options")); } -void menu_plugin::populate(float &customtop, float &custombottom) +void menu_plugin::populate() { for (auto &curplugin : m_plugins) item_append(curplugin, 0, (void *)curplugin.c_str()); @@ -125,7 +125,7 @@ void menu_plugin_opt::handle(event const *ev) } } -void menu_plugin_opt::populate(float &customtop, float &custombottom) +void menu_plugin_opt::populate() { std::vector<std::tuple<std::string, std::string, std::string>> menu_list; std::string flags; diff --git a/src/frontend/mame/ui/pluginopt.h b/src/frontend/mame/ui/pluginopt.h index 15196c1ca2d..3779cf130c2 100644 --- a/src/frontend/mame/ui/pluginopt.h +++ b/src/frontend/mame/ui/pluginopt.h @@ -32,7 +32,7 @@ public: virtual ~menu_plugin(); private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::vector<std::string> &m_plugins; @@ -48,7 +48,7 @@ protected: virtual bool custom_ui_cancel() override { return true; } private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::string const m_menu; diff --git a/src/frontend/mame/ui/quitmenu.cpp b/src/frontend/mame/ui/quitmenu.cpp index bb26f7e6290..29f12143831 100644 --- a/src/frontend/mame/ui/quitmenu.cpp +++ b/src/frontend/mame/ui/quitmenu.cpp @@ -45,7 +45,7 @@ void menu_confirm_quit::custom_render(void *selectedref, float top, float bottom } -void menu_confirm_quit::populate(float &customtop, float &custombottom) +void menu_confirm_quit::populate() { } diff --git a/src/frontend/mame/ui/quitmenu.h b/src/frontend/mame/ui/quitmenu.h index 81ca61e2892..206ef1983ea 100644 --- a/src/frontend/mame/ui/quitmenu.h +++ b/src/frontend/mame/ui/quitmenu.h @@ -27,7 +27,7 @@ protected: virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; diff --git a/src/frontend/mame/ui/selector.cpp b/src/frontend/mame/ui/selector.cpp index 71643f4bf4e..b3a579cd049 100644 --- a/src/frontend/mame/ui/selector.cpp +++ b/src/frontend/mame/ui/selector.cpp @@ -95,7 +95,7 @@ void menu_selector::handle(event const *ev) // populate //------------------------------------------------- -void menu_selector::populate(float &customtop, float &custombottom) +void menu_selector::populate() { set_heading(util::string_format(_("menu-selector", "%1$s - Search: %2$s_"), m_title, m_search)); @@ -124,11 +124,21 @@ void menu_selector::populate(float &customtop, float &custombottom) } item_append(menu_item_type::SEPARATOR); - custombottom = line_height() + 3.0f * tb_border(); m_initial = -1; } //------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_selector::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + set_custom_space(0.0F, line_height() + 3.0F * tb_border()); +} + +//------------------------------------------------- // perform our special rendering //------------------------------------------------- diff --git a/src/frontend/mame/ui/selector.h b/src/frontend/mame/ui/selector.h index 17fdb972343..8d504a42e2d 100644 --- a/src/frontend/mame/ui/selector.h +++ b/src/frontend/mame/ui/selector.h @@ -38,13 +38,14 @@ public: virtual ~menu_selector() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool custom_ui_cancel() override { return !m_search.empty(); } private: enum { VISIBLE_SEARCH_ITEMS = 200 }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void find_matches(const char *str); diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 7b268f7ba97..047e6f6f721 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -135,6 +135,9 @@ void menu_select_game::recompute_metrics(uint32_t width, uint32_t height, float menu_select_launch::recompute_metrics(width, height, aspect); m_icons.clear(); + + // configure the custom rendering + set_custom_space(3.0F * line_height() + 5.0F * tb_border(), 4.0F * line_height() + 3.0F * tb_border()); } @@ -346,7 +349,7 @@ void menu_select_game::handle(event const *ev) // populate //------------------------------------------------- -void menu_select_game::populate(float &customtop, float &custombottom) +void menu_select_game::populate() { for (auto &icon : m_icons) // TODO: why is this here? maybe better on resize or setting change? icon.second.texture.reset(); @@ -468,10 +471,6 @@ void menu_select_game::populate(float &customtop, float &custombottom) m_skip_main_items = 0; } - // configure the custom rendering - customtop = 3.0f * line_height() + 5.0f * tb_border(); - custombottom = 4.0f * line_height() + 3.0f * tb_border(); - // reselect prior game launched, if any if (old_item_selected != -1) { diff --git a/src/frontend/mame/ui/selgame.h b/src/frontend/mame/ui/selgame.h index 1f28052ff88..af1dad248ac 100644 --- a/src/frontend/mame/ui/selgame.h +++ b/src/frontend/mame/ui/selgame.h @@ -58,7 +58,7 @@ private: static bool s_first_start; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // drawing diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index 7cceaa6ccb8..f24eb7b3581 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -172,7 +172,7 @@ public: virtual ~software_parts() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; ui_software_info const &m_uiinfo; @@ -189,7 +189,7 @@ public: private: bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, void const *driver, bool software, bool inlist); - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; void const *m_driver; @@ -280,7 +280,7 @@ menu_select_launch::software_parts::~software_parts() // populate //------------------------------------------------- -void menu_select_launch::software_parts::populate(float &customtop, float &custombottom) +void menu_select_launch::software_parts::populate() { std::vector<s_parts::const_iterator> parts; parts.reserve(m_parts.size()); @@ -350,7 +350,7 @@ menu_select_launch::bios_selection::~bios_selection() // populate //------------------------------------------------- -void menu_select_launch::bios_selection::populate(float &customtop, float &custombottom) +void menu_select_launch::bios_selection::populate() { for (auto &elem : m_bios) item_append(elem.first, 0, (void *)&elem.first); diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index 56590e9e7ee..50822545dd1 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -526,6 +526,18 @@ void menu_select_software::handle(event const *ev) } //------------------------------------------------- +// recompute_metrics +//------------------------------------------------- + +void menu_select_software::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu_select_launch::recompute_metrics(width, height, aspect); + + // configure the custom rendering + set_custom_space(4.0F * line_height() + 5.0F * tb_border(), 4.0F * line_height() + 4.0F * tb_border()); +} + +//------------------------------------------------- // menu_deactivated //------------------------------------------------- @@ -545,7 +557,7 @@ void menu_select_software::menu_deactivated() // populate //------------------------------------------------- -void menu_select_software::populate(float &customtop, float &custombottom) +void menu_select_software::populate() { for (auto &icon : m_data->icons()) // TODO: why is this here? maybe better on resize or setting change? icon.second.texture.reset(); @@ -605,10 +617,7 @@ void menu_select_software::populate(float &customtop, float &custombottom) m_displaylist[curitem].get().parentname.empty() ? 0 : FLAG_INVERT, (void *)&m_displaylist[curitem].get()); } - // configure the custom rendering m_skip_main_items = 0; - customtop = 4.0f * line_height() + 5.0f * tb_border(); - custombottom = 4.0f * line_height() + 4.0f * tb_border(); if (old_software != -1) { diff --git a/src/frontend/mame/ui/selsoft.h b/src/frontend/mame/ui/selsoft.h index 4b22ebc6eaf..1ac874ac93a 100644 --- a/src/frontend/mame/ui/selsoft.h +++ b/src/frontend/mame/ui/selsoft.h @@ -33,6 +33,8 @@ public: virtual ~menu_select_software() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; + virtual void menu_deactivated() override; private: @@ -42,7 +44,7 @@ private: struct search_item; class machine_data; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // drawing diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp index be3e056c97f..9fd0b5bb177 100644 --- a/src/frontend/mame/ui/simpleselgame.cpp +++ b/src/frontend/mame/ui/simpleselgame.cpp @@ -236,7 +236,7 @@ void simple_menu_select_game::inkey_special(const event &menu_event) // populate - populate the game select menu //------------------------------------------------- -void simple_menu_select_game::populate(float &customtop, float &custombottom) +void simple_menu_select_game::populate() { int matchcount; int curitem; @@ -282,10 +282,19 @@ void simple_menu_select_game::populate(float &customtop, float &custombottom) { item_append(_("Return to Previous Menu"), 0, nullptr); } +} + + +//------------------------------------------------- +// recompute_metrics - recompute metrics +//------------------------------------------------- + +void simple_menu_select_game::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); // configure the custom rendering - customtop = line_height() + 3.0f * tb_border(); - custombottom = 4.0f * line_height() + 3.0f * tb_border(); + set_custom_space(line_height() + 3.0f * tb_border(), 4.0f * line_height() + 3.0f * tb_border()); } diff --git a/src/frontend/mame/ui/simpleselgame.h b/src/frontend/mame/ui/simpleselgame.h index e5ea310c7ec..4f1effa4305 100644 --- a/src/frontend/mame/ui/simpleselgame.h +++ b/src/frontend/mame/ui/simpleselgame.h @@ -29,13 +29,14 @@ public: static void force_game_select(mame_ui_manager &mui, render_container &container); protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool custom_ui_cancel() override { return !m_search.empty(); } private: enum { VISIBLE_GAMES_IN_LIST = 15 }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // internal methods diff --git a/src/frontend/mame/ui/sliders.cpp b/src/frontend/mame/ui/sliders.cpp index e95789500ca..e162ebeee1a 100644 --- a/src/frontend/mame/ui/sliders.cpp +++ b/src/frontend/mame/ui/sliders.cpp @@ -160,7 +160,7 @@ void menu_sliders::handle(event const *ev) // menu //------------------------------------------------- -void menu_sliders::populate(float &customtop, float &custombottom) +void menu_sliders::populate() { std::string tempstring; @@ -224,8 +224,18 @@ void menu_sliders::populate(float &customtop, float &custombottom) if (ref) set_selection(ref); } +} + + +//------------------------------------------------- +// recompute_metrics - recompute metrics +//------------------------------------------------- + +void menu_sliders::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); - custombottom = 2.0f * line_height() + 2.0f * tb_border(); + set_custom_space(0.0f, 2.0f * line_height() + 2.0f * tb_border()); } diff --git a/src/frontend/mame/ui/sliders.h b/src/frontend/mame/ui/sliders.h index 99a5c6e9cfb..645169189cc 100644 --- a/src/frontend/mame/ui/sliders.h +++ b/src/frontend/mame/ui/sliders.h @@ -25,12 +25,13 @@ public: virtual ~menu_sliders() override; protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void menu_activated() override; virtual void menu_deactivated() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; bool const m_menuless_mode; diff --git a/src/frontend/mame/ui/slotopt.cpp b/src/frontend/mame/ui/slotopt.cpp index f1419122f98..1b30b6120c1 100644 --- a/src/frontend/mame/ui/slotopt.cpp +++ b/src/frontend/mame/ui/slotopt.cpp @@ -171,7 +171,7 @@ bool menu_slot_devices::try_refresh_current_options() // populate //------------------------------------------------- -void menu_slot_devices::populate(float &customtop, float &custombottom) +void menu_slot_devices::populate() { // we need to keep our own copy of the machine_config because we // can change this out from under the caller @@ -202,9 +202,19 @@ void menu_slot_devices::populate(float &customtop, float &custombottom) } item_append(menu_item_type::SEPARATOR); item_append(_("Reset System"), 0, ITEMREF_RESET); +} + + +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void menu_slot_devices::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); // leave space for the name of the current option at the bottom - custombottom = line_height() + 3.0f * tb_border(); + set_custom_space(0.0F, line_height() + 3.0F * tb_border()); } diff --git a/src/frontend/mame/ui/slotopt.h b/src/frontend/mame/ui/slotopt.h index 449d22627aa..6dae4ce062a 100644 --- a/src/frontend/mame/ui/slotopt.h +++ b/src/frontend/mame/ui/slotopt.h @@ -25,6 +25,10 @@ public: menu_slot_devices(mame_ui_manager &mui, render_container &container); virtual ~menu_slot_devices() override; +protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; + virtual void custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) override; + private: enum class step_t { @@ -32,8 +36,7 @@ private: PREVIOUS }; - virtual void populate(float &customtop, float &custombottom) override; - virtual void custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) override; + virtual void populate() override; virtual void handle(event const *ev) override; device_slot_interface::slot_option const *get_current_option(device_slot_interface &slot) const; diff --git a/src/frontend/mame/ui/sndmenu.cpp b/src/frontend/mame/ui/sndmenu.cpp index 136cbcf98f4..f389c128c07 100644 --- a/src/frontend/mame/ui/sndmenu.cpp +++ b/src/frontend/mame/ui/sndmenu.cpp @@ -139,7 +139,7 @@ void menu_sound_options::handle(event const *ev) // populate //------------------------------------------------- -void menu_sound_options::populate(float &customtop, float &custombottom) +void menu_sound_options::populate() { uint32_t arrow_flags = get_arrow_flags(uint16_t(0), uint16_t(std::size(m_sound_rate) - 1), m_cur_rates); m_sample_rate = m_sound_rate[m_cur_rates]; diff --git a/src/frontend/mame/ui/sndmenu.h b/src/frontend/mame/ui/sndmenu.h index 48d85b7d1a5..6e79d4f6faa 100644 --- a/src/frontend/mame/ui/sndmenu.h +++ b/src/frontend/mame/ui/sndmenu.h @@ -38,7 +38,7 @@ private: ENABLE_SAMPLES }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; uint16_t m_cur_rates; diff --git a/src/frontend/mame/ui/state.cpp b/src/frontend/mame/ui/state.cpp index 3e3c460f203..49412c8a244 100644 --- a/src/frontend/mame/ui/state.cpp +++ b/src/frontend/mame/ui/state.cpp @@ -118,7 +118,7 @@ menu_load_save_state_base::~menu_load_save_state_base() // populate //------------------------------------------------- -void menu_load_save_state_base::populate(float &customtop, float &custombottom) +void menu_load_save_state_base::populate() { // build the "filename to code" map, if we have not already (if it were not for the // possibility that the system keyboard can be changed at runtime, I would put this @@ -224,9 +224,6 @@ void menu_load_save_state_base::populate(float &customtop, float &custombottom) if (is_one_shot()) item_append(_("Cancel"), 0, nullptr); - // set up custom render proc - custombottom = (2.0f * line_height()) + (3.0f * tb_border()); - // get ready to poll inputs m_switch_poller.reset(); m_keys_released = false; @@ -421,6 +418,19 @@ void menu_load_save_state_base::handle_keys(uint32_t flags, int &iptkey) //------------------------------------------------- +// recompute_metrics - recompute metrics +//------------------------------------------------- + +void menu_load_save_state_base::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + autopause_menu<>::recompute_metrics(width, height, aspect); + + // set up custom render proc + set_custom_space(0.0F, (2.0F * line_height()) + (3.0F * tb_border())); +} + + +//------------------------------------------------- // custom_render - perform our special rendering //------------------------------------------------- @@ -446,14 +456,14 @@ void menu_load_save_state_base::custom_render(void *selectedref, float top, floa { draw_text_box( std::begin(text), std::next(std::begin(text), count), - origx1, origx2, origy2 + tb_border(), origy2 + (count * line_height()) + (3.0f * tb_border()), + origx1, origx2, origy2 + tb_border(), origy2 + (count * line_height()) + (3.0F * tb_border()), text_layout::text_justify::CENTER, text_layout::word_wrapping::NEVER, false, ui().colors().text_color(), ui().colors().background_color()); } // draw the confirmation prompt if necessary if (!m_confirm_prompt.empty()) - ui().draw_text_box(container(), m_confirm_prompt, text_layout::text_justify::CENTER, 0.5f, 0.5f, ui().colors().background_color()); + ui().draw_text_box(container(), m_confirm_prompt, text_layout::text_justify::CENTER, 0.5F, 0.5F, ui().colors().background_color()); } diff --git a/src/frontend/mame/ui/state.h b/src/frontend/mame/ui/state.h index c9594cf25cf..8d982678d7d 100644 --- a/src/frontend/mame/ui/state.h +++ b/src/frontend/mame/ui/state.h @@ -36,9 +36,10 @@ protected: bool must_exist, bool one_shot); + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void handle_keys(uint32_t flags, int &iptkey) override; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; virtual void process_file(std::string &&file_name) = 0; diff --git a/src/frontend/mame/ui/submenu.cpp b/src/frontend/mame/ui/submenu.cpp index 3450504fc4c..82eb23d6a17 100644 --- a/src/frontend/mame/ui/submenu.cpp +++ b/src/frontend/mame/ui/submenu.cpp @@ -285,7 +285,7 @@ void submenu::handle(event const *ev) const char *minimum = sm_option.entry->minimum(); const char *maximum = sm_option.entry->maximum(); f_step = atof(minimum); - if (f_step <= 0.0f) { + if (f_step <= 0.0F) { int pmin = getprecisionchr(minimum); int pmax = getprecisionchr(maximum); tmptxt = '1' + std::string((pmin > pmax) ? pmin : pmax, '0'); @@ -339,7 +339,7 @@ void submenu::handle(event const *ev) // populate //------------------------------------------------- -void submenu::populate(float &customtop, float &custombottom) +void submenu::populate() { // add options for (auto sm_option = m_options.begin(); sm_option < m_options.end(); ++sm_option) @@ -405,7 +405,7 @@ void submenu::populate(float &customtop, float &custombottom) } else { - f_min = 0.0f; + f_min = 0.0F; f_max = std::numeric_limits<float>::max(); } arrow_flags = get_arrow_flags(f_min, f_max, f_cur); @@ -446,7 +446,17 @@ void submenu::populate(float &customtop, float &custombottom) } item_append(menu_item_type::SEPARATOR); - custombottom = ui().get_line_height() + (3.0f * tb_border()); +} + +//------------------------------------------------- +// recompute metrics +//------------------------------------------------- + +void submenu::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + set_custom_space(0.0F, line_height() + (3.0F * tb_border())); } //------------------------------------------------- diff --git a/src/frontend/mame/ui/submenu.h b/src/frontend/mame/ui/submenu.h index fdcbfa2c7c2..c307f220924 100644 --- a/src/frontend/mame/ui/submenu.h +++ b/src/frontend/mame/ui/submenu.h @@ -60,10 +60,11 @@ public: //static std::vector<option> export_options(); protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; std::vector<option> m_options; diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp index 5d3c74f8676..da0ec08cbac 100644 --- a/src/frontend/mame/ui/swlist.cpp +++ b/src/frontend/mame/ui/swlist.cpp @@ -77,7 +77,7 @@ menu_software_parts::~menu_software_parts() // populate //------------------------------------------------- -void menu_software_parts::populate(float &customtop, float &custombottom) +void menu_software_parts::populate() { m_entries.clear(); @@ -243,7 +243,7 @@ void menu_software_list::update_search(void *selectedref) // populate //------------------------------------------------- -void menu_software_list::populate(float &customtop, float &custombottom) +void menu_software_list::populate() { // build up the list of entries for the menu if (m_entrylist.empty()) @@ -368,7 +368,7 @@ menu_software::~menu_software() // populate //------------------------------------------------- -void menu_software::populate(float &customtop, float &custombottom) +void menu_software::populate() { bool have_compatible = false; diff --git a/src/frontend/mame/ui/swlist.h b/src/frontend/mame/ui/swlist.h index b77d8090d7b..ce50ad2cfae 100644 --- a/src/frontend/mame/ui/swlist.h +++ b/src/frontend/mame/ui/swlist.h @@ -43,7 +43,7 @@ private: }; using entry_list = std::list<software_part_menu_entry>; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // variables @@ -88,7 +88,7 @@ private: std::string m_search; bool m_ordered_by_shortname; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; // functions @@ -104,7 +104,7 @@ class menu_software : public menu public: menu_software(mame_ui_manager &mui, render_container &container, const char *interface, software_list_device **result); virtual ~menu_software() override; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; private: diff --git a/src/frontend/mame/ui/tapectrl.cpp b/src/frontend/mame/ui/tapectrl.cpp index 5eb505712a4..f41a52addd5 100644 --- a/src/frontend/mame/ui/tapectrl.cpp +++ b/src/frontend/mame/ui/tapectrl.cpp @@ -56,7 +56,7 @@ menu_tape_control::~menu_tape_control() // populate - populates the main tape control menu //------------------------------------------------- -void menu_tape_control::populate(float &customtop, float &custombottom) +void menu_tape_control::populate() { if (current_device()) { diff --git a/src/frontend/mame/ui/tapectrl.h b/src/frontend/mame/ui/tapectrl.h index 1117e88ef5e..5a7fba62b64 100644 --- a/src/frontend/mame/ui/tapectrl.h +++ b/src/frontend/mame/ui/tapectrl.h @@ -25,7 +25,7 @@ public: virtual ~menu_tape_control() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; static void get_time_string(std::string &dest, cassette_image_device *cassette, int *curpos, int *endpos); diff --git a/src/frontend/mame/ui/textbox.cpp b/src/frontend/mame/ui/textbox.cpp index ac3f7337668..9c6dfded606 100644 --- a/src/frontend/mame/ui/textbox.cpp +++ b/src/frontend/mame/ui/textbox.cpp @@ -92,6 +92,18 @@ void menu_textbox::handle_key(int key) //------------------------------------------------- +// recompute_metrics - recompute metrics +//------------------------------------------------- + +void menu_textbox::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + m_layout = std::nullopt; +} + + +//------------------------------------------------- // custom_mouse_scroll - handle scroll events //------------------------------------------------- diff --git a/src/frontend/mame/ui/textbox.h b/src/frontend/mame/ui/textbox.h index bdbb63f934a..724134a482b 100644 --- a/src/frontend/mame/ui/textbox.h +++ b/src/frontend/mame/ui/textbox.h @@ -31,6 +31,7 @@ protected: virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) = 0; + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; virtual bool custom_mouse_scroll(int lines) override; private: diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp index 6a3d95d2139..aaafd1944ba 100644 --- a/src/frontend/mame/ui/utils.cpp +++ b/src/frontend/mame/ui/utils.cpp @@ -403,7 +403,7 @@ private: ADD_FILTER }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; bool set_filter_type(unsigned pos, typename Base::type n) @@ -529,7 +529,7 @@ void composite_filter_impl_base<Impl, Base, Type>::show_ui( template <class Impl, class Base, typename Base::type Type> -void composite_filter_impl_base<Impl, Base, Type>::menu_configure::populate(float &customtop, float &custombottom) +void composite_filter_impl_base<Impl, Base, Type>::menu_configure::populate() { // add items for each active filter unsigned i = 0; @@ -995,7 +995,7 @@ private: INCLUDE_CLONES }; - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; category_machine_filter &m_parent; @@ -1047,7 +1047,7 @@ void category_machine_filter::show_ui(mame_ui_manager &mui, render_container &co } -void category_machine_filter::menu_configure::populate(float &customtop, float &custombottom) +void category_machine_filter::menu_configure::populate() { inifile_manager const &mgr(mame_machine_manager::instance()->inifile()); unsigned const filecnt(mgr.get_file_count()); diff --git a/src/frontend/mame/ui/videoopt.cpp b/src/frontend/mame/ui/videoopt.cpp index 67881db6cd0..0aafba84d26 100644 --- a/src/frontend/mame/ui/videoopt.cpp +++ b/src/frontend/mame/ui/videoopt.cpp @@ -46,7 +46,7 @@ menu_video_targets::~menu_video_targets() { } -void menu_video_targets::populate(float &customtop, float &custombottom) +void menu_video_targets::populate() { // find the targets for (unsigned targetnum = 0; ; targetnum++) @@ -113,7 +113,7 @@ menu_video_options::~menu_video_options() { } -void menu_video_options::populate(float &customtop, float &custombottom) +void menu_video_options::populate() { uintptr_t ref; diff --git a/src/frontend/mame/ui/videoopt.h b/src/frontend/mame/ui/videoopt.h index b296cad06ab..cea2f231073 100644 --- a/src/frontend/mame/ui/videoopt.h +++ b/src/frontend/mame/ui/videoopt.h @@ -26,7 +26,7 @@ public: virtual ~menu_video_targets() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; }; @@ -38,7 +38,7 @@ public: virtual ~menu_video_options() override; private: - virtual void populate(float &customtop, float &custombottom) override; + virtual void populate() override; virtual void handle(event const *ev) override; render_target &m_target; diff --git a/src/osd/modules/input/input_sdl.cpp b/src/osd/modules/input/input_sdl.cpp index 2c8f604c9a2..94b904d0cf8 100644 --- a/src/osd/modules/input/input_sdl.cpp +++ b/src/osd/modules/input/input_sdl.cpp @@ -18,15 +18,6 @@ // standard sdl header #include <SDL2/SDL.h> -#include <cctype> -// ReSharper disable once CppUnusedIncludeDirective -#include <algorithm> -#include <cstddef> -#include <iterator> -#include <memory> -#include <mutex> -#include <optional> -#include <queue> // MAME headers #include "emu.h" @@ -41,6 +32,14 @@ #include "../../sdl/osdsdl.h" #include "../../sdl/window.h" +#include <algorithm> +#include <cctype> +#include <cstddef> +#include <iterator> +#include <memory> +#include <optional> +#include <tuple> + // winnt.h defines this #ifdef DELETE #undef DELETE @@ -53,6 +52,145 @@ namespace { #define GET_FOCUS_WINDOW(ev) focus_window() //#define GET_FOCUS_WINDOW(ev) window_from_id((ev)->windowID) +char const *const CONTROLLER_AXIS_XBOX[]{ + "LSX", + "LSY", + "RSX", + "RSY", + "LT", + "RT" }; + +[[maybe_unused]] char const *const CONTROLLER_AXIS_PS[]{ + "LSX", + "LSY", + "RSX", + "RSY", + "L2", + "R2" }; + +[[maybe_unused]] char const *const CONTROLLER_AXIS_SWITCH[]{ + "LSX", + "LSY", + "RSX", + "RSY", + "ZL", + "ZR" }; + +char const *const CONTROLLER_BUTTON_XBOX360[]{ + "A", + "B", + "X", + "Y", + "Back", + "Guide", + "Start", + "LSB", + "RSB", + "LB", + "RB", + "D-pad Up", + "D-pad Down", + "D-pad Left", + "D-pad Right", + "Share", + "P1", + "P2", + "P3", + "P4", + "Touchpad" }; + +[[maybe_unused]] char const *const CONTROLLER_BUTTON_XBOXONE[]{ + "A", + "B", + "X", + "Y", + "View", + "Guide", + "Menu", + "LSB", + "RSB", + "LB", + "RB", + "D-pad Up", + "D-pad Down", + "D-pad Left", + "D-pad Right", + "Share", + "P1", + "P2", + "P3", + "P4", + "Touchpad" }; + +[[maybe_unused]] char const *const CONTROLLER_BUTTON_PS3[]{ + "Cross", + "Circle", + "Square", + "Triangle", + "Select", + "PS", + "Start", + "L3", + "R3", + "L1", + "R1", + "D-pad Up", + "D-pad Down", + "D-pad Left", + "D-pad Right", + "Microphone", + "P1", + "P2", + "P3", + "P4", + "Touchpad" }; + +[[maybe_unused]] char const *const CONTROLLER_BUTTON_PS4[]{ + "Cross", + "Circle", + "Square", + "Triangle", + "Share", + "PS", + "Options", + "L3", + "R3", + "L1", + "R1", + "D-pad Up", + "D-pad Down", + "D-pad Left", + "D-pad Right", + "Microphone", + "P1", + "P2", + "P3", + "P4", + "Touchpad" }; + +[[maybe_unused]] char const *const CONTROLLER_BUTTON_SWITCH[]{ + "B", + "A", + "Y", + "Z", + "-", + "Home", + "+", + "LSB", + "RSB", + "L", + "R", + "D-pad Up", + "D-pad Down", + "D-pad Left", + "D-pad Right", + "Capture", + "P1", + "P2", + "P3", + "P4", + "Touchpad" }; + struct key_lookup_table { int code; @@ -326,9 +464,7 @@ key_lookup_table sdl_lookup_table[] = KE(APP2) -{ - -1, "" -} + { -1, "" } }; //============================================================ @@ -615,111 +751,305 @@ public: }; //============================================================ -// sdl_joystick_device +// sdl_joystick_device_base //============================================================ -class sdl_joystick_device : public sdl_device +class sdl_joystick_device_base : public sdl_device { public: - // state information for a joystick - struct sdl_joystick_state + std::optional<std::string> const &serial() const { return m_serial; } + SDL_JoystickID instance() const { return m_instance; } + + bool is_instance(SDL_JoystickID instance) const { return m_instance == instance; } + +protected: + sdl_joystick_device_base( + running_machine &machine, + std::string &&name, + std::string &&id, + input_module &module, + char const *serial) : + sdl_device(machine, std::move(name), std::move(id), DEVICE_CLASS_JOYSTICK, module), + m_instance(-1) { - int32_t axes[MAX_AXES]; - int32_t buttons[MAX_BUTTONS]; - int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; - int32_t balls[MAX_AXES]; - }; + if (serial) + m_serial = serial; + } - struct sdl_api_state + void set_instance(SDL_JoystickID instance) { - SDL_Joystick *device = nullptr; - SDL_Haptic *hapdevice = nullptr; - SDL_JoystickID joystick_id; - std::optional<std::string> serial; - }; + assert(0 > m_instance); + assert(0 <= instance); - sdl_joystick_state joystick; - sdl_api_state sdl_state; + m_instance = instance; + } - sdl_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : - sdl_device(machine, std::move(name), std::move(id), DEVICE_CLASS_JOYSTICK, module), - joystick({{0}}) + void clear_instance() { + m_instance = -1; + } + +private: + std::optional<std::string> m_serial; + SDL_JoystickID m_instance; +}; + +//============================================================ +// sdl_joystick_device +//============================================================ + +class sdl_joystick_device : public sdl_joystick_device_base +{ +public: + sdl_joystick_device( + running_machine &machine, + std::string &&name, + std::string &&id, + input_module &module, + SDL_Joystick *joy, + char const *serial) : + sdl_joystick_device_base( + machine, + std::move(name), + std::move(id), + module, + serial), + m_joystick({{0}}), + m_joydevice(joy), + m_hapdevice(SDL_HapticOpenFromJoystick(joy)) + { + set_instance(SDL_JoystickInstanceID(joy)); + } + + void configure() + { + char tempname[32]; + + // loop over all axes + for (int axis = 0; (axis < MAX_AXES) && (axis < SDL_JoystickNumAxes(m_joydevice)); axis++) + { + input_item_id itemid; + + if (axis < INPUT_MAX_AXIS) + itemid = input_item_id(ITEM_ID_XAXIS + axis); + else if (axis < (INPUT_MAX_AXIS + INPUT_MAX_ADD_ABSOLUTE)) + itemid = input_item_id(ITEM_ID_ADD_ABSOLUTE1 - INPUT_MAX_AXIS + axis); + else + itemid = ITEM_ID_OTHER_AXIS_ABSOLUTE; + + snprintf(tempname, sizeof(tempname), "A%d", axis + 1); + device()->add_item( + tempname, + itemid, + generic_axis_get_state<std::int32_t>, + &m_joystick.axes[axis]); + } + + // loop over all buttons + for (int button = 0; (button < MAX_BUTTONS) && (button < SDL_JoystickNumButtons(m_joydevice)); button++) + { + input_item_id itemid; + + m_joystick.buttons[button] = 0; + + if (button < INPUT_MAX_BUTTONS) + itemid = input_item_id(ITEM_ID_BUTTON1 + button); + else if (button < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH) + itemid = input_item_id(ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + button); + else + itemid = ITEM_ID_OTHER_SWITCH; + + device()->add_item( + default_button_name(button), + itemid, + generic_button_get_state<std::int32_t>, + &m_joystick.buttons[button]); + } + + // loop over all hats + for (int hat = 0; (hat < MAX_HATS) && (hat < SDL_JoystickNumHats(m_joydevice)); hat++) + { + input_item_id itemid; + + snprintf(tempname, sizeof(tempname), "Hat %d Up", hat + 1); + itemid = input_item_id((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1UP + 4 * hat : ITEM_ID_OTHER_SWITCH); + device()->add_item( + tempname, + itemid, + generic_button_get_state<std::int32_t>, + &m_joystick.hatsU[hat]); + + snprintf(tempname, sizeof(tempname), "Hat %d Down", hat + 1); + itemid = input_item_id((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1DOWN + 4 * hat : ITEM_ID_OTHER_SWITCH); + device()->add_item( + tempname, + itemid, + generic_button_get_state<std::int32_t>, + &m_joystick.hatsD[hat]); + + snprintf(tempname, sizeof(tempname), "Hat %d Left", hat + 1); + itemid = input_item_id((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1LEFT + 4 * hat : ITEM_ID_OTHER_SWITCH); + device()->add_item( + tempname, + itemid, + generic_button_get_state<std::int32_t>, + &m_joystick.hatsL[hat]); + + snprintf(tempname, sizeof(tempname), "Hat %d Right", hat + 1); + itemid = input_item_id((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1RIGHT + 4 * hat : ITEM_ID_OTHER_SWITCH); + device()->add_item( + tempname, + itemid, + generic_button_get_state<std::int32_t>, + &m_joystick.hatsR[hat]); + } + + // loop over all (track)balls + for (int ball = 0; (ball < (MAX_AXES / 2)) && (ball < SDL_JoystickNumBalls(m_joydevice)); ball++) + { + int itemid; + + if (ball * 2 < INPUT_MAX_ADD_RELATIVE) + itemid = ITEM_ID_ADD_RELATIVE1 + ball * 2; + else + itemid = ITEM_ID_OTHER_AXIS_RELATIVE; + + snprintf(tempname, sizeof(tempname), "R%d X", ball + 1); + device()->add_item( + tempname, + input_item_id(itemid), + generic_axis_get_state<std::int32_t>, + &m_joystick.balls[ball * 2]); + + snprintf(tempname, sizeof(tempname), "R%d Y", ball + 1); + device()->add_item( + tempname, input_item_id(itemid + 1), + generic_axis_get_state<std::int32_t>, + &m_joystick.balls[ball * 2 + 1]); + } } ~sdl_joystick_device() { - if (sdl_state.device) + if (m_joydevice) { - if (sdl_state.hapdevice) + if (m_hapdevice) { - SDL_HapticClose(sdl_state.hapdevice); - sdl_state.hapdevice = nullptr; + SDL_HapticClose(m_hapdevice); + m_hapdevice = nullptr; } - SDL_JoystickClose(sdl_state.device); - sdl_state.device = nullptr; + SDL_JoystickClose(m_joydevice); + m_joydevice = nullptr; } } - void reset() override + virtual void reset() override { - memset(&joystick, 0, sizeof(joystick)); + memset(&m_joystick, 0, sizeof(m_joystick)); } - void process_event(SDL_Event &sdlevent) override + virtual void process_event(SDL_Event &sdlevent) override { switch (sdlevent.type) { case SDL_JOYAXISMOTION: - joystick.axes[sdlevent.jaxis.axis] = (sdlevent.jaxis.value * 2); + if (sdlevent.jaxis.axis < MAX_AXES) + m_joystick.axes[sdlevent.jaxis.axis] = (sdlevent.jaxis.value * 2); break; case SDL_JOYBALLMOTION: //printf("Ball %d %d\n", sdlevent.jball.xrel, sdlevent.jball.yrel); - joystick.balls[sdlevent.jball.ball * 2] = sdlevent.jball.xrel * osd::INPUT_RELATIVE_PER_PIXEL; - joystick.balls[sdlevent.jball.ball * 2 + 1] = sdlevent.jball.yrel * osd::INPUT_RELATIVE_PER_PIXEL; + if (sdlevent.jball.ball < (MAX_AXES / 2)) + { + m_joystick.balls[sdlevent.jball.ball * 2] = sdlevent.jball.xrel * osd::INPUT_RELATIVE_PER_PIXEL; + m_joystick.balls[sdlevent.jball.ball * 2 + 1] = sdlevent.jball.yrel * osd::INPUT_RELATIVE_PER_PIXEL; + } break; case SDL_JOYHATMOTION: - joystick.hatsU[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_UP) ? 0x80 : 0; - joystick.hatsD[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_DOWN) ? 0x80 : 0; - joystick.hatsL[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_LEFT) ? 0x80 : 0; - joystick.hatsR[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_RIGHT) ? 0x80 : 0; + if (sdlevent.jhat.hat < MAX_HATS) + { + m_joystick.hatsU[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_UP) ? 0x80 : 0; + m_joystick.hatsD[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_DOWN) ? 0x80 : 0; + m_joystick.hatsL[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_LEFT) ? 0x80 : 0; + m_joystick.hatsR[sdlevent.jhat.hat] = (sdlevent.jhat.value & SDL_HAT_RIGHT) ? 0x80 : 0; + } break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: if (sdlevent.jbutton.button < MAX_BUTTONS) - joystick.buttons[sdlevent.jbutton.button] = (sdlevent.jbutton.state == SDL_PRESSED) ? 0x80 : 0; + m_joystick.buttons[sdlevent.jbutton.button] = (sdlevent.jbutton.state == SDL_PRESSED) ? 0x80 : 0; break; case SDL_JOYDEVICEREMOVED: osd_printf_verbose("Joystick: %s [GUID %s] disconnected\n", name(), id()); + clear_instance(); reset(); - if (sdl_state.device) + if (m_joydevice) { - if (sdl_state.hapdevice) + if (m_hapdevice) { - SDL_HapticClose(sdl_state.hapdevice); - sdl_state.hapdevice = nullptr; + SDL_HapticClose(m_hapdevice); + m_hapdevice = nullptr; } - SDL_JoystickClose(sdl_state.device); - sdl_state.device = nullptr; + SDL_JoystickClose(m_joydevice); + m_joydevice = nullptr; } break; } } + + bool has_haptic() const + { + return m_hapdevice != nullptr; + } + + bool reconnect_match(std::string_view g, char const *s) const + { + return + !m_joydevice && + (id() == g) && + ((s && serial() && (*serial() == s)) || (!s && !serial())); + } + + void attach_device(SDL_Joystick *joy) + { + assert(joy); + assert(!m_joydevice); + + set_instance(SDL_JoystickInstanceID(joy)); + m_joydevice = joy; + m_hapdevice = SDL_HapticOpenFromJoystick(joy); + } + +protected: + // state information for a joystick + struct sdl_joystick_state + { + int32_t axes[MAX_AXES]; + int32_t buttons[MAX_BUTTONS]; + int32_t hatsU[MAX_HATS], hatsD[MAX_HATS], hatsL[MAX_HATS], hatsR[MAX_HATS]; + int32_t balls[MAX_AXES]; + }; + + sdl_joystick_state m_joystick; + +private: + SDL_Joystick *m_joydevice; + SDL_Haptic *m_hapdevice; }; +//============================================================ +// sdl_sixaxis_joystick_device +//============================================================ + class sdl_sixaxis_joystick_device : public sdl_joystick_device { public: - sdl_sixaxis_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module) : - sdl_joystick_device(machine, std::move(name), std::move(id), module) - { - } + using sdl_joystick_device::sdl_joystick_device; - void process_event(SDL_Event &sdlevent) override + virtual void process_event(SDL_Event &sdlevent) override { switch (sdlevent.type) { @@ -728,12 +1058,12 @@ public: int const axis = sdlevent.jaxis.axis; if (axis <= 3) { - joystick.axes[sdlevent.jaxis.axis] = (sdlevent.jaxis.value * 2); + m_joystick.axes[sdlevent.jaxis.axis] = (sdlevent.jaxis.value * 2); } else { int const magic = (sdlevent.jaxis.value / 2) + 16384; - joystick.axes[sdlevent.jaxis.axis] = magic; + m_joystick.axes[sdlevent.jaxis.axis] = magic; } } break; @@ -747,13 +1077,315 @@ public: }; //============================================================ +// sdl_game_controller_device +//============================================================ + +class sdl_game_controller_device : public sdl_joystick_device_base +{ +public: + sdl_game_controller_device( + running_machine &machine, + std::string &&name, + std::string &&id, + input_module &module, + SDL_GameController *ctrl, + char const *serial) : + sdl_joystick_device_base( + machine, + std::move(name), + std::move(id), + module, + serial), + m_controller({{0}}), + m_ctrldevice(ctrl) + { + set_instance(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ctrl))); + } + + ~sdl_game_controller_device() + { + if (m_ctrldevice) + { + SDL_GameControllerClose(m_ctrldevice); + m_ctrldevice = nullptr; + } + } + + void configure() + { + char const *const *axisnames = CONTROLLER_AXIS_XBOX; + char const *const *buttonnames = CONTROLLER_BUTTON_XBOX360; +#if SDL_VERSION_ATLEAST(2, 0, 12) + auto const ctrltype = SDL_GameControllerGetType(m_ctrldevice); + switch (ctrltype) + { + case SDL_CONTROLLER_TYPE_UNKNOWN: + osd_printf_verbose("Game Controller: ... unknown type\n", int(ctrltype)); + break; + case SDL_CONTROLLER_TYPE_XBOX360: + osd_printf_verbose("Game Controller: ... Xbox 360 type\n"); + axisnames = CONTROLLER_AXIS_XBOX; + buttonnames = CONTROLLER_BUTTON_XBOX360; + break; + case SDL_CONTROLLER_TYPE_XBOXONE: + osd_printf_verbose("Game Controller: ... Xbox One type\n"); + axisnames = CONTROLLER_AXIS_XBOX; + buttonnames = CONTROLLER_BUTTON_XBOXONE; + break; + case SDL_CONTROLLER_TYPE_PS3: + osd_printf_verbose("Game Controller: ... PlayStation 3 type\n"); + axisnames = CONTROLLER_AXIS_PS; + buttonnames = CONTROLLER_BUTTON_PS3; + break; + case SDL_CONTROLLER_TYPE_PS4: + osd_printf_verbose("Game Controller: ... PlayStation 4 type\n"); + axisnames = CONTROLLER_AXIS_PS; + buttonnames = CONTROLLER_BUTTON_PS4; + break; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + osd_printf_verbose("Game Controller: ... Switch Pro Controller type\n"); + axisnames = CONTROLLER_AXIS_SWITCH; + buttonnames = CONTROLLER_BUTTON_SWITCH; + break; +#if SDL_VERSION_ATLEAST(2, 0, 14) // TODO: support more controller types + //case SDL_CONTROLLER_TYPE_VIRTUAL: + //case SDL_CONTROLLER_TYPE_PS5: + //case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + //case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + //case SDL_CONTROLLER_TYPE_SWITCH_JOYCON_LEFT: + //case SDL_CONTROLLER_TYPE_SWITCH_JOYCON_RIGHT: + //case SDL_CONTROLLER_TYPE_SWITCH_JOYCON_PAIR: +#endif + default: // default to Xbox 360 names + osd_printf_verbose("Game Controller: ... unrecognised type (%d)\n", int(ctrltype)); + break; + } +#endif + + // add axes + std::tuple<SDL_GameControllerAxis, input_item_id, bool> axes[]{ + { SDL_CONTROLLER_AXIS_LEFTX, ITEM_ID_XAXIS, false }, + { SDL_CONTROLLER_AXIS_LEFTY, ITEM_ID_YAXIS, false }, + { SDL_CONTROLLER_AXIS_RIGHTX, ITEM_ID_ZAXIS, false }, + { SDL_CONTROLLER_AXIS_RIGHTY, ITEM_ID_RZAXIS, false }, + { SDL_CONTROLLER_AXIS_TRIGGERLEFT, ITEM_ID_SLIDER1, true }, + { SDL_CONTROLLER_AXIS_TRIGGERRIGHT, ITEM_ID_SLIDER2, true } }; + for (auto [axis, item, buttontest] : axes) + { + bool avail = true; +#if SDL_VERSION_ATLEAST(2, 0, 14) + avail = SDL_GameControllerHasAxis(m_ctrldevice, axis); +#endif + if (avail) + { + auto const binding = SDL_GameControllerGetBindForAxis(m_ctrldevice, axis); + switch (binding.bindType) + { + case SDL_CONTROLLER_BINDTYPE_NONE: + avail = false; + break; + case SDL_CONTROLLER_BINDTYPE_BUTTON: + if (buttontest) + avail = false; + break; + default: + break; + } + } + if (avail) + { + device()->add_item( + axisnames[axis], + item, + generic_axis_get_state<std::int32_t>, + &m_controller.axes[axis]); + } + } + + // add automatically numbered buttons + std::pair<SDL_GameControllerButton, SDL_GameControllerAxis> numberedbuttons[]{ + { SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_INVALID, SDL_CONTROLLER_AXIS_TRIGGERLEFT }, + { SDL_CONTROLLER_BUTTON_INVALID, SDL_CONTROLLER_AXIS_TRIGGERRIGHT }, + { SDL_CONTROLLER_BUTTON_LEFTSTICK, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_RIGHTSTICK, SDL_CONTROLLER_AXIS_INVALID }, +#if SDL_VERSION_ATLEAST(2, 0, 14) + { SDL_CONTROLLER_BUTTON_PADDLE1, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_PADDLE2, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_PADDLE3, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_PADDLE4, SDL_CONTROLLER_AXIS_INVALID }, +#endif + { SDL_CONTROLLER_BUTTON_GUIDE, SDL_CONTROLLER_AXIS_INVALID }, +#if SDL_VERSION_ATLEAST(2, 0, 14) + { SDL_CONTROLLER_BUTTON_MISC1, SDL_CONTROLLER_AXIS_INVALID }, + { SDL_CONTROLLER_BUTTON_TOUCHPAD, SDL_CONTROLLER_AXIS_INVALID }, +#endif + }; + input_item_id button_item = ITEM_ID_BUTTON1; + for (auto [button, axis] : numberedbuttons) + { + bool avail = true; + if (SDL_CONTROLLER_BUTTON_INVALID != button) + { +#if SDL_VERSION_ATLEAST(2, 0, 14) + avail = SDL_GameControllerHasButton(m_ctrldevice, button); +#endif + if (avail) + { + auto const binding = SDL_GameControllerGetBindForButton(m_ctrldevice, button); + switch (binding.bindType) + { + case SDL_CONTROLLER_BINDTYPE_NONE: + avail = false; + break; + default: + break; + } + } + if (avail) + { + device()->add_item( + buttonnames[button], + button_item++, + generic_button_get_state<std::int32_t>, + &m_controller.buttons[button]); + } + } + else + { +#if SDL_VERSION_ATLEAST(2, 0, 14) + avail = SDL_GameControllerHasAxis(m_ctrldevice, axis); +#endif + if (avail) + { + auto const binding = SDL_GameControllerGetBindForAxis(m_ctrldevice, axis); + switch (binding.bindType) + { + case SDL_CONTROLLER_BINDTYPE_BUTTON: + break; + default: + avail = false; + } + } + if (avail) + { + device()->add_item( + axisnames[axis], + button_item++, + [] (void *device_internal, void *item_internal) -> int + { + return (*reinterpret_cast<int32_t const *>(item_internal) <= -16'384) ? 1 : 0; + }, + &m_controller.axes[axis]); + } + } + } + + // add buttons with fixed item IDs + std::pair<SDL_GameControllerButton, input_item_id> fixedbuttons[]{ + { SDL_CONTROLLER_BUTTON_BACK, ITEM_ID_SELECT }, + { SDL_CONTROLLER_BUTTON_START, ITEM_ID_START }, + { SDL_CONTROLLER_BUTTON_DPAD_UP, ITEM_ID_HAT1UP }, + { SDL_CONTROLLER_BUTTON_DPAD_DOWN, ITEM_ID_HAT1DOWN }, + { SDL_CONTROLLER_BUTTON_DPAD_LEFT, ITEM_ID_HAT1LEFT }, + { SDL_CONTROLLER_BUTTON_DPAD_RIGHT, ITEM_ID_HAT1RIGHT } }; + for (auto [button, item] : fixedbuttons) + { + bool avail = true; +#if SDL_VERSION_ATLEAST(2, 0, 14) + avail = SDL_GameControllerHasButton(m_ctrldevice, button); +#endif + if (avail) + { + auto const binding = SDL_GameControllerGetBindForButton(m_ctrldevice, button); + switch (binding.bindType) + { + case SDL_CONTROLLER_BINDTYPE_NONE: + avail = false; + break; + default: + break; + } + } + if (avail) + { + device()->add_item( + buttonnames[button], + item, + generic_button_get_state<std::int32_t>, + &m_controller.buttons[button]); + } + } + } + + virtual void reset() override + { + memset(&m_controller, 0, sizeof(m_controller)); + } + + virtual void process_event(SDL_Event &sdlevent) override + { + switch (sdlevent.type) + { + case SDL_CONTROLLERAXISMOTION: + if (sdlevent.caxis.axis < SDL_CONTROLLER_AXIS_MAX) + { + switch (sdlevent.caxis.axis) + { + case SDL_CONTROLLER_AXIS_TRIGGERLEFT: // MAME wants negative values for triggers + case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: + m_controller.axes[sdlevent.caxis.axis] = -normalize_absolute_axis(sdlevent.caxis.value, -32'767, 32'767); + break; + default: + m_controller.axes[sdlevent.caxis.axis] = normalize_absolute_axis(sdlevent.caxis.value, -32'767, 32'767); + } + } + break; + + case SDL_CONTROLLERBUTTONDOWN: + case SDL_CONTROLLERBUTTONUP: + if (sdlevent.cbutton.button < SDL_CONTROLLER_BUTTON_MAX) + m_controller.buttons[sdlevent.cbutton.button] = (sdlevent.cbutton.state == SDL_PRESSED) ? 0x80 : 0x00; + break; + + case SDL_CONTROLLERDEVICEREMOVED: + osd_printf_verbose("Game Controller: %s [GUID %s] disconnected\n", name(), id()); + clear_instance(); + reset(); + if (m_ctrldevice) + { + SDL_GameControllerClose(m_ctrldevice); + m_ctrldevice = nullptr; + } + break; + } + } + +private: + // state information for a game controller + struct sdl_controller_state + { + int32_t axes[SDL_CONTROLLER_AXIS_MAX]; + int32_t buttons[SDL_CONTROLLER_BUTTON_MAX]; + }; + + sdl_controller_state m_controller; + SDL_GameController *m_ctrldevice; +}; + +//============================================================ // sdl_input_module //============================================================ class sdl_input_module : public input_module_base, public sdl_event_subscriber { public: - sdl_input_module(const char *type) : input_module_base(type, "sdl") + sdl_input_module(char const *type, char const *name) : input_module_base(type, name) { } @@ -804,7 +1436,7 @@ class sdl_keyboard_module : public sdl_input_module keyboard_trans_table * m_key_trans_table; public: sdl_keyboard_module() : - sdl_input_module(OSD_KEYBOARDINPUT_PROVIDER), + sdl_input_module(OSD_KEYBOARDINPUT_PROVIDER, "sdl"), m_key_trans_table(nullptr) { } @@ -936,7 +1568,7 @@ private: class sdl_mouse_module : public sdl_input_module { public: - sdl_mouse_module() : sdl_input_module(OSD_MOUSEINPUT_PROVIDER) + sdl_mouse_module() : sdl_input_module(OSD_MOUSEINPUT_PROVIDER, "sdl") { } @@ -979,16 +1611,11 @@ public: class sdl_joystick_module : public sdl_input_module { -private: - bool m_initialized_joystick; - bool m_initialized_haptic; - bool m_sixaxis_mode; public: sdl_joystick_module() : - sdl_input_module(OSD_JOYSTICKINPUT_PROVIDER), + sdl_input_module(OSD_JOYSTICKINPUT_PROVIDER, "sdljoy"), m_initialized_joystick(false), - m_initialized_haptic(false), - m_sixaxis_mode(false) + m_initialized_haptic(false) { } @@ -997,14 +1624,10 @@ public: sdl_input_module::exit(); if (m_initialized_joystick) - { SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - } if (m_initialized_haptic) - { SDL_QuitSubSystem(SDL_INIT_HAPTIC); - } } virtual void input_init(running_machine &machine) override @@ -1026,9 +1649,7 @@ public: sdl_input_module::input_init(machine); - char tempname[512]; - - m_sixaxis_mode = downcast<const sdl_options *>(options())->sixaxis(); + bool const sixaxis_mode = downcast<const sdl_options *>(options())->sixaxis(); osd_printf_verbose("Joystick: Start initialization\n"); for (int physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++) @@ -1047,9 +1668,9 @@ public: if (serial) id.append(1, '-').append(serial); - sdl_joystick_device *const devinfo = m_sixaxis_mode - ? &devicelist().create_device<sdl_sixaxis_joystick_device>(machine, name ? name : guid_str, guid_str, *this) - : &devicelist().create_device<sdl_joystick_device>(machine, name ? name : guid_str, guid_str, *this); + sdl_joystick_device *const devinfo = sixaxis_mode + ? &devicelist().create_device<sdl_sixaxis_joystick_device>(machine, name ? name : guid_str, guid_str, *this, joy, serial) + : &devicelist().create_device<sdl_joystick_device>(machine, name ? name : guid_str, guid_str, *this, joy, serial); if (!devinfo) { @@ -1057,12 +1678,6 @@ public: continue; } - devinfo->sdl_state.device = joy; - devinfo->sdl_state.joystick_id = SDL_JoystickInstanceID(joy); - devinfo->sdl_state.hapdevice = SDL_HapticOpenFromJoystick(joy); - if (serial) - devinfo->sdl_state.serial = serial; - osd_printf_verbose("Joystick: %s [GUID %s] Vendor ID %04X, Product ID %04X, Revision %04X, Serial %s\n", name ? name : "<nullptr>", guid_str, @@ -1075,80 +1690,14 @@ public: SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy), SDL_JoystickNumBalls(joy)); - if (devinfo->sdl_state.hapdevice) + if (devinfo->has_haptic()) osd_printf_verbose("Joystick: ... Has haptic capability\n"); else osd_printf_verbose("Joystick: ... Does not have haptic capability\n"); - - // loop over all axes - for (int axis = 0; axis < SDL_JoystickNumAxes(joy); axis++) - { - input_item_id itemid; - - if (axis < INPUT_MAX_AXIS) - itemid = (input_item_id)(ITEM_ID_XAXIS + axis); - else if (axis < INPUT_MAX_AXIS + INPUT_MAX_ADD_ABSOLUTE) - itemid = (input_item_id)(ITEM_ID_ADD_ABSOLUTE1 - INPUT_MAX_AXIS + axis); - else - itemid = ITEM_ID_OTHER_AXIS_ABSOLUTE; - - snprintf(tempname, sizeof(tempname), "A%d", axis + 1); - devinfo->device()->add_item(tempname, itemid, generic_axis_get_state<std::int32_t>, &devinfo->joystick.axes[axis]); - } - - // loop over all buttons if (SDL_JoystickNumButtons(joy) > MAX_BUTTONS) osd_printf_verbose("Joystick: ... Has %d buttons which exceeds supported %d buttons\n", SDL_JoystickNumButtons(joy), MAX_BUTTONS); - for (int button = 0; (button < MAX_BUTTONS) && (button < SDL_JoystickNumButtons(joy)); button++) - { - input_item_id itemid; - - devinfo->joystick.buttons[button] = 0; - - if (button < INPUT_MAX_BUTTONS) - itemid = (input_item_id)(ITEM_ID_BUTTON1 + button); - else if (button < INPUT_MAX_BUTTONS + INPUT_MAX_ADD_SWITCH) - itemid = (input_item_id)(ITEM_ID_ADD_SWITCH1 - INPUT_MAX_BUTTONS + button); - else - itemid = ITEM_ID_OTHER_SWITCH; - - devinfo->device()->add_item(default_button_name(button), itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.buttons[button]); - } - - // loop over all hats - for (int hat = 0; hat < SDL_JoystickNumHats(joy); hat++) - { - input_item_id itemid; - - snprintf(tempname, sizeof(tempname), "Hat %d Up", hat + 1); - itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1UP + 4 * hat : ITEM_ID_OTHER_SWITCH); - devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsU[hat]); - snprintf(tempname, sizeof(tempname), "Hat %d Down", hat + 1); - itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1DOWN + 4 * hat : ITEM_ID_OTHER_SWITCH); - devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsD[hat]); - snprintf(tempname, sizeof(tempname), "Hat %d Left", hat + 1); - itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1LEFT + 4 * hat : ITEM_ID_OTHER_SWITCH); - devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsL[hat]); - snprintf(tempname, sizeof(tempname), "Hat %d Right", hat + 1); - itemid = (input_item_id)((hat < INPUT_MAX_HATS) ? ITEM_ID_HAT1RIGHT + 4 * hat : ITEM_ID_OTHER_SWITCH); - devinfo->device()->add_item(tempname, itemid, generic_button_get_state<std::int32_t>, &devinfo->joystick.hatsR[hat]); - } - - // loop over all (track)balls - for (int ball = 0; ball < SDL_JoystickNumBalls(joy); ball++) - { - int itemid; - if (ball * 2 < INPUT_MAX_ADD_RELATIVE) - itemid = ITEM_ID_ADD_RELATIVE1 + ball * 2; - else - itemid = ITEM_ID_OTHER_AXIS_RELATIVE; - - snprintf(tempname, sizeof(tempname), "R%d X", ball + 1); - devinfo->device()->add_item(tempname, (input_item_id)itemid, generic_axis_get_state<std::int32_t>, &devinfo->joystick.balls[ball * 2]); - snprintf(tempname, sizeof(tempname), "R%d Y", ball + 1); - devinfo->device()->add_item(tempname, (input_item_id)(itemid + 1), generic_axis_get_state<std::int32_t>, &devinfo->joystick.balls[ball * 2 + 1]); - } + devinfo->configure(); } static int const event_types[] = { @@ -1186,17 +1735,12 @@ public: [&guid_str, &serial] (auto const &device) { auto &devinfo = downcast<sdl_joystick_device &>(*device); - return - !devinfo.sdl_state.device && - (devinfo.id() == guid_str) && - ((serial && devinfo.sdl_state.serial && (*devinfo.sdl_state.serial == serial)) || (!serial && !devinfo.sdl_state.serial)); + return devinfo.reconnect_match(guid_str, serial); }); if (devicelist().end() != target_device) { auto &devinfo = downcast<sdl_joystick_device &>(**target_device); - devinfo.sdl_state.device = joy; - devinfo.sdl_state.joystick_id = SDL_JoystickInstanceID(joy); - devinfo.sdl_state.hapdevice = SDL_HapticOpenFromJoystick(joy); + devinfo.attach_device(joy); osd_printf_verbose("Joystick: %s [GUID %s] reconnected\n", devinfo.name(), guid_str); } else @@ -1207,10 +1751,10 @@ public: } else { - // Figure out which joystick this event id destined for + // figure out which joystick this event is destined for sdl_joystick_device *const target_device = find_joystick(sdlevent.jdevice.which); // FIXME: this depends on SDL_JoystickID being the same size as Sint32 - // If we find a matching joystick, dispatch the event to the joystick + // if we find a matching joystick, dispatch the event to the joystick if (target_device) target_device->queue_events(&sdlevent, 1); } @@ -1222,11 +1766,128 @@ private: for (auto &ptr : devicelist()) { sdl_joystick_device *const device = downcast<sdl_joystick_device *>(ptr.get()); - if (device->sdl_state.device && (device->sdl_state.joystick_id == instance)) + if (device->is_instance(instance)) return device; } return nullptr; } + + bool m_initialized_joystick; + bool m_initialized_haptic; +}; + + +//============================================================ +// sdl_game_controller_module +//============================================================ + +class sdl_game_controller_module : public sdl_input_module +{ +public: + sdl_game_controller_module() : + sdl_input_module(OSD_JOYSTICKINPUT_PROVIDER, "sdlgame"), + m_initialized_game_controller(false) + { + } + + virtual void exit() override + { + sdl_input_module::exit(); + + if (m_initialized_game_controller) + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + } + + virtual void input_init(running_machine &machine) override + { + m_initialized_game_controller = !SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); + if (!m_initialized_game_controller) + { + osd_printf_error("Could not initialize SDL Game Controller: %s.\n", SDL_GetError()); + return; + } + + sdl_input_module::input_init(machine); + + osd_printf_verbose("Game Controller: Start initialization\n"); + for (int physical_stick = 0; physical_stick < SDL_NumJoysticks(); physical_stick++) + { + if (!SDL_IsGameController(physical_stick)) + continue; + + SDL_GameController *const ctrl = SDL_GameControllerOpen(physical_stick); + char const *const name = SDL_GameControllerName(ctrl); + SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(physical_stick); + char guid_str[256]; + guid_str[0] = '\0'; + SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str) - 1); + char const *serial = nullptr; +#if SDL_VERSION_ATLEAST(2, 0, 14) + serial = SDL_GameControllerGetSerial(ctrl); +#endif + std::string id(guid_str); + if (serial) + id.append(1, '-').append(serial); + + sdl_game_controller_device *const devinfo = &devicelist().create_device<sdl_game_controller_device>( + machine, + name ? name : guid_str, + guid_str, + *this, + ctrl, + serial); + + if (!devinfo) + { + SDL_GameControllerClose(ctrl); + continue; + } + + osd_printf_verbose("Game Controller: %s [GUID %s] Vendor ID %04X, Product ID %04X, Revision %04X, Serial %s\n", + name ? name : "<nullptr>", + guid_str, + SDL_GameControllerGetVendor(ctrl), + SDL_GameControllerGetProduct(ctrl), + SDL_GameControllerGetProductVersion(ctrl), + serial ? serial : "<nullptr>"); + + devinfo->configure(); + } + + static int const event_types[] = { + int(SDL_CONTROLLERAXISMOTION), + int(SDL_CONTROLLERBUTTONDOWN), + int(SDL_CONTROLLERBUTTONUP), + int(SDL_CONTROLLERDEVICEREMOVED) }; + + sdl_event_manager::instance().subscribe(event_types, this); + + osd_printf_verbose("Joystick: End initialization\n"); + } + + virtual void handle_event(SDL_Event &sdlevent) override + { + // figure out which game controller this event is destined for + sdl_game_controller_device *const target_device = find_controller(sdlevent.jdevice.which); // FIXME: this depends on SDL_JoystickID being the same size as Sint32 + + // if we find a matching controller, dispatch the event to the game controller + if (target_device) + target_device->queue_events(&sdlevent, 1); + } + +private: + sdl_game_controller_device *find_controller(SDL_JoystickID instance) + { + for (auto &ptr : devicelist()) + { + sdl_game_controller_device *const device = downcast<sdl_game_controller_device *>(ptr.get()); + if (device->is_instance(instance)) + return device; + } + return nullptr; + } + + bool m_initialized_game_controller; }; } // anonymous namespace @@ -1237,10 +1898,12 @@ private: MODULE_NOT_SUPPORTED(sdl_keyboard_module, OSD_KEYBOARDINPUT_PROVIDER, "sdl") MODULE_NOT_SUPPORTED(sdl_mouse_module, OSD_MOUSEINPUT_PROVIDER, "sdl") -MODULE_NOT_SUPPORTED(sdl_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "sdl") +MODULE_NOT_SUPPORTED(sdl_joystick_module, OSD_JOYSTICKINPUT_PROVIDER, "sdljoy") +MODULE_NOT_SUPPORTED(sdl_game_controller_module, OSD_JOYSTICKINPUT_PROVIDER, "sdlgame") #endif // defined(SDLMAME_SDL2) MODULE_DEFINITION(KEYBOARDINPUT_SDL, sdl_keyboard_module) MODULE_DEFINITION(MOUSEINPUT_SDL, sdl_mouse_module) -MODULE_DEFINITION(JOYSTICKINPUT_SDL, sdl_joystick_module) +MODULE_DEFINITION(JOYSTICKINPUT_SDLJOY, sdl_joystick_module) +MODULE_DEFINITION(JOYSTICKINPUT_SDLGAME, sdl_game_controller_module) diff --git a/src/osd/modules/input/input_sdlcommon.cpp b/src/osd/modules/input/input_sdlcommon.cpp index f0d8a8632f6..7fd13ce2b8f 100644 --- a/src/osd/modules/input/input_sdlcommon.cpp +++ b/src/osd/modules/input/input_sdlcommon.cpp @@ -71,10 +71,10 @@ void sdl_event_manager::process_events(running_machine &machine) auto subscribers = m_subscription_index.equal_range(sdlevent.type); // Dispatch the events - std::for_each(subscribers.first, subscribers.second, [&sdlevent](auto sub) - { - sub.second->handle_event(sdlevent); - }); + std::for_each( + subscribers.first, + subscribers.second, + [&sdlevent] (auto sub) { sub.second->handle_event(sdlevent); }); } } diff --git a/src/osd/modules/input/input_winhybrid.cpp b/src/osd/modules/input/input_winhybrid.cpp index 52d991a9674..5280d42c818 100644 --- a/src/osd/modules/input/input_winhybrid.cpp +++ b/src/osd/modules/input/input_winhybrid.cpp @@ -226,8 +226,6 @@ protected: if (result != DI_OK) fatalerror("DirectInput: Unable to enumerate game controllers (result=%08X)\n", uint32_t(result)); - xinput_joystick_device *devinfo; - // now add all xinput devices if (!m_xinput_detect_failed) { @@ -236,16 +234,9 @@ protected: { XINPUT_STATE state = { 0 }; + // allocate and link in a new device if (m_xinput_helper->xinput_get_state(i, &state) == ERROR_SUCCESS) - { - // allocate and link in a new device - devinfo = m_xinput_helper->create_xinput_device(machine, i, *this); - if (!devinfo) - continue; - - // Configure each gamepad to add buttons and Axes, etc. - devinfo->configure(); - } + m_xinput_helper->create_xinput_device(machine, i, *this); } } } diff --git a/src/osd/modules/input/input_xinput.cpp b/src/osd/modules/input/input_xinput.cpp index e7242a4e38a..fda2b9d8b23 100644 --- a/src/osd/modules/input/input_xinput.cpp +++ b/src/osd/modules/input/input_xinput.cpp @@ -5,6 +5,101 @@ // input_xinput.cpp - XInput API input support for Windows // //============================================================ +/* + +XInput is infamously inflexible. It currently only supports a single +controller type (game controller) with a fixed report format. The +report format includes: +* 16-bit field for single-bit buttons and D-pad directions (two bits + undefined) +* Two 8-bit axis values, used for triggers, pedals, buttons or throttle + and rudder controls, depending on the controller +* Four 16-bit axis values, used for joysticks, steering wheels or hat + switches, depending on the controller + +Some button names have changed at various times: +* Face buttons White and Black became shoulder buttons LB and RB, + respectively. +* Navigation buttons Start and Back became Menu and View, respectively. + +Subtype Gamepad Wheel Arcade stick Arcade pad Flight stick Dance pad Guitar Drum kit + +D-pad D-pad D-pad Joystick D-pad Foot switch D-Pad/Strum D-pad +L trigger Trigger Brake Button Button Rudder Pickup select^ +R trigger Trigger Accelerator Button Button Throttle ^ +L stick X Stick Wheel Roll +L stick Y Stick Pitch +R stick X Stick Hat left/right Whammy bar +R stick Y Stick Hat up/down Orientation + +A Button Button Button Button Primary fire Foot switch Fret 1 Floor tom +B Button Button Button Button Secondary fire Foot switch Fret 2 Snare +X Button Button Button Button Button Foot switch Fret 4 Low tom +Y Button Button Button Button Button Foot switch Fret 3 High tom +LB Button Button Button^ Button Button^ Fret 5 Bass drum +RB Button Button Button^ Button Button^ Button^ Button^ +LSB Button Button^ Button^ Button^ Button^ Fret mod^ Button^ +RSB Button Button^ Button^ Button^ Button^ Button^ Button^ + +^ optional + + +There are multiple physical button layouts for arcade sticks, for +example: + +Gamester Xbox Arcade Stick, Hori Real Arcade Pro EX +LT X Y LB +RT A B RB + +PXN 0082 Arcade Stick +LB X Y RB +LT A B RT + +Mortal Kombat Tournament Edition Arcade Stick + X Y + RT +LB A B + +Hori Fighting Stick EX2 + B X Y +A LT RT + +Hori Real Arcade Pro VX-SA Kai, Razer Atrox + B X Y LB +A LT RT RB + +Hori Real Arcade Pro.V Kai, Mayflash F300, Mayflash F500 + X Y RB LB +A B RT LT + +Mad Catz Brawl Stick + X Y LB LT +A B RB RT + +Arcade pads typically have six face buttons, and come with different +layouts corresponding to the latter two arcade stick layouts, with the +rightmost column on the shoulder buttons. + + +Dance mats usually have this layout: +BK ST +B U A +L R +Y D X + +This layout seems somewhat unusual: +BK ST +A U B +L R +X D Y + +This layout is also available but rare: +BK ST +A U B +L R +Y D X + +*/ #include "modules/osdmodule.h" @@ -17,83 +112,441 @@ // standard windows headers #include <windows.h> +#include <algorithm> +#include <cstdint> +#include <string> +#include <tuple> +#include <utility> + #define XINPUT_LIBRARIES { "xinput1_4.dll", "xinput9_1_0.dll" } -#define XINPUT_AXIS_MINVALUE -32767 -#define XINPUT_AXIS_MAXVALUE 32767 +#define XINPUT_AXIS_MINVALUE (-32'767) +#define XINPUT_AXIS_MAXVALUE (32'767) namespace { -// default axis names -const char *const xinput_axis_name[] = +char const *const AXIS_NAMES_GAMEPAD[]{ + "LSX", + "LSY", + "RSX", + "RSY", + "LT", + "RT" }; + +char const *const AXIS_NAMES_WHEEL[]{ + "Wheel", + "LSY", + "RSX", + "RSY", + "Brake", + "Accelerator" }; + +char const *const AXIS_NAMES_FLIGHT_STICK[]{ + "Joystick X", + "Joystick Y", + nullptr, + nullptr, + "Rudder", + "Throttle" }; + +input_item_id const AXIS_IDS_GAMEPAD[]{ + ITEM_ID_XAXIS, + ITEM_ID_YAXIS, + ITEM_ID_ZAXIS, + ITEM_ID_RZAXIS, + ITEM_ID_SLIDER1, + ITEM_ID_SLIDER2 }; + +input_item_id const AXIS_IDS_FLIGHT_STICK[]{ + ITEM_ID_XAXIS, + ITEM_ID_YAXIS, + ITEM_ID_INVALID, + ITEM_ID_INVALID, + ITEM_ID_RZAXIS, + ITEM_ID_ZAXIS }; + +const char *const HAT_NAMES_GAMEPAD[]{ + "D-pad Up", + "D-pad Down", + "D-pad Left", + "D-pad Right", + "POV Hat Up", + "POV Hat Down", + "POV Hat Left", + "POV Hat Right" }; + +const char *const HAT_NAMES_ARCADE_STICK[]{ + "Joystick Up", + "Joystick Down", + "Joystick Left", + "Joystick Right", + nullptr, + nullptr, + nullptr, + nullptr }; + + +//============================================================ +// xinput_joystick_device +//============================================================ + +class xinput_joystick_device : public device_info { - "LSX", - "LSY", - "RSX", - "RSY" +public: + xinput_joystick_device( + running_machine &machine, + std::string &&name, + std::string &&id, + input_module &module, + uint32_t player, + XINPUT_CAPABILITIES const &caps, + std::shared_ptr<xinput_api_helper> helper); + + void poll() override; + void reset() override; + void configure(); + +private: + static inline constexpr USHORT SWITCH_BITS[] = + { + XINPUT_GAMEPAD_A, + XINPUT_GAMEPAD_B, + XINPUT_GAMEPAD_X, + XINPUT_GAMEPAD_Y, + XINPUT_GAMEPAD_LEFT_SHOULDER, + XINPUT_GAMEPAD_RIGHT_SHOULDER, + XINPUT_GAMEPAD_LEFT_THUMB, + XINPUT_GAMEPAD_RIGHT_THUMB, + XINPUT_GAMEPAD_START, + XINPUT_GAMEPAD_BACK, + + XINPUT_GAMEPAD_DPAD_UP, + XINPUT_GAMEPAD_DPAD_DOWN, + XINPUT_GAMEPAD_DPAD_LEFT, + XINPUT_GAMEPAD_DPAD_RIGHT + }; + + enum + { + SWITCH_A, // button bits + SWITCH_B, + SWITCH_X, + SWITCH_Y, + SWITCH_LB, + SWITCH_RB, + SWITCH_LSB, + SWITCH_RSB, + SWITCH_START, + SWITCH_BACK, + + SWITCH_DPAD_UP, // D-pad bits + SWITCH_DPAD_DOWN, + SWITCH_DPAD_LEFT, + SWITCH_DPAD_RIGHT, + + SWITCH_HAT_UP, // for flight stick with POV hat as right stick + SWITCH_HAT_DOWN, + SWITCH_HAT_LEFT, + SWITCH_HAT_RIGHT, + + SWITCH_LT, // for arcade stick/pad with LT/RT buttons + SWITCH_RT, + + SWITCH_TOTAL + }; + + enum + { + AXIS_LT, // half-axes for triggers + AXIS_RT, + + AXIS_LSX, // full-precision axes + AXIS_LSY, + AXIS_RSX, + AXIS_RSY, + + AXIS_RUDDER, // LT/RT mapped differently for flight sticks + AXIS_THROTTLE, + + AXIS_TOTAL + }; + + uint32_t const m_player_index; + XINPUT_CAPABILITIES const m_capabilities; + XINPUT_STATE m_xinput_state; + uint8_t m_switches[SWITCH_TOTAL]; + int32_t m_axes[AXIS_TOTAL]; + + std::shared_ptr<xinput_api_helper> m_xinput_helper; }; -const input_item_id xinput_axis_ids[] = +xinput_joystick_device::xinput_joystick_device( + running_machine &machine, + std::string &&name, + std::string &&id, + input_module &module, + uint32_t player, + XINPUT_CAPABILITIES const &caps, + std::shared_ptr<xinput_api_helper> helper) : + device_info(machine, std::move(name), std::move(id), DEVICE_CLASS_JOYSTICK, module), + m_player_index(player), + m_capabilities(caps), + m_xinput_state{ 0 }, + m_xinput_helper(helper) { - ITEM_ID_XAXIS, - ITEM_ID_YAXIS, - ITEM_ID_ZAXIS, - ITEM_ID_RZAXIS -}; + std::fill(std::begin(m_switches), std::end(m_switches), 0); + std::fill(std::begin(m_axes), std::end(m_axes), 0); +} -const USHORT xinput_pov_dir[] = { - XINPUT_GAMEPAD_DPAD_UP, - XINPUT_GAMEPAD_DPAD_DOWN, - XINPUT_GAMEPAD_DPAD_LEFT, - XINPUT_GAMEPAD_DPAD_RIGHT -}; +void xinput_joystick_device::poll() +{ + // poll the device first + DWORD const prevpacket = m_xinput_state.dwPacketNumber; + HRESULT result = m_xinput_helper->xinput_get_state(m_player_index, &m_xinput_state); -const char *const xinput_pov_names[] = { - "DPAD Up", - "DPAD Down", - "DPAD Left", - "DPAD Right" -}; + // if we can't poll the device or nothing changed, skip + if (FAILED(result) || (prevpacket == m_xinput_state.dwPacketNumber)) + return; -const USHORT xinput_buttons[] = { - XINPUT_GAMEPAD_A, - XINPUT_GAMEPAD_B, - XINPUT_GAMEPAD_X, - XINPUT_GAMEPAD_Y, - XINPUT_GAMEPAD_LEFT_SHOULDER, - XINPUT_GAMEPAD_RIGHT_SHOULDER, - XINPUT_GAMEPAD_LEFT_THUMB, - XINPUT_GAMEPAD_RIGHT_THUMB, - XINPUT_GAMEPAD_START, - XINPUT_GAMEPAD_BACK -}; + // translate button bits + for (unsigned i = 0; std::size(SWITCH_BITS) > i; ++i) + m_switches[SWITCH_A + i] = (m_xinput_state.Gamepad.wButtons & SWITCH_BITS[i]) ? 0xff : 0x00; + + // translate the triggers onto the negative side of the axes + m_axes[AXIS_LT] = -normalize_absolute_axis(m_xinput_state.Gamepad.bLeftTrigger, -255, 255); + m_axes[AXIS_RT] = -normalize_absolute_axis(m_xinput_state.Gamepad.bRightTrigger, -255, 255); + + // translate full-precision axes - Y direction is opposite to what MAME uses + m_axes[AXIS_LSX] = normalize_absolute_axis(m_xinput_state.Gamepad.sThumbLX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE); + m_axes[AXIS_LSY] = normalize_absolute_axis(-m_xinput_state.Gamepad.sThumbLY, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE); + m_axes[AXIS_RSX] = normalize_absolute_axis(m_xinput_state.Gamepad.sThumbRX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE); + m_axes[AXIS_RSY] = normalize_absolute_axis(-m_xinput_state.Gamepad.sThumbRY, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE); + + // translate LT/RT switches for arcade sticks/pads + m_switches[SWITCH_LT] = (0x80 <= m_xinput_state.Gamepad.bLeftTrigger) ? 0xff : 0x00; + m_switches[SWITCH_RT] = (0x80 <= m_xinput_state.Gamepad.bRightTrigger) ? 0xff : 0x00; + + // translate POV hat for flight sticks + m_switches[SWITCH_HAT_UP] = (16'384 <= m_xinput_state.Gamepad.sThumbRY) ? 0xff : 0x00; + m_switches[SWITCH_HAT_DOWN] = (-16'384 >= m_xinput_state.Gamepad.sThumbRY) ? 0xff : 0x00; + m_switches[SWITCH_HAT_LEFT] = (-16'384 >= m_xinput_state.Gamepad.sThumbRX) ? 0xff : 0x00; + m_switches[SWITCH_HAT_RIGHT] = (16'384 <= m_xinput_state.Gamepad.sThumbRX) ? 0xff : 0x00; + + // translate rudder and throttle for flight sticks + m_axes[AXIS_RUDDER] = normalize_absolute_axis(m_xinput_state.Gamepad.bLeftTrigger, 0, 255); + m_axes[AXIS_THROTTLE] = normalize_absolute_axis(m_xinput_state.Gamepad.bRightTrigger, 0, 255); +} -const char *const xinput_button_names[] = { - "A", - "B", - "X", - "Y", - "LB", - "RB", - "LS", - "RS", - "Start", - "Back" -}; +void xinput_joystick_device::reset() +{ + std::fill(std::begin(m_switches), std::end(m_switches), 0); + std::fill(std::begin(m_axes), std::end(m_axes), 0); +} -const input_item_id xinput_button_ids[] = { - ITEM_ID_BUTTON1, - ITEM_ID_BUTTON2, - ITEM_ID_BUTTON3, - ITEM_ID_BUTTON4, - ITEM_ID_BUTTON5, - ITEM_ID_BUTTON6, - ITEM_ID_BUTTON7, - ITEM_ID_BUTTON8, - ITEM_ID_START, - ITEM_ID_SELECT -}; +void xinput_joystick_device::configure() +{ + // TODO: don't add axes not present in capabilities + // TODO: proper support for dance mat, guitar and drum kit controllers + + // default characteristics for a gamepad + char const *type_name = "unsupported"; + char const *subtype_name = "unsupported"; + bool lt_rt_button = false; + bool lt_rt_fullaxis = false; + bool rstick_hat = false; + char const *const *axis_names = AXIS_NAMES_GAMEPAD; + input_item_id const *axis_ids = AXIS_IDS_GAMEPAD; + char const *const *hat_names = HAT_NAMES_GAMEPAD; + + // consider the device type to decide how to map controls + switch (m_capabilities.Type) + { + case XINPUT_DEVTYPE_GAMEPAD: + type_name = "game controller"; + switch (m_capabilities.SubType) + { + case 0x00: // XINPUT_DEVSUBTYPE_UNKNOWN: work around MinGW header issues + subtype_name = "unknown"; + break; + case XINPUT_DEVSUBTYPE_GAMEPAD: + subtype_name = "gamepad"; + break; + case XINPUT_DEVSUBTYPE_WHEEL: + subtype_name = "wheel"; + axis_names = AXIS_NAMES_WHEEL; + break; + case XINPUT_DEVSUBTYPE_ARCADE_STICK: + subtype_name = "arcade stick"; + lt_rt_button = true; + hat_names = HAT_NAMES_ARCADE_STICK; + break; + case 0x04: // XINPUT_DEVSUBTYPE_FLIGHT_STICK: work around MinGW header issues + subtype_name = "flight stick"; + lt_rt_fullaxis = true; + rstick_hat = true; + axis_names = AXIS_NAMES_FLIGHT_STICK; + axis_ids = AXIS_IDS_FLIGHT_STICK; + break; + case XINPUT_DEVSUBTYPE_DANCE_PAD: + subtype_name = "dance pad"; + break; + case XINPUT_DEVSUBTYPE_GUITAR: + case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE: + case XINPUT_DEVSUBTYPE_GUITAR_BASS: + subtype_name = "guitar"; + break; + case XINPUT_DEVSUBTYPE_DRUM_KIT: + subtype_name = "drum kit"; + break; + case XINPUT_DEVSUBTYPE_ARCADE_PAD: + subtype_name = "arcade pad"; + lt_rt_button = true; + break; + } + break; + } + + // log some diagnostic information + osd_printf_verbose( + "Configuring XInput player %d type 0x%02X (%s) sub type 0x%02X (%s)\n", + m_player_index + 1, + m_capabilities.Type, + type_name, + m_capabilities.SubType, + subtype_name); + osd_printf_verbose( + "XInput switch capabilities A=%d B=%d X=%d Y=%d LB=%d RB=%d LSB=%d RSB=%d Start=%d Back=%d Up=%d Down=%d Left=%d Right=%d\n", + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_A) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_B) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_X) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_Y) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_START) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) ? 1 : 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) ? 1 : 0); + osd_printf_verbose( + "XInput axis capabilities LT=0x%02X (%d-bit) RT=0x%02X (%d-bit) LSX=0x%04X (%d-bit) LSY=0x%04X (%d-bit) RSX=0x%04X (%d-bit) RSY=0x%04X (%d-bit)\n", + m_capabilities.Gamepad.bLeftTrigger, + count_leading_ones_32(uint32_t(m_capabilities.Gamepad.bLeftTrigger) << 24), + m_capabilities.Gamepad.bRightTrigger, + count_leading_ones_32(uint32_t(m_capabilities.Gamepad.bRightTrigger) << 24), + m_capabilities.Gamepad.sThumbLX, + count_leading_ones_32(uint32_t(uint16_t(m_capabilities.Gamepad.sThumbLX)) << 16), + m_capabilities.Gamepad.sThumbLY, + count_leading_ones_32(uint32_t(uint16_t(m_capabilities.Gamepad.sThumbLY)) << 16), + m_capabilities.Gamepad.sThumbRX, + count_leading_ones_32(uint32_t(uint16_t(m_capabilities.Gamepad.sThumbRX)) << 16), + m_capabilities.Gamepad.sThumbRY, + count_leading_ones_32(uint32_t(uint16_t(m_capabilities.Gamepad.sThumbRY)) << 16)); + + // add full-precision axes + for (unsigned i = 0; ((rstick_hat ? AXIS_LSY : AXIS_RSY) - AXIS_LSX) >= i; ++i) + { + device()->add_item( + axis_names[i], + axis_ids[i], + generic_axis_get_state<int32_t>, + &m_axes[AXIS_LSX + i]); + } + + // add extra axes for flight sticks + if (lt_rt_fullaxis) + { + for (unsigned i = 0; (AXIS_THROTTLE - AXIS_RUDDER) >= i; ++i) + { + device()->add_item( + axis_names[4 + i], + axis_ids[4 + i], + generic_axis_get_state<int32_t>, + &m_axes[AXIS_RUDDER + i]); + } + } + + // add hats + bool const hat_caps[]{ + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0, + (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0, + rstick_hat && m_capabilities.Gamepad.sThumbRY, + rstick_hat && m_capabilities.Gamepad.sThumbRY, + rstick_hat && m_capabilities.Gamepad.sThumbRX, + rstick_hat && m_capabilities.Gamepad.sThumbRX }; + for (unsigned i = 0; (SWITCH_HAT_RIGHT - SWITCH_DPAD_UP) >= i; ++i) + { + if (hat_caps[i]) + { + device()->add_item( + hat_names[i], + input_item_id(ITEM_ID_HAT1UP + i), // matches up/down/left/right order + generic_button_get_state<uint8_t>, + &m_switches[SWITCH_DPAD_UP + i]); + } + } + + // add buttons + std::tuple<unsigned, char const *, bool> const button_caps[]{ + { SWITCH_A, "A", (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_A) != 0 }, + { SWITCH_B, "B", (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_B) != 0 }, + { SWITCH_X, "X", (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_X) != 0 }, + { SWITCH_Y, "Y", (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_Y) != 0 }, + { SWITCH_LT, "LT", lt_rt_button && m_capabilities.Gamepad.bLeftTrigger }, + { SWITCH_RT, "RT", lt_rt_button && m_capabilities.Gamepad.bRightTrigger }, + { SWITCH_LB, "LB", (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0 }, + { SWITCH_RB, "RB", (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0 }, + { SWITCH_LSB, "LSB", (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0 }, + { SWITCH_RSB, "RSB", (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0 } }; + input_item_id button_id = ITEM_ID_BUTTON1; + for (auto [i, name, supported] : button_caps) + { + if (supported) + { + device()->add_item( + name, + button_id++, + generic_button_get_state<uint8_t>, + &m_switches[i]); + } + } + + // add start/back + if (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_START) + { + device()->add_item( + "Start", + ITEM_ID_START, + generic_button_get_state<uint8_t>, + &m_switches[SWITCH_START]); + } + if (m_capabilities.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) + { + device()->add_item( + "Back", + ITEM_ID_SELECT, + generic_button_get_state<uint8_t>, + &m_switches[SWITCH_BACK]); + } + + // add triggers/pedals + if (!lt_rt_button && !lt_rt_fullaxis) + { + for (unsigned i = 0; (AXIS_RT - AXIS_LT) >= i; ++i) + { + device()->add_item( + axis_names[4 + i], + axis_ids[4 + i], + generic_axis_get_state<int32_t>, + &m_axes[AXIS_LT + i]); + } + } +} //============================================================ @@ -134,16 +587,9 @@ protected: { XINPUT_STATE state = {0}; + // allocate and link in a new device if (m_xinput_helper->xinput_get_state(i, &state) == ERROR_SUCCESS) - { - // allocate and link in a new device - auto *devinfo = m_xinput_helper->create_xinput_device(machine, i, *this); - if (!devinfo) - continue; - - // Configure each gamepad to add buttons and Axes, etc. - devinfo->configure(); - } + m_xinput_helper->create_xinput_device(machine, i, *this); } } @@ -174,141 +620,32 @@ int xinput_api_helper::initialize() // create_xinput_device //============================================================ -xinput_joystick_device * xinput_api_helper::create_xinput_device(running_machine &machine, UINT index, wininput_module &module) +device_info *xinput_api_helper::create_xinput_device(running_machine &machine, UINT index, wininput_module &module) { + // If we can't get the capabilities skip this device XINPUT_CAPABILITIES caps = { 0 }; if (FAILED(xinput_get_capabilities(index, 0, &caps))) - { - // If we can't get the capabilities skip this device return nullptr; - } char device_name[16]; snprintf(device_name, sizeof(device_name), "XInput Player %u", index + 1); // allocate the device object - auto &devinfo = module.devicelist().create_device<xinput_joystick_device>(machine, device_name, device_name, module, shared_from_this()); - - // Set the player ID - devinfo.xinput_state.player_index = index; - - // Assign the caps we captured earlier - devinfo.xinput_state.caps = caps; + auto &devinfo = module.devicelist().create_device<xinput_joystick_device>( + machine, + device_name, + device_name, + module, + index, + caps, + shared_from_this()); + + // configure each controller to add buttons, axes, etc. + devinfo.configure(); return &devinfo; } -//============================================================ -// xinput_joystick_device -//============================================================ - -xinput_joystick_device::xinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, std::shared_ptr<xinput_api_helper> helper) : - device_info(machine, std::string(name), std::string(id), DEVICE_CLASS_JOYSTICK, module), - gamepad({ { 0 } }), - xinput_state({ 0 }), - m_xinput_helper(helper), - m_configured(false) -{ -} - -void xinput_joystick_device::poll() -{ - if (!m_configured) - return; - - // poll the device first - HRESULT result = m_xinput_helper->xinput_get_state(xinput_state.player_index, &xinput_state.xstate); - - // If we can't poll the device, skip - if (FAILED(result)) - return; - - // Copy the XState into State - // Start with the POV (DPAD) - for (int povindex = 0; povindex < XINPUT_MAX_POV; povindex++) - { - int currentPov = xinput_pov_dir[povindex]; - gamepad.povs[povindex] = (xinput_state.xstate.Gamepad.wButtons & currentPov) ? 0xFF : 0; - } - - // Now do the buttons - for (int buttonindex = 0; buttonindex < XINPUT_MAX_BUTTONS; buttonindex++) - { - int currentButton = xinput_buttons[buttonindex]; - gamepad.buttons[buttonindex] = (xinput_state.xstate.Gamepad.wButtons & currentButton) ? 0xFF : 0; - } - - // Now grab the axis values - // Each of the thumbstick axis members is a signed value between -32768 and 32767 describing the position of the thumbstick - // However, the Y axis values are inverted from what MAME expects, so negate the value - gamepad.left_thumb_x = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbLX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE); - gamepad.left_thumb_y = normalize_absolute_axis(-xinput_state.xstate.Gamepad.sThumbLY, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE); - gamepad.right_thumb_x = normalize_absolute_axis(xinput_state.xstate.Gamepad.sThumbRX, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE); - gamepad.right_thumb_y = normalize_absolute_axis(-xinput_state.xstate.Gamepad.sThumbRY, XINPUT_AXIS_MINVALUE, XINPUT_AXIS_MAXVALUE); - - // Now the triggers, place them on half-axes (negative side) - gamepad.left_trigger = -normalize_absolute_axis(xinput_state.xstate.Gamepad.bLeftTrigger, -255, 255); - gamepad.right_trigger = -normalize_absolute_axis(xinput_state.xstate.Gamepad.bRightTrigger, -255, 255); -} - -void xinput_joystick_device::reset() -{ - memset(&gamepad, 0, sizeof(gamepad)); -} - -void xinput_joystick_device::configure() -{ - std::lock_guard<std::mutex> scope_lock(m_device_lock); - - if (m_configured) - return; - - // Add the axes - for (int axisnum = 0; axisnum < XINPUT_MAX_AXIS; axisnum++) - { - device()->add_item( - xinput_axis_name[axisnum], - xinput_axis_ids[axisnum], - generic_axis_get_state<LONG>, - &gamepad.left_thumb_x + axisnum); - } - - // Populate the POVs - // For XBOX, we treat the DPAD as a hat switch - for (int povnum = 0; povnum < XINPUT_MAX_POV; povnum++) - { - device()->add_item( - xinput_pov_names[povnum], - input_item_id(ITEM_ID_HAT1UP + povnum), // matches up/down/left/right order - generic_button_get_state<BYTE>, - &gamepad.povs[povnum]); - } - - // populate the buttons - for (int butnum = 0; butnum < XINPUT_MAX_BUTTONS; butnum++) - { - device()->add_item( - xinput_button_names[butnum], - xinput_button_ids[butnum], - generic_button_get_state<BYTE>, - &gamepad.buttons[butnum]); - } - - device()->add_item( - "RT", - ITEM_ID_ADD_ABSOLUTE1, - generic_axis_get_state<LONG>, - &gamepad.right_trigger); - - device()->add_item( - "LT", - ITEM_ID_ADD_ABSOLUTE2, - generic_axis_get_state<LONG>, - &gamepad.left_trigger); - - m_configured = true; -} - #else // defined(OSD_WINDOWS) #include "input_module.h" diff --git a/src/osd/modules/input/input_xinput.h b/src/osd/modules/input/input_xinput.h index bd918f9aacb..edf3dc23ce5 100644 --- a/src/osd/modules/input/input_xinput.h +++ b/src/osd/modules/input/input_xinput.h @@ -7,15 +7,9 @@ #include "modules/lib/osdlib.h" -#include <cstdint> -#include <memory> -#include <mutex> -#include <string_view> - #include <xinput.h> - -class xinput_joystick_device; +#include <memory> class xinput_api_helper : public std::enable_shared_from_this<xinput_api_helper> @@ -24,7 +18,7 @@ public: xinput_api_helper() { } int initialize(); - xinput_joystick_device *create_xinput_device(running_machine &machine, UINT index, wininput_module &module); + device_info *create_xinput_device(running_machine &machine, UINT index, wininput_module &module); DWORD xinput_get_state(DWORD dwUserindex, XINPUT_STATE *pState) const { @@ -46,48 +40,4 @@ private: xinput_get_caps_fn XInputGetCapabilities = nullptr; }; - -class xinput_joystick_device : public device_info -{ -public: - static inline constexpr int XINPUT_MAX_POV = 4; - static inline constexpr int XINPUT_MAX_BUTTONS = 10; - static inline constexpr int XINPUT_MAX_AXIS = 4; - - struct gamepad_state - { - BYTE buttons[XINPUT_MAX_BUTTONS]; - BYTE povs[XINPUT_MAX_POV]; - LONG left_trigger; - LONG right_trigger; - LONG left_thumb_x; - LONG left_thumb_y; - LONG right_thumb_x; - LONG right_thumb_y; - }; - - // state information for a gamepad; state must be first element - struct xinput_api_state - { - uint32_t player_index; - XINPUT_STATE xstate; - XINPUT_CAPABILITIES caps; - }; - - gamepad_state gamepad; - xinput_api_state xinput_state; - -private: - std::shared_ptr<xinput_api_helper> m_xinput_helper; - std::mutex m_device_lock; - bool m_configured; - -public: - xinput_joystick_device(running_machine &machine, std::string &&name, std::string &&id, input_module &module, std::shared_ptr<xinput_api_helper> helper); - - void poll() override; - void reset() override; - void configure(); -}; - #endif // MAME_OSD_INPUT_INPUT_XINPUT_H diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index 6d6a865a9c7..d370bb0e658 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -283,7 +283,8 @@ void osd_common_t::register_options() REGISTER_MODULE(m_mod_man, LIGHTGUNINPUT_WIN32); REGISTER_MODULE(m_mod_man, LIGHTGUN_NONE); - REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_SDL); + REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_SDLJOY); + REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_SDLGAME); REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_WINHYBRID); REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_DINPUT); REGISTER_MODULE(m_mod_man, JOYSTICKINPUT_XINPUT); |