summaryrefslogtreecommitdiff
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/applets/profile_select.cpp10
-rw-r--r--src/yuzu/applets/profile_select.h8
-rw-r--r--src/yuzu/bootmanager.cpp3
-rw-r--r--src/yuzu/bootmanager.h3
-rw-r--r--src/yuzu/configuration/config.cpp3
-rw-r--r--src/yuzu/configuration/configure_per_general.cpp10
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp11
-rw-r--r--src/yuzu/game_list_worker.cpp124
-rw-r--r--src/yuzu/main.cpp2
-rw-r--r--src/yuzu/main.h2
-rw-r--r--src/yuzu/ui_settings.h1
11 files changed, 150 insertions, 27 deletions
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp
index 7fbc9deeb..42e26b978 100644
--- a/src/yuzu/applets/profile_select.cpp
+++ b/src/yuzu/applets/profile_select.cpp
@@ -27,20 +27,20 @@ constexpr std::array<u8, 107> backup_jpeg{
0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
};
-QString FormatUserEntryText(const QString& username, Service::Account::UUID uuid) {
+QString FormatUserEntryText(const QString& username, Common::UUID uuid) {
return QtProfileSelectionDialog::tr(
"%1\n%2", "%1 is the profile username, %2 is the formatted UUID (e.g. "
"00112233-4455-6677-8899-AABBCCDDEEFF))")
.arg(username, QString::fromStdString(uuid.FormatSwitch()));
}
-QString GetImagePath(Service::Account::UUID uuid) {
+QString GetImagePath(Common::UUID uuid) {
const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
"/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg";
return QString::fromStdString(path);
}
-QPixmap GetIcon(Service::Account::UUID uuid) {
+QPixmap GetIcon(Common::UUID uuid) {
QPixmap icon{GetImagePath(uuid)};
if (!icon) {
@@ -154,12 +154,12 @@ QtProfileSelector::QtProfileSelector(GMainWindow& parent) {
QtProfileSelector::~QtProfileSelector() = default;
void QtProfileSelector::SelectProfile(
- std::function<void(std::optional<Service::Account::UUID>)> callback) const {
+ std::function<void(std::optional<Common::UUID>)> callback) const {
this->callback = std::move(callback);
emit MainWindowSelectProfile();
}
-void QtProfileSelector::MainWindowFinishedSelection(std::optional<Service::Account::UUID> uuid) {
+void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) {
// Acquire the HLE mutex
std::lock_guard lock{HLE::g_hle_lock};
callback(uuid);
diff --git a/src/yuzu/applets/profile_select.h b/src/yuzu/applets/profile_select.h
index 1c2922e54..c5b90a78e 100644
--- a/src/yuzu/applets/profile_select.h
+++ b/src/yuzu/applets/profile_select.h
@@ -9,6 +9,7 @@
#include <QList>
#include <QTreeView>
#include "core/frontend/applets/profile_select.h"
+#include "core/hle/service/acc/profile_manager.h"
class GMainWindow;
class QDialogButtonBox;
@@ -60,14 +61,13 @@ public:
explicit QtProfileSelector(GMainWindow& parent);
~QtProfileSelector() override;
- void SelectProfile(
- std::function<void(std::optional<Service::Account::UUID>)> callback) const override;
+ void SelectProfile(std::function<void(std::optional<Common::UUID>)> callback) const override;
signals:
void MainWindowSelectProfile() const;
private:
- void MainWindowFinishedSelection(std::optional<Service::Account::UUID> uuid);
+ void MainWindowFinishedSelection(std::optional<Common::UUID> uuid);
- mutable std::function<void(std::optional<Service::Account::UUID>)> callback;
+ mutable std::function<void(std::optional<Common::UUID>)> callback;
};
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index eeee603d1..9e420b359 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -440,8 +440,7 @@ void GRenderWindow::CaptureScreenshot(u16 res_scale, const QString& screenshot_p
layout);
}
-void GRenderWindow::OnMinimalClientAreaChangeRequest(
- const std::pair<unsigned, unsigned>& minimal_size) {
+void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<unsigned, unsigned> minimal_size) {
setMinimumSize(minimal_size.first, minimal_size.second);
}
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 3df33aca1..7f9f8e8e3 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -162,8 +162,7 @@ private:
void TouchUpdateEvent(const QTouchEvent* event);
void TouchEndEvent();
- void OnMinimalClientAreaChangeRequest(
- const std::pair<unsigned, unsigned>& minimal_size) override;
+ void OnMinimalClientAreaChangeRequest(std::pair<unsigned, unsigned> minimal_size) override;
QWidget* container = nullptr;
GGLWidgetInternal* child = nullptr;
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() {
UISettings::values.icon_size = ReadSetting(QStringLiteral("icon_size"), 64).toUInt();
UISettings::values.row_1_text_id = ReadSetting(QStringLiteral("row_1_text_id"), 3).toUInt();
UISettings::values.row_2_text_id = ReadSetting(QStringLiteral("row_2_text_id"), 2).toUInt();
+ UISettings::values.cache_game_list =
+ ReadSetting(QStringLiteral("cache_game_list"), true).toBool();
qt_config->endGroup();
}
@@ -1009,6 +1011,7 @@ void Config::SaveUIGamelistValues() {
WriteSetting(QStringLiteral("icon_size"), UISettings::values.icon_size, 64);
WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3);
WriteSetting(QStringLiteral("row_2_text_id"), UISettings::values.row_2_text_id, 2);
+ WriteSetting(QStringLiteral("cache_game_list"), UISettings::values.cache_game_list, true);
qt_config->endGroup();
}
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 @@
#include <QTimer>
#include <QTreeView>
+#include "common/common_paths.h"
+#include "common/file_util.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/xts_archive.h"
@@ -79,6 +81,14 @@ void ConfigurePerGameGeneral::applyConfiguration() {
disabled_addons.push_back(item.front()->text().toStdString());
}
+ auto current = Settings::values.disabled_addons[title_id];
+ std::sort(disabled_addons.begin(), disabled_addons.end());
+ std::sort(current.begin(), current.end());
+ if (disabled_addons != current) {
+ FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
+ "game_list" + DIR_SEP + fmt::format("{:016X}.pv.txt", title_id));
+ }
+
Settings::values.disabled_addons[title_id] = disabled_addons;
}
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index 002a51780..6d7d04c98 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -33,14 +33,13 @@ constexpr std::array<u8, 107> backup_jpeg{
0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
};
-QString GetImagePath(Service::Account::UUID uuid) {
+QString GetImagePath(Common::UUID uuid) {
const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
"/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg";
return QString::fromStdString(path);
}
-QString GetAccountUsername(const Service::Account::ProfileManager& manager,
- Service::Account::UUID uuid) {
+QString GetAccountUsername(const Service::Account::ProfileManager& manager, Common::UUID uuid) {
Service::Account::ProfileBase profile;
if (!manager.GetProfileBase(uuid, profile)) {
return {};
@@ -51,14 +50,14 @@ QString GetAccountUsername(const Service::Account::ProfileManager& manager,
return QString::fromStdString(text);
}
-QString FormatUserEntryText(const QString& username, Service::Account::UUID uuid) {
+QString FormatUserEntryText(const QString& username, Common::UUID uuid) {
return ConfigureProfileManager::tr("%1\n%2",
"%1 is the profile username, %2 is the formatted UUID (e.g. "
"00112233-4455-6677-8899-AABBCCDDEEFF))")
.arg(username, QString::fromStdString(uuid.FormatSwitch()));
}
-QPixmap GetIcon(Service::Account::UUID uuid) {
+QPixmap GetIcon(Common::UUID uuid) {
QPixmap icon{GetImagePath(uuid)};
if (!icon) {
@@ -190,7 +189,7 @@ void ConfigureProfileManager::AddUser() {
return;
}
- const auto uuid = Service::Account::UUID::Generate();
+ const auto uuid = Common::UUID::Generate();
profile_manager->CreateNewUser(uuid, username.toStdString());
item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)});
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 @@
#include <QDir>
#include <QFileInfo>
+#include <QSettings>
#include "common/common_paths.h"
#include "common/file_util.h"
@@ -30,13 +31,119 @@
#include "yuzu/ui_settings.h"
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();
+ }
+
+ return str;
+ }
+
+ std::ifstream stream(path);
+
+ if (stream) {
+ const std::string out(std::istreambuf_iterator<char>{stream},
+ std::istreambuf_iterator<char>{});
+ 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");
+ if (!file1.IsOpen()) {
+ LOG_ERROR(Frontend, "Failed to open cache file.");
+ return generator();
+ }
+
+ if (!file1.Resize(icon.size())) {
+ LOG_ERROR(Frontend, "Failed to resize cache file to necessary size.");
+ return generator();
+ }
+
+ if (file1.WriteBytes(icon.data(), icon.size()) != icon.size()) {
+ LOG_ERROR(Frontend, "Failed to write data to cache file.");
+ return generator();
+ }
+
+ std::ofstream stream2(path2, std::ios::out);
+ if (stream2) {
+ stream2 << nacp;
+ }
+
+ return std::make_pair(icon, nacp);
+ }
+
+ FileUtil::IOFile file1(path1, "rb");
+ std::ifstream stream2(path2);
+
+ if (!file1.IsOpen()) {
+ LOG_ERROR(Frontend, "Failed to open cache file for reading.");
+ return generator();
+ }
+
+ if (!stream2) {
+ LOG_ERROR(Frontend, "Failed to open cache file for reading.");
+ return generator();
+ }
+
+ 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>{});
+ return std::make_pair(vec, out);
+ }
+
+ return generator();
+}
+
void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const FileSys::NCA& nca,
std::vector<u8>& icon, std::string& name) {
- auto [nacp, icon_file] = patch_manager.ParseControlNCA(nca);
- if (icon_file != nullptr)
- icon = icon_file->ReadAllBytes();
- if (nacp != nullptr)
- name = nacp->GetApplicationName();
+ std::tie(icon, name) = GetGameListCachedObject<std::pair<std::vector<u8>, std::string>>(
+ fmt::format("{:016X}", patch_manager.GetTitleID()), {}, [&patch_manager, &nca] {
+ const auto [nacp, icon_f] = patch_manager.ParseControlNCA(nca);
+ return std::make_pair(icon_f->ReadAllBytes(), nacp->GetApplicationName());
+ });
}
bool HasSupportedFileExtension(const std::string& file_name) {
@@ -114,8 +221,11 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
};
if (UISettings::values.show_add_ons) {
- list.insert(
- 2, new GameListItem(FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable())));
+ const auto patch_versions = GetGameListCachedObject<QString>(
+ fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] {
+ return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable());
+ });
+ list.insert(2, new GameListItem(patch_versions));
}
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() {
tr("The file was successfully installed."));
game_list->PopulateAsync(UISettings::values.game_directory_path,
UISettings::values.game_directory_deepscan);
+ FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) +
+ DIR_SEP + "game_list");
};
const auto failed = [this]() {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 7bf82e665..1137bbc7a 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -104,7 +104,7 @@ signals:
void ErrorDisplayFinished();
- void ProfileSelectorFinishedSelection(std::optional<Service::Account::UUID> uuid);
+ void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid);
void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
void SoftwareKeyboardFinishedCheckDialog();
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 {
uint8_t row_1_text_id;
uint8_t row_2_text_id;
std::atomic_bool is_game_list_reload_pending{false};
+ bool cache_game_list;
};
extern Values values;