(Very temporary) Add testing UI for external updates/DLC
Some checks failed
eden-license / license-header (pull_request_target) Failing after 27s
eden-build / source (pull_request) Has been skipped
eden-build / linux (pull_request) Successful in 22m13s
eden-build / android (pull_request) Successful in 15m5s
eden-build / windows (msvc) (pull_request) Successful in 58m23s

This is no where close to finished; it is just meant for testing purposes
Due to some game list cache issues i have to temporary remove it for now but it will added back once the proper UI is done
This commit is contained in:
Briar 2025-04-22 23:00:19 +02:00
parent 79ed4f6c2e
commit e8621f65bb
4 changed files with 120 additions and 37 deletions

View file

@ -1,6 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <memory>
#include <string>
#include <utility>
@ -30,39 +33,7 @@
#include "yuzu/uisettings.h"
namespace {
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 =
Common::FS::PathToUTF8String(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) /
"game_list" / fmt::format("{}.{}", filename, ext));
void(Common::FS::CreateParentDirs(path));
if (!Common::FS::Exists(path)) {
const auto str = generator();
QFile file{QString::fromStdString(path)};
if (file.open(QFile::WriteOnly)) {
file.write(str.toUtf8());
}
return str;
}
QFile file{QString::fromStdString(path)};
if (file.open(QFile::ReadOnly)) {
return QString::fromUtf8(file.readAll());
}
return generator();
}
std::pair<std::vector<u8>, std::string> GetGameListCachedObject(
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") {
@ -217,10 +188,11 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
new GameListItemPlayTime(play_time_manager.GetPlayTime(program_id)),
};
const auto patch_versions = GetGameListCachedObject(
fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] {
return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable());
});
// Don't use cache for patch version info - TODO: Actually make this work and cahce both external
// and nand updates / DLCs
// Right now, the cache is generated too soon and due to cotnent privder chanes
// only edternal updates/DLCs are cached.
const auto patch_versions = FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable());
list.insert(2, new GameListItem(patch_versions));
return list;

View file

