summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2023-01-12 17:59:59 +1100
committer Vas Crabb <vas@vastheman.com>2023-01-12 18:14:13 +1100
commitfee7047c16a04f816a0de031ec469f5b96be9f74 (patch)
treef9be050cbdb952d8315cc241648e5ddc8422b247 /src
parent9e8064c85eb420e61df7ba56f197877680e642c6 (diff)
-osd: Better XInput and SDL game controller input enhancements:
* Added initial support for XInput controller subtypes, starting with driving, arcade and flight controllers. * Check XInput capabilities to ignore buttons and hats that aren't present. * Added preliminary SDL Game Controller joystick provider. Reconnection and mixed Game Controller/Joystick devices are unsupported. * Show the input token for the highlighted control on input device menus. -ui: Allow menus to set required space above and below menu when metrics change. Fixes the initial bad layout on the system selecton menu, or bad layout after resizing windows.
Diffstat (limited to 'src')
-rw-r--r--src/emu/render.cpp6
-rw-r--r--src/frontend/mame/ui/about.cpp17
-rw-r--r--src/frontend/mame/ui/about.h3
-rw-r--r--src/frontend/mame/ui/analogipt.cpp13
-rw-r--r--src/frontend/mame/ui/analogipt.h3
-rw-r--r--src/frontend/mame/ui/auditmenu.cpp15
-rw-r--r--src/frontend/mame/ui/auditmenu.h3
-rw-r--r--src/frontend/mame/ui/barcode.cpp2
-rw-r--r--src/frontend/mame/ui/barcode.h2
-rw-r--r--src/frontend/mame/ui/cheatopt.cpp2
-rw-r--r--src/frontend/mame/ui/cheatopt.h2
-rw-r--r--src/frontend/mame/ui/confswitch.cpp22
-rw-r--r--src/frontend/mame/ui/confswitch.h5
-rw-r--r--src/frontend/mame/ui/custui.cpp43
-rw-r--r--src/frontend/mame/ui/custui.h13
-rw-r--r--src/frontend/mame/ui/datmenu.cpp29
-rw-r--r--src/frontend/mame/ui/datmenu.h3
-rw-r--r--src/frontend/mame/ui/devopt.cpp2
-rw-r--r--src/frontend/mame/ui/devopt.h2
-rw-r--r--src/frontend/mame/ui/dirmenu.cpp41
-rw-r--r--src/frontend/mame/ui/dirmenu.h2
-rw-r--r--src/frontend/mame/ui/filecreate.cpp26
-rw-r--r--src/frontend/mame/ui/filecreate.h9
-rw-r--r--src/frontend/mame/ui/filemngr.cpp16
-rw-r--r--src/frontend/mame/ui/filemngr.h3
-rw-r--r--src/frontend/mame/ui/filesel.cpp20
-rw-r--r--src/frontend/mame/ui/filesel.h5
-rw-r--r--src/frontend/mame/ui/imgcntrl.cpp2
-rw-r--r--src/frontend/mame/ui/imgcntrl.h2
-rw-r--r--src/frontend/mame/ui/info.cpp6
-rw-r--r--src/frontend/mame/ui/info.h6
-rw-r--r--src/frontend/mame/ui/info_pty.cpp2
-rw-r--r--src/frontend/mame/ui/info_pty.h2
-rw-r--r--src/frontend/mame/ui/inputdevices.cpp57
-rw-r--r--src/frontend/mame/ui/inputdevices.h2
-rw-r--r--src/frontend/mame/ui/inputmap.cpp25
-rw-r--r--src/frontend/mame/ui/inputmap.h12
-rw-r--r--src/frontend/mame/ui/inputopts.cpp2
-rw-r--r--src/frontend/mame/ui/inputopts.h2
-rw-r--r--src/frontend/mame/ui/inputtoggle.cpp2
-rw-r--r--src/frontend/mame/ui/inputtoggle.h2
-rw-r--r--src/frontend/mame/ui/keyboard.cpp2
-rw-r--r--src/frontend/mame/ui/keyboard.h2
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp2
-rw-r--r--src/frontend/mame/ui/mainmenu.h2
-rw-r--r--src/frontend/mame/ui/menu.cpp14
-rw-r--r--src/frontend/mame/ui/menu.h5
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp14
-rw-r--r--src/frontend/mame/ui/miscmenu.h14
-rw-r--r--src/frontend/mame/ui/optsmenu.cpp8
-rw-r--r--src/frontend/mame/ui/optsmenu.h4
-rw-r--r--src/frontend/mame/ui/pluginopt.cpp4
-rw-r--r--src/frontend/mame/ui/pluginopt.h4
-rw-r--r--src/frontend/mame/ui/quitmenu.cpp2
-rw-r--r--src/frontend/mame/ui/quitmenu.h2
-rw-r--r--src/frontend/mame/ui/selector.cpp14
-rw-r--r--src/frontend/mame/ui/selector.h3
-rw-r--r--src/frontend/mame/ui/selgame.cpp9
-rw-r--r--src/frontend/mame/ui/selgame.h2
-rw-r--r--src/frontend/mame/ui/selmenu.cpp8
-rw-r--r--src/frontend/mame/ui/selsoft.cpp17
-rw-r--r--src/frontend/mame/ui/selsoft.h4
-rw-r--r--src/frontend/mame/ui/simpleselgame.cpp15
-rw-r--r--src/frontend/mame/ui/simpleselgame.h3
-rw-r--r--src/frontend/mame/ui/sliders.cpp14
-rw-r--r--src/frontend/mame/ui/sliders.h3
-rw-r--r--src/frontend/mame/ui/slotopt.cpp14
-rw-r--r--src/frontend/mame/ui/slotopt.h7
-rw-r--r--src/frontend/mame/ui/sndmenu.cpp2
-rw-r--r--src/frontend/mame/ui/sndmenu.h2
-rw-r--r--src/frontend/mame/ui/state.cpp22
-rw-r--r--src/frontend/mame/ui/state.h3
-rw-r--r--src/frontend/mame/ui/submenu.cpp18
-rw-r--r--src/frontend/mame/ui/submenu.h3
-rw-r--r--src/frontend/mame/ui/swlist.cpp6
-rw-r--r--src/frontend/mame/ui/swlist.h6
-rw-r--r--src/frontend/mame/ui/tapectrl.cpp2
-rw-r--r--src/frontend/mame/ui/tapectrl.h2
-rw-r--r--src/frontend/mame/ui/textbox.cpp12
-rw-r--r--src/frontend/mame/ui/textbox.h1
-rw-r--r--src/frontend/mame/ui/utils.cpp8
-rw-r--r--src/frontend/mame/ui/videoopt.cpp4
-rw-r--r--src/frontend/mame/ui/videoopt.h4
-rw-r--r--src/osd/modules/input/input_sdl.cpp999
-rw-r--r--src/osd/modules/input/input_sdlcommon.cpp8
-rw-r--r--src/osd/modules/input/input_winhybrid.cpp13
-rw-r--r--src/osd/modules/input/input_xinput.cpp723
-rw-r--r--src/osd/modules/input/input_xinput.h54
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp3
89 files changed, 1870 insertions, 650 deletions
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);