From 0aad5cb057cf872a272964c25ea522404bf668ce Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 19 Jul 2017 22:04:29 +1000 Subject: Make internal UI display list of missing files if system/software set is found but incomplete. Also consolidated selgame/selsoft code for actually launching systems into one place. --- src/frontend/mame/audit.cpp | 5 +- src/frontend/mame/ui/inifile.cpp | 4 +- src/frontend/mame/ui/selgame.cpp | 134 +++++-------- src/frontend/mame/ui/selgame.h | 4 + src/frontend/mame/ui/selmenu.cpp | 406 ++++++++++++++++++++++++++++++++++++++- src/frontend/mame/ui/selmenu.h | 94 ++++++++- src/frontend/mame/ui/selsoft.cpp | 401 +++----------------------------------- src/frontend/mame/ui/selsoft.h | 52 +---- src/frontend/mame/ui/utils.cpp | 39 ++++ src/frontend/mame/ui/utils.h | 43 +++-- 10 files changed, 645 insertions(+), 537 deletions(-) diff --git a/src/frontend/mame/audit.cpp b/src/frontend/mame/audit.cpp index 97bad77b76b..b0268675005 100644 --- a/src/frontend/mame/audit.cpp +++ b/src/frontend/mame/audit.cpp @@ -273,7 +273,10 @@ media_auditor::summary media_auditor::summarize(const char *name, std::ostream * // output the game name, file name, and length (if applicable) if (output) { - util::stream_format(*output, "%-12s: %s", name, record.name()); + if (name) + util::stream_format(*output, "%-12s: %s", name, record.name()); + else + util::stream_format(*output, "%s", record.name()); if (record.expected_length() > 0) util::stream_format(*output, " (%d bytes)", record.expected_length()); *output << " - "; diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp index 3b74671af1e..2da9adb59d2 100644 --- a/src/frontend/mame/ui/inifile.cpp +++ b/src/frontend/mame/ui/inifile.cpp @@ -159,9 +159,7 @@ favorite_manager::favorite_manager(running_machine &machine, ui_options &moption void favorite_manager::add_favorite_game(const game_driver *driver) { - m_list.emplace(driver->type.fullname(), - ui_software_info{driver->name, driver->type.fullname(), "", "", "", 0, "", driver, "", "", "", - 1, "", "", "", true}); + m_list.emplace(driver->type.fullname(), *driver); save_favorite_games(); } diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 33cebb00083..fce7ad41d9f 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -33,6 +33,7 @@ #include "softlist_dev.h" #include "uiinput.h" #include "luaengine.h" + extern const char UI_VERSION_TAG[]; namespace ui { @@ -77,7 +78,7 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &conta if (first_start) { - reselect_last::driver = moptions.last_used_machine(); + reselect_last::set_driver(moptions.last_used_machine()); std::string tmp(moptions.last_used_filter()); std::size_t found = tmp.find_first_of(","); if (found == std::string::npos) @@ -171,7 +172,7 @@ void menu_select_game::handle() bool check_filter = false; - // if i have to load datfile, performe an hard reset + // if I have to load datfile, perform a hard reset if (ui_globals::reset) { ui_globals::reset = false; @@ -197,11 +198,9 @@ void menu_select_game::handle() const event *menu_event = process(PROCESS_LR_REPEAT); if (menu_event && menu_event->itemref) { - if (m_ui_error) + if (dismiss_error()) { // reset the error on any future menu_event - m_ui_error = false; - machine().ui_input().reset(); } else if (menu_event->iptkey == IPT_UI_SELECT) { @@ -459,9 +458,7 @@ void menu_select_game::handle() } // if we're in an error state, overlay an error message - if (m_ui_error) - ui().draw_text_box(container(), _("The selected machine is missing one or more required ROM or CHD images. " - "Please select a different machine.\n\nPress any key to continue."), ui::text_layout::CENTER, 0.5f, 0.5f, UI_RED_COLOR); + draw_error_text(); // handle filters selection from key shortcuts if (check_filter) @@ -536,7 +533,7 @@ void menu_select_game::populate(float &customtop, float &custombottom) int curitem = 0; for (auto & elem : m_displaylist) { - if (old_item_selected == -1 && elem->name == reselect_last::driver) + if (old_item_selected == -1 && elem->name == reselect_last::driver()) old_item_selected = curitem; bool cloneof = strcmp(elem->parent, "0"); @@ -564,7 +561,7 @@ void menu_select_game::populate(float &customtop, float &custombottom) auto flags = flags_ui | FLAG_UI_FAVORITE; if (favmap.second.startempty == 1) { - if (old_item_selected == -1 && favmap.second.shortname == reselect_last::driver) + if (old_item_selected == -1 && favmap.second.shortname == reselect_last::driver()) old_item_selected = curitem; bool cloneof = strcmp(favmap.second.driver->parent, "0"); @@ -579,7 +576,7 @@ void menu_select_game::populate(float &customtop, float &custombottom) } else { - if (old_item_selected == -1 && favmap.second.shortname == reselect_last::driver) + if (old_item_selected == -1 && favmap.second.shortname == reselect_last::driver()) old_item_selected = curitem; item_append(favmap.second.longname, favmap.second.devicetype, favmap.second.parentname.empty() ? flags : (FLAG_INVERT | flags), (void *)&favmap.second); @@ -618,11 +615,13 @@ void menu_select_game::populate(float &customtop, float &custombottom) else top_line = selected - (ui_globals::visible_main_lines / 2); - if (reselect_last::software.empty()) + if (reselect_last::software().empty()) reselect_last::reset(); } else + { reselect_last::reset(); + } } //------------------------------------------------- @@ -773,31 +772,32 @@ void menu_select_game::inkey_select(const event *menu_event) { const game_driver *driver = (const game_driver *)menu_event->itemref; - // special case for configure options if ((uintptr_t)driver == CONF_OPTS) + { + // special case for configure options menu::stack_push(ui(), container()); - - // special case for configure machine + } else if (uintptr_t(driver) == CONF_MACHINE) { + // special case for configure machine if (m_prev_selected) menu::stack_push(ui(), container(), reinterpret_cast(m_prev_selected)); return; } - - // special case for configure plugins else if ((uintptr_t)driver == CONF_PLUGINS) { + // special case for configure plugins menu::stack_push(ui(), container()); } - // anything else is a driver else { + // anything else is a driver + // audit the game first to see if we're going to work driver_enumerator enumerator(machine().options(), *driver); enumerator.next(); media_auditor auditor(enumerator); - media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST); + media_auditor::summary const summary = auditor.audit_media(AUDIT_VALIDATE_FAST); // if everything looks good, schedule the new driver if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) @@ -812,24 +812,13 @@ void menu_select_game::inkey_select(const event *menu_event) } } - s_bios biosname; - if (!ui().options().skip_bios_menu() && has_multiple_bios(driver, biosname)) - menu::stack_push(ui(), container(), biosname, (void *)driver, false, false); - else - { - reselect_last::driver = driver->name; - reselect_last::software.clear(); - reselect_last::swlist.clear(); - mame_machine_manager::instance()->schedule_new_driver(*driver); - machine().schedule_hard_reset(); - stack_reset(); - } + if (!select_bios(*driver, false)) + launch_system(*driver); } - // otherwise, display an error else { - reset(reset_options::REMEMBER_REF); - m_ui_error = true; + // otherwise, display an error + set_error(reset_options::REMEMBER_REF, make_error_text(media_auditor::NOTFOUND != summary, auditor)); } } } @@ -841,7 +830,6 @@ void menu_select_game::inkey_select(const event *menu_event) void menu_select_game::inkey_select_favorite(const event *menu_event) { ui_software_info *ui_swinfo = (ui_software_info *)menu_event->itemref; - ui_options &mopt = ui().options(); if ((uintptr_t)ui_swinfo == CONF_OPTS) { @@ -869,7 +857,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) driver_enumerator enumerator(machine().options(), *ui_swinfo->driver); enumerator.next(); media_auditor auditor(enumerator); - media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST); + media_auditor::summary const summary = auditor.audit_media(AUDIT_VALIDATE_FAST); if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) { @@ -884,25 +872,16 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) } // if everything looks good, schedule the new driver - s_bios biosname; - if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname)) - menu::stack_push(ui(), container(), biosname, (void *)ui_swinfo->driver, false, false); - else + if (!select_bios(*ui_swinfo->driver, false)) { - reselect_last::driver = ui_swinfo->driver->name; - reselect_last::software.clear(); - reselect_last::swlist.clear(); - reselect_last::set(true); - mame_machine_manager::instance()->schedule_new_driver(*ui_swinfo->driver); - machine().schedule_hard_reset(); - stack_reset(); + reselect_last::reselect(true); + launch_system(*ui_swinfo->driver); } } else { // otherwise, display an error - reset(reset_options::REMEMBER_REF); - m_ui_error = true; + set_error(reset_options::REMEMBER_REF, make_error_text(media_auditor::NOTFOUND != summary, auditor)); } } else @@ -914,50 +893,17 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) software_list_device *swlist = software_list_device::find_by_name(*drv.config(), ui_swinfo->listname.c_str()); const software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str()); - media_auditor::summary summary = auditor.audit_software(swlist->list_name(), swinfo, AUDIT_VALIDATE_FAST); + media_auditor::summary const summary = auditor.audit_software(swlist->list_name(), swinfo, AUDIT_VALIDATE_FAST); if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) { - s_bios biosname; - if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname)) - { - menu::stack_push(ui(), container(), biosname, (void *)ui_swinfo, true, false); - return; - } - else if (!mopt.skip_parts_menu() && swinfo->has_multiple_parts(ui_swinfo->interface.c_str())) - { - s_parts parts; - for (const software_part &swpart : swinfo->parts()) - { - if (swpart.matches_interface(ui_swinfo->interface.c_str())) - { - std::string menu_part_name(swpart.name()); - if (swpart.feature("part_id") != nullptr) - menu_part_name.assign("(").append(swpart.feature("part_id")).append(")"); - parts.emplace(swpart.name(), menu_part_name); - } - } - menu::stack_push(ui(), container(), parts, ui_swinfo); - return; - } - - std::string string_list = string_format("%s:%s:%s:%s", ui_swinfo->listname, ui_swinfo->shortname, ui_swinfo->part, ui_swinfo->instance); - mopt.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE); - std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname); - mopt.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE); - reselect_last::driver = drv.driver().name; - reselect_last::software = ui_swinfo->shortname; - reselect_last::swlist = ui_swinfo->listname; - mame_machine_manager::instance()->schedule_new_driver(drv.driver()); - machine().schedule_hard_reset(); - stack_reset(); + if (!select_bios(*ui_swinfo, false) && !select_part(*swinfo, *ui_swinfo)) + launch_system(drv.driver(), *ui_swinfo, ui_swinfo->part); } - - // otherwise, display an error else { - reset(reset_options::REMEMBER_POSITION); - m_ui_error = true; + // otherwise, display an error + set_error(reset_options::REMEMBER_POSITION, make_error_text(media_auditor::NOTFOUND != summary, auditor)); } } } @@ -1745,4 +1691,18 @@ std::string menu_select_game::make_software_description(ui_software_info const & return string_format(_("System: %1$-.100s"), software.driver->type.fullname()); } + +std::string menu_select_game::make_error_text(bool summary, media_auditor const &auditor) +{ + std::ostringstream str; + str << _("The selected machine is missing one or more required ROM or CHD images. Please select a different machine.\n\n"); + if (summary) + { + auditor.summarize(nullptr, &str); + str << "\n"; + } + str << _("Press any key to continue."); + return str.str(); +} + } // namespace ui diff --git a/src/frontend/mame/ui/selgame.h b/src/frontend/mame/ui/selgame.h index fd9dc1ba1ca..9ec37346fc2 100644 --- a/src/frontend/mame/ui/selgame.h +++ b/src/frontend/mame/ui/selgame.h @@ -15,8 +15,10 @@ #include "ui/selmenu.h" +class media_auditor; namespace ui { + class menu_select_game : public menu_select_launch { public: @@ -76,6 +78,8 @@ private: bool load_available_machines(); void load_custom_filters(); + static std::string make_error_text(bool summary, media_auditor const &auditor); + void *get_selection_ptr() const { void *const selected_ref(get_selection_ref()); diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index 03cbe9fa10c..73baa494dcc 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -14,7 +14,6 @@ #include "ui/icorender.h" #include "ui/inifile.h" -#include "ui/utils.h" // these hold static bitmap images #include "ui/defimg.ipp" @@ -28,6 +27,7 @@ #include "emuopts.h" #include "rendutil.h" #include "softlist.h" +#include "softlist_dev.h" #include "uiinput.h" #include "luaengine.h" @@ -38,7 +38,9 @@ namespace ui { + namespace { + std::pair const arts_info[] = { { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY }, @@ -69,10 +71,259 @@ char const *const hover_msg[] = { } // anonymous namespace +std::string menu_select_launch::reselect_last::s_driver; +std::string menu_select_launch::reselect_last::s_software; +std::string menu_select_launch::reselect_last::s_swlist; +bool menu_select_launch::reselect_last::s_reselect = false; + std::mutex menu_select_launch::s_cache_guard; menu_select_launch::cache_ptr_map menu_select_launch::s_caches; +template bool menu_select_launch::select_bios(game_driver const &, bool); +template bool menu_select_launch::select_bios(ui_software_info const &, bool); + + +void menu_select_launch::reselect_last::reset() +{ + s_driver.clear(); + s_software.clear(); + s_swlist.clear(); + reselect(false); +} + +void menu_select_launch::reselect_last::set_driver(std::string const &name) +{ + s_driver = name; + s_software.clear(); + s_swlist.clear(); +} + +void menu_select_launch::reselect_last::set_software(game_driver const &driver, ui_software_info const &swinfo) +{ + s_driver = driver.name; + if (swinfo.startempty) + { + // magic strings are bad... + s_software = "[Start empty]"; + s_swlist.clear(); + } + else + { + s_software = swinfo.shortname; + s_swlist = swinfo.listname; + } +} + + +//------------------------------------------------- +// ctor +//------------------------------------------------- + +menu_select_launch::software_parts::software_parts(mame_ui_manager &mui, render_container &container, s_parts &&parts, ui_software_info const &ui_info) + : menu(mui, container) + , m_uiinfo(ui_info) + , m_parts(std::move(parts)) +{ +} + +//------------------------------------------------- +// dtor +//------------------------------------------------- + +menu_select_launch::software_parts::~software_parts() +{ +} + +//------------------------------------------------- +// populate +//------------------------------------------------- + +void menu_select_launch::software_parts::populate(float &customtop, float &custombottom) +{ + for (auto & elem : m_parts) + item_append(elem.first, elem.second, 0, (void *)&elem); + + item_append(menu_item_type::SEPARATOR); + customtop = ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER); +} + +//------------------------------------------------- +// handle +//------------------------------------------------- + +void menu_select_launch::software_parts::handle() +{ + // process the menu + const event *menu_event = process(0); + if (menu_event && (menu_event->iptkey) == IPT_UI_SELECT && menu_event->itemref) + { + for (auto const &elem : m_parts) + { + if ((void*)&elem == menu_event->itemref) + { + launch_system(ui(), *m_uiinfo.driver, &m_uiinfo, &elem.first, nullptr); + break; + } + } + } +} + +//------------------------------------------------- +// perform our special rendering +//------------------------------------------------- + +void menu_select_launch::software_parts::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) +{ + float width; + ui().draw_text_full(container(), _("Software part selection:"), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, + mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &width, nullptr); + width += 2 * UI_BOX_LR_BORDER; + float maxwidth = std::max(origx2 - origx1, width); + + // compute our bounds + float x1 = 0.5f - 0.5f * maxwidth; + float x2 = x1 + maxwidth; + float y1 = origy1 - top; + float y2 = origy1 - UI_BOX_TB_BORDER; + + // draw a box + ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); + + // take off the borders + x1 += UI_BOX_LR_BORDER; + x2 -= UI_BOX_LR_BORDER; + y1 += UI_BOX_TB_BORDER; + + // draw the text within it + ui().draw_text_full(container(), _("Software part selection:"), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, + mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); +} + + +//------------------------------------------------- +// ctor +//------------------------------------------------- + +menu_select_launch::bios_selection::bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, game_driver const &driver, bool inlist) + : bios_selection(mui, container, std::move(biosname), reinterpret_cast(&driver), false, inlist) +{ +} + +menu_select_launch::bios_selection::bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, ui_software_info const &swinfo, bool inlist) + : bios_selection(mui, container, std::move(biosname), reinterpret_cast(&swinfo), true, inlist) +{ +} + +menu_select_launch::bios_selection::bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, void const *driver, bool software, bool inlist) + : menu(mui, container) + , m_driver(driver) + , m_software(software) + , m_inlist(inlist) + , m_bios(std::move(biosname)) +{ +} + +//------------------------------------------------- +// dtor +//------------------------------------------------- + +menu_select_launch::bios_selection::~bios_selection() +{ +} + +//------------------------------------------------- +// populate +//------------------------------------------------- + +void menu_select_launch::bios_selection::populate(float &customtop, float &custombottom) +{ + for (auto & elem : m_bios) + item_append(elem.first, "", 0, (void *)&elem.first); + + item_append(menu_item_type::SEPARATOR); + customtop = ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER); +} + +//------------------------------------------------- +// handle +//------------------------------------------------- + +void menu_select_launch::bios_selection::handle() +{ + // process the menu + const event *menu_event = process(0); + if (menu_event && menu_event->iptkey == IPT_UI_SELECT && menu_event->itemref) + { + for (auto & elem : m_bios) + { + if ((void*)&elem.first == menu_event->itemref) + { + if (!m_software) + { + const game_driver *s_driver = (const game_driver *)m_driver; + if (m_inlist) + { + ui_software_info empty(*s_driver); + launch_system(ui(), *s_driver, &empty, nullptr, &elem.second); + } + else + { + reselect_last::reselect(true); + launch_system(ui(), *s_driver, nullptr, nullptr, &elem.second); + } + } + else + { + ui_software_info *ui_swinfo = (ui_software_info *)m_driver; + machine().options().set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE); // oh dear, relying on this persisting through the part selection menu + driver_enumerator drivlist(machine().options(), *ui_swinfo->driver); + drivlist.next(); + software_list_device *swlist = software_list_device::find_by_name(*drivlist.config(), ui_swinfo->listname.c_str()); + const software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str()); + if (!select_part(ui(), container(), *swinfo, *ui_swinfo)) + { + reselect_last::reselect(true); + launch_system(ui(), drivlist.driver(), ui_swinfo, nullptr, &elem.second); + } + } + } + } + } +} + +//------------------------------------------------- +// perform our special rendering +//------------------------------------------------- + +void menu_select_launch::bios_selection::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) +{ + float width; + ui().draw_text_full(container(), _("Bios selection:"), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, + mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &width, nullptr); + width += 2 * UI_BOX_LR_BORDER; + float maxwidth = std::max(origx2 - origx1, width); + + // compute our bounds + float x1 = 0.5f - 0.5f * maxwidth; + float x2 = x1 + maxwidth; + float y1 = origy1 - top; + float y2 = origy1 - UI_BOX_TB_BORDER; + + // draw a box + ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); + + // take off the borders + x1 += UI_BOX_LR_BORDER; + x2 -= UI_BOX_LR_BORDER; + y1 += UI_BOX_TB_BORDER; + + // draw the text within it + ui().draw_text_full(container(), _("Bios selection:"), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, + mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); +} + + menu_select_launch::cache::cache(running_machine &machine) : m_snapx_bitmap(std::make_unique(0, 0)) , m_snapx_texture() @@ -151,6 +402,7 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c , m_info_driver(nullptr) , m_info_software(nullptr) , m_info_view(-1) + , m_items_list() , m_info_buffer() , m_cache() , m_is_swlist(is_swlist) @@ -179,6 +431,71 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c } +bool menu_select_launch::dismiss_error() +{ + bool const result = m_ui_error; + if (result) + { + m_ui_error = false; + m_error_text.clear(); + machine().ui_input().reset(); + } + return result; +} + +void menu_select_launch::set_error(reset_options ropt, std::string &&message) +{ + reset(ropt); + m_ui_error = true; + m_error_text = std::move(message); +} + + +//------------------------------------------------- +// actually start an emulation session +//------------------------------------------------- + +void menu_select_launch::launch_system(mame_ui_manager &mui, game_driver const &driver, ui_software_info const *swinfo, std::string const *part, int const *bios) +{ + emu_options &moptions(mui.machine().options()); + moptions.set_system_name(driver.name); + + if (swinfo) + { + if (!swinfo->startempty) + { + if (part) + { + std::string const string_list(util::string_format("%s:%s:%s:%s", swinfo->listname, swinfo->shortname, *part, swinfo->instance)); + printf("%s\n", string_list.c_str()); + moptions.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE); + } + else + { + std::string const string_list(util::string_format("%s:%s", swinfo->listname, swinfo->shortname)); + printf("%s\n", string_list.c_str()); + moptions.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE); + } + + std::string const snap_list(util::string_format("%s%s%s", swinfo->listname, PATH_SEPARATOR, swinfo->shortname)); + moptions.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE); + } + reselect_last::set_software(driver, *swinfo); + } + else + { + reselect_last::set_driver(driver); + } + + if (bios) + moptions.set_value(OPTION_BIOS, *bios, OPTION_PRIORITY_CMDLINE); + + mame_machine_manager::instance()->schedule_new_driver(driver); + mui.machine().schedule_hard_reset(); + stack_reset(mui.machine()); +} + + //------------------------------------------------- // perform our special rendering //------------------------------------------------- @@ -517,6 +834,50 @@ void menu_select_launch::draw_info_arrow(int ub, float origx1, float origx2, flo 0.5f * (origx1 + origx2) + 0.5f * (ud_arrow_width * text_size), oy1 + 0.75f * (line_height * text_size), fgcolor, orientation); } +bool menu_select_launch::draw_error_text() +{ + if (m_ui_error) + ui().draw_text_box(container(), m_error_text.c_str(), ui::text_layout::CENTER, 0.5f, 0.5f, UI_RED_COLOR); + + return m_ui_error; +} + + +template bool menu_select_launch::select_bios(T const &driver, bool inlist) +{ + s_bios biosname; + if (ui().options().skip_bios_menu() || !has_multiple_bios(driver, biosname)) + return false; + + menu::stack_push(ui(), container(), std::move(biosname), driver, inlist); + return true; +} + +bool menu_select_launch::select_part(software_info const &info, ui_software_info const &ui_info) +{ + return select_part(ui(), container(), info, ui_info); +} + +bool menu_select_launch::select_part(mame_ui_manager &mui, render_container &container, software_info const &info, ui_software_info const &ui_info) +{ + if (mui.options().skip_parts_menu() || !info.has_multiple_parts(ui_info.interface.c_str())) + return false; + + s_parts parts; + for (software_part const &part : info.parts()) + { + if (part.matches_interface(ui_info.interface.c_str())) + { + std::string menu_part_name(part.name()); + if (part.feature("part_id")) + menu_part_name.assign("(").append(part.feature("part_id")).append(")"); + parts.emplace(part.name(), std::move(menu_part_name)); + } + } + menu::stack_push(mui, container, std::move(parts), ui_info); + return true; +} + //------------------------------------------------- // draw toolbar @@ -1860,12 +2221,55 @@ void menu_select_launch::draw_snapx(float origx1, float origy1, float origx2, fl } +//------------------------------------------------- +// get bios count +//------------------------------------------------- + +bool menu_select_launch::has_multiple_bios(ui_software_info const &swinfo, s_bios &biosname) +{ + return has_multiple_bios(*swinfo.driver, biosname); +} + +bool menu_select_launch::has_multiple_bios(game_driver const &driver, s_bios &biosname) +{ + if (!driver.rom) + return false; + + auto const entries = rom_build_entries(driver.rom); + + std::string default_name; + for (const rom_entry &rom : entries) + if (ROMENTRY_ISDEFAULT_BIOS(&rom)) + default_name = ROM_GETNAME(&rom); + + for (const rom_entry &rom : entries) + { + if (ROMENTRY_ISSYSTEM_BIOS(&rom)) + { + std::string name(ROM_GETHASHDATA(&rom)); + std::string bname(ROM_GETNAME(&rom)); + int bios_flags = ROM_GETBIOSFLAGS(&rom); + + if (bname == default_name) + { + name.append(_(" (default)")); + biosname.emplace(biosname.begin(), name, bios_flags - 1); + } + else + biosname.emplace_back(name, bios_flags - 1); + } + } + return biosname.size() > 1U; +} + + void menu_select_launch::exit(running_machine &machine) { std::lock_guard guard(s_cache_guard); s_caches.erase(&machine); } + //------------------------------------------------- // draw infos //------------------------------------------------- diff --git a/src/frontend/mame/ui/selmenu.h b/src/frontend/mame/ui/selmenu.h index 6bd63b4355c..6556f5afdc0 100644 --- a/src/frontend/mame/ui/selmenu.h +++ b/src/frontend/mame/ui/selmenu.h @@ -41,11 +41,38 @@ protected: rightbottom }; + class reselect_last + { + public: + static std::string const &driver() { return s_driver; } + static std::string const &software() { return s_software; } + static std::string const &swlist() { return s_swlist; } + + static void reselect(bool value) { s_reselect = value; } + static bool get() { return s_reselect; } + static void reset(); + + static void set_driver(std::string const &name); + static void set_driver(game_driver const &driver) { set_driver(driver.name); } + static void set_software(game_driver const &driver, ui_software_info const &swinfo); + + private: + static std::string s_driver, s_software, s_swlist; + static bool s_reselect; + }; + menu_select_launch(mame_ui_manager &mui, render_container &container, bool is_swlist); focused_menu get_focus() const { return m_focus; } void set_focus(focused_menu focus) { m_focus = focus; } + bool dismiss_error(); + void set_error(reset_options ropt, std::string &&message); + + void launch_system(game_driver const &driver) { launch_system(ui(), driver, nullptr, nullptr, nullptr); } + void launch_system(game_driver const &driver, ui_software_info const &swinfo) { launch_system(ui(), driver, &swinfo, nullptr, nullptr); } + void launch_system(game_driver const &driver, ui_software_info const &swinfo, std::string const &part) { launch_system(ui(), driver, &swinfo, &part, nullptr); } + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; // handlers @@ -55,16 +82,61 @@ protected: void draw_common_arrow(float origx1, float origy1, float origx2, float origy2, int current, int dmin, int dmax, float title); void draw_info_arrow(int ub, float origx1, float origx2, float oy1, float line_height, float text_size, float ud_arrow_width); + bool draw_error_text(); + + template bool select_bios(T const &driver, bool inlist); + bool select_part(software_info const &info, ui_software_info const &ui_info); + int visible_items; void *m_prev_selected; int m_total_lines; int m_topline_datsview; // right box top line - bool m_ui_error; private: using bitmap_vector = std::vector; using texture_ptr_vector = std::vector; + using s_parts = std::unordered_map; + using s_bios = std::vector>; + + class software_parts : public menu + { + public: + software_parts(mame_ui_manager &mui, render_container &container, s_parts &&parts, ui_software_info const &ui_info); + virtual ~software_parts() override; + + protected: + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; + + private: + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle() override; + + ui_software_info const &m_uiinfo; + s_parts const m_parts; + }; + + class bios_selection : public menu + { + public: + bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, game_driver const &driver, bool inlist); + bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, ui_software_info const &swinfo, bool inlist); + virtual ~bios_selection() override; + + protected: + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; + + private: + bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, void const *driver, bool software, bool inlist); + + virtual void populate(float &customtop, float &custombottom) override; + virtual void handle() override; + + void const *m_driver; + bool m_software, m_inlist; + s_bios m_bios; + }; + class cache { public: @@ -117,12 +189,6 @@ private: // draw left panel virtual float draw_left_panel(float x1, float y1, float x2, float y2) = 0; - game_driver const *m_info_driver; - ui_software_info const *m_info_software; - int m_info_view; - std::vector m_items_list; - std::string m_info_buffer; - // draw infos void infos_render(float x1, float y1, float x2, float y2); virtual void general_info(const game_driver *driver, std::string &buffer) = 0; @@ -178,9 +244,23 @@ private: virtual std::string make_driver_description(game_driver const &driver) const = 0; virtual std::string make_software_description(ui_software_info const &software) const = 0; + static void launch_system(mame_ui_manager &mui, game_driver const &driver, ui_software_info const *swinfo, std::string const *part, int const *bios); + static bool select_part(mame_ui_manager &mui, render_container &container, software_info const &info, ui_software_info const &ui_info); + static bool has_multiple_bios(ui_software_info const &swinfo, s_bios &biosname); + static bool has_multiple_bios(game_driver const &driver, s_bios &biosname); + // cleanup function static void exit(running_machine &machine); + bool m_ui_error; + std::string m_error_text; + + game_driver const *m_info_driver; + ui_software_info const *m_info_software; + int m_info_view; + std::vector m_items_list; + std::string m_info_buffer; + cache_ptr m_cache; bool m_is_swlist; focused_menu m_focus; diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index 9e71a42f2a6..94f87cdde32 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -29,10 +29,7 @@ namespace ui { -std::string reselect_last::driver; -std::string reselect_last::software; -std::string reselect_last::swlist; -bool reselect_last::m_reselect = false; + static const char *region_lists[] = { "arab", "arg", "asia", "aus", "aut", "bel", "blr", "bra", "can", "chi", "chn", "cze", "den", "ecu", "esp", "euro", "fin", "fra", "gbr", "ger", "gre", "hkg", "hun", "irl", "isr", "isv", "ita", "jpn", "kaz", "kor", "lat", "lux", "mex", "ned", "nld", "nor", "nzl", @@ -87,42 +84,6 @@ bool compare_software(ui_software_info a, ui_software_info b) } } -//------------------------------------------------- -// get bios count -//------------------------------------------------- - -bool has_multiple_bios(const game_driver *driver, s_bios &biosname) -{ - if (driver->rom == nullptr) - return false; - - auto entries = rom_build_entries(driver->rom); - - std::string default_name; - for (const rom_entry &rom : entries) - if (ROMENTRY_ISDEFAULT_BIOS(&rom)) - default_name = ROM_GETNAME(&rom); - - for (const rom_entry &rom : entries) - { - if (ROMENTRY_ISSYSTEM_BIOS(&rom)) - { - std::string name(ROM_GETHASHDATA(&rom)); - std::string bname(ROM_GETNAME(&rom)); - int bios_flags = ROM_GETBIOSFLAGS(&rom); - - if (bname == default_name) - { - name.append(_(" (default)")); - biosname.emplace(biosname.begin(), name, bios_flags - 1); - } - else - biosname.emplace_back(name, bios_flags - 1); - } - } - return (biosname.size() > 1); -} - //------------------------------------------------- // ctor //------------------------------------------------- @@ -130,8 +91,7 @@ bool has_multiple_bios(const game_driver *driver, s_bios &biosname) menu_select_software::menu_select_software(mame_ui_manager &mui, render_container &container, const game_driver *driver) : menu_select_launch(mui, container, true) { - if (reselect_last::get()) - reselect_last::set(false); + reselect_last::reselect(false); sw_filters::actual = 0; highlight = 0; @@ -175,11 +135,9 @@ void menu_select_software::handle() if (menu_event && menu_event->itemref) { - if (m_ui_error) + if (dismiss_error()) { // reset the error on any future event - m_ui_error = false; - machine().ui_input().reset(); } else if (menu_event->iptkey == IPT_UI_SELECT) { @@ -372,10 +330,7 @@ void menu_select_software::handle() } // if we're in an error state, overlay an error message - if (m_ui_error) - ui().draw_text_box(container(), _("The selected software is missing one or more required files. " - "Please select a different software.\n\nPress any key to continue."), - ui::text_layout::CENTER, 0.5f, 0.5f, UI_RED_COLOR); + draw_error_text(); // handle filters selection from key shortcuts if (check_filter) @@ -472,10 +427,10 @@ void menu_select_software::populate(float &customtop, float &custombottom) // iterate over entries for (size_t curitem = 0; curitem < m_displaylist.size(); ++curitem) { - if (reselect_last::software == "[Start empty]" && !reselect_last::driver.empty()) + if (reselect_last::software() == "[Start empty]" && !reselect_last::driver().empty()) old_software = 0; - else if (m_displaylist[curitem]->shortname == reselect_last::software && m_displaylist[curitem]->listname == reselect_last::swlist) + else if (m_displaylist[curitem]->shortname == reselect_last::software() && m_displaylist[curitem]->listname == reselect_last::swlist()) old_software = m_has_empty_start ? curitem + 1 : curitem; item_append(m_displaylist[curitem]->longname, m_displaylist[curitem]->devicetype, @@ -515,7 +470,7 @@ void menu_select_software::populate(float &customtop, float &custombottom) void menu_select_software::build_software_list() { // add start empty item - m_swinfo.emplace_back(m_driver->name, m_driver->type.fullname(), "", "", "", 0, "", m_driver, "", "", "", 1, "", "", "", true); + m_swinfo.emplace_back(*m_driver); machine_config config(*m_driver, machine().options()); @@ -531,50 +486,26 @@ void menu_select_software::build_software_list() { const char *instance_name = nullptr; const char *type_name = nullptr; - ui_software_info tmpmatches; for (device_image_interface &image : image_interface_iterator(config.root_device())) { - const char *interface = image.image_interface(); - if (interface != nullptr && part.matches_interface(interface)) + char const *const interface = image.image_interface(); + if (interface && part.matches_interface(interface)) { instance_name = image.instance_name().c_str(); - if (instance_name != nullptr) - tmpmatches.instance = image.instance_name(); - type_name = image.image_type_name(); - if (type_name != nullptr) - tmpmatches.devicetype = type_name; break; } } - - if (instance_name == nullptr || type_name == nullptr) + if (!instance_name || !type_name) continue; - tmpmatches.shortname = swinfo.shortname(); - tmpmatches.longname = swinfo.longname(); - tmpmatches.parentname = swinfo.parentname(); - tmpmatches.year = swinfo.year(); - tmpmatches.publisher = swinfo.publisher(); - tmpmatches.supported = swinfo.supported(); - tmpmatches.part = part.name(); - tmpmatches.driver = m_driver; - tmpmatches.listname = swlist.list_name(); - tmpmatches.interface = part.interface(); - tmpmatches.startempty = 0; - tmpmatches.parentlongname.clear(); - tmpmatches.usage.clear(); - tmpmatches.available = false; - - for (const feature_list_item &flist : swinfo.other_info()) - if (!strcmp(flist.name().c_str(), "usage")) - tmpmatches.usage = flist.value(); - - m_swinfo.push_back(tmpmatches); + ui_software_info tmpmatches(swinfo, part, *m_driver, swlist.list_name(), instance_name, type_name); + m_filter.region.set(tmpmatches.longname); m_filter.publisher.set(tmpmatches.publisher); m_filter.year.set(tmpmatches.year); m_filter.type.set(tmpmatches.devicetype); + m_swinfo.emplace_back(std::move(tmpmatches)); } } } @@ -658,27 +589,15 @@ void menu_select_software::build_software_list() void menu_select_software::inkey_select(const event *menu_event) { ui_software_info *ui_swinfo = (ui_software_info *)menu_event->itemref; - ui_options &mopt = ui().options(); if (ui_swinfo->startempty == 1) { - s_bios biosname; - if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname)) + if (!select_bios(*ui_swinfo->driver, true)) { - menu::stack_push(ui(), container(), biosname, (void *)ui_swinfo->driver, false, true); - } - else - { - reselect_last::driver = ui_swinfo->driver->name; - reselect_last::software = "[Start empty]"; - reselect_last::swlist.clear(); - reselect_last::set(true); - mame_machine_manager::instance()->schedule_new_driver(*ui_swinfo->driver); - machine().schedule_hard_reset(); - stack_reset(); + reselect_last::reselect(true); + launch_system(*ui_swinfo->driver, *ui_swinfo); } } - else { // first validate @@ -688,51 +607,28 @@ void menu_select_software::inkey_select(const event *menu_event) software_list_device *swlist = software_list_device::find_by_name(*drivlist.config(), ui_swinfo->listname.c_str()); const software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str()); - media_auditor::summary summary = auditor.audit_software(swlist->list_name(), swinfo, AUDIT_VALIDATE_FAST); + media_auditor::summary const summary = auditor.audit_software(swlist->list_name(), swinfo, AUDIT_VALIDATE_FAST); if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) { - s_bios biosname; - if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname)) + if (!select_bios(*ui_swinfo, false) && !select_part(*swinfo, *ui_swinfo)) { - menu::stack_push(ui(), container(), biosname, (void *)ui_swinfo, true, false); - return; + reselect_last::reselect(true); + launch_system(drivlist.driver(), *ui_swinfo); } - else if (!mopt.skip_parts_menu() && swinfo->has_multiple_parts(ui_swinfo->interface.c_str())) - { - s_parts parts; - for (const software_part &swpart : swinfo->parts()) - { - if (swpart.matches_interface(ui_swinfo->interface.c_str())) - { - std::string menu_part_name(swpart.name()); - if (swpart.feature("part_id") != nullptr) - menu_part_name.assign("(").append(swpart.feature("part_id")).append(")"); - parts.emplace(swpart.name(), menu_part_name); - } - } - menu::stack_push(ui(), container(), parts, ui_swinfo); - return; - } - - machine().options().set_system_name(m_driver->name); - machine().options().set_value(OPTION_SOFTWARENAME, ui_swinfo->shortname, OPTION_PRIORITY_CMDLINE); - std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname); - machine().options().set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE); - reselect_last::driver = drivlist.driver().name; - reselect_last::software = ui_swinfo->shortname; - reselect_last::swlist = ui_swinfo->listname; - reselect_last::set(true); - mame_machine_manager::instance()->schedule_new_driver(drivlist.driver()); - machine().schedule_hard_reset(); - stack_reset(); } - - // otherwise, display an error else { - reset(reset_options::REMEMBER_POSITION); - m_ui_error = true; + // otherwise, display an error + std::ostringstream str; + str << _("The selected software is missing one or more required files. Please select a different software.\n\n"); + if (media_auditor::NOTFOUND != summary) + { + auditor.summarize(nullptr, &str); + str << "\n"; + } + str << _("Press any key to continue."), + set_error(reset_options::REMEMBER_POSITION, str.str()); } } } @@ -1239,243 +1135,6 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float } } -//------------------------------------------------- -// ctor -//------------------------------------------------- - -software_parts::software_parts(mame_ui_manager &mui, render_container &container, s_parts parts, ui_software_info *ui_info) : menu(mui, container) -{ - m_parts = parts; - m_uiinfo = ui_info; -} - -//------------------------------------------------- -// dtor -//------------------------------------------------- - -software_parts::~software_parts() -{ -} - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void software_parts::populate(float &customtop, float &custombottom) -{ - for (auto & elem : m_parts) - item_append(elem.first, elem.second, 0, (void *)&elem); - - item_append(menu_item_type::SEPARATOR); - customtop = ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER); -} - -//------------------------------------------------- -// handle -//------------------------------------------------- - -void software_parts::handle() -{ - // process the menu - const event *menu_event = process(0); - if (menu_event && (menu_event->iptkey) == IPT_UI_SELECT && menu_event->itemref) - { - for (auto & elem : m_parts) - { - if ((void*)&elem == menu_event->itemref) - { - std::string string_list = std::string(m_uiinfo->listname).append(":").append(m_uiinfo->shortname).append(":").append(elem.first).append(":").append(m_uiinfo->instance); - machine().options().set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE); - - reselect_last::driver = m_uiinfo->driver->name; - reselect_last::software = m_uiinfo->shortname; - reselect_last::swlist = m_uiinfo->listname; - reselect_last::set(true); - - std::string snap_list = std::string(m_uiinfo->listname).append("/").append(m_uiinfo->shortname); - machine().options().set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE); - - mame_machine_manager::instance()->schedule_new_driver(*m_uiinfo->driver); - machine().schedule_hard_reset(); - stack_reset(); - } - } - } -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void software_parts::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - float width; - ui().draw_text_full(container(), _("Software part selection:"), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - float maxwidth = std::max(origx2 - origx1, width); - - // compute our bounds - float x1 = 0.5f - 0.5f * maxwidth; - float x2 = x1 + maxwidth; - float y1 = origy1 - top; - float y2 = origy1 - UI_BOX_TB_BORDER; - - // draw a box - ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); - - // take off the borders - x1 += UI_BOX_LR_BORDER; - x2 -= UI_BOX_LR_BORDER; - y1 += UI_BOX_TB_BORDER; - - // draw the text within it - ui().draw_text_full(container(), _("Software part selection:"), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); -} - -//------------------------------------------------- -// ctor -//------------------------------------------------- - -bios_selection::bios_selection(mame_ui_manager &mui, render_container &container, s_bios biosname, void *_driver, bool _software, bool _inlist) : menu(mui, container) -{ - m_bios = biosname; - m_driver = _driver; - m_software = _software; - m_inlist = _inlist; -} - -//------------------------------------------------- -// dtor -//------------------------------------------------- - -bios_selection::~bios_selection() -{ -} - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void bios_selection::populate(float &customtop, float &custombottom) -{ - for (auto & elem : m_bios) - item_append(elem.first, "", 0, (void *)&elem.first); - - item_append(menu_item_type::SEPARATOR); - customtop = ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER); -} - -//------------------------------------------------- -// handle -//------------------------------------------------- - -void bios_selection::handle() -{ - // process the menu - const event *menu_event = process(0); - emu_options &moptions = machine().options(); - if (menu_event && menu_event->iptkey == IPT_UI_SELECT && menu_event->itemref) - { - for (auto & elem : m_bios) - { - if ((void*)&elem.first == menu_event->itemref) - { - if (!m_software) - { - const game_driver *s_driver = (const game_driver *)m_driver; - reselect_last::driver = s_driver->name; - if (m_inlist) - reselect_last::software = "[Start empty]"; - else - { - reselect_last::software.clear(); - reselect_last::swlist.clear(); - reselect_last::set(true); - } - - moptions.set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE); - mame_machine_manager::instance()->schedule_new_driver(*s_driver); - machine().schedule_hard_reset(); - stack_reset(); - } - else - { - ui_software_info *ui_swinfo = (ui_software_info *)m_driver; - machine().options().set_value(OPTION_BIOS, elem.second, OPTION_PRIORITY_CMDLINE); - driver_enumerator drivlist(machine().options(), *ui_swinfo->driver); - drivlist.next(); - software_list_device *swlist = software_list_device::find_by_name(*drivlist.config(), ui_swinfo->listname.c_str()); - const software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str()); - if (!ui().options().skip_parts_menu() && swinfo->has_multiple_parts(ui_swinfo->interface.c_str())) - { - s_parts parts; - for (const software_part &swpart : swinfo->parts()) - { - if (swpart.matches_interface(ui_swinfo->interface.c_str())) - { - std::string menu_part_name(swpart.name()); - if (swpart.feature("part_id") != nullptr) - menu_part_name.assign("(").append(swpart.feature("part_id")).append(")"); - parts.emplace(swpart.name(), menu_part_name); - } - } - menu::stack_push(ui(), container(), parts, ui_swinfo); - return; - } - moptions.set_value(OPTION_SYSTEMNAME, drivlist.driver().name, OPTION_PRIORITY_CMDLINE); - moptions.set_value(OPTION_SOFTWARENAME, - ui_swinfo->listname + ":" + ui_swinfo->shortname, - OPTION_PRIORITY_CMDLINE); - moptions.set_value(OPTION_SNAPNAME, - ui_swinfo->listname + std::string(PATH_SEPARATOR) + ui_swinfo->shortname, - OPTION_PRIORITY_CMDLINE); - reselect_last::driver = drivlist.driver().name; - reselect_last::software = ui_swinfo->shortname; - reselect_last::swlist = ui_swinfo->listname; - reselect_last::set(true); - mame_machine_manager::instance()->schedule_new_driver(drivlist.driver()); - machine().schedule_hard_reset(); - stack_reset(); - } - } - } - } -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void bios_selection::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - float width; - ui().draw_text_full(container(), _("Bios selection:"), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - float maxwidth = std::max(origx2 - origx1, width); - - // compute our bounds - float x1 = 0.5f - 0.5f * maxwidth; - float x2 = x1 + maxwidth; - float y1 = origy1 - top; - float y2 = origy1 - UI_BOX_TB_BORDER; - - // draw a box - ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_GREEN_COLOR); - - // take off the borders - x1 += UI_BOX_LR_BORDER; - x2 -= UI_BOX_LR_BORDER; - y1 += UI_BOX_TB_BORDER; - - // draw the text within it - ui().draw_text_full(container(), _("Bios selection:"), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); -} - - //------------------------------------------------- // get selected software and/or driver //------------------------------------------------- diff --git a/src/frontend/mame/ui/selsoft.h b/src/frontend/mame/ui/selsoft.h index 3f014460791..68bce43f6c1 100644 --- a/src/frontend/mame/ui/selsoft.h +++ b/src/frontend/mame/ui/selsoft.h @@ -16,8 +16,6 @@ #include "ui/selmenu.h" namespace ui { -using s_bios = std::vector>; -using s_parts = std::unordered_map; // Menu Class class menu_select_software : public menu_select_launch @@ -31,6 +29,7 @@ protected: private: enum { VISIBLE_GAMES_IN_SEARCH = 200 }; + std::string m_search; const game_driver *m_driver; bool m_has_empty_start; @@ -68,55 +67,6 @@ private: virtual void general_info(const game_driver *driver, std::string &buffer) override {} }; -class software_parts : public menu -{ -public: - software_parts(mame_ui_manager &mui, render_container &container, s_parts parts, ui_software_info *ui_info); - virtual ~software_parts() override; - -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - -private: - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; - - ui_software_info *m_uiinfo; - s_parts m_parts; -}; - -class bios_selection : public menu -{ -public: - bios_selection(mame_ui_manager &mui, render_container &container, s_bios biosname, void *driver, bool software, bool inlist); - virtual ~bios_selection() override; - -protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - -private: - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; - - void *m_driver; - bool m_software, m_inlist; - s_bios m_bios; -}; - -struct reselect_last -{ - static std::string driver, software, swlist; - static void set(bool value) { m_reselect = value; } - static bool get() { return m_reselect; } - static void reset() { driver.clear(); software.clear(); swlist.clear(); set(false); } - -private: - static bool m_reselect; -}; - -// Getter -bool has_multiple_bios(const game_driver *driver, s_bios &biosname); - } // namespace ui #endif /* MAME_FRONTEND_UI_SELSOFT_H */ diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp index 937d0a0cc3f..7395b0b8a1c 100644 --- a/src/frontend/mame/ui/utils.cpp +++ b/src/frontend/mame/ui/utils.cpp @@ -11,6 +11,9 @@ #include "emu.h" #include "ui/utils.h" +#include "softlist.h" + + extern const char UI_VERSION_TAG[]; const char UI_VERSION_TAG[] = "# UI INFO "; @@ -195,3 +198,39 @@ void c_year::set(const char *str) ui.push_back(name); } + + +ui_software_info::ui_software_info( + software_info const &info, + software_part const &p, + game_driver const &d, + std::string const &li, + std::string const &is, + std::string const &de) + : shortname(info.shortname()), longname(info.longname()), parentname(info.parentname()) + , year(info.year()), publisher(info.publisher()) + , supported(info.supported()) + , part(p.name()) + , driver(&d) + , listname(li), interface(p.interface()), instance(is) + , startempty(0) + , parentlongname() + , usage() + , devicetype(de) + , available(false) +{ + for (feature_list_item const &feature : info.other_info()) + { + if (feature.name() == "usage") + { + usage = feature.value(); + break; + } + } +} + +// info for starting empty +ui_software_info::ui_software_info(game_driver const &d) + : shortname(d.name), longname(d.type.fullname()), driver(&d), startempty(1), available(true) +{ +} diff --git a/src/frontend/mame/ui/utils.h b/src/frontend/mame/ui/utils.h index 2ea74d6aa4a..b00f0c3a775 100644 --- a/src/frontend/mame/ui/utils.h +++ b/src/frontend/mame/ui/utils.h @@ -128,15 +128,35 @@ enum // GLOBAL STRUCTURES struct ui_software_info { - ui_software_info() {} - ui_software_info(std::string sname, std::string lname, std::string pname, std::string y, std::string pub, - uint8_t s, std::string pa, const game_driver *d, std::string li, std::string i, std::string is, uint8_t em, - std::string plong, std::string u, std::string de, bool av) + ui_software_info() { } + + // info for software list item + ui_software_info( + software_info const &info, + software_part const &p, + game_driver const &d, + std::string const &li, + std::string const &is, + std::string const &de); + + // info for starting empty + ui_software_info(game_driver const &d); + + // copyable/movable + ui_software_info(ui_software_info const &) = default; + ui_software_info(ui_software_info &&) = default; + ui_software_info &operator=(ui_software_info const &) = default; + ui_software_info &operator=(ui_software_info &&) = default; + + bool operator==(ui_software_info const &r) { - shortname = sname; longname = lname; parentname = pname; year = y; publisher = pub; - supported = s; part = pa; driver = d; listname = li; interface = i; instance = is; startempty = em; - parentlongname = plong; usage = u; devicetype = de; available = av; + return shortname == r.shortname && longname == r.longname && parentname == r.parentname + && year == r.year && publisher == r.publisher && supported == r.supported + && part == r.part && driver == r.driver && listname == r.listname + && interface == r.interface && instance == r.instance && startempty == r.startempty + && parentlongname == r.parentlongname && usage == r.usage && devicetype == r.devicetype; } + std::string shortname; std::string longname; std::string parentname; @@ -153,15 +173,6 @@ struct ui_software_info std::string usage; std::string devicetype; bool available = false; - - bool operator==(const ui_software_info& r) - { - return shortname == r.shortname && longname == r.longname && parentname == r.parentname - && year == r.year && publisher == r.publisher && supported == r.supported - && part == r.part && driver == r.driver && listname == r.listname - && interface == r.interface && instance == r.instance && startempty == r.startempty - && parentlongname == r.parentlongname && usage == r.usage && devicetype == r.devicetype; - } }; // Manufacturers -- cgit v1.2.3