From 456e6948a83bec6fb3245f8aa247bb4a588702ee Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 19 Aug 2023 03:21:05 +1000 Subject: [PATCH] ui/utils: Added a source file filter for system selection menu. * ui/selmenu.cpp: Show system source file in general info. * frontend/infoxml.cpp: Consolidated source file path formatting in one place. * ui/devopt.cpp: Get decimal separator from C++ locale. --- src/frontend/mame/clifront.cpp | 32 ++++-------------- src/frontend/mame/infoxml.cpp | 47 +++++++++++++++++--------- src/frontend/mame/infoxml.h | 3 ++ src/frontend/mame/ui/devopt.cpp | 18 +++++++--- src/frontend/mame/ui/info.cpp | 10 ++---- src/frontend/mame/ui/selmenu.cpp | 3 ++ src/frontend/mame/ui/simpleselgame.cpp | 10 ++---- src/frontend/mame/ui/systemlist.cpp | 1 + src/frontend/mame/ui/utils.cpp | 40 +++++++++++++++++++++- src/frontend/mame/ui/utils.h | 5 +++ 10 files changed, 108 insertions(+), 61 deletions(-) diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 74e6c850786..4ded3c16fc3 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -403,25 +403,10 @@ void cli_frontend::listsource(const std::vector &args) { auto const list_system_source = [] (device_type type) { - std::string_view src(type.source()); - auto prefix(src.find("src/mame/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\mame\\"); - if (std::string_view::npos != prefix) - { - src.remove_prefix(prefix + 9); - } - else - { - auto prefix(src.find("src/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\"); - if (std::string_view::npos != prefix) - { - src.remove_prefix(prefix + 4); - } - } - osd_printf_info("%-16s %s\n", type.shortname(), src); + osd_printf_info( + "%-16s %s\n", + type.shortname(), + info_xml_creator::format_sourcefile(type.source())); }; apply_action( args, @@ -520,13 +505,8 @@ void cli_frontend::listbrothers(const std::vector &args) drivlist.reset(); while (drivlist.next()) { - std::string_view src(drivlist.driver().type.source()); - auto prefix(src.find("src/mame/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\mame\\"); - if (std::string_view::npos != prefix) - src.remove_prefix(prefix + 9); - int const clone_of = drivlist.clone(); + auto const src(info_xml_creator::format_sourcefile(drivlist.driver().type.source())); + int const clone_of(drivlist.clone()); if (clone_of != -1) osd_printf_info("%-20s %-16s %s\n", src, drivlist.driver().name, (clone_of == -1 ? "" : drivlist.driver(clone_of).name)); else diff --git a/src/frontend/mame/infoxml.cpp b/src/frontend/mame/infoxml.cpp index 31651bef2b6..37d649a1131 100644 --- a/src/frontend/mame/infoxml.cpp +++ b/src/frontend/mame/infoxml.cpp @@ -340,7 +340,7 @@ constexpr std::pair f_feature_names[] = { //------------------------------------------------- -// get_feature_name - get XML name for feature +// feature_name - get XML name for feature //------------------------------------------------- char const *info_xml_creator::feature_name(device_t::feature_type feature) @@ -357,6 +357,33 @@ char const *info_xml_creator::feature_name(device_t::feature_type feature) } +//------------------------------------------------- +// format_sourcefile - sanitise source file path +//------------------------------------------------- + +std::string info_xml_creator::format_sourcefile(std::string_view path) +{ + using namespace std::literals; + + if (auto prefix(path.rfind("src/mame/"sv)); std::string_view::npos != prefix) + path.remove_prefix(prefix + 9); + else if (auto prefix(path.rfind("src\\mame\\"sv)); std::string_view::npos != prefix) + path.remove_prefix(prefix + 9); + else if (auto prefix(path.rfind("/src/"sv)); std::string_view::npos != prefix) + path.remove_prefix(prefix + 5); + else if (auto prefix(path.rfind("\\src\\"sv)); std::string_view::npos != prefix) + path.remove_prefix(prefix + 5); + else if (path.substr(0, 4) == "src/"sv) + path.remove_prefix(4); + else if (path.substr(0, 4) == "src\\"sv) + path.remove_prefix(4); + + std::string result(path); + std::replace(result.begin(), result.end(), '\\', '/'); + return result; +} + + //------------------------------------------------- // info_xml_creator - constructor //------------------------------------------------- @@ -714,14 +741,8 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive // print the header and the machine name util::stream_format(out, "\t<%s name=\"%s\"", XML_TOP, normalize_string(driver.name)); - // strip away any path information from the source_file and output it - std::string_view src(driver.type.source()); - auto prefix(src.find("src/mame/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\mame\\"); - if (std::string_view::npos != prefix) - src.remove_prefix(prefix + 9); - util::stream_format(out, " sourcefile=\"%s\"", normalize_string(src)); + // strip away extra path information from the source file and output it + util::stream_format(out, " sourcefile=\"%s\"", normalize_string(info_xml_creator::format_sourcefile(driver.type.source()))); // append bios and runnable flags if (driver.flags & machine_flags::IS_BIOS_ROOT) @@ -815,13 +836,7 @@ void output_one_device(std::ostream &out, machine_config &config, device_t &devi // start to output info util::stream_format(out, "\t<%s name=\"%s\"", XML_TOP, normalize_string(device.shortname())); - std::string_view src(device.source()); - auto prefix(src.find("src/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\"); - if (std::string_view::npos != prefix) - src.remove_prefix(prefix + 4); - util::stream_format(out, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(src)); + util::stream_format(out, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(info_xml_creator::format_sourcefile(device.source()))); auto const parent(device.type().parent_rom_device_type()); if (parent) util::stream_format(out, " romof=\"%s\"", normalize_string(parent->shortname())); diff --git a/src/frontend/mame/infoxml.h b/src/frontend/mame/infoxml.h index 00a614bcd3a..06141ef83ba 100644 --- a/src/frontend/mame/infoxml.h +++ b/src/frontend/mame/infoxml.h @@ -16,6 +16,8 @@ #include "emuopts.h" #include +#include +#include #include @@ -35,6 +37,7 @@ public: void output(std::ostream &out, const std::function &filter = { }, bool include_devices = true); static char const *feature_name(device_t::feature_type feature); + static std::string format_sourcefile(std::string_view path); private: // internal state diff --git a/src/frontend/mame/ui/devopt.cpp b/src/frontend/mame/ui/devopt.cpp index 0e9b44a25fc..cb0574bec6c 100644 --- a/src/frontend/mame/ui/devopt.cpp +++ b/src/frontend/mame/ui/devopt.cpp @@ -15,7 +15,10 @@ #include "romload.h" #include "screen.h" -#include "utf8.h" +#include "util/unicode.h" +#include "util/utf8.h" + +#include namespace ui { @@ -55,6 +58,13 @@ void menu_device_config::populate_text(std::optional &layout, float if (!d.configured()) d.config_complete(); + // get decimal separator + std::string point; + { + wchar_t const s(std::use_facet >(std::locale()).decimal_point()); + point = utf8_from_wstring(std::wstring_view(&s, 1)); + } + layout->add_text( util::string_format( m_mounted @@ -93,7 +103,7 @@ void menu_device_config::populate_text(std::optional &layout, float if (d > 0) { size_t dpos = hz.length() - d; - hz.insert(dpos, "."); + hz.insert(dpos, point); size_t last = hz.find_last_not_of('0'); hz = hz.substr(0, last + (last != dpos ? 1 : 0)); } @@ -129,7 +139,7 @@ void menu_device_config::populate_text(std::optional &layout, float if (valid) { size_t dpos = hz.length() - 6; - hz.insert(dpos, "."); + hz.insert(dpos, point); size_t last = hz.find_last_not_of('0'); hz = hz.substr(0, last + (last != dpos ? 1 : 0)); } @@ -175,7 +185,7 @@ void menu_device_config::populate_text(std::optional &layout, float if (d > 0) { size_t dpos = hz.length() - d; - hz.insert(dpos, "."); + hz.insert(dpos, point); size_t last = hz.find_last_not_of('0'); hz = hz.substr(0, last + (last != dpos ? 1 : 0)); } diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index 569070f8a29..8d672dd8c96 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -14,6 +14,8 @@ #include "ui/systemlist.h" #include "ui/ui.h" +#include "infoxml.h" + #include "drivenum.h" #include "emuopts.h" #include "romload.h" @@ -374,17 +376,11 @@ std::string machine_info::game_info_string() const } // print description, manufacturer, and CPU: - std::string_view src(m_machine.system().type.source()); - auto prefix(src.find("src/mame/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\mame\\"); - if (std::string_view::npos != prefix) - src.remove_prefix(prefix + 9); util::stream_format(buf, _("%1$s\n%2$s %3$s\nDriver: %4$s\n\nCPU:\n"), system_list::instance().systems()[driver_list::find(m_machine.system().name)].description, m_machine.system().year, m_machine.system().manufacturer, - src); + info_xml_creator::format_sourcefile(m_machine.system().type.source())); // loop over all CPUs execute_interface_enumerator execiter(m_machine.root_device()); diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index baa89bfefe0..d846b21ba57 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -17,6 +17,7 @@ #include "audit.h" #include "cheat.h" +#include "infoxml.h" #include "mame.h" #include "mameopts.h" @@ -3124,6 +3125,8 @@ void menu_select_launch::general_info(ui_system_info const *system, game_driver str << _("Media Audit\tDisabled\nSamples Audit\tDisabled\n"); } + util::stream_format(str, _("Source File\t%1$s\n"), info_xml_creator::format_sourcefile(driver.type.source())); + buffer = std::move(str).str(); } diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp index 3919f97df23..094f1f7744d 100644 --- a/src/frontend/mame/ui/simpleselgame.cpp +++ b/src/frontend/mame/ui/simpleselgame.cpp @@ -17,6 +17,8 @@ #include "ui/ui.h" #include "ui/utils.h" +#include "infoxml.h" + #include "audit.h" #include "drivenum.h" #include "emuopts.h" @@ -352,13 +354,7 @@ void simple_menu_select_game::custom_render(void *selectedref, float top, float tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer); // next line source path - std::string_view src(driver->type.source()); - auto prefix(src.find("src/mame/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\mame\\"); - if (std::string_view::npos != prefix) - src.remove_prefix(prefix + 9); - tempbuf[2] = string_format(_("Driver: %1$s"), src); + tempbuf[2] = string_format(_("Driver: %1$s"), info_xml_creator::format_sourcefile(driver->type.source())); // update cached values if selection changed if (driver != m_cached_driver) diff --git a/src/frontend/mame/ui/systemlist.cpp b/src/frontend/mame/ui/systemlist.cpp index d2132e7f6c9..d7450aac162 100644 --- a/src/frontend/mame/ui/systemlist.cpp +++ b/src/frontend/mame/ui/systemlist.cpp @@ -301,6 +301,7 @@ void system_list::populate_list(bool copydesc) m_filter_data.add_manufacturer(driver.manufacturer); m_filter_data.add_year(driver.year); + m_filter_data.add_source_file(driver.type.source()); } } } diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp index d9e58280e7a..b83abc5c277 100644 --- a/src/frontend/mame/ui/utils.cpp +++ b/src/frontend/mame/ui/utils.cpp @@ -14,6 +14,7 @@ #include "ui/inifile.h" #include "ui/selector.h" +#include "infoxml.h" #include "language.h" #include "mame.h" @@ -96,6 +97,7 @@ constexpr char const *MACHINE_FILTER_NAMES[machine_filter::COUNT] = { N_p("machine-filter", "Clones"), N_p("machine-filter", "Manufacturer"), N_p("machine-filter", "Year"), + N_p("machine-filter", "Source File"), N_p("machine-filter", "Save Supported"), N_p("machine-filter", "Save Unsupported"), N_p("machine-filter", "CHD Required"), @@ -800,6 +802,18 @@ public: }; +class source_file_machine_filter : public choice_filter_impl_base +{ +public: + source_file_machine_filter(machine_filter_data const &data, char const *value, util::core_file *file, unsigned indent) + : choice_filter_impl_base(data.source_files(), value) + { + } + + virtual bool apply(ui_system_info const &system) const override { return !have_choices() || (selection_valid() && (selection_text() == info_xml_creator::format_sourcefile(system.driver->type.source()))); } +}; + + //------------------------------------------------- // complementary machine filters @@ -1227,6 +1241,7 @@ public: case FAVORITE: case MANUFACTURER: case YEAR: + case SOURCE_FILE: case CUSTOM: case COUNT: break; @@ -1236,7 +1251,17 @@ public: static bool is_inclusion(type n) { - return (CATEGORY == n) || (MANUFACTURER == n) || (YEAR == n); + switch (n) + { + case CATEGORY: + case MANUFACTURER: + case YEAR: + case SOURCE_FILE: + return true; + + default: + return false; + } } private: @@ -1602,10 +1627,21 @@ void machine_filter_data::add_year(std::string const &year) m_years.emplace(pos, year); } +void machine_filter_data::add_source_file(std::string_view path) +{ + std::vector::iterator const pos(std::lower_bound(m_source_files.begin(), m_source_files.end(), path)); + if ((m_source_files.end() == pos) || (*pos != path)) + m_source_files.emplace(pos, path); +} + void machine_filter_data::finalise() { + for (std::string &path : m_source_files) + path = info_xml_creator::format_sourcefile(path); + std::stable_sort(m_manufacturers.begin(), m_manufacturers.end()); std::stable_sort(m_years.begin(), m_years.end()); + std::stable_sort(m_source_files.begin(), m_source_files.end()); } std::string machine_filter_data::extract_manufacturer(std::string const &manufacturer) @@ -1780,6 +1816,8 @@ machine_filter::ptr machine_filter::create(type n, machine_filter_data const &da return std::make_unique(data, value, file, indent); case YEAR: return std::make_unique(data, value, file, indent); + case SOURCE_FILE: + return std::make_unique(data, value, file, indent); case SAVE: return std::make_unique(data, value, file, indent); case NOSAVE: diff --git a/src/frontend/mame/ui/utils.h b/src/frontend/mame/ui/utils.h index ba340541078..c0a4e1d30ca 100644 --- a/src/frontend/mame/ui/utils.h +++ b/src/frontend/mame/ui/utils.h @@ -186,6 +186,7 @@ public: CLONES, MANUFACTURER, YEAR, + SOURCE_FILE, SAVE, NOSAVE, CHD, @@ -276,10 +277,13 @@ class machine_filter_data public: std::vector const &manufacturers() const { return m_manufacturers; } std::vector const &years() const { return m_years; } + std::vector const &source_files() const { return m_source_files; } // adding entries void add_manufacturer(std::string const &manufacturer); void add_year(std::string const &year); + void add_source_file(std::string_view path); + void finalise(); // use heuristics to extract meaningful parts from machine metadata @@ -306,6 +310,7 @@ private: std::vector m_manufacturers; std::vector m_years; + std::vector m_source_files; machine_filter::type m_current_filter = machine_filter::ALL; filter_map m_filters;