@ -1,6 +1,9 @@
// SPDX-FileCopyrightText: Copyright yuzu/Citra Emulator Project / Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <cinttypes>
#include <clocale>
#include <cmath>
@ -24,6 +27,8 @@
#include <boost/container/flat_set.hpp>
// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
#include "core/file_sys/external_content_manager.h"
#include "applets/qt_amiibo_settings.h"
#include "applets/qt_controller.h"
#include "applets/qt_error.h"
@ -302,6 +307,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
#endif
system->Initialize();
RegisterExternalAddons();
Common::Log::Initialize();
Common::Log::Start();
@ -332,6 +338,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
RegisterMetaTypes();
InitializeWidgets();
SaveExternalAddons();
InitializeDebugWidgets();
InitializeRecentFileMenuActions();
InitializeHotkeys();
@ -559,6 +566,24 @@ GMainWindow::~GMainWindow() {
#endif
}
void GMainWindow::RegisterExternalAddons() {
const auto external_config_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "external_addon_paths.txt";
auto external_manager = FileSys::GetExternalContentManager();
external_manager->LoadRegisteredPaths(external_config_path.string());
}
void GMainWindow::SaveExternalAddons() {
const auto external_config_path = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "external_addon_paths.txt";
auto external_manager = FileSys::GetExternalContentManager();
LOG_INFO(Frontend, "Saving external file list...");
external_manager->SaveRegisteredPaths(external_config_path.string());
// Clear the game list cache before repopulating
Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "game_list");
game_list->PopulateAsync(UISettings::values.game_dirs);
}
void GMainWindow::RegisterMetaTypes() {
// Register integral and floating point types
qRegisterMetaType<u8>("u8");
@ -1516,6 +1541,8 @@ void GMainWindow::ConnectMenuEvents() {
connect_menu(ui->action_Install_File_NAND, &GMainWindow::OnMenuInstallToNAND);
connect_menu(ui->action_Exit, &QMainWindow::close);
connect_menu(ui->action_Load_Amiibo, &GMainWindow::OnLoadAmiibo);
connect_menu(ui->action_Select_External_File ,
&GMainWindow::OnMenuSelectExternalFile);
// Emulation
connect_menu(ui->action_Pause, &GMainWindow::OnPauseContinueGame);
@ -5156,6 +5183,71 @@ Service::AM::FrontendAppletParameters GMainWindow::LibraryAppletParameters(
};
}
void GMainWindow::OnMenuSelectExternalFile() {
if (system->IsPoweredOn()) {
QMessageBox::warning(this, tr("Error"),
tr("The game is running. Please close the game to select external files."));
return;
}
const QString extensions = tr("Nintendo Submission Package (*.nsp);;NX Card Image (*.xci)");
QString starting_dir = QString::fromStdString(UISettings::values.roms_path);
const QString file_path = QFileDialog::getOpenFileName(this, tr("Select External File"),
starting_dir, extensions);
if (file_path.isEmpty()) {
return;
}
if (!QFile::exists(file_path)) {
QMessageBox::warning(this, tr("Error"), tr("Selected file does not exist."));
return;
}
QFile test_file(file_path);
if (!test_file.open(QIODevice::ReadOnly)) {
QMessageBox::warning(this, tr("Error"),
tr("Selected file is not readable. Check file permissions."));
return;
}
test_file.close();
const auto file_path_std = file_path.toStdString();
const auto extension = QString::fromStdString(Common::ToLower(std::filesystem::path(file_path_std).extension().string()));
bool success = false;
if (extension == QStringLiteral(".nsp")) {
QProgressDialog progress(tr("Loading NSP file..."), tr("Cancel"), 0, 0, this);
progress.setWindowModality(Qt::WindowModal);
progress.show();
QApplication::processEvents();
try {
success = FileSys::GetExternalContentManager()->RequestRegisterExternalNSP(file_path_std);
} catch (const std::exception& e) {
QMessageBox::warning(this, tr("Error"),
tr("An error occurred processing the NSP file:\n%1").arg(QString::fromStdString(e.what())));
return;
}
progress.close();
} else {
QMessageBox::warning(this, tr("Error"),
tr("Unsupported file format. Supported formats are NSP and XCI."));
return;
}
if (!success) {
QMessageBox::warning(this, tr("Error"),
tr("Failed to register external file. It might be an invalid or unsupported format."));
return;
}
SaveExternalAddons();
QMessageBox::information(this, tr("Success"),
tr("External file successfully registered. It will be available as an update or DLC for matching games."));
}
void VolumeButton::wheelEvent(QWheelEvent* event) {
int num_degrees = event->angleDelta().y() / 8;

View file

@ -1,6 +1,9 @@
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <memory>
@ -326,6 +329,10 @@ private:
Service::AM::FrontendAppletParameters LibraryAppletParameters(u64 program_id,
Service::AM::AppletId applet_id);
void OnMenuSelectExternalFile();
void RegisterExternalAddons();
void SaveExternalAddons();
private slots:
void OnStartGame();
void OnRestartGame();

View file

@ -69,6 +69,8 @@
<addaction name="action_Open_yuzu_Folder"/>
<addaction name="separator"/>
<addaction name="action_Exit"/>
<addaction name="separator"/>
<addaction name="action_Select_External_File"/>
</widget>
<widget class="QMenu" name="menu_Emulation">
<property name="title">
@ -209,6 +211,16 @@
<string>L&amp;oad File...</string>
</property>
</action>
<action name="action_Select_External_File">
<property name="text">
<string>Select External Addon File...</string>
</property>
</action>
<action name="action_Manage_External_Files">
<property name="text">
<string>Manage External Files...</string>
</property>
</action>
<action name="action_Load_Folder">
<property name="text">
<string>Load &amp;Folder...</string>