diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/frontend/mame/ui/datfile.cpp | 199 | ||||
-rw-r--r-- | src/frontend/mame/ui/datfile.h | 49 | ||||
-rw-r--r-- | src/frontend/mame/ui/inifile.cpp | 2 | ||||
-rw-r--r-- | src/frontend/mame/ui/inifile.h | 10 | ||||
-rw-r--r-- | src/frontend/mame/ui/selgame.cpp | 659 | ||||
-rw-r--r-- | src/frontend/mame/ui/selgame.h | 15 | ||||
-rw-r--r-- | src/frontend/mame/ui/selmenu.cpp | 360 | ||||
-rw-r--r-- | src/frontend/mame/ui/selmenu.h | 40 | ||||
-rw-r--r-- | src/frontend/mame/ui/selsoft.cpp | 332 | ||||
-rw-r--r-- | src/frontend/mame/ui/selsoft.h | 7 |
10 files changed, 733 insertions, 940 deletions
diff --git a/src/frontend/mame/ui/datfile.cpp b/src/frontend/mame/ui/datfile.cpp index d5c77e30893..17552f34d68 100644 --- a/src/frontend/mame/ui/datfile.cpp +++ b/src/frontend/mame/ui/datfile.cpp @@ -9,11 +9,15 @@ ***************************************************************************/ #include "emu.h" +#include "ui/datfile.h" + #include "drivenum.h" #include "ui/moptions.h" -#include "ui/datfile.h" #include "ui/utils.h" +#include <utility> + + namespace ui { namespace { //------------------------------------------------- @@ -59,7 +63,7 @@ std::string datfile_manager::m_story_rev; std::string datfile_manager::m_ginit_rev; bool datfile_manager::first_run = true; -#define opendatsfile(f) if (parseopen(#f".dat")) { init_##f(); parseclose(); } +#define opendatsfile(f) do { fileptr datfile = parseopen(#f".dat"); if (datfile) init_##f(std::move(datfile)); } while (false) //------------------------------------------------- // ctor @@ -84,10 +88,10 @@ datfile_manager::datfile_manager(running_machine &machine, ui_options &moptions) //------------------------------------------------- // initialize sysinfo.dat index //------------------------------------------------- -void datfile_manager::init_sysinfo() +void datfile_manager::init_sysinfo(fileptr &&fp) { int swcount = 0; - auto count = index_datafile(m_sysidx, swcount, m_sysinfo_rev, TAG_SYSINFO_R, '.'); + auto count = index_datafile(std::move(fp), m_sysidx, swcount, m_sysinfo_rev, TAG_SYSINFO_R, '.'); osd_printf_verbose("Sysinfo.dat games found = %i\n", count); osd_printf_verbose("Rev = %s\n", m_sysinfo_rev.c_str()); } @@ -95,20 +99,20 @@ void datfile_manager::init_sysinfo() //------------------------------------------------- // initialize story.dat index //------------------------------------------------- -void datfile_manager::init_story() +void datfile_manager::init_story(fileptr &&fp) { int swcount = 0; - auto count = index_datafile(m_storyidx, swcount, m_story_rev, TAG_STORY_R, 's'); + auto count = index_datafile(std::move(fp), m_storyidx, swcount, m_story_rev, TAG_STORY_R, 's'); osd_printf_verbose("Story.dat games found = %i\n", count); } //------------------------------------------------- // initialize history.dat index //------------------------------------------------- -void datfile_manager::init_history() +void datfile_manager::init_history(fileptr &&fp) { int swcount = 0; - auto count = index_datafile(m_histidx, swcount, m_history_rev, TAG_HISTORY_R, ' '); + auto count = index_datafile(std::move(fp), m_histidx, swcount, m_history_rev, TAG_HISTORY_R, ' '); osd_printf_verbose("History.dat systems found = %i\n", count); osd_printf_verbose("History.dat software packages found = %i\n", swcount); osd_printf_verbose("Rev = %s\n", m_history_rev.c_str()); @@ -117,11 +121,11 @@ void datfile_manager::init_history() //------------------------------------------------- // initialize gameinit.dat index //------------------------------------------------- -void datfile_manager::init_gameinit() +void datfile_manager::init_gameinit(fileptr &&fp) { int swcount = 0; drvindex tmp; - auto count = index_mame_mess_info(m_ginitidx, tmp, swcount); + auto count = index_mame_mess_info(std::move(fp), m_ginitidx, tmp, swcount); osd_printf_verbose("Gameinit.dat games found = %i\n", count); osd_printf_verbose("Rev = %s\n", m_ginit_rev.c_str()); } @@ -129,10 +133,10 @@ void datfile_manager::init_gameinit() //------------------------------------------------- // initialize mameinfo.dat index //------------------------------------------------- -void datfile_manager::init_mameinfo() +void datfile_manager::init_mameinfo(fileptr &&fp) { int drvcount = 0; - auto count = index_mame_mess_info(m_mameidx, m_drvidx, drvcount); + auto count = index_mame_mess_info(std::move(fp), m_mameidx, m_drvidx, drvcount); osd_printf_verbose("Mameinfo.dat games found = %i\n", count); osd_printf_verbose("Mameinfo.dat drivers found = %d\n", drvcount); osd_printf_verbose("Rev = %s\n", m_mame_rev.c_str()); @@ -141,10 +145,10 @@ void datfile_manager::init_mameinfo() //------------------------------------------------- // initialize messinfo.dat index //------------------------------------------------- -void datfile_manager::init_messinfo() +void datfile_manager::init_messinfo(fileptr &&fp) { int drvcount = 0; - auto count = index_mame_mess_info(m_messidx, m_messdrvidx, drvcount); + auto count = index_mame_mess_info(std::move(fp), m_messidx, m_messdrvidx, drvcount); osd_printf_verbose("Messinfo.dat games found = %i\n", count); osd_printf_verbose("Messinfo.dat drivers found = %d\n", drvcount); osd_printf_verbose("Rev = %s\n", m_mess_rev.c_str()); @@ -153,26 +157,31 @@ void datfile_manager::init_messinfo() //------------------------------------------------- // initialize command.dat index //------------------------------------------------- -void datfile_manager::init_command() +void datfile_manager::init_command(fileptr &&fp) { int swcount = 0; std::string tmp; - auto count = index_datafile(m_cmdidx, swcount, tmp, std::string(), 'c'); + auto count = index_datafile(std::move(fp), m_cmdidx, swcount, tmp, std::string(), 'c'); osd_printf_verbose("Command.dat games found = %i\n", count); } -bool datfile_manager::has_software(std::string const &softlist, std::string const &softname, std::string const &parentname) +bool datfile_manager::has_software(std::string const &softlist, std::string const &softname, std::string const &parentname) const +{ + return bool(find_software(softlist, softname, parentname)); +} + +long const *datfile_manager::find_software(std::string const &softlist, std::string const &softname, std::string const &parentname) const { // Find software in software list index - auto const found(m_swindex.find(softlist)); - if (found == m_swindex.end()) - return false; + auto const software(m_swindex.find(softlist)); + if (software == m_swindex.end()) + return nullptr; - m_itemsiter = found->second.find(softname); - if ((m_itemsiter == found->second.end()) && !parentname.empty()) - m_itemsiter = found->second.find(parentname); + auto itemsiter = software->second.find(softname); + if ((itemsiter == software->second.end()) && !parentname.empty()) + itemsiter = software->second.find(parentname); - return m_itemsiter != found->second.end(); + return (itemsiter != software->second.end()) ? &itemsiter->second : nullptr; } //------------------------------------------------- @@ -180,18 +189,22 @@ bool datfile_manager::has_software(std::string const &softlist, std::string cons //------------------------------------------------- void datfile_manager::load_software_info(std::string const &softlist, std::string &buffer, std::string const &softname, std::string const &parentname) { + if (m_swindex.empty()) + return; + // Load history text - if (!m_swindex.empty() && parseopen("history.dat")) + fileptr const datfile = parseopen("history.dat"); + if (datfile) { // Find software in software list index - if (!has_software(softlist, softname, parentname)) + long const *const s_offset = find_software(softlist, softname, parentname); + if (!s_offset) return; - auto s_offset = m_itemsiter->second; char rbuf[64 * 1024]; - fseek(fp, s_offset, SEEK_SET); + std::fseek(datfile.get(), *s_offset, SEEK_SET); std::string readbuf; - while (fgets(rbuf, 64 * 1024, fp) != nullptr) + while (std::fgets(rbuf, 64 * 1024, datfile.get()) != nullptr) { readbuf = chartrimcarriage(rbuf); @@ -202,7 +215,6 @@ void datfile_manager::load_software_info(std::string const &softlist, std::strin // add this string to the buffer buffer.append(readbuf).append("\n"); } - parseclose(); } } @@ -211,66 +223,69 @@ void datfile_manager::load_software_info(std::string const &softlist, std::strin //------------------------------------------------- void datfile_manager::load_data_info(const game_driver *drv, std::string &buffer, int type) { - dataindex index_idx; - drvindex driver_idx; - std::string tag, filename; + dataindex const *index_idx = nullptr; + drvindex const *driver_idx = nullptr; + std::string const *tag; + std::string filename; switch (type) { case UI_HISTORY_LOAD: filename = "history.dat"; - tag = TAG_BIO; - index_idx = m_histidx; + tag = &TAG_BIO; + index_idx = &m_histidx; break; case UI_MAMEINFO_LOAD: filename = "mameinfo.dat"; - tag = TAG_MAME; - index_idx = m_mameidx; - driver_idx = m_drvidx; + tag = &TAG_MAME; + index_idx = &m_mameidx; + driver_idx = &m_drvidx; break; case UI_SYSINFO_LOAD: filename = "sysinfo.dat"; - tag = TAG_BIO; - index_idx = m_sysidx; + tag = &TAG_BIO; + index_idx = &m_sysidx; break; case UI_MESSINFO_LOAD: filename = "messinfo.dat"; - tag = TAG_MAME; - index_idx = m_messidx; - driver_idx = m_messdrvidx; + tag = &TAG_MAME; + index_idx = &m_messidx; + driver_idx = &m_messdrvidx; break; case UI_STORY_LOAD: filename = "story.dat"; - tag = TAG_STORY; - index_idx = m_storyidx; + tag = &TAG_STORY; + index_idx = &m_storyidx; break; case UI_GINIT_LOAD: filename = "gameinit.dat"; - tag = TAG_MAME; - index_idx = m_ginitidx; + tag = &TAG_MAME; + index_idx = &m_ginitidx; break; + default: + assert(false); + return; } - if (parseopen(filename.c_str())) + fileptr const datfile = parseopen(filename.c_str()); + if (datfile) { - load_data_text(drv, buffer, index_idx, tag); + load_data_text(datfile.get(), drv, buffer, *index_idx, *tag); // load driver info - if (!driver_idx.empty()) - load_driver_text(drv, buffer, driver_idx, TAG_DRIVER); + if (driver_idx && !driver_idx->empty()) + load_driver_text(datfile.get(), drv, buffer, *driver_idx, TAG_DRIVER); // cleanup mameinfo and sysinfo double line spacing - if ((tag == TAG_MAME && type != UI_GINIT_LOAD) || type == UI_SYSINFO_LOAD) + if (((*tag == TAG_MAME) && (type != UI_GINIT_LOAD)) || (type == UI_SYSINFO_LOAD)) strreplace(buffer, "\n\n", "\n"); - - parseclose(); } } //------------------------------------------------- // load a game text into the buffer //------------------------------------------------- -void datfile_manager::load_data_text(const game_driver *drv, std::string &buffer, dataindex &idx, std::string const &tag) +void datfile_manager::load_data_text(FILE *fp, game_driver const *drv, std::string &buffer, dataindex const &idx, std::string const &tag) { auto itemsiter = idx.find(drv); if (itemsiter == idx.end()) @@ -288,10 +303,10 @@ void datfile_manager::load_data_text(const game_driver *drv, std::string &buffer } auto s_offset = itemsiter->second; - fseek(fp, s_offset, SEEK_SET); + std::fseek(fp, s_offset, SEEK_SET); char rbuf[64 * 1024]; std::string readbuf; - while (fgets(rbuf, 64 * 1024, fp) != nullptr) + while (std::fgets(rbuf, 64 * 1024, fp) != nullptr) { readbuf = chartrimcarriage(rbuf); @@ -312,7 +327,7 @@ void datfile_manager::load_data_text(const game_driver *drv, std::string &buffer // load a driver name and offset into an // indexed array //------------------------------------------------- -void datfile_manager::load_driver_text(const game_driver *drv, std::string &buffer, drvindex &idx, std::string const &tag) +void datfile_manager::load_driver_text(FILE *fp, game_driver const *drv, std::string &buffer, drvindex const &idx, std::string const &tag) { std::string s(core_filename_extract_base(drv->source_file)); auto index = idx.find(s); @@ -323,10 +338,10 @@ void datfile_manager::load_driver_text(const game_driver *drv, std::string &buff buffer.append("\n--- DRIVER INFO ---\n").append("Driver: ").append(s).append("\n\n"); auto s_offset = index->second; - fseek(fp, s_offset, SEEK_SET); + std::fseek(fp, s_offset, SEEK_SET); char rbuf[64 * 1024]; std::string readbuf; - while (fgets(rbuf, 64 * 1024, fp) != nullptr) + while (std::fgets(rbuf, 64 * 1024, fp) != nullptr) { readbuf = chartrimcarriage(rbuf); @@ -347,7 +362,7 @@ void datfile_manager::load_driver_text(const game_driver *drv, std::string &buff // load a game name and offset into an // indexed array (mameinfo) //------------------------------------------------- -int datfile_manager::index_mame_mess_info(dataindex &index, drvindex &index_drv, int &drvcount) +int datfile_manager::index_mame_mess_info(fileptr &&fp, dataindex &index, drvindex &index_drv, int &drvcount) { size_t foundtag; auto t_mame = TAG_MAMEINFO_R.size(); @@ -357,7 +372,7 @@ int datfile_manager::index_mame_mess_info(dataindex &index, drvindex &index_drv, char rbuf[64 * 1024]; std::string readbuf, xid, name; - while (fgets(rbuf, 64 * 1024, fp) != nullptr) + while (std::fgets(rbuf, 64 * 1024, fp.get()) != nullptr) { readbuf = chartrimcarriage(rbuf); if (m_mame_rev.empty() && readbuf.compare(0, t_mame, TAG_MAMEINFO_R) == 0) @@ -378,7 +393,7 @@ int datfile_manager::index_mame_mess_info(dataindex &index, drvindex &index_drv, else if (readbuf.compare(0, t_info, TAG_INFO) == 0) { // TAG_INFO - fgets(rbuf, 64 * 1024, fp); + std::fgets(rbuf, 64 * 1024, fp.get()); xid = chartrimcarriage(rbuf); name = readbuf.substr(t_info + 1); if (xid == TAG_MAME) @@ -386,11 +401,11 @@ int datfile_manager::index_mame_mess_info(dataindex &index, drvindex &index_drv, // validate driver auto game_index = driver_list::find(name.c_str()); if (game_index != -1) - index.emplace(&driver_list::driver(game_index), ftell(fp)); + index.emplace(&driver_list::driver(game_index), std::ftell(fp.get())); } else if (xid == TAG_DRIVER) { - index_drv.emplace(name, ftell(fp)); + index_drv.emplace(name, std::ftell(fp.get())); drvcount++; } } @@ -402,14 +417,14 @@ int datfile_manager::index_mame_mess_info(dataindex &index, drvindex &index_drv, // load a game name and offset into an // indexed array //------------------------------------------------- -int datfile_manager::index_datafile(dataindex &index, int &swcount, std::string &rev, std::string const &tag, char sep) +int datfile_manager::index_datafile(fileptr &&fp, dataindex &index, int &swcount, std::string &rev, std::string const &tag, char sep) { std::string readbuf; auto const tag_size = tag.size(); auto const t_info = TAG_INFO.size(); auto const t_bio = TAG_BIO.size(); char rbuf[64 * 1024]; - while (fgets(rbuf, 64 * 1024, fp) != nullptr) + while (std::fgets(rbuf, 64 * 1024, fp.get()) != nullptr) { readbuf = chartrimcarriage(rbuf); @@ -433,13 +448,13 @@ int datfile_manager::index_datafile(dataindex &index, int &swcount, std::string { auto game_index = driver_list::find(e.c_str()); if (game_index != -1) - index.emplace(&driver_list::driver(game_index), ftell(fp)); + index.emplace(&driver_list::driver(game_index), std::ftell(fp.get())); } } else if (!readbuf.empty() && readbuf[0] == DATAFILE_TAG[0]) { // search for software info - fgets(rbuf, 64 * 1024, fp); + std::fgets(rbuf, 64 * 1024, fp.get()); std::string readbuf_2(chartrimcarriage(rbuf)); if (readbuf_2.compare(0, t_bio, TAG_BIO) == 0) { @@ -450,7 +465,7 @@ int datfile_manager::index_datafile(dataindex &index, int &swcount, std::string std::vector<std::string> token_roms = tokenize(s_roms, ','); for (auto & li : token_list) for (auto & ro : token_roms) - m_swindex[li].emplace(ro, ftell(fp)); + m_swindex[li].emplace(ro, std::ftell(fp.get())); swcount++; } } @@ -461,25 +476,25 @@ int datfile_manager::index_datafile(dataindex &index, int &swcount, std::string //--------------------------------------------------------- // parseopen - Open up file for reading //--------------------------------------------------------- -bool datfile_manager::parseopen(const char *filename) +datfile_manager::fileptr datfile_manager::parseopen(const char *filename) { emu_file file(m_options.history_path(), OPEN_FLAG_READ); if (file.open(filename) != osd_file::error::NONE) - return false; + return fileptr(nullptr, &std::fclose); - m_fullpath = file.fullpath(); + std::string const fullpath = file.fullpath(); file.close(); - fp = fopen(m_fullpath.c_str(), "rb"); + fileptr result(std::fopen(fullpath.c_str(), "rb"), &std::fclose); - fgetc(fp); - fseek(fp, 0, SEEK_SET); - return true; + fgetc(result.get()); + fseek(result.get(), 0, SEEK_SET); + return result; } //------------------------------------------------- // create the menu index //------------------------------------------------- -void datfile_manager::index_menuidx(const game_driver *drv, dataindex const &idx, drvindex &index) +void datfile_manager::index_menuidx(fileptr &&fp, const game_driver *drv, dataindex const &idx, drvindex &index) { auto itemsiter = idx.find(drv); if (itemsiter == idx.end()) @@ -495,11 +510,11 @@ void datfile_manager::index_menuidx(const game_driver *drv, dataindex const &idx // seek to correct point in datafile auto const s_offset = itemsiter->second; - fseek(fp, s_offset, SEEK_SET); + std::fseek(fp.get(), s_offset, SEEK_SET); auto const tinfo = TAG_INFO.size(); char rbuf[64 * 1024]; std::string readbuf; - while (fgets(rbuf, 64 * 1024, fp) != nullptr) + while (std::fgets(rbuf, 64 * 1024, fp.get()) != nullptr) { readbuf = chartrimcarriage(rbuf); @@ -509,9 +524,9 @@ void datfile_manager::index_menuidx(const game_driver *drv, dataindex const &idx // TAG_COMMAND identifies the driver if (readbuf == TAG_COMMAND) { - fgets(rbuf, 64 * 1024, fp); + std::fgets(rbuf, 64 * 1024, fp.get()); chartrimcarriage(rbuf); - index.emplace(rbuf, ftell(fp)); + index.emplace(rbuf, std::ftell(fp.get())); } } } @@ -519,16 +534,17 @@ void datfile_manager::index_menuidx(const game_driver *drv, dataindex const &idx //------------------------------------------------- // load command text into the buffer //------------------------------------------------- -void datfile_manager::load_command_info(std::string &buffer, std::string &sel) +void datfile_manager::load_command_info(std::string &buffer, std::string const &sel) { - if (parseopen("command.dat")) + fileptr const datfile = parseopen("command.dat"); + if (datfile) { // open and seek to correct point in datafile - auto offset = m_menuidx.at(sel); - fseek(fp, offset, SEEK_SET); + auto const offset = m_menuidx.at(sel); + std::fseek(datfile.get(), offset, SEEK_SET); char rbuf[64 * 1024]; std::string readbuf; - while (fgets(rbuf, 64 * 1024, fp) != nullptr) + while (std::fgets(rbuf, 64 * 1024, datfile.get()) != nullptr) { readbuf = chartrimcarriage(rbuf); @@ -543,7 +559,6 @@ void datfile_manager::load_command_info(std::string &buffer, std::string &sel) // add this string to the buffer buffer.append(readbuf).append("\n");; } - parseclose(); } } @@ -552,14 +567,14 @@ void datfile_manager::load_command_info(std::string &buffer, std::string &sel) //------------------------------------------------- void datfile_manager::command_sub_menu(const game_driver *drv, std::vector<std::string> &menuitems) { - if (parseopen("command.dat")) + fileptr datfile = parseopen("command.dat"); + if (datfile) { m_menuidx.clear(); - index_menuidx(drv, m_cmdidx, m_menuidx); + index_menuidx(std::move(datfile), drv, m_cmdidx, m_menuidx); menuitems.reserve(m_menuidx.size()); - for (auto & elem : m_menuidx) + for (auto const &elem : m_menuidx) menuitems.push_back(elem.first); - parseclose(); } } diff --git a/src/frontend/mame/ui/datfile.h b/src/frontend/mame/ui/datfile.h index a8d9c1599a0..93d13527cc9 100644 --- a/src/frontend/mame/ui/datfile.h +++ b/src/frontend/mame/ui/datfile.h @@ -13,9 +13,12 @@ #pragma once +#include <cstdio> +#include <memory> #include <string> #include <unordered_map> + class ui_options; namespace ui { @@ -33,7 +36,7 @@ public: // actions void load_data_info(const game_driver *drv, std::string &buffer, int type); - void load_command_info(std::string &buffer, std::string &sel); + void load_command_info(std::string &buffer, std::string const &sel); void load_software_info(std::string const &softlist, std::string &buffer, std::string const &softname, std::string const &parentname); void command_sub_menu(const game_driver *drv, std::vector<std::string> &menuitems); void reset_run() { first_run = true; } @@ -52,9 +55,7 @@ public: bool has_sysinfo(game_driver const *driver) const { return m_sysidx.find(driver) != m_sysidx.end(); } bool has_story(game_driver const *driver) const { return m_storyidx.find(driver) != m_storyidx.end(); } bool has_gameinit(game_driver const *driver) const { return m_ginitidx.find(driver) != m_ginitidx.end(); } - - // this isn't really just a getter - it affects some internal state - bool has_software(std::string const &softlist, std::string const &softname, std::string const &parentname); + bool has_software(std::string const &softlist, std::string const &softname, std::string const &parentname) const; bool has_data(game_driver const *a = nullptr) const { @@ -66,6 +67,7 @@ private: using drvindex = std::unordered_map<std::string, long>; using dataindex = std::unordered_map<const game_driver *, long>; using swindex = std::unordered_map<std::string, drvindex>; + using fileptr = std::unique_ptr<FILE, int (*)(FILE *)>; // global index static dataindex m_histidx, m_mameidx, m_messidx, m_cmdidx, m_sysidx, m_storyidx, m_ginitidx; @@ -73,32 +75,29 @@ private: static swindex m_swindex; // internal helpers - void init_history(); - void init_mameinfo(); - void init_messinfo(); - void init_command(); - void init_sysinfo(); - void init_story(); - void init_gameinit(); - - // file open/close/seek - bool parseopen(const char *filename); - void parseclose() { if (fp != nullptr) fclose(fp); } - - int index_mame_mess_info(dataindex &index, drvindex &index_drv, int &drvcount); - int index_datafile(dataindex &index, int &swcount, std::string &rev, std::string const &tag, char sep); - void index_menuidx(const game_driver *drv, dataindex const &idx, drvindex &index); - drvindex::const_iterator m_itemsiter; - - void load_data_text(const game_driver *drv, std::string &buffer, dataindex &idx, const std::string &tag); - void load_driver_text(const game_driver *drv, std::string &buffer, drvindex &idx, const std::string &tag); + void init_history(fileptr &&fp); + void init_mameinfo(fileptr &&fp); + void init_messinfo(fileptr &&fp); + void init_command(fileptr &&fp); + void init_sysinfo(fileptr &&fp); + void init_story(fileptr &&fp); + void init_gameinit(fileptr &&fp); + + fileptr parseopen(char const *filename); + + int index_mame_mess_info(fileptr &&fp, dataindex &index, drvindex &index_drv, int &drvcount); + int index_datafile(fileptr &&fp, dataindex &index, int &swcount, std::string &rev, std::string const &tag, char sep); + void index_menuidx(fileptr &&fp, game_driver const *drv, dataindex const &idx, drvindex &index); + + long const *find_software(std::string const &softlist, std::string const &softname, std::string const &parentname) const; + + void load_data_text(FILE *fp, game_driver const *drv, std::string &buffer, dataindex const &idx, std::string const &tag); + void load_driver_text(FILE *fp, game_driver const *drv, std::string &buffer, drvindex const &idx, std::string const &tag); // internal state running_machine &m_machine; // reference to our machine ui_options &m_options; - std::string m_fullpath; static std::string m_history_rev, m_mame_rev, m_mess_rev, m_sysinfo_rev, m_story_rev, m_ginit_rev; - FILE *fp = nullptr; static bool first_run; }; diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp index d8693356f05..f0f6adbfc38 100644 --- a/src/frontend/mame/ui/inifile.cpp +++ b/src/frontend/mame/ui/inifile.cpp @@ -313,7 +313,7 @@ bool favorite_manager::isgame_favorite(const game_driver *driver) // check if game is already in favorite list //------------------------------------------------- -bool favorite_manager::isgame_favorite(ui_software_info &swinfo) +bool favorite_manager::isgame_favorite(ui_software_info const &swinfo) { for (size_t x = 0; x < m_list.size(); x++) if (m_list[x] == swinfo) diff --git a/src/frontend/mame/ui/inifile.h b/src/frontend/mame/ui/inifile.h index 0658cf1f7db..f8da04145a7 100644 --- a/src/frontend/mame/ui/inifile.h +++ b/src/frontend/mame/ui/inifile.h @@ -8,10 +8,10 @@ ***************************************************************************/ -#pragma once +#ifndef MAME_FRONTEND_UI_INIFILE_H +#define MAME_FRONTEND_UI_INIFILE_H -#ifndef __UI_INIFILE_H__ -#define __UI_INIFILE_H__ +#pragma once #include "../frontend/mame/ui/utils.h" @@ -97,7 +97,7 @@ public: // check bool isgame_favorite(); bool isgame_favorite(const game_driver *driver); - bool isgame_favorite(ui_software_info &swinfo); + bool isgame_favorite(ui_software_info const &swinfo); // save void save_favorite_games(); @@ -120,4 +120,4 @@ private: ui_options &m_options; }; -#endif /* __UI_INIFILE_H__ */ +#endif // MAME_FRONTEND_UI_INIFILE_H diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 5c0b68ae525..08ce99bc61d 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -37,8 +37,8 @@ extern const char UI_VERSION_TAG[]; namespace ui { -static bool first_start = true; -static const char *dats_info[] = { +namespace { +char const *const dats_info[] = { __("General Info"), __("History"), __("Mameinfo"), @@ -46,8 +46,12 @@ static const char *dats_info[] = { __("Messinfo"), __("Command"), __("Gameinit"), - __("Mamescore") }; + __("Mamescore") +}; +} // anonymous namespace + +bool menu_select_game::first_start = true; std::vector<const game_driver *> menu_select_game::m_sortedlist; int menu_select_game::m_isabios = 0; @@ -57,8 +61,11 @@ int menu_select_game::m_isabios = 0; menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &container, const char *gamename) : menu_select_launch(mui, container, false) + , m_info_buffer() + , m_info_driver(nullptr) + , m_info_software(nullptr) + , m_info_view(-1) { - set_focus(focused_menu::main); highlight = 0; std::string error_string, last_filter, sub_filter; ui_options &moptions = mui.options(); @@ -426,8 +433,9 @@ void menu_select_game::handle() inkey_special(menu_event); } else if (menu_event->iptkey == IPT_UI_CONFIGURE) + { inkey_navigation(); - + } else if (menu_event->iptkey == IPT_OTHER) { m_prev_selected = nullptr; @@ -748,253 +756,6 @@ void menu_select_game::build_available_list() std::stable_sort(m_unavailsortedlist.begin(), m_unavailsortedlist.end(), sorted_game_list); } -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_select_game::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - ui_software_info *swinfo = nullptr; - float width, maxwidth = origx2 - origx1; - std::string tempbuf[5]; - rgb_t color = UI_BACKGROUND_COLOR; - bool isstar = false; - inifile_manager &inifile = mame_machine_manager::instance()->inifile(); - float tbarspace = ui().get_line_height(); - float text_size = 1.0f; - - tempbuf[0] = string_format(_("%1$s %2$s ( %3$d / %4$d machines (%5$d BIOS) )"), - emulator_info::get_appname(), - bare_build_version, - visible_items, - (driver_list::total() - 1), - m_isabios); - - std::string filtered; - if (main_filters::actual == FILTER_CATEGORY && inifile.total() > 0) - { - filtered = string_format(_("%1$s (%2$s - %3$s) - "), - main_filters::text[main_filters::actual], - inifile.get_file(), - inifile.get_category()); - } - else if (main_filters::actual == FILTER_MANUFACTURER) - { - filtered = string_format(_("%1$s (%2$s) - "), - main_filters::text[main_filters::actual], - c_mnfct::ui[c_mnfct::actual]); - } - else if (main_filters::actual == FILTER_YEAR) - { - filtered = string_format(_("%1$s (%2$s) - "), - main_filters::text[main_filters::actual], - c_year::ui[c_year::actual]); - } - - // display the current typeahead - if (isfavorite()) - tempbuf[1].clear(); - else - tempbuf[1] = string_format(_("%1$s Search: %2$s_"), filtered, m_search); - - // get the size of the text - for (int line = 0; line < 2; ++line) - { - ui().draw_text_full(container(), tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NONE, rgb_t::white, rgb_t::black, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - maxwidth = MAX(width, maxwidth); - } - - if (maxwidth > origx2 - origx1) - { - text_size = (origx2 - origx1) / maxwidth; - maxwidth = origx2 - origx1; - } - - // 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 - ui().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 < 2; ++line) - { - ui().draw_text_full(container(), tempbuf[line].c_str(), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size); - y1 += ui().get_line_height(); - } - - // determine the text to render below - const game_driver *driver = nullptr; - if (!isfavorite()) - { - driver = (FPTR(selectedref) > skip_main_items) ? (const game_driver *)selectedref : reinterpret_cast<const game_driver *>(m_prev_selected); - } - else - { - swinfo = (FPTR(selectedref) > skip_main_items) ? (ui_software_info *)selectedref : reinterpret_cast<ui_software_info *>(m_prev_selected); - if (swinfo != nullptr && swinfo->startempty == 1) - driver = swinfo->driver; - } - - if (driver) - { - isstar = mame_machine_manager::instance()->favorite().isgame_favorite(driver); - - // first line is game name - tempbuf[0] = string_format(_("Romset: %1$-.100s"), driver->name); - - // next line is year, manufacturer - tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer); - - // next line is clone/parent status - int cloneof = driver_list::non_bios_clone(*driver); - - if (cloneof != -1) - tempbuf[2] = string_format(_("Driver is clone of: %1$-.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 (swinfo != nullptr) - { - isstar = mame_machine_manager::instance()->favorite().isgame_favorite(*swinfo); - - // first line is system - tempbuf[0] = string_format(_("System: %1$-.100s"), swinfo->driver->description); - - // next line is year, publisher - tempbuf[1] = string_format(_("%1$s, %2$-.100s"), swinfo->year, swinfo->publisher); - - // next line is parent/clone - if (!swinfo->parentname.empty()) - tempbuf[2] = string_format(_("Software is clone of: %1$-.100s"), !swinfo->parentlongname.empty() ? swinfo->parentlongname : swinfo->parentname); - 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 - tempbuf[4] = string_format(_("romset: %1$-.100s"), swinfo->shortname); - } - else - { - std::string copyright(emulator_info::get_copyright()); - size_t found = copyright.find("\n"); - - tempbuf[0].clear(); - tempbuf[1] = string_format(_("%1$s %2$s"), emulator_info::get_appname(), 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); - - // get the size of the text - maxwidth = origx2 - origx1; - - for (auto & elem : tempbuf) - { - ui().draw_text_full(container(), elem.c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NONE, rgb_t::white, rgb_t::black, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - maxwidth = MAX(maxwidth, width); - } - - if (maxwidth > origx2 - origx1) - { - text_size = (origx2 - origx1) / maxwidth; - maxwidth = origx2 - origx1; - } - - // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; - x2 = x1 + maxwidth; - y1 = origy2 + UI_BOX_TB_BORDER; - y2 = origy2 + bottom; - - // draw a box - ui().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) - { - ui().draw_text_full(container(), elem.c_str(), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size); - y1 += ui().get_line_height(); - } -} //------------------------------------------------- // force the game select menu to be visible @@ -1209,7 +970,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event) // returns if the search can be activated //------------------------------------------------- -inline bool menu_select_game::isfavorite() +inline bool menu_select_game::isfavorite() const { return (main_filters::actual == FILTER_FAVORITE); } @@ -1243,73 +1004,6 @@ void menu_select_game::inkey_special(const event *menu_event) } -void menu_select_game::inkey_navigation() -{ - switch (get_focus()) - { - case focused_menu::main: - if (selected <= visible_items) - { - m_prev_selected = item[selected].ref; - selected = visible_items + 1; - } - else - { - if (ui_globals::panels_status != HIDE_LEFT_PANEL) - set_focus(focused_menu::left); - - else if (ui_globals::panels_status == HIDE_BOTH) - { - for (int x = 0; x < item.size(); ++x) - if (item[x].ref == m_prev_selected) - selected = x; - } - else - { - set_focus(focused_menu::righttop); - } - } - break; - - case focused_menu::left: - if (ui_globals::panels_status != HIDE_RIGHT_PANEL) - { - set_focus(focused_menu::righttop); - } - else - { - set_focus(focused_menu::main); - if (!m_prev_selected) - { - selected = 0; - return; - } - - for (int x = 0; x < item.size(); ++x) - if (item[x].ref == m_prev_selected) - selected = x; - } - break; - - case focused_menu::righttop: - set_focus(focused_menu::rightbottom); - break; - - case focused_menu::rightbottom: - set_focus(focused_menu::main); - if (!m_prev_selected) - { - selected = 0; - return; - } - - for (int x = 0; x < item.size(); ++x) - if (item[x].ref == m_prev_selected) - selected = x; - break; - } -} - //------------------------------------------------- // build list //------------------------------------------------- @@ -1966,38 +1660,127 @@ float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2) void menu_select_game::infos_render(float origx1, float origy1, float origx2, float origy2) { - float line_height = ui().get_line_height(); - static std::string buffer; + float const line_height = ui().get_line_height(); + float text_size = ui().options().infos_size(); std::vector<int> xstart; std::vector<int> xend; - float text_size = ui().options().infos_size(); - const game_driver *driver = nullptr; - ui_software_info *soft = nullptr; - bool is_favorites = ((item[0].flags & FLAG_UI_FAVORITE) != 0); - static ui_software_info *oldsoft = nullptr; - static const game_driver *olddriver = nullptr; - static int oldview = -1; - static int old_sw_view = -1; - - if (is_favorites) + + ui_software_info const *software; + game_driver const *driver; + get_selection(software, driver); + + if (software && ((software->startempty != 1) || !driver)) { - soft = reinterpret_cast<ui_software_info *>(get_selection_ptr()); - if (soft && soft->startempty == 1) + m_info_driver = nullptr; + + 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 (software->usage.empty()) { - driver = soft->driver; - oldsoft = nullptr; + ui().draw_text_full(container(), _("History"), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, + mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); + ui_globals::cur_sw_dats_view = 0; } else - olddriver = nullptr; + { + float title_size = 0.0f; + float txt_length = 0.0f; + std::string t_text[2]; + t_text[0] = _("History"); + t_text[1] = _("Usage"); + + for (auto & elem: t_text) + { + ui().draw_text_full(container(), elem.c_str(), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, + mame_ui_manager::NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr); + txt_length += 0.01f; + title_size = (std::max)(txt_length, title_size); + } + + rgb_t fgcolor = UI_TEXT_COLOR; + rgb_t bgcolor = UI_TEXT_BG_COLOR; + if (get_focus() == focused_menu::rightbottom) + { + fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00); + bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff); + } + + float middle = origx2 - origx1; + + if (bgcolor != UI_TEXT_BG_COLOR) + { + ui().draw_textured_box(container(), origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f), + origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); + } + + ui().draw_text_full(container(), t_text[ui_globals::cur_sw_dats_view].c_str(), origx1, origy1, origx2 - origx1, + ui::text_layout::CENTER, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr); + + draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::cur_sw_dats_view, 0, 1, title_size); + } + + if (m_info_software != software || m_info_view != ui_globals::cur_sw_dats_view) + { + m_info_buffer.clear(); + m_info_view = ui_globals::cur_sw_dats_view; + m_info_software = software; + if (ui_globals::cur_sw_dats_view == 0) + { + if (software->startempty == 1) + mame_machine_manager::instance()->datfile().load_data_info(software->driver, m_info_buffer, UI_HISTORY_LOAD); + else + mame_machine_manager::instance()->datfile().load_software_info(software->listname, m_info_buffer, software->shortname, software->parentname); + } + else + m_info_buffer = software->usage; + } + + if (m_info_buffer.empty()) + { + ui().draw_text_full(container(), _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, ui::text_layout::CENTER, + ui::text_layout::WORD, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); + return; + } + else + { + m_total_lines = ui().wrap_text(container(), m_info_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 (m_total_lines < r_visible_lines) + r_visible_lines = m_total_lines; + if (m_topline_datsview < 0) + m_topline_datsview = 0; + if (m_topline_datsview + r_visible_lines >= m_total_lines) + m_topline_datsview = m_total_lines - r_visible_lines; + + for (int r = 0; r < r_visible_lines; ++r) + { + int itemline = r + m_topline_datsview; + std::string tempbuf(m_info_buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline])); + + // up arrow + if (r == 0 && m_topline_datsview != 0) + draw_info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width); + // bottom arrow + else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1) + draw_info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width); + else + ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT, + ui::text_layout::TRUNCATE, mame_ui_manager::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 - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines); } - else + else if (driver) { - driver = reinterpret_cast<const game_driver *>(get_selection_ptr()); - oldsoft = nullptr; - } + m_info_software = nullptr; - if (driver) - { 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; @@ -2046,19 +1829,19 @@ void menu_select_game::infos_render(float origx1, float origy1, float origx2, fl draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::curdats_view, UI_FIRST_LOAD, UI_LAST_LOAD, title_size); - if (driver != olddriver || ui_globals::curdats_view != oldview) + if (driver != m_info_driver || ui_globals::curdats_view != m_info_view) { - buffer.clear(); - olddriver = driver; - oldview = ui_globals::curdats_view; + m_info_buffer.clear(); + m_info_driver = driver; + m_info_view = ui_globals::curdats_view; m_topline_datsview = 0; m_total_lines = 0; std::vector<std::string> m_item; if (ui_globals::curdats_view == UI_GENERAL_LOAD) - general_info(driver, buffer); + general_info(driver, m_info_buffer); else if (ui_globals::curdats_view != UI_COMMAND_LOAD) - mame_machine_manager::instance()->datfile().load_data_info(driver, buffer, ui_globals::curdats_view); + mame_machine_manager::instance()->datfile().load_data_info(driver, m_info_buffer, ui_globals::curdats_view); else mame_machine_manager::instance()->datfile().command_sub_menu(driver, m_item); @@ -2067,25 +1850,25 @@ void menu_select_game::infos_render(float origx1, float origy1, float origx2, fl for (size_t x = 0; x < m_item.size(); ++x) { std::string t_buffer; - buffer.append(m_item[x]).append("\n"); + m_info_buffer.append(m_item[x]).append("\n"); mame_machine_manager::instance()->datfile().load_command_info(t_buffer, m_item[x]); if (!t_buffer.empty()) - buffer.append(t_buffer).append("\n"); + m_info_buffer.append(t_buffer).append("\n"); } - convert_command_glyph(buffer); + convert_command_glyph(m_info_buffer); } } - if (buffer.empty()) + if (m_info_buffer.empty()) { ui().draw_text_full(container(), _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::WORD, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); return; } else if (ui_globals::curdats_view != UI_STORY_LOAD && ui_globals::curdats_view != UI_COMMAND_LOAD) - m_total_lines = ui().wrap_text(container(), buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size); + m_total_lines = ui().wrap_text(container(), m_info_buffer.c_str(), origx1, origy1, origx2 - origx1 - (2.0f * gutter_width), xstart, xend, text_size); else - m_total_lines = ui().wrap_text(container(), buffer.c_str(), 0.0f, 0.0f, 1.0f - (2.0f * gutter_width), xstart, xend, text_size); + m_total_lines = ui().wrap_text(container(), m_info_buffer.c_str(), 0.0f, 0.0f, 1.0f - (2.0f * gutter_width), xstart, xend, text_size); int r_visible_lines = floor((origy2 - oy1) / (line_height * text_size)); if (m_total_lines < r_visible_lines) @@ -2099,7 +1882,7 @@ void menu_select_game::infos_render(float origx1, float origy1, float origx2, fl for (int r = 0; r < r_visible_lines; ++r) { int itemline = r + m_topline_datsview; - std::string tempbuf(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline])); + std::string tempbuf(m_info_buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline])); // up arrow if (r == 0 && m_topline_datsview != 0) @@ -2159,8 +1942,10 @@ void menu_select_game::infos_render(float origx1, float origy1, float origx2, fl ui::text_layout::RIGHT, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size3); } else + { ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size3); + } } else { @@ -2174,112 +1959,6 @@ void menu_select_game::infos_render(float origx1, float origy1, float origx2, fl // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow right_visible_lines = r_visible_lines - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines); } - else if (soft) - { - 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->usage.empty()) - { - ui().draw_text_full(container(), _("History"), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::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_length = 0.0f; - std::string t_text[2]; - t_text[0] = _("History"); - t_text[1] = _("Usage"); - - for (auto & elem: t_text) - { - ui().draw_text_full(container(), elem.c_str(), origx1, origy1, origx2 - origx1, ui::text_layout::CENTER, ui::text_layout::TRUNCATE, - mame_ui_manager::NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr); - txt_length += 0.01f; - title_size = (std::max)(txt_length, title_size); - } - - rgb_t fgcolor = UI_TEXT_COLOR; - rgb_t bgcolor = UI_TEXT_BG_COLOR; - if (get_focus() == focused_menu::rightbottom) - { - fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00); - bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff); - } - - float middle = origx2 - origx1; - - if (bgcolor != UI_TEXT_BG_COLOR) - { - ui().draw_textured_box(container(), origx1 + ((middle - title_size) * 0.5f), origy1, origx1 + ((middle + title_size) * 0.5f), - origy1 + line_height, bgcolor, rgb_t(255, 43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); - } - - ui().draw_text_full(container(), t_text[ui_globals::cur_sw_dats_view].c_str(), origx1, origy1, origx2 - origx1, - ui::text_layout::CENTER, ui::text_layout::TRUNCATE, mame_ui_manager::NORMAL, fgcolor, bgcolor, 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) - mame_machine_manager::instance()->datfile().load_data_info(soft->driver, buffer, UI_HISTORY_LOAD); - else - mame_machine_manager::instance()->datfile().load_software_info(soft->listname, buffer, soft->shortname, soft->parentname); - } - else - buffer = soft->usage; - } - - if (buffer.empty()) - { - ui().draw_text_full(container(), _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, ui::text_layout::CENTER, - ui::text_layout::WORD, mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); - return; - } - else - { - m_total_lines = ui().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 (m_total_lines < r_visible_lines) - r_visible_lines = m_total_lines; - if (m_topline_datsview < 0) - m_topline_datsview = 0; - if (m_topline_datsview + r_visible_lines >= m_total_lines) - m_topline_datsview = m_total_lines - r_visible_lines; - - for (int r = 0; r < r_visible_lines; ++r) - { - int itemline = r + m_topline_datsview; - std::string tempbuf(buffer.substr(xstart[itemline], xend[itemline] - xstart[itemline])); - - // up arrow - if (r == 0 && m_topline_datsview != 0) - draw_info_arrow(0, origx1, origx2, oy1, line_height, text_size, ud_arrow_width); - // bottom arrow - else if (r == r_visible_lines - 1 && itemline != m_total_lines - 1) - draw_info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width); - else - ui().draw_text_full(container(), tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, ui::text_layout::LEFT, - ui::text_layout::TRUNCATE, mame_ui_manager::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 - (m_topline_datsview != 0) - (m_topline_datsview + r_visible_lines != m_total_lines); - } } @@ -2301,4 +1980,60 @@ void menu_select_game::get_selection(ui_software_info const *&software, game_dri } } + +void menu_select_game::make_topbox_text(std::string &line0, std::string &line1, std::string &line2) const +{ + inifile_manager &inifile = mame_machine_manager::instance()->inifile(); + + line0 = string_format(_("%1$s %2$s ( %3$d / %4$d machines (%5$d BIOS) )"), + emulator_info::get_appname(), + bare_build_version, + visible_items, + (driver_list::total() - 1), + m_isabios); + + std::string filtered; + if (main_filters::actual == FILTER_CATEGORY && inifile.total() > 0) + { + filtered = string_format(_("%1$s (%2$s - %3$s) - "), + main_filters::text[main_filters::actual], + inifile.get_file(), + inifile.get_category()); + } + else if (main_filters::actual == FILTER_MANUFACTURER) + { + filtered = string_format(_("%1$s (%2$s) - "), + main_filters::text[main_filters::actual], + c_mnfct::ui[c_mnfct::actual]); + } + else if (main_filters::actual == FILTER_YEAR) + { + filtered = string_format(_("%1$s (%2$s) - "), + main_filters::text[main_filters::actual], + c_year::ui[c_year::actual]); + } + + // display the current typeahead + if (isfavorite()) + line1.clear(); + else + line1 = string_format(_("%1$s Search: %2$s_"), filtered, m_search); + + line2.clear(); +} + + +std::string menu_select_game::make_driver_description(game_driver const &driver) const +{ + // first line is game name + return string_format(_("Romset: %1$-.100s"), driver.name); +} + + +std::string menu_select_game::make_software_description(ui_software_info const &software) const +{ + // first line is system + return string_format(_("System: %1$-.100s"), software.driver->description); +} + } // namespace ui diff --git a/src/frontend/mame/ui/selgame.h b/src/frontend/mame/ui/selgame.h index 046ab142052..699d9222f1b 100644 --- a/src/frontend/mame/ui/selgame.h +++ b/src/frontend/mame/ui/selgame.h @@ -27,7 +27,6 @@ public: static void force_game_select(mame_ui_manager &mui, render_container &container); protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool menu_has_search_active() override { return (m_search[0] != 0); } private: @@ -40,9 +39,15 @@ private: enum { VISIBLE_GAMES_IN_SEARCH = 200 }; char m_search[40]; + static bool first_start; static int m_isabios; int highlight; + std::string m_info_buffer; + game_driver const *m_info_driver; + ui_software_info const *m_info_software; + int m_info_view; + static std::vector<const game_driver *> m_sortedlist; std::vector<const game_driver *> m_availsortedlist; std::vector<const game_driver *> m_unavailsortedlist; @@ -59,13 +64,18 @@ private: // get selected software and/or driver virtual void get_selection(ui_software_info const *&software, game_driver const *&driver) const override; + // text for main top/bottom panels + virtual void make_topbox_text(std::string &line0, std::string &line1, std::string &line2) const override; + virtual std::string make_driver_description(game_driver const &driver) const override; + virtual std::string make_software_description(ui_software_info const &software) const override; + // internal methods void build_custom(); void build_category(); void build_available_list(); void build_list(const char *filter_text = nullptr, int filter = 0, bool bioscheck = false, std::vector<const game_driver *> vec = {}); - bool isfavorite(); + bool isfavorite() const; void populate_search(); void init_sorted_list(); bool load_available_machines(); @@ -87,7 +97,6 @@ private: void inkey_select_favorite(const event *menu_event); void inkey_special(const event *menu_event); void inkey_export(); - void inkey_navigation(); }; } // namespace ui diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index 123be37cd1b..64b4855c967 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -13,6 +13,7 @@ #include "ui/selmenu.h" #include "ui/icorender.h" +#include "ui/inifile.h" #include "ui/utils.h" // these hold static bitmap images @@ -26,6 +27,7 @@ #include "drivenum.h" #include "emuopts.h" #include "rendutil.h" +#include "softlist.h" #include "uiinput.h" #include <algorithm> @@ -189,75 +191,264 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c //------------------------------------------------- -// draw right box title +// perform our special rendering //------------------------------------------------- -float menu_select_launch::draw_right_box_title(float x1, float y1, float x2, float y2) +void menu_select_launch::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - auto line_height = ui().get_line_height(); - float midl = (x2 - x1) * 0.5f; + std::string tempbuf[5]; - // add outlined box for options - ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_BACKGROUND_COLOR); + // determine the text for the header + make_topbox_text(tempbuf[0], tempbuf[1], tempbuf[2]); - // add separator line - container().add_line(x1 + midl, y1, x1 + midl, y1 + line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - std::string buffer[RP_LAST + 1]; - buffer[RP_IMAGES] = _("Images"); - buffer[RP_INFOS] = _("Infos"); + // get the size of the text + float maxwidth = origx2 - origx1; + for (int line = 0; line < 3; ++line) + { + float width; + ui().draw_text_full(container(), tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::NEVER, + mame_ui_manager::NONE, rgb_t::white, rgb_t::black, &width, nullptr); + width += 2 * UI_BOX_LR_BORDER; + maxwidth = (std::max)(width, maxwidth); + } - // check size float text_size = 1.0f; - for (auto & elem : buffer) + if (maxwidth > origx2 - origx1) { - auto textlen = ui().get_string_width(elem.c_str()) + 0.01f; - float tmp_size = (textlen > midl) ? (midl / textlen) : 1.0f; - text_size = MIN(text_size, tmp_size); + text_size = (origx2 - origx1) / maxwidth; + maxwidth = origx2 - origx1; } - for (int cells = RP_FIRST; cells <= RP_LAST; ++cells) + // compute our bounds + float tbarspace = ui().get_line_height(); + 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 + ui().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) { - rgb_t bgcolor = UI_TEXT_BG_COLOR; - rgb_t fgcolor = UI_TEXT_COLOR; + ui().draw_text_full(container(), tempbuf[line].c_str(), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::NEVER, + mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size); + y1 += ui().get_line_height(); + } - if (mouse_hit && x1 <= mouse_x && x1 + midl > mouse_x && y1 <= mouse_y && y1 + line_height > mouse_y) + // determine the text to render below + ui_software_info const *swinfo; + game_driver const *driver; + get_selection(swinfo, driver); + + bool isstar = false; + rgb_t color = UI_BACKGROUND_COLOR; + if (swinfo && ((swinfo->startempty != 1) || !driver)) + { + isstar = mame_machine_manager::instance()->favorite().isgame_favorite(*swinfo); + + // first line is long name or system + tempbuf[0] = make_software_description(*swinfo); + + // next line is year, publisher + tempbuf[1] = string_format(_("%1$s, %2$-.100s"), swinfo->year, swinfo->publisher); + + // next line is parent/clone + if (!swinfo->parentname.empty()) + tempbuf[2] = string_format(_("Software is clone of: %1$-.100s"), !swinfo->parentlongname.empty() ? swinfo->parentlongname : swinfo->parentname); + else + tempbuf[2] = _("Software is parent"); + + // next line is supported status + if (swinfo->supported == SOFTWARE_SUPPORTED_NO) { - if (ui_globals::rpanel != cells) - { - bgcolor = UI_MOUSEOVER_BG_COLOR; - fgcolor = UI_MOUSEOVER_COLOR; - hover = HOVER_RP_FIRST + cells; - } + 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; } - if (ui_globals::rpanel != cells) + // last line is romset name + tempbuf[4] = string_format(_("romset: %1$-.100s"), swinfo->shortname); + } + else if (driver) + { + isstar = mame_machine_manager::instance()->favorite().isgame_favorite(driver); + + // first line is game description/game name + tempbuf[0] = make_driver_description(*driver); + + // next line is year, manufacturer + tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer); + + // next line is clone/parent status + int cloneof = driver_list::non_bios_clone(*driver); + + if (cloneof != -1) + tempbuf[2] = string_format(_("Driver is clone of: %1$-.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 + { + std::string copyright(emulator_info::get_copyright()); + size_t found = copyright.find("\n"); + + tempbuf[0].clear(); + tempbuf[1] = string_format(_("%1$s %2$s"), emulator_info::get_appname(), 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); + + // get the size of the text + maxwidth = origx2 - origx1; + + for (auto &elem : tempbuf) + { + float width; + ui().draw_text_full(container(), elem.c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::NEVER, + mame_ui_manager::NONE, rgb_t::white, rgb_t::black, &width, nullptr); + width += 2 * UI_BOX_LR_BORDER; + maxwidth = (std::max)(maxwidth, width); + } + + if (maxwidth > origx2 - origx1) + { + text_size = (origx2 - origx1) / maxwidth; + maxwidth = origx2 - origx1; + } + + // compute our bounds + x1 = 0.5f - 0.5f * maxwidth; + x2 = x1 + maxwidth; + y1 = origy2 + UI_BOX_TB_BORDER; + y2 = origy2 + bottom; + + // draw a box + ui().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) + { + ui().draw_text_full(container(), elem.c_str(), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::NEVER, + mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size); + y1 += ui().get_line_height(); + } +} + + +void menu_select_launch::inkey_navigation() +{ + switch (get_focus()) + { + case focused_menu::main: + if (selected <= visible_items) { - container().add_line(x1, y1 + line_height, x1 + midl, y1 + line_height, UI_LINE_WIDTH, - UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - if (fgcolor != UI_MOUSEOVER_COLOR) - fgcolor = UI_CLONE_COLOR; + m_prev_selected = item[selected].ref; + selected = visible_items + 1; } + else + { + if (ui_globals::panels_status != HIDE_LEFT_PANEL) + set_focus(focused_menu::left); - if (m_focus == focused_menu::righttop && ui_globals::rpanel == cells) + else if (ui_globals::panels_status == HIDE_BOTH) + { + for (int x = 0; x < item.size(); ++x) + if (item[x].ref == m_prev_selected) + selected = x; + } + else + { + set_focus(focused_menu::righttop); + } + } + break; + + case focused_menu::left: + if (ui_globals::panels_status != HIDE_RIGHT_PANEL) { - fgcolor = rgb_t(0xff, 0xff, 0x00); - bgcolor = rgb_t(0xff, 0xff, 0xff); - ui().draw_textured_box(container(), x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height, - bgcolor, rgb_t(43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); + set_focus(focused_menu::righttop); } - else if (bgcolor == UI_MOUSEOVER_BG_COLOR) + else { - container().add_rect(x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height, - bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); + set_focus(focused_menu::main); + select_prev(); } + break; - ui().draw_text_full(container(), buffer[cells].c_str(), x1 + UI_LINE_WIDTH, y1, midl - UI_LINE_WIDTH, - ui::text_layout::CENTER, ui::text_layout::NEVER, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size); - x1 += midl; - } + case focused_menu::righttop: + set_focus(focused_menu::rightbottom); + break; - return (y1 + line_height + UI_LINE_WIDTH); + case focused_menu::rightbottom: + set_focus(focused_menu::main); + select_prev(); + break; + } } @@ -340,7 +531,7 @@ void menu_select_launch::draw_info_arrow(int ub, float origx1, float origx2, flo // draw toolbar //------------------------------------------------- -void menu_select_launch::draw_toolbar(float x1, float y1, float x2, float y2, bool software) +void menu_select_launch::draw_toolbar(float x1, float y1, float x2, float y2) { // draw a box ui().draw_outlined_box(container(), x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B)); @@ -351,8 +542,8 @@ void menu_select_launch::draw_toolbar(float x1, float y1, float x2, float y2, bo y1 += UI_BOX_TB_BORDER; y2 -= UI_BOX_TB_BORDER; - texture_ptr_vector const &t_texture = software ? m_cache->sw_toolbar_texture() : m_cache->toolbar_texture(); - bitmap_ptr_vector const &t_bitmap = software ? m_cache->sw_toolbar_bitmap() : m_cache->toolbar_bitmap(); + texture_ptr_vector const &t_texture(m_is_swlist ? m_cache->sw_toolbar_texture() : m_cache->toolbar_texture()); + bitmap_ptr_vector const &t_bitmap(m_is_swlist ? m_cache->sw_toolbar_bitmap() : m_cache->toolbar_bitmap()); auto const num_valid(std::count_if(std::begin(t_bitmap), std::end(t_bitmap), [](bitmap_ptr const &e) { return e && e->valid(); })); @@ -1273,6 +1464,79 @@ void menu_select_launch::draw_right_panel(float origx1, float origy1, float orig //------------------------------------------------- +// draw right box title +//------------------------------------------------- + +float menu_select_launch::draw_right_box_title(float x1, float y1, float x2, float y2) +{ + auto line_height = ui().get_line_height(); + float midl = (x2 - x1) * 0.5f; + + // add outlined box for options + ui().draw_outlined_box(container(), x1, y1, x2, y2, UI_BACKGROUND_COLOR); + + // add separator line + container().add_line(x1 + midl, y1, x1 + midl, y1 + line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + + std::string buffer[RP_LAST + 1]; + buffer[RP_IMAGES] = _("Images"); + buffer[RP_INFOS] = _("Infos"); + + // check size + float text_size = 1.0f; + for (auto & elem : buffer) + { + auto textlen = ui().get_string_width(elem.c_str()) + 0.01f; + float tmp_size = (textlen > midl) ? (midl / textlen) : 1.0f; + text_size = MIN(text_size, tmp_size); + } + + for (int cells = RP_FIRST; cells <= RP_LAST; ++cells) + { + rgb_t bgcolor = UI_TEXT_BG_COLOR; + rgb_t fgcolor = UI_TEXT_COLOR; + + if (mouse_hit && x1 <= mouse_x && x1 + midl > mouse_x && y1 <= mouse_y && y1 + line_height > mouse_y) + { + if (ui_globals::rpanel != cells) + { + bgcolor = UI_MOUSEOVER_BG_COLOR; + fgcolor = UI_MOUSEOVER_COLOR; + hover = HOVER_RP_FIRST + cells; + } + } + + if (ui_globals::rpanel != cells) + { + container().add_line(x1, y1 + line_height, x1 + midl, y1 + line_height, UI_LINE_WIDTH, + UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + if (fgcolor != UI_MOUSEOVER_COLOR) + fgcolor = UI_CLONE_COLOR; + } + + if (m_focus == focused_menu::righttop && ui_globals::rpanel == cells) + { + fgcolor = rgb_t(0xff, 0xff, 0x00); + bgcolor = rgb_t(0xff, 0xff, 0xff); + ui().draw_textured_box(container(), x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height, + bgcolor, rgb_t(43, 43, 43), hilight_main_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); + } + else if (bgcolor == UI_MOUSEOVER_BG_COLOR) + { + container().add_rect(x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height, + bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); + } + + ui().draw_text_full(container(), buffer[cells].c_str(), x1 + UI_LINE_WIDTH, y1, midl - UI_LINE_WIDTH, + ui::text_layout::CENTER, ui::text_layout::NEVER, mame_ui_manager::NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size); + x1 += midl; + } + + return (y1 + line_height + UI_LINE_WIDTH); +} + + +//------------------------------------------------- // perform our special rendering //------------------------------------------------- diff --git a/src/frontend/mame/ui/selmenu.h b/src/frontend/mame/ui/selmenu.h index 02abce5a3e8..99838673e36 100644 --- a/src/frontend/mame/ui/selmenu.h +++ b/src/frontend/mame/ui/selmenu.h @@ -46,19 +46,15 @@ protected: focused_menu get_focus() const { return m_focus; } void set_focus(focused_menu focus) { m_focus = focus; } - // draw right box - float draw_right_box_title(float x1, float y1, float x2, float y2); + virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; + + // hanlders + void inkey_navigation(); // draw arrow 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); - // draw toolbar - void draw_toolbar(float x1, float y1, float x2, float y2, bool software = false); - - // draw star - void draw_star(float x0, float y0); - int visible_items; void *m_prev_selected; int m_total_lines; @@ -124,7 +120,27 @@ private: // get selected software and/or driver virtual void get_selection(ui_software_info const *&software, game_driver const *&driver) const = 0; - + void select_prev() + { + if (!m_prev_selected) + { + selected = 0; + } + else + { + for (int x = 0; x < item.size(); ++x) + { + if (item[x].ref == m_prev_selected) + { + selected = x; + break; + } + } + } + } + + void draw_toolbar(float x1, float y1, float x2, float y2); + void draw_star(float x0, float y0); float draw_icon(int linenum, void *selectedref, float x1, float y1); void get_title_search(std::string &title, std::string &search); @@ -140,6 +156,7 @@ private: // draw right panel void draw_right_panel(float origx1, float origy1, float origx2, float origy2); + float draw_right_box_title(float x1, float y1, float x2, float y2); // images render void arts_render(float origx1, float origy1, float origx2, float origy2); @@ -147,6 +164,11 @@ private: void arts_render_images(bitmap_argb32 *bitmap, float origx1, float origy1, float origx2, float origy2); void draw_snapx(float origx1, float origy1, float origx2, float origy2); + // text for main top/bottom panels + virtual void make_topbox_text(std::string &line0, std::string &line1, std::string &line2) const = 0; + 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; + // cleanup function static void exit(running_machine &machine); diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index 3c9b7ae025b..8839666d838 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -298,9 +298,10 @@ void menu_select_software::handle() check_filter = true; m_prev_selected = nullptr; } - else if (menu_event->iptkey == IPT_UI_CONFIGURE) + { inkey_navigation(); + } } if (menu_event && !menu_event->itemref) @@ -650,231 +651,6 @@ void menu_select_software::build_software_list() m_sortedlist.push_back(&m_swinfo[x]); } -//------------------------------------------------- -// perform our special rendering -//------------------------------------------------- - -void menu_select_software::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - ui_software_info *swinfo = (selectedref != nullptr) ? (ui_software_info *)selectedref : ((m_prev_selected != nullptr) ? (ui_software_info *)m_prev_selected : nullptr); - const game_driver *driver = nullptr; - float width; - std::string tempbuf[5], filtered; - rgb_t color = UI_BACKGROUND_COLOR; - bool isstar = false; - float tbarspace = ui().get_line_height(); - float text_size = 1.0f; - - // determine the text for the header - int vis_item = (m_search[0] != 0) ? visible_items : (m_has_empty_start ? visible_items - 1 : visible_items); - tempbuf[0] = string_format(_("%1$s %2$s ( %3$d / %4$d software packages )"), emulator_info::get_appname(), bare_build_version, vis_item, m_swinfo.size() - 1); - tempbuf[1] = string_format(_("Driver: \"%1$s\" software list "), m_driver->description); - - if (sw_filters::actual == UI_SW_REGION && m_filter.region.ui.size() != 0) - filtered = string_format(_("Region: %1$s -"), m_filter.region.ui[m_filter.region.actual]); - else if (sw_filters::actual == UI_SW_PUBLISHERS) - filtered = string_format(_("Publisher: %1$s -"), m_filter.publisher.ui[m_filter.publisher.actual]); - else if (sw_filters::actual == UI_SW_YEARS) - filtered = string_format(_("Year: %1$s -"), m_filter.year.ui[m_filter.year.actual]); - else if (sw_filters::actual == UI_SW_LIST) - filtered = string_format(_("Software List: %1$s -"), m_filter.swlist.description[m_filter.swlist.actual]); - else if (sw_filters::actual == UI_SW_TYPE) - filtered = string_format(_("Device type: %1$s -"), m_filter.type.ui[m_filter.type.actual]); - - tempbuf[2] = string_format(_("%s Search: %s_"), filtered, m_search); - - // get the size of the text - float maxwidth = origx2 - origx1; - - for (int line = 0; line < 3; ++line) - { - ui().draw_text_full(container(), tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NONE, rgb_t::white, rgb_t::black, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - maxwidth = MAX(width, maxwidth); - } - - if (maxwidth > origx2 - origx1) - { - text_size = (origx2 - origx1) / maxwidth; - maxwidth = origx2 - origx1; - } - - // 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 - ui().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) - { - ui().draw_text_full(container(), tempbuf[line].c_str(), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size); - y1 += ui().get_line_height(); - } - - // determine the text to render below - if (swinfo != nullptr && swinfo->startempty == 1) - driver = swinfo->driver; - - if (driver != nullptr) - { - isstar = mame_machine_manager::instance()->favorite().isgame_favorite(driver); - - // first line is game description - tempbuf[0] = string_format(_("%1$-.100s"), driver->description); - - // next line is year, manufacturer - tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer); - - // next line is clone/parent status - int cloneof = driver_list::non_bios_clone(*driver); - - if (cloneof != -1) - tempbuf[2] = string_format(_("Driver is clone of: %1$-.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 (swinfo != nullptr) - { - isstar = mame_machine_manager::instance()->favorite().isgame_favorite(*swinfo); - - // first line is long name - tempbuf[0] = string_format(_("%1$-.100s"), swinfo->longname.c_str()); - - // next line is year, publisher - tempbuf[1] = string_format(_("%1$s, %2$-.100s"), swinfo->year.c_str(), swinfo->publisher.c_str()); - - // next line is parent/clone - if (!swinfo->parentname.empty()) - tempbuf[2] = string_format(_("Software is clone of: %1$-.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 - tempbuf[4] = string_format(_("romset: %1$-.100s"), swinfo->shortname.c_str()); - } - else - { - std::string copyright(emulator_info::get_copyright()); - size_t found = copyright.find("\n"); - - tempbuf[0].clear(); - tempbuf[1] = string_format("%s %s", emulator_info::get_appname(), 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) - { - ui().draw_text_full(container(), elem.c_str(), 0.0f, 0.0f, 1.0f, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NONE, rgb_t::white, rgb_t::black, &width, nullptr); - width += 2 * UI_BOX_LR_BORDER; - maxwidth = MAX(maxwidth, width); - } - - if (maxwidth > origx2 - origx1) - { - text_size = (origx2 - origx1) / maxwidth; - maxwidth = origx2 - origx1; - } - - // compute our bounds - x1 = 0.5f - 0.5f * maxwidth; - x2 = x1 + maxwidth; - y1 = origy2 + UI_BOX_TB_BORDER; - y2 = origy2 + bottom; - - // draw a box - ui().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) - { - ui().draw_text_full(container(), elem.c_str(), x1, y1, x2 - x1, ui::text_layout::CENTER, ui::text_layout::NEVER, - mame_ui_manager::NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size); - y1 += ui().get_line_height(); - } -} //------------------------------------------------- // handle select key event @@ -989,73 +765,6 @@ void menu_select_software::inkey_special(const event *menu_event) } -void menu_select_software::inkey_navigation() -{ - switch (get_focus()) - { - case focused_menu::main: - if (selected <= visible_items) - { - m_prev_selected = item[selected].ref; - selected = visible_items + 1; - } - else - { - if (ui_globals::panels_status != HIDE_LEFT_PANEL) - set_focus(focused_menu::left); - - else if (ui_globals::panels_status == HIDE_BOTH) - { - for (int x = 0; x < item.size(); ++x) - if (item[x].ref == m_prev_selected) - selected = x; - } - else - { - set_focus(focused_menu::righttop); - } - } - break; - - case focused_menu::left: - if (ui_globals::panels_status != HIDE_RIGHT_PANEL) - { - set_focus(focused_menu::righttop); - } - else - { - set_focus(focused_menu::main); - if (m_prev_selected == nullptr) - { - selected = 0; - return; - } - - for (int x = 0; x < item.size(); ++x) - if (item[x].ref == m_prev_selected) - selected = x; - } - break; - - case focused_menu::righttop: - set_focus(focused_menu::rightbottom); - break; - - case focused_menu::rightbottom: - set_focus(focused_menu::main); - if (m_prev_selected == nullptr) - { - selected = 0; - return; - } - - for (int x = 0; x < item.size(); ++x) - if (item[x].ref == m_prev_selected) - selected = x; - break; - } -} - //------------------------------------------------- // load custom filters info from file //------------------------------------------------- @@ -1940,4 +1649,41 @@ void menu_select_software::get_selection(ui_software_info const *&software, game driver = software ? software->driver : nullptr; } + +void menu_select_software::make_topbox_text(std::string &line0, std::string &line1, std::string &line2) const +{ + // determine the text for the header + int vis_item = (m_search[0] != 0) ? visible_items : (m_has_empty_start ? visible_items - 1 : visible_items); + line0 = string_format(_("%1$s %2$s ( %3$d / %4$d software packages )"), emulator_info::get_appname(), bare_build_version, vis_item, m_swinfo.size() - 1); + line1 = string_format(_("Driver: \"%1$s\" software list "), m_driver->description); + + std::string filtered; + if (sw_filters::actual == UI_SW_REGION && m_filter.region.ui.size() != 0) + filtered = string_format(_("Region: %1$s -"), m_filter.region.ui[m_filter.region.actual]); + else if (sw_filters::actual == UI_SW_PUBLISHERS) + filtered = string_format(_("Publisher: %1$s -"), m_filter.publisher.ui[m_filter.publisher.actual]); + else if (sw_filters::actual == UI_SW_YEARS) + filtered = string_format(_("Year: %1$s -"), m_filter.year.ui[m_filter.year.actual]); + else if (sw_filters::actual == UI_SW_LIST) + filtered = string_format(_("Software List: %1$s -"), m_filter.swlist.description[m_filter.swlist.actual]); + else if (sw_filters::actual == UI_SW_TYPE) + filtered = string_format(_("Device type: %1$s -"), m_filter.type.ui[m_filter.type.actual]); + + line2 = string_format(_("%s Search: %s_"), filtered, m_search); +} + + +std::string menu_select_software::make_driver_description(game_driver const &driver) const +{ + // first line is game description + return string_format(_("%1$-.100s"), driver.description); +} + + +std::string menu_select_software::make_software_description(ui_software_info const &software) const +{ + // first line is long name + return string_format(_("%1$-.100s"), software.longname); +} + } // namespace ui diff --git a/src/frontend/mame/ui/selsoft.h b/src/frontend/mame/ui/selsoft.h index 7d5e81ad959..1f18671f9d8 100644 --- a/src/frontend/mame/ui/selsoft.h +++ b/src/frontend/mame/ui/selsoft.h @@ -27,7 +27,6 @@ public: virtual ~menu_select_software() override; protected: - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool menu_has_search_active() override { return (m_search[0] != 0); } private: @@ -47,6 +46,11 @@ private: // get selected software and/or driver virtual void get_selection(ui_software_info const *&software, game_driver const *&driver) const override; + // text for main top/bottom panels + virtual void make_topbox_text(std::string &line0, std::string &line1, std::string &line2) const override; + virtual std::string make_driver_description(game_driver const &driver) const override; + virtual std::string make_software_description(ui_software_info const &software) const override; + ui_software_info *m_searchlist[VISIBLE_GAMES_IN_SEARCH + 1]; std::vector<ui_software_info *> m_displaylist, m_tmp, m_sortedlist; std::vector<ui_software_info> m_swinfo; @@ -62,7 +66,6 @@ private: // handlers void inkey_select(const event *menu_event); void inkey_special(const event *menu_event); - void inkey_navigation(); }; class software_parts : public menu |