summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui/selmenu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/selmenu.cpp')
-rw-r--r--src/frontend/mame/ui/selmenu.cpp406
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
//-------------------------------------------------