Skip to content
Snippets Groups Projects
Commit f95bdb50 authored by Zach Hilman's avatar Zach Hilman
Browse files

game_list: Implement caching for game list

Preserves list of add ons and the icon, which are the two costliest parts of game list population.
parent 180f22f1
No related branches found
No related tags found
No related merge requests found
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QSettings>
#include "common/common_paths.h" #include "common/common_paths.h"
#include "common/file_util.h" #include "common/file_util.h"
...@@ -30,13 +31,101 @@ ...@@ -30,13 +31,101 @@
#include "yuzu/ui_settings.h" #include "yuzu/ui_settings.h"
namespace { namespace {
template <typename T>
T GetGameListCachedObject(const std::string& filename, const std::string& ext,
const std::function<T()>& generator);
template <>
QString GetGameListCachedObject(const std::string& filename, const std::string& ext,
const std::function<QString()>& generator) {
if (!UISettings::values.cache_game_list || filename == "0000000000000000")
return generator();
const auto& path = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + "game_list" +
DIR_SEP + filename + "." + ext;
FileUtil::CreateFullPath(path);
if (!FileUtil::Exists(path)) {
const auto str = generator();
std::ofstream stream(path);
if (stream)
stream << str.toStdString();
stream.close();
return str;
}
std::ifstream stream(path);
if (stream) {
const std::string out(std::istreambuf_iterator<char>{stream},
std::istreambuf_iterator<char>{});
stream.close();
return QString::fromStdString(out);
}
return generator();
}
template <>
std::pair<std::vector<u8>, std::string> GetGameListCachedObject(
const std::string& filename, const std::string& ext,
const std::function<std::pair<std::vector<u8>, std::string>()>& generator) {
if (!UISettings::values.cache_game_list || filename == "0000000000000000")
return generator();
const auto& path1 = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
"game_list" + DIR_SEP + filename + ".jpeg";
const auto& path2 = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
"game_list" + DIR_SEP + filename + ".appname.txt";
FileUtil::CreateFullPath(path1);
if (!FileUtil::Exists(path1) || !FileUtil::Exists(path2)) {
const auto [icon, nacp] = generator();
FileUtil::IOFile file1(path1, "wb");
file1.Resize(icon.size());
file1.WriteBytes(icon.data(), icon.size());
std::ofstream stream2(path2, std::ios::out);
if (stream2)
stream2 << nacp;
file1.Close();
stream2.close();
return std::make_pair(icon, nacp);
}
FileUtil::IOFile file1(path1, "rb");
std::ifstream stream2(path2);
std::vector<u8> vec(file1.GetSize());
file1.ReadBytes(vec.data(), vec.size());
if (stream2 && !vec.empty()) {
const std::string out(std::istreambuf_iterator<char>{stream2},
std::istreambuf_iterator<char>{});
stream2.close();
return std::make_pair(vec, out);
}
return generator();
}
void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const FileSys::NCA& nca, void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const FileSys::NCA& nca,
std::vector<u8>& icon, std::string& name) { std::vector<u8>& icon, std::string& name) {
auto [nacp, icon_file] = patch_manager.ParseControlNCA(nca); auto res = GetGameListCachedObject<std::pair<std::vector<u8>, std::string>>(
if (icon_file != nullptr) fmt::format("{:016X}", patch_manager.GetTitleID()), {}, [&patch_manager, &nca] {
icon = icon_file->ReadAllBytes(); const auto [nacp, icon_f] = patch_manager.ParseControlNCA(nca);
if (nacp != nullptr) return std::make_pair(icon_f->ReadAllBytes(), nacp->GetApplicationName());
name = nacp->GetApplicationName(); });
icon = std::move(res.first);
name = std::move(res.second);
} }
bool HasSupportedFileExtension(const std::string& file_name) { bool HasSupportedFileExtension(const std::string& file_name) {
...@@ -114,8 +203,11 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri ...@@ -114,8 +203,11 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
}; };
if (UISettings::values.show_add_ons) { if (UISettings::values.show_add_ons) {
list.insert( const auto patch_versions = GetGameListCachedObject<QString>(
2, new GameListItem(FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()))); fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] {
return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable());
});
list.insert(2, new GameListItem(patch_versions));
} }
return list; return list;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment