diff options
Diffstat (limited to 'src/frontend/mame/ui/inifile.cpp')
-rw-r--r-- | src/frontend/mame/ui/inifile.cpp | 585 |
1 files changed, 204 insertions, 381 deletions
diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp index b68be00122b..852884fea6a 100644 --- a/src/frontend/mame/ui/inifile.cpp +++ b/src/frontend/mame/ui/inifile.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Maurizio Petrarota, Vas Crabb +// copyright-holders:Maurizio Petrarota /*************************************************************************** ui/inifile.cpp @@ -16,24 +16,13 @@ #include "drivenum.h" #include "softlist_dev.h" -#include <algorithm> -#include <cstring> -#include <iterator> - - -namespace { - -char const FAVORITE_FILENAME[] = "favorites.ini"; - -} // anonymous namespace - //------------------------------------------------- // ctor //------------------------------------------------- -inifile_manager::inifile_manager(ui_options &options) - : m_options(options) +inifile_manager::inifile_manager(running_machine &machine, ui_options &moptions) + : m_options(moptions) , m_ini_index() { // scan directories and create index @@ -119,103 +108,204 @@ void inifile_manager::init_category(std::string &&filename, emu_file &file) FAVORITE MANAGER **************************************************************************/ -bool favorite_manager::favorite_compare::operator()(ui_software_info const &lhs, ui_software_info const &rhs) const +//------------------------------------------------- +// ctor +//------------------------------------------------- + +favorite_manager::favorite_manager(running_machine &machine, ui_options &moptions) + : m_machine(machine) + , m_options(moptions) { - assert(lhs.driver); - assert(rhs.driver); + parse_favorite(); +} - if (!lhs.startempty) +//------------------------------------------------- +// add a game +//------------------------------------------------- + +void favorite_manager::add_favorite_game(const game_driver *driver) +{ + m_list.emplace(driver->type.fullname(), *driver); + save_favorite_games(); +} + +//------------------------------------------------- +// add a system +//------------------------------------------------- + +void favorite_manager::add_favorite_game(ui_software_info &swinfo) +{ + m_list.emplace(swinfo.longname, swinfo); + save_favorite_games(); +} + +//------------------------------------------------- +// add a game / system +//------------------------------------------------- + +void favorite_manager::add_favorite_game() +{ + if ((machine().system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE) { - if (rhs.startempty) - return false; - else if (lhs.listname < rhs.listname) - return true; - else if (lhs.listname > rhs.listname) - return false; - else if (lhs.shortname < rhs.shortname) - return true; - else if (lhs.shortname > rhs.shortname) - return false; + add_favorite_game(&machine().system()); + return; } - else if (!rhs.startempty) + + auto software_avail = false; + for (device_image_interface &image : image_interface_iterator(machine().root_device())) { - return true; + if (image.exists() && image.loaded_through_softlist()) + { + const software_info *swinfo = image.software_entry(); + const software_part *part = image.part_entry(); + ui_software_info tmpmatches; + tmpmatches.shortname = swinfo->shortname(); + tmpmatches.longname = image.longname(); + tmpmatches.parentname = swinfo->parentname(); + tmpmatches.year = image.year(); + tmpmatches.publisher = image.manufacturer(); + tmpmatches.supported = image.supported(); + tmpmatches.part = part->name(); + tmpmatches.driver = &machine().system(); + tmpmatches.listname = strensure(image.software_list_name()); + tmpmatches.interface = part->interface(); + tmpmatches.instance = image.instance_name(); + tmpmatches.startempty = 0; + tmpmatches.parentlongname.clear(); + if (!swinfo->parentname().empty()) + { + auto swlist = software_list_device::find_by_name(machine().config(), image.software_list_name()); + for (const software_info &c_swinfo : swlist->get_info()) + { + std::string c_parent(c_swinfo.parentname()); + if (!c_parent.empty() && c_parent == swinfo->shortname()) + { + tmpmatches.parentlongname = c_swinfo.longname(); + break; + } + } + } + + tmpmatches.usage.clear(); + for (const feature_list_item &flist : swinfo->other_info()) + if (!strcmp(flist.name().c_str(), "usage")) + tmpmatches.usage = flist.value(); + + tmpmatches.devicetype = strensure(image.image_type_name()); + tmpmatches.available = true; + software_avail = true; + m_list.emplace(tmpmatches.longname, tmpmatches); + save_favorite_games(); + } } - return 0 > std::strncmp(lhs.driver->name, rhs.driver->name, ARRAY_LENGTH(lhs.driver->name)); + if (!software_avail) + add_favorite_game(&machine().system()); } -bool favorite_manager::favorite_compare::operator()(ui_software_info const &lhs, game_driver const &rhs) const +//------------------------------------------------- +// remove a favorite from list +//------------------------------------------------- + +void favorite_manager::remove_favorite_game(ui_software_info const &swinfo) { - assert(lhs.driver); + for (auto e = m_list.begin(); e != m_list.end(); ++e) + if (e->second == swinfo) + { + m_list.erase(e); + break; + } + m_current = m_list.begin(); + save_favorite_games(); +} + +//------------------------------------------------- +// remove a favorite from list +//------------------------------------------------- - if (!lhs.startempty) - return false; - else - return 0 > std::strncmp(lhs.driver->name, rhs.name, ARRAY_LENGTH(rhs.name)); +void favorite_manager::remove_favorite_game() +{ + m_list.erase(m_current); + m_current = m_list.begin(); + save_favorite_games(); } -bool favorite_manager::favorite_compare::operator()(game_driver const &lhs, ui_software_info const &rhs) const +//------------------------------------------------- +// check if game is already in favorite list +//------------------------------------------------- + +bool favorite_manager::isgame_favorite() { - assert(rhs.driver); + if ((machine().system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE) + return isgame_favorite(&machine().system()); + + auto image_loaded = false; - if (!rhs.startempty) - return true; - else - return 0 > std::strncmp(lhs.name, rhs.driver->name, ARRAY_LENGTH(lhs.name)); + for (device_image_interface &image : image_interface_iterator(machine().root_device())) + { + const software_info *swinfo = image.software_entry(); + if (image.exists() && swinfo != nullptr) + { + image_loaded = true; + for (auto current = m_list.begin(); current != m_list.end(); ++current) + if (current->second.shortname == swinfo->shortname() && + current->second.listname == image.software_list_name()) + { + m_current = current; + return true; + } + } + } + + if (!image_loaded) + return isgame_favorite(&machine().system()); + + m_current = m_list.begin(); + return false; } -bool favorite_manager::favorite_compare::operator()(ui_software_info const &lhs, running_software_key const &rhs) const +//------------------------------------------------- +// check if game is already in favorite list +//------------------------------------------------- + +bool favorite_manager::isgame_favorite(const game_driver *driver) { - assert(lhs.driver); - assert(std::get<1>(rhs)); - - if (lhs.startempty) - return true; - else if (lhs.listname < std::get<1>(rhs)) - return true; - else if (lhs.listname > std::get<1>(rhs)) - return false; - else if (lhs.shortname < std::get<2>(rhs)) - return true; - else if (lhs.shortname > std::get<2>(rhs)) - return false; - else - return 0 > std::strncmp(lhs.driver->name, std::get<0>(rhs).name, ARRAY_LENGTH(lhs.driver->name)); + for (auto current = m_list.begin(); current != m_list.end(); ++current) + if (current->second.driver == driver && current->second.shortname == driver->name) + { + m_current = current; + return true; + } + + m_current = m_list.begin(); + return false; } -bool favorite_manager::favorite_compare::operator()(running_software_key const &lhs, ui_software_info const &rhs) const +//------------------------------------------------- +// check if game is already in favorite list +//------------------------------------------------- + +bool favorite_manager::isgame_favorite(ui_software_info const &swinfo) { - assert(std::get<1>(lhs)); - assert(rhs.driver); - - if (rhs.startempty) - return false; - else if (std::get<1>(lhs) < rhs.listname) - return true; - else if (std::get<1>(lhs) > rhs.listname) - return false; - else if (std::get<2>(lhs) < rhs.shortname) - return true; - else if (std::get<2>(lhs) > rhs.shortname) - return false; - else - return 0 > std::strncmp(std::get<0>(lhs).name, rhs.driver->name, ARRAY_LENGTH(rhs.driver->name)); -} + for (auto current = m_list.begin(); current != m_list.end(); ++current) + if (current->second == swinfo) + { + m_current = current; + return true; + } + m_current = m_list.begin(); + return false; +} //------------------------------------------------- -// construction/destruction +// parse favorite file //------------------------------------------------- -favorite_manager::favorite_manager(ui_options &options) - : m_options(options) - , m_favorites() - , m_sorted() - , m_need_sort(true) +void favorite_manager::parse_favorite() { emu_file file(m_options.ui_path(), OPEN_FLAG_READ); - if (file.open(FAVORITE_FILENAME) == osd_file::error::NONE) + if (file.open(favorite_filename) == osd_file::error::NONE) { char readbuf[1024]; file.gets(readbuf, 1024); @@ -242,8 +332,7 @@ favorite_manager::favorite_manager(ui_options &options) file.gets(readbuf, 1024); chartrimcarriage(readbuf); auto dx = driver_list::find(readbuf); - if (0 > dx) - continue; + if (dx == -1) continue; tmpmatches.driver = &driver_list::driver(dx); file.gets(readbuf, 1024); tmpmatches.listname = chartrimcarriage(readbuf); @@ -261,319 +350,53 @@ favorite_manager::favorite_manager(ui_options &options) tmpmatches.devicetype = chartrimcarriage(readbuf); file.gets(readbuf, 1024); tmpmatches.available = atoi(readbuf); - m_favorites.emplace(std::move(tmpmatches)); + m_list.emplace(tmpmatches.longname, tmpmatches); } file.close(); } } - -//------------------------------------------------- -// add -//------------------------------------------------- - -void favorite_manager::add_favorite_system(game_driver const &driver) -{ - add_impl(driver); -} - -void favorite_manager::add_favorite_software(ui_software_info const &swinfo) -{ - add_impl(swinfo); -} - -void favorite_manager::add_favorite(running_machine &machine) -{ - apply_running_machine( - machine, - [this, &machine] (game_driver const &driver, device_image_interface *imagedev, software_info const *software, bool &done) - { - if (imagedev) - { - // creating this is fairly expensive, but we'll assume this usually succeeds - ui_software_info info; - software_part const *const part(imagedev->part_entry()); - assert(software); - assert(part); - - // start with simple stuff that can just be copied - info.shortname = software->shortname(); - info.longname = imagedev->longname(); - info.parentname = software->parentname(); - info.year = imagedev->year(); - info.publisher = imagedev->manufacturer(); - info.supported = imagedev->supported(); - info.part = part->name(); - info.driver = &driver; - info.listname = imagedev->software_list_name(); - info.interface = part->interface(); - info.instance = imagedev->instance_name(); - info.startempty = 0; - info.devicetype = strensure(imagedev->image_type_name()); - info.available = true; - - // look up the parent in the list if necessary (eugh, O(n) walk) - if (!info.parentname.empty()) - { - auto const listdev = software_list_device::find_by_name(machine.config(), info.listname); - assert(listdev); - for (software_info const &other : listdev->get_info()) - { - if (other.shortname() == info.parentname) - { - info.parentlongname = other.longname(); - break; - } - } - } - - // fill in with the first usage entry we find - for (feature_list_item const &feature : software->other_info()) - { - if (feature.name() == "usage") - { - info.usage = feature.value(); - break; - } - } - - // hooray for move semantics! - add_impl(std::move(info)); - } - else - { - add_impl(driver); - } - }); -} - -template <typename T> void favorite_manager::add_impl(T &&key) -{ - auto const ins(m_favorites.emplace(std::forward<T>(key))); - if (ins.second) - { - if (!m_sorted.empty()) - m_sorted.emplace_back(std::ref(*ins.first)); - m_need_sort = true; - save_favorites(); - } -} - - -//------------------------------------------------- -// check -//------------------------------------------------- - -bool favorite_manager::is_favorite_system(game_driver const &driver) const -{ - return check_impl(driver); -} - -bool favorite_manager::is_favorite_software(ui_software_info const &swinfo) const -{ - auto found(m_favorites.lower_bound(swinfo)); - if ((m_favorites.end() != found) && (found->listname == swinfo.listname) && (found->shortname == swinfo.shortname)) - return true; - else if (m_favorites.begin() == found) - return false; - - // need to back up and check for matching software with lexically earlier driver - --found; - return (found->listname == swinfo.listname) && (found->shortname == swinfo.shortname); -} - -bool favorite_manager::is_favorite(running_machine &machine) const -{ - bool result(false); - apply_running_machine( - machine, - [this, &result] (game_driver const &driver, device_image_interface *imagedev, software_info const *software, bool &done) - { - assert(!result); - result = imagedev - ? check_impl(running_software_key(driver, imagedev->software_list_name(), software->shortname())) - : check_impl(driver); - done = done || result; - }); - return result; -} - -bool favorite_manager::is_favorite_system_software(ui_software_info const &swinfo) const -{ - return check_impl(swinfo); -} - -template <typename T> bool favorite_manager::check_impl(T const &key) const -{ - return m_favorites.find(key) != m_favorites.end(); -} - - -//------------------------------------------------- -// remove -//------------------------------------------------- - -void favorite_manager::remove_favorite_system(game_driver const &driver) -{ - remove_impl(driver); -} - -void favorite_manager::remove_favorite_software(ui_software_info const &swinfo) -{ - remove_impl(swinfo); -} - -void favorite_manager::remove_favorite(running_machine &machine) -{ - apply_running_machine( - machine, - [this] (game_driver const &driver, device_image_interface *imagedev, software_info const *software, bool &done) - { - done = imagedev - ? remove_impl(running_software_key(driver, imagedev->software_list_name(), software->shortname())) - : remove_impl(driver); - }); -} - -template <typename T> bool favorite_manager::remove_impl(T const &key) -{ - auto const found(m_favorites.find(key)); - if (m_favorites.end() != found) - { - m_favorites.erase(found); - m_sorted.clear(); - m_need_sort = true; - save_favorites(); - return true; - } - else - { - return false; - } -} - - //------------------------------------------------- -// implementation +// save favorite //------------------------------------------------- -template <typename T> -void favorite_manager::apply_running_machine(running_machine &machine, T &&action) -{ - bool done(false); - - // TODO: this should be changed - it interacts poorly with cartslots on arcade systems - if ((machine.system().flags & machine_flags::MASK_TYPE) == machine_flags::TYPE_ARCADE) - { - action(machine.system(), nullptr, nullptr, done); - } - else - { - bool have_software(false); - for (device_image_interface &image_dev : image_interface_iterator(machine.root_device())) - { - software_info const *const sw(image_dev.software_entry()); - if (image_dev.exists() && image_dev.loaded_through_softlist() && sw) - { - assert(image_dev.software_list_name()); - - have_software = true; - action(machine.system(), &image_dev, sw, done); - if (done) - return; - } - } - - if (!have_software) - action(machine.system(), nullptr, nullptr, done); - } -} - -void favorite_manager::update_sorted() -{ - if (m_need_sort) - { - if (m_sorted.empty()) - std::copy(m_favorites.begin(), m_favorites.end(), std::back_inserter(m_sorted)); - - assert(m_favorites.size() == m_sorted.size()); - std::stable_sort( - m_sorted.begin(), - m_sorted.end(), - [] (ui_software_info const &lhs, ui_software_info const &rhs) -> bool - { - assert(lhs.driver); - assert(rhs.driver); - - int cmp; - - cmp = core_stricmp(lhs.longname.c_str(), rhs.longname.c_str()); - if (0 > cmp) - return true; - else if (0 < cmp) - return false; - - cmp = core_stricmp(lhs.driver->type.fullname(), rhs.driver->type.fullname()); - if (0 > cmp) - return true; - else if (0 < cmp) - return false; - - cmp = std::strcmp(lhs.listname.c_str(), rhs.listname.c_str()); - if (0 > cmp) - return true; - else if (0 < cmp) - return false; - - return false; - }); - - m_need_sort = false; - } -} - -void favorite_manager::save_favorites() +void favorite_manager::save_favorite_games() { // attempt to open the output file emu_file file(m_options.ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(FAVORITE_FILENAME) == osd_file::error::NONE) + if (file.open(favorite_filename) == osd_file::error::NONE) { - if (m_favorites.empty()) + if (m_list.empty()) { - // delete it if there are no favorites file.remove_on_close(); + file.close(); + return; } - else + + // generate the favorite INI + std::ostringstream text; + text << "[ROOT_FOLDER]\n[Favorite]\n\n"; + for (auto & e : m_list) { - // generate the favorite INI - file.puts("[ROOT_FOLDER]\n[Favorite]\n\n"); - util::ovectorstream buf; - for (ui_software_info const &info : m_favorites) - { - buf.clear(); - buf.rdbuf()->clear(); - - buf << info.shortname << '\n'; - buf << info.longname << '\n'; - buf << info.parentname << '\n'; - buf << info.year << '\n'; - buf << info.publisher << '\n'; - util::stream_format(buf, "%d\n", info.supported); - buf << info.part << '\n'; - util::stream_format(buf, "%s\n", info.driver->name); - buf << info.listname << '\n'; - buf << info.interface << '\n'; - buf << info.instance << '\n'; - util::stream_format(buf, "%d\n", info.startempty); - buf << info.parentlongname << '\n'; - buf << info.usage << '\n'; - buf << info.devicetype << '\n'; - util::stream_format(buf, "%d\n", info.available); - - buf.put('\0'); - file.puts(&buf.vec()[0]); - } + auto elem = e.second; + text << elem.shortname << '\n'; + text << elem.longname << '\n'; + text << elem.parentname << '\n'; + text << elem.year << '\n'; + text << elem.publisher << '\n'; + util::stream_format(text, "%d\n", elem.supported); + text << elem.part << '\n'; + util::stream_format(text, "%s\n", elem.driver->name); + text << elem.listname << '\n'; + text << elem.interface << '\n'; + text << elem.instance << '\n'; + util::stream_format(text, "%d\n", elem.startempty); + text << elem.parentlongname << '\n'; + text << elem.usage << '\n'; + text << elem.devicetype << '\n'; + util::stream_format(text, "%d\n", elem.available); } + file.puts(text.str().c_str()); file.close(); } } |