summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/configuration/config.cpp3
-rw-r--r--src/yuzu/configuration/configure_per_general.cpp10
-rw-r--r--src/yuzu/game_list_worker.cpp124
-rw-r--r--src/yuzu/main.cpp2
-rw-r--r--src/yuzu/ui_settings.h1
5 files changed, 133 insertions, 7 deletions
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index db27da23e..b1942bedc 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -645,6 +645,8 @@ void Config::ReadUIGamelistValues() {
645 UISettings::values.icon_size = ReadSetting(QStringLiteral("icon_size"), 64).toUInt(); 645 UISettings::values.icon_size = ReadSetting(QStringLiteral("icon_size"), 64).toUInt();
646 UISettings::values.row_1_text_id = ReadSetting(QStringLiteral("row_1_text_id"), 3).toUInt(); 646 UISettings::values.row_1_text_id = ReadSetting(QStringLiteral("row_1_text_id"), 3).toUInt();
647 UISettings::values.row_2_text_id = ReadSetting(QStringLiteral("row_2_text_id"), 2).toUInt(); 647 UISettings::values.row_2_text_id = ReadSetting(QStringLiteral("row_2_text_id"), 2).toUInt();
648 UISettings::values.cache_game_list =
649 ReadSetting(QStringLiteral("cache_game_list"), true).toBool();
648 650
649 qt_config->endGroup(); 651 qt_config->endGroup();
650} 652}
@@ -1009,6 +1011,7 @@ void Config::SaveUIGamelistValues() {
1009 WriteSetting(QStringLiteral("icon_size"), UISettings::values.icon_size, 64); 1011 WriteSetting(QStringLiteral("icon_size"), UISettings::values.icon_size, 64);
1010 WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3); 1012 WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3);
1011 WriteSetting(QStringLiteral("row_2_text_id"), UISettings::values.row_2_text_id, 2); 1013 WriteSetting(QStringLiteral("row_2_text_id"), UISettings::values.row_2_text_id, 2);
1014 WriteSetting(QStringLiteral("cache_game_list"), UISettings::values.cache_game_list, true);
1012 1015
1013 qt_config->endGroup(); 1016 qt_config->endGroup();
1014} 1017}
diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_general.cpp
index 2bdfc8e5a..c3e68fdf5 100644
--- a/src/yuzu/configuration/configure_per_general.cpp
+++ b/src/yuzu/configuration/configure_per_general.cpp
@@ -13,6 +13,8 @@
13#include <QTimer> 13#include <QTimer>
14#include <QTreeView> 14#include <QTreeView>
15 15
16#include "common/common_paths.h"
17#include "common/file_util.h"
16#include "core/file_sys/control_metadata.h" 18#include "core/file_sys/control_metadata.h"
17#include "core/file_sys/patch_manager.h" 19#include "core/file_sys/patch_manager.h"
18#include "core/file_sys/xts_archive.h" 20#include "core/file_sys/xts_archive.h"
@@ -79,6 +81,14 @@ void ConfigurePerGameGeneral::applyConfiguration() {
79 disabled_addons.push_back(item.front()->text().toStdString()); 81 disabled_addons.push_back(item.front()->text().toStdString());
80 } 82 }
81 83
84 auto current = Settings::values.disabled_addons[title_id];
85 std::sort(disabled_addons.begin(), disabled_addons.end());
86 std::sort(current.begin(), current.end());
87 if (disabled_addons != current) {
88 FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
89 "game_list" + DIR_SEP + fmt::format("{:016X}.pv.txt", title_id));
90 }
91
82 Settings::values.disabled_addons[title_id] = disabled_addons; 92 Settings::values.disabled_addons[title_id] = disabled_addons;
83} 93}
84 94
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 82d2826ba..4d951a4e7 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -9,6 +9,7 @@
9 9
10#include <QDir> 10#include <QDir>
11#include <QFileInfo> 11#include <QFileInfo>
12#include <QSettings>
12 13
13#include "common/common_paths.h" 14#include "common/common_paths.h"
14#include "common/file_util.h" 15#include "common/file_util.h"
@@ -30,13 +31,119 @@
30#include "yuzu/ui_settings.h" 31#include "yuzu/ui_settings.h"
31 32
32namespace { 33namespace {
34
35template <typename T>
36T GetGameListCachedObject(const std::string& filename, const std::string& ext,
37 const std::function<T()>& generator);
38
39template <>
40QString GetGameListCachedObject(const std::string& filename, const std::string& ext,
41 const std::function<QString()>& generator) {
42 if (!UISettings::values.cache_game_list || filename == "0000000000000000") {
43 return generator();
44 }
45
46 const auto path = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + "game_list" +
47 DIR_SEP + filename + '.' + ext;
48
49 FileUtil::CreateFullPath(path);
50
51 if (!FileUtil::Exists(path)) {
52 const auto str = generator();
53
54 std::ofstream stream(path);
55 if (stream) {
56 stream << str.toStdString();
57 }
58
59 return str;
60 }
61
62 std::ifstream stream(path);
63
64 if (stream) {
65 const std::string out(std::istreambuf_iterator<char>{stream},
66 std::istreambuf_iterator<char>{});
67 return QString::fromStdString(out);
68 }
69
70 return generator();
71}
72
73template <>
74std::pair<std::vector<u8>, std::string> GetGameListCachedObject(
75 const std::string& filename, const std::string& ext,
76 const std::function<std::pair<std::vector<u8>, std::string>()>& generator) {
77 if (!UISettings::values.cache_game_list || filename == "0000000000000000") {
78 return generator();
79 }
80
81 const auto path1 = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + "game_list" +
82 DIR_SEP + filename + ".jpeg";
83 const auto path2 = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + "game_list" +
84 DIR_SEP + filename + ".appname.txt";
85
86 FileUtil::CreateFullPath(path1);
87
88 if (!FileUtil::Exists(path1) || !FileUtil::Exists(path2)) {
89 const auto [icon, nacp] = generator();
90
91 FileUtil::IOFile file1(path1, "wb");
92 if (!file1.IsOpen()) {
93 LOG_ERROR(Frontend, "Failed to open cache file.");
94 return generator();
95 }
96
97 if (!file1.Resize(icon.size())) {
98 LOG_ERROR(Frontend, "Failed to resize cache file to necessary size.");
99 return generator();
100 }
101
102 if (file1.WriteBytes(icon.data(), icon.size()) != icon.size()) {
103 LOG_ERROR(Frontend, "Failed to write data to cache file.");
104 return generator();
105 }
106
107 std::ofstream stream2(path2, std::ios::out);
108 if (stream2) {
109 stream2 << nacp;
110 }
111
112 return std::make_pair(icon, nacp);
113 }
114
115 FileUtil::IOFile file1(path1, "rb");
116 std::ifstream stream2(path2);
117
118 if (!file1.IsOpen()) {
119 LOG_ERROR(Frontend, "Failed to open cache file for reading.");
120 return generator();
121 }
122
123 if (!stream2) {
124 LOG_ERROR(Frontend, "Failed to open cache file for reading.");
125 return generator();
126 }
127
128 std::vector<u8> vec(file1.GetSize());
129 file1.ReadBytes(vec.data(), vec.size());
130
131 if (stream2 && !vec.empty()) {
132 const std::string out(std::istreambuf_iterator<char>{stream2},
133 std::istreambuf_iterator<char>{});
134 return std::make_pair(vec, out);
135 }
136
137 return generator();
138}
139
33void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const FileSys::NCA& nca, 140void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const FileSys::NCA& nca,
34 std::vector<u8>& icon, std::string& name) { 141 std::vector<u8>& icon, std::string& name) {
35 auto [nacp, icon_file] = patch_manager.ParseControlNCA(nca); 142 std::tie(icon, name) = GetGameListCachedObject<std::pair<std::vector<u8>, std::string>>(
36 if (icon_file != nullptr) 143 fmt::format("{:016X}", patch_manager.GetTitleID()), {}, [&patch_manager, &nca] {
37 icon = icon_file->ReadAllBytes(); 144 const auto [nacp, icon_f] = patch_manager.ParseControlNCA(nca);
38 if (nacp != nullptr) 145 return std::make_pair(icon_f->ReadAllBytes(), nacp->GetApplicationName());
39 name = nacp->GetApplicationName(); 146 });
40} 147}
41 148
42bool HasSupportedFileExtension(const std::string& file_name) { 149bool HasSupportedFileExtension(const std::string& file_name) {
@@ -114,8 +221,11 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
114 }; 221 };
115 222
116 if (UISettings::values.show_add_ons) { 223 if (UISettings::values.show_add_ons) {
117 list.insert( 224 const auto patch_versions = GetGameListCachedObject<QString>(
118 2, new GameListItem(FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()))); 225 fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] {
226 return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable());
227 });
228 list.insert(2, new GameListItem(patch_versions));
119 } 229 }
120 230
121 return list; 231 return list;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index cef2cc1ae..f8a0daebd 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1396,6 +1396,8 @@ void GMainWindow::OnMenuInstallToNAND() {
1396 tr("The file was successfully installed.")); 1396 tr("The file was successfully installed."));
1397 game_list->PopulateAsync(UISettings::values.game_directory_path, 1397 game_list->PopulateAsync(UISettings::values.game_directory_path,
1398 UISettings::values.game_directory_deepscan); 1398 UISettings::values.game_directory_deepscan);
1399 FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) +
1400 DIR_SEP + "game_list");
1399 }; 1401 };
1400 1402
1401 const auto failed = [this]() { 1403 const auto failed = [this]() {
diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h
index dbd318e20..a62cd6911 100644
--- a/src/yuzu/ui_settings.h
+++ b/src/yuzu/ui_settings.h
@@ -79,6 +79,7 @@ struct Values {
79 uint8_t row_1_text_id; 79 uint8_t row_1_text_id;
80 uint8_t row_2_text_id; 80 uint8_t row_2_text_id;
81 std::atomic_bool is_game_list_reload_pending{false}; 81 std::atomic_bool is_game_list_reload_pending{false};
82 bool cache_game_list;
82}; 83};
83 84
84extern Values values; 85extern Values values;