diff options
Diffstat (limited to 'src/frontend/mame/ui/selgame.cpp')
-rw-r--r-- | src/frontend/mame/ui/selgame.cpp | 211 |
1 files changed, 101 insertions, 110 deletions
diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 9deb0ef6649..c22cb3a54a5 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -30,6 +30,9 @@ #include "uiinput.h" #include "luaengine.h" +#include <cstring> +#include <iterator> + extern const char UI_VERSION_TAG[]; @@ -326,12 +329,12 @@ void menu_select_game::handle() break; case IPT_UI_AUDIT_FAST: - if (!m_unavailsortedlist.empty()) - menu::stack_push<menu_audit>(ui(), container(), m_availsortedlist, m_unavailsortedlist, 1); + 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_availsortedlist, m_unavailsortedlist, 2); + menu::stack_push<menu_audit>(ui(), container(), m_availsortedlist, menu_audit::mode::ALL); break; } } @@ -367,44 +370,25 @@ void menu_select_game::populate(float &customtop, float &custombottom) m_displaylist.clear(); // if filter is set on category, build category list - switch (main_filters::actual) - { - case machine_filter::ALL: - m_displaylist = m_sortedlist; - break; - case machine_filter::AVAILABLE: - m_displaylist = m_availsortedlist; - break; - case machine_filter::UNAVAILABLE: - m_displaylist = m_unavailsortedlist; - break; - default: - { - auto const it(main_filters::filters.find(main_filters::actual)); - std::copy_if( - m_sortedlist.begin(), - m_sortedlist.end(), - std::back_inserter(m_displaylist), - [&flt = *it->second] (game_driver const *drv) { return flt.apply(*drv); }); - } - } + auto const it(main_filters::filters.find(main_filters::actual)); + it->second->apply(m_availsortedlist.begin(), m_availsortedlist.end(), std::back_inserter(m_displaylist)); // iterate over entries int curitem = 0; - for (auto & elem : m_displaylist) + for (ui_system_info const &elem : m_displaylist) { - if (old_item_selected == -1 && elem->name == reselect_last::driver()) + if (old_item_selected == -1 && elem.driver->name == reselect_last::driver()) old_item_selected = curitem; - bool cloneof = strcmp(elem->parent, "0"); + bool cloneof = strcmp(elem.driver->parent, "0"); if (cloneof) { - int cx = driver_list::find(elem->parent); + 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->type.fullname(), "", (cloneof) ? (flags_ui | FLAG_INVERT) : flags_ui, (void *)elem); + item_append(elem.driver->type.fullname(), "", (cloneof) ? (flags_ui | FLAG_INVERT) : flags_ui, (void *)elem.driver); curitem++; } } @@ -490,19 +474,16 @@ void menu_select_game::populate(float &customtop, float &custombottom) void menu_select_game::build_available_list() { - int m_total = driver_list::total(); - std::vector<bool> m_included(m_total, false); + std::size_t const total = driver_list::total(); + std::vector<bool> included(total, false); - // open a path to the ROMs and find them in the array + // iterate over ROM directories and look for potential ROMs file_enumerator path(machine().options().media_path()); - const osd::directory::entry *dir; - - // iterate while we get new objects - while ((dir = path.next()) != nullptr) + for (osd::directory::entry const *dir = path.next(); dir; dir = path.next()) { char drivername[50]; char *dst = drivername; - const char *src; + char const *src; // build a name for it for (src = dir->name; *src != 0 && *src != '.' && dst < &drivername[ARRAY_LENGTH(drivername) - 1]; ++src) @@ -510,67 +491,63 @@ void menu_select_game::build_available_list() *dst = 0; int drivnum = driver_list::find(drivername); - if (drivnum != -1 && !m_included[drivnum]) - { - m_availsortedlist.push_back(&driver_list::driver(drivnum)); - m_included[drivnum] = true; - } + if (drivnum != -1 && !included[drivnum]) + included[drivnum] = true; } // now check and include NONE_NEEDED if (!ui().options().hide_romless()) { - for (int x = 0; x < m_total; ++x) + // FIXME: can't use the convenience macros tiny ROM entries + auto const is_required_rom = + [] (tiny_rom_entry const &rom) + { + return ((rom.flags & ROMENTRY_TYPEMASK) == ROMENTRYTYPE_ROM) && ((rom.flags & ROM_OPTIONALMASK) != ROM_OPTIONAL) && !std::strchr(rom.hashdata, '!'); + }; + for (std::size_t x = 0; total > x; ++x) { - auto driver = &driver_list::driver(x); - if (!m_included[x] && driver != &GAME_NAME(___empty)) + game_driver const &driver(driver_list::driver(x)); + if (!included[x] && (&GAME_NAME(___empty) != &driver)) { - auto entries = rom_build_entries(driver->rom); - const rom_entry *rom = entries.data(); - bool noroms = true; - - // check NO-DUMP - for (; !ROMENTRY_ISEND(rom) && noroms == true; ++rom) - if (ROMENTRY_ISFILE(rom)) + bool noroms(true); + tiny_rom_entry const *rom; + for (rom = driver.rom; (rom->flags & ROMENTRY_TYPEMASK) != ROMENTRYTYPE_END; ++rom) + { + // check optional and NO_DUMP + if (is_required_rom(*rom)) { - util::hash_collection hashes(ROM_GETHASHDATA(rom)); - if (!hashes.flag(util::hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom)) - noroms = false; + noroms = false; + break; // break before incrementing, or it will subtly break the check for all ROMs belonging to parent } + } if (!noroms) { // check if clone == parent - auto cx = driver_list::clone(*driver); - if (cx != -1 && m_included[cx]) + auto const cx(driver_list::clone(driver)); + if ((0 <= cx) && included[cx]) { - auto drv = &driver_list::driver(cx); - if (driver->rom == drv->rom) + game_driver const &parent(driver_list::driver(cx)); + if (driver.rom == parent.rom) + { noroms = true; - - // check if clone < parent - if (!noroms) + } + else { + // check if clone < parent noroms = true; - for (; !ROMENTRY_ISEND(rom) && noroms == true; ++rom) + for ( ; noroms && rom && ((rom->flags & ROMENTRY_TYPEMASK) != ROMENTRYTYPE_END); ++rom) { - if (ROMENTRY_ISFILE(rom)) + if (is_required_rom(*rom)) { - util::hash_collection hashes(ROM_GETHASHDATA(rom)); - if (hashes.flag(util::hash_collection::FLAG_NO_DUMP) || ROM_ISOPTIONAL(rom)) - continue; - - uint64_t lenght = ROM_GETLENGTH(rom); - auto found = false; - auto parent_entries = rom_build_entries(drv->rom); - for (auto parentrom = parent_entries.data(); !ROMENTRY_ISEND(parentrom) && found == false; ++parentrom) + util::hash_collection const hashes(rom->hashdata); + + bool found(false); + for (tiny_rom_entry const *parentrom = parent.rom; !found && ((parentrom->flags & ROMENTRY_TYPEMASK) != ROMENTRYTYPE_END); ++parentrom) { - if (ROMENTRY_ISFILE(parentrom) && ROM_GETLENGTH(parentrom) == lenght) + if (is_required_rom(*parentrom) && (rom->length == parentrom->length)) { - util::hash_collection parenthashes(ROM_GETHASHDATA(parentrom)); - if (parenthashes.flag(util::hash_collection::FLAG_NO_DUMP) || ROM_ISOPTIONAL(parentrom)) - continue; - + util::hash_collection const parenthashes(parentrom->hashdata); if (hashes == parenthashes) found = true; } @@ -583,23 +560,23 @@ void menu_select_game::build_available_list() } if (noroms) - { - m_availsortedlist.push_back(&driver_list::driver(x)); - m_included[x] = true; - } + included[x] = true; } } } - // sort - std::stable_sort(m_availsortedlist.begin(), m_availsortedlist.end(), sorted_game_list); - - // now build the unavailable list - for (int x = 0; x < m_total; ++x) - if (!m_included[x] && &driver_list::driver(x) != &GAME_NAME(___empty)) - m_unavailsortedlist.push_back(&driver_list::driver(x)); // sort - std::stable_sort(m_unavailsortedlist.begin(), m_unavailsortedlist.end(), sorted_game_list); + 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); }); } @@ -823,8 +800,8 @@ void menu_select_game::populate_search() for (; index < m_displaylist.size(); ++index) { // pick the best match between driver name and description - int curpenalty = fuzzy_substring(m_search, m_displaylist[index]->type.fullname()); - int tmp = fuzzy_substring(m_search, m_displaylist[index]->name); + 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); // insert into the sorted table of matches @@ -841,7 +818,7 @@ void menu_select_game::populate_search() m_searchlist[matchnum + 1] = m_searchlist[matchnum]; } - m_searchlist[matchnum] = m_displaylist[index]; + m_searchlist[matchnum] = m_displaylist[index].driver; penalty[matchnum] = curpenalty; } } @@ -1033,7 +1010,9 @@ void menu_select_game::inkey_export() } else { - list = m_displaylist; + list.reserve(m_displaylist.size()); + for (ui_system_info const &info : m_displaylist) + list.emplace_back(info.driver); } } @@ -1086,8 +1065,8 @@ bool menu_select_game::load_available_machines() if (file.open(emulator_info::get_configname(), "_avail.ini") != osd_file::error::NONE) return false; - std::string readbuf; char rbuf[MAX_CHAR_INFO]; + std::string readbuf; file.gets(rbuf, MAX_CHAR_INFO); file.gets(rbuf, MAX_CHAR_INFO); readbuf = chartrimcarriage(rbuf); @@ -1100,28 +1079,40 @@ bool menu_select_game::load_available_machines() return false; } - file.gets(rbuf, MAX_CHAR_INFO); - file.gets(rbuf, MAX_CHAR_INFO); - file.gets(rbuf, MAX_CHAR_INFO); - auto avsize = atoi(rbuf); - file.gets(rbuf, MAX_CHAR_INFO); - auto unavsize = atoi(rbuf); - // load available list - for (int x = 0; x < avsize; ++x) + std::unordered_set<std::string> available; + while (file.gets(rbuf, MAX_CHAR_INFO)) { - file.gets(rbuf, MAX_CHAR_INFO); - int find = atoi(rbuf); - m_availsortedlist.push_back(&driver_list::driver(find)); + readbuf = rbuf; + strtrimspace(readbuf); + + if (readbuf.empty() || ('#' == readbuf[0])) // ignore empty lines and line comments + ; + else if ('[' == readbuf[0]) // throw out the rest of the file if we find a section heading + break; + else + available.emplace(std::move(readbuf)); } - // load unavailable list - for (int x = 0; x < unavsize; ++x) + // turn it into the sorted system list we all love + m_availsortedlist.reserve(driver_list::total()); + for (std::size_t x = 0; driver_list::total() > x; ++x) { - file.gets(rbuf, MAX_CHAR_INFO); - int find = atoi(rbuf); - m_unavailsortedlist.push_back(&driver_list::driver(find)); + 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; } |