summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui/selgame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/selgame.cpp')
-rw-r--r--src/frontend/mame/ui/selgame.cpp755
1 files changed, 265 insertions, 490 deletions
diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp
index def4ceaa5f9..0b47fa1d7d1 100644
--- a/src/frontend/mame/ui/selgame.cpp
+++ b/src/frontend/mame/ui/selgame.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Maurizio Petrarota, Vas Crabb
+// copyright-holders:Maurizio Petrarota
/*********************************************************************
ui/selgame.cpp
@@ -12,7 +12,6 @@
#include "ui/selgame.h"
#include "ui/auditmenu.h"
-#include "ui/icorender.h"
#include "ui/inifile.h"
#include "ui/miscmenu.h"
#include "ui/optsmenu.h"
@@ -32,190 +31,17 @@
#include "uiinput.h"
#include "luaengine.h"
-#include <atomic>
-#include <condition_variable>
#include <cstring>
#include <iterator>
-#include <memory>
-#include <mutex>
-#include <thread>
extern const char UI_VERSION_TAG[];
namespace ui {
-namespace {
-
-constexpr uint32_t FLAGS_UI = ui::menu::FLAG_LEFT_ARROW | ui::menu::FLAG_RIGHT_ARROW;
-
-} // anonymous namespace
-
-class menu_select_game::persistent_data
-{
-public:
- enum available : unsigned
- {
- AVAIL_NONE = 0U,
- AVAIL_SORTED_LIST = 1U << 0,
- AVAIL_BIOS_COUNT = 1U << 1,
- AVAIL_UCS_SHORTNAME = 1U << 2,
- AVAIL_UCS_DESCRIPTION = 1U << 3,
- AVAIL_UCS_MANUF_DESC = 1U << 4,
- AVAIL_FILTER_DATA = 1U << 5
- };
-
- ~persistent_data()
- {
- if (m_thread)
- m_thread->join();
- }
-
- void cache_data()
- {
- std::unique_lock<std::mutex> lock(m_mutex);
- do_start_caching();
- }
-
- bool is_available(available desired)
- {
- return (m_available.load(std::memory_order_acquire) & desired) == desired;
- }
-
- void wait_available(available desired)
- {
- if (!is_available(desired))
- {
- std::unique_lock<std::mutex> lock(m_mutex);
- do_start_caching();
- m_condition.wait(lock, [this, desired] () { return is_available(desired); });
- }
- }
-
- std::vector<ui_system_info> &sorted_list()
- {
- wait_available(AVAIL_SORTED_LIST);
- return m_sorted_list;
- }
-
- int bios_count()
- {
- wait_available(AVAIL_BIOS_COUNT);
- return m_bios_count;
- }
-
- bool unavailable_systems()
- {
- wait_available(AVAIL_SORTED_LIST);
- return std::find_if(m_sorted_list.begin(), m_sorted_list.end(), [] (ui_system_info const &info) { return !info.available; }) != m_sorted_list.end();
- }
-
- machine_filter_data &filter_data()
- {
- wait_available(AVAIL_FILTER_DATA);
- return m_filter_data;
- }
-
- static persistent_data &instance()
- {
- static persistent_data data;
- return data;
- }
-
-private:
- persistent_data()
- : m_started(false)
- , m_available(AVAIL_NONE)
- , m_bios_count(0)
- {
- }
-
- void notify_available(available value)
- {
- std::unique_lock<std::mutex> lock(m_mutex);
- m_available.fetch_or(value, std::memory_order_release);
- m_condition.notify_all();
- }
-
- void do_start_caching()
- {
- if (!m_started)
- {
- m_started = true;
- m_thread = std::make_unique<std::thread>([this] { do_cache_data(); });
- }
- }
-
- void do_cache_data()
- {
- // generate full list
- m_sorted_list.reserve(driver_list::total());
- std::unordered_set<std::string> manufacturers, years;
- for (int x = 0; x < driver_list::total(); ++x)
- {
- game_driver const &driver(driver_list::driver(x));
- if (&driver != &GAME_NAME(___empty))
- {
- if (driver.flags & machine_flags::IS_BIOS_ROOT)
- ++m_bios_count;
-
- m_sorted_list.emplace_back(driver, x, false);
- m_filter_data.add_manufacturer(driver.manufacturer);
- m_filter_data.add_year(driver.year);
- }
- }
-
- // notify that BIOS count is valie
- notify_available(AVAIL_BIOS_COUNT);
-
- // sort drivers and notify
- std::stable_sort(
- m_sorted_list.begin(),
- m_sorted_list.end(),
- [] (ui_system_info const &lhs, ui_system_info const &rhs) { return sorted_game_list(lhs.driver, rhs.driver); });
- notify_available(AVAIL_SORTED_LIST);
-
- // sort manufacturers and years
- m_filter_data.finalise();
- notify_available(AVAIL_FILTER_DATA);
-
- // convert shortnames to UCS-4
- for (ui_system_info &info : m_sorted_list)
- info.ucs_shortname = ustr_from_utf8(normalize_unicode(info.driver->name, unicode_normalization_form::D, true));
- notify_available(AVAIL_UCS_SHORTNAME);
-
- // convert descriptions to UCS-4
- for (ui_system_info &info : m_sorted_list)
- info.ucs_description = ustr_from_utf8(normalize_unicode(info.driver->type.fullname(), unicode_normalization_form::D, true));
- notify_available(AVAIL_UCS_DESCRIPTION);
-
- // convert "<manufacturer> <description>" to UCS-4
- std::string buf;
- for (ui_system_info &info : m_sorted_list)
- {
- buf.assign(info.driver->manufacturer);
- buf.append(1, ' ');
- buf.append(info.driver->type.fullname());
- info.ucs_manufacturer_description = ustr_from_utf8(normalize_unicode(buf, unicode_normalization_form::D, true));
- }
- notify_available(AVAIL_UCS_MANUF_DESC);
- }
-
- // synchronisation
- std::mutex m_mutex;
- std::condition_variable m_condition;
- std::unique_ptr<std::thread> m_thread;
- std::atomic<bool> m_started;
- std::atomic<unsigned> m_available;
-
- // data
- std::vector<ui_system_info> m_sorted_list;
- machine_filter_data m_filter_data;
- int m_bios_count;
-};
-
-bool menu_select_game::s_first_start = true;
-
+bool menu_select_game::first_start = true;
+std::vector<const game_driver *> menu_select_game::m_sortedlist;
+int menu_select_game::m_isabios = 0;
//-------------------------------------------------
// ctor
@@ -223,30 +49,33 @@ bool menu_select_game::s_first_start = true;
menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &container, const char *gamename)
: menu_select_launch(mui, container, false)
- , m_persistent_data(persistent_data::instance())
- , m_icons(MAX_ICONS_RENDER)
- , m_icon_paths()
- , m_displaylist()
- , m_searchlist()
- , m_searched_fields(persistent_data::AVAIL_NONE)
- , m_populated_favorites(false)
{
std::string error_string, last_filter, sub_filter;
ui_options &moptions = mui.options();
// load drivers cache
- m_persistent_data.cache_data();
+ init_sorted_list();
- // check if there are available system icons
- check_for_icons(nullptr);
+ // check if there are available icons
+ ui_globals::has_icons = false;
+ file_enumerator path(moptions.icons_directory());
+ const osd::directory::entry *dir;
+ while ((dir = path.next()) != nullptr)
+ {
+ std::string src(dir->name);
+ if (src.find(".ico") != std::string::npos || src.find("icons") != std::string::npos)
+ {
+ ui_globals::has_icons = true;
+ break;
+ }
+ }
// build drivers list
if (!load_available_machines())
build_available_list();
- if (s_first_start)
+ if (first_start)
{
- //s_first_start = false; TODO: why wansn't it ever clearing the first start flag?
reselect_last::set_driver(moptions.last_used_machine());
ui_globals::rpanel = std::min<int>(std::max<int>(moptions.last_right_panel(), RP_FIRST), RP_LAST);
@@ -267,23 +96,32 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &conta
emu_file file(ui().options().ui_path(), OPEN_FLAG_READ);
if (file.open_ram(fake_ini.c_str(), fake_ini.size()) == osd_file::error::NONE)
{
- m_persistent_data.filter_data().load_ini(file);
+ machine_filter::ptr flt(machine_filter::create(file));
+ if (flt)
+ {
+ main_filters::actual = flt->get_type();
+ main_filters::filters.emplace(main_filters::actual, std::move(flt));
+ }
file.close();
}
}
// do this after processing the last used filter setting so it overwrites the placeholder
load_custom_filters();
- m_filter_highlight = m_persistent_data.filter_data().get_current_filter_type();
+ m_filter_highlight = main_filters::actual;
if (!moptions.remember_last())
reselect_last::reset();
mui.machine().options().set_value(OPTION_SNAPNAME, "%g/%i", OPTION_PRIORITY_CMDLINE);
+ ui_globals::curimage_view = FIRST_VIEW;
ui_globals::curdats_view = 0;
+ ui_globals::switch_image = false;
+ ui_globals::default_image = true;
ui_globals::panels_status = moptions.hide_panels();
ui_globals::curdats_total = 1;
+ m_searchlist[0] = nullptr;
}
//-------------------------------------------------
@@ -302,7 +140,17 @@ menu_select_game::~menu_select_game()
if (driver)
last_driver = driver->name;
- std::string const filter(m_persistent_data.filter_data().get_config_string());
+ std::string filter;
+ auto const active_filter(main_filters::filters.find(main_filters::actual));
+ if (main_filters::filters.end() != active_filter)
+ {
+ char const *val(active_filter->second->filter_text());
+ filter = val ? util::string_format("%s,%s", active_filter->second->config_name(), val) : active_filter->second->config_name();
+ }
+ else
+ {
+ filter = machine_filter::config_name(main_filters::actual);
+ }
ui_options &mopt = ui().options();
mopt.set_value(OPTION_LAST_RIGHT_PANEL, ui_globals::rpanel, OPTION_PRIORITY_CMDLINE);
@@ -330,13 +178,13 @@ void menu_select_game::handle()
return;
}
- // if I have to select software, force software list submenu
+ // if i have to reselect a software, force software list submenu
if (reselect_last::get())
{
const game_driver *driver;
const ui_software_info *software;
get_selection(software, driver);
- menu::stack_push<menu_select_software>(ui(), container(), *driver);
+ menu::stack_push<menu_select_software>(ui(), container(), driver);
return;
}
@@ -393,7 +241,7 @@ void menu_select_game::handle()
case IPT_UI_SELECT:
if (get_focus() == focused_menu::MAIN)
{
- if (m_populated_favorites)
+ if (isfavorite())
inkey_select_favorite(menu_event);
else
inkey_select(menu_event);
@@ -402,12 +250,11 @@ void menu_select_game::handle()
case IPT_CUSTOM:
// handle IPT_CUSTOM (mouse right click)
- if (!m_populated_favorites)
+ if (!isfavorite())
{
menu::stack_push<menu_machine_configure>(
ui(), container(),
- *reinterpret_cast<const game_driver *>(m_prev_selected),
- nullptr,
+ reinterpret_cast<const game_driver *>(m_prev_selected),
menu_event->mouse.x0, menu_event->mouse.y0);
}
else
@@ -415,21 +262,18 @@ void menu_select_game::handle()
ui_software_info *sw = reinterpret_cast<ui_software_info *>(m_prev_selected);
menu::stack_push<menu_machine_configure>(
ui(), container(),
- *sw->driver,
- [this, empty = sw->startempty] (bool fav, bool changed)
- {
- if (changed)
- reset(empty ? reset_options::SELECT_FIRST : reset_options::REMEMBER_REF);
- },
+ (const game_driver *)sw->driver,
menu_event->mouse.x0, menu_event->mouse.y0);
}
break;
case IPT_UI_LEFT:
- if (ui_globals::rpanel == RP_IMAGES)
+ if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW)
{
// Images
- previous_image_view();
+ ui_globals::curimage_view--;
+ ui_globals::switch_image = true;
+ ui_globals::default_image = false;
}
else if (ui_globals::rpanel == RP_INFOS)
{
@@ -439,10 +283,12 @@ void menu_select_game::handle()
break;
case IPT_UI_RIGHT:
- if (ui_globals::rpanel == RP_IMAGES)
+ if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW)
{
// Images
- next_image_view();
+ ui_globals::curimage_view++;
+ ui_globals::switch_image = true;
+ ui_globals::default_image = false;
}
else if (ui_globals::rpanel == RP_INFOS)
{
@@ -455,17 +301,17 @@ void menu_select_game::handle()
if (uintptr_t(menu_event->itemref) > skip_main_items)
{
favorite_manager &mfav(mame_machine_manager::instance()->favorite());
- if (!m_populated_favorites)
+ if (!isfavorite())
{
game_driver const *const driver(reinterpret_cast<game_driver const *>(menu_event->itemref));
- if (!mfav.is_favorite_system(*driver))
+ if (!mfav.isgame_favorite(driver))
{
- mfav.add_favorite_system(*driver);
+ mfav.add_favorite_game(driver);
machine().popmessage(_("%s\n added to favorites list."), driver->type.fullname());
}
else
{
- mfav.remove_favorite_system(*driver);
+ mfav.remove_favorite_game();
machine().popmessage(_("%s\n removed from favorites list."), driver->type.fullname());
}
}
@@ -473,19 +319,19 @@ void menu_select_game::handle()
{
ui_software_info const *const swinfo(reinterpret_cast<ui_software_info const *>(menu_event->itemref));
machine().popmessage(_("%s\n removed from favorites list."), swinfo->longname);
- mfav.remove_favorite_software(*swinfo);
+ mfav.remove_favorite_game(*swinfo);
reset(reset_options::SELECT_FIRST);
}
}
break;
case IPT_UI_AUDIT_FAST:
- if (m_persistent_data.unavailable_systems())
- menu::stack_push<menu_audit>(ui(), container(), m_persistent_data.sorted_list(), menu_audit::mode::FAST);
+ if (std::find_if(m_availsortedlist.begin(), m_availsortedlist.end(), [] (ui_system_info const &info) { return !info.available; }) != m_availsortedlist.end())
+ menu::stack_push<menu_audit>(ui(), container(), m_availsortedlist, menu_audit::mode::FAST);
break;
case IPT_UI_AUDIT_ALL:
- menu::stack_push<menu_audit>(ui(), container(), m_persistent_data.sorted_list(), menu_audit::mode::ALL);
+ menu::stack_push<menu_audit>(ui(), container(), m_availsortedlist, menu_audit::mode::ALL);
break;
}
}
@@ -502,113 +348,98 @@ void menu_select_game::handle()
void menu_select_game::populate(float &customtop, float &custombottom)
{
- for (auto &icon : m_icons) // TODO: why is this here? maybe better on resize or setting change?
- icon.second.texture.reset();
-
- set_switch_image();
+ ui_globals::redraw_icon = true;
+ ui_globals::switch_image = true;
int old_item_selected = -1;
+ uint32_t flags_ui = FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
if (!isfavorite())
{
- m_populated_favorites = false;
- m_displaylist.clear();
- machine_filter const *const flt(m_persistent_data.filter_data().get_current_filter());
-
// if search is not empty, find approximate matches
if (!m_search.empty())
{
populate_search();
- if (flt)
- {
- for (auto it = m_searchlist.begin(); (m_searchlist.end() != it) && (MAX_VISIBLE_SEARCH > m_displaylist.size()); ++it)
- {
- if (flt->apply(it->second))
- m_displaylist.emplace_back(it->second);
- }
- }
- else
- {
- std::transform(
- m_searchlist.begin(),
- std::next(m_searchlist.begin(), (std::min)(m_searchlist.size(), MAX_VISIBLE_SEARCH)),
- std::back_inserter(m_displaylist),
- [] (auto const &entry) { return entry.second; });
- }
}
else
{
+ // reset search string
+ m_search.clear();
+ m_displaylist.clear();
+
// if filter is set on category, build category list
- std::vector<ui_system_info> const &sorted(m_persistent_data.sorted_list());
- if (!flt)
- std::copy(sorted.begin(), sorted.end(), std::back_inserter(m_displaylist));
+ auto const it(main_filters::filters.find(main_filters::actual));
+ if (main_filters::filters.end() == it)
+ m_displaylist = m_availsortedlist;
else
- flt->apply(sorted.begin(), sorted.end(), std::back_inserter(m_displaylist));
- }
+ it->second->apply(m_availsortedlist.begin(), m_availsortedlist.end(), std::back_inserter(m_displaylist));
- // iterate over entries
- int curitem = 0;
- for (ui_system_info const &elem : m_displaylist)
- {
- if (old_item_selected == -1 && elem.driver->name == reselect_last::driver())
- old_item_selected = curitem;
-
- bool cloneof = strcmp(elem.driver->parent, "0");
- if (cloneof)
+ // iterate over entries
+ int curitem = 0;
+ for (ui_system_info const &elem : m_displaylist)
{
- int cx = driver_list::find(elem.driver->parent);
- if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0))
- cloneof = false;
- }
+ if (old_item_selected == -1 && elem.driver->name == reselect_last::driver())
+ old_item_selected = curitem;
- item_append(elem.driver->type.fullname(), "", (cloneof) ? (FLAGS_UI | FLAG_INVERT) : FLAGS_UI, (void *)elem.driver);
- curitem++;
+ bool cloneof = strcmp(elem.driver->parent, "0");
+ if (cloneof)
+ {
+ int cx = driver_list::find(elem.driver->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+
+ item_append(elem.driver->type.fullname(), "", (cloneof) ? (flags_ui | FLAG_INVERT) : flags_ui, (void *)elem.driver);
+ curitem++;
+ }
}
}
else
{
// populate favorites list
- m_populated_favorites = true;
m_search.clear();
- mame_machine_manager::instance()->favorite().apply_sorted(
- [this, &old_item_selected, curitem = 0] (ui_software_info const &info) mutable
- {
- if (info.startempty == 1)
- {
- if (old_item_selected == -1 && info.shortname == reselect_last::driver())
- old_item_selected = curitem;
+ int curitem = 0;
- bool cloneof = strcmp(info.driver->parent, "0");
- if (cloneof)
- {
- int cx = driver_list::find(info.driver->parent);
- if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0))
- cloneof = false;
- }
+ // iterate over entries
+ for (auto & favmap : mame_machine_manager::instance()->favorite().m_list)
+ {
+ auto flags = flags_ui | FLAG_UI_FAVORITE;
+ if (favmap.second.startempty == 1)
+ {
+ if (old_item_selected == -1 && favmap.second.shortname == reselect_last::driver())
+ old_item_selected = curitem;
- item_append(info.longname, "", cloneof ? (FLAGS_UI | FLAG_INVERT) : FLAGS_UI, (void *)&info);
- }
- else
- {
- if (old_item_selected == -1 && info.shortname == reselect_last::driver())
- old_item_selected = curitem;
- item_append(info.longname, info.devicetype,
- info.parentname.empty() ? FLAGS_UI : (FLAG_INVERT | FLAGS_UI), (void *)&info);
- }
- curitem++;
- });
+ bool cloneof = strcmp(favmap.second.driver->parent, "0");
+ if (cloneof)
+ {
+ int cx = driver_list::find(favmap.second.driver->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0))
+ cloneof = false;
+ }
+
+ item_append(favmap.second.longname, "", (cloneof) ? (flags | FLAG_INVERT) : flags, (void *)&favmap.second);
+ }
+ else
+ {
+ 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);
+ }
+ curitem++;
+ }
}
- item_append(menu_item_type::SEPARATOR, FLAGS_UI);
+ item_append(menu_item_type::SEPARATOR, flags_ui);
// add special items
if (stack_has_special_main_menu())
{
- item_append(_("Configure Options"), "", FLAGS_UI, (void *)(uintptr_t)CONF_OPTS);
- item_append(_("Configure Machine"), "", FLAGS_UI, (void *)(uintptr_t)CONF_MACHINE);
+ item_append(_("Configure Options"), "", flags_ui, (void *)(uintptr_t)CONF_OPTS);
+ item_append(_("Configure Machine"), "", flags_ui, (void *)(uintptr_t)CONF_MACHINE);
skip_main_items = 2;
if (machine().options().plugins())
{
- item_append(_("Plugins"), "", FLAGS_UI, (void *)(uintptr_t)CONF_PLUGINS);
+ item_append(_("Plugins"), "", flags_ui, (void *)(uintptr_t)CONF_PLUGINS);
skip_main_items++;
}
}
@@ -656,11 +487,11 @@ void menu_select_game::build_available_list()
// build a name for it
for (src = dir->name; *src != 0 && *src != '.' && dst < &drivername[ARRAY_LENGTH(drivername) - 1]; ++src)
- *dst++ = tolower(uint8_t(*src));
+ *dst++ = tolower((uint8_t) * src);
*dst = 0;
- int const drivnum = driver_list::find(drivername);
- if (0 <= drivnum)
+ int drivnum = driver_list::find(drivername);
+ if (drivnum != -1 && !included[drivnum])
included[drivnum] = true;
}
@@ -731,9 +562,18 @@ void menu_select_game::build_available_list()
}
}
- // copy into the persistent sorted list
- for (ui_system_info &info : m_persistent_data.sorted_list())
- info.available = included[info.index];
+ // sort
+ m_availsortedlist.reserve(total);
+ for (std::size_t x = 0; total > x; ++x)
+ {
+ game_driver const &driver(driver_list::driver(x));
+ if (&driver != &GAME_NAME(___empty))
+ m_availsortedlist.emplace_back(driver, included[x]);
+ }
+ std::stable_sort(
+ m_availsortedlist.begin(),
+ m_availsortedlist.end(),
+ [] (ui_system_info const &a, ui_system_info const &b) { return sorted_game_list(a.driver, b.driver); });
}
@@ -769,17 +609,13 @@ void menu_select_game::inkey_select(const event *menu_event)
if ((uintptr_t)driver == CONF_OPTS)
{
// special case for configure options
- menu::stack_push<menu_game_options>(
- ui(),
- container(),
- m_persistent_data.filter_data(),
- [this] () { reset(reset_options::SELECT_FIRST); });
+ menu::stack_push<menu_game_options>(ui(), container());
}
else if (uintptr_t(driver) == CONF_MACHINE)
{
// special case for configure machine
if (m_prev_selected)
- menu::stack_push<menu_machine_configure>(ui(), container(), *reinterpret_cast<const game_driver *>(m_prev_selected));
+ menu::stack_push<menu_machine_configure>(ui(), container(), reinterpret_cast<const game_driver *>(m_prev_selected));
return;
}
else if ((uintptr_t)driver == CONF_PLUGINS)
@@ -804,7 +640,7 @@ void menu_select_game::inkey_select(const event *menu_event)
{
if (!swlistdev.get_info().empty())
{
- menu::stack_push<menu_select_software>(ui(), container(), *driver);
+ menu::stack_push<menu_select_software>(ui(), container(), driver);
return;
}
}
@@ -831,11 +667,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
if ((uintptr_t)ui_swinfo == CONF_OPTS)
{
// special case for configure options
- menu::stack_push<menu_game_options>(
- ui(),
- container(),
- m_persistent_data.filter_data(),
- [this] () { reset(reset_options::SELECT_FIRST); });
+ menu::stack_push<menu_game_options>(ui(), container());
}
else if ((uintptr_t)ui_swinfo == CONF_MACHINE)
{
@@ -843,15 +675,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
if (m_prev_selected)
{
ui_software_info *swinfo = reinterpret_cast<ui_software_info *>(m_prev_selected);
- menu::stack_push<menu_machine_configure>(
- ui(),
- container(),
- *swinfo->driver,
- [this, empty = swinfo->startempty] (bool fav, bool changed)
- {
- if (changed)
- reset(empty ? reset_options::SELECT_FIRST : reset_options::REMEMBER_REF);
- });
+ menu::stack_push<menu_machine_configure>(ui(), container(), (const game_driver *)swinfo->driver);
}
return;
}
@@ -874,7 +698,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
{
if (!swlistdev.get_info().empty())
{
- menu::stack_push<menu_select_software>(ui(), container(), *ui_swinfo->driver);
+ menu::stack_push<menu_select_software>(ui(), container(), ui_swinfo->driver);
return;
}
}
@@ -922,7 +746,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
bool menu_select_game::isfavorite() const
{
- return machine_filter::FAVORITE == m_persistent_data.filter_data().get_current_filter_type();
+ return machine_filter::FAVORITE == main_filters::actual;
}
@@ -947,7 +771,7 @@ void menu_select_game::change_info_pane(int delta)
game_driver const *drv;
ui_software_info const *soft;
get_selection(soft, drv);
- if (!m_populated_favorites)
+ if (!isfavorite())
{
if (uintptr_t(drv) > skip_main_items)
cap_delta(ui_globals::curdats_view, ui_globals::curdats_total);
@@ -967,59 +791,49 @@ void menu_select_game::change_info_pane(int delta)
void menu_select_game::populate_search()
{
- // ensure search list is populated
- if (m_searchlist.empty())
+ // allocate memory to track the penalty value
+ std::vector<int> penalty(VISIBLE_GAMES_IN_SEARCH, 9999);
+ int index = 0;
+ for (; index < m_displaylist.size(); ++index)
{
- std::vector<ui_system_info> const &sorted(m_persistent_data.sorted_list());
- m_searchlist.reserve(sorted.size());
- for (ui_system_info const &info : sorted)
- m_searchlist.emplace_back(1.0, std::ref(info));
- }
-
- // keep track of what we matched against
- const std::u32string ucs_search(ustr_from_utf8(normalize_unicode(m_search, unicode_normalization_form::D, true)));
-
- // match shortnames
- if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_SHORTNAME))
- {
- m_searched_fields |= persistent_data::AVAIL_UCS_SHORTNAME;
- for (std::pair<double, std::reference_wrapper<ui_system_info const> > &info : m_searchlist)
- info.first = util::edit_distance(ucs_search, info.second.get().ucs_shortname);
- }
+ // pick the best match between driver name and description
+ int curpenalty = fuzzy_substring(m_search, m_displaylist[index].driver->type.fullname());
+ int tmp = fuzzy_substring(m_search, m_displaylist[index].driver->name);
+ curpenalty = std::min(curpenalty, tmp);
- // match descriptions
- if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_DESCRIPTION))
- {
- m_searched_fields |= persistent_data::AVAIL_UCS_DESCRIPTION;
- for (std::pair<double, std::reference_wrapper<ui_system_info const> > &info : m_searchlist)
+ // insert into the sorted table of matches
+ for (int matchnum = VISIBLE_GAMES_IN_SEARCH - 1; matchnum >= 0; --matchnum)
{
- if (info.first)
+ // stop if we're worse than the current entry
+ if (curpenalty >= penalty[matchnum])
+ break;
+
+ // as long as this isn't the last entry, bump this one down
+ if (matchnum < VISIBLE_GAMES_IN_SEARCH - 1)
{
- double const penalty(util::edit_distance(ucs_search, info.second.get().ucs_description));
- info.first = (std::min)(penalty, info.first);
+ penalty[matchnum + 1] = penalty[matchnum];
+ m_searchlist[matchnum + 1] = m_searchlist[matchnum];
}
+
+ m_searchlist[matchnum] = m_displaylist[index].driver;
+ penalty[matchnum] = curpenalty;
}
}
- // match "<manufacturer> <description>"
- if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_MANUF_DESC))
+ (index < VISIBLE_GAMES_IN_SEARCH) ? m_searchlist[index] = nullptr : m_searchlist[VISIBLE_GAMES_IN_SEARCH] = nullptr;
+ uint32_t flags_ui = FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW;
+ for (int curitem = 0; m_searchlist[curitem]; ++curitem)
{
- m_searched_fields |= persistent_data::AVAIL_UCS_MANUF_DESC;
- for (std::pair<double, std::reference_wrapper<ui_system_info const> > &info : m_searchlist)
+ bool cloneof = strcmp(m_searchlist[curitem]->parent, "0");
+ if (cloneof)
{
- if (info.first)
- {
- double const penalty(util::edit_distance(ucs_search, info.second.get().ucs_manufacturer_description));
- info.first = (std::min)(penalty, info.first);
- }
+ int cx = driver_list::find(m_searchlist[curitem]->parent);
+ if (cx != -1 && ((driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT) != 0))
+ cloneof = false;
}
+ item_append(m_searchlist[curitem]->type.fullname(), "", (!cloneof) ? flags_ui : (FLAG_INVERT | flags_ui),
+ (void *)m_searchlist[curitem]);
}
-
- // sort according to edit distance
- std::stable_sort(
- m_searchlist.begin(),
- m_searchlist.end(),
- [] (auto const &lhs, auto const &rhs) { return lhs.first < rhs.first; });
}
//-------------------------------------------------
@@ -1075,21 +889,6 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff
else
str << _("Sound\tOK\n");
- if (flags.unemulated_features() & device_t::feature::CAPTURE)
- str << _("Capture\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::CAPTURE)
- str << _("Capture\tImperfect\n");
-
- if (flags.unemulated_features() & device_t::feature::CAMERA)
- str << _("Camera\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::CAMERA)
- str << _("Camera\tImperfect\n");
-
- if (flags.unemulated_features() & device_t::feature::MICROPHONE)
- str << _("Microphone\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::MICROPHONE)
- str << _("Microphone\tImperfect\n");
-
if (flags.unemulated_features() & device_t::feature::CONTROLS)
str << _("Controls\tUnimplemented\n");
else if (flags.imperfect_features() & device_t::feature::CONTROLS)
@@ -1105,10 +904,15 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff
else if (flags.imperfect_features() & device_t::feature::MOUSE)
str << _("Mouse\tImperfect\n");
- if (flags.unemulated_features() & device_t::feature::MEDIA)
- str << _("Media\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::MEDIA)
- str << _("Media\tImperfect\n");
+ if (flags.unemulated_features() & device_t::feature::MICROPHONE)
+ str << _("Microphone\tUnimplemented\n");
+ else if (flags.imperfect_features() & device_t::feature::MICROPHONE)
+ str << _("Microphone\tImperfect\n");
+
+ if (flags.unemulated_features() & device_t::feature::CAMERA)
+ str << _("Camera\tUnimplemented\n");
+ else if (flags.imperfect_features() & device_t::feature::CAMERA)
+ str << _("Camera\tImperfect\n");
if (flags.unemulated_features() & device_t::feature::DISK)
str << _("Disk\tUnimplemented\n");
@@ -1120,31 +924,6 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff
else if (flags.imperfect_features() & device_t::feature::PRINTER)
str << _("Printer\tImperfect\n");
- if (flags.unemulated_features() & device_t::feature::TAPE)
- str << _("Mag. Tape\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::TAPE)
- str << _("Mag. Tape\tImperfect\n");
-
- if (flags.unemulated_features() & device_t::feature::PUNCH)
- str << _("Punch Tape\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::PUNCH)
- str << _("Punch Tape\tImperfect\n");
-
- if (flags.unemulated_features() & device_t::feature::DRUM)
- str << _("Mag. Drum\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::DRUM)
- str << _("Mag. Drum\tImperfect\n");
-
- if (flags.unemulated_features() & device_t::feature::ROM)
- str << _("(EP)ROM\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::ROM)
- str << _("(EP)ROM\tImperfect\n");
-
- if (flags.unemulated_features() & device_t::feature::COMMS)
- str << _("Communications\tUnimplemented\n");
- else if (flags.imperfect_features() & device_t::feature::COMMS)
- str << _("Communications\tImperfect\n");
-
if (flags.unemulated_features() & device_t::feature::LAN)
str << _("LAN\tUnimplemented\n");
else if (flags.imperfect_features() & device_t::feature::LAN)
@@ -1208,86 +987,71 @@ void menu_select_game::general_info(const game_driver *driver, std::string &buff
buffer = str.str();
}
-
-//-------------------------------------------------
-// get (possibly cached) icon texture
-//-------------------------------------------------
-
-render_texture *menu_select_game::get_icon_texture(int linenum, void *selectedref)
+void menu_select_game::inkey_export()
{
- game_driver const *const driver(m_populated_favorites
- ? reinterpret_cast<ui_software_info const *>(selectedref)->driver
- : reinterpret_cast<game_driver const *>(selectedref));
- assert(driver);
-
- icon_cache::iterator icon(m_icons.find(driver));
- if ((m_icons.end() == icon) || !icon->second.texture)
+ std::vector<game_driver const *> list;
+ if (!m_search.empty())
{
- if (m_icon_paths.empty())
- m_icon_paths = make_icon_paths(nullptr);
-
- // allocate an entry or allocate a texture on forced redraw
- if (m_icons.end() == icon)
+ for (int curitem = 0; m_searchlist[curitem]; ++curitem)
+ list.push_back(m_searchlist[curitem]);
+ }
+ else
+ {
+ if (isfavorite())
{
- icon = m_icons.emplace(driver, texture_ptr(machine().render().texture_alloc(), machine().render())).first;
+ // iterate over favorites
+ for (auto & favmap : mame_machine_manager::instance()->favorite().m_list)
+ {
+ if (favmap.second.startempty == 1)
+ list.push_back(favmap.second.driver);
+ else
+ return;
+ }
}
else
{
- assert(!icon->second.texture);
- icon->second.texture.reset(machine().render().texture_alloc());
+ list.reserve(m_displaylist.size());
+ for (ui_system_info const &info : m_displaylist)
+ list.emplace_back(info.driver);
}
-
- // set clone status
- bool cloneof = strcmp(driver->parent, "0");
- if (cloneof)
- {
- auto cx = driver_list::find(driver->parent);
- if ((cx >= 0) && (driver_list::driver(cx).flags & machine_flags::IS_BIOS_ROOT))
- cloneof = false;
- }
-
- bitmap_argb32 tmp;
- emu_file snapfile(std::string(m_icon_paths), OPEN_FLAG_READ);
- if (snapfile.open(std::string(driver->name), ".ico") == osd_file::error::NONE)
- {
- render_load_ico_highest_detail(snapfile, tmp);
- snapfile.close();
- }
- if (!tmp.valid() && cloneof && (snapfile.open(std::string(driver->parent), ".ico") == osd_file::error::NONE))
- {
- render_load_ico_highest_detail(snapfile, tmp);
- snapfile.close();
- }
-
- scale_icon(std::move(tmp), icon->second);
}
- return icon->second.bitmap.valid() ? icon->second.texture.get() : nullptr;
+ menu::stack_push<menu_export>(ui(), container(), std::move(list));
}
+//-------------------------------------------------
+// save drivers infos to file
+//-------------------------------------------------
-void menu_select_game::inkey_export()
+void menu_select_game::init_sorted_list()
{
- std::vector<game_driver const *> list;
- if (m_populated_favorites)
- {
- // iterate over favorites
- mame_machine_manager::instance()->favorite().apply(
- [&list] (ui_software_info const &info)
- {
- assert(info.driver);
- if (info.startempty)
- list.push_back(info.driver);
- });
- }
- else
+ if (!m_sortedlist.empty())
+ return;
+
+ // generate full list
+ std::unordered_set<std::string> manufacturers, years;
+ for (int x = 0; x < driver_list::total(); ++x)
{
- list.reserve(m_displaylist.size());
- for (ui_system_info const &info : m_displaylist)
- list.emplace_back(info.driver);
+ game_driver const &driver(driver_list::driver(x));
+ if (&driver != &GAME_NAME(___empty))
+ {
+ if (driver.flags & machine_flags::IS_BIOS_ROOT)
+ m_isabios++;
+
+ m_sortedlist.push_back(&driver);
+ manufacturers.emplace(c_mnfct::getname(driver.manufacturer));
+ years.emplace(driver.year);
+ }
}
- menu::stack_push<menu_export>(ui(), container(), std::move(list));
+ // sort manufacturers - years and driver
+ for (auto it = manufacturers.begin(); manufacturers.end() != it; it = manufacturers.erase(it))
+ c_mnfct::ui.emplace_back(*it);
+ std::sort(c_mnfct::ui.begin(), c_mnfct::ui.end(), [] (std::string const &x, std::string const &y) { return 0 > core_stricmp(x.c_str(), y.c_str()); });
+ for (auto it = years.begin(); years.end() != it; it = years.erase(it))
+ c_year::ui.emplace_back(*it);
+ std::stable_sort(c_year::ui.begin(), c_year::ui.end());
+ std::stable_sort(m_sortedlist.begin(), m_sortedlist.end(), sorted_game_list);
}
//-------------------------------------------------
@@ -1329,18 +1093,27 @@ bool menu_select_game::load_available_machines()
else
available.emplace(std::move(readbuf));
}
- file.close();
// turn it into the sorted system list we all love
- for (ui_system_info &info : m_persistent_data.sorted_list())
+ m_availsortedlist.reserve(driver_list::total());
+ for (std::size_t x = 0; driver_list::total() > x; ++x)
{
- std::unordered_set<std::string>::iterator const it(available.find(&info.driver->name[0]));
- bool const found(available.end() != it);
- info.available = found;
- if (found)
- available.erase(it);
+ game_driver const &driver(driver_list::driver(x));
+ if (&driver != &GAME_NAME(___empty))
+ {
+ std::unordered_set<std::string>::iterator const it(available.find(&driver.name[0]));
+ bool const found(available.end() != it);
+ m_availsortedlist.emplace_back(driver, found);
+ if (found)
+ available.erase(it);
+ }
}
+ std::stable_sort(
+ m_availsortedlist.begin(),
+ m_availsortedlist.end(),
+ [] (ui_system_info const &a, ui_system_info const &b) { return sorted_game_list(a.driver, b.driver); });
+ file.close();
return true;
}
@@ -1353,9 +1126,9 @@ void menu_select_game::load_custom_filters()
emu_file file(ui().options().ui_path(), OPEN_FLAG_READ);
if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
{
- machine_filter::ptr flt(machine_filter::create(file, m_persistent_data.filter_data()));
+ machine_filter::ptr flt(machine_filter::create(file));
if (flt)
- m_persistent_data.filter_data().set_filter(std::move(flt)); // not emplace/insert - could replace bogus filter from ui.ini line
+ main_filters::filters[flt->get_type()] = std::move(flt); // not emplace/insert - could replace bogus filter from ui.ini line
file.close();
}
@@ -1368,8 +1141,7 @@ void menu_select_game::load_custom_filters()
float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
{
- machine_filter_data &filter_data(m_persistent_data.filter_data());
- return menu_select_launch::draw_left_panel<machine_filter>(filter_data.get_current_filter_type(), filter_data.get_filters(), x1, y1, x2, y2);
+ return menu_select_launch::draw_left_panel<machine_filter>(main_filters::actual, main_filters::filters, x1, y1, x2, y2);
}
@@ -1379,7 +1151,7 @@ float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
void menu_select_game::get_selection(ui_software_info const *&software, game_driver const *&driver) const
{
- if (m_populated_favorites)
+ if (item[0].flags & FLAG_UI_FAVORITE) // TODO: work out why this doesn't use isfavorite()
{
software = reinterpret_cast<ui_software_info const *>(get_selection_ptr());
driver = software ? software->driver : nullptr;
@@ -1398,18 +1170,18 @@ void menu_select_game::make_topbox_text(std::string &line0, std::string &line1,
bare_build_version,
visible_items,
(driver_list::total() - 1),
- m_persistent_data.bios_count());
+ m_isabios);
- if (m_populated_favorites)
+ if (isfavorite())
{
line1.clear();
}
else
{
- machine_filter const *const it(m_persistent_data.filter_data().get_current_filter());
- char const *const filter(it ? it->filter_text() : nullptr);
+ auto const it(main_filters::filters.find(main_filters::actual));
+ char const *const filter((main_filters::filters.end() != it) ? it->second->filter_text() : nullptr);
if (filter)
- line1 = string_format(_("%1$s: %2$s - Search: %3$s_"), it->display_name(), filter, m_search);
+ line1 = string_format(_("%1$s: %2$s - Search: %3$s_"), it->second->display_name(), filter, m_search);
else
line1 = string_format(_("Search: %1$s_"), m_search);
}
@@ -1436,12 +1208,15 @@ void menu_select_game::filter_selected()
{
if ((machine_filter::FIRST <= m_filter_highlight) && (machine_filter::LAST >= m_filter_highlight))
{
- m_persistent_data.filter_data().get_filter(machine_filter::type(m_filter_highlight)).show_ui(
+ m_search.clear();
+ auto it(main_filters::filters.find(machine_filter::type(m_filter_highlight)));
+ if (main_filters::filters.end() == it)
+ it = main_filters::filters.emplace(machine_filter::type(m_filter_highlight), machine_filter::create(machine_filter::type(m_filter_highlight))).first;
+ it->second->show_ui(
ui(),
container(),
[this] (machine_filter &filter)
{
- set_switch_image();
machine_filter::type const new_type(filter.get_type());
if (machine_filter::CUSTOM == new_type)
{
@@ -1452,7 +1227,7 @@ void menu_select_game::filter_selected()
file.close();
}
}
- m_persistent_data.filter_data().set_current_filter_type(new_type);
+ main_filters::actual = new_type;
reset(reset_options::SELECT_FIRST);
});
}