diff options
Diffstat (limited to 'src/emu/ui/selsoft.cpp')
-rw-r--r-- | src/emu/ui/selsoft.cpp | 1976 |
1 files changed, 0 insertions, 1976 deletions
diff --git a/src/emu/ui/selsoft.cpp b/src/emu/ui/selsoft.cpp deleted file mode 100644 index 985a7d31bfc..00000000000 --- a/src/emu/ui/selsoft.cpp +++ /dev/null @@ -1,1976 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Dankan1890 -/*************************************************************************** - - ui/selsoft.cpp - - UI softwares menu. - -***************************************************************************/ - -#include "emu.h" -#include "emuopts.h" -#include "ui/ui.h" -#include "ui/menu.h" -#include "uiinput.h" -#include "audit.h" -#include "ui/selsoft.h" -#include "ui/datmenu.h" -#include "ui/datfile.h" -#include "ui/inifile.h" -#include "ui/selector.h" -#include "rendfont.h" -#include "rendutil.h" -#include "softlist.h" -#include <algorithm> - -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", - "pol", "rus", "slo", "spa", "sui", "swe", "tha", "tpe", "tw", "uk", "ukr", "usa" }; - -//------------------------------------------------- -// compares two items in the software list and -// sort them by parent-clone -//------------------------------------------------- - -bool compare_software(ui_software_info a, ui_software_info b) -{ - ui_software_info *x = &a; - ui_software_info *y = &b; - - bool clonex = (x->parentname[0] != '\0'); - bool cloney = (y->parentname[0] != '\0'); - - if (!clonex && !cloney) - return (strmakelower(x->longname) < strmakelower(y->longname)); - - std::string cx(x->parentlongname), cy(y->parentlongname); - - if (clonex && cx[0] == '\0') - clonex = false; - - if (cloney && cy[0] == '\0') - cloney = false; - - if (!clonex && !cloney) - return (strmakelower(x->longname) < strmakelower(y->longname)); - else if (clonex && cloney) - { - if (!core_stricmp(x->parentname.c_str(), y->parentname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str())) - return (strmakelower(x->longname) < strmakelower(y->longname)); - else - return (strmakelower(cx) < strmakelower(cy)); - } - else if (!clonex && cloney) - { - if (!core_stricmp(x->shortname.c_str(), y->parentname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str())) - return true; - else - return (strmakelower(x->longname) < strmakelower(cy)); - } - else - { - if (!core_stricmp(x->parentname.c_str(), y->shortname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str())) - return false; - else - return (strmakelower(cx) < strmakelower(y->longname)); - } -} - -//------------------------------------------------- -// get bios count -//------------------------------------------------- - -bool has_multiple_bios(const game_driver *driver, std::vector<s_bios> &biosname) -{ - if (driver->rom == nullptr) - return 0; - - std::string default_name; - for (const rom_entry *rom = driver->rom; !ROMENTRY_ISEND(rom); ++rom) - if (ROMENTRY_ISDEFAULT_BIOS(rom)) - default_name = ROM_GETNAME(rom); - - for (const rom_entry *rom = driver->rom; !ROMENTRY_ISEND(rom); ++rom) - { - 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 -//------------------------------------------------- - -ui_menu_select_software::ui_menu_select_software(running_machine &machine, render_container *container, const game_driver *driver) : ui_menu(machine, container) -{ - if (reselect_last::get()) - reselect_last::set(false); - - sw_filters::actual = 0; - - m_driver = driver; - build_software_list(); - load_sw_custom_filters(); - - ui_globals::curimage_view = SNAPSHOT_VIEW; - ui_globals::switch_image = true; - ui_globals::cur_sw_dats_view = UI_FIRST_LOAD; - - std::string error_string; - machine.options().set_value(OPTION_SOFTWARENAME, "", OPTION_PRIORITY_CMDLINE, error_string); -} - -//------------------------------------------------- -// dtor -//------------------------------------------------- - -ui_menu_select_software::~ui_menu_select_software() -{ - ui_globals::curimage_view = CABINETS_VIEW; - ui_globals::switch_image = true; -} - -//------------------------------------------------- -// handle -//------------------------------------------------- - -void ui_menu_select_software::handle() -{ - bool check_filter = false; - - // ignore pause keys by swallowing them before we process the menu - machine().ui_input().pressed(IPT_UI_PAUSE); - - // process the menu - const ui_menu_event *m_event = process(UI_MENU_PROCESS_LR_REPEAT); - - if (m_event != nullptr && m_event->itemref != nullptr) - { - // reset the error on any future m_event - if (ui_error) - ui_error = false; - - // handle selections - else if (m_event->iptkey == IPT_UI_SELECT) - inkey_select(m_event); - - // handle UI_LEFT - else if (m_event->iptkey == IPT_UI_LEFT) - { - // Images - if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW) - { - ui_globals::curimage_view--; - ui_globals::switch_image = true; - ui_globals::default_image = false; - } - - // Infos - else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view > 0) - { - ui_globals::cur_sw_dats_view--; - topline_datsview = 0; - } - } - - // handle UI_RIGHT - else if (m_event->iptkey == IPT_UI_RIGHT) - { - // Images - if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW) - { - ui_globals::curimage_view++; - ui_globals::switch_image = true; - ui_globals::default_image = false; - } - - // Infos - else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < 1) - { - ui_globals::cur_sw_dats_view++; - topline_datsview = 0; - } - } - - // handle UI_DATS - else if (m_event->iptkey == IPT_UI_DATS && machine().ui().options().enabled_dats()) - { - ui_software_info *ui_swinfo = (ui_software_info *)m_event->itemref; - - if ((FPTR)ui_swinfo > 1 && machine().datfile().has_data(ui_swinfo->driver)) - { - if (ui_swinfo->startempty == 1) - ui_menu::stack_push(global_alloc_clear<ui_menu_dats_view>(machine(), container, ui_swinfo->driver)); - else - ui_menu::stack_push(global_alloc_clear<ui_menu_dats_view>(machine(), container, ui_swinfo)); - } - } - - // handle UI_UP_FILTER - else if (m_event->iptkey == IPT_UI_UP_FILTER && sw_filters::actual > UI_SW_FIRST) - { - l_sw_hover = sw_filters::actual - 1; - check_filter = true; - } - - // handle UI_DOWN_FILTER - else if (m_event->iptkey == IPT_UI_DOWN_FILTER && sw_filters::actual < UI_SW_LAST) - { - l_sw_hover = sw_filters::actual + 1; - check_filter = true; - } - - // handle UI_LEFT_PANEL - else if (m_event->iptkey == IPT_UI_LEFT_PANEL) - ui_globals::rpanel = RP_IMAGES; - - // handle UI_RIGHT_PANEL - else if (m_event->iptkey == IPT_UI_RIGHT_PANEL) - ui_globals::rpanel = RP_INFOS; - - // escape pressed with non-empty text clears the text - else if (m_event->iptkey == IPT_UI_CANCEL && m_search[0] != 0) - { - m_search[0] = '\0'; - reset(UI_MENU_RESET_SELECT_FIRST); - } - - // handle UI_FAVORITES - else if (m_event->iptkey == IPT_UI_FAVORITES) - { - ui_software_info *swinfo = (ui_software_info *)m_event->itemref; - - if ((FPTR)swinfo > 2) - { - if (!machine().favorite().isgame_favorite(*swinfo)) - { - machine().favorite().add_favorite_game(*swinfo); - machine().popmessage("%s\n added to favorites list.", swinfo->longname.c_str()); - } - - else - { - machine().popmessage("%s\n removed from favorites list.", swinfo->longname.c_str()); - machine().favorite().remove_favorite_game(); - } - } - } - - // typed characters append to the buffer - else if (m_event->iptkey == IPT_SPECIAL) - inkey_special(m_event); - - else if (m_event->iptkey == IPT_OTHER) - check_filter = true; - } - - if (m_event != nullptr && m_event->itemref == nullptr) - { - // reset the error on any future m_event - if (ui_error) - ui_error = false; - - else if (m_event->iptkey == IPT_OTHER) - check_filter = true; - - // handle UI_UP_FILTER - else if (m_event->iptkey == IPT_UI_UP_FILTER && sw_filters::actual > UI_SW_FIRST) - { - l_sw_hover = sw_filters::actual - 1; - check_filter = true; - } - - // handle UI_DOWN_FILTER - else if (m_event->iptkey == IPT_UI_DOWN_FILTER && sw_filters::actual < UI_SW_LAST) - { - l_sw_hover = sw_filters::actual + 1; - check_filter = true; - } - } - - // if we're in an error state, overlay an error message - if (ui_error) - machine().ui().draw_text_box(container, - "The selected software is missing one or more required files. " - "Please select a different software.\n\nPress any key (except ESC) to continue.", - JUSTIFY_CENTER, 0.5f, 0.5f, UI_RED_COLOR); - - // handle filters selection from key shortcuts - if (check_filter) - { - m_search[0] = '\0'; - - switch (l_sw_hover) - { - case UI_SW_REGION: - ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.region.ui, - m_filter.region.actual, SELECTOR_SOFTWARE, l_sw_hover)); - break; - case UI_SW_YEARS: - ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.year.ui, - m_filter.year.actual, SELECTOR_SOFTWARE, l_sw_hover)); - break; - case UI_SW_LIST: - ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.swlist.description, - m_filter.swlist.actual, SELECTOR_SOFTWARE, l_sw_hover)); - break; - case UI_SW_TYPE: - ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.type.ui, - m_filter.type.actual, SELECTOR_SOFTWARE, l_sw_hover)); - break; - case UI_SW_PUBLISHERS: - ui_menu::stack_push(global_alloc_clear<ui_menu_selector>(machine(), container, m_filter.publisher.ui, - m_filter.publisher.actual, SELECTOR_SOFTWARE, l_sw_hover)); - break; - case UI_SW_CUSTOM: - sw_filters::actual = l_sw_hover; - ui_menu::stack_push(global_alloc_clear<ui_menu_swcustom_filter>(machine(), container, m_driver, m_filter)); - break; - default: - sw_filters::actual = l_sw_hover; - reset(UI_MENU_RESET_SELECT_FIRST); - break; - } - } -} - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void ui_menu_select_software::populate() -{ - UINT32 flags_ui = MENU_FLAG_UI_SWLIST | MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW; - m_has_empty_start = true; - int old_software = -1; - - machine_config config(*m_driver, machine().options()); - image_interface_iterator iter(config.root_device()); - - for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next()) - if (image->filename() == nullptr && image->must_be_loaded()) - { - m_has_empty_start = false; - break; - } - - // no active search - if (m_search[0] == 0) - { - // if the device can be loaded empty, add an item - if (m_has_empty_start) - item_append("[Start empty]", nullptr, flags_ui, (void *)&m_swinfo[0]); - - m_displaylist.clear(); - m_tmp.clear(); - - switch (sw_filters::actual) - { - case UI_SW_PUBLISHERS: - build_list(m_tmp, m_filter.publisher.ui[m_filter.publisher.actual].c_str()); - break; - - case UI_SW_LIST: - build_list(m_tmp, m_filter.swlist.name[m_filter.swlist.actual].c_str()); - break; - - case UI_SW_YEARS: - build_list(m_tmp, m_filter.year.ui[m_filter.year.actual].c_str()); - break; - - case UI_SW_TYPE: - build_list(m_tmp, m_filter.type.ui[m_filter.type.actual].c_str()); - break; - - case UI_SW_REGION: - build_list(m_tmp, m_filter.region.ui[m_filter.region.actual].c_str()); - break; - - case UI_SW_CUSTOM: - build_custom(); - break; - - default: - build_list(m_tmp); - break; - } - - // iterate over entries - for (size_t curitem = 0; curitem < m_displaylist.size(); ++curitem) - { - 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) - old_software = m_has_empty_start ? curitem + 1 : curitem; - - item_append(m_displaylist[curitem]->longname.c_str(), m_displaylist[curitem]->devicetype.c_str(), - m_displaylist[curitem]->parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui), (void *)m_displaylist[curitem]); - } - } - - else - { - find_matches(m_search, VISIBLE_GAMES_IN_SEARCH); - - for (int curitem = 0; m_searchlist[curitem] != nullptr; ++curitem) - item_append(m_searchlist[curitem]->longname.c_str(), m_searchlist[curitem]->devicetype.c_str(), - m_searchlist[curitem]->parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui), - (void *)m_searchlist[curitem]); - } - - item_append(MENU_SEPARATOR_ITEM, nullptr, flags_ui, nullptr); - - // configure the custom rendering - customtop = 4.0f * machine().ui().get_line_height() + 5.0f * UI_BOX_TB_BORDER; - custombottom = 5.0f * machine().ui().get_line_height() + 4.0f * UI_BOX_TB_BORDER; - - if (old_software != -1) - { - selected = old_software; - top_line = selected - (ui_globals::visible_sw_lines / 2); - } - - reselect_last::reset(); -} - -//------------------------------------------------- -// build a list of softwares -//------------------------------------------------- - -void ui_menu_select_software::build_software_list() -{ - // add start empty item - m_swinfo.emplace_back(m_driver->name, m_driver->description, "", "", "", 0, "", m_driver, "", "", "", 1, "", "", "", true); - - machine_config config(*m_driver, machine().options()); - software_list_device_iterator deviter(config.root_device()); - - // iterate thru all software lists - for (software_list_device *swlist = deviter.first(); swlist != nullptr; swlist = deviter.next()) - { - m_filter.swlist.name.push_back(swlist->list_name()); - m_filter.swlist.description.push_back(swlist->description()); - for (software_info *swinfo = swlist->first_software_info(); swinfo != nullptr; swinfo = swinfo->next()) - { - software_part *part = swinfo->first_part(); - if (part->is_compatible(*swlist)) - { - const char *instance_name = nullptr; - const char *type_name = nullptr; - ui_software_info tmpmatches; - image_interface_iterator imgiter(config.root_device()); - for (device_image_interface *image = imgiter.first(); image != nullptr; image = imgiter.next()) - { - const char *interface = image->image_interface(); - if (interface != nullptr && part->matches_interface(interface)) - { - instance_name = image->instance_name(); - 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) - continue; - - if (swinfo->shortname()) tmpmatches.shortname = swinfo->shortname(); - if (swinfo->longname()) tmpmatches.longname = swinfo->longname(); - if (swinfo->parentname()) tmpmatches.parentname = swinfo->parentname(); - if (swinfo->year()) tmpmatches.year = swinfo->year(); - if (swinfo->publisher()) tmpmatches.publisher = swinfo->publisher(); - tmpmatches.supported = swinfo->supported(); - if (part->name()) tmpmatches.part = part->name(); - tmpmatches.driver = m_driver; - if (swlist->list_name()) tmpmatches.listname = swlist->list_name(); - if (part->interface()) tmpmatches.interface = part->interface(); - tmpmatches.startempty = 0; - tmpmatches.parentlongname.clear(); - tmpmatches.usage.clear(); - tmpmatches.available = false; - - for (feature_list_item *flist = swinfo->other_info(); flist != nullptr; flist = flist->next()) - if (!strcmp(flist->name(), "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_displaylist.resize(m_swinfo.size() + 1); - - // retrieve and set the long name of software for parents - for (size_t y = 1; y < m_swinfo.size(); ++y) - { - if (!m_swinfo[y].parentname.empty()) - { - std::string lparent(m_swinfo[y].parentname); - bool found = false; - - // first scan backward - for (int x = y; x > 0; --x) - if (lparent == m_swinfo[x].shortname && m_swinfo[y].listname == m_swinfo[x].listname) - { - m_swinfo[y].parentlongname = m_swinfo[x].longname; - found = true; - break; - } - - // not found? then scan forward - for (size_t x = y; !found && x < m_swinfo.size(); ++x) - if (lparent == m_swinfo[x].shortname && m_swinfo[y].listname == m_swinfo[x].listname) - { - m_swinfo[y].parentlongname = m_swinfo[x].longname; - break; - } - } - } - - std::string searchstr, curpath; - const osd_directory_entry *dir; - for (auto & elem : m_filter.swlist.name) - { - path_iterator path(machine().options().media_path()); - while (path.next(curpath)) - { - searchstr.assign(curpath).append(PATH_SEPARATOR).append(elem).append(";"); - file_enumerator fpath(searchstr.c_str()); - - // iterate while we get new objects - while ((dir = fpath.next()) != nullptr) - { - std::string name; - if (dir->type == ENTTYPE_FILE) - name = core_filename_extract_base(dir->name, true); - else if (dir->type == ENTTYPE_DIR && strcmp(dir->name, ".") != 0) - name = dir->name; - else - continue; - - strmakelower(name); - for (auto & yelem : m_swinfo) - if (yelem.shortname == name && yelem.listname == elem) - { - yelem.available = true; - break; - } - } - } - } - - // sort array - std::stable_sort(m_swinfo.begin() + 1, m_swinfo.end(), compare_software); - std::stable_sort(m_filter.region.ui.begin(), m_filter.region.ui.end()); - std::stable_sort(m_filter.year.ui.begin(), m_filter.year.ui.end()); - std::stable_sort(m_filter.type.ui.begin(), m_filter.type.ui.end()); - std::stable_sort(m_filter.publisher.ui.begin(), m_filter.publisher.ui.end()); - - for (size_t x = 1; x < m_swinfo.size(); ++x) - m_sortedlist.push_back(&m_swinfo[x]); -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void ui_menu_select_software::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - ui_software_info *swinfo = (ui_software_info *)selectedref; - const game_driver *driver = nullptr; - ui_manager &mui = machine().ui(); - float width; - std::string tempbuf[5], filtered; - rgb_t color = UI_BACKGROUND_COLOR; - bool isstar = false; - float tbarspace = mui.get_line_height(); - - // determine the text for the header - int vis_item = (m_search[0] != 0) ? visible_items : (m_has_empty_start ? visible_items - 1 : visible_items); - strprintf(tempbuf[0], "MAME %s ( %d / %d softwares )", bare_build_version, vis_item, (int)m_swinfo.size() - 1); - tempbuf[1].assign("Driver: \"").append(m_driver->description).append("\" software list "); - - if (sw_filters::actual == UI_SW_REGION && m_filter.region.ui.size() != 0) - filtered.assign("Region: ").append(m_filter.region.ui[m_filter.region.actual]).append(" - "); - else if (sw_filters::actual == UI_SW_PUBLISHERS) - filtered.assign("Publisher: ").append(m_filter.publisher.ui[m_filter.publisher.actual]).append(" - "); - else if (sw_filters::actual == UI_SW_YEARS) - filtered.assign("Year: ").append(m_filter.year.ui[m_filter.year.actual]).append(" - "); - else if (sw_filters::actual == UI_SW_LIST) - filtered.assign("Software List: ").append(m_filter.swlist.description[m_filter.swlist.actual]).append(" - "); - else if (sw_filters::actual == UI_SW_TYPE) - filtered.assign("Device type: ").append(m_filter.type.ui[m_filter.type.actual]).append(" - "); - - tempbuf[2].assign(filtered).append("Search: ").append(m_search).append("_"); - - // get the size of the text - float maxwidth = origx2 - origx1; - - for (int line = 0; line < 3; ++line) - { - mui.draw_text_full(container, tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER, - DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - maxwidth = MAX(width, maxwidth); - } - - // compute our bounds - float x1 = 0.5f - 0.5f * maxwidth; - float x2 = x1 + maxwidth; - float y1 = origy1 - top; - float y2 = origy1 - 3.0f * UI_BOX_TB_BORDER - tbarspace; - - // draw a box - mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_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 - for (int line = 0; line < 3; ++line) - { - mui.draw_text_full(container, tempbuf[line].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER, - DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); - y1 += mui.get_line_height(); - } - - // determine the text to render below - if (swinfo && swinfo->startempty == 1) - driver = swinfo->driver; - - if ((FPTR)driver > 1) - { - isstar = machine().favorite().isgame_favorite(driver); - - // first line is game description - strprintf(tempbuf[0], "%-.100s", driver->description); - - // next line is year, manufacturer - strprintf(tempbuf[1], "%s, %-.100s", driver->year, driver->manufacturer); - - // next line is clone/parent status - int cloneof = driver_list::non_bios_clone(*driver); - - if (cloneof != -1) - strprintf(tempbuf[2], "Driver is clone of: %-.100s", driver_list::driver(cloneof).description); - else - tempbuf[2] = "Driver is parent"; - - // next line is overall driver status - if (driver->flags & MACHINE_NOT_WORKING) - tempbuf[3] = "Overall: NOT WORKING"; - else if (driver->flags & MACHINE_UNEMULATED_PROTECTION) - tempbuf[3] = "Overall: Unemulated Protection"; - else - tempbuf[3] = "Overall: Working"; - - // next line is graphics, sound status - if (driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS)) - tempbuf[4] = "Graphics: Imperfect, "; - else - tempbuf[4] = "Graphics: OK, "; - - if (driver->flags & MACHINE_NO_SOUND) - tempbuf[4].append("Sound: Unimplemented"); - else if (driver->flags & MACHINE_IMPERFECT_SOUND) - tempbuf[4].append("Sound: Imperfect"); - else - tempbuf[4].append("Sound: OK"); - - color = UI_GREEN_COLOR; - - if ((driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS - | MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND)) != 0) - color = UI_YELLOW_COLOR; - - if ((driver->flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION)) != 0) - color = UI_RED_COLOR; - - } - - else if ((FPTR)swinfo > 1) - { - isstar = machine().favorite().isgame_favorite(*swinfo); - - // first line is long name - strprintf(tempbuf[0], "%-.100s", swinfo->longname.c_str()); - - // next line is year, publisher - strprintf(tempbuf[1], "%s, %-.100s", swinfo->year.c_str(), swinfo->publisher.c_str()); - - // next line is parent/clone - if (!swinfo->parentname.empty()) - strprintf(tempbuf[2], "Software is clone of: %-.100s", !swinfo->parentlongname.empty() ? swinfo->parentlongname.c_str() : swinfo->parentname.c_str()); - else - tempbuf[2] = "Software is parent"; - - // next line is supported status - if (swinfo->supported == SOFTWARE_SUPPORTED_NO) - { - tempbuf[3] = "Supported: No"; - color = UI_RED_COLOR; - } - else if (swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL) - { - tempbuf[3] = "Supported: Partial"; - color = UI_YELLOW_COLOR; - } - else - { - tempbuf[3] = "Supported: Yes"; - color = UI_GREEN_COLOR; - } - - // last line is romset name - strprintf(tempbuf[4], "romset: %-.100s", swinfo->shortname.c_str()); - } - - else - { - std::string copyright(emulator_info::get_copyright()); - size_t found = copyright.find("\n"); - - tempbuf[0].clear(); - tempbuf[1].assign(emulator_info::get_appname()).append(" ").append(build_version); - tempbuf[2] = copyright.substr(0, found); - tempbuf[3] = copyright.substr(found + 1); - tempbuf[4].clear(); - } - - // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; - x2 = x1 + maxwidth; - y1 = y2; - y2 = origy1 - UI_BOX_TB_BORDER; - - // draw toolbar - draw_toolbar(x1, y1, x2, y2, true); - - // get the size of the text - maxwidth = origx2 - origx1; - - for (auto & elem : tempbuf) - { - mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER, - DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - maxwidth = MAX(maxwidth, width); - } - - // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; - x2 = x1 + maxwidth; - y1 = origy2 + UI_BOX_TB_BORDER; - y2 = origy2 + bottom; - - // draw a box - mui.draw_outlined_box(container, x1, y1, x2, y2, color); - - // take off the borders - x1 += UI_BOX_LR_BORDER; - x2 -= UI_BOX_LR_BORDER; - y1 += UI_BOX_TB_BORDER; - - // is favorite? draw the star - if (isstar) - draw_star(x1, y1); - - // draw all lines - for (auto & elem : tempbuf) - { - mui.draw_text_full(container, elem.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER, - DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); - y1 += machine().ui().get_line_height(); - } -} - -//------------------------------------------------- -// handle select key event -//------------------------------------------------- - -void ui_menu_select_software::inkey_select(const ui_menu_event *m_event) -{ - ui_software_info *ui_swinfo = (ui_software_info *)m_event->itemref; - ui_options &mopt = machine().ui().options(); - - if (ui_swinfo->startempty == 1) - { - std::vector<s_bios> biosname; - if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname)) - ui_menu::stack_push(global_alloc_clear<ui_bios_selection>(machine(), 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); - machine().manager().schedule_new_driver(*ui_swinfo->driver); - machine().schedule_hard_reset(); - ui_menu::stack_reset(machine()); - } - } - - else - { - // first validate - driver_enumerator drivlist(machine().options(), *ui_swinfo->driver); - media_auditor auditor(drivlist); - drivlist.next(); - software_list_device *swlist = software_list_device::find_by_name(drivlist.config(), ui_swinfo->listname.c_str()); - software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str()); - - media_auditor::summary 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) - { - std::vector<s_bios> biosname; - if (!mopt.skip_bios_menu() && has_multiple_bios(ui_swinfo->driver, biosname)) - { - ui_menu::stack_push(global_alloc_clear<ui_bios_selection>(machine(), container, biosname, (void *)ui_swinfo, true, false)); - return; - } - else if (!mopt.skip_parts_menu() && swinfo->has_multiple_parts(ui_swinfo->interface.c_str())) - { - std::unordered_map<std::string, std::string> parts; - for (const software_part *swpart = swinfo->first_part(); swpart != nullptr; swpart = swpart->next()) - { - 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); - } - } - ui_menu::stack_push(global_alloc_clear<ui_software_parts>(machine(), container, parts, ui_swinfo)); - return; - } - std::string error_string; - std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance); - machine().options().set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); - 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, error_string); - reselect_last::driver = drivlist.driver().name; - reselect_last::software = ui_swinfo->shortname; - reselect_last::swlist = ui_swinfo->listname; - reselect_last::set(true); - machine().manager().schedule_new_driver(drivlist.driver()); - machine().schedule_hard_reset(); - ui_menu::stack_reset(machine()); - } - - // otherwise, display an error - else - { - reset(UI_MENU_RESET_REMEMBER_POSITION); - ui_error = true; - } - } -} - -//------------------------------------------------- -// handle special key event -//------------------------------------------------- - -void ui_menu_select_software::inkey_special(const ui_menu_event *m_event) -{ - int buflen = strlen(m_search); - - // if it's a backspace and we can handle it, do so - if ((m_event->unichar == 8 || m_event->unichar == 0x7f) && buflen > 0) - { - *(char *)utf8_previous_char(&m_search[buflen]) = 0; - reset(UI_MENU_RESET_SELECT_FIRST); - } - - // if it's any other key and we're not maxed out, update - else if (m_event->unichar >= ' ' && m_event->unichar < 0x7f) - { - buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, m_event->unichar); - m_search[buflen] = 0; - reset(UI_MENU_RESET_SELECT_FIRST); - } -} - -//------------------------------------------------- -// load custom filters info from file -//------------------------------------------------- - -void ui_menu_select_software::load_sw_custom_filters() -{ - // attempt to open the output file - emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_READ); - if (file.open("custom_", m_driver->name, "_filter.ini") == FILERR_NONE) - { - char buffer[MAX_CHAR_INFO]; - - // get number of filters - file.gets(buffer, MAX_CHAR_INFO); - char *pb = strchr(buffer, '='); - sw_custfltr::numother = atoi(++pb) - 1; - - // get main filter - file.gets(buffer, MAX_CHAR_INFO); - pb = strchr(buffer, '=') + 2; - - for (int y = 0; y < sw_filters::length; ++y) - if (!strncmp(pb, sw_filters::text[y], strlen(sw_filters::text[y]))) - { - sw_custfltr::main = y; - break; - } - - for (int x = 1; x <= sw_custfltr::numother; ++x) - { - file.gets(buffer, MAX_CHAR_INFO); - char *cb = strchr(buffer, '=') + 2; - for (int y = 0; y < sw_filters::length; y++) - { - if (!strncmp(cb, sw_filters::text[y], strlen(sw_filters::text[y]))) - { - sw_custfltr::other[x] = y; - if (y == UI_SW_PUBLISHERS) - { - file.gets(buffer, MAX_CHAR_INFO); - char *ab = strchr(buffer, '=') + 2; - for (size_t z = 0; z < m_filter.publisher.ui.size(); ++z) - if (!strncmp(ab, m_filter.publisher.ui[z].c_str(), m_filter.publisher.ui[z].length())) - sw_custfltr::mnfct[x] = z; - } - else if (y == UI_SW_YEARS) - { - file.gets(buffer, MAX_CHAR_INFO); - char *db = strchr(buffer, '=') + 2; - for (size_t z = 0; z < m_filter.year.ui.size(); ++z) - if (!strncmp(db, m_filter.year.ui[z].c_str(), m_filter.year.ui[z].length())) - sw_custfltr::year[x] = z; - } - else if (y == UI_SW_LIST) - { - file.gets(buffer, MAX_CHAR_INFO); - char *gb = strchr(buffer, '=') + 2; - for (size_t z = 0; z < m_filter.swlist.name.size(); ++z) - if (!strncmp(gb, m_filter.swlist.name[z].c_str(), m_filter.swlist.name[z].length())) - sw_custfltr::list[x] = z; - } - else if (y == UI_SW_TYPE) - { - file.gets(buffer, MAX_CHAR_INFO); - char *fb = strchr(buffer, '=') + 2; - for (size_t z = 0; z < m_filter.type.ui.size(); ++z) - if (!strncmp(fb, m_filter.type.ui[z].c_str(), m_filter.type.ui[z].length())) - sw_custfltr::type[x] = z; - } - else if (y == UI_SW_REGION) - { - file.gets(buffer, MAX_CHAR_INFO); - char *eb = strchr(buffer, '=') + 2; - for (size_t z = 0; z < m_filter.region.ui.size(); ++z) - if (!strncmp(eb, m_filter.region.ui[z].c_str(), m_filter.region.ui[z].length())) - sw_custfltr::region[x] = z; - } - } - } - } - file.close(); - } -} - -//------------------------------------------------- -// set software regions -//------------------------------------------------- - -void c_sw_region::set(std::string &str) -{ - std::string name = getname(str); - if (std::find(ui.begin(), ui.end(), name) != ui.end()) - return; - - ui.push_back(name); -} - -std::string c_sw_region::getname(std::string &str) -{ - std::string fullname(str); - strmakelower(fullname); - size_t found = fullname.find("("); - - if (found != std::string::npos) - { - size_t ends = fullname.find_first_not_of("abcdefghijklmnopqrstuvwxyz", found + 1); - std::string temp(fullname.substr(found + 1, ends - found - 1)); - - for (auto & elem : region_lists) - if (temp == elem) - return (str.substr(found + 1, ends - found - 1)); - } - return std::string("<none>"); -} - -//------------------------------------------------- -// set software device type -//------------------------------------------------- - -void c_sw_type::set(std::string &str) -{ - if (std::find(ui.begin(), ui.end(), str) != ui.end()) - return; - - ui.push_back(str); -} - -//------------------------------------------------- -// set software years -//------------------------------------------------- - -void c_sw_year::set(std::string &str) -{ - if (std::find(ui.begin(), ui.end(), str) != ui.end()) - return; - - ui.push_back(str); -} - -//------------------------------------------------- -// set software publishers -//------------------------------------------------- - -void c_sw_publisher::set(std::string &str) -{ - std::string name = getname(str); - if (std::find(ui.begin(), ui.end(), name) != ui.end()) - return; - - ui.push_back(name); -} - -std::string c_sw_publisher::getname(std::string &str) -{ - size_t found = str.find("("); - - if (found != std::string::npos) - return (str.substr(0, found - 1)); - else - return str; -} - -//------------------------------------------------- -// build display list -//------------------------------------------------- -void ui_menu_select_software::build_list(std::vector<ui_software_info *> &s_drivers, const char *filter_text, int filter) -{ - - if (s_drivers.empty() && filter == -1) - { - filter = sw_filters::actual; - s_drivers = m_sortedlist; - } - - // iterate over entries - for (auto & s_driver : s_drivers) - { - switch (filter) - { - case UI_SW_PARENTS: - if (s_driver->parentname.empty()) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_CLONES: - if (!s_driver->parentname.empty()) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_AVAILABLE: - if (s_driver->available) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_UNAVAILABLE: - if (!s_driver->available) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_SUPPORTED: - if (s_driver->supported == SOFTWARE_SUPPORTED_YES) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_PARTIAL_SUPPORTED: - if (s_driver->supported == SOFTWARE_SUPPORTED_PARTIAL) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_UNSUPPORTED: - if (s_driver->supported == SOFTWARE_SUPPORTED_NO) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_REGION: - { - std::string name = m_filter.region.getname(s_driver->longname); - - if(!name.empty() && name == filter_text) - m_displaylist.push_back(s_driver); - break; - } - - case UI_SW_PUBLISHERS: - { - std::string name = m_filter.publisher.getname(s_driver->publisher); - - if(!name.empty() && name == filter_text) - m_displaylist.push_back(s_driver); - break; - } - - case UI_SW_YEARS: - if(s_driver->year == filter_text) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_LIST: - if(s_driver->listname == filter_text) - m_displaylist.push_back(s_driver); - break; - - case UI_SW_TYPE: - if(s_driver->devicetype == filter_text) - m_displaylist.push_back(s_driver); - break; - - default: - m_displaylist.push_back(s_driver); - break; - } - } -} - -//------------------------------------------------- -// find approximate matches -//------------------------------------------------- - -void ui_menu_select_software::find_matches(const char *str, int count) -{ - // allocate memory to track the penalty value - std::vector<int> penalty(count, 9999); - int index = 0; - - for (; m_displaylist[index]; ++index) - { - // pick the best match between driver name and description - int curpenalty = fuzzy_substring(str, m_displaylist[index]->longname); - int tmp = fuzzy_substring(str, m_displaylist[index]->shortname); - curpenalty = MIN(curpenalty, tmp); - - // insert into the sorted table of matches - for (int matchnum = count - 1; matchnum >= 0; --matchnum) - { - // 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 < count - 1) - { - penalty[matchnum + 1] = penalty[matchnum]; - m_searchlist[matchnum + 1] = m_searchlist[matchnum]; - } - - m_searchlist[matchnum] = m_displaylist[index]; - penalty[matchnum] = curpenalty; - } - } - (index < count) ? m_searchlist[index] = nullptr : m_searchlist[count] = nullptr; -} - -//------------------------------------------------- -// build custom display list -//------------------------------------------------- - -void ui_menu_select_software::build_custom() -{ - std::vector<ui_software_info *> s_drivers; - - build_list(m_sortedlist, nullptr, sw_custfltr::main); - - for (int count = 1; count <= sw_custfltr::numother; ++count) - { - int filter = sw_custfltr::other[count]; - s_drivers = m_displaylist; - m_displaylist.clear(); - - switch (filter) - { - case UI_SW_YEARS: - build_list(s_drivers, m_filter.year.ui[sw_custfltr::year[count]].c_str(), filter); - break; - case UI_SW_LIST: - build_list(s_drivers, m_filter.swlist.name[sw_custfltr::list[count]].c_str(), filter); - break; - case UI_SW_TYPE: - build_list(s_drivers, m_filter.type.ui[sw_custfltr::type[count]].c_str(), filter); - break; - case UI_SW_PUBLISHERS: - build_list(s_drivers, m_filter.publisher.ui[sw_custfltr::mnfct[count]].c_str(), filter); - break; - case UI_SW_REGION: - build_list(s_drivers, m_filter.region.ui[sw_custfltr::region[count]].c_str(), filter); - break; - default: - build_list(s_drivers, nullptr, filter); - break; - } - } -} - -//------------------------------------------------- -// draw left box -//------------------------------------------------- - -float ui_menu_select_software::draw_left_panel(float x1, float y1, float x2, float y2) -{ - ui_manager &mui = machine().ui(); - - if (ui_globals::panels_status == SHOW_PANELS || ui_globals::panels_status == HIDE_RIGHT_PANEL) - { - float origy1 = y1; - float origy2 = y2; - float text_size = 0.75f; - float l_height = mui.get_line_height(); - float line_height = l_height * text_size; - float left_width = 0.0f; - int text_lenght = sw_filters::length; - int afilter = sw_filters::actual; - int phover = HOVER_SW_FILTER_FIRST; - const char **text = sw_filters::text; - float sc = y2 - y1 - (2.0f * UI_BOX_TB_BORDER); - - if ((text_lenght * line_height) > sc) - { - float lm = sc / (text_lenght); - text_size = lm / l_height; - line_height = l_height * text_size; - } - - float text_sign = mui.get_string_width_ex("_# ", text_size); - for (int x = 0; x < text_lenght; ++x) - { - float total_width; - - // compute width of left hand side - total_width = mui.get_string_width_ex(text[x], text_size); - total_width += text_sign; - - // track the maximum - if (total_width > left_width) - left_width = total_width; - } - - x2 = x1 + left_width + 2.0f * UI_BOX_LR_BORDER; - //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B)); - mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - - // take off the borders - x1 += UI_BOX_LR_BORDER; - x2 -= UI_BOX_LR_BORDER; - y1 += UI_BOX_TB_BORDER; - y2 -= UI_BOX_TB_BORDER; - - for (int filter = 0; filter < text_lenght; ++filter) - { - std::string str(text[filter]); - rgb_t bgcolor = UI_TEXT_BG_COLOR; - rgb_t fgcolor = UI_TEXT_COLOR; - - if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y1 + line_height > mouse_y) - { - bgcolor = UI_MOUSEOVER_BG_COLOR; - fgcolor = UI_MOUSEOVER_COLOR; - hover = phover + filter; - } - - if (afilter == filter) - { - bgcolor = UI_SELECTED_BG_COLOR; - fgcolor = UI_SELECTED_COLOR; - } - - if (bgcolor != UI_TEXT_BG_COLOR) - container->add_rect(x1, y1, x2, y1 + line_height, bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); - - float x1t = x1 + text_sign; - if (afilter == UI_SW_CUSTOM) - { - if (filter == sw_custfltr::main) - { - str.assign("@custom1 ").append(text[filter]); - x1t -= text_sign; - } - else - { - for (int count = 1; count <= sw_custfltr::numother; ++count) - { - int cfilter = sw_custfltr::other[count]; - if (cfilter == filter) - { - strprintf(str, "@custom%d %s", count + 1, text[filter]); - x1t -= text_sign; - break; - } - } - } - convert_command_glyph(str); - } - - mui.draw_text_full(container, str.c_str(), x1t, y1, x2 - x1, JUSTIFY_LEFT, WRAP_NEVER, - DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size); - y1 += line_height; - } - - x1 = x2 + UI_BOX_LR_BORDER; - x2 = x1 + 2.0f * UI_BOX_LR_BORDER; - y1 = origy1; - y2 = origy2; - line_height = mui.get_line_height(); - float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect(); - rgb_t fgcolor = UI_TEXT_COLOR; - - // set left-right arrows dimension - float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width; - float ar_y0 = 0.5f * (y2 + y1) + 0.1f * line_height; - float ar_x1 = ar_x0 + lr_arrow_width; - float ar_y1 = 0.5f * (y2 + y1) + 0.9f * line_height; - - //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B)); - - if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y) - { - fgcolor = UI_MOUSEOVER_COLOR; - hover = HOVER_LPANEL_ARROW; - } - - draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X); - return x2 + UI_BOX_LR_BORDER; - } - else - { - float line_height = mui.get_line_height(); - float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect(); - rgb_t fgcolor = UI_TEXT_COLOR; - - // set left-right arrows dimension - float ar_x0 = 0.5f * (x2 + x1) - 0.5f * lr_arrow_width; - float ar_y0 = 0.5f * (y2 + y1) + 0.1f * line_height; - float ar_x1 = ar_x0 + lr_arrow_width; - float ar_y1 = 0.5f * (y2 + y1) + 0.9f * line_height; - - //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B)); - - if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y) - { - fgcolor = UI_MOUSEOVER_COLOR; - hover = HOVER_LPANEL_ARROW; - } - - draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90); - return x2 + UI_BOX_LR_BORDER; - } -} - -//------------------------------------------------- -// draw infos -//------------------------------------------------- - -void ui_menu_select_software::infos_render(void *selectedref, float origx1, float origy1, float origx2, float origy2) -{ - ui_manager &mui = machine().ui(); - float line_height = mui.get_line_height(); - static std::string buffer; - std::vector<int> xstart; - std::vector<int> xend; - float text_size = machine().ui().options().infos_size(); - ui_software_info *soft = (ui_software_info *)selectedref; - static ui_software_info *oldsoft = nullptr; - static int old_sw_view = -1; - - float gutter_width = 0.4f * line_height * machine().render().ui_aspect() * 1.3f; - float ud_arrow_width = line_height * machine().render().ui_aspect(); - float oy1 = origy1 + line_height; - - // apply title to right panel - if (soft && soft->usage.empty()) - { - mui.draw_text_full(container, "History", origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); - ui_globals::cur_sw_dats_view = 0; - } - else - { - float title_size = 0.0f; - float txt_lenght = 0.0f; - std::string t_text[2]; - t_text[0] = "History"; - t_text[1] = "Usage"; - - for (auto & elem : t_text) - { - mui.draw_text_full(container, elem.c_str(), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_lenght, nullptr); - txt_lenght += 0.01f; - title_size = MAX(txt_lenght, title_size); - } - - mui.draw_text_full(container, t_text[ui_globals::cur_sw_dats_view].c_str(), origx1, origy1, origx2 - origx1, - JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, - nullptr, nullptr); - - draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::cur_sw_dats_view, 0, 1, title_size); - } - - if (oldsoft != soft || old_sw_view != ui_globals::cur_sw_dats_view) - { - buffer.clear(); - old_sw_view = ui_globals::cur_sw_dats_view; - oldsoft = soft; - if (ui_globals::cur_sw_dats_view == 0) - { - if (soft->startempty == 1) - machine().datfile().load_data_info(soft->driver, buffer, UI_HISTORY_LOAD); - else - machine().datfile().load_software_info(soft->listname, buffer, soft->shortname, soft->parentname); - } - else - buffer = soft->usage; - } - - if (buffer.empty()) - { - mui.draw_text_full(container, "No Infos Available", origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, JUSTIFY_CENTER, - WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); - return; - } - else - totallines = mui.wrap_text(container, buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size); - - int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size)); - if (totallines < r_visible_lines) - r_visible_lines = totallines; - if (topline_datsview < 0) - topline_datsview = 0; - if (topline_datsview + r_visible_lines >= totallines) - topline_datsview = totallines - r_visible_lines; - - for (int r = 0; r < r_visible_lines; ++r) - { - int itemline = r + topline_datsview; - std::string tempbuf; - tempbuf.assign(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline])); - - // up arrow - if (r == 0 && topline_datsview != 0) - info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width); - // bottom arrow - else if (r == r_visible_lines - 1 && itemline != totallines - 1) - info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width); - else - mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, - JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, - nullptr, nullptr, text_size); - oy1 += (line_height * text_size); - } - - // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - right_visible_lines = r_visible_lines - (topline_datsview != 0) - (topline_datsview + r_visible_lines != totallines); -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void ui_menu_select_software::arts_render(void *selectedref, float origx1, float origy1, float origx2, float origy2) -{ - ui_manager &mui = machine().ui(); - float line_height = mui.get_line_height(); - static ui_software_info *oldsoft = nullptr; - static const game_driver *olddriver = nullptr; - const game_driver *driver = nullptr; - ui_software_info *soft = (ui_software_info *)selectedref; - - if (soft && soft->startempty == 1) - { - driver = soft->driver; - oldsoft = nullptr; - } - else - olddriver = nullptr; - - if (driver) - { - if (ui_globals::default_image) - ((driver->flags & MACHINE_TYPE_ARCADE) == 0) ? ui_globals::curimage_view = CABINETS_VIEW : ui_globals::curimage_view = SNAPSHOT_VIEW; - - std::string searchstr; - searchstr = arts_render_common(origx1, origy1, origx2, origy2); - - // loads the image if necessary - if (driver != olddriver || !snapx_bitmap->valid() || ui_globals::switch_image) - { - emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ); - bitmap_argb32 *tmp_bitmap; - tmp_bitmap = auto_alloc(machine(), bitmap_argb32); - - // try to load snapshot first from saved "0000.png" file - std::string fullname(driver->name); - render_load_png(*tmp_bitmap, snapfile, fullname.c_str(), "0000.png"); - - if (!tmp_bitmap->valid()) - render_load_jpeg(*tmp_bitmap, snapfile, fullname.c_str(), "0000.jpg"); - - // if fail, attemp to load from standard file - if (!tmp_bitmap->valid()) - { - fullname.assign(driver->name).append(".png"); - render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str()); - - if (!tmp_bitmap->valid()) - { - fullname.assign(driver->name).append(".jpg"); - render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str()); - } - } - - // if fail again, attemp to load from parent file - if (!tmp_bitmap->valid()) - { - // set clone status - bool cloneof = strcmp(driver->parent, "0"); - if (cloneof) - { - int cx = driver_list::find(driver->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)) - cloneof = false; - } - - if (cloneof) - { - fullname.assign(driver->parent).append(".png"); - render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str()); - - if (!tmp_bitmap->valid()) - { - fullname.assign(driver->parent).append(".jpg"); - render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str()); - } - } - } - - olddriver = driver; - ui_globals::switch_image = false; - arts_render_images(tmp_bitmap, origx1, origy1, origx2, origy2, false); - auto_free(machine(), tmp_bitmap); - } - - // if the image is available, loaded and valid, display it - if (snapx_bitmap->valid()) - { - float x1 = origx1 + 0.01f; - float x2 = origx2 - 0.01f; - float y1 = origy1 + UI_BOX_TB_BORDER + line_height; - float y2 = origy2 - UI_BOX_TB_BORDER - line_height; - - // apply texture - container->add_quad( x1, y1, x2, y2, ARGB_WHITE, snapx_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - } - } - else if (soft) - { - std::string fullname, pathname; - if (ui_globals::default_image) - (soft->startempty == 0) ? ui_globals::curimage_view = SNAPSHOT_VIEW : ui_globals::curimage_view = CABINETS_VIEW; - - // arts title and searchpath - std::string searchstr; - searchstr = arts_render_common(origx1, origy1, origx2, origy2); - - // loads the image if necessary - if (soft != oldsoft || !snapx_bitmap->valid() || ui_globals::switch_image) - { - emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ); - bitmap_argb32 *tmp_bitmap; - tmp_bitmap = auto_alloc(machine(), bitmap_argb32); - - if (soft->startempty == 1) - { - // Load driver snapshot - fullname.assign(soft->driver->name).append(".png"); - render_load_png(*tmp_bitmap, snapfile, nullptr, fullname.c_str()); - - if (!tmp_bitmap->valid()) - { - fullname.assign(soft->driver->name).append(".jpg"); - render_load_jpeg(*tmp_bitmap, snapfile, nullptr, fullname.c_str()); - } - } - else if (ui_globals::curimage_view == TITLES_VIEW) - { - // First attempt from name list - pathname.assign(soft->listname).append("_titles"); - fullname.assign(soft->shortname).append(".png"); - render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); - - if (!tmp_bitmap->valid()) - { - fullname.assign(soft->shortname).append(".jpg"); - render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); - } - } - else - { - // First attempt from name list - pathname = soft->listname; - fullname.assign(soft->shortname).append(".png"); - render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); - - if (!tmp_bitmap->valid()) - { - fullname.assign(soft->shortname).append(".jpg"); - render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); - } - - if (!tmp_bitmap->valid()) - { - // Second attempt from driver name + part name - pathname.assign(soft->driver->name).append(soft->part); - fullname.assign(soft->shortname).append(".png"); - render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); - - if (!tmp_bitmap->valid()) - { - fullname.assign(soft->shortname).append(".jpg"); - render_load_jpeg(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str()); - } - } - } - - oldsoft = soft; - ui_globals::switch_image = false; - arts_render_images(tmp_bitmap, origx1, origy1, origx2, origy2, true); - auto_free(machine(), tmp_bitmap); - } - - // if the image is available, loaded and valid, display it - if (snapx_bitmap->valid()) - { - float x1 = origx1 + 0.01f; - float x2 = origx2 - 0.01f; - float y1 = origy1 + UI_BOX_TB_BORDER + line_height; - float y2 = origy2 - UI_BOX_TB_BORDER - line_height; - - // apply texture - container->add_quad(x1, y1, x2, y2, ARGB_WHITE, snapx_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - } - } -} - -void ui_menu_select_software::draw_right_panel(void *selectedref, float origx1, float origy1, float origx2, float origy2) -{ - ui_manager &mui = machine().ui(); - float line_height = mui.get_line_height(); - float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect(); - rgb_t fgcolor = UI_TEXT_COLOR; - bool hide = (ui_globals::panels_status == HIDE_RIGHT_PANEL || ui_globals::panels_status == HIDE_BOTH); - float x2 = (hide) ? origx2 : origx1 + 2.0f * UI_BOX_LR_BORDER; - - // set left-right arrows dimension - float ar_x0 = 0.5f * (x2 + origx1) - 0.5f * lr_arrow_width; - float ar_y0 = 0.5f * (origy2 + origy1) + 0.1f * line_height; - float ar_x1 = ar_x0 + lr_arrow_width; - float ar_y1 = 0.5f * (origy2 + origy1) + 0.9f * line_height; - - //machine().ui().draw_outlined_box(container, origx1, origy1, origx2, origy2, UI_BACKGROUND_COLOR); - mui.draw_outlined_box(container, origx1, origy1, origx2, origy2, rgb_t(0xEF, 0x12, 0x47, 0x7B)); - - if (mouse_hit && origx1 <= mouse_x && x2 > mouse_x && origy1 <= mouse_y && origy2 > mouse_y) - { - fgcolor = UI_MOUSEOVER_COLOR; - hover = HOVER_RPANEL_ARROW; - } - - if (hide) - { - draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90 ^ ORIENTATION_FLIP_X); - return; - } - - draw_arrow(container, ar_x0, ar_y0, ar_x1, ar_y1, fgcolor, ROT90); - origx1 = x2; - origy1 = draw_right_box_title(origx1, origy1, origx2, origy2); - - if (ui_globals::rpanel == RP_IMAGES) - arts_render(selectedref, origx1, origy1, origx2, origy2); - else - infos_render(selectedref, origx1, origy1, origx2, origy2); -} - -//------------------------------------------------- -// ctor -//------------------------------------------------- - -ui_software_parts::ui_software_parts(running_machine &machine, render_container *container, std::unordered_map<std::string, std::string> parts, ui_software_info *ui_info) : ui_menu(machine, container) -{ - m_parts = parts; - m_uiinfo = ui_info; -} - -//------------------------------------------------- -// dtor -//------------------------------------------------- - -ui_software_parts::~ui_software_parts() -{ -} - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void ui_software_parts::populate() -{ - for (auto & elem : m_parts) - item_append(elem.first.c_str(), elem.second.c_str(), 0, (void *)&elem); - - item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); - customtop = machine().ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER); -} - -//------------------------------------------------- -// handle -//------------------------------------------------- - -void ui_software_parts::handle() -{ - // process the menu - const ui_menu_event *event = process(0); - if (event != nullptr && event->iptkey == IPT_UI_SELECT && event->itemref != nullptr) - for (auto & elem : m_parts) - if ((void*)&elem == event->itemref) - { - std::string error_string; - 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, error_string); - - 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, error_string); - - machine().manager().schedule_new_driver(*m_uiinfo->driver); - machine().schedule_hard_reset(); - ui_menu::stack_reset(machine()); - } -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void ui_software_parts::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - float width; - ui_manager &mui = machine().ui(); - mui.draw_text_full(container, "Software part selection:", 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - float maxwidth = 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 - mui.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 - mui.draw_text_full(container, "Software part selection:", x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); -} - -//------------------------------------------------- -// ctor -//------------------------------------------------- - -ui_bios_selection::ui_bios_selection(running_machine &machine, render_container *container, std::vector<s_bios> biosname, void *_driver, bool _software, bool _inlist) : ui_menu(machine, container) -{ - m_bios = biosname; - m_driver = _driver; - m_software = _software; - m_inlist = _inlist; -} - -//------------------------------------------------- -// dtor -//------------------------------------------------- - -ui_bios_selection::~ui_bios_selection() -{ -} - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void ui_bios_selection::populate() -{ - for (auto & elem : m_bios) - item_append(elem.name.c_str(), nullptr, 0, (void *)&elem.name); - - item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); - customtop = machine().ui().get_line_height() + (3.0f * UI_BOX_TB_BORDER); -} - -//------------------------------------------------- -// handle -//------------------------------------------------- - -void ui_bios_selection::handle() -{ - // process the menu - const ui_menu_event *event = process(0); - ui_options &moptions = machine().ui().options(); - if (event != nullptr && event->iptkey == IPT_UI_SELECT && event->itemref != nullptr) - for (auto & elem : m_bios) - if ((void*)&elem.name == 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); - } - - std::string error; - moptions.set_value("bios", elem.id, OPTION_PRIORITY_CMDLINE, error); - machine().manager().schedule_new_driver(*s_driver); - machine().schedule_hard_reset(); - ui_menu::stack_reset(machine()); - } - else - { - ui_software_info *ui_swinfo = (ui_software_info *)m_driver; - std::string error; - machine().options().set_value("bios", elem.id, OPTION_PRIORITY_CMDLINE, error); - 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()); - software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str()); - if (!moptions.skip_parts_menu() && swinfo->has_multiple_parts(ui_swinfo->interface.c_str())) - { - std::unordered_map<std::string, std::string> parts; - for (const software_part *swpart = swinfo->first_part(); swpart != nullptr; swpart = swpart->next()) - { - 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); - } - } - ui_menu::stack_push(global_alloc_clear<ui_software_parts>(machine(), container, parts, ui_swinfo)); - return; - } - std::string error_string; - std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance); - moptions.set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); - std::string snap_list = std::string(ui_swinfo->listname).append(PATH_SEPARATOR).append(ui_swinfo->shortname); - moptions.set_value(OPTION_SNAPNAME, snap_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string); - reselect_last::driver = drivlist.driver().name; - reselect_last::software = ui_swinfo->shortname; - reselect_last::swlist = ui_swinfo->listname; - reselect_last::set(true); - machine().manager().schedule_new_driver(drivlist.driver()); - machine().schedule_hard_reset(); - ui_menu::stack_reset(machine()); - } - } -} - -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void ui_bios_selection::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - float width; - ui_manager &mui = machine().ui(); - mui.draw_text_full(container, "Bios selection:", 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - float maxwidth = 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 - mui.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 - mui.draw_text_full(container, "Bios selection:", x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); -} |