diff options
Diffstat (limited to 'src/frontend/mame/ui/auditmenu.cpp')
-rw-r--r-- | src/frontend/mame/ui/auditmenu.cpp | 254 |
1 files changed, 148 insertions, 106 deletions
diff --git a/src/frontend/mame/ui/auditmenu.cpp b/src/frontend/mame/ui/auditmenu.cpp index 23c0eee30ba..0349e1c2949 100644 --- a/src/frontend/mame/ui/auditmenu.cpp +++ b/src/frontend/mame/ui/auditmenu.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Maurizio Petrarota +// copyright-holders:Maurizio Petrarota, Vas Crabb /********************************************************************* ui/auditmenu.cpp @@ -9,39 +9,31 @@ *********************************************************************/ #include "emu.h" +#include "ui/auditmenu.h" + #include "ui/ui.h" -#include "ui/menu.h" + #include "audit.h" -#include "ui/auditmenu.h" #include "drivenum.h" +#include <numeric> + + extern const char UI_VERSION_TAG[]; namespace ui { -//------------------------------------------------- -// sort -//------------------------------------------------- -inline int cs_stricmp(const char *s1, const char *s2) -{ - for (;;) - { - int c1 = tolower(*s1++); - int c2 = tolower(*s2++); - if (c1 == 0 || c1 != c2) - return c1 - c2; - } -} +namespace { -bool sorted_game_list(const game_driver *x, const game_driver *y) -{ - bool clonex = (x->parent[0] != '0'); - bool cloney = (y->parent[0] != '0'); +void *const ITEMREF_START = reinterpret_cast<void *>(std::uintptr_t(1)); + +} // anonymous namespace - if (!clonex && !cloney) - return (cs_stricmp(x->type.fullname(), y->type.fullname()) < 0); - int cx = -1, cy = -1; +bool sorted_game_list(const game_driver *x, const game_driver *y) +{ + bool clonex = (x->parent[0] != '0') || x->parent[1]; + int cx = -1; if (clonex) { cx = driver_list::find(x->parent); @@ -49,6 +41,8 @@ bool sorted_game_list(const game_driver *x, const game_driver *y) clonex = false; } + bool cloney = (y->parent[0] != '0') || y->parent[1]; + int cy = -1; if (cloney) { cy = driver_list::find(y->parent); @@ -57,123 +51,181 @@ bool sorted_game_list(const game_driver *x, const game_driver *y) } if (!clonex && !cloney) - return (cs_stricmp(x->type.fullname(), y->type.fullname()) < 0); + { + return (core_stricmp(x->type.fullname(), y->type.fullname()) < 0); + } else if (clonex && cloney) { - if (!cs_stricmp(x->parent, y->parent)) - return (cs_stricmp(x->type.fullname(), y->type.fullname()) < 0); + if (!core_stricmp(x->parent, y->parent)) + return (core_stricmp(x->type.fullname(), y->type.fullname()) < 0); else - return (cs_stricmp(driver_list::driver(cx).type.fullname(), driver_list::driver(cy).type.fullname()) < 0); + return (core_stricmp(driver_list::driver(cx).type.fullname(), driver_list::driver(cy).type.fullname()) < 0); } else if (!clonex && cloney) { - if (!cs_stricmp(x->name, y->parent)) + if (!core_stricmp(x->name, y->parent)) return true; else - return (cs_stricmp(x->type.fullname(), driver_list::driver(cy).type.fullname()) < 0); + return (core_stricmp(x->type.fullname(), driver_list::driver(cy).type.fullname()) < 0); } else { - if (!cs_stricmp(x->parent, y->name)) + if (!core_stricmp(x->parent, y->name)) return false; else - return (cs_stricmp(driver_list::driver(cx).type.fullname(), y->type.fullname()) < 0); + return (core_stricmp(driver_list::driver(cx).type.fullname(), y->type.fullname()) < 0); } } -//------------------------------------------------- -// ctor / dtor -//------------------------------------------------- -menu_audit::menu_audit(mame_ui_manager &mui, render_container &container, vptr_game &availablesorted, vptr_game &unavailablesorted, int _audit_mode) +menu_audit::menu_audit(mame_ui_manager &mui, render_container &container, std::vector<ui_system_info> &availablesorted, mode audit_mode) : menu(mui, container) + , m_worker_thread() + , m_audit_mode(audit_mode) + , m_total((mode::FAST == audit_mode) + ? std::accumulate(availablesorted.begin(), availablesorted.end(), std::size_t(0), [] (std::size_t n, ui_system_info const &info) { return n + (info.available ? 0 : 1); }) + : availablesorted.size()) , m_availablesorted(availablesorted) - , m_unavailablesorted(unavailablesorted) - , m_audit_mode(_audit_mode) - , m_first(true) + , m_audited(0) + , m_current(nullptr) + , m_phase(phase::CONSENT) { - if (m_audit_mode == 2) + switch (m_audit_mode) { - m_availablesorted.clear(); - m_unavailablesorted.clear(); + case mode::FAST: + m_prompt[0] = util::string_format(_("Audit ROMs for %1$u machines marked unavailable?"), m_total); + break; + case mode::ALL: + m_prompt[0] = util::string_format(_("Audit ROMs for all %1$u machines?"), m_total); + break; } + std::string filename(emulator_info::get_configname()); + filename += "_avail.ini"; + m_prompt[1] = util::string_format(_("(results will be saved to %1$s)"), filename); } menu_audit::~menu_audit() { } -//------------------------------------------------- -// handle -//------------------------------------------------- - -void menu_audit::handle() +void menu_audit::custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) { - process(PROCESS_CUSTOM_ONLY); - - if (m_first) + switch (m_phase) { - ui().draw_text_box(container(), _("Audit in progress..."), ui::text_layout::CENTER, 0.5f, 0.5f, UI_GREEN_COLOR); - m_first = false; - return; + case phase::CONSENT: + draw_text_box( + std::begin(m_prompt), std::end(m_prompt), + x, x2, y - top, y - UI_BOX_TB_BORDER, + ui::text_layout::CENTER, ui::text_layout::NEVER, false, + UI_TEXT_COLOR, UI_GREEN_COLOR, 1.0f); + break; + + case phase::AUDIT: + { + // there's a race here between the total audited being updated and the next driver pointer being loaded + // it doesn't matter because we redraw on every frame anyway so it sorts itself out very quickly + game_driver const *const driver(m_current.load()); + std::size_t const audited(m_audited.load()); + std::string const text(util::string_format( + _("Auditing ROMs for machine %2$u of %3$u...\n%1$s"), + driver ? driver->type.fullname() : "", + audited + 1, + m_total)); + ui().draw_text_box(container(), text.c_str(), ui::text_layout::CENTER, 0.5f, 0.5f, UI_GREEN_COLOR); + } + break; } +} + +void menu_audit::populate(float &customtop, float &custombottom) +{ + item_append(_("Start Audit"), "", 0, ITEMREF_START); + customtop = (ui().get_line_height() * 2.0f) + (UI_BOX_TB_BORDER * 3.0f); +} - if (m_audit_mode == 1) +void menu_audit::handle() +{ + switch (m_phase) { - vptr_game::iterator iter = m_unavailablesorted.begin(); - while (iter != m_unavailablesorted.end()) + case phase::CONSENT: { - driver_enumerator enumerator(machine().options(), (*iter)->name); - enumerator.next(); - media_auditor auditor(enumerator); - media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST); - - // if everything looks good, include the driver - if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) + event const *const menu_event(process(0)); + if (menu_event && (ITEMREF_START == menu_event->itemref) && (IPT_UI_SELECT == menu_event->iptkey)) { - m_availablesorted.push_back((*iter)); - iter = m_unavailablesorted.erase(iter); + m_phase = phase::AUDIT; + m_worker_thread = std::thread( + [this] () + { + switch (m_audit_mode) + { + case mode::FAST: + audit_fast(); + return; + case mode::ALL: + audit_all(); + return; + } + throw false; + }); } - else - ++iter; } + break; + + case phase::AUDIT: + process(PROCESS_CUSTOM_ONLY | PROCESS_NOINPUT); + + if (m_audited.load() >= m_total) + { + m_worker_thread.join(); + save_available_machines(); + reset_parent(reset_options::SELECT_FIRST); + stack_pop(); + } + break; } - else +} + +void menu_audit::audit_fast() +{ + for (ui_system_info &info : m_availablesorted) { - driver_enumerator enumerator(machine().options()); - media_auditor auditor(enumerator); - while (enumerator.next()) + if (!info.available) { - media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST); + m_current.store(info.driver); + driver_enumerator enumerator(machine().options(), info.driver->name); + enumerator.next(); + media_auditor auditor(enumerator); + media_auditor::summary const summary(auditor.audit_media(AUDIT_VALIDATE_FAST)); + info.available = (summary == media_auditor::CORRECT) || (summary == media_auditor::BEST_AVAILABLE) || (summary == media_auditor::NONE_NEEDED); // if everything looks good, include the driver - if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED) - m_availablesorted.push_back(&enumerator.driver()); - else - m_unavailablesorted.push_back(&enumerator.driver()); + info.available = (summary == media_auditor::CORRECT) || (summary == media_auditor::BEST_AVAILABLE) || (summary == media_auditor::NONE_NEEDED); + ++m_audited; } } - - // sort - std::stable_sort(m_availablesorted.begin(), m_availablesorted.end(), sorted_game_list); - std::stable_sort(m_unavailablesorted.begin(), m_unavailablesorted.end(), sorted_game_list); - save_available_machines(); - reset_parent(reset_options::SELECT_FIRST); - stack_pop(); } -//------------------------------------------------- -// populate -//------------------------------------------------- - -void menu_audit::populate(float &customtop, float &custombottom) +void menu_audit::audit_all() { - item_append("Dummy", "", 0, (void *)(uintptr_t)1); -} + m_availablesorted.clear(); + driver_enumerator enumerator(machine().options()); + media_auditor auditor(enumerator); + while (enumerator.next()) + { + m_current.store(&enumerator.driver()); + media_auditor::summary const summary(auditor.audit_media(AUDIT_VALIDATE_FAST)); -//------------------------------------------------- -// save drivers infos to file -//------------------------------------------------- + // if everything looks good, include the driver + m_availablesorted.emplace_back(enumerator.driver(), (summary == media_auditor::CORRECT) || (summary == media_auditor::BEST_AVAILABLE) || (summary == media_auditor::NONE_NEEDED)); + ++m_audited; + } + + // sort + std::stable_sort( + m_availablesorted.begin(), + m_availablesorted.end(), + [] (ui_system_info const &a, ui_system_info const &b) { return sorted_game_list(a.driver, b.driver); }); +} void menu_audit::save_available_machines() { @@ -182,25 +234,15 @@ void menu_audit::save_available_machines() if (file.open(emulator_info::get_configname(), "_avail.ini") == osd_file::error::NONE) { // generate header - std::ostringstream buffer; - buffer << "#\n" << UI_VERSION_TAG << emulator_info::get_bare_build_version() << "\n#\n\n"; - util::stream_format(buffer, "%d\n", m_availablesorted.size()); - util::stream_format(buffer, "%d\n", m_unavailablesorted.size()); + file.printf("#\n%s%s\n#\n\n", UI_VERSION_TAG, emulator_info::get_bare_build_version()); // generate available list - for (size_t x = 0; x < m_availablesorted.size(); ++x) + for (ui_system_info const &info : m_availablesorted) { - int find = driver_list::find(m_availablesorted[x]->name); - util::stream_format(buffer, "%d\n", find); + if (info.available) + file.printf("%s\n", info.driver->name); } - // generate unavailable list - for (size_t x = 0; x < m_unavailablesorted.size(); ++x) - { - int find = driver_list::find(m_unavailablesorted[x]->name); - util::stream_format(buffer, "%d\n", find); - } - file.puts(buffer.str().c_str()); file.close(); } } |