mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
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.
This commit is contained in:
parent
d3568b23eb
commit
0aad5cb057
@ -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 << " - ";
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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<menu_game_options>(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<menu_machine_configure>(ui(), container(), reinterpret_cast<const game_driver *>(m_prev_selected));
|
||||
return;
|
||||
}
|
||||
|
||||
// special case for configure plugins
|
||||
else if ((uintptr_t)driver == CONF_PLUGINS)
|
||||
{
|
||||
// special case for configure plugins
|
||||
menu::stack_push<menu_plugins_configure>(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<bios_selection>(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<bios_selection>(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<bios_selection>(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<software_parts>(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
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
//-------------------------------------------------
|
||||
|
@ -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 <typename T> 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<bitmap_argb32>;
|
||||
using texture_ptr_vector = std::vector<texture_ptr>;
|
||||
|
||||
using s_parts = std::unordered_map<std::string, std::string>;
|
||||
using s_bios = std::vector<std::pair<std::string, int>>;
|
||||
|
||||
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<std::string> 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<std::string> m_items_list;
|
||||
std::string m_info_buffer;
|
||||
|
||||
cache_ptr m_cache;
|
||||
bool m_is_swlist;
|
||||
focused_menu m_focus;
|
||||
|
@ -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;
|
||||
ui_software_info tmpmatches(swinfo, part, *m_driver, swlist.list_name(), instance_name, type_name);
|
||||
|
||||
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);
|
||||
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<bios_selection>(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<bios_selection>(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<software_parts>(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<software_parts>(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
|
||||
//-------------------------------------------------
|
||||
|
@ -16,8 +16,6 @@
|
||||
#include "ui/selmenu.h"
|
||||
|
||||
namespace ui {
|
||||
using s_bios = std::vector<std::pair<std::string, int>>;
|
||||
using s_parts = std::unordered_map<std::string, std::string>;
|
||||
|
||||
// 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 */
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user