diff options
Diffstat (limited to 'src')
31 files changed, 1069 insertions, 880 deletions
diff --git a/src/devices/cpu/mcs51/ds5002fp.h b/src/devices/cpu/mcs51/ds5002fp.h index 3b7f8702799..8538c44b25d 100644 --- a/src/devices/cpu/mcs51/ds5002fp.h +++ b/src/devices/cpu/mcs51/ds5002fp.h @@ -6,6 +6,8 @@ #ifndef MAME_CPU_MCS51_DS5002FP_H #define MAME_CPU_MCS51_DS5002FP_H +#pragma once + #include "i8051.h" DECLARE_DEVICE_TYPE(DS5002FP, ds5002fp_device) diff --git a/src/devices/cpu/mcs51/i80c51.h b/src/devices/cpu/mcs51/i80c51.h index 2d5394f763a..d2f347816da 100644 --- a/src/devices/cpu/mcs51/i80c51.h +++ b/src/devices/cpu/mcs51/i80c51.h @@ -4,6 +4,8 @@ #ifndef MAME_CPU_MCS51_I80C51_H #define MAME_CPU_MCS51_I80C51_H +#pragma once + #include "i8051.h" // cmos variants diff --git a/src/devices/cpu/mcs51/i80c52.h b/src/devices/cpu/mcs51/i80c52.h index c472d8d4023..2b4b0f344dd 100644 --- a/src/devices/cpu/mcs51/i80c52.h +++ b/src/devices/cpu/mcs51/i80c52.h @@ -4,6 +4,8 @@ #ifndef MAME_CPU_MCS51_I80C52_H #define MAME_CPU_MCS51_I80C52_H +#pragma once + #include "i8052.h" class i80c52_device : public i8052_device diff --git a/src/devices/cpu/mcs51/sab80c535.h b/src/devices/cpu/mcs51/sab80c535.h index 5c0b2c1cef5..bd25534f566 100644 --- a/src/devices/cpu/mcs51/sab80c535.h +++ b/src/devices/cpu/mcs51/sab80c535.h @@ -4,6 +4,8 @@ #ifndef MAME_CPU_MCS51_SAB80C535_H #define MAME_CPU_MCS51_SAB80C535_H +#pragma once + #include "i80c52.h" class sab80c535_device : public i8052_device 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; diff --git a/src/frontend/mame/ui/filecreate.cpp b/src/frontend/mame/ui/filecreate.cpp index 8dd564aa03b..1d01f5d856e 100644 --- a/src/frontend/mame/ui/filecreate.cpp +++ b/src/frontend/mame/ui/filecreate.cpp @@ -19,7 +19,6 @@ #include "formats/flopimg.h" -#include "path.h" #include "zippath.h" #include <cstring> @@ -31,7 +30,7 @@ namespace ui { CONSTANTS ***************************************************************************/ -// conditional compilation to enable chosing of image formats - this is not +// conditional compilation to enable choosing of image formats - this is not // yet fully implemented #define ENABLE_FORMATS 0 @@ -55,11 +54,14 @@ CONFIRM SAVE AS MENU // ctor //------------------------------------------------- -menu_confirm_save_as::menu_confirm_save_as(mame_ui_manager &mui, render_target &target, bool &yes) +menu_confirm_save_as::menu_confirm_save_as( + mame_ui_manager &mui, + render_target &target, + handler_function &&handler) : menu(mui, target) - , m_yes(yes) + , m_handler(std::move(handler)) { - m_yes = false; + set_needs_prev_menu_item(false); } @@ -78,7 +80,7 @@ menu_confirm_save_as::~menu_confirm_save_as() void menu_confirm_save_as::populate() { - item_append(_("File Already Exists - Override?"), FLAG_DISABLE, nullptr); + item_append(_("File Already Exists - Overwrite?"), FLAG_DISABLE, nullptr); item_append(menu_item_type::SEPARATOR); item_append(_("No"), 0, ITEMREF_NO); item_append(_("Yes"), 0, ITEMREF_YES); @@ -94,10 +96,9 @@ bool menu_confirm_save_as::handle(event const *ev) if (ev && (ev->iptkey == IPT_UI_SELECT)) { if (ev->itemref == ITEMREF_YES) - m_yes = true; - - // no matter what, pop out - stack_pop(); + m_handler(); + else + stack_pop(); } return false; @@ -113,18 +114,21 @@ FILE CREATE MENU // ctor //------------------------------------------------- -menu_file_create::menu_file_create(mame_ui_manager &mui, render_target &target, device_image_interface *image, std::string ¤t_directory, std::string ¤t_file, bool &ok) +menu_file_create::menu_file_create( + mame_ui_manager &mui, + render_target &target, + device_image_interface &image, + std::string_view current_directory, + std::string &&starting_name, + handler_function &&handler) : menu(mui, target) - , m_ok(ok) + , m_handler(std::move(handler)) + , m_image(image) , m_current_directory(current_directory) - , m_current_file(current_file) , m_current_format(nullptr) + , m_filename(std::move(starting_name)) { - m_image = image; - m_ok = false; - m_filename.reserve(1024); - m_filename = core_filename_extract_base(current_file); } @@ -193,7 +197,7 @@ void menu_file_create::populate() item_append(_("New Image Name:"), *new_image_name, 0, ITEMREF_NEW_IMAGE_NAME); // do we support multiple formats? - image_device_format const *const format = ENABLE_FORMATS ? m_image->formatlist().front().get() : nullptr; + image_device_format const *const format = ENABLE_FORMATS ? m_image.formatlist().front().get() : nullptr; if (format) { // FIXME: is this in the right order? It reassigns m_current_format after reading it. @@ -224,15 +228,9 @@ bool menu_file_create::handle(event const *ev) { std::string tmp_file(m_filename); if (tmp_file.find('.') != -1 && tmp_file.find('.') < tmp_file.length() - 1) - { - m_current_file = m_filename; - m_ok = true; - stack_pop(); - } + m_handler(m_filename); else - { - ui().popup_time(1, "%s", _("Please enter a file extension too")); - } + ui().popup_time(1, "%s", _("Please enter a file name extension, too")); } break; @@ -280,12 +278,29 @@ SELECT FORMAT MENU // ctor //------------------------------------------------- -menu_select_format::menu_select_format(mame_ui_manager &mui, render_target &target, const std::vector<const floppy_image_format_t *> &formats, int ext_match, const floppy_image_format_t **result) +menu_select_format::menu_select_format( + mame_ui_manager &mui, + render_target &target, + floppy_image_device &fd, + std::string_view name, + handler_function &&handler) : menu(mui, target) + , m_handler(std::move(handler)) { - m_formats = formats; - m_ext_match = ext_match; - m_result = result; + m_formats.reserve(fd.get_formats().size()); + for (floppy_image_format_t const *i : fd.get_formats()) + { + if (i->supports_save() && i->extension_matches(name)) + m_formats.emplace_back(i); + } + m_ext_match = m_formats.size(); + for (floppy_image_format_t const *i : fd.get_formats()) + { + if (i->supports_save() && !i->extension_matches(name)) + m_formats.emplace_back(i); + } + + set_heading(_("Select image format")); } @@ -304,15 +319,16 @@ menu_select_format::~menu_select_format() void menu_select_format::populate() { - item_append(_("Select image format"), FLAG_DISABLE, nullptr); for (unsigned int i = 0; i != m_formats.size(); i++) { const floppy_image_format_t *fmt = m_formats[i]; - if (i && i == m_ext_match) + if (i && (i == m_ext_match)) item_append(menu_item_type::SEPARATOR); item_append(fmt->description(), fmt->name(), 0, const_cast<floppy_image_format_t *>(fmt)); } + + item_append(menu_item_type::SEPARATOR); } @@ -323,11 +339,8 @@ void menu_select_format::populate() bool menu_select_format::handle(event const *ev) { // process the menu - if (ev && ev->iptkey == IPT_UI_SELECT) - { - *m_result = (floppy_image_format_t *)ev->itemref; - stack_pop(); - } + if (ev && (ev->iptkey == IPT_UI_SELECT)) + m_handler(*reinterpret_cast<floppy_image_format_t const *>(ev->itemref)); return false; } @@ -341,12 +354,16 @@ SELECT FORMAT MENU // ctor //------------------------------------------------- -menu_select_floppy_init::menu_select_floppy_init(mame_ui_manager &mui, render_target &target, std::vector<std::reference_wrapper<const floppy_image_device::fs_info>> &&fs, int *result) +menu_select_floppy_init::menu_select_floppy_init( + mame_ui_manager &mui, + render_target &target, + std::vector<std::reference_wrapper<floppy_image_device::fs_info const> > &&fs, + handler_function &&handler) : menu(mui, target) + , m_handler(std::move(handler)) , m_fs(std::move(fs)) - , m_result(result) - { + set_heading(_("Select initial contents")); } @@ -365,10 +382,9 @@ menu_select_floppy_init::~menu_select_floppy_init() void menu_select_floppy_init::populate() { - item_append(_("Select initial contents"), FLAG_DISABLE, nullptr); - int id = 0; - for (const floppy_image_device::fs_info &fmt : m_fs) - item_append(fmt.m_description, fmt.m_name, 0, (void *)(uintptr_t)(id++)); + for (floppy_image_device::fs_info const &fs : m_fs) + item_append(fs.m_description, fs.m_name, 0, &const_cast<floppy_image_device::fs_info &>(fs)); + item_append(menu_item_type::SEPARATOR); } @@ -380,10 +396,7 @@ bool menu_select_floppy_init::handle(event const *ev) { // process the menu if (ev && ev->iptkey == IPT_UI_SELECT) - { - *m_result = int(uintptr_t(ev->itemref)); - stack_pop(); - } + m_handler(*reinterpret_cast<floppy_image_device::fs_info const *>(ev->itemref)); return false; } diff --git a/src/frontend/mame/ui/filecreate.h b/src/frontend/mame/ui/filecreate.h index 91bdac0ce47..6ecfb354460 100644 --- a/src/frontend/mame/ui/filecreate.h +++ b/src/frontend/mame/ui/filecreate.h @@ -17,6 +17,11 @@ #include "imagedev/floppy.h" +#include <functional> +#include <string> +#include <string_view> +#include <vector> + class floppy_image_format_t; @@ -27,14 +32,16 @@ namespace ui { class menu_confirm_save_as : public menu { public: - menu_confirm_save_as(mame_ui_manager &mui, render_target &target, bool &yes); + using handler_function = std::function<void ()>; + + menu_confirm_save_as(mame_ui_manager &mui, render_target &target, handler_function &&handler); virtual ~menu_confirm_save_as() override; private: virtual void populate() override; virtual bool handle(event const *ev) override; - bool &m_yes; + handler_function m_handler; }; @@ -43,7 +50,15 @@ private: class menu_file_create : public menu { public: - menu_file_create(mame_ui_manager &mui, render_target &target, device_image_interface *image, std::string ¤t_directory, std::string ¤t_file, bool &ok); + using handler_function = std::function<void (std::string const &)>; + + menu_file_create( + mame_ui_manager &mui, + render_target &target, + device_image_interface &image, + std::string_view current_directory, + std::string &&starting_name, + handler_function &&handler); virtual ~menu_file_create() override; protected: @@ -55,11 +70,10 @@ private: virtual void populate() override; virtual bool handle(event const *ev) override; - bool & m_ok; - device_image_interface * m_image; - std::string & m_current_directory; - std::string & m_current_file; - const image_device_format * m_current_format; + handler_function m_handler; + device_image_interface & m_image; + std::string_view const m_current_directory; + image_device_format const * m_current_format; std::string m_filename; }; @@ -68,8 +82,15 @@ private: class menu_select_format : public menu { public: - menu_select_format(mame_ui_manager &mui, render_target &target, - const std::vector<const floppy_image_format_t *> &formats, int ext_match, const floppy_image_format_t **result); + using handler_function = std::function<void (floppy_image_format_t const &)>; + + menu_select_format( + mame_ui_manager &mui, + render_target &target, + floppy_image_device &fd, + std::string_view name, + handler_function &&handler); + virtual ~menu_select_format() override; private: @@ -77,9 +98,9 @@ private: virtual bool handle(event const *ev) override; // internal state - std::vector<const floppy_image_format_t *> m_formats; - int m_ext_match; - const floppy_image_format_t * *m_result; + handler_function const m_handler; + std::vector<floppy_image_format_t const *> m_formats; + size_t m_ext_match; }; // ======================> menu_select_floppy_init @@ -87,8 +108,13 @@ private: class menu_select_floppy_init : public menu { public: - menu_select_floppy_init(mame_ui_manager &mui, render_target &target, - std::vector<std::reference_wrapper<const floppy_image_device::fs_info>> &&fs, int *result); + using handler_function = std::function<void (floppy_image_device::fs_info const &)>; + + menu_select_floppy_init( + mame_ui_manager &mui, + render_target &target, + std::vector<std::reference_wrapper<floppy_image_device::fs_info const> > &&fs, + handler_function &&handler); virtual ~menu_select_floppy_init() override; private: @@ -96,8 +122,8 @@ private: virtual bool handle(event const *ev) override; // internal state - std::vector<std::reference_wrapper<const floppy_image_device::fs_info>> m_fs; - int * m_result; + handler_function const m_handler; + std::vector<std::reference_wrapper<floppy_image_device::fs_info const > > m_fs; }; diff --git a/src/frontend/mame/ui/filemngr.cpp b/src/frontend/mame/ui/filemngr.cpp index 80f6eb067b7..85dd66c6ae3 100644 --- a/src/frontend/mame/ui/filemngr.cpp +++ b/src/frontend/mame/ui/filemngr.cpp @@ -45,7 +45,7 @@ menu_file_manager::menu_file_manager(mame_ui_manager &mui, render_target &target { // The warning string is used when accessing from the force_file_manager call, i.e. // when the file manager is loaded top front in the case of mandatory image devices - set_heading(_("File Manager")); + set_heading(_("Media Control")); } @@ -74,11 +74,11 @@ void menu_file_manager::recompute_metrics(uint32_t width, uint32_t height, float m_warnings_layout.emplace(create_layout(max_width, text_layout::text_justify::LEFT)); m_warnings_layout->add_text(m_warnings, ui().colors().text_color()); - set_custom_space(0.0F, (float(m_warnings_layout->lines() + 1) * line_height()) + (6.0F * tb_border())); + set_custom_space(0.0F, (float(m_warnings_layout->lines() + 3) * line_height()) + (6.0F * tb_border())); } else { - set_custom_space(0.0F, line_height() + (3.0F * tb_border())); + set_custom_space(0.0F, (3.0F * line_height()) + (3.0F * tb_border())); } } @@ -91,7 +91,47 @@ void menu_file_manager::custom_render(uint32_t flags, void *selectedref, float t { // access the path if (m_selected_device && m_selected_device->exists()) - extra_text_render(top, (3.0F * tb_border()) + line_height(), origx1, origy1, origx2, origy2, std::string_view(), m_selected_device->filename()); + { + if (m_selected_device->has_preset_images_selection()) + { + extra_text_render( + top, (3.0F * tb_border()) + line_height(), origx1, origy1, origx2, origy2, + std::string_view(), + util::string_format(_("%1$s preset %2$u"), m_selected_device->filename(), m_selected_device->current_preset_image_id() + 1)); + } + else if (!m_selected_device->loaded_through_softlist()) + { + extra_text_render( + top, (3.0F * tb_border()) + line_height(), origx1, origy1, origx2, origy2, + std::string_view(), + m_selected_device->filename()); + } + else + { + software_info const &swinfo(*m_selected_device->software_entry()); + unsigned const lines((swinfo.supported() == software_support::SUPPORTED) ? 2 : 3); + std::string const line2(util::string_format(_("%1$s, %2$s"), swinfo.publisher(), swinfo.year())); + std::string_view text[3]; + text[0] = swinfo.longname(); + text[1] = line2; + switch (swinfo.supported()) + { + case software_support::UNSUPPORTED: + text[2] = _("Not supported"); + break; + case software_support::PARTIALLY_SUPPORTED: + text[2] = _("Partially supported"); + break; + case software_support::SUPPORTED: + break; + } + draw_text_box( + std::begin(text), std::next(std::begin(text), lines), + origx1, origx2, origy2 + tb_border(), origy2 + (lines * 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()); + } + } // show the warnings if any if (m_warnings_layout) @@ -130,9 +170,9 @@ void menu_file_manager::fill_image_line(device_image_interface &img, std::string software_part const *const part = img.part_entry(); auto const partid = img.get_feature("part_id"); if (partid) - filename = string_format(_("%1$s (%2$s: %3$s)"), img.basename(), part->name(), partid); + filename = string_format(_("%1$s:%2$s (%3$s)"), img.basename(), part->name(), partid); else - filename = string_format(_("%1$s (%2$s)"), img.basename(), part->name()); + filename = string_format(_("%1$s:%2$s"), img.basename(), part->name()); } } @@ -146,64 +186,47 @@ void menu_file_manager::populate() // cycle through all devices for this system bool missing_mandatory = false; - std::unordered_set<std::string> devtags; std::string tmp_inst, tmp_name; + device_t *prev_parent = nullptr; for (device_t &dev : device_enumerator(machine().root_device())) { - bool tag_appended = false; - if (!devtags.insert(dev.tag()).second) - continue; - // check whether it owns an image interface - image_interface_enumerator subiter(dev); - if (subiter.first() != nullptr) + for (device_image_interface &scan : image_interface_enumerator(dev, 1)) { - // if so, cycle through all its image interfaces - for (device_image_interface &scan : subiter) + if ((&scan.device() == &dev) || (!scan.has_preset_images_selection() && !scan.user_loadable())) + continue; + + // check whether we already had some devices with the same owner: if not, output the owner tag! + if (&dev != prev_parent) { - if (scan.has_preset_images_selection()) - { - if (devtags.insert(scan.device().tag()).second) - { - item_append(string_format(_("[root%1$s]"), scan.device().owner()->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); - int const index = item_append(scan.image_type_name(), scan.preset_images_list()[scan.current_preset_image_id()], 0, (void *)&scan); - m_notifiers.emplace_back(scan.add_media_change_notifier( - [this, index, &scan] (device_image_interface::media_change_event ev) - { - item(index).set_subtext(scan.preset_images_list()[scan.current_preset_image_id()]); - })); - } - } - else if (scan.user_loadable()) - { - // if it is a child device, and not something further down the device tree, we want it in the menu! - if (!strcmp(scan.device().owner()->tag(), dev.tag())) - { - if (devtags.insert(scan.device().tag()).second) + item_append(string_format(_("[root%1$s]"), dev.tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); + prev_parent = &dev; + } + + if (scan.has_preset_images_selection()) + { + int const index = item_append(scan.image_type_name(), scan.preset_images_list()[scan.current_preset_image_id()], 0, (void *)&scan); + m_notifiers.emplace_back(scan.add_media_change_notifier( + [this, index, &scan] (device_image_interface::media_change_event ev) { - if (!scan.basename() && scan.must_be_loaded()) - missing_mandatory = true; - - // check whether we already had some devices with the same owner: if not, output the owner tag! - if (!tag_appended) - { - item_append(string_format(_("[root%1$s]"), dev.tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); - tag_appended = true; - } - - // finally, append the image interface to the menu - fill_image_line(scan, tmp_inst, tmp_name); - int const index = item_append(std::move(tmp_inst), std::move(tmp_name), 0, (void *)&scan); - m_notifiers.emplace_back(scan.add_media_change_notifier( - [this, index, &scan] (device_image_interface::media_change_event ev) - { - std::string text, subtext; - fill_image_line(scan, text, subtext); - item(index).set_subtext(std::move(subtext)); - })); - } - } - } + item(index).set_subtext(scan.preset_images_list()[scan.current_preset_image_id()]); + })); + } + else if (scan.user_loadable()) + { + if (!scan.basename() && scan.must_be_loaded()) + missing_mandatory = true; + + // finally, append the image interface to the menu + fill_image_line(scan, tmp_inst, tmp_name); + int const index = item_append(std::move(tmp_inst), std::move(tmp_name), 0, (void *)&scan); + m_notifiers.emplace_back(scan.add_media_change_notifier( + [this, index, &scan] (device_image_interface::media_change_event ev) + { + std::string text, subtext; + fill_image_line(scan, text, subtext); + item(index).set_subtext(std::move(subtext)); + })); } } } diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp index a70eb4f6094..cb7fc6f3451 100644 --- a/src/frontend/mame/ui/filesel.cpp +++ b/src/frontend/mame/ui/filesel.cpp @@ -56,7 +56,7 @@ namespace ui { menu_file_selector::menu_file_selector( mame_ui_manager &mui, render_target &target, - device_image_interface *image, + device_image_interface &image, std::string_view directory, std::string_view file, bool has_empty, @@ -65,17 +65,14 @@ menu_file_selector::menu_file_selector( handler_function &&handler) : menu(mui, target) , m_handler(std::move(handler)) - , m_image(image) , m_current_directory(directory) , m_current_file(file) - , m_result(result::INVALID) , m_has_empty(has_empty) , m_has_softlist(has_softlist) , m_has_create(has_create) - , m_is_midi(image->device().type() == MIDIIN || image->device().type() == MIDIOUT) + , m_is_midi((image.device().type() == MIDIIN) || (image.device().type() == MIDIOUT)) , m_clicked_directory(std::string::npos, std::string::npos) { - (void)m_image; set_process_flags(PROCESS_IGNOREPAUSE); } @@ -86,8 +83,6 @@ menu_file_selector::menu_file_selector( menu_file_selector::~menu_file_selector() { - if (m_handler) - m_handler(m_result, std::move(m_current_directory), std::move(m_current_file)); } @@ -324,7 +319,7 @@ void menu_file_selector::append_entry_menu_item(const file_selector_entry *entry break; case SELECTOR_ENTRY_TYPE_MIDI: - text = _("[midi port]"); + text = _("[MIDI port]"); break; case SELECTOR_ENTRY_TYPE_CREATE: @@ -363,26 +358,19 @@ void menu_file_selector::select_item(const file_selector_entry &entry) switch (entry.type) { case SELECTOR_ENTRY_TYPE_EMPTY: - // empty slot - unload - m_result = result::EMPTY; - stack_pop(); + m_handler(result::EMPTY, m_current_directory, m_current_file); break; case SELECTOR_ENTRY_TYPE_MIDI: - // create - m_result = result::MIDI; - stack_pop(); + m_handler(result::MIDI, m_current_directory, m_current_file); break; case SELECTOR_ENTRY_TYPE_CREATE: - // create - m_result = result::CREATE; - stack_pop(); + m_handler(result::CREATE, m_current_directory, m_current_file); break; case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST: - m_result = result::SOFTLIST; - stack_pop(); + m_handler(result::SOFTLIST, m_current_directory, m_current_file); break; case SELECTOR_ENTRY_TYPE_DRIVE: @@ -407,8 +395,7 @@ void menu_file_selector::select_item(const file_selector_entry &entry) case SELECTOR_ENTRY_TYPE_FILE: // file m_current_file.assign(entry.fullpath); - m_result = result::FILE; - stack_pop(); + m_handler(result::FILE, m_current_directory, m_current_file); break; } } @@ -570,6 +557,7 @@ void menu_file_selector::populate() // append all of the menu entries for (file_selector_entry const &entry : m_entrylist) append_entry_menu_item(&entry); + item_append(menu_item_type::SEPARATOR); // set the selection (if we have one) if (selected_entry) @@ -627,11 +615,10 @@ bool menu_file_selector::handle(event const *ev) } else if (ev->itemref && (ev->iptkey == IPT_UI_SELECT)) { - // handle selections - select_item(*reinterpret_cast<file_selector_entry const *>(ev->itemref)); - - // reset the char buffer when pressing IPT_UI_SELECT + // reset search when selecting an item m_filename.clear(); + + select_item(*reinterpret_cast<file_selector_entry const *>(ev->itemref)); return true; } @@ -656,7 +643,6 @@ menu_select_rw::menu_select_rw( : menu(mui, target) , m_handler(std::move(handler)) , m_can_in_place(can_in_place) - , m_result(result::INVALID) { } @@ -667,8 +653,6 @@ menu_select_rw::menu_select_rw( menu_select_rw::~menu_select_rw() { - if (m_handler) - m_handler(m_result); } @@ -684,7 +668,8 @@ void menu_select_rw::populate() if (m_can_in_place) item_append(_("Read-write"), 0, itemref_from_result(result::READWRITE)); item_append(_("Read this image, write to another image"), 0, itemref_from_result(result::WRITE_OTHER)); - item_append(_("Read this image, write to diff"), 0, itemref_from_result(result::WRITE_DIFF)); + //item_append(_("Read this image, write to diff"), 0, itemref_from_result(result::WRITE_DIFF)); + item_append(menu_item_type::SEPARATOR); } @@ -695,10 +680,7 @@ void menu_select_rw::populate() bool menu_select_rw::handle(event const *ev) { if (ev && ev->iptkey == IPT_UI_SELECT) - { - m_result = result_from_itemref(ev->itemref); - stack_pop(); - } + m_handler(result_from_itemref(ev->itemref)); return false; } diff --git a/src/frontend/mame/ui/filesel.h b/src/frontend/mame/ui/filesel.h index 37bc69ff4ce..351a8b954bf 100644 --- a/src/frontend/mame/ui/filesel.h +++ b/src/frontend/mame/ui/filesel.h @@ -33,7 +33,6 @@ class menu_file_selector : public menu public: enum class result { - INVALID = -1, EMPTY = 0x1000, SOFTLIST, CREATE, @@ -41,12 +40,12 @@ public: MIDI }; - using handler_function = std::function<void (result result, std::string &&directory, std::string &&file)>; + using handler_function = std::function<void (result result, std::string const &directory, std::string const &file)>; menu_file_selector( mame_ui_manager &mui, render_target &target, - device_image_interface *image, + device_image_interface &image, std::string_view directory, std::string_view file, bool has_empty, @@ -87,12 +86,10 @@ private: // internal state handler_function const m_handler; - device_image_interface *const m_image; std::string m_current_directory; std::string m_current_file; std::optional<text_layout> m_path_layout; std::pair<float, float> m_path_position; - result m_result; bool const m_has_empty; bool const m_has_softlist; bool const m_has_create; @@ -122,7 +119,6 @@ class menu_select_rw : public menu public: enum class result { - INVALID = -1, READONLY = 0x3000, READWRITE, WRITE_OTHER, @@ -148,7 +144,6 @@ private: // internal state handler_function const m_handler; bool const m_can_in_place; - result m_result; }; } // namespace ui diff --git a/src/frontend/mame/ui/floppycntrl.cpp b/src/frontend/mame/ui/floppycntrl.cpp index 72208626cb4..e820d165936 100644 --- a/src/frontend/mame/ui/floppycntrl.cpp +++ b/src/frontend/mame/ui/floppycntrl.cpp @@ -28,12 +28,12 @@ namespace ui { menu_control_floppy_image::menu_control_floppy_image(mame_ui_manager &mui, render_target &target, device_image_interface &image) : menu_control_device_image(mui, target, image), - fd(dynamic_cast<floppy_image_device &>(image)), - input_format(nullptr), - output_format(nullptr), - create_fs(nullptr), - input_filename(), - output_filename() + m_fd(dynamic_cast<floppy_image_device &>(image)), + m_input_format(nullptr), + m_output_format(nullptr), + m_create_fs(nullptr), + m_input_filename(), + m_output_filename() { } @@ -41,183 +41,233 @@ menu_control_floppy_image::~menu_control_floppy_image() { } -void menu_control_floppy_image::do_load_create() +void menu_control_floppy_image::create_format_selected(std::string_view path, floppy_image_format_t const &format) { - if(input_filename.empty()) { - auto [err, message] = fd.create(output_filename, nullptr, nullptr); - if (err) { - machine().popmessage(_("Error creating floppy image: %1$s"), !message.empty() ? message : err.message()); - return; - } - if (create_fs) { - // HACK: ensure the floppy_image structure is created since device_image_interface may not otherwise do so during "init phase" - err = fd.finish_load().first; - if (!err) { - fs::meta_data meta; - fd.init_fs(create_fs, meta); - } - } - } else { - auto [err, message] = fd.load(input_filename); - if (!err && !output_filename.empty()) { - message.clear(); - err = fd.reopen_for_write(output_filename); - } - if (err) { - machine().popmessage(_("Error opening floppy image: %1$s"), !message.empty() ? message : err.message()); - return; - } + // get all formatable file systems + std::vector<std::reference_wrapper<floppy_image_device::fs_info const> > filesystems; + for (auto const &this_fs : m_fd.get_fs()) + { + if (can_format(this_fs)) + filesystems.emplace_back(std::ref(this_fs)); } - if(output_format) - fd.setup_write(output_format); -} - -void menu_control_floppy_image::hook_load(const std::string &filename) -{ - std::error_condition err; - input_filename = filename; - std::tie(err, input_format) = static_cast<floppy_image_device &>(m_image).identify(filename); - if (!input_format) + if (filesystems.size() == 1) { - machine().popmessage("Error: %s", err.message()); - stack_pop(); + stack_pop(); // pop the format selection menu + m_output_format = &format; + m_output_filename = path; + m_create_fs = &filesystems[0].get(); + if (do_load_create()) + { + stack_pop(); // pop the create file menu + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } } else { - bool can_in_place = input_format->supports_save(); - if (can_in_place) - { - std::string tmp_path; - util::core_file::ptr tmp_file; - // attempt to open the file for writing but *without* create - std::error_condition const filerr = util::zippath_fopen(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE, tmp_file, tmp_path); - if(!filerr) - tmp_file.reset(); - else - can_in_place = false; - } - menu::stack_push<menu_select_rw>( + menu::stack_push<menu_select_floppy_init>( ui(), target(), - can_in_place, - [this] (menu_select_rw::result result) + std::move(filesystems), + [this, &format, p = std::string(path)] (floppy_image_device::fs_info const &fs) { - switch (result) + stack_pop(); // pop the file system selection menu + stack_pop(); // pop the format selection menu + m_output_format = &format; + m_output_filename = std::move(p); + m_create_fs = &fs; + if (do_load_create()) { - case menu_select_rw::result::READONLY: - do_load_create(); - fd.setup_write(nullptr); - stack_pop(); - break; - - case menu_select_rw::result::READWRITE: - output_format = input_format; - do_load_create(); - stack_pop(); - break; - - case menu_select_rw::result::WRITE_DIFF: - machine().popmessage("Sorry, diffs are not supported yet\n"); - stack_pop(); - break; - - case menu_select_rw::result::WRITE_OTHER: - menu::stack_push<menu_file_create>(ui(), target(), &m_image, m_current_directory, m_current_file, m_create_ok); - m_state = CHECK_CREATE; - break; - - case menu_select_rw::result::INVALID: - m_state = START_FILE; - break; + stack_pop(); // pop the create file menu + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus } }); } } -bool menu_control_floppy_image::can_format(const floppy_image_device::fs_info &fs) +void menu_control_floppy_image::output_format_selected(std::string_view path, floppy_image_format_t const &format) { - return !fs.m_manager || fs.m_manager->can_format(); + stack_pop(); // pop the format selection menu + stack_pop(); // pop the create file menu + stack_pop(); // pop the access mode menu + m_output_filename = path; + m_output_format = &format; + m_create_fs = nullptr; + if (do_load_create()) + { + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } +} + +void menu_control_floppy_image::create_write_other(std::string const &name) +{ + auto path = util::zippath_combine(m_current_directory, name); + bool can_create, need_confirm; + test_create(path, can_create, need_confirm); + if (!can_create) + return; + + if (need_confirm) + { + menu::stack_push<menu_confirm_save_as>( + ui(), + target(), + [this, path] () + { + stack_pop(); // pop the confirm overwrite menu + menu::stack_push<menu_select_format>( + ui(), + target(), + m_fd, + path, + [this, path] (floppy_image_format_t const &format) { output_format_selected(path, format); }); + }); + } + else + { + menu::stack_push<menu_select_format>( + ui(), + target(), + m_fd, + path, + [this, path] (floppy_image_format_t const &format) { output_format_selected(path, format); }); + } } -void menu_control_floppy_image::menu_activated() +bool menu_control_floppy_image::do_load_create() { - switch (m_state) { - case DO_CREATE: { - std::vector<const floppy_image_format_t *> format_array; - for(const floppy_image_format_t *i : fd.get_formats()) { - if(!i->supports_save()) - continue; - if (i->extension_matches(m_current_file.c_str())) - format_array.push_back(i); + if (m_input_filename.empty()) + { + auto [err, message] = m_fd.create(m_output_filename, nullptr, nullptr); + if (err) + { + machine().popmessage(_("Error creating floppy image: %1$s"), !message.empty() ? message : err.message()); + return false; } - int ext_match = format_array.size(); - for(const floppy_image_format_t *i : fd.get_formats()) { - if(!i->supports_save()) - continue; - if (!i->extension_matches(m_current_file.c_str())) - format_array.push_back(i); + if (m_create_fs) + { + // HACK: ensure the floppy_image structure is created since device_image_interface may not otherwise do so during "init phase" + err = m_fd.finish_load().first; + if (!err) + { + fs::meta_data meta; + m_fd.init_fs(m_create_fs, meta); + } + } + // TODO: what should we do if the image was created but formatting failed? + } + else + { + auto [err, message] = m_fd.load(m_input_filename); + if (!err && !m_output_filename.empty()) + { + message.clear(); + err = m_fd.reopen_for_write(m_output_filename); + // TODO: is any cleanup needed if it failed here? } - output_format = nullptr; - menu::stack_push<menu_select_format>(ui(), target(), format_array, ext_match, &output_format); + if (err) + { + machine().popmessage(_("Error opening floppy image: %1$s"), !message.empty() ? message : err.message()); + return false; + } + } + if (m_output_format) + m_fd.setup_write(m_output_format); + return true; +} - m_state = SELECT_FORMAT; - break; +bool menu_control_floppy_image::hook_load(const std::string &filename) +{ + m_input_filename = filename; + m_output_filename.clear(); + m_output_format = nullptr; + std::error_condition err; + std::tie(err, m_input_format) = static_cast<floppy_image_device &>(m_image).identify(filename); + if (!m_input_format) + { + machine().popmessage(_("Error identifying image format: %1$s"), err.message()); + return false; } - case SELECT_FORMAT: - if(!output_format) { - m_state = START_FILE; - menu_activated(); - } else { - // get all formatable file systems - std::vector<std::reference_wrapper<const floppy_image_device::fs_info>> fs; - for (const auto &this_fs : fd.get_fs()) { - if (can_format(this_fs)) - fs.emplace_back(std::ref(this_fs)); - } + bool can_in_place = m_input_format->supports_save(); + if (can_in_place) + { + std::string tmp_path; + util::core_file::ptr tmp_file; + // attempt to open the file for writing but *without* create + std::error_condition const filerr = util::zippath_fopen(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE, tmp_file, tmp_path); + if (filerr) + can_in_place = false; + } - output_filename = util::zippath_combine(m_current_directory, m_current_file); - if(fs.size() == 1) { - create_fs = &(fs[0].get()); - do_load_create(); - stack_pop(); - } else { - m_submenu_result.i = -1; - menu::stack_push<menu_select_floppy_init>(ui(), target(), std::move(fs), &m_submenu_result.i); - m_state = SELECT_INIT; - } - } - break; - - case SELECT_INIT: - // figure out which (if any) create file system was selected - create_fs = nullptr; - if(m_submenu_result.i >= 0) { - int i = 0; - for (const auto &this_fs : fd.get_fs()) { - if (can_format(this_fs)) { - if (i == m_submenu_result.i) { - create_fs = &this_fs; - break; + menu::stack_push<menu_select_rw>( + ui(), + target(), + can_in_place, + [this] (menu_select_rw::result result) + { + switch (result) + { + case menu_select_rw::result::READONLY: + { + stack_pop(); // pop the access mode menu + bool const result = do_load_create(); + m_fd.setup_write(nullptr); + if (result) + { + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } } - i++; + break; + + case menu_select_rw::result::READWRITE: + stack_pop(); // pop the access mode menu + m_output_format = m_input_format; + if (do_load_create()) + { + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } + break; + + case menu_select_rw::result::WRITE_DIFF: + machine().popmessage(_("Sorry, diffs are not supported yet.")); + break; + + case menu_select_rw::result::WRITE_OTHER: + menu::stack_push<menu_file_create>( + ui(), target(), + m_image, + m_current_directory, + std::string(), + [this] (std::string const &name) { create_write_other(name); }); + break; } - } - } + }); + return false; +} - if(!create_fs) { - m_state = START_FILE; - menu_activated(); - } else { - do_load_create(); - stack_pop(); - } - break; +bool menu_control_floppy_image::hook_create(std::string_view path) +{ + m_input_format = nullptr; + m_input_filename.clear(); + menu::stack_push<menu_select_format>( + ui(), + target(), + m_fd, + path, + [this, p = std::string(path)] (floppy_image_format_t const &format) { create_format_selected(p, format); }); - default: - menu_control_device_image::menu_activated(); - } + return false; +} + +bool menu_control_floppy_image::can_format(floppy_image_device::fs_info const &fs) +{ + return !fs.m_manager || fs.m_manager->can_format(); } } // namespace ui diff --git a/src/frontend/mame/ui/floppycntrl.h b/src/frontend/mame/ui/floppycntrl.h index 8ff0baab814..36811cc1c9a 100644 --- a/src/frontend/mame/ui/floppycntrl.h +++ b/src/frontend/mame/ui/floppycntrl.h @@ -15,6 +15,8 @@ #include "imagedev/floppy.h" #include <memory> +#include <string> +#include <string_view> namespace ui { @@ -25,19 +27,20 @@ public: menu_control_floppy_image(mame_ui_manager &ui, render_target &target, device_image_interface &image); virtual ~menu_control_floppy_image() override; -protected: - virtual void menu_activated() override; - private: - enum { SELECT_FORMAT = LAST_ID, SELECT_MEDIA, SELECT_INIT }; + floppy_image_device &m_fd; + const floppy_image_format_t *m_input_format, *m_output_format; + const floppy_image_device::fs_info *m_create_fs; + std::string m_input_filename, m_output_filename; + + virtual bool hook_load(const std::string &filename) override; + virtual bool hook_create(std::string_view path) override; - floppy_image_device &fd; - const floppy_image_format_t *input_format, *output_format; - const floppy_image_device::fs_info *create_fs; - std::string input_filename, output_filename; + void create_format_selected(std::string_view path, floppy_image_format_t const &format); + void output_format_selected(std::string_view path, floppy_image_format_t const &format); + void create_write_other(std::string const &name); + bool do_load_create(); - void do_load_create(); - virtual void hook_load(const std::string &filename) override; static bool can_format(const floppy_image_device::fs_info &fs); }; diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp index 5aa6ae2579f..b236ff40765 100644 --- a/src/frontend/mame/ui/imgcntrl.cpp +++ b/src/frontend/mame/ui/imgcntrl.cpp @@ -26,6 +26,7 @@ #include "image.h" #include "softlist_dev.h" +#include "util/path.h" #include "util/zippath.h" @@ -42,14 +43,10 @@ namespace ui { menu_control_device_image::menu_control_device_image(mame_ui_manager &mui, render_target &target, device_image_interface &image) : menu(mui, target) , m_image(image) - , m_create_ok(false) - , m_create_confirmed(false) , m_swi(nullptr) , m_swp(nullptr) , m_sld(nullptr) { - m_submenu_result.i = -1; - if (m_image.software_list_name()) m_sld = software_list_device::find_by_name(mui.machine().config(), m_image.software_list_name()); m_swi = m_image.software_entry(); @@ -134,19 +131,16 @@ menu_control_device_image::~menu_control_device_image() //------------------------------------------------- -// test_create - creates a new disk image +// test_create //------------------------------------------------- -void menu_control_device_image::test_create(bool &can_create, bool &need_confirm) +void menu_control_device_image::test_create(std::string const &path, bool &can_create, bool &need_confirm) { - // assemble the full path - auto path = util::zippath_combine(m_current_directory, m_current_file); - // does a file or a directory exist at the path auto entry = osd_stat(path); auto file_type = (entry != nullptr) ? entry->type : osd::directory::entry::entry_type::NONE; - switch(file_type) + switch (file_type) { case osd::directory::entry::entry_type::NONE: // no file/dir here - always create @@ -176,266 +170,352 @@ void menu_control_device_image::test_create(bool &can_create, bool &need_confirm //------------------------------------------------- -// load_software_part +// hook_load //------------------------------------------------- -void menu_control_device_image::load_software_part() +bool menu_control_device_image::hook_load(std::string const &name) { - std::string temp_name = string_format("%s:%s:%s", m_sld->list_name(), m_swi->shortname(), m_swp->name()); - - driver_enumerator drivlist(machine().options(), machine().options().system_name()); - drivlist.next(); - media_auditor auditor(drivlist); - media_auditor::summary summary = auditor.audit_software(*m_sld, *m_swi, AUDIT_VALIDATE_FAST); - // if everything looks good, load software - if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) + auto [err, msg] = m_image.load(name); + if (err) { - auto [err, msg] = m_image.load_software(temp_name); - if (err) - machine().popmessage(_("Error loading software item: %1$s"), !msg.empty() ? msg : err.message()); - stack_pop(); + machine().popmessage(_("Error loading media image: %1$s"), !msg.empty() ? msg : err.message()); + return false; } else { - machine().popmessage(_("Files required for the selected software are missing or incorrect.")); - m_state = SELECT_SOFTLIST; - menu_activated(); + return true; } } //------------------------------------------------- -// hook_load +// hook_create //------------------------------------------------- -void menu_control_device_image::hook_load(const std::string &name) +bool menu_control_device_image::hook_create(std::string_view path) { - auto [err, msg] = m_image.load(name); - if (err) - machine().popmessage(_("Error loading media image: %1$s"), !msg.empty() ? msg : err.message()); - stack_pop(); + auto [err, msg] = m_image.create(path, nullptr, nullptr); + if (!err) + return true; + + machine().popmessage(_("Error creating media image: %1$s"), !msg.empty() ? msg : err.message()); + return false; } //------------------------------------------------- -// populate +// start_file //------------------------------------------------- -void menu_control_device_image::populate() +void menu_control_device_image::start_file() { - throw emu_fatalerror("menu_control_device_image::populate: Shouldn't get here!"); + menu::stack_push<menu_file_selector>( + ui(), target(), + m_image, + m_current_directory, + m_current_file, + true, + m_image.image_interface() != nullptr, + m_image.is_creatable(), + [this] (menu_file_selector::result result, std::string const &directory, std::string const &file) + { + m_current_directory = directory; + m_current_file = file; + switch (result) + { + case menu_file_selector::result::EMPTY: + m_image.unload(); + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + break; + + case menu_file_selector::result::FILE: + if (hook_load(file)) + { + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } + break; + + case menu_file_selector::result::CREATE: + menu::stack_push<menu_file_create>( + ui(), + target(), + m_image, + directory, + std::string(core_filename_extract_base(m_current_file)), + [this] (std::string const &name) { create_file(m_current_directory, name); }); + break; + + case menu_file_selector::result::SOFTLIST: + stack_pop(); // pop the file selection menu + start_softlist(); + break; + + case menu_file_selector::result::MIDI: + stack_pop(); // pop the file selection menu + start_midi(); + break; + } + }); } //------------------------------------------------- -// handle +// start_softlist //------------------------------------------------- -bool menu_control_device_image::handle(event const *ev) +void menu_control_device_image::start_softlist() { - throw emu_fatalerror("menu_control_device_image::handle: Shouldn't get here!"); + menu::stack_push<menu_software>( + ui(), + target(), + m_image.image_interface(), + [this] (software_list_device *sld) + { + if (!sld) + { + stack_pop(); // pop the software lists menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } + else + { + menu::stack_push<menu_software_list>( + ui(), + target(), + *sld, + m_image.image_interface(), + [this, sld] (std::string_view item) { software_item_selected(*sld, item); }); + } + }); } //------------------------------------------------- -// menu_activated +// start_midi //------------------------------------------------- -void menu_control_device_image::menu_activated() +void menu_control_device_image::start_midi() { - switch(m_state) - { - case START_FILE: - menu::stack_push<menu_file_selector>( - ui(), target(), - &m_image, - m_current_directory, - m_current_file, - true, - m_image.image_interface() != nullptr, - m_image.is_creatable(), - [this] (menu_file_selector::result result, std::string &&directory, std::string &&file) + menu::stack_push<menu_midi_inout>( + ui(), + target(), + m_image.device().type() == MIDIIN, + [this] (std::string const &port) + { + auto const [err, msg] = m_image.load(port); + if (err) { - m_current_directory = std::move(directory); - m_current_file = std::move(file); - switch (result) - { - case menu_file_selector::result::EMPTY: - m_image.unload(); - stack_pop(); - break; + machine().popmessage(_("Error opening MIDI port: %1$s"), !msg.empty() ? msg : err.message()); + } + else + { + stack_pop(); // pop the MIDI port selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } + }); +} - case menu_file_selector::result::FILE: - hook_load(m_current_file); - break; - case menu_file_selector::result::CREATE: - menu::stack_push<menu_file_create>(ui(), target(), &m_image, m_current_directory, m_current_file, m_create_ok); - m_state = CHECK_CREATE; - break; +//------------------------------------------------- +// load_software_part +//------------------------------------------------- - case menu_file_selector::result::SOFTLIST: - m_state = START_SOFTLIST; - break; +bool menu_control_device_image::load_software_part(software_list_device &sld, software_info const &swi, software_part const &swp) +{ + std::string temp_name = string_format("%s:%s:%s", sld.list_name(), swi.shortname(), swp.name()); - case menu_file_selector::result::MIDI: - m_state = START_MIDI; - break; + driver_enumerator drivlist(machine().options(), machine().options().system_name()); + drivlist.next(); + media_auditor auditor(drivlist); + media_auditor::summary summary = auditor.audit_software(sld, swi, AUDIT_VALIDATE_FAST); - default: // return to system - stack_pop(); - break; + // if everything looks good, load software + if ((summary == media_auditor::CORRECT) || (summary == media_auditor::BEST_AVAILABLE) || (summary == media_auditor::NONE_NEEDED)) + { + auto [err, msg] = m_image.load_software(temp_name); + if (!err) + return true; + + machine().popmessage(_("Error loading software item: %1$s"), !msg.empty() ? msg : err.message()); + return false; + } + else + { + machine().popmessage(_("Files required for the selected software are missing or incorrect.")); + return false; + } +} + + +//------------------------------------------------- +// software_item_selected +//------------------------------------------------- + +void menu_control_device_image::software_item_selected(software_list_device &sld, std::string_view item) +{ + auto *const swi = sld.find(item); + assert(swi); + + if (swi->has_multiple_parts(m_image.image_interface())) + { + menu::stack_push<menu_software_parts>( + ui(), + target(), + *swi, + m_image.image_interface(), + false, + [this, &sld, swi] (menu_software_parts::result action, software_part const *swp) + { + assert(menu_software_parts::result::ENTRY == action); + assert(swp); + + if (load_software_part(sld, *swi, *swp)) + { + stack_pop(); // pop the software parts menu + stack_pop(); // pop the software items menu + stack_pop(); // pop the software lists menu + stack_pop(); // pop the fake menu that orchestrates the other menus } }); - break; + } + else + { + auto *const swp = swi->find_part("", m_image.image_interface()); + assert(swp); - case START_SOFTLIST: - m_sld = nullptr; - menu::stack_push<menu_software>(ui(), target(), m_image.image_interface(), &m_sld); - m_state = SELECT_SOFTLIST; - break; + if (load_software_part(sld, *swi, *swp)) + { + stack_pop(); // pop the software items menu + stack_pop(); // pop the software lists menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } + } +} - case START_MIDI: - m_midi = ""; - menu::stack_push<menu_midi_inout>(ui(), target(), m_image.device().type() == MIDIIN, &m_midi); - m_state = SELECT_MIDI; - break; - case SELECT_MIDI: - if(!m_midi.empty()) +//------------------------------------------------- +// other_part_selected +//------------------------------------------------- + +void menu_control_device_image::other_part_selected(menu_software_parts::result action, software_part const *swp) +{ + switch (action) + { + case menu_software_parts::result::ENTRY: + assert(swp); + if (load_software_part(*m_sld, *m_swi, *swp)) { - auto [err, msg] = m_image.load(m_midi); - if (err) - machine().popmessage(_("Error connecting to midi port: %1$s"), !msg.empty() ? msg : err.message()); + stack_pop(); // pop the software parts menu + stack_pop(); // pop the fake menu that orchestrates the other menus } - stack_pop(); break; - case START_OTHER_PART: - m_submenu_result.swparts = menu_software_parts::result::INVALID; - menu::stack_push<menu_software_parts>(ui(), target(), m_swi, m_image.image_interface(), &m_swp, true, m_submenu_result.swparts); - m_state = SELECT_OTHER_PART; + case menu_software_parts::result::FMGR: + stack_pop(); // pop the software parts menu + start_file(); break; - case SELECT_SOFTLIST: - if (!m_sld) - { - stack_pop(); - } - else - { - m_software_info_name.clear(); - menu::stack_push<menu_software_list>(ui(), target(), m_sld, m_image.image_interface(), m_software_info_name); - m_state = SELECT_PARTLIST; - } + case menu_software_parts::result::EMPTY: + m_image.unload(); + stack_pop(); // pop the software parts menu + stack_pop(); // pop the fake menu that orchestrates the other menus break; - case SELECT_PARTLIST: - m_swi = m_sld->find(m_software_info_name); - if (!m_swi) - { - m_state = START_SOFTLIST; - menu_activated(); - } - else if (m_swi->has_multiple_parts(m_image.image_interface())) - { - m_submenu_result.swparts = menu_software_parts::result::INVALID; - m_swp = nullptr; - menu::stack_push<menu_software_parts>(ui(), target(), m_swi, m_image.image_interface(), &m_swp, false, m_submenu_result.swparts); - m_state = SELECT_ONE_PART; - } - else - { - m_swp = m_swi->find_part("", m_image.image_interface()); - load_software_part(); - } + case menu_software_parts::result::SWLIST: + stack_pop(); // pop the software parts menu + start_softlist(); break; + } +} - case SELECT_ONE_PART: - switch (m_submenu_result.swparts) - { - case menu_software_parts::result::ENTRY: - load_software_part(); - break; - default: // return to list - m_state = SELECT_SOFTLIST; - menu_activated(); - break; - } - break; +//------------------------------------------------- +// create_file +//------------------------------------------------- + +void menu_control_device_image::create_file(std::string const &directory, std::string const &name) +{ + auto path = util::zippath_combine(directory, name); + bool can_create, need_confirm; + test_create(path, can_create, need_confirm); + if (!can_create) + return; - case SELECT_OTHER_PART: - switch (m_submenu_result.swparts) + if (need_confirm) + { + menu::stack_push<menu_confirm_save_as>( + ui(), + target(), + [this, path] () + { + stack_pop(); // pop the confirm overwrite menu + if (hook_create(path)) + { + stack_pop(); // pop the create file menu + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } + }); + } + else + { + if (hook_create(path)) { - case menu_software_parts::result::ENTRY: - load_software_part(); - break; + stack_pop(); // pop the create file menu + stack_pop(); // pop the file selection menu + stack_pop(); // pop the fake menu that orchestrates the other menus + } + } +} - case menu_software_parts::result::FMGR: - m_state = START_FILE; - menu_activated(); - break; - case menu_software_parts::result::EMPTY: - m_image.unload(); - stack_pop(); - break; +//------------------------------------------------- +// populate +//------------------------------------------------- - case menu_software_parts::result::SWLIST: - m_state = START_SOFTLIST; - menu_activated(); - break; +void menu_control_device_image::populate() +{ + throw emu_fatalerror("menu_control_device_image::populate: Shouldn't get here!"); +} - case menu_software_parts::result::INVALID: // return to system - stack_pop(); - break; - } - break; - case CREATE_FILE: - { - bool can_create, need_confirm; - test_create(can_create, need_confirm); - if (can_create) - { - if (need_confirm) - { - menu::stack_push<menu_confirm_save_as>(ui(), target(), m_create_confirmed); - m_state = CREATE_CONFIRM; - } - else - { - m_state = DO_CREATE; - menu_activated(); - } - } - else - { - m_state = START_FILE; - menu_activated(); - } - } - break; +//------------------------------------------------- +// handle +//------------------------------------------------- + +bool menu_control_device_image::handle(event const *ev) +{ + throw emu_fatalerror("menu_control_device_image::handle: Shouldn't get here!"); +} + + +//------------------------------------------------- +// menu_activated +//------------------------------------------------- - case CREATE_CONFIRM: - m_state = m_create_confirmed ? DO_CREATE : START_FILE; - menu_activated(); +void menu_control_device_image::menu_activated() +{ + switch (m_state) + { + case START_FILE: + start_file(); + m_state = DONE; break; - case CHECK_CREATE: - m_state = m_create_ok ? CREATE_FILE : START_FILE; - menu_activated(); + case START_OTHER_PART: + menu::stack_push<menu_software_parts>( + ui(), + target(), + *m_swi, + m_image.image_interface(), + true, + [this] (menu_software_parts::result action, software_part const *swp) { other_part_selected(action, swp); }); + m_state = DONE; break; - case DO_CREATE: - { - auto path = util::zippath_combine(m_current_directory, m_current_file); - auto [err, msg] = m_image.create(path, nullptr, nullptr); - if (err) - machine().popmessage(_("Error creating media image: %1$s"), !msg.empty() ? msg : err.message()); - stack_pop(); - } + case DONE: + stack_pop(); break; } } diff --git a/src/frontend/mame/ui/imgcntrl.h b/src/frontend/mame/ui/imgcntrl.h index eb24e1856ca..7fadb1907cd 100644 --- a/src/frontend/mame/ui/imgcntrl.h +++ b/src/frontend/mame/ui/imgcntrl.h @@ -26,47 +26,42 @@ public: virtual ~menu_control_device_image() override; protected: - enum - { - START_FILE, START_OTHER_PART, START_SOFTLIST, START_MIDI, - SELECT_PARTLIST, SELECT_ONE_PART, SELECT_OTHER_PART, - CREATE_FILE, CREATE_CONFIRM, CHECK_CREATE, DO_CREATE, SELECT_SOFTLIST, SELECT_MIDI, - LAST_ID - }; - - // this is a single union that contains all of the different types of - // results we could get from child menus - union - { - menu_software_parts::result swparts; - int i; - } m_submenu_result; - // instance variables - made protected so they can be shared with floppycntrl.cpp - int m_state; device_image_interface & m_image; std::string m_current_directory; std::string m_current_file; - bool m_create_ok; // methods virtual void menu_activated() override; virtual bool handle(event const *ev) override; - virtual void hook_load(const std::string &filename); + + virtual void create_file(std::string const &directory, std::string const &name); + void test_create(std::string const &path, bool &can_create, bool &need_confirm); private: + enum + { + START_FILE, START_OTHER_PART, DONE + }; + // instance variables - bool m_create_confirmed; + int m_state; const software_info * m_swi; const software_part * m_swp; class software_list_device * m_sld; - std::string m_software_info_name; - std::string m_midi; // methods virtual void populate() override; - void test_create(bool &can_create, bool &need_confirm); - void load_software_part(); + + virtual bool hook_load(std::string const &filename); + virtual bool hook_create(std::string_view path); + + void start_file(); + void start_softlist(); + void start_midi(); + bool load_software_part(software_list_device &sld, software_info const &swi, software_part const &swp); + void software_item_selected(software_list_device &sld, std::string_view item); + void other_part_selected(menu_software_parts::result action, software_part const *swp); }; } // namespace ui diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index 734187327fb..52a538d20d6 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -652,6 +652,12 @@ std::string machine_info::get_screen_desc(screen_device &screen) const menu_game_info::menu_game_info(mame_ui_manager &mui, render_target &target) : menu_textbox(mui, target) { set_process_flags(PROCESS_CUSTOM_NAV); + + for (device_image_interface &image : image_interface_enumerator(machine().root_device())) + { + if (image.user_loadable() || image.has_preset_images_selection()) + m_notifiers.emplace_back(image.add_media_change_notifier(delegate(&menu_game_info::reload, this))); + } } menu_game_info::~menu_game_info() @@ -670,7 +676,85 @@ void menu_game_info::populate_text(std::optional<text_layout> &layout, float &wi { rgb_t const color = ui().colors().text_color(); layout.emplace(create_layout(width)); + + // add the system info text layout->add_text(ui().machine_info().game_info_string(), color); + + // add media information + std::ostringstream mediainfo; + device_t *prev_parent = nullptr; + for (device_t &parent : device_enumerator(machine().root_device())) + { + for (device_image_interface &image : image_interface_enumerator(parent, 1)) + { + if ((&image.device() != &parent) && (image.user_loadable() || image.has_preset_images_selection())) + { + if (&parent != prev_parent) + { + prev_parent = &parent; + util::stream_format(mediainfo, _("\nMedia: [root%1$s]\n"), parent.tag()); + } + if (image.user_loadable()) + { + if (!image.exists()) + { + util::stream_format( mediainfo, _("%1$s (%2$s): [no media]\n"), + image.instance_name(), + image.brief_instance_name()); + } + else if (!image.loaded_through_softlist()) + { + util::stream_format(mediainfo, _("%1$s (%2$s): %3$s\n"), + image.instance_name(), + image.brief_instance_name(), + image.filename()); + } + else + { + software_info const &swinfo(*image.software_entry()); + auto const partid = image.get_feature("part_id"); + char const *fmt; + if (partid) + { + if (swinfo.supported() == software_support::UNSUPPORTED) + fmt = _("%1$s (%2$s): %3$s:%4$s %5$s (not supported)\n%6$s\n%7$s, %8$s\n"); + else if (swinfo.supported() == software_support::UNSUPPORTED) + fmt = _("%1$s (%2$s): %3$s:%4$s %5$s (partially supported)\n%6$s\n%7$s, %8$s\n"); + else + fmt = _("%1$s (%2$s): %3$s:%4$s %5$s\n%6$s\n%7$s, %8$s\n"); + } + else + { + if (swinfo.supported() == software_support::UNSUPPORTED) + fmt = _("%1$s (%2$s): %3$s:%4$s (not supported)\n%6$s\n%7$s, %8$s\n"); + else if (swinfo.supported() == software_support::UNSUPPORTED) + fmt = _("%1$s (%2$s): %3$s:%4$s (partially supported)\n%6$s\n%7$s, %8$s\n"); + else + fmt = _("%1$s (%2$s): %3$s:%4$s\n%6$s\n%7$s, %8$s\n"); + } + util::stream_format(mediainfo, fmt, + image.instance_name(), + image.brief_instance_name(), + image.basename(), + image.part_entry()->name(), + partid, + swinfo.longname(), + swinfo.publisher(), + swinfo.year()); + } + } + else if (image.has_preset_images_selection()) + { + util::stream_format(mediainfo, _("%1$s (%2$s preset %u)\n"), + image.preset_images_list()[image.current_preset_image_id()], + image.filename(), + image.current_preset_image_id() + 1); + } + } + } + } + layout->add_text(std::move(mediainfo).str(), color); + lines = layout->lines(); } width = layout->actual_width(); @@ -680,6 +764,11 @@ void menu_game_info::populate() { } +void menu_game_info::reload(device_image_interface::media_change_event ev) +{ + reset_layout(); +} + /*------------------------------------------------- menu_warn_info - handle the emulation warnings menu @@ -739,93 +828,4 @@ void menu_warn_info::populate() { } - -/*------------------------------------------------- - menu_image_info - handle the image information menu --------------------------------------------------*/ - -menu_image_info::menu_image_info(mame_ui_manager &mui, render_target &target) : menu(mui, target) -{ - set_heading(_("Media Image Information")); -} - -menu_image_info::~menu_image_info() -{ -} - -void menu_image_info::menu_activated() -{ - reset(reset_options::REMEMBER_POSITION); -} - -void menu_image_info::populate() -{ - for (device_image_interface &image : image_interface_enumerator(machine().root_device())) - image_info(image); -} - -bool menu_image_info::handle(event const *ev) -{ - return false; -} - - -/*------------------------------------------------- - image_info - display image info for a specific - image interface device --------------------------------------------------*/ - -void menu_image_info::image_info(device_image_interface &image) -{ - if (!image.user_loadable()) - return; - - m_notifiers.emplace_back(image.add_media_change_notifier(delegate(&menu_image_info::reload, this))); - - if (image.exists()) - { - // display device type and filename - item_append(image.brief_instance_name(), image.basename(), 0, &image); - - // if image has been loaded through softlist, let's add some more info - if (image.loaded_through_softlist()) - { - software_info const &swinfo(*image.software_entry()); - - // display full name, publisher and year - item_append(swinfo.longname(), FLAG_DISABLE, nullptr); - item_append(string_format("%1$s, %2$s", swinfo.publisher(), swinfo.year()), FLAG_DISABLE, nullptr); - - // display supported information, if available - switch (swinfo.supported()) - { - case software_support::UNSUPPORTED: - item_append(_("Not supported"), FLAG_DISABLE, nullptr); - break; - case software_support::PARTIALLY_SUPPORTED: - item_append(_("Partially supported"), FLAG_DISABLE, nullptr); - break; - case software_support::SUPPORTED: - break; - } - } - } - else - { - item_append(image.brief_instance_name(), _("[empty]"), 0, &image); - } - item_append(menu_item_type::SEPARATOR); -} - - -/*------------------------------------------------- - reload - refresh the menu after a media change --------------------------------------------------*/ - -void menu_image_info::reload(device_image_interface::media_change_event ev) -{ - m_notifiers.clear(); - reset(reset_options::REMEMBER_REF); -} - } // namespace ui diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h index a289fc9f9dd..2d20dd26fc8 100644 --- a/src/frontend/mame/ui/info.h +++ b/src/frontend/mame/ui/info.h @@ -112,6 +112,10 @@ protected: private: virtual void populate() override; + + void reload(device_image_interface::media_change_event ev); + + std::vector<util::notifier_subscription> m_notifiers; }; @@ -128,25 +132,6 @@ private: virtual void populate() override; }; - -class menu_image_info : public menu -{ -public: - menu_image_info(mame_ui_manager &mui, render_target &target); - virtual ~menu_image_info() override; - -protected: - virtual void menu_activated() override; - -private: - virtual void populate() override; - virtual bool handle(event const *ev) override; - void image_info(device_image_interface &image); - void reload(device_image_interface::media_change_event ev); - - std::vector<util::notifier_subscription> m_notifiers; -}; - } // namespace ui #endif // MAME_FRONTEND_UI_INFO_H diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index 9a7ad400995..391a91d34eb 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -53,7 +53,6 @@ enum : unsigned { BOOKKEEPING, GAME_INFO, WARN_INFO, - IMAGE_MENU_IMAGE_INFO, IMAGE_MENU_FILE_MANAGER, TAPE_CONTROL, SLOT_DEVICES, @@ -130,18 +129,13 @@ void menu_main::populate() item_append(_("menu-main", "Warning Information"), 0, (void *)WARN_INFO); for (device_image_interface &image : image_interface_enumerator(machine().root_device())) - if (image.user_loadable()) - { - item_append(_("menu-main", "Media Image Information"), 0, (void *)IMAGE_MENU_IMAGE_INFO); - break; - } - - for (device_image_interface &image : image_interface_enumerator(machine().root_device())) + { if (image.user_loadable() || image.has_preset_images_selection()) { - item_append(_("menu-main", "File Manager"), 0, (void *)IMAGE_MENU_FILE_MANAGER); + item_append(_("menu-main", "Media Control"), 0, (void *)IMAGE_MENU_FILE_MANAGER); break; } + } if (cassette_device_enumerator(machine().root_device()).first() != nullptr) item_append(_("menu-main", "Tape Control"), 0, (void *)TAPE_CONTROL); @@ -251,10 +245,6 @@ bool menu_main::handle(event const *ev) menu::stack_push<menu_warn_info>(ui(), target()); break; - case IMAGE_MENU_IMAGE_INFO: - menu::stack_push<menu_image_info>(ui(), target()); - break; - case IMAGE_MENU_FILE_MANAGER: menu::stack_push<menu_file_manager>(ui(), target(), std::string()); break; diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp index da42c25a531..80776617104 100644 --- a/src/frontend/mame/ui/menu.cpp +++ b/src/frontend/mame/ui/menu.cpp @@ -615,7 +615,7 @@ void menu::draw(uint32_t flags) // compute the width and height of the full menu float visible_width = 0; - float visible_main_menu_height = 0; + float visible_main_menu_height = line_height() * m_items.size(); for (auto const &pitem : m_items) { // compute width of left hand side @@ -629,9 +629,6 @@ void menu::draw(uint32_t flags) // track the maximum visible_width = std::max(total_width, visible_width); - - // track the height as well - visible_main_menu_height += line_height(); } // lay out the heading if present @@ -755,6 +752,7 @@ void menu::draw(uint32_t flags) // work out what we're dealing with bool const uparrow = !linenum && m_show_up_arrow; bool const downarrow = (linenum == (m_visible_lines - 1)) && m_show_down_arrow; + bool const hovered = have_pointer() && pointer_in_rect(m_items_left, line_y0, m_items_right, line_y1); // highlight if necessary if (is_selected(itemnum)) @@ -772,7 +770,7 @@ void menu::draw(uint32_t flags) fgcolor = fgcolor2 = fgcolor3 = ui().colors().mouseover_color(); bgcolor = ui().colors().mouseover_bg_color(); } - else if (have_pointer() && pointer_in_rect(m_items_left, line_y0, m_items_right, line_y1)) + else if (hovered) { if ((track_pointer::TRACK_LINE == m_pointer_state) && pointerline) { @@ -899,21 +897,31 @@ void menu::draw(uint32_t flags) } // apply arrows - if (is_selected(itemnum) && (pitem.flags() & (FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW))) + bool const adjustarrows = is_selectable(pitem) && (pitem.flags() & (FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW)); + if (adjustarrows && (is_selected(itemnum) || (hovered && (track_pointer::IDLE == m_pointer_state)))) { - m_adjust_top = line_y0 + (0.1F * line_height()); - m_adjust_bottom = line_y0 + (0.9F * line_height()); + float const t = line_y0 + (0.1F * line_height()); + float const b = line_y0 + (0.9F * line_height()); + if (hovered) + { + m_adjust_top = t; + m_adjust_bottom = b; + } if (pitem.flags() & FLAG_LEFT_ARROW) { - m_decrease_left = effective_left + effective_width - subitem_width - gutter_width(); - float const r = m_decrease_left + lr_arrow_width(); - draw_arrow(m_decrease_left, m_adjust_top, r, m_adjust_bottom, fgcolor, ROT90 ^ ORIENTATION_FLIP_X); + float const l = effective_left + effective_width - subitem_width - gutter_width(); + float const r = l + lr_arrow_width(); + draw_arrow(l, t, r, b, fgcolor, ROT90 ^ ORIENTATION_FLIP_X); + if (hovered) + m_decrease_left = l; } if (pitem.flags() & FLAG_RIGHT_ARROW) { float const r = effective_left + effective_width + gutter_width(); - m_increase_left = r - lr_arrow_width(); - draw_arrow(m_increase_left, m_adjust_top, r, m_adjust_bottom, fgcolor, ROT90); + float const l = r - lr_arrow_width(); + draw_arrow(l, t, r, b, fgcolor, ROT90); + if (hovered) + m_increase_left = l; } } } @@ -1357,13 +1365,23 @@ std::pair<int, bool> menu::handle_primary_down(uint32_t flags, ui_event const &u // FIXME: should repeat if appropriate if (!is_touch && (y >= m_adjust_top) && (y < m_adjust_bottom)) { + // work out which line/item it is + auto const lineno(int((y - m_items_top) / line_height())); + int const itemno(lineno + top_line); + assert(lineno >= 0); + assert(lineno < m_visible_lines); + assert(itemno < m_items.size()); + assert(is_selectable(m_items[itemno])); + if ((x >= m_decrease_left) && (x < (m_decrease_left + lr_arrow_width()))) { + m_selected = itemno; m_pointer_state = track_pointer::COMPLETED; return std::make_pair(IPT_UI_LEFT, false); } else if ((x >= m_increase_left) && (x < (m_increase_left + lr_arrow_width()))) { + m_selected = itemno; m_pointer_state = track_pointer::COMPLETED; return std::make_pair(IPT_UI_RIGHT, false); } diff --git a/src/frontend/mame/ui/midiinout.cpp b/src/frontend/mame/ui/midiinout.cpp index 387f66b3e57..a5edd55f5a8 100644 --- a/src/frontend/mame/ui/midiinout.cpp +++ b/src/frontend/mame/ui/midiinout.cpp @@ -17,12 +17,16 @@ namespace ui { -menu_midi_inout::menu_midi_inout(mame_ui_manager &mui, render_target &target, bool is_input, std::string *channel) +menu_midi_inout::menu_midi_inout( + mame_ui_manager &mui, + render_target &target, + bool is_input, + handler_function &&handler) : menu(mui, target) - , m_channel(channel) + , m_handler(std::move(handler)) , m_is_input(is_input) { - set_heading(m_is_input ? _("MIDI input channel") : _("MIDI output channel")); + set_heading(m_is_input ? _("menu-midiport", "MIDI input port") : _("menu-midiport", "MIDI output port")); } menu_midi_inout::~menu_midi_inout() @@ -31,14 +35,11 @@ menu_midi_inout::~menu_midi_inout() bool menu_midi_inout::handle(event const *ev) { - if(!ev) + if (!ev) return false; - if(ev->iptkey == IPT_UI_SELECT) { - *m_channel = m_port_names[uintptr_t(ev->itemref)]; - stack_pop(); - return true; - } + if (ev->iptkey == IPT_UI_SELECT) + m_handler(m_port_names[uintptr_t(ev->itemref)]); return false; } @@ -51,53 +52,27 @@ bool menu_midi_inout::handle(event const *ev) void menu_midi_inout::populate() { - auto ports = machine().osd().list_midi_ports(); - for(auto &p : ports) - if((m_is_input && p.input) || (!m_is_input && p.output)) { - item_append(p.name, "", 0, (void *)(m_port_names.size())); - m_port_names.push_back(p.name); + m_port_names.clear(); + auto const ports = machine().osd().list_midi_ports(); + m_port_names.reserve(ports.size()); + for (auto &p : ports) + { + if ((m_is_input && p.input) || (!m_is_input && p.output)) + { + item_append(p.name, 0, (void *)(m_port_names.size())); + m_port_names.emplace_back(p.name); } -} - - -//------------------------------------------------- -// recompute_metrics - recompute metrics -//------------------------------------------------- - -void menu_midi_inout::recompute_metrics(uint32_t width, uint32_t height, float aspect) -{ - menu::recompute_metrics(width, height, aspect); -} - - -//------------------------------------------------- -// menu_midi_inout_custom_render - perform our special -// rendering -//------------------------------------------------- - -void menu_midi_inout::custom_render(uint32_t flags, void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) -{ -} - - -//------------------------------------------------- -// menu_activated - handle menu gaining focus -//------------------------------------------------- - -void menu_midi_inout::menu_activated() -{ - // scripts or the other form of the menu could have changed something in the mean time - reset(reset_options::REMEMBER_POSITION); -} - + } -//------------------------------------------------- -// menu_deactivated - handle menu losing focus -//------------------------------------------------- + if (m_port_names.empty()) + { + item_append( + m_is_input ? _("menu-midiport", "[no MIDI input ports available]") : _("menu-midiport", "[no MIDI output ports available]"), + FLAG_DISABLE, + nullptr); + } -void menu_midi_inout::menu_deactivated() -{ + item_append(menu_item_type::SEPARATOR); } } // namespace ui - diff --git a/src/frontend/mame/ui/midiinout.h b/src/frontend/mame/ui/midiinout.h index 60f21d15929..522a1cf652c 100644 --- a/src/frontend/mame/ui/midiinout.h +++ b/src/frontend/mame/ui/midiinout.h @@ -15,25 +15,29 @@ #include "ui/menu.h" +#include <functional> +#include <string> +#include <vector> + namespace ui { class menu_midi_inout : public menu { public: - menu_midi_inout(mame_ui_manager &mui, render_target &target, bool is_input, std::string *channel); - virtual ~menu_midi_inout() override; + using handler_function = std::function<void (std::string const &)>; -protected: - virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; - virtual void custom_render(uint32_t flags, 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; + menu_midi_inout( + mame_ui_manager &mui, + render_target &target, + bool is_input, + handler_function &&handler); + virtual ~menu_midi_inout() override; private: - std::vector<std::string> m_port_names; - std::string *m_channel; - bool m_is_input; + handler_function const m_handler; + std::vector<std::string> m_port_names; + bool const m_is_input; virtual void populate() override; virtual bool handle(event const *ev) override; diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp index 44232cf2879..ecc39fe79e0 100644 --- a/src/frontend/mame/ui/swlist.cpp +++ b/src/frontend/mame/ui/swlist.cpp @@ -56,18 +56,17 @@ static bool is_valid_softlist_part_char(char32_t ch) menu_software_parts::menu_software_parts( mame_ui_manager &mui, render_target &target, - const software_info *info, + const software_info &info, const char *interface, - const software_part **part, bool other_opt, - result &result) + handler_function &&handler) : menu(mui, target) - , m_result(result) + , m_handler(std::move(handler)) + , m_info(info) + , m_interface(interface) + , m_other_opt(other_opt) { - m_info = info; - m_interface = interface; - m_selected_part = part; - m_other_opt = other_opt; + set_heading(util::string_format(_("%1$s (%2$s)"), info.longname(), info.shortname())); } @@ -107,19 +106,22 @@ void menu_software_parts::populate() item_append(_("[software list]"), 0, &entry3); } - for (const software_part &swpart : m_info->parts()) + for (const software_part &swpart : m_info.parts()) { if (swpart.matches_interface(m_interface)) { software_part_menu_entry &entry(*m_entries.emplace(m_entries.end())); // check if the available parts have specific part_id to be displayed (e.g. "Map Disc", "Bonus Disc", etc.) - // if not, we simply display "part_name"; if yes we display "part_name (part_id)" - std::string menu_part_name(swpart.name()); - if (swpart.feature("part_id") != nullptr) - menu_part_name.append(" (").append(swpart.feature("part_id")).append(")"); + // if not, we simply display "part_name"; if yes we display "part_id (part_name)" + std::string menu_part_name; + auto const partid = swpart.feature("part_id"); + if (partid) + menu_part_name = string_format(_("%1$s (%2$s)"), partid, swpart.name()); + else + menu_part_name = swpart.name(); entry.type = result::ENTRY; entry.part = &swpart; - item_append(m_info->shortname(), menu_part_name, 0, &entry); + item_append(std::move(menu_part_name), m_info.shortname(), 0, &entry); } } @@ -136,9 +138,7 @@ bool menu_software_parts::handle(event const *ev) if (ev && (ev->iptkey == IPT_UI_SELECT) && ev->itemref) { software_part_menu_entry *entry = (software_part_menu_entry *)ev->itemref; - m_result = entry->type; - *m_selected_part = entry->part; - stack_pop(); + m_handler(entry->type, entry->part); } return false; @@ -153,15 +153,20 @@ bool menu_software_parts::handle(event const *ev) // ctor //------------------------------------------------- -menu_software_list::menu_software_list(mame_ui_manager &mui, render_target &target, software_list_device *swlist, const char *interface, std::string &result) - : menu(mui, target), m_result(result) +menu_software_list::menu_software_list( + mame_ui_manager &mui, + render_target &target, + software_list_device &swlist, + const char *interface, + handler_function &&handler) + : menu(mui, target) + , m_handler(std::move(handler)) + , m_swlist(swlist) + , m_interface(interface) + , m_ordered_by_shortname(false) { - set_heading(swlist->description()); - + set_heading(swlist.description()); set_process_flags(PROCESS_IGNOREPAUSE); - m_swlist = swlist; - m_interface = interface; - m_ordered_by_shortname = false; } @@ -186,7 +191,7 @@ void menu_software_list::append_software_entry(const software_info &swinfo) // check if at least one of the parts has the correct interface and add a menu entry only in this case for (const software_part &swpart : swinfo.parts()) { - if (swpart.matches_interface(m_interface) && m_swlist->is_compatible(swpart) == SOFTWARE_IS_COMPATIBLE) + if (swpart.matches_interface(m_interface) && m_swlist.is_compatible(swpart) == SOFTWARE_IS_COMPATIBLE) { entry_updated = true; entry.short_name.assign(swinfo.shortname()); @@ -257,7 +262,7 @@ void menu_software_list::populate() { // build up the list of entries for the menu if (m_entrylist.empty()) - for (const software_info &swinfo : m_swlist->get_info()) + for (const software_info &swinfo : m_swlist.get_info()) append_software_entry(swinfo); if (m_entrylist.size() > 1) @@ -332,9 +337,9 @@ bool menu_software_list::handle(event const *ev) else if (ev->itemref) { // handle selections + m_search.clear(); entry_info *info = (entry_info *)ev->itemref; - m_result = info->short_name; - stack_pop(); + m_handler(info->short_name); } return false; } @@ -392,13 +397,16 @@ bool menu_software_list::handle(event const *ev) // ctor //------------------------------------------------- -menu_software::menu_software(mame_ui_manager &mui, render_target &target, const char *interface, software_list_device **result) +menu_software::menu_software( + mame_ui_manager &mui, + render_target &target, + const char *interface, + handler_function &&handler) : menu(mui, target) + , m_interface(interface) + , m_handler(std::move(handler)) { - set_heading(_("Software List")); - - m_interface = interface; - m_result = result; + set_heading(_("Software Lists")); } @@ -422,24 +430,34 @@ void menu_software::populate() // Add original software lists for this system software_list_device_enumerator iter(machine().config().root_device()); for (software_list_device &swlistdev : iter) + { if (swlistdev.is_original()) + { if (!swlistdev.get_info().empty() && m_interface != nullptr) { bool found = false; for (const software_info &swinfo : swlistdev.get_info()) + { for (const software_part &swpart : swinfo.parts()) + { if (swpart.matches_interface(m_interface)) { found = true; break; } + } + } if (found) item_append(swlistdev.description(), 0, (void *)&swlistdev); } + } + } // add compatible software lists for this system for (software_list_device &swlistdev : iter) + { if (swlistdev.is_compatible()) + { if (!swlistdev.get_info().empty() && m_interface != nullptr) { bool found = false; @@ -458,6 +476,8 @@ void menu_software::populate() } have_compatible = true; } + } + } item_append(menu_item_type::SEPARATOR); } @@ -472,8 +492,8 @@ bool menu_software::handle(event const *ev) if (ev && (ev->iptkey == IPT_UI_SELECT)) { //menu::stack_push<menu_software_list>(ui(), target(), (software_list_config *)ev->itemref, image); - *m_result = reinterpret_cast<software_list_device *>(ev->itemref); - stack_pop(); + auto *const result = reinterpret_cast<software_list_device *>(ev->itemref); + m_handler(result); } return false; diff --git a/src/frontend/mame/ui/swlist.h b/src/frontend/mame/ui/swlist.h index b7616dc5e56..011f7674a51 100644 --- a/src/frontend/mame/ui/swlist.h +++ b/src/frontend/mame/ui/swlist.h @@ -13,7 +13,10 @@ #include "ui/menu.h" +#include <functional> #include <list> +#include <string> +#include <string_view> namespace ui { @@ -25,14 +28,21 @@ class menu_software_parts : public menu public: enum class result { - INVALID = -1, - EMPTY = 0x2000, + EMPTY, FMGR, SWLIST, ENTRY }; - menu_software_parts(mame_ui_manager &mui, render_target &target, const software_info *info, const char *interface, const software_part **part, bool other_opt, result &result); + using handler_function = std::function<void (result, software_part const *)>; + + menu_software_parts( + mame_ui_manager &mui, + render_target &target, + software_info const &info, + char const *interface, + bool other_opt, + handler_function &&handler); virtual ~menu_software_parts() override; private: @@ -47,12 +57,11 @@ private: virtual bool handle(event const *ev) override; // variables + handler_function const m_handler; entry_list m_entries; - const software_info * m_info; - const char * m_interface; - const software_part ** m_selected_part; + software_info const & m_info; + char const *const m_interface; bool m_other_opt; - result & m_result; }; @@ -61,7 +70,14 @@ private: class menu_software_list : public menu { public: - menu_software_list(mame_ui_manager &mui, render_target &target, software_list_device *swlist, const char *interface, std::string &result); + using handler_function = std::function<void (std::string_view)>; + + menu_software_list( + mame_ui_manager &mui, + render_target &target, + software_list_device &swlist, + char const *interface, + handler_function &&handler); virtual ~menu_software_list() override; protected: @@ -81,18 +97,18 @@ private: }; // variables - software_list_device * m_swlist; // currently selected list - const char * m_interface; - std::string & m_result; - std::list<entry_info> m_entrylist; - std::string m_search; - bool m_ordered_by_shortname; + handler_function const m_handler; + software_list_device & m_swlist; // currently selected list + char const *const m_interface; + std::list<entry_info> m_entrylist; + std::string m_search; + bool m_ordered_by_shortname; virtual void populate() override; virtual bool handle(event const *ev) override; // functions - void append_software_entry(const software_info &swinfo); + void append_software_entry(software_info const &swinfo); void update_search(void *selectedref); }; @@ -102,14 +118,20 @@ private: class menu_software : public menu { public: - menu_software(mame_ui_manager &mui, render_target &target, const char *interface, software_list_device **result); + using handler_function = std::function<void (software_list_device *)>; + + menu_software( + mame_ui_manager &mui, + render_target &target, + char const *interface, + handler_function &&handler); virtual ~menu_software() override; virtual void populate() override; virtual bool handle(event const *ev) override; private: - const char * m_interface; - software_list_device ** m_result; + char const *const m_interface; + handler_function const m_handler; }; } // namespace ui diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp index e0696986d13..f29f02876ad 100644 --- a/src/lib/formats/flopimg.cpp +++ b/src/lib/formats/flopimg.cpp @@ -183,21 +183,20 @@ bool floppy_image_format_t::supports_save() const noexcept return false; } -bool floppy_image_format_t::extension_matches(const char *file_name) const +bool floppy_image_format_t::extension_matches(std::string_view file_name) const noexcept { - const char *ext = strrchr(file_name, '.'); - if(!ext) + auto const sep = file_name.rfind('.'); + if(std::string_view::npos == sep) return false; - ext++; - int elen = strlen(ext); - const char *rext = extensions(); + auto const ext = file_name.substr(sep + 1); + char const *rext = extensions(); for(;;) { - const char *next_ext = strchr(rext, ','); - int rlen = next_ext ? next_ext - rext : strlen(rext); - if(rlen == elen && !memcmp(ext, rext, rlen)) + char const *next_ext = strchr(rext, ','); + int const rlen = next_ext ? (next_ext - rext) : strlen(rext); + if(std::string_view(rext, rlen) == ext) return true; if(next_ext) - rext = next_ext +1; + rext = next_ext + 1; else break; } diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h index 3c0acd4fedb..af90d8528b2 100644 --- a/src/lib/formats/flopimg.h +++ b/src/lib/formats/flopimg.h @@ -93,7 +93,7 @@ public: //! This checks if the file has the proper extension for this format. //! @param file_name //! @returns true if file matches the extension. - bool extension_matches(const char *file_name) const; + bool extension_matches(std::string_view file_name) const noexcept; protected: //! Input for convert_to_edge diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp index ef4e4334db5..c498dcbbf52 100644 --- a/src/lib/util/zippath.cpp +++ b/src/lib/util/zippath.cpp @@ -713,30 +713,29 @@ std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags filerr = std::errc::permission_denied; else filerr = std::errc::no_such_file_or_directory; - goto done; } else if (osd::directory::entry::entry_type::DIR == entry_type) { filerr = std::errc::is_a_directory; - goto done; } else if (openflags & OPEN_FLAG_WRITE) { filerr = std::errc::permission_denied; - goto done; } - - // attempt to read the file - filerr = create_core_file_from_zip(*zip, file); - if (filerr) - goto done; - - // update subpath, if appropriate - if (subpath.empty()) - subpath.assign(zip->current_name()); + else + { + // attempt to read the file + filerr = create_core_file_from_zip(*zip, file); + if (!filerr) + { + // update subpath, if appropriate + if (subpath.empty()) + subpath.assign(zip->current_name()); + } + } // we're done - goto done; + break; } } @@ -748,6 +747,9 @@ std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags // if we errored, then go up a directory if (filerr) { + if (std::errc::no_such_file_or_directory != filerr) + break; + // go up a directory auto temp = zippath_parent(mainpath); @@ -773,7 +775,6 @@ std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags } } -done: // store the revised path revised_path.clear(); if (!filerr) diff --git a/src/mame/casio/pickytlk.cpp b/src/mame/casio/pickytlk.cpp index e3ba1612eca..8bf0c078195 100644 --- a/src/mame/casio/pickytlk.cpp +++ b/src/mame/casio/pickytlk.cpp @@ -69,7 +69,7 @@ namespace { class pickytlk_base_state : public driver_device { public: - DECLARE_CROSSHAIR_MAPPER_MEMBER(pen_y_mapper); + float pen_y_mapper(float linear_value); ioport_value pen_y_rescale_r(); ioport_value pen_target_r(); @@ -171,11 +171,11 @@ void pickytlk_base_state::machine_reset() m_pen_target = PEN_TARGET_LCD; } -CROSSHAIR_MAPPER_MEMBER(pickytlk_base_state::pen_y_mapper) +float pickytlk_base_state::pen_y_mapper(float linear_value) { // Parameter `linear_value` is ignored, since we will read the input port directly // for adjustments, just need to return that value in the expected range [0.0f..1.0f]. - return (float) pen_y_rescale_r() / 0xff; + return float(pen_y_rescale_r()) / 0xff; } ioport_value pickytlk_base_state::pen_y_rescale_r() diff --git a/src/mame/sega/sega_beena.cpp b/src/mame/sega/sega_beena.cpp index f434f4f53c1..2446fb1519a 100644 --- a/src/mame/sega/sega_beena.cpp +++ b/src/mame/sega/sega_beena.cpp @@ -1789,7 +1789,7 @@ public: void sega_beena(machine_config &config); - virtual DECLARE_CROSSHAIR_MAPPER_MEMBER(pen_y_mapper); + virtual float pen_y_mapper(float linear_value); protected: virtual void video_start() override ATTR_COLD; @@ -2019,7 +2019,7 @@ void sega_beena_state::update_sensors(offs_t offset) } } -CROSSHAIR_MAPPER_MEMBER(sega_beena_state::pen_y_mapper) +float sega_beena_state::pen_y_mapper(float linear_value) { // TODO: Either remove or adapt for Storyware layout return linear_value; diff --git a/src/mame/sega/sega_ferie.cpp b/src/mame/sega/sega_ferie.cpp index 097168c1f55..b7a988e98b4 100644 --- a/src/mame/sega/sega_ferie.cpp +++ b/src/mame/sega/sega_ferie.cpp @@ -88,7 +88,7 @@ public: void sega_ferie(machine_config &config); - DECLARE_CROSSHAIR_MAPPER_MEMBER(pen_y_mapper); + float pen_y_mapper(float linear_value); ioport_value pen_y_rescale_r(); ioport_value pen_target_r(); @@ -321,11 +321,11 @@ void sega_ferie_state::machine_reset() m_pen_target = PEN_TARGET_LCD; } -CROSSHAIR_MAPPER_MEMBER(sega_ferie_state::pen_y_mapper) +float sega_ferie_state::pen_y_mapper(float linear_value) { // Parameter `linear_value` is ignored, since we will read the input port directly // for adjustments, just need to return that value in the expected range [0.0f..1.0f]. - return (float) pen_y_rescale_r() / 0xff; + return float(pen_y_rescale_r()) / 0xff; } ioport_value sega_ferie_state::pen_y_rescale_r() |
