summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2026-05-10 03:07:34 +1000
committer Vas Crabb <vas@vastheman.com>2026-05-10 03:34:22 +1000
commitd6dd21e2013c80ecbc97dc3cce3df964e8e4c2aa (patch)
tree8a42e21bf7ed3fe4bad8769fcd8aa52b8469a48c /src/emu
parent937399619268781d75a0f04edf5b2fd9e247ce38 (diff)
ui: Improved media control experience, cleaned up a lot of bad code.
ui/imgcntrl, ui/floppycntrl.cpp: Completely reworked logic - backtracking through menus is more intuitive, and more context is retained when encountering an error (it should be a bit easier to follow the code as well). ui/floppycntrl.cpp: Don't show the initial content selection menu when opening an image to read from while writing to a separate file. ui/filecreate.cpp: Moved the logic to enumerate floppy formats into the menu, use headings and separators, use callbacks to notify when an item is selected, don't pop menus when an item is selected, avoid actual work in destructors. ui/midiinout.cpp: Fixed infinite growth when repopulating the menu, don't pop the menu when a port is chosen, use a callback to notify that a port is chosen, use headings and separators, and in informative placeholder if no ports are available. ui/filesel.cpp: Don't show the option to write to a floppy diff (it still isn't implemented, it can be re-added if it's ever implemented), don't pop the menus when selecting an item, avoid actual work in destructors. ui/filemngr.cpp: Show more detail in the info box below the menu for software items and presets, substantially simplified the code for walking media devices. ui/info.cpp: Got rid of the media information menu, added media information to the system information menu. ui/menu.cpp: Allow immediately adjusting the hovered item with pen/mouse, saving a click. emu/ioport: Fixed incorrect strings displayed for 4C_5C, 3C_4C, 2C_3C and 3C_5C. The array absolutely must stay in order. Also added an assertion to catch these errors early. emu/ioport.cpp: Use a much less gross method of handling default strings (apparently someone forgot about function overloading). emu/ioport.cpp: Retired the crosshair mapper member macros - they don't serve much purpose. util/zippath.cpp: Actually report a failure to open a plain file rather than looking for files inside non-existent archives, making every error turn into "file not found". formats/flopimg.cpp: Allow matching extensions on string object names, rather than requiring a NUL-terminated string.
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/ioport.cpp42
-rw-r--r--src/emu/ioport.h16
-rw-r--r--src/emu/validity.cpp33
-rw-r--r--src/emu/validity.h5
4 files changed, 48 insertions, 48 deletions
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index fc5a0de293c..12707741cd3 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -33,6 +33,7 @@
#include <cctype>
#include <ctime>
#include <sstream>
+#include <type_traits>
namespace {
@@ -111,7 +112,7 @@ inline u8 compute_shift(ioport_value mask)
const struct
{
- u32 id;
+ input_string_index id;
const char *string;
} input_port_default_strings[] =
{
@@ -145,10 +146,10 @@ const struct
{ INPUT_STRING_3C_3C, "3 Coins/3 Credits" },
{ INPUT_STRING_2C_2C, "2 Coins/2 Credits" },
{ INPUT_STRING_1C_1C, "1 Coin/1 Credit" },
- { INPUT_STRING_3C_5C, "3 Coins/5 Credits" },
{ INPUT_STRING_4C_5C, "4 Coins/5 Credits" },
{ INPUT_STRING_3C_4C, "3 Coins/4 Credits" },
{ INPUT_STRING_2C_3C, "2 Coins/3 Credits" },
+ { INPUT_STRING_3C_5C, "3 Coins/5 Credits" },
{ INPUT_STRING_4C_7C, "4 Coins/7 Credits" },
{ INPUT_STRING_2C_4C, "2 Coins/4 Credits" },
{ INPUT_STRING_1C_2C, "1 Coin/2 Credits" },
@@ -3304,27 +3305,21 @@ ioport_configurer& ioport_configurer::field_set_gm_note(u8 note)
// ioport_token to a default string
//-------------------------------------------------
-const char *ioport_configurer::string_from_token(const char *string)
+const char *ioport_configurer::string_from_token(input_string_index string)
{
- // 0 is an invalid index
- if (string == nullptr)
- return nullptr;
-
- // if the index is greater than the count, assume it to be a pointer
- if (uintptr_t(string) >= INPUT_STRING_COUNT)
- return string;
-
-#if false // Set true, If you want to take care missing-token or wrong-sorting
+#if 0 // Set true, If you want to take care missing-token or wrong-sorting
// otherwise, scan the list for a matching string and return it
for (int index = 0; index < std::size(input_port_default_strings); index++)
- if (input_port_default_strings[index].id == uintptr_t(string))
+ if (input_port_default_strings[index].id == string)
return input_port_default_strings[index].string;
return "(Unknown Default)";
#else
- return input_port_default_strings[uintptr_t(string)-1].string;
+ auto const index = std::underlying_type_t<input_string_index>(string) - 1;
+ assert(input_port_default_strings[index].id == string);
+ return input_port_default_strings[index].string;
#endif
}
@@ -3384,7 +3379,7 @@ ioport_configurer& ioport_configurer::field_alloc(ioport_type type, ioport_value
// append the field
if (type != IPT_UNKNOWN && type != IPT_UNUSED)
m_curport->m_active |= mask;
- m_curfield = &m_curport->m_fieldlist.append(*new ioport_field(*m_curport, type, defval, mask, string_from_token(name)));
+ m_curfield = &m_curport->m_fieldlist.append(*new ioport_field(*m_curport, type, defval, mask, name));
// reset the current setting
m_cursetting = nullptr;
@@ -3392,6 +3387,11 @@ ioport_configurer& ioport_configurer::field_alloc(ioport_type type, ioport_value
return *this;
}
+ioport_configurer& ioport_configurer::field_alloc(ioport_type type, ioport_value defval, ioport_value mask, input_string_index name)
+{
+ return field_alloc(type, defval, mask, string_from_token(name));
+}
+
//-------------------------------------------------
// field_add_char - add a character to a field
@@ -3444,10 +3444,15 @@ ioport_configurer& ioport_configurer::setting_alloc(ioport_value value, const ch
throw emu_fatalerror("setting_alloc called with no active field (value=%X name=%s)\n", value, name);
// append a new setting
- m_cursetting = &m_curfield->m_settinglist.emplace_back(*m_curfield, value & m_curfield->mask(), string_from_token(name));
+ m_cursetting = &m_curfield->m_settinglist.emplace_back(*m_curfield, value & m_curfield->mask(), name);
return *this;
}
+ioport_configurer& ioport_configurer::setting_alloc(ioport_value value, input_string_index name)
+{
+ return setting_alloc(value, string_from_token(name));
+}
+
//-------------------------------------------------
// set_condition - set the condition for either
@@ -3483,6 +3488,11 @@ ioport_configurer& ioport_configurer::onoff_alloc(const char *name, ioport_value
return *this;
}
+ioport_configurer& ioport_configurer::onoff_alloc(input_string_index name, ioport_value defval, ioport_value mask, const char *diplocation)
+{
+ return onoff_alloc(string_from_token(name), defval, mask, diplocation);
+}
+
/***************************************************************************
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index d018cdf1ffa..b40b0272086 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -97,7 +97,7 @@ enum ioport_type_class
// default strings used in port definitions
-enum
+enum input_string_index
{
INPUT_STRING_Off = 1,
INPUT_STRING_On,
@@ -1035,7 +1035,7 @@ public:
ioport_configurer(device_t &owner, ioport_list &portlist, std::ostream &errorbuf);
// static helpers
- static const char *string_from_token(const char *string);
+ static const char *string_from_token(input_string_index string);
// port helpers
ioport_configurer& port_alloc(const char *tag);
@@ -1043,10 +1043,12 @@ public:
// field helpers
ioport_configurer& field_alloc(ioport_type type, ioport_value defval, ioport_value mask, const char *name = nullptr);
+ ioport_configurer& field_alloc(ioport_type type, ioport_value defval, ioport_value mask, input_string_index name);
ioport_configurer& field_add_char(std::initializer_list<char32_t> charlist);
ioport_configurer& field_add_code(input_seq_type which, input_code code);
ioport_configurer& field_set_way(int way) { m_curfield->m_way = way; return *this; }
- ioport_configurer& field_set_name(const char *name) { assert(m_curfield != nullptr); m_curfield->m_name = string_from_token(name); return *this; }
+ ioport_configurer& field_set_name(const char *name) { assert(m_curfield != nullptr); m_curfield->m_name = name; return *this; }
+ ioport_configurer& field_set_name(input_string_index name) { assert(m_curfield != nullptr); m_curfield->m_name = string_from_token(name); return *this; }
ioport_configurer& field_set_player(int player) { m_curfield->m_player = player - 1; return *this; }
ioport_configurer& field_set_cocktail() { m_curfield->m_flags |= ioport_field::FIELD_FLAG_COCKTAIL; field_set_player(2); return *this; }
ioport_configurer& field_set_toggle() { m_curfield->m_flags |= ioport_field::FIELD_FLAG_TOGGLE; return *this; }
@@ -1071,10 +1073,12 @@ public:
// setting helpers
ioport_configurer& setting_alloc(ioport_value value, const char *name);
+ ioport_configurer& setting_alloc(ioport_value value, input_string_index name);
// misc helpers
ioport_configurer& set_condition(ioport_condition::condition_t condition, const char *tag, ioport_value mask, ioport_value value);
ioport_configurer& onoff_alloc(const char *name, ioport_value defval, ioport_value mask, const char *diplocation);
+ ioport_configurer& onoff_alloc(input_string_index name, ioport_value defval, ioport_value mask, const char *diplocation);
// allow UTF-8 strings to be used for names transparently
ioport_configurer& field_alloc(ioport_type type, ioport_value defval, ioport_value mask, const char8_t *name) { return field_alloc(type, defval, mask, reinterpret_cast<const char *>(name)); }
@@ -1106,12 +1110,8 @@ private:
#define INPUT_CHANGED_MEMBER(name) void name(ioport_field &field, u32 param, ioport_value oldval, ioport_value newval)
#define DECLARE_INPUT_CHANGED_MEMBER(name) void name(ioport_field &field, u32 param, ioport_value oldval, ioport_value newval)
-// macro for port changed callback functions (PORT_CROSSHAIR_MAPPER)
-#define CROSSHAIR_MAPPER_MEMBER(name) float name(float linear_value)
-#define DECLARE_CROSSHAIR_MAPPER_MEMBER(name) float name(float linear_value)
-
// macro for wrapping a default string
-#define DEF_STR(str_num) ((const char *)INPUT_STRING_##str_num)
+#define DEF_STR(str_num) (INPUT_STRING_##str_num)
diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp
index b65e1faf3c9..e93ee223be4 100644
--- a/src/emu/validity.cpp
+++ b/src/emu/validity.cpp
@@ -117,17 +117,6 @@ struct pure_virtual_base
//-------------------------------------------------
-// ioport_string_from_index - return an indexed
-// string from the I/O port system
-//-------------------------------------------------
-
-inline char const *ioport_string_from_index(u32 index)
-{
- return ioport_configurer::string_from_token(reinterpret_cast<char const *>(uintptr_t(index)));
-}
-
-
-//-------------------------------------------------
// random_u64
// random_s64
// random_u32
@@ -1894,13 +1883,13 @@ void validate_delegates_functoid()
// strings
//-------------------------------------------------
-inline int validity_checker::get_defstr_index(const char *string, bool suppress_error)
+inline input_string_index validity_checker::get_defstr_index(const char *string, bool suppress_error)
{
// check for strings that should be DEF_STR
- auto strindex = m_defstr_map.find(string);
- if (!suppress_error && strindex != m_defstr_map.end() && string != ioport_string_from_index(strindex->second))
+ auto const strindex = m_defstr_map.find(string);
+ if (!suppress_error && (strindex != m_defstr_map.end()) && (string != ioport_configurer::string_from_token(strindex->second)))
osd_printf_error("Must use DEF_STR( %s )\n", string);
- return (strindex != m_defstr_map.end()) ? strindex->second : 0;
+ return (strindex != m_defstr_map.end()) ? strindex->second : input_string_index(0);
}
@@ -1978,9 +1967,9 @@ validity_checker::validity_checker(emu_options &options, bool quick)
// pre-populate the defstr map with all the default strings
for (int strnum = 1; strnum < INPUT_STRING_COUNT; strnum++)
{
- const char *string = ioport_string_from_index(strnum);
+ const char *string = ioport_configurer::string_from_token(input_string_index(strnum));
if (string != nullptr)
- m_defstr_map.insert(std::make_pair(string, strnum));
+ m_defstr_map.emplace(string, input_string_index(strnum));
}
}
@@ -2579,8 +2568,8 @@ void validity_checker::validate_analog_input_field(const ioport_field &field)
void validity_checker::validate_dip_settings(const ioport_field &field)
{
- char const *const demo_sounds = ioport_string_from_index(INPUT_STRING_Demo_Sounds);
- char const *const flipscreen = ioport_string_from_index(INPUT_STRING_Flip_Screen);
+ char const *const demo_sounds = ioport_configurer::string_from_token(INPUT_STRING_Demo_Sounds);
+ char const *const flipscreen = ioport_configurer::string_from_token(INPUT_STRING_Flip_Screen);
char const *const name = field.specific_name() ? field.specific_name() : "UNNAMED";
u8 coin_list[__input_string_coinage_end + 1 - __input_string_coinage_start] = { 0 };
bool coin_error = false;
@@ -2589,7 +2578,7 @@ void validity_checker::validate_dip_settings(const ioport_field &field)
for (auto setting = field.settings().begin(); field.settings().end() != setting; ++setting)
{
// note any coinage strings
- int strindex = get_defstr_index(setting->name());
+ input_string_index const strindex = get_defstr_index(setting->name());
if (strindex >= __input_string_coinage_start && strindex <= __input_string_coinage_end)
coin_list[strindex - __input_string_coinage_start] = 1;
@@ -2610,7 +2599,7 @@ void validity_checker::validate_dip_settings(const ioport_field &field)
if (field.settings().end() != nextsetting)
{
// check for inverted off/on DIP switch order
- int next_strindex = get_defstr_index(nextsetting->name(), true);
+ input_string_index next_strindex = get_defstr_index(nextsetting->name(), true);
if (strindex == INPUT_STRING_On && next_strindex == INPUT_STRING_Off)
osd_printf_error("%s option must have Off/On options in the order: Off, On\n", name);
@@ -2638,7 +2627,7 @@ void validity_checker::validate_dip_settings(const ioport_field &field)
output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, " Note proper coin sort order should be:\n");
for (int entry = 0; entry < std::size(coin_list); entry++)
if (coin_list[entry])
- output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, " %s\n", ioport_string_from_index(__input_string_coinage_start + entry));
+ output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, " %s\n", ioport_configurer::string_from_token(input_string_index(__input_string_coinage_start + entry)));
}
}
diff --git a/src/emu/validity.h b/src/emu/validity.h
index fbf5f239323..6b15164454e 100644
--- a/src/emu/validity.h
+++ b/src/emu/validity.h
@@ -56,11 +56,12 @@ protected:
private:
// internal map types
using game_driver_map = std::unordered_map<std::string, game_driver const *>;
+ using input_string_map = std::unordered_map<std::string, input_string_index>;
using int_map = std::unordered_map<std::string, uintptr_t>;
using string_set = std::unordered_set<std::string>;
// internal helpers
- int get_defstr_index(const char *string, bool suppress_error = false);
+ input_string_index get_defstr_index(const char *string, bool suppress_error = false);
// core helpers
void validate_begin();
@@ -100,7 +101,7 @@ private:
game_driver_map m_names_map;
game_driver_map m_descriptions_map;
game_driver_map m_roms_map;
- int_map m_defstr_map;
+ input_string_map m_defstr_map;
// current state
game_driver const * m_current_driver;