From d6dd21e2013c80ecbc97dc3cce3df964e8e4c2aa Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sun, 10 May 2026 03:07:34 +1000 Subject: 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. --- src/emu/ioport.cpp | 42 ++++++++++++++++++++++++++---------------- src/emu/ioport.h | 16 ++++++++-------- src/emu/validity.cpp | 33 +++++++++++---------------------- src/emu/validity.h | 5 +++-- 4 files changed, 48 insertions(+), 48 deletions(-) (limited to 'src/emu') 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 #include #include +#include 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(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 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(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 @@ -116,17 +116,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(uintptr_t(index))); -} - - //------------------------------------------------- // random_u64 // random_s64 @@ -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; + using input_string_map = std::unordered_map; using int_map = std::unordered_map; using string_set = std::unordered_set; // 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; -- cgit v1.2.3