diff options
Diffstat (limited to 'src/frontend/mame/ui/selmenu.cpp')
-rw-r--r-- | src/frontend/mame/ui/selmenu.cpp | 406 |
1 files changed, 405 insertions, 1 deletions
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<char const *, char const *> 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<void const *>(&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<void const *>(&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<bitmap_argb32>(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 <typename T> 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<bios_selection>(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<software_parts>(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<std::mutex> guard(s_cache_guard); s_caches.erase(&machine); } + //------------------------------------------------- // draw infos //------------------------------------------------- |