summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2026-05-10 03:07:34 +1000
committer Vas Crabb <vas@vastheman.com>2026-05-10 03:34:22 +1000
commitd6dd21e2013c80ecbc97dc3cce3df964e8e4c2aa (patch)
tree8a42e21bf7ed3fe4bad8769fcd8aa52b8469a48c
parent937399619268781d75a0f04edf5b2fd9e247ce38 (diff)
ui: Improved media control experience, cleaned up a lot of bad code.
ui/imgcntrl, ui/floppycntrl.cpp: Completely reworked logic - backtracking through menus is more intuitive, and more context is retained when encountering an error (it should be a bit easier to follow the code as well). ui/floppycntrl.cpp: Don't show the initial content selection menu when opening an image to read from while writing to a separate file. ui/filecreate.cpp: Moved the logic to enumerate floppy formats into the menu, use headings and separators, use callbacks to notify when an item is selected, don't pop menus when an item is selected, avoid actual work in destructors. ui/midiinout.cpp: Fixed infinite growth when repopulating the menu, don't pop the menu when a port is chosen, use a callback to notify that a port is chosen, use headings and separators, and in informative placeholder if no ports are available. ui/filesel.cpp: Don't show the option to write to a floppy diff (it still isn't implemented, it can be re-added if it's ever implemented), don't pop the menus when selecting an item, avoid actual work in destructors. ui/filemngr.cpp: Show more detail in the info box below the menu for software items and presets, substantially simplified the code for walking media devices. ui/info.cpp: Got rid of the media information menu, added media information to the system information menu. ui/menu.cpp: Allow immediately adjusting the hovered item with pen/mouse, saving a click. emu/ioport: Fixed incorrect strings displayed for 4C_5C, 3C_4C, 2C_3C and 3C_5C. The array absolutely must stay in order. Also added an assertion to catch these errors early. emu/ioport.cpp: Use a much less gross method of handling default strings (apparently someone forgot about function overloading). emu/ioport.cpp: Retired the crosshair mapper member macros - they don't serve much purpose. util/zippath.cpp: Actually report a failure to open a plain file rather than looking for files inside non-existent archives, making every error turn into "file not found". formats/flopimg.cpp: Allow matching extensions on string object names, rather than requiring a NUL-terminated string.
-rw-r--r--src/devices/cpu/mcs51/ds5002fp.h2
-rw-r--r--src/devices/cpu/mcs51/i80c51.h2
-rw-r--r--src/devices/cpu/mcs51/i80c52.h2
-rw-r--r--src/devices/cpu/mcs51/sab80c535.h2
-rw-r--r--src/emu/ioport.cpp42
-rw-r--r--src/emu/ioport.h16
-rw-r--r--src/emu/validity.cpp33
-rw-r--r--src/emu/validity.h5
-rw-r--r--src/frontend/mame/ui/filecreate.cpp109
-rw-r--r--src/frontend/mame/ui/filecreate.h60
-rw-r--r--src/frontend/mame/ui/filemngr.cpp137
-rw-r--r--src/frontend/mame/ui/filesel.cpp48
-rw-r--r--src/frontend/mame/ui/filesel.h9
-rw-r--r--src/frontend/mame/ui/floppycntrl.cpp356
-rw-r--r--src/frontend/mame/ui/floppycntrl.h23
-rw-r--r--src/frontend/mame/ui/imgcntrl.cpp480
-rw-r--r--src/frontend/mame/ui/imgcntrl.h43
-rw-r--r--src/frontend/mame/ui/info.cpp178
-rw-r--r--src/frontend/mame/ui/info.h23
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp16
-rw-r--r--src/frontend/mame/ui/menu.cpp44
-rw-r--r--src/frontend/mame/ui/midiinout.cpp81
-rw-r--r--src/frontend/mame/ui/midiinout.h24
-rw-r--r--src/frontend/mame/ui/swlist.cpp90
-rw-r--r--src/frontend/mame/ui/swlist.h58
-rw-r--r--src/lib/formats/flopimg.cpp19
-rw-r--r--src/lib/formats/flopimg.h2
-rw-r--r--src/lib/util/zippath.cpp29
-rw-r--r--src/mame/casio/pickytlk.cpp6
-rw-r--r--src/mame/sega/sega_beena.cpp4
-rw-r--r--src/mame/sega/sega_ferie.cpp6
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 &current_directory, std::string &current_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 &current_directory, std::string &current_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()