summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mame/ui/analogipt.cpp39
-rw-r--r--src/frontend/mame/ui/analogipt.h10
-rw-r--r--src/frontend/mame/ui/confswitch.cpp414
-rw-r--r--src/frontend/mame/ui/confswitch.h97
-rw-r--r--src/frontend/mame/ui/custui.cpp82
-rw-r--r--src/frontend/mame/ui/custui.h20
-rw-r--r--src/frontend/mame/ui/inputmap.cpp319
-rw-r--r--src/frontend/mame/ui/inputmap.h47
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp3
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp1
-rw-r--r--src/frontend/mame/ui/optsmenu.cpp2
11 files changed, 615 insertions, 419 deletions
diff --git a/src/frontend/mame/ui/analogipt.cpp b/src/frontend/mame/ui/analogipt.cpp
index f70e62d9de0..d63f6afc490 100644
--- a/src/frontend/mame/ui/analogipt.cpp
+++ b/src/frontend/mame/ui/analogipt.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods, Vas Crabb
/*********************************************************************
ui/analogipt.cpp
@@ -12,11 +12,13 @@
#include "ui/analogipt.h"
#include <algorithm>
+#include <string>
+#include <utility>
namespace ui {
-inline menu_analog::item_data::item_data(ioport_field &f, int t)
+inline menu_analog::item_data::item_data(ioport_field &f, int t) noexcept
: field(f)
, type(t)
, min((ANALOG_ITEM_SENSITIVITY == t) ? 1 : 0)
@@ -32,9 +34,12 @@ inline menu_analog::item_data::item_data(ioport_field &f, int t)
}
-inline menu_analog::field_data::field_data(ioport_field &f)
+inline menu_analog::field_data::field_data(ioport_field &f) noexcept
: field(f)
, range(f.maxval() - f.minval())
+ , neutral(float(f.analog_reverse() ? (f.maxval() - f.defvalue()) : (f.defvalue() - f.minval())) / range)
+ , origin((f.analog_wraps() && (f.defvalue() != f.minval()) && (f.defvalue() != f.maxval())) ? 0.0f : neutral)
+ , show_neutral((f.defvalue() != f.minval()) && (f.defvalue() != f.maxval()))
{
}
@@ -56,8 +61,9 @@ menu_analog::~menu_analog()
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
- float const extrawidth(0.4f + (ui().box_lr_border() * 2.0f) + (ui().get_line_height() * machine().render().ui_aspect()));
- float const nameavail(1.0f - (ui().box_lr_border() * 2.0f) - extrawidth);
+ float const aspect(machine().render().ui_aspect(&container()));
+ float const extrawidth(0.4f + (((ui().box_lr_border() * 2.0f) + ui().get_line_height()) * aspect));
+ float const nameavail(1.0f - (ui().box_lr_border() * 2.0f * aspect) - extrawidth);
float namewidth(0.0f);
for (field_data &data : m_field_data)
namewidth = (std::min)((std::max)(ui().get_string_width(data.field.get().name()), namewidth), nameavail);
@@ -68,9 +74,9 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa
ui().draw_outlined_box(container(), boxleft, y2 + ui().box_tb_border(), boxright, y2 + bottom, ui().colors().background_color());
// show live fields
- namewidth += ui().get_line_height() * machine().render().ui_aspect();
+ namewidth += ui().get_line_height() * aspect;
unsigned line(0U);
- float const nameleft(boxleft + ui().box_lr_border());
+ float const nameleft(boxleft + (ui().box_lr_border() * aspect));
float const indleft(nameleft + namewidth);
float const indright(indleft + 0.4f);
ioport_field *const selfield(selectedref ? &reinterpret_cast<item_data *>(selectedref)->field.get() : nullptr);
@@ -82,7 +88,7 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa
ui().draw_text_full(
container(),
data.field.get().name(),
- nameleft, liney, namewidth, ui::text_layout::LEFT, ui::text_layout::TRUNCATE,
+ nameleft, liney, namewidth, ui::text_layout::LEFT, ui::text_layout::NEVER,
mame_ui_manager::NORMAL, fgcolor, ui().colors().text_bg_color());
ioport_value cur(0U);
@@ -94,11 +100,16 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa
float const indtop(liney + (ui().get_line_height() * 0.2f));
float const indbottom(liney + (ui().get_line_height() * 0.8f));
- container().add_rect(indleft, indtop, indleft + (fill * 0.4f), indbottom, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ if (data.origin > fill)
+ container().add_rect(indleft + (fill * 0.4f), indtop, indleft + (data.origin * 0.4f), indbottom, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ else
+ container().add_rect(indleft + (data.origin * 0.4f), indtop, indleft + (fill * 0.4f), indbottom, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
container().add_line(indleft, indtop, indright, indtop, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
container().add_line(indright, indtop, indright, indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
container().add_line(indright, indbottom, indleft, indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
container().add_line(indleft, indbottom, indleft, indtop, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ if (data.show_neutral)
+ container().add_line(indleft + (data.neutral * 0.4f), indtop, indleft + (data.neutral * 0.4f), indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
// TODO: ensure field being configured is visible
if (++line >= m_visible_fields)
@@ -228,7 +239,7 @@ void menu_analog::populate(float &customtop, float &custombottom)
}
// put on arrows
- uint32_t flags = 0;
+ uint32_t flags(0U);
if (data.cur > data.min)
flags |= FLAG_LEFT_ARROW;
if (data.cur < data.max)
@@ -245,6 +256,8 @@ void menu_analog::populate(float &customtop, float &custombottom)
void menu_analog::find_fields()
{
+ assert(m_field_data.empty());
+
// collect analog fields
for (auto &port : machine().ioport().ports())
{
@@ -288,9 +301,9 @@ void menu_analog::find_fields()
}
}
- // restrict live display to 40% height plus borders
- if ((ui().get_line_height() * m_field_data.size()) > 0.4f)
- m_visible_fields = unsigned(0.4f / ui().get_line_height());
+ // restrict live display to 60% height plus borders
+ if ((ui().get_line_height() * m_field_data.size()) > 0.6f)
+ m_visible_fields = unsigned(0.6f / ui().get_line_height());
else
m_visible_fields = m_field_data.size();
}
diff --git a/src/frontend/mame/ui/analogipt.h b/src/frontend/mame/ui/analogipt.h
index b71cc095cc0..40c76602af5 100644
--- a/src/frontend/mame/ui/analogipt.h
+++ b/src/frontend/mame/ui/analogipt.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods, Vas Crabb
/***************************************************************************
ui/analogipt.h
@@ -7,7 +7,6 @@
Analog inputs menu.
***************************************************************************/
-
#ifndef MAME_FRONTEND_UI_ANALOGIPT_H
#define MAME_FRONTEND_UI_ANALOGIPT_H
@@ -42,7 +41,7 @@ private:
struct item_data
{
- item_data(ioport_field &f, int t);
+ item_data(ioport_field &f, int t) noexcept;
std::reference_wrapper<ioport_field> field;
int type;
@@ -53,10 +52,13 @@ private:
struct field_data
{
- field_data(ioport_field &f);
+ field_data(ioport_field &f) noexcept;
std::reference_wrapper<ioport_field> field;
float range;
+ float neutral;
+ float origin;
+ bool show_neutral;
};
using item_data_vector = std::vector<item_data>;
diff --git a/src/frontend/mame/ui/confswitch.cpp b/src/frontend/mame/ui/confswitch.cpp
new file mode 100644
index 00000000000..82eec967b08
--- /dev/null
+++ b/src/frontend/mame/ui/confswitch.cpp
@@ -0,0 +1,414 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/*********************************************************************
+
+ ui/confswitch.cpp
+
+ Configuration/DIP switches menu.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "ui/confswitch.h"
+
+#include <algorithm>
+#include <cstring>
+
+
+namespace ui {
+
+namespace {
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+// DIP switch rendering parameters in terms of line height
+constexpr float DIP_SWITCH_HEIGHT = 1.6f;
+constexpr float DIP_SWITCH_SPACING = DIP_SWITCH_HEIGHT / 5.0f;
+constexpr float SINGLE_TOGGLE_SWITCH_FIELD_WIDTH = DIP_SWITCH_HEIGHT / 2.0f;
+constexpr float SINGLE_TOGGLE_SWITCH_WIDTH = SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * 0.8f;
+// make the switch nub 80% of the width space and 1/2 of the switch height
+constexpr float SINGLE_TOGGLE_SWITCH_HEIGHT = (DIP_SWITCH_HEIGHT / 2.0f) * 0.8f;
+
+} // anonymous namespace
+
+
+
+/*-------------------------------------------------
+ menu_confswitch
+-------------------------------------------------*/
+
+menu_confswitch::field_descriptor::field_descriptor(ioport_field &f) noexcept
+ : field(f)
+{
+}
+
+
+menu_confswitch::switch_group_descriptor::switch_group_descriptor(ioport_field const &f, ioport_diplocation const &loc) noexcept
+ : name(loc.name())
+ , owner(f.device())
+ , mask(0U)
+ , state(0U)
+{
+}
+
+
+inline bool menu_confswitch::switch_group_descriptor::matches(ioport_field const &f, ioport_diplocation const &loc) const noexcept
+{
+ return (&owner.get() == &f.device()) && !strcmp(loc.name(), name);
+}
+
+
+inline unsigned menu_confswitch::switch_group_descriptor::switch_count() const noexcept
+{
+ return (sizeof(mask) * 8) - count_leading_zeros(mask);
+}
+
+
+menu_confswitch::menu_confswitch(mame_ui_manager &mui, render_container &container, uint32_t type)
+ : menu(mui, container)
+ , m_fields()
+ , m_switch_groups()
+ , m_active_switch_groups(0U)
+ , m_type(type)
+{
+}
+
+
+menu_confswitch::~menu_confswitch()
+{
+}
+
+
+void menu_confswitch::populate(float &customtop, float &custombottom)
+{
+ // locate relevant fields if necessary
+ if (m_fields.empty())
+ find_fields();
+
+ // reset switch group masks
+ m_active_switch_groups = 0U;
+ for (switch_group_descriptor &group : m_switch_groups)
+ group.mask = group.state = 0U;
+
+ // loop over input ports and set up the current values
+ device_t *prev_owner(nullptr);
+ bool first_entry(true);
+ for (field_descriptor &desc : m_fields)
+ {
+ ioport_field &field(desc.field);
+ if (field.enabled())
+ {
+ if (!field.settings().empty())
+ {
+ // add a device heading if necessary
+ if (&field.device() != prev_owner)
+ {
+ prev_owner = &field.device();
+ if (first_entry)
+ first_entry = false;
+ else
+ item_append(menu_item_type::SEPARATOR);
+ item_append(string_format("[root%s]", prev_owner->tag()), "", 0, nullptr);
+ }
+
+ // set the left/right flags appropriately
+ uint32_t flags(0U);
+ if (field.has_previous_setting())
+ flags |= FLAG_LEFT_ARROW;
+ if (field.has_next_setting())
+ flags |= FLAG_RIGHT_ARROW;
+
+ // add the menu item
+ item_append(field.name(), field.setting_name(), flags, &field);
+ }
+
+ // track switch groups
+ if (!field.diplocations().empty())
+ {
+ // get current settings
+ ioport_field::user_settings settings;
+ field.get_user_settings(settings);
+
+ // iterate over each bit in the field
+ ioport_value accummask(field.mask());
+ for (ioport_diplocation const &loc : field.diplocations())
+ {
+ // find the matching switch group
+ switch_group_descriptor &group(
+ *std::find_if(
+ m_switch_groups.begin(),
+ m_switch_groups.end(), [&field, &loc] (switch_group_descriptor const &sw) { return sw.matches(field, loc); }));
+
+ // count if this is the first switch in the group
+ if (!group.mask)
+ ++m_active_switch_groups;
+
+ // apply the bits
+ group.mask |= uint32_t(1) << (loc.number() - 1);
+ ioport_value const mask(accummask & ~(accummask - 1));
+ if (((settings.value & mask) && !loc.inverted()) || (!(settings.value & mask) && loc.inverted()))
+ group.state |= uint32_t(1) << (loc.number() - 1);
+
+ // clear the relevant bit in the accumulated mask
+ accummask &= ~mask;
+ }
+ }
+ }
+ }
+
+ item_append(menu_item_type::SEPARATOR);
+ item_append(_("Reset"), "", 0, (void *)1);
+}
+
+
+void menu_confswitch::handle()
+{
+ // process the menu
+ event const *const menu_event(process(0));
+
+ // handle events
+ if (menu_event && menu_event->itemref)
+ {
+ if (uintptr_t(menu_event->itemref) == 1U)
+ {
+ // reset
+ if (menu_event->iptkey == IPT_UI_SELECT)
+ machine().schedule_hard_reset();
+ }
+ else
+ {
+ // actual settings
+ ioport_field &field(*reinterpret_cast<ioport_field *>(menu_event->itemref));
+ bool changed(false);
+
+ switch (menu_event->iptkey)
+ {
+ // if selected, reset to default value
+ case IPT_UI_SELECT:
+ {
+ ioport_field::user_settings settings;
+ field.get_user_settings(settings);
+ settings.value = field.defvalue();
+ field.set_user_settings(settings);
+ }
+ changed = true;
+ break;
+
+ // left goes to previous setting
+ case IPT_UI_LEFT:
+ field.select_previous_setting();
+ changed = true;
+ break;
+
+ // right goes to next setting
+ case IPT_UI_RIGHT:
+ field.select_next_setting();
+ changed = true;
+ break;
+ }
+
+ // if anything changed, rebuild the menu, trying to stay on the same field
+ if (changed)
+ reset(reset_options::REMEMBER_REF);
+ }
+ }
+}
+
+
+void menu_confswitch::find_fields()
+{
+ assert(m_fields.empty());
+ assert(m_switch_groups.empty());
+
+ // find relevant input ports
+ for (auto &port : machine().ioport().ports())
+ {
+ for (ioport_field &field : port.second->fields())
+ {
+ if (field.type() == m_type)
+ {
+ m_fields.emplace_back(field);
+
+ // iterate over locations
+ for (ioport_diplocation const &loc : field.diplocations())
+ {
+ auto const found(
+ std::find_if(
+ m_switch_groups.begin(),
+ m_switch_groups.end(), [&field, &loc] (switch_group_descriptor const &sw) { return sw.matches(field, loc); }));
+ if (m_switch_groups.end() == found)
+ m_switch_groups.emplace_back(field, loc);
+ }
+ }
+ }
+ }
+}
+
+
+
+/*-------------------------------------------------
+ menu_settings_dip_switches
+-------------------------------------------------*/
+
+menu_settings_dip_switches::menu_settings_dip_switches(mame_ui_manager &mui, render_container &container)
+ : menu_confswitch(mui, container, IPT_DIPSWITCH)
+ , m_visible_switch_groups(0U)
+{
+}
+
+
+menu_settings_dip_switches::~menu_settings_dip_switches()
+{
+}
+
+
+void menu_settings_dip_switches::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
+{
+ // catch if no diploc has to be drawn
+ if (!m_visible_switch_groups)
+ return;
+
+ // calculate optimal width
+ float const aspect(machine().render().ui_aspect(&container()));
+ float const lineheight(ui().get_line_height());
+ float const singlewidth(lineheight * SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * aspect);
+ float const maxwidth(1.0f - (ui().box_lr_border() * 2.0f * aspect));
+ float width(0.0f);
+ unsigned maxswitches(0U);
+ for (switch_group_descriptor const &group : switch_groups())
+ {
+ if (group.mask)
+ {
+ maxswitches = (std::max)(group.switch_count(), maxswitches);
+ float const namewidth(ui().get_string_width(group.name));
+ float const switchwidth(singlewidth * maxswitches);
+ width = (std::min)((std::max)(namewidth + switchwidth + (lineheight * aspect), width), maxwidth);
+ }
+ }
+
+ // draw extra menu area
+ float const boxwidth((std::max)(width + (ui().box_lr_border() * 2.0f * aspect), x2 - x1));
+ float const boxleft((1.0f - boxwidth) / 2.0f);
+ ui().draw_outlined_box(container(), boxleft, y2 + ui().box_tb_border(), boxleft + boxwidth, y2 + bottom, ui().colors().background_color());
+
+ // calculate centred layout
+ float const nameleft((1.0f - width) / 2.0f);
+ float const switchleft(nameleft + width - (singlewidth * maxswitches));
+ float const namewidth(width - (singlewidth * maxswitches) - (lineheight * aspect));
+
+ // iterate over switch groups
+ ioport_field *const field((uintptr_t(selectedref) != 1U) ? reinterpret_cast<ioport_field *>(selectedref) : nullptr);
+ float const nubheight(lineheight * SINGLE_TOGGLE_SWITCH_HEIGHT);
+ float const nubwidth(lineheight * SINGLE_TOGGLE_SWITCH_WIDTH * aspect);
+ float const ygap(lineheight * ((DIP_SWITCH_HEIGHT / 2) - SINGLE_TOGGLE_SWITCH_HEIGHT) / 2);
+ float const xgap((singlewidth + (UI_LINE_WIDTH / 2) - nubwidth) / 2);
+ unsigned line(0U);
+ for (switch_group_descriptor const &group : switch_groups())
+ {
+ if (group.mask)
+ {
+ // determine the mask of selected bits
+ uint32_t selectedmask(0U);
+ if (field)
+ {
+ for (ioport_diplocation const &loc : field->diplocations())
+ if (group.matches(*field, loc))
+ selectedmask |= uint32_t(1) << (loc.number() - 1);
+ }
+
+ // draw the name
+ float const liney(y2 + (ui().box_tb_border() * 2.0f) + (lineheight * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) * line));
+ ui().draw_text_full(
+ container(),
+ group.name,
+ nameleft, liney + (lineheight * (DIP_SWITCH_HEIGHT - 1.0f) / 2.0f), namewidth,
+ ui::text_layout::RIGHT, ui::text_layout::NEVER,
+ mame_ui_manager::NORMAL, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ // draw the group outline
+ float const switchbottom(liney + (DIP_SWITCH_HEIGHT * lineheight));
+ unsigned const cnt(group.switch_count());
+ ui().draw_outlined_box(
+ container(),
+ switchleft, liney, switchleft + (singlewidth * cnt), switchbottom,
+ ui().colors().background_color());
+ for (unsigned i = 1; cnt > i; ++i)
+ {
+ container().add_line(
+ switchleft + (singlewidth * i), liney, switchleft + (singlewidth * i), switchbottom,
+ UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+
+ // compute top and bottom for on and off positions
+ float const yoff(liney + UI_LINE_WIDTH + ygap);
+ float const yon(switchbottom - UI_LINE_WIDTH - ygap - nubheight);
+
+ // draw the switch nubs
+ for (unsigned toggle = 0; cnt > toggle; ++toggle)
+ {
+ float const nubleft(switchleft + (singlewidth * toggle) + xgap);
+ if (BIT(group.mask, toggle))
+ {
+ float const nubtop(BIT(group.state, toggle) ? yon : yoff);
+ container().add_rect(
+ nubleft, nubtop, nubleft + nubwidth, nubtop + nubheight,
+ BIT(selectedmask, toggle) ? ui().colors().dipsw_color() : ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ else
+ {
+ container().add_rect(
+ nubleft, yoff, nubleft + nubwidth, yon + nubheight,
+ ui().colors().unavailable_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ }
+
+ // limit the number of visible switch groups
+ if (++line >= m_visible_switch_groups)
+ break;
+ }
+ }
+}
+
+
+void menu_settings_dip_switches::populate(float &customtop, float &custombottom)
+{
+ // let the base class add items
+ menu_confswitch::populate(customtop, custombottom);
+
+ // use up to about 70% of height for DIP switch display
+ if (active_switch_groups())
+ {
+ float const lineheight(ui().get_line_height());
+ float const groupheight(DIP_SWITCH_HEIGHT * lineheight);
+ float const groupspacing(DIP_SWITCH_SPACING * lineheight);
+ if ((active_switch_groups() * (groupheight + groupspacing)) > 0.7f)
+ 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) + (ui().box_tb_border() * 3.0f);
+ }
+ else
+ {
+ m_visible_switch_groups = 0U;
+ custombottom = 0.0f;
+ }
+}
+
+
+
+/*-------------------------------------------------
+ menu_settings_machine_config
+-------------------------------------------------*/
+
+menu_settings_machine_config::menu_settings_machine_config(mame_ui_manager &mui, render_container &container) : menu_confswitch(mui, container, IPT_CONFIG)
+{
+}
+
+menu_settings_machine_config::~menu_settings_machine_config()
+{
+}
+
+
+} // namespace ui
diff --git a/src/frontend/mame/ui/confswitch.h b/src/frontend/mame/ui/confswitch.h
new file mode 100644
index 00000000000..35dac6d75d9
--- /dev/null
+++ b/src/frontend/mame/ui/confswitch.h
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods
+/***************************************************************************
+
+ ui/confswitch.h
+
+ Configuration/DIP switches menu.
+
+***************************************************************************/
+#ifndef MAME_FRONTEND_UI_CONFSWITCH_H
+#define MAME_FRONTEND_UI_CONFSWITCH_H
+
+#include "ui/menu.h"
+
+#include <functional>
+#include <vector>
+
+
+namespace ui {
+
+class menu_confswitch : public menu
+{
+public:
+ virtual ~menu_confswitch() override;
+
+protected:
+ struct field_descriptor
+ {
+ field_descriptor(ioport_field &f) noexcept;
+
+ std::reference_wrapper<ioport_field> field;
+ };
+
+ struct switch_group_descriptor
+ {
+ switch_group_descriptor(ioport_field const &f, ioport_diplocation const &loc) noexcept;
+
+ bool matches(ioport_field const &f, ioport_diplocation const &loc) const noexcept;
+ unsigned switch_count() const noexcept;
+
+ char const *name;
+ std::reference_wrapper<device_t> owner;
+ uint32_t mask;
+ uint32_t state;
+ };
+
+ using field_vector = std::vector<field_descriptor>;
+ using switch_group_vector = std::vector<switch_group_descriptor>;
+
+ menu_confswitch(mame_ui_manager &mui, render_container &container, uint32_t type);
+
+ virtual void populate(float &customtop, float &custombottom) override;
+
+ field_vector const &fields() { return m_fields; }
+ switch_group_vector const &switch_groups() { return m_switch_groups; }
+ unsigned active_switch_groups() const { return m_active_switch_groups; }
+
+ int m_dipcount;
+
+private:
+ virtual void handle() override;
+
+ void find_fields();
+
+ field_vector m_fields;
+ switch_group_vector m_switch_groups;
+ unsigned m_active_switch_groups;
+ int const m_type;
+};
+
+
+class menu_settings_dip_switches : public menu_confswitch
+{
+public:
+ menu_settings_dip_switches(mame_ui_manager &mui, render_container &container);
+ virtual ~menu_settings_dip_switches() override;
+
+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;
+
+ unsigned m_visible_switch_groups;
+};
+
+
+class menu_settings_machine_config : public menu_confswitch
+{
+public:
+ menu_settings_machine_config(mame_ui_manager &mui, render_container &container);
+ virtual ~menu_settings_machine_config();
+};
+
+} // namespace ui
+
+#endif // MAME_FRONTEND_UI_CONFSWITCH_H
diff --git a/src/frontend/mame/ui/custui.cpp b/src/frontend/mame/ui/custui.cpp
index 65b1ad2fa5e..5eec6d1c6ba 100644
--- a/src/frontend/mame/ui/custui.cpp
+++ b/src/frontend/mame/ui/custui.cpp
@@ -37,7 +37,9 @@ const char *const menu_custom_ui::HIDE_STATUS[] = {
// ctor
//-------------------------------------------------
-menu_custom_ui::menu_custom_ui(mame_ui_manager &mui, render_container &container) : menu(mui, container)
+menu_custom_ui::menu_custom_ui(mame_ui_manager &mui, render_container &container, std::function<void ()> &&handler)
+ : menu(mui, container)
+ , m_handler(std::move(handler))
{
// load languages
file_enumerator path(mui.machine().options().language_path());
@@ -72,6 +74,9 @@ menu_custom_ui::~menu_custom_ui()
load_translation(machine().options());
}
ui_globals::reset = true;
+
+ if (m_handler)
+ m_handler();
}
//-------------------------------------------------
@@ -91,7 +96,14 @@ void menu_custom_ui::handle()
{
case FONT_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
- menu::stack_push<menu_font_ui>(ui(), container());
+ menu::stack_push<menu_font_ui>(
+ ui(),
+ container(),
+ [this] (bool changed)
+ {
+ if (changed)
+ reset(reset_options::REMEMBER_REF);
+ });
break;
case COLORS_MENU:
if (menu_event->iptkey == IPT_UI_SELECT)
@@ -182,9 +194,19 @@ void menu_custom_ui::custom_render(void *selectedref, float top, float bottom, f
// ctor
//-------------------------------------------------
-menu_font_ui::menu_font_ui(mame_ui_manager &mui, render_container &container) : menu(mui, container)
+menu_font_ui::menu_font_ui(mame_ui_manager &mui, render_container &container, std::function<void (bool)> &&handler)
+ : menu(mui, container)
+ , m_handler(std::move(handler))
+ , m_fonts()
+ , m_font_min(atof(mui.options().get_entry(OPTION_FONT_ROWS)->minimum()))
+ , m_font_max(atof(mui.options().get_entry(OPTION_FONT_ROWS)->maximum()))
+ , m_font_size(mui.options().font_rows())
+ , m_info_min(atof(mui.options().get_entry(OPTION_INFOS_SIZE)->minimum()))
+ , m_info_max(atof(mui.options().get_entry(OPTION_INFOS_SIZE)->maximum()))
+ , m_info_size(mui.options().infos_size())
+ , m_changed(false)
+ , m_actual(0U)
{
- ui_options &moptions = mui.options();
std::string name(mui.machine().options().ui_font());
list();
@@ -192,7 +214,6 @@ menu_font_ui::menu_font_ui(mame_ui_manager &mui, render_container &container) :
m_bold = (strreplace(name, "[B]", "") + strreplace(name, "[b]", "") > 0);
m_italic = (strreplace(name, "[I]", "") + strreplace(name, "[i]", "") > 0);
#endif
- m_actual = 0;
for (std::size_t index = 0; index < m_fonts.size(); index++)
{
@@ -202,13 +223,6 @@ menu_font_ui::menu_font_ui(mame_ui_manager &mui, render_container &container) :
break;
}
}
-
- m_info_size = moptions.infos_size();
- m_font_size = moptions.font_rows();
- m_info_max = atof(moptions.get_entry(OPTION_INFOS_SIZE)->maximum());
- m_info_min = atof(moptions.get_entry(OPTION_INFOS_SIZE)->minimum());
- m_font_max = atof(moptions.get_entry(OPTION_FONT_ROWS)->maximum());
- m_font_min = atof(moptions.get_entry(OPTION_FONT_ROWS)->minimum());
}
//-------------------------------------------------
@@ -229,25 +243,30 @@ void menu_font_ui::list()
menu_font_ui::~menu_font_ui()
{
- std::string error_string;
- ui_options &moptions = ui().options();
+ if (m_changed)
+ {
+ ui_options &moptions = ui().options();
- std::string name(m_fonts[m_actual].first);
+ std::string name(m_fonts[m_actual].first);
#ifdef UI_WINDOWS
- if (name != "default")
- {
- if (m_italic)
- name.insert(0, "[I]");
- if (m_bold)
- name.insert(0, "[B]");
- }
+ if (name != "default")
+ {
+ if (m_italic)
+ name.insert(0, "[I]");
+ if (m_bold)
+ name.insert(0, "[B]");
+ }
#endif
- machine().options().set_value(OPTION_UI_FONT, name, OPTION_PRIORITY_CMDLINE);
- moptions.set_value(OPTION_INFOS_SIZE, m_info_size, OPTION_PRIORITY_CMDLINE);
- moptions.set_value(OPTION_FONT_ROWS, m_font_size, OPTION_PRIORITY_CMDLINE);
+ machine().options().set_value(OPTION_UI_FONT, name, OPTION_PRIORITY_CMDLINE);
+ moptions.set_value(OPTION_INFOS_SIZE, m_info_size, OPTION_PRIORITY_CMDLINE);
+ moptions.set_value(OPTION_FONT_ROWS, m_font_size, OPTION_PRIORITY_CMDLINE);
+
+ // OPTION_FONT_ROWS was changed; update the font info
+ ui().update_target_font_height();
+ }
- // OPTION_FONT_ROWS was changed; update the font info
- ui().update_target_font_height();
+ if (m_handler)
+ m_handler(m_changed);
}
//-------------------------------------------------
@@ -261,7 +280,8 @@ void menu_font_ui::handle()
// process the menu
const event *menu_event = process(PROCESS_LR_REPEAT);
- if (menu_event != nullptr && menu_event->itemref != nullptr)
+ if (menu_event && menu_event->itemref)
+ {
switch ((uintptr_t)menu_event->itemref)
{
case INFOS_SIZE:
@@ -297,10 +317,10 @@ void menu_font_ui::handle()
ui(), container(), std::move(display_names), m_actual,
[this] (int selection)
{
+ m_changed = true;
m_actual = selection;
reset(reset_options::REMEMBER_REF);
});
- changed = true;
}
break;
@@ -315,9 +335,13 @@ void menu_font_ui::handle()
break;
#endif
}
+ }
if (changed)
+ {
+ m_changed = true;
reset(reset_options::REMEMBER_REF);
+ }
}
//-------------------------------------------------
diff --git a/src/frontend/mame/ui/custui.h b/src/frontend/mame/ui/custui.h
index a419e424375..2da5cfd132b 100644
--- a/src/frontend/mame/ui/custui.h
+++ b/src/frontend/mame/ui/custui.h
@@ -15,7 +15,11 @@
#include "ui/menu.h"
+#include <functional>
+
+
namespace ui {
+
//-------------------------------------------------
// Custom UI menu
//-------------------------------------------------
@@ -23,7 +27,7 @@ namespace ui {
class menu_custom_ui : public menu
{
public:
- menu_custom_ui(mame_ui_manager &mui, render_container &container);
+ menu_custom_ui(mame_ui_manager &mui, render_container &container, std::function<void ()> &&handler);
virtual ~menu_custom_ui() override;
protected:
@@ -43,6 +47,7 @@ private:
static const char *const HIDE_STATUS[];
+ std::function<void ()> m_handler;
std::vector<std::string> m_lang;
std::uint16_t m_currlang;
};
@@ -54,7 +59,7 @@ private:
class menu_font_ui : public menu
{
public:
- menu_font_ui(mame_ui_manager &mui, render_container &container);
+ menu_font_ui(mame_ui_manager &mui, render_container &container, std::function<void (bool)> &&handler);
virtual ~menu_font_ui() override;
protected:
@@ -75,14 +80,19 @@ private:
void list();
+ std::function<void (bool)> m_handler;
+ std::vector<std::pair<std::string, std::string> > m_fonts;
+ const int m_font_min, m_font_max;
+ int m_font_size;
+ const float m_info_min, m_info_max;
+ float m_info_size;
+ bool m_changed;
+
std::uint16_t m_actual;
- std::vector<std::pair<std::string, std::string> > m_fonts;
#ifdef UI_WINDOWS
bool m_bold, m_italic;
#endif
- float m_info_min, m_info_max, m_info_size;
- int m_font_min, m_font_max, m_font_size;
};
//-------------------------------------------------
diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp
index cc91e92766e..182a2201d83 100644
--- a/src/frontend/mame/ui/inputmap.cpp
+++ b/src/frontend/mame/ui/inputmap.cpp
@@ -19,25 +19,6 @@
namespace ui {
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define MAX_PHYSICAL_DIPS 10
-#define MAX_INPUT_PORTS 32
-#define MAX_BITS_PER_PORT 32
-
-/* DIP switch rendering parameters */
-#define DIP_SWITCH_HEIGHT 0.05f
-#define DIP_SWITCH_SPACING 0.01f
-#define SINGLE_TOGGLE_SWITCH_FIELD_WIDTH 0.025f
-#define SINGLE_TOGGLE_SWITCH_WIDTH 0.020f
-/* make the switch 80% of the width space and 1/2 of the switch height */
-#define PERCENTAGE_OF_HALF_FIELD_USED 0.80f
-#define SINGLE_TOGGLE_SWITCH_HEIGHT ((DIP_SWITCH_HEIGHT / 2) * PERCENTAGE_OF_HALF_FIELD_USED)
-
-
-
/*-------------------------------------------------
menu_input_groups_populate - populate the
input groups menu
@@ -440,304 +421,4 @@ void menu_input::populate_sorted(std::vector<input_item_data *> &&itemarray)
}
}
-
-/*-------------------------------------------------
- menu_settings_dip_switches - handle the DIP
- switches menu
--------------------------------------------------*/
-
-menu_settings_dip_switches::menu_settings_dip_switches(mame_ui_manager &mui, render_container &container) : menu_settings(mui, container, IPT_DIPSWITCH)
-{
-}
-
-menu_settings_dip_switches::~menu_settings_dip_switches()
-{
-}
-
-/*-------------------------------------------------
- menu_settings_driver_config - handle the
- driver config menu
--------------------------------------------------*/
-
-menu_settings_driver_config::menu_settings_driver_config(mame_ui_manager &mui, render_container &container) : menu_settings(mui, container, IPT_CONFIG)
-{
-}
-
-menu_settings_driver_config::~menu_settings_driver_config()
-{
-}
-
-/*-------------------------------------------------
- menu_settings_common - handle one of the
- switches menus
--------------------------------------------------*/
-
-void menu_settings::handle()
-{
- // process the menu
- const event *menu_event = process(0);
-
- // handle events
- if (menu_event != nullptr && menu_event->itemref != nullptr)
- {
- // reset
- if ((uintptr_t)menu_event->itemref == 1)
- {
- if (menu_event->iptkey == IPT_UI_SELECT)
- machine().schedule_hard_reset();
- }
- // actual settings
- else
- {
- ioport_field *field = (ioport_field *)menu_event->itemref;
- ioport_field::user_settings settings;
- int changed = false;
-
- switch (menu_event->iptkey)
- {
- /* if selected, reset to default value */
- case IPT_UI_SELECT:
- field->get_user_settings(settings);
- settings.value = field->defvalue();
- field->set_user_settings(settings);
- changed = true;
- break;
-
- /* left goes to previous setting */
- case IPT_UI_LEFT:
- field->select_previous_setting();
- changed = true;
- break;
-
- /* right goes to next setting */
- case IPT_UI_RIGHT:
- field->select_next_setting();
- changed = true;
- break;
- }
-
- /* if anything changed, rebuild the menu, trying to stay on the same field */
- if (changed)
- reset(reset_options::REMEMBER_REF);
- }
- }
-}
-
-
-/*-------------------------------------------------
- menu_settings_populate - populate one of the
- switches menus
--------------------------------------------------*/
-
-menu_settings::menu_settings(mame_ui_manager &mui, render_container &container, uint32_t _type) : menu(mui, container), diplist(nullptr), dipcount(0)
-{
- type = _type;
-}
-
-void menu_settings::populate(float &customtop, float &custombottom)
-{
- dip_descriptor **diplist_tailptr;
- std::string prev_owner;
- bool first_entry = true;
-
- /* reset the dip switch tracking */
- dipcount = 0;
- diplist = nullptr;
- diplist_tailptr = &diplist;
-
- /* loop over input ports and set up the current values */
- for (auto &port : machine().ioport().ports())
- for (ioport_field &field : port.second->fields())
- if (field.type() == type && field.enabled())
- {
- if (!field.settings().empty())
- {
- uint32_t flags = 0;
-
- /* set the left/right flags appropriately */
- if (field.has_previous_setting())
- flags |= FLAG_LEFT_ARROW;
- if (field.has_next_setting())
- flags |= FLAG_RIGHT_ARROW;
-
- /* add the menu item */
- if (strcmp(field.device().tag(), prev_owner.c_str()) != 0)
- {
- if (first_entry)
- first_entry = false;
- else
- item_append(menu_item_type::SEPARATOR);
- string_format("[root%s]", field.device().tag());
- item_append(string_format("[root%s]", field.device().tag()), "", 0, nullptr);
- prev_owner.assign(field.device().tag());
- }
-
- item_append(field.name(), field.setting_name(), flags, (void *)&field);
- }
-
- /* for DIP switches, build up the model */
- if (type == IPT_DIPSWITCH && !field.diplocations().empty())
- {
- ioport_field::user_settings settings;
- uint32_t accummask = field.mask();
-
- /* get current settings */
- field.get_user_settings(settings);
-
- /* iterate over each bit in the field */
- for (const ioport_diplocation &diploc : field.diplocations())
- {
- uint32_t mask = accummask & ~(accummask - 1);
- dip_descriptor *dip;
-
- /* find the matching switch name */
- for (dip = diplist; dip != nullptr; dip = dip->next)
- if (dip->owner == &field.device() && strcmp(dip->name, diploc.name()) == 0)
- break;
-
- /* allocate new if none */
- if (dip == nullptr)
- {
- dip = (dip_descriptor *)m_pool_alloc(sizeof(*dip));
- dip->next = nullptr;
- dip->name = diploc.name();
- dip->owner = &field.device();
- dip->mask = dip->state = 0;
- *diplist_tailptr = dip;
- diplist_tailptr = &dip->next;
- dipcount++;
- }
-
- /* apply the bits */
- dip->mask |= 1 << (diploc.number() - 1);
- if (((settings.value & mask) != 0 && !diploc.inverted()) || ((settings.value & mask) == 0 && diploc.inverted()))
- dip->state |= 1 << (diploc.number() - 1);
-
- /* clear the relevant bit in the accumulated mask */
- accummask &= ~mask;
- }
- }
- }
- if (type == IPT_DIPSWITCH)
- custombottom = dipcount ? dipcount * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) + DIP_SWITCH_SPACING : 0;
-
- item_append(menu_item_type::SEPARATOR);
- item_append(_("Reset"), "", 0, (void *)1);
-}
-
-menu_settings::~menu_settings()
-{
-}
-
-/*-------------------------------------------------
- menu_settings_custom_render - perform our special
- rendering
--------------------------------------------------*/
-
-void menu_settings_dip_switches::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
-{
- // catch if no diploc has to be drawn
- if (bottom == 0)
- return;
-
- // add borders
- y1 = y2 + ui().box_tb_border();
- y2 = y1 + bottom;
-
- // draw extra menu area
- ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color());
- y1 += (float)DIP_SWITCH_SPACING;
-
- // iterate over DIP switches
- for (dip_descriptor *dip = diplist; dip != nullptr; dip = dip->next)
- {
- uint32_t selectedmask = 0;
-
- // determine the mask of selected bits
- if ((uintptr_t)selectedref != 1)
- {
- ioport_field *field = (ioport_field *)selectedref;
-
- if (field != nullptr && !field->diplocations().empty())
- for (const ioport_diplocation &diploc : field->diplocations())
- if (dip->owner == &field->device() && strcmp(dip->name, diploc.name()) == 0)
- selectedmask |= 1 << (diploc.number() - 1);
- }
-
- // draw one switch
- custom_render_one(x1, y1, x2, y1 + DIP_SWITCH_HEIGHT, dip, selectedmask);
- y1 += (float)(DIP_SWITCH_SPACING + DIP_SWITCH_HEIGHT);
- }
-}
-
-
-/*-------------------------------------------------
- menu_settings_custom_render_one - draw a single
- DIP switch
--------------------------------------------------*/
-
-void menu_settings_dip_switches::custom_render_one(float x1, float y1, float x2, float y2, const dip_descriptor *dip, uint32_t selectedmask)
-{
- float switch_field_width = SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * container().manager().ui_aspect();
- float switch_width = SINGLE_TOGGLE_SWITCH_WIDTH * container().manager().ui_aspect();
- int numtoggles, toggle;
- float switch_toggle_gap;
- float y1_off, y1_on;
-
- /* determine the number of toggles in the DIP */
- numtoggles = 32 - count_leading_zeros(dip->mask);
-
- /* center based on the number of switches */
- x1 += (x2 - x1 - numtoggles * switch_field_width) / 2;
-
- /* draw the dip switch name */
- ui().draw_text_full(container(),
- dip->name,
- 0,
- y1 + (DIP_SWITCH_HEIGHT - ui().target_font_height()) / 2,
- x1 - ui().get_string_width(" "),
- ui::text_layout::RIGHT,
- ui::text_layout::NEVER,
- mame_ui_manager::NORMAL,
- ui().colors().text_color(),
- PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA),
- nullptr ,
- nullptr);
-
- /* compute top and bottom for on and off positions */
- switch_toggle_gap = ((DIP_SWITCH_HEIGHT/2) - SINGLE_TOGGLE_SWITCH_HEIGHT)/2;
- y1_off = y1 + UI_LINE_WIDTH + switch_toggle_gap;
- y1_on = y1 + DIP_SWITCH_HEIGHT/2 + switch_toggle_gap;
-
- /* iterate over toggles */
- for (toggle = 0; toggle < numtoggles; toggle++)
- {
- float innerx1;
-
- /* first outline the switch */
- ui().draw_outlined_box(container(), x1, y1, x1 + switch_field_width, y2, ui().colors().background_color());
-
- /* compute x1/x2 for the inner filled in switch */
- innerx1 = x1 + (switch_field_width - switch_width) / 2;
-
- /* see if the switch is actually used */
- if (dip->mask & (1 << toggle))
- {
- float innery1 = (dip->state & (1 << toggle)) ? y1_on : y1_off;
- container().add_rect(innerx1, innery1, innerx1 + switch_width, innery1 + SINGLE_TOGGLE_SWITCH_HEIGHT,
- (selectedmask & (1 << toggle)) ? ui().colors().dipsw_color() : ui().colors().text_color(),
- PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- }
- else
- {
- container().add_rect(innerx1, y1_off, innerx1 + switch_width, y1_on + SINGLE_TOGGLE_SWITCH_HEIGHT,
- ui().colors().unavailable_color(),
- PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- }
-
- /* advance to the next switch */
- x1 += switch_field_width;
- }
-}
-
} // namespace ui
diff --git a/src/frontend/mame/ui/inputmap.h b/src/frontend/mame/ui/inputmap.h
index d0ffc4ec12c..bfb6dbcec17 100644
--- a/src/frontend/mame/ui/inputmap.h
+++ b/src/frontend/mame/ui/inputmap.h
@@ -7,7 +7,6 @@
Internal menus for input mappings.
***************************************************************************/
-
#ifndef MAME_FRONTEND_UI_INPUTMAP_H
#define MAME_FRONTEND_UI_INPUTMAP_H
@@ -99,52 +98,6 @@ private:
virtual void update_input(struct input_item_data *seqchangeditem) override;
};
-class menu_settings : public menu
-{
-public:
- menu_settings(mame_ui_manager &mui, render_container &container, uint32_t type);
- virtual ~menu_settings() override;
-
-protected:
- /* DIP switch descriptor */
- struct dip_descriptor
- {
- dip_descriptor * next;
- const char * name;
- device_t * owner;
- uint32_t mask;
- uint32_t state;
- };
-
- dip_descriptor * diplist;
- int dipcount;
- int type;
-
-private:
- virtual void populate(float &customtop, float &custombottom) override;
- virtual void handle() override;
-};
-
-class menu_settings_dip_switches : public menu_settings
-{
-public:
- menu_settings_dip_switches(mame_ui_manager &mui, render_container &container);
- virtual ~menu_settings_dip_switches() override;
-
-protected:
- virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override;
-
-private:
- void custom_render_one(float x1, float y1, float x2, float y2, const dip_descriptor *dip, uint32_t selectedmask);
-};
-
-class menu_settings_driver_config : public menu_settings
-{
-public:
- menu_settings_driver_config(mame_ui_manager &mui, render_container &container);
- virtual ~menu_settings_driver_config();
-};
-
} // namespace ui
#endif // MAME_FRONTEND_UI_INPUTMAP_H
diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp
index 10cbced036d..c6052ae2fd6 100644
--- a/src/frontend/mame/ui/mainmenu.cpp
+++ b/src/frontend/mame/ui/mainmenu.cpp
@@ -14,6 +14,7 @@
#include "ui/analogipt.h"
#include "ui/barcode.h"
#include "ui/cheatopt.h"
+#include "ui/confswitch.h"
#include "ui/datmenu.h"
#include "ui/filemngr.h"
#include "ui/info.h"
@@ -163,7 +164,7 @@ void menu_main::handle()
break;
case SETTINGS_DRIVER_CONFIG:
- menu::stack_push<menu_settings_driver_config>(ui(), container());
+ menu::stack_push<menu_settings_machine_config>(ui(), container());
break;
case ANALOG:
diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp
index 0c263e2b875..b7a52f2a4e5 100644
--- a/src/frontend/mame/ui/miscmenu.cpp
+++ b/src/frontend/mame/ui/miscmenu.cpp
@@ -28,6 +28,7 @@
#include <fstream>
namespace ui {
+
/***************************************************************************
MENU HANDLERS
***************************************************************************/
diff --git a/src/frontend/mame/ui/optsmenu.cpp b/src/frontend/mame/ui/optsmenu.cpp
index 497d527e6cf..17dddd10c67 100644
--- a/src/frontend/mame/ui/optsmenu.cpp
+++ b/src/frontend/mame/ui/optsmenu.cpp
@@ -282,7 +282,7 @@ void menu_game_options::handle_item_event(event const &menu_event)
break;
case CUSTOM_MENU:
if (menu_event.iptkey == IPT_UI_SELECT)
- menu::stack_push<menu_custom_ui>(ui(), container());
+ menu::stack_push<menu_custom_ui>(ui(), container(), [this] () { reset(reset_options::REMEMBER_REF); });
break;
default:
menu_simple_game_options::handle_item_event(menu_event);