[qt_common] reorg, move more stuff out of main
Signed-off-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
parent
75f18095e0
commit
ca349ad7b0
20 changed files with 923 additions and 680 deletions
|
@ -1,6 +1,7 @@
|
||||||
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
find_package(Qt6 REQUIRED COMPONENTS Core)
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Core)
|
find_package(Qt6 REQUIRED COMPONENTS Core)
|
||||||
|
|
||||||
add_library(qt_common STATIC
|
add_library(qt_common STATIC
|
||||||
|
@ -18,11 +19,15 @@ add_library(qt_common STATIC
|
||||||
qt_path_util.h qt_path_util.cpp
|
qt_path_util.h qt_path_util.cpp
|
||||||
qt_game_util.h qt_game_util.cpp
|
qt_game_util.h qt_game_util.cpp
|
||||||
qt_frontend_util.h qt_frontend_util.cpp
|
qt_frontend_util.h qt_frontend_util.cpp
|
||||||
|
qt_meta.h qt_meta.cpp
|
||||||
|
qt_content_util.h qt_content_util.cpp
|
||||||
|
qt_rom_util.h qt_rom_util.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
create_target_directory_groups(qt_common)
|
create_target_directory_groups(qt_common)
|
||||||
target_link_libraries(qt_common PUBLIC core Qt6::Widgets SimpleIni::SimpleIni QuaZip::QuaZip)
|
target_link_libraries(qt_common PUBLIC core Qt6::Widgets SimpleIni::SimpleIni QuaZip::QuaZip)
|
||||||
target_link_libraries(qt_common PRIVATE Qt6::Core)
|
target_link_libraries(qt_common PRIVATE Qt6::Core)
|
||||||
|
target_link_libraries(qt_common PRIVATE Qt6::Core)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
target_include_directories(qt_common PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
|
target_include_directories(qt_common PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
|
||||||
|
|
|
@ -2,11 +2,6 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include "qt_common.h"
|
#include "qt_common.h"
|
||||||
#include "common/fs/fs.h"
|
|
||||||
#include "common/fs/path_util.h"
|
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
|
||||||
#include "frontend_common/firmware_manager.h"
|
|
||||||
#include "uisettings.h"
|
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QStringLiteral>
|
#include <QStringLiteral>
|
||||||
|
@ -16,7 +11,6 @@
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include "qt_frontend_util.h"
|
|
||||||
|
|
||||||
#include <JlCompress.h>
|
#include <JlCompress.h>
|
||||||
|
|
||||||
|
@ -27,19 +21,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace QtCommon {
|
namespace QtCommon {
|
||||||
MetadataResult ResetMetadata()
|
|
||||||
{
|
QObject *rootObject = nullptr;
|
||||||
if (!Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir)
|
Core::System *system = nullptr;
|
||||||
/ "game_list/")) {
|
|
||||||
return MetadataResult::Empty;
|
|
||||||
} else if (Common::FS::RemoveDirRecursively(
|
|
||||||
Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list")) {
|
|
||||||
return MetadataResult::Success;
|
|
||||||
UISettings::values.is_game_list_reload_pending.exchange(true);
|
|
||||||
} else {
|
|
||||||
return MetadataResult::Failure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Core::Frontend::WindowSystemType GetWindowSystemType()
|
Core::Frontend::WindowSystemType GetWindowSystemType()
|
||||||
{
|
{
|
||||||
|
@ -86,157 +70,14 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
|
||||||
return wsi;
|
return wsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
FirmwareInstallResult InstallFirmware(
|
const QString tr(const char* str)
|
||||||
const QString& location,
|
|
||||||
bool recursive,
|
|
||||||
std::function<bool(std::size_t, std::size_t)> QtProgressCallback,
|
|
||||||
Core::System* system,
|
|
||||||
FileSys::VfsFilesystem* vfs,
|
|
||||||
QWidget* parent)
|
|
||||||
{
|
{
|
||||||
static constexpr const char* failedTitle = "Firmware Install Failed";
|
return QGuiApplication::tr(str);
|
||||||
static constexpr const char* successTitle = "Firmware Install Failed";
|
|
||||||
static constexpr QMessageBox::StandardButtons buttons = QMessageBox::Ok;
|
|
||||||
|
|
||||||
QMessageBox::Icon icon;
|
|
||||||
FirmwareInstallResult result;
|
|
||||||
|
|
||||||
const auto ShowMessage = [&]() {
|
|
||||||
QtCommon::Frontend::ShowMessage(icon,
|
|
||||||
failedTitle,
|
|
||||||
GetFirmwareInstallResultString(result),
|
|
||||||
buttons,
|
|
||||||
parent);
|
|
||||||
};
|
|
||||||
|
|
||||||
LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString());
|
|
||||||
|
|
||||||
// Check for a reasonable number of .nca files (don't hardcode them, just see if there's some in
|
|
||||||
// there.)
|
|
||||||
std::filesystem::path firmware_source_path = location.toStdString();
|
|
||||||
if (!Common::FS::IsDir(firmware_source_path)) {
|
|
||||||
return FirmwareInstallResult::NoOp;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::filesystem::path> out;
|
|
||||||
const Common::FS::DirEntryCallable callback =
|
|
||||||
[&out](const std::filesystem::directory_entry& entry) {
|
|
||||||
if (entry.path().has_extension() && entry.path().extension() == ".nca") {
|
|
||||||
out.emplace_back(entry.path());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
QtProgressCallback(100, 10);
|
|
||||||
|
|
||||||
if (recursive) {
|
|
||||||
Common::FS::IterateDirEntriesRecursively(firmware_source_path,
|
|
||||||
callback,
|
|
||||||
Common::FS::DirEntryFilter::File);
|
|
||||||
} else {
|
|
||||||
Common::FS::IterateDirEntries(firmware_source_path,
|
|
||||||
callback,
|
|
||||||
Common::FS::DirEntryFilter::File);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.size() <= 0) {
|
|
||||||
result = FirmwareInstallResult::NoNCAs;
|
|
||||||
icon = QMessageBox::Warning;
|
|
||||||
ShowMessage();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Locate and erase the content of nand/system/Content/registered/*.nca, if any.
|
|
||||||
auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory();
|
|
||||||
if (sysnand_content_vdir->IsWritable()
|
|
||||||
&& !sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) {
|
|
||||||
result = FirmwareInstallResult::FailedDelete;
|
|
||||||
icon = QMessageBox::Critical;
|
|
||||||
ShowMessage();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO(Frontend,
|
|
||||||
"Cleaned nand/system/Content/registered folder in preparation for new firmware.");
|
|
||||||
|
|
||||||
QtProgressCallback(100, 20);
|
|
||||||
|
|
||||||
auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered");
|
|
||||||
|
|
||||||
bool success = true;
|
|
||||||
int i = 0;
|
|
||||||
for (const auto& firmware_src_path : out) {
|
|
||||||
i++;
|
|
||||||
auto firmware_src_vfile = vfs->OpenFile(firmware_src_path.generic_string(),
|
|
||||||
FileSys::OpenMode::Read);
|
|
||||||
auto firmware_dst_vfile = firmware_vdir
|
|
||||||
->CreateFileRelative(firmware_src_path.filename().string());
|
|
||||||
|
|
||||||
if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) {
|
|
||||||
LOG_ERROR(Frontend,
|
|
||||||
"Failed to copy firmware file {} to {} in registered folder!",
|
|
||||||
firmware_src_path.generic_string(),
|
|
||||||
firmware_src_path.filename().string());
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (QtProgressCallback(100,
|
|
||||||
20
|
|
||||||
+ static_cast<int>(((i) / static_cast<float>(out.size()))
|
|
||||||
* 70.0))) {
|
|
||||||
result = FirmwareInstallResult::FailedCorrupted;
|
|
||||||
icon = QMessageBox::Warning;
|
|
||||||
ShowMessage();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
result = FirmwareInstallResult::FailedCopy;
|
|
||||||
icon = QMessageBox::Critical;
|
|
||||||
ShowMessage();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-scan VFS for the newly placed firmware files.
|
|
||||||
system->GetFileSystemController().CreateFactories(*vfs);
|
|
||||||
|
|
||||||
const auto pair = FirmwareManager::GetFirmwareVersion(*system);
|
|
||||||
const auto firmware_data = pair.first;
|
|
||||||
const std::string display_version(firmware_data.display_version.data());
|
|
||||||
|
|
||||||
result = FirmwareInstallResult::Success;
|
|
||||||
QtCommon::Frontend::ShowMessage(QMessageBox::Information,
|
|
||||||
qApp->tr(successTitle),
|
|
||||||
qApp->tr(GetFirmwareInstallResultString(result))
|
|
||||||
.arg(QString::fromStdString(display_version)),
|
|
||||||
buttons,
|
|
||||||
parent);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString UnzipFirmwareToTmp(const QString& location)
|
const QString tr(const std::string& str)
|
||||||
{
|
{
|
||||||
namespace fs = std::filesystem;
|
return QGuiApplication::tr(str.c_str());
|
||||||
fs::path tmp{fs::temp_directory_path()};
|
|
||||||
|
|
||||||
if (!fs::create_directories(tmp / "eden" / "firmware")) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp /= "eden";
|
|
||||||
tmp /= "firmware";
|
|
||||||
|
|
||||||
QString qCacheDir = QString::fromStdString(tmp.string());
|
|
||||||
|
|
||||||
QFile zip(location);
|
|
||||||
|
|
||||||
QStringList result = JlCompress::extractDir(&zip, qCacheDir);
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return qCacheDir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QtCommon
|
} // namespace QtCommon
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
#ifndef QT_COMMON_H
|
#ifndef QT_COMMON_H
|
||||||
#define QT_COMMON_H
|
#define QT_COMMON_H
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include <core/frontend/emu_window.h>
|
#include <core/frontend/emu_window.h>
|
||||||
|
@ -13,68 +11,28 @@
|
||||||
#include <core/file_sys/vfs/vfs_real.h>
|
#include <core/file_sys/vfs/vfs_real.h>
|
||||||
|
|
||||||
namespace QtCommon {
|
namespace QtCommon {
|
||||||
static constexpr std::array<const char *, 3> METADATA_RESULTS = {
|
|
||||||
"The operation completed successfully.",
|
|
||||||
"The metadata cache couldn't be deleted. It might be in use or non-existent.",
|
|
||||||
"The metadata cache is already empty.",
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MetadataResult {
|
extern QObject *rootObject;
|
||||||
Success,
|
extern Core::System *system;
|
||||||
Failure,
|
|
||||||
Empty,
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* @brief ResetMetadata Reset game list metadata.
|
|
||||||
* @return A result code.
|
|
||||||
*/
|
|
||||||
MetadataResult ResetMetadata();
|
|
||||||
|
|
||||||
/**
|
typedef std::function<bool(std::size_t, std::size_t)> QtProgressCallback;
|
||||||
* \brief Get a string representation of a result from ResetMetadata.
|
|
||||||
* \param result The result code.
|
|
||||||
* \return A string representation of the passed result code.
|
|
||||||
*/
|
|
||||||
inline constexpr const char *GetResetMetadataResultString(MetadataResult result)
|
|
||||||
{
|
|
||||||
return METADATA_RESULTS.at(static_cast<std::size_t>(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr std::array<const char *, 6> FIRMWARE_RESULTS
|
|
||||||
= {"Successfully installed firmware version %1",
|
|
||||||
"",
|
|
||||||
"Unable to locate potential firmware NCA files",
|
|
||||||
"Failed to delete one or more firmware files.",
|
|
||||||
"One or more firmware files failed to copy into NAND.",
|
|
||||||
"Firmware installation cancelled, firmware may be in a bad state or corrupted."
|
|
||||||
"Restart Eden or re-install firmware."};
|
|
||||||
|
|
||||||
enum class FirmwareInstallResult {
|
|
||||||
Success,
|
|
||||||
NoOp,
|
|
||||||
NoNCAs,
|
|
||||||
FailedDelete,
|
|
||||||
FailedCopy,
|
|
||||||
FailedCorrupted,
|
|
||||||
};
|
|
||||||
|
|
||||||
FirmwareInstallResult InstallFirmware(
|
|
||||||
const QString &location,
|
|
||||||
bool recursive,
|
|
||||||
std::function<bool(std::size_t, std::size_t)> QtProgressCallback,
|
|
||||||
Core::System *system,
|
|
||||||
FileSys::VfsFilesystem *vfs,
|
|
||||||
QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
QString UnzipFirmwareToTmp(const QString &location);
|
|
||||||
|
|
||||||
inline constexpr const char *GetFirmwareInstallResultString(FirmwareInstallResult result)
|
|
||||||
{
|
|
||||||
return FIRMWARE_RESULTS.at(static_cast<std::size_t>(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
Core::Frontend::WindowSystemType GetWindowSystemType();
|
Core::Frontend::WindowSystemType GetWindowSystemType();
|
||||||
|
|
||||||
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow *window);
|
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow *window);
|
||||||
|
|
||||||
|
static inline void SetRootObject(QObject *parent)
|
||||||
|
{
|
||||||
|
rootObject = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void SetSystem(Core::System *newSystem)
|
||||||
|
{
|
||||||
|
system = newSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString tr(const char *str);
|
||||||
|
const QString tr(const std::string &str);
|
||||||
|
|
||||||
} // namespace QtCommon
|
} // namespace QtCommon
|
||||||
#endif
|
#endif
|
||||||
|
|
202
src/qt_common/qt_content_util.cpp
Normal file
202
src/qt_common/qt_content_util.cpp
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
#include "qt_content_util.h"
|
||||||
|
#include "common/fs/fs.h"
|
||||||
|
#include "frontend_common/content_manager.h"
|
||||||
|
#include "frontend_common/firmware_manager.h"
|
||||||
|
#include "qt_common/qt_game_util.h"
|
||||||
|
#include "qt_frontend_util.h"
|
||||||
|
|
||||||
|
#include <JlCompress.h>
|
||||||
|
|
||||||
|
namespace QtCommon::Content {
|
||||||
|
|
||||||
|
bool CheckGameFirmware(u64 program_id, Core::System &system, QObject *parent)
|
||||||
|
{
|
||||||
|
if (FirmwareManager::GameRequiresFirmware(program_id)
|
||||||
|
&& !FirmwareManager::CheckFirmwarePresence(system)) {
|
||||||
|
auto result = QtCommon::Frontend::ShowMessage(
|
||||||
|
QMessageBox::Warning,
|
||||||
|
"Game Requires Firmware",
|
||||||
|
"The game you are trying to launch requires firmware to boot or to get past the "
|
||||||
|
"opening menu. Please <a href='https://yuzu-mirror.github.io/help/quickstart'>"
|
||||||
|
"dump and install firmware</a>, or press \"OK\" to launch anyways.",
|
||||||
|
QMessageBox::Ok | QMessageBox::Cancel,
|
||||||
|
parent);
|
||||||
|
|
||||||
|
return result == QMessageBox::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FirmwareInstallResult InstallFirmware(
|
||||||
|
const QString& location,
|
||||||
|
bool recursive,
|
||||||
|
QtProgressCallback callback,
|
||||||
|
FileSys::VfsFilesystem* vfs)
|
||||||
|
{
|
||||||
|
static constexpr const char* failedTitle = "Firmware Install Failed";
|
||||||
|
static constexpr const char* successTitle = "Firmware Install Failed";
|
||||||
|
static constexpr QMessageBox::StandardButtons buttons = QMessageBox::Ok;
|
||||||
|
|
||||||
|
QMessageBox::Icon icon;
|
||||||
|
FirmwareInstallResult result;
|
||||||
|
|
||||||
|
const auto ShowMessage = [&]() {
|
||||||
|
QtCommon::Frontend::ShowMessage(icon,
|
||||||
|
failedTitle,
|
||||||
|
GetFirmwareInstallResultString(result),
|
||||||
|
buttons,
|
||||||
|
rootObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString());
|
||||||
|
|
||||||
|
// Check for a reasonable number of .nca files (don't hardcode them, just see if there's some in
|
||||||
|
// there.)
|
||||||
|
std::filesystem::path firmware_source_path = location.toStdString();
|
||||||
|
if (!Common::FS::IsDir(firmware_source_path)) {
|
||||||
|
return FirmwareInstallResult::NoOp;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::filesystem::path> out;
|
||||||
|
const Common::FS::DirEntryCallable dir_callback =
|
||||||
|
[&out](const std::filesystem::directory_entry& entry) {
|
||||||
|
if (entry.path().has_extension() && entry.path().extension() == ".nca") {
|
||||||
|
out.emplace_back(entry.path());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
callback(100, 10);
|
||||||
|
|
||||||
|
if (recursive) {
|
||||||
|
Common::FS::IterateDirEntriesRecursively(firmware_source_path,
|
||||||
|
dir_callback,
|
||||||
|
Common::FS::DirEntryFilter::File);
|
||||||
|
} else {
|
||||||
|
Common::FS::IterateDirEntries(firmware_source_path,
|
||||||
|
dir_callback,
|
||||||
|
Common::FS::DirEntryFilter::File);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out.size() <= 0) {
|
||||||
|
result = FirmwareInstallResult::NoNCAs;
|
||||||
|
icon = QMessageBox::Warning;
|
||||||
|
ShowMessage();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate and erase the content of nand/system/Content/registered/*.nca, if any.
|
||||||
|
auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory();
|
||||||
|
if (sysnand_content_vdir->IsWritable()
|
||||||
|
&& !sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) {
|
||||||
|
result = FirmwareInstallResult::FailedDelete;
|
||||||
|
icon = QMessageBox::Critical;
|
||||||
|
ShowMessage();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO(Frontend,
|
||||||
|
"Cleaned nand/system/Content/registered folder in preparation for new firmware.");
|
||||||
|
|
||||||
|
callback(100, 20);
|
||||||
|
|
||||||
|
auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered");
|
||||||
|
|
||||||
|
bool success = true;
|
||||||
|
int i = 0;
|
||||||
|
for (const auto& firmware_src_path : out) {
|
||||||
|
i++;
|
||||||
|
auto firmware_src_vfile = vfs->OpenFile(firmware_src_path.generic_string(),
|
||||||
|
FileSys::OpenMode::Read);
|
||||||
|
auto firmware_dst_vfile = firmware_vdir
|
||||||
|
->CreateFileRelative(firmware_src_path.filename().string());
|
||||||
|
|
||||||
|
if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) {
|
||||||
|
LOG_ERROR(Frontend,
|
||||||
|
"Failed to copy firmware file {} to {} in registered folder!",
|
||||||
|
firmware_src_path.generic_string(),
|
||||||
|
firmware_src_path.filename().string());
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback(100, 20 + static_cast<int>(((i) / static_cast<float>(out.size())) * 70.0))) {
|
||||||
|
result = FirmwareInstallResult::FailedCorrupted;
|
||||||
|
icon = QMessageBox::Warning;
|
||||||
|
ShowMessage();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
result = FirmwareInstallResult::FailedCopy;
|
||||||
|
icon = QMessageBox::Critical;
|
||||||
|
ShowMessage();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-scan VFS for the newly placed firmware files.
|
||||||
|
system->GetFileSystemController().CreateFactories(*vfs);
|
||||||
|
|
||||||
|
const auto pair = FirmwareManager::GetFirmwareVersion(*system);
|
||||||
|
const auto firmware_data = pair.first;
|
||||||
|
const std::string display_version(firmware_data.display_version.data());
|
||||||
|
|
||||||
|
result = FirmwareInstallResult::Success;
|
||||||
|
QtCommon::Frontend::Information(rootObject,
|
||||||
|
tr(successTitle),
|
||||||
|
tr(GetFirmwareInstallResultString(result))
|
||||||
|
.arg(QString::fromStdString(display_version)),
|
||||||
|
buttons);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UnzipFirmwareToTmp(const QString& location)
|
||||||
|
{
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
fs::path tmp{fs::temp_directory_path()};
|
||||||
|
|
||||||
|
if (!fs::create_directories(tmp / "eden" / "firmware")) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp /= "eden";
|
||||||
|
tmp /= "firmware";
|
||||||
|
|
||||||
|
QString qCacheDir = QString::fromStdString(tmp.string());
|
||||||
|
|
||||||
|
QFile zip(location);
|
||||||
|
|
||||||
|
QStringList result = JlCompress::extractDir(&zip, qCacheDir);
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return qCacheDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content //
|
||||||
|
void VerifyGameContents(const std::string& game_path, QtProgressCallback callback) {
|
||||||
|
const auto result = ContentManager::VerifyGameContents(*system, game_path, callback);
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case ContentManager::GameVerificationResult::Success:
|
||||||
|
QtCommon::Frontend::Information(rootObject, tr("Integrity verification succeeded!"),
|
||||||
|
tr("The operation completed successfully."));
|
||||||
|
break;
|
||||||
|
case ContentManager::GameVerificationResult::Failed:
|
||||||
|
QtCommon::Frontend::Critical(rootObject, tr("Integrity verification failed!"),
|
||||||
|
tr("File contents may be corrupt or missing."));
|
||||||
|
break;
|
||||||
|
case ContentManager::GameVerificationResult::NotImplemented:
|
||||||
|
QtCommon::Frontend::Warning(
|
||||||
|
rootObject,
|
||||||
|
tr("Integrity verification couldn't be performed"),
|
||||||
|
tr("Firmware installation cancelled, firmware may be in a bad state or corrupted. "
|
||||||
|
"File contents could not be checked for validity."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
48
src/qt_common/qt_content_util.h
Normal file
48
src/qt_common/qt_content_util.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef QT_CONTENT_UTIL_H
|
||||||
|
#define QT_CONTENT_UTIL_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "qt_common/qt_common.h"
|
||||||
|
|
||||||
|
namespace QtCommon::Content {
|
||||||
|
|
||||||
|
//
|
||||||
|
bool CheckGameFirmware(u64 program_id, Core::System &system, QObject *parent);
|
||||||
|
|
||||||
|
static constexpr std::array<const char *, 6> FIRMWARE_RESULTS
|
||||||
|
= {"Successfully installed firmware version %1",
|
||||||
|
"",
|
||||||
|
"Unable to locate potential firmware NCA files",
|
||||||
|
"Failed to delete one or more firmware files.",
|
||||||
|
"One or more firmware files failed to copy into NAND.",
|
||||||
|
"Firmware installation cancelled, firmware may be in a bad state or corrupted."
|
||||||
|
"Restart Eden or re-install firmware."};
|
||||||
|
|
||||||
|
enum class FirmwareInstallResult {
|
||||||
|
Success,
|
||||||
|
NoOp,
|
||||||
|
NoNCAs,
|
||||||
|
FailedDelete,
|
||||||
|
FailedCopy,
|
||||||
|
FailedCorrupted,
|
||||||
|
};
|
||||||
|
|
||||||
|
FirmwareInstallResult InstallFirmware(
|
||||||
|
const QString &location,
|
||||||
|
bool recursive,
|
||||||
|
QtProgressCallback callback,
|
||||||
|
FileSys::VfsFilesystem *vfs);
|
||||||
|
|
||||||
|
QString UnzipFirmwareToTmp(const QString &location);
|
||||||
|
|
||||||
|
inline constexpr const char *GetFirmwareInstallResultString(FirmwareInstallResult result)
|
||||||
|
{
|
||||||
|
return FIRMWARE_RESULTS.at(static_cast<std::size_t>(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content //
|
||||||
|
void VerifyGameContents(const std::string &game_path, QtProgressCallback callback);
|
||||||
|
}
|
||||||
|
#endif // QT_CONTENT_UTIL_H
|
|
@ -4,27 +4,84 @@
|
||||||
#include "qt_frontend_util.h"
|
#include "qt_frontend_util.h"
|
||||||
|
|
||||||
namespace QtCommon::Frontend {
|
namespace QtCommon::Frontend {
|
||||||
|
|
||||||
QMessageBox::StandardButton ShowMessage(QMessageBox::Icon icon,
|
QMessageBox::StandardButton ShowMessage(QMessageBox::Icon icon,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &text,
|
const QString &text,
|
||||||
QMessageBox::StandardButtons buttons,
|
QMessageBox::StandardButtons buttons,
|
||||||
QWidget *parent)
|
QObject *parent)
|
||||||
{
|
{
|
||||||
#ifdef YUZU_QT_WIDGETS
|
#ifdef YUZU_QT_WIDGETS
|
||||||
QMessageBox *box = new QMessageBox(icon, title, text, buttons, parent);
|
QMessageBox *box = new QMessageBox(icon, title, text, buttons, (QWidget *) parent);
|
||||||
return static_cast<QMessageBox::StandardButton>(box->exec());
|
return static_cast<QMessageBox::StandardButton>(box->exec());
|
||||||
#endif
|
#endif
|
||||||
// TODO(crueter): If Qt Widgets is disabled...
|
// TODO(crueter): If Qt Widgets is disabled...
|
||||||
// need a way to reference icon/buttons too
|
// need a way to reference icon/buttons too
|
||||||
}
|
}
|
||||||
|
|
||||||
QMessageBox::StandardButton ShowMessage(QMessageBox::Icon icon,
|
QMessageBox::StandardButton Information(QObject *parent,
|
||||||
const char *title,
|
const QString &title,
|
||||||
const char *text,
|
const QString &text,
|
||||||
QMessageBox::StandardButtons buttons,
|
QMessageBox::StandardButtons buttons)
|
||||||
QWidget *parent)
|
|
||||||
{
|
{
|
||||||
return ShowMessage(icon, qApp->tr(title), qApp->tr(text), buttons, parent);
|
return ShowMessage(QMessageBox::Information, title, text, buttons, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Warning(QObject *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons)
|
||||||
|
{
|
||||||
|
return ShowMessage(QMessageBox::Warning, title, text, buttons, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Critical(QObject *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons)
|
||||||
|
{
|
||||||
|
return ShowMessage(QMessageBox::Critical, title, text, buttons, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Question(QObject *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons)
|
||||||
|
{
|
||||||
|
return ShowMessage(QMessageBox::Question, title, text, buttons, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Information(QObject *parent,
|
||||||
|
const char *title,
|
||||||
|
const char *text,
|
||||||
|
QMessageBox::StandardButtons buttons)
|
||||||
|
{
|
||||||
|
return ShowMessage(QMessageBox::Information, parent->tr(title), parent->tr(text), buttons, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Warning(QObject *parent,
|
||||||
|
const char *title,
|
||||||
|
const char *text,
|
||||||
|
QMessageBox::StandardButtons buttons)
|
||||||
|
{
|
||||||
|
return ShowMessage(QMessageBox::Warning, parent->tr(title), parent->tr(text), buttons, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Critical(QObject *parent,
|
||||||
|
const char *title,
|
||||||
|
const char *text,
|
||||||
|
QMessageBox::StandardButtons buttons)
|
||||||
|
{
|
||||||
|
return ShowMessage(QMessageBox::Critical, parent->tr(title), parent->tr(text), buttons, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Question(QObject *parent,
|
||||||
|
const char *title,
|
||||||
|
const char *text,
|
||||||
|
QMessageBox::StandardButtons buttons)
|
||||||
|
{
|
||||||
|
return ShowMessage(QMessageBox::Question, parent->tr(title), parent->tr(text), buttons, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace QtCommon::Frontend
|
} // namespace QtCommon::Frontend
|
||||||
|
|
|
@ -17,16 +17,52 @@
|
||||||
namespace QtCommon::Frontend {
|
namespace QtCommon::Frontend {
|
||||||
Q_NAMESPACE
|
Q_NAMESPACE
|
||||||
|
|
||||||
|
// TODO(crueter) widgets-less impl, choices et al.
|
||||||
QMessageBox::StandardButton ShowMessage(QMessageBox::Icon icon,
|
QMessageBox::StandardButton ShowMessage(QMessageBox::Icon icon,
|
||||||
const QString &title,
|
const QString &title,
|
||||||
const QString &text,
|
const QString &text,
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::NoButton,
|
QMessageBox::StandardButtons buttons = QMessageBox::NoButton,
|
||||||
QWidget *parent = nullptr);
|
QObject *parent = nullptr);
|
||||||
|
|
||||||
QMessageBox::StandardButton ShowMessage(QMessageBox::Icon icon,
|
QMessageBox::StandardButton Information(QObject *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Warning(QObject *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Critical(QObject *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Question(QObject *parent,
|
||||||
|
const QString &title,
|
||||||
|
const QString &text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Information(QObject *parent,
|
||||||
const char *title,
|
const char *title,
|
||||||
const char *text,
|
const char *text,
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::NoButton,
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
QWidget *parent = nullptr);
|
|
||||||
|
QMessageBox::StandardButton Warning(QObject *parent,
|
||||||
|
const char *title,
|
||||||
|
const char *text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Critical(QObject *parent,
|
||||||
|
const char *title,
|
||||||
|
const char *text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
QMessageBox::StandardButton Question(QObject *parent,
|
||||||
|
const char *title,
|
||||||
|
const char *text,
|
||||||
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
} // namespace QtCommon::Frontend
|
} // namespace QtCommon::Frontend
|
||||||
#endif // QT_FRONTEND_UTIL_H
|
#endif // QT_FRONTEND_UTIL_H
|
||||||
|
|
|
@ -4,40 +4,50 @@
|
||||||
#include "qt_game_util.h"
|
#include "qt_game_util.h"
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
|
#include "core/file_sys/savedata_factory.h"
|
||||||
|
#include "frontend_common/content_manager.h"
|
||||||
|
#include "qt_common.h"
|
||||||
|
#include "qt_common/uisettings.h"
|
||||||
|
#include "qt_frontend_util.h"
|
||||||
|
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <shlobj.h>
|
#include "common/scope_exit.h"
|
||||||
#include <windows.h>
|
#include "common/string_util.h"
|
||||||
#include "common/scope_exit.h"
|
#include <shlobj.h>
|
||||||
#include "common/string_util.h"
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include "fmt/ostream.h"
|
#include "fmt/ostream.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace QtCommon {
|
namespace QtCommon::Game {
|
||||||
|
|
||||||
bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
|
bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
|
||||||
const std::string& comment,
|
const std::string& comment,
|
||||||
const std::filesystem::path& icon_path,
|
const std::filesystem::path& icon_path,
|
||||||
const std::filesystem::path& command,
|
const std::filesystem::path& command,
|
||||||
const std::string& arguments, const std::string& categories,
|
const std::string& arguments,
|
||||||
const std::string& keywords, const std::string& name) try {
|
const std::string& categories,
|
||||||
|
const std::string& keywords,
|
||||||
|
const std::string& name)
|
||||||
|
try {
|
||||||
#ifdef _WIN32 // Windows
|
#ifdef _WIN32 // Windows
|
||||||
HRESULT hr = CoInitialize(nullptr);
|
HRESULT hr = CoInitialize(nullptr);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
LOG_ERROR(Frontend, "CoInitialize failed");
|
LOG_ERROR(Frontend, "CoInitialize failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SCOPE_EXIT {
|
SCOPE_EXIT
|
||||||
|
{
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
};
|
};
|
||||||
IShellLinkW* ps1 = nullptr;
|
IShellLinkW* ps1 = nullptr;
|
||||||
IPersistFile* persist_file = nullptr;
|
IPersistFile* persist_file = nullptr;
|
||||||
SCOPE_EXIT {
|
SCOPE_EXIT
|
||||||
|
{
|
||||||
if (persist_file != nullptr) {
|
if (persist_file != nullptr) {
|
||||||
persist_file->Release();
|
persist_file->Release();
|
||||||
}
|
}
|
||||||
|
@ -45,7 +55,10 @@ bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
|
||||||
ps1->Release();
|
ps1->Release();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW,
|
HRESULT hres = CoCreateInstance(CLSID_ShellLink,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
IID_IShellLinkW,
|
||||||
reinterpret_cast<void**>(&ps1));
|
reinterpret_cast<void**>(&ps1));
|
||||||
if (FAILED(hres)) {
|
if (FAILED(hres)) {
|
||||||
LOG_ERROR(Frontend, "Failed to create IShellLinkW instance");
|
LOG_ERROR(Frontend, "Failed to create IShellLinkW instance");
|
||||||
|
@ -115,17 +128,18 @@ bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
|
||||||
fmt::print(shortcut_stream, "Keywords={}\n", keywords);
|
fmt::print(shortcut_stream, "Keywords={}\n", keywords);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
#else // Unsupported platform
|
#else // Unsupported platform
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
} catch (const std::exception& e) {
|
||||||
catch (const std::exception& e) {
|
|
||||||
LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
|
LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name,
|
bool MakeShortcutIcoPath(const u64 program_id,
|
||||||
std::filesystem::path& out_icon_path) {
|
const std::string_view game_file_name,
|
||||||
|
std::filesystem::path& out_icon_path)
|
||||||
|
{
|
||||||
// Get path to Yuzu icons directory & icon extension
|
// Get path to Yuzu icons directory & icon extension
|
||||||
std::string ico_extension = "png";
|
std::string ico_extension = "png";
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -146,12 +160,13 @@ bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenEdenFolder(const Common::FS::EdenPath& path) {
|
void OpenEdenFolder(const Common::FS::EdenPath& path)
|
||||||
QDesktopServices::openUrl(QUrl(
|
{
|
||||||
QString::fromStdString(Common::FS::GetEdenPathString(path))));
|
QDesktopServices::openUrl(QUrl(QString::fromStdString(Common::FS::GetEdenPathString(path))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenRootDataFolder() {
|
void OpenRootDataFolder()
|
||||||
|
{
|
||||||
OpenEdenFolder(Common::FS::EdenPath::EdenDir);
|
OpenEdenFolder(Common::FS::EdenPath::EdenDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,4 +190,211 @@ void OpenLogFolder()
|
||||||
OpenEdenFolder(Common::FS::EdenPath::LogDir);
|
OpenEdenFolder(Common::FS::EdenPath::LogDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString GetGameListErrorRemoving(QtCommon::Game::InstalledEntryType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case QtCommon::Game::InstalledEntryType::Game:
|
||||||
|
return tr("Error Removing Contents");
|
||||||
|
case QtCommon::Game::InstalledEntryType::Update:
|
||||||
|
return tr("Error Removing Update");
|
||||||
|
case QtCommon::Game::InstalledEntryType::AddOnContent:
|
||||||
|
return tr("Error Removing DLC");
|
||||||
|
default:
|
||||||
|
return QStringLiteral("Error Removing <Invalid Type>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Game Content //
|
||||||
|
void RemoveBaseContent(u64 program_id, InstalledEntryType type)
|
||||||
|
{
|
||||||
|
const auto res = ContentManager::RemoveBaseContent(system->GetFileSystemController(),
|
||||||
|
program_id);
|
||||||
|
if (res) {
|
||||||
|
QtCommon::Frontend::Information(rootObject,
|
||||||
|
"Successfully Removed",
|
||||||
|
"Successfully removed the installed base game.");
|
||||||
|
} else {
|
||||||
|
QtCommon::Frontend::Warning(
|
||||||
|
rootObject,
|
||||||
|
GetGameListErrorRemoving(type),
|
||||||
|
tr("The base game is not installed in the NAND and cannot be removed."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveUpdateContent(u64 program_id, InstalledEntryType type)
|
||||||
|
{
|
||||||
|
const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id);
|
||||||
|
if (res) {
|
||||||
|
QtCommon::Frontend::Information(rootObject,
|
||||||
|
"Successfully Removed",
|
||||||
|
"Successfully removed the installed update.");
|
||||||
|
} else {
|
||||||
|
QtCommon::Frontend::Warning(rootObject,
|
||||||
|
GetGameListErrorRemoving(type),
|
||||||
|
tr("There is no update installed for this title."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAddOnContent(u64 program_id, InstalledEntryType type)
|
||||||
|
{
|
||||||
|
const size_t count = ContentManager::RemoveAllDLC(*system, program_id);
|
||||||
|
if (count == 0) {
|
||||||
|
QtCommon::Frontend::Warning(rootObject,
|
||||||
|
GetGameListErrorRemoving(type),
|
||||||
|
tr("There are no DLCs installed for this title."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QtCommon::Frontend::Information(rootObject,
|
||||||
|
tr("Successfully Removed"),
|
||||||
|
tr("Successfully removed %1 installed DLC.").arg(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global Content //
|
||||||
|
|
||||||
|
void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target)
|
||||||
|
{
|
||||||
|
const auto target_file_name = [target] {
|
||||||
|
switch (target) {
|
||||||
|
case GameListRemoveTarget::GlShaderCache:
|
||||||
|
return "opengl.bin";
|
||||||
|
case GameListRemoveTarget::VkShaderCache:
|
||||||
|
return "vulkan.bin";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
||||||
|
const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id);
|
||||||
|
const auto target_file = shader_cache_folder_path / target_file_name;
|
||||||
|
|
||||||
|
if (!Common::FS::Exists(target_file)) {
|
||||||
|
QtCommon::Frontend::Warning(rootObject,
|
||||||
|
tr("Error Removing Transferable Shader Cache"),
|
||||||
|
tr("A shader cache for this title does not exist."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Common::FS::RemoveFile(target_file)) {
|
||||||
|
QtCommon::Frontend::Information(rootObject,
|
||||||
|
tr("Successfully Removed"),
|
||||||
|
tr("Successfully removed the transferable shader cache."));
|
||||||
|
} else {
|
||||||
|
QtCommon::Frontend::Warning(rootObject,
|
||||||
|
tr("Error Removing Transferable Shader Cache"),
|
||||||
|
tr("Failed to remove the transferable shader cache."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveVulkanDriverPipelineCache(u64 program_id)
|
||||||
|
{
|
||||||
|
static constexpr std::string_view target_file_name = "vulkan_pipelines.bin";
|
||||||
|
|
||||||
|
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
||||||
|
const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id);
|
||||||
|
const auto target_file = shader_cache_folder_path / target_file_name;
|
||||||
|
|
||||||
|
if (!Common::FS::Exists(target_file)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Common::FS::RemoveFile(target_file)) {
|
||||||
|
QtCommon::Frontend::Warning(rootObject,
|
||||||
|
tr("Error Removing Vulkan Driver Pipeline Cache"),
|
||||||
|
tr("Failed to remove the driver pipeline cache."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAllTransferableShaderCaches(u64 program_id)
|
||||||
|
{
|
||||||
|
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
||||||
|
const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id);
|
||||||
|
|
||||||
|
if (!Common::FS::Exists(program_shader_cache_dir)) {
|
||||||
|
QtCommon::Frontend::Warning(rootObject,
|
||||||
|
tr("Error Removing Transferable Shader Caches"),
|
||||||
|
tr("A shader cache for this title does not exist."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Common::FS::RemoveDirRecursively(program_shader_cache_dir)) {
|
||||||
|
QtCommon::Frontend::Information(rootObject,
|
||||||
|
tr("Successfully Removed"),
|
||||||
|
tr("Successfully removed the transferable shader caches."));
|
||||||
|
} else {
|
||||||
|
QtCommon::Frontend::Warning(
|
||||||
|
rootObject,
|
||||||
|
tr("Error Removing Transferable Shader Caches"),
|
||||||
|
tr("Failed to remove the transferable shader cache directory."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path)
|
||||||
|
{
|
||||||
|
const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path));
|
||||||
|
const auto config_file_name = program_id == 0
|
||||||
|
? Common::FS::PathToUTF8String(file_path.filename())
|
||||||
|
.append(".ini")
|
||||||
|
: fmt::format("{:016X}.ini", program_id);
|
||||||
|
const auto custom_config_file_path = Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir)
|
||||||
|
/ "custom" / config_file_name;
|
||||||
|
|
||||||
|
if (!Common::FS::Exists(custom_config_file_path)) {
|
||||||
|
QtCommon::Frontend::Warning(rootObject,
|
||||||
|
tr("Error Removing Custom Configuration"),
|
||||||
|
tr("A custom configuration for this title does not exist."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Common::FS::RemoveFile(custom_config_file_path)) {
|
||||||
|
QtCommon::Frontend::Information(rootObject,
|
||||||
|
tr("Successfully Removed"),
|
||||||
|
tr("Successfully removed the custom game configuration."));
|
||||||
|
} else {
|
||||||
|
QtCommon::Frontend::Warning(rootObject,
|
||||||
|
tr("Error Removing Custom Configuration"),
|
||||||
|
tr("Failed to remove the custom game configuration."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveCacheStorage(u64 program_id, FileSys::VfsFilesystem* vfs)
|
||||||
|
{
|
||||||
|
const auto nand_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir);
|
||||||
|
auto vfs_nand_dir = vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir),
|
||||||
|
FileSys::OpenMode::Read);
|
||||||
|
|
||||||
|
const auto cache_storage_path
|
||||||
|
= FileSys::SaveDataFactory::GetFullPath({},
|
||||||
|
vfs_nand_dir,
|
||||||
|
FileSys::SaveDataSpaceId::User,
|
||||||
|
FileSys::SaveDataType::Cache,
|
||||||
|
0 /* program_id */,
|
||||||
|
{},
|
||||||
|
0);
|
||||||
|
|
||||||
|
const auto path = Common::FS::ConcatPathSafe(nand_dir, cache_storage_path);
|
||||||
|
|
||||||
|
// Not an error if it wasn't cleared.
|
||||||
|
Common::FS::RemoveDirRecursively(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata //
|
||||||
|
void ResetMetadata()
|
||||||
|
{
|
||||||
|
const QString title = tr("Reset Metadata Cache");
|
||||||
|
|
||||||
|
if (!Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir)
|
||||||
|
/ "game_list/")) {
|
||||||
|
QtCommon::Frontend::Warning(rootObject, title, tr("The metadata cache is already empty."));
|
||||||
|
} else if (Common::FS::RemoveDirRecursively(
|
||||||
|
Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list")) {
|
||||||
|
QtCommon::Frontend::Information(rootObject,
|
||||||
|
title,
|
||||||
|
tr("The operation completed successfully."));
|
||||||
|
UISettings::values.is_game_list_reload_pending.exchange(true);
|
||||||
|
} else {
|
||||||
|
QtCommon::Frontend::Warning(
|
||||||
|
rootObject,
|
||||||
|
title,
|
||||||
|
tr("The metadata cache couldn't be deleted. It might be in use or non-existent."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QtCommon::Game
|
||||||
|
|
|
@ -4,23 +4,25 @@
|
||||||
#ifndef QT_GAME_UTIL_H
|
#ifndef QT_GAME_UTIL_H
|
||||||
#define QT_GAME_UTIL_H
|
#define QT_GAME_UTIL_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "frontend_common/content_manager.h"
|
#include <core/file_sys/vfs/vfs.h>
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace QtCommon {
|
namespace QtCommon::Game {
|
||||||
|
|
||||||
static constexpr std::array<const char *, 3> GAME_VERIFICATION_RESULTS = {
|
enum class InstalledEntryType {
|
||||||
"The operation completed successfully.",
|
Game,
|
||||||
"File contents may be corrupt or missing..",
|
Update,
|
||||||
"Firmware installation cancelled, firmware may be in a bad state or corrupted. "
|
AddOnContent,
|
||||||
"File contents could not be checked for validity."
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr const char *GetGameVerificationResultString(ContentManager::GameVerificationResult result)
|
enum class GameListRemoveTarget {
|
||||||
{
|
GlShaderCache,
|
||||||
return GAME_VERIFICATION_RESULTS.at(static_cast<std::size_t>(result));
|
VkShaderCache,
|
||||||
}
|
AllShaderCache,
|
||||||
|
CustomConfiguration,
|
||||||
|
CacheStorage,
|
||||||
|
};
|
||||||
|
|
||||||
bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
|
bool CreateShortcutLink(const std::filesystem::path& shortcut_path,
|
||||||
const std::string& comment,
|
const std::string& comment,
|
||||||
|
@ -41,6 +43,20 @@ void OpenNANDFolder();
|
||||||
void OpenSDMCFolder();
|
void OpenSDMCFolder();
|
||||||
void OpenModFolder();
|
void OpenModFolder();
|
||||||
void OpenLogFolder();
|
void OpenLogFolder();
|
||||||
|
|
||||||
|
void RemoveBaseContent(u64 program_id, InstalledEntryType type);
|
||||||
|
void RemoveUpdateContent(u64 program_id, InstalledEntryType type);
|
||||||
|
void RemoveAddOnContent(u64 program_id, InstalledEntryType type);
|
||||||
|
|
||||||
|
void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target);
|
||||||
|
void RemoveVulkanDriverPipelineCache(u64 program_id);
|
||||||
|
void RemoveAllTransferableShaderCaches(u64 program_id);
|
||||||
|
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path);
|
||||||
|
void RemoveCacheStorage(u64 program_id, FileSys::VfsFilesystem* vfs);
|
||||||
|
|
||||||
|
// Metadata //
|
||||||
|
void ResetMetadata();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // QT_GAME_UTIL_H
|
#endif // QT_GAME_UTIL_H
|
||||||
|
|
72
src/qt_common/qt_meta.cpp
Normal file
72
src/qt_common/qt_meta.cpp
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
#include "qt_meta.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/frontend/applets/cabinet.h"
|
||||||
|
#include "core/frontend/applets/controller.h"
|
||||||
|
#include "core/frontend/applets/profile_select.h"
|
||||||
|
#include "core/frontend/applets/software_keyboard.h"
|
||||||
|
#include "core/hle/service/am/frontend/applet_web_browser_types.h"
|
||||||
|
|
||||||
|
namespace QtCommon::Meta {
|
||||||
|
|
||||||
|
void RegisterMetaTypes()
|
||||||
|
{
|
||||||
|
// Register integral and floating point types
|
||||||
|
qRegisterMetaType<u8>("u8");
|
||||||
|
qRegisterMetaType<u16>("u16");
|
||||||
|
qRegisterMetaType<u32>("u32");
|
||||||
|
qRegisterMetaType<u64>("u64");
|
||||||
|
qRegisterMetaType<u128>("u128");
|
||||||
|
qRegisterMetaType<s8>("s8");
|
||||||
|
qRegisterMetaType<s16>("s16");
|
||||||
|
qRegisterMetaType<s32>("s32");
|
||||||
|
qRegisterMetaType<s64>("s64");
|
||||||
|
qRegisterMetaType<f32>("f32");
|
||||||
|
qRegisterMetaType<f64>("f64");
|
||||||
|
|
||||||
|
// Register string types
|
||||||
|
qRegisterMetaType<std::string>("std::string");
|
||||||
|
qRegisterMetaType<std::wstring>("std::wstring");
|
||||||
|
qRegisterMetaType<std::u8string>("std::u8string");
|
||||||
|
qRegisterMetaType<std::u16string>("std::u16string");
|
||||||
|
qRegisterMetaType<std::u32string>("std::u32string");
|
||||||
|
qRegisterMetaType<std::string_view>("std::string_view");
|
||||||
|
qRegisterMetaType<std::wstring_view>("std::wstring_view");
|
||||||
|
qRegisterMetaType<std::u8string_view>("std::u8string_view");
|
||||||
|
qRegisterMetaType<std::u16string_view>("std::u16string_view");
|
||||||
|
qRegisterMetaType<std::u32string_view>("std::u32string_view");
|
||||||
|
|
||||||
|
// Register applet types
|
||||||
|
|
||||||
|
// Cabinet Applet
|
||||||
|
qRegisterMetaType<Core::Frontend::CabinetParameters>("Core::Frontend::CabinetParameters");
|
||||||
|
qRegisterMetaType<std::shared_ptr<Service::NFC::NfcDevice>>(
|
||||||
|
"std::shared_ptr<Service::NFC::NfcDevice>");
|
||||||
|
|
||||||
|
// Controller Applet
|
||||||
|
qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
|
||||||
|
|
||||||
|
// Profile Select Applet
|
||||||
|
qRegisterMetaType<Core::Frontend::ProfileSelectParameters>(
|
||||||
|
"Core::Frontend::ProfileSelectParameters");
|
||||||
|
|
||||||
|
// Software Keyboard Applet
|
||||||
|
qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>(
|
||||||
|
"Core::Frontend::KeyboardInitializeParameters");
|
||||||
|
qRegisterMetaType<Core::Frontend::InlineAppearParameters>(
|
||||||
|
"Core::Frontend::InlineAppearParameters");
|
||||||
|
qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters");
|
||||||
|
qRegisterMetaType<Service::AM::Frontend::SwkbdResult>("Service::AM::Frontend::SwkbdResult");
|
||||||
|
qRegisterMetaType<Service::AM::Frontend::SwkbdTextCheckResult>(
|
||||||
|
"Service::AM::Frontend::SwkbdTextCheckResult");
|
||||||
|
qRegisterMetaType<Service::AM::Frontend::SwkbdReplyType>(
|
||||||
|
"Service::AM::Frontend::SwkbdReplyType");
|
||||||
|
|
||||||
|
// Web Browser Applet
|
||||||
|
qRegisterMetaType<Service::AM::Frontend::WebExitReason>("Service::AM::Frontend::WebExitReason");
|
||||||
|
|
||||||
|
// Register loader types
|
||||||
|
qRegisterMetaType<Core::SystemResultStatus>("Core::SystemResultStatus");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
src/qt_common/qt_meta.h
Normal file
12
src/qt_common/qt_meta.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef QT_META_H
|
||||||
|
#define QT_META_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace QtCommon::Meta {
|
||||||
|
|
||||||
|
//
|
||||||
|
void RegisterMetaTypes();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // QT_META_H
|
|
@ -7,17 +7,22 @@
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
|
#include "qt_common/qt_frontend_util.h"
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
bool QtCommon::PathUtil::OpenShaderCache(u64 program_id)
|
namespace QtCommon::Path {
|
||||||
|
|
||||||
|
bool OpenShaderCache(u64 program_id, QObject *parent)
|
||||||
{
|
{
|
||||||
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
||||||
const auto shader_cache_folder_path{shader_cache_dir / fmt::format("{:016x}", program_id)};
|
const auto shader_cache_folder_path{shader_cache_dir / fmt::format("{:016x}", program_id)};
|
||||||
if (!Common::FS::CreateDirs(shader_cache_folder_path)) {
|
if (!Common::FS::CreateDirs(shader_cache_folder_path)) {
|
||||||
return false;
|
QtCommon::Frontend::ShowMessage(QMessageBox::Warning, "Error Opening Shader Cache", "Failed to create or open shader cache for this title, ensure your app data directory has write permissions.", QMessageBox::Ok, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto shader_path_string{Common::FS::PathToUTF8String(shader_cache_folder_path)};
|
const auto shader_path_string{Common::FS::PathToUTF8String(shader_cache_folder_path)};
|
||||||
const auto qt_shader_cache_path = QString::fromStdString(shader_path_string);
|
const auto qt_shader_cache_path = QString::fromStdString(shader_path_string);
|
||||||
return QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path));
|
return QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#define QT_PATH_UTIL_H
|
#define QT_PATH_UTIL_H
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
namespace QtCommon::PathUtil { bool OpenShaderCache(u64 program_id); }
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace QtCommon::Path { bool OpenShaderCache(u64 program_id, QObject *parent); }
|
||||||
|
|
||||||
#endif // QT_PATH_UTIL_H
|
#endif // QT_PATH_UTIL_H
|
||||||
|
|
75
src/qt_common/qt_rom_util.cpp
Normal file
75
src/qt_common/qt_rom_util.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include "qt_rom_util.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
namespace QtCommon::ROM {
|
||||||
|
|
||||||
|
bool RomFSRawCopy(size_t total_size,
|
||||||
|
size_t& read_size,
|
||||||
|
QtProgressCallback callback,
|
||||||
|
const FileSys::VirtualDir& src,
|
||||||
|
const FileSys::VirtualDir& dest,
|
||||||
|
bool full)
|
||||||
|
{
|
||||||
|
// TODO(crueter)
|
||||||
|
// if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable())
|
||||||
|
// return false;
|
||||||
|
// if (dialog.wasCanceled())
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
// std::vector<u8> buffer(CopyBufferSize);
|
||||||
|
// auto last_timestamp = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
// const auto QtRawCopy = [&](const FileSys::VirtualFile& src_file,
|
||||||
|
// const FileSys::VirtualFile& dest_file) {
|
||||||
|
// if (src_file == nullptr || dest_file == nullptr) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if (!dest_file->Resize(src_file->GetSize())) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (std::size_t i = 0; i < src_file->GetSize(); i += buffer.size()) {
|
||||||
|
// if (dialog.wasCanceled()) {
|
||||||
|
// dest_file->Resize(0);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// using namespace std::literals::chrono_literals;
|
||||||
|
// const auto new_timestamp = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
// if ((new_timestamp - last_timestamp) > 33ms) {
|
||||||
|
// last_timestamp = new_timestamp;
|
||||||
|
// dialog.setValue(
|
||||||
|
// static_cast<int>(std::min(read_size, total_size) * 100 / total_size));
|
||||||
|
// QCoreApplication::processEvents();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const auto read = src_file->Read(buffer.data(), buffer.size(), i);
|
||||||
|
// dest_file->Write(buffer.data(), read, i);
|
||||||
|
|
||||||
|
// read_size += read;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// if (full) {
|
||||||
|
// for (const auto& file : src->GetFiles()) {
|
||||||
|
// const auto out = VfsDirectoryCreateFileWrapper(dest, file->GetName());
|
||||||
|
// if (!QtRawCopy(file, out))
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (const auto& dir : src->GetSubdirectories()) {
|
||||||
|
// const auto out = dest->CreateSubdirectory(dir->GetName());
|
||||||
|
// if (!RomFSRawCopy(total_size, read_size, dialog, dir, out, full))
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
17
src/qt_common/qt_rom_util.h
Normal file
17
src/qt_common/qt_rom_util.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef QT_ROM_UTIL_H
|
||||||
|
#define QT_ROM_UTIL_H
|
||||||
|
|
||||||
|
#include "qt_common/qt_common.h"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace QtCommon::ROM {
|
||||||
|
|
||||||
|
bool RomFSRawCopy(size_t total_size,
|
||||||
|
size_t& read_size,
|
||||||
|
QtProgressCallback callback,
|
||||||
|
const FileSys::VirtualDir& src,
|
||||||
|
const FileSys::VirtualDir& dest,
|
||||||
|
bool full);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // QT_ROM_UTIL_H
|
|
@ -11,6 +11,7 @@
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "qt_common/qt_common.h"
|
#include "qt_common/qt_common.h"
|
||||||
|
#include "qt_common/qt_game_util.h"
|
||||||
#include "qt_common/uisettings.h"
|
#include "qt_common/uisettings.h"
|
||||||
#include "ui_configure_filesystem.h"
|
#include "ui_configure_filesystem.h"
|
||||||
|
|
||||||
|
@ -130,17 +131,7 @@ void ConfigureFilesystem::SetDirectory(DirectoryTarget target, QLineEdit* edit)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureFilesystem::ResetMetadata() {
|
void ConfigureFilesystem::ResetMetadata() {
|
||||||
auto result = QtCommon::ResetMetadata();
|
QtCommon::Game::ResetMetadata();
|
||||||
const QString resultMessage = tr(QtCommon::GetResetMetadataResultString(result));
|
|
||||||
const QString title = tr("Reset Metadata Cache");
|
|
||||||
|
|
||||||
switch (result) {
|
|
||||||
case QtCommon::MetadataResult::Failure:
|
|
||||||
QMessageBox::warning(this, title, resultMessage);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
QMessageBox::information(this, title, resultMessage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureFilesystem::UpdateEnabledControls() {
|
void ConfigureFilesystem::UpdateEnabledControls() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include <regex>
|
#include "yuzu/game_list.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
@ -13,19 +13,20 @@
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <fmt/ranges.h>
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
#include "core/file_sys/registered_cache.h"
|
#include "core/file_sys/registered_cache.h"
|
||||||
|
#include "qt_common/qt_game_util.h"
|
||||||
|
#include "qt_common/uisettings.h"
|
||||||
#include "yuzu/compatibility_list.h"
|
#include "yuzu/compatibility_list.h"
|
||||||
#include "yuzu/game_list.h"
|
|
||||||
#include "yuzu/game_list_p.h"
|
#include "yuzu/game_list_p.h"
|
||||||
#include "yuzu/game_list_worker.h"
|
#include "yuzu/game_list_worker.h"
|
||||||
#include "yuzu/main.h"
|
#include "yuzu/main.h"
|
||||||
#include "qt_common/uisettings.h"
|
|
||||||
#include "yuzu/util/controller_navigation.h"
|
#include "yuzu/util/controller_navigation.h"
|
||||||
|
#include <fmt/ranges.h>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist_, QObject* parent)
|
GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist_, QObject* parent)
|
||||||
: QObject(parent), gamelist{gamelist_} {}
|
: QObject(parent), gamelist{gamelist_} {}
|
||||||
|
@ -608,30 +609,30 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
|
||||||
connect(open_transferable_shader_cache, &QAction::triggered,
|
connect(open_transferable_shader_cache, &QAction::triggered,
|
||||||
[this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); });
|
[this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); });
|
||||||
connect(remove_all_content, &QAction::triggered, [this, program_id]() {
|
connect(remove_all_content, &QAction::triggered, [this, program_id]() {
|
||||||
emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::Game);
|
emit RemoveInstalledEntryRequested(program_id, QtCommon::Game::InstalledEntryType::Game);
|
||||||
});
|
});
|
||||||
connect(remove_update, &QAction::triggered, [this, program_id]() {
|
connect(remove_update, &QAction::triggered, [this, program_id]() {
|
||||||
emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::Update);
|
emit RemoveInstalledEntryRequested(program_id, QtCommon::Game::InstalledEntryType::Update);
|
||||||
});
|
});
|
||||||
connect(remove_dlc, &QAction::triggered, [this, program_id]() {
|
connect(remove_dlc, &QAction::triggered, [this, program_id]() {
|
||||||
emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::AddOnContent);
|
emit RemoveInstalledEntryRequested(program_id, QtCommon::Game::InstalledEntryType::AddOnContent);
|
||||||
});
|
});
|
||||||
connect(remove_gl_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
connect(remove_gl_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
||||||
emit RemoveFileRequested(program_id, GameListRemoveTarget::GlShaderCache, path);
|
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::GlShaderCache, path);
|
||||||
});
|
});
|
||||||
connect(remove_vk_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
connect(remove_vk_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
||||||
emit RemoveFileRequested(program_id, GameListRemoveTarget::VkShaderCache, path);
|
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::VkShaderCache, path);
|
||||||
});
|
});
|
||||||
connect(remove_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
connect(remove_shader_cache, &QAction::triggered, [this, program_id, path]() {
|
||||||
emit RemoveFileRequested(program_id, GameListRemoveTarget::AllShaderCache, path);
|
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::AllShaderCache, path);
|
||||||
});
|
});
|
||||||
connect(remove_custom_config, &QAction::triggered, [this, program_id, path]() {
|
connect(remove_custom_config, &QAction::triggered, [this, program_id, path]() {
|
||||||
emit RemoveFileRequested(program_id, GameListRemoveTarget::CustomConfiguration, path);
|
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::CustomConfiguration, path);
|
||||||
});
|
});
|
||||||
connect(remove_play_time_data, &QAction::triggered,
|
connect(remove_play_time_data, &QAction::triggered,
|
||||||
[this, program_id]() { emit RemovePlayTimeRequested(program_id); });
|
[this, program_id]() { emit RemovePlayTimeRequested(program_id); });
|
||||||
connect(remove_cache_storage, &QAction::triggered, [this, program_id, path] {
|
connect(remove_cache_storage, &QAction::triggered, [this, program_id, path] {
|
||||||
emit RemoveFileRequested(program_id, GameListRemoveTarget::CacheStorage, path);
|
emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::CacheStorage, path);
|
||||||
});
|
});
|
||||||
connect(dump_romfs, &QAction::triggered, [this, program_id, path]() {
|
connect(dump_romfs, &QAction::triggered, [this, program_id, path]() {
|
||||||
emit DumpRomFSRequested(program_id, path, DumpRomFSTarget::Normal);
|
emit DumpRomFSRequested(program_id, path, DumpRomFSTarget::Normal);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "qt_common/uisettings.h"
|
#include "qt_common/uisettings.h"
|
||||||
|
#include "qt_common/qt_game_util.h"
|
||||||
#include "yuzu/compatibility_list.h"
|
#include "yuzu/compatibility_list.h"
|
||||||
#include "yuzu/play_time_manager.h"
|
#include "yuzu/play_time_manager.h"
|
||||||
|
|
||||||
|
@ -46,14 +47,6 @@ enum class GameListOpenTarget {
|
||||||
ModData,
|
ModData,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class GameListRemoveTarget {
|
|
||||||
GlShaderCache,
|
|
||||||
VkShaderCache,
|
|
||||||
AllShaderCache,
|
|
||||||
CustomConfiguration,
|
|
||||||
CacheStorage,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class DumpRomFSTarget {
|
enum class DumpRomFSTarget {
|
||||||
Normal,
|
Normal,
|
||||||
SDMC,
|
SDMC,
|
||||||
|
@ -64,12 +57,6 @@ enum class GameListShortcutTarget {
|
||||||
Applications,
|
Applications,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class InstalledEntryType {
|
|
||||||
Game,
|
|
||||||
Update,
|
|
||||||
AddOnContent,
|
|
||||||
};
|
|
||||||
|
|
||||||
class GameList : public QWidget {
|
class GameList : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -118,8 +105,8 @@ signals:
|
||||||
void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
|
void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
|
||||||
const std::string& game_path);
|
const std::string& game_path);
|
||||||
void OpenTransferableShaderCacheRequested(u64 program_id);
|
void OpenTransferableShaderCacheRequested(u64 program_id);
|
||||||
void RemoveInstalledEntryRequested(u64 program_id, InstalledEntryType type);
|
void RemoveInstalledEntryRequested(u64 program_id, QtCommon::Game::InstalledEntryType type);
|
||||||
void RemoveFileRequested(u64 program_id, GameListRemoveTarget target,
|
void RemoveFileRequested(u64 program_id, QtCommon::Game::GameListRemoveTarget target,
|
||||||
const std::string& game_path);
|
const std::string& game_path);
|
||||||
void RemovePlayTimeRequested(u64 program_id);
|
void RemovePlayTimeRequested(u64 program_id);
|
||||||
void DumpRomFSRequested(u64 program_id, const std::string& game_path, DumpRomFSTarget target);
|
void DumpRomFSRequested(u64 program_id, const std::string& game_path, DumpRomFSTarget target);
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "qt_common/qt_common.h"
|
#include "qt_common/qt_common.h"
|
||||||
#include "qt_common/qt_game_util.h"
|
#include "qt_common/qt_game_util.h"
|
||||||
#include "qt_common/qt_path_util.h"
|
#include "qt_common/qt_path_util.h"
|
||||||
|
#include "qt_common/qt_meta.h"
|
||||||
|
#include "qt_common/qt_content_util.h"
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <unistd.h> // for chdir
|
#include <unistd.h> // for chdir
|
||||||
|
@ -299,14 +301,6 @@ enum class CalloutFlag : uint32_t {
|
||||||
DRDDeprecation = 0x2,
|
DRDDeprecation = 0x2,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Some games perform worse or straight-up don't work with updates,
|
|
||||||
* so this tracks which games are bad in this regard.
|
|
||||||
*/
|
|
||||||
constexpr std::array<u64, 1> bad_update_games{
|
|
||||||
0x0100F2C0115B6000 // Tears of the Kingdom
|
|
||||||
};
|
|
||||||
|
|
||||||
const int GMainWindow::max_recent_files_item;
|
const int GMainWindow::max_recent_files_item;
|
||||||
|
|
||||||
static void RemoveCachedContents() {
|
static void RemoveCachedContents() {
|
||||||
|
@ -389,6 +383,7 @@ static void OverrideWindowsFont() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
// TODO(crueter): carboxyl does this, is it needed in qml?
|
||||||
inline static bool isDarkMode() {
|
inline static bool isDarkMode() {
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
||||||
const auto scheme = QGuiApplication::styleHints()->colorScheme();
|
const auto scheme = QGuiApplication::styleHints()->colorScheme();
|
||||||
|
@ -407,6 +402,9 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
|
||||||
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, user_data_migrator{this},
|
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, user_data_migrator{this},
|
||||||
vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
|
vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
|
||||||
provider{std::make_unique<FileSys::ManualContentProvider>()} {
|
provider{std::make_unique<FileSys::ManualContentProvider>()} {
|
||||||
|
QtCommon::SetSystem(system.get());
|
||||||
|
QtCommon::SetRootObject(this);
|
||||||
|
|
||||||
Common::FS::CreateEdenPaths();
|
Common::FS::CreateEdenPaths();
|
||||||
this->config = std::make_unique<QtConfig>();
|
this->config = std::make_unique<QtConfig>();
|
||||||
|
|
||||||
|
@ -463,7 +461,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
|
||||||
|
|
||||||
Network::Init();
|
Network::Init();
|
||||||
|
|
||||||
RegisterMetaTypes();
|
QtCommon::Meta::RegisterMetaTypes();
|
||||||
|
|
||||||
InitializeWidgets();
|
InitializeWidgets();
|
||||||
InitializeDebugWidgets();
|
InitializeDebugWidgets();
|
||||||
|
@ -734,65 +732,6 @@ GMainWindow::~GMainWindow() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::RegisterMetaTypes() {
|
|
||||||
// Register integral and floating point types
|
|
||||||
qRegisterMetaType<u8>("u8");
|
|
||||||
qRegisterMetaType<u16>("u16");
|
|
||||||
qRegisterMetaType<u32>("u32");
|
|
||||||
qRegisterMetaType<u64>("u64");
|
|
||||||
qRegisterMetaType<u128>("u128");
|
|
||||||
qRegisterMetaType<s8>("s8");
|
|
||||||
qRegisterMetaType<s16>("s16");
|
|
||||||
qRegisterMetaType<s32>("s32");
|
|
||||||
qRegisterMetaType<s64>("s64");
|
|
||||||
qRegisterMetaType<f32>("f32");
|
|
||||||
qRegisterMetaType<f64>("f64");
|
|
||||||
|
|
||||||
// Register string types
|
|
||||||
qRegisterMetaType<std::string>("std::string");
|
|
||||||
qRegisterMetaType<std::wstring>("std::wstring");
|
|
||||||
qRegisterMetaType<std::u8string>("std::u8string");
|
|
||||||
qRegisterMetaType<std::u16string>("std::u16string");
|
|
||||||
qRegisterMetaType<std::u32string>("std::u32string");
|
|
||||||
qRegisterMetaType<std::string_view>("std::string_view");
|
|
||||||
qRegisterMetaType<std::wstring_view>("std::wstring_view");
|
|
||||||
qRegisterMetaType<std::u8string_view>("std::u8string_view");
|
|
||||||
qRegisterMetaType<std::u16string_view>("std::u16string_view");
|
|
||||||
qRegisterMetaType<std::u32string_view>("std::u32string_view");
|
|
||||||
|
|
||||||
// Register applet types
|
|
||||||
|
|
||||||
// Cabinet Applet
|
|
||||||
qRegisterMetaType<Core::Frontend::CabinetParameters>("Core::Frontend::CabinetParameters");
|
|
||||||
qRegisterMetaType<std::shared_ptr<Service::NFC::NfcDevice>>(
|
|
||||||
"std::shared_ptr<Service::NFC::NfcDevice>");
|
|
||||||
|
|
||||||
// Controller Applet
|
|
||||||
qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters");
|
|
||||||
|
|
||||||
// Profile Select Applet
|
|
||||||
qRegisterMetaType<Core::Frontend::ProfileSelectParameters>(
|
|
||||||
"Core::Frontend::ProfileSelectParameters");
|
|
||||||
|
|
||||||
// Software Keyboard Applet
|
|
||||||
qRegisterMetaType<Core::Frontend::KeyboardInitializeParameters>(
|
|
||||||
"Core::Frontend::KeyboardInitializeParameters");
|
|
||||||
qRegisterMetaType<Core::Frontend::InlineAppearParameters>(
|
|
||||||
"Core::Frontend::InlineAppearParameters");
|
|
||||||
qRegisterMetaType<Core::Frontend::InlineTextParameters>("Core::Frontend::InlineTextParameters");
|
|
||||||
qRegisterMetaType<Service::AM::Frontend::SwkbdResult>("Service::AM::Frontend::SwkbdResult");
|
|
||||||
qRegisterMetaType<Service::AM::Frontend::SwkbdTextCheckResult>(
|
|
||||||
"Service::AM::Frontend::SwkbdTextCheckResult");
|
|
||||||
qRegisterMetaType<Service::AM::Frontend::SwkbdReplyType>(
|
|
||||||
"Service::AM::Frontend::SwkbdReplyType");
|
|
||||||
|
|
||||||
// Web Browser Applet
|
|
||||||
qRegisterMetaType<Service::AM::Frontend::WebExitReason>("Service::AM::Frontend::WebExitReason");
|
|
||||||
|
|
||||||
// Register loader types
|
|
||||||
qRegisterMetaType<Core::SystemResultStatus>("Core::SystemResultStatus");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
|
void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters,
|
||||||
std::shared_ptr<Service::NFC::NfcDevice> nfp_device) {
|
std::shared_ptr<Service::NFC::NfcDevice> nfp_device) {
|
||||||
cabinet_applet =
|
cabinet_applet =
|
||||||
|
@ -1634,8 +1573,9 @@ void GMainWindow::ConnectWidgetEvents() {
|
||||||
connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
|
connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
|
||||||
connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory);
|
connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory);
|
||||||
connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
|
connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
|
||||||
connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this,
|
connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this, [this](u64 program_id) {
|
||||||
&GMainWindow::OnTransferableShaderCacheOpenFile);
|
QtCommon::Path::OpenShaderCache(program_id, this);
|
||||||
|
});
|
||||||
connect(game_list, &GameList::RemoveInstalledEntryRequested, this,
|
connect(game_list, &GameList::RemoveInstalledEntryRequested, this,
|
||||||
&GMainWindow::OnGameListRemoveInstalledEntry);
|
&GMainWindow::OnGameListRemoveInstalledEntry);
|
||||||
connect(game_list, &GameList::RemoveFileRequested, this, &GMainWindow::OnGameListRemoveFile);
|
connect(game_list, &GameList::RemoveFileRequested, this, &GMainWindow::OnGameListRemoveFile);
|
||||||
|
@ -1970,74 +1910,10 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
|
||||||
nullptr, // Net Connect
|
nullptr, // Net Connect
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Game Updates check */
|
/** firmware check */
|
||||||
|
|
||||||
// yuzu's configuration doesn't actually support lists so this is a bit hacky
|
if (!QtCommon::Content::CheckGameFirmware(params.program_id, *system, this)) {
|
||||||
QSettings settings;
|
return false;
|
||||||
QStringList currentIgnored = settings.value("ignoredBadUpdates", {}).toStringList();
|
|
||||||
|
|
||||||
if (std::find(bad_update_games.begin(), bad_update_games.end(), params.program_id) !=
|
|
||||||
bad_update_games.end() &&
|
|
||||||
!currentIgnored.contains(QString::number(params.program_id))) {
|
|
||||||
QMessageBox* msg = new QMessageBox(this);
|
|
||||||
msg->setWindowTitle(tr("Game Updates Warning"));
|
|
||||||
msg->setIcon(QMessageBox::Warning);
|
|
||||||
msg->setText(
|
|
||||||
tr("The game you are trying to launch is known to have performance or booting "
|
|
||||||
"issues when updates are applied. Please try increasing the memory layout to "
|
|
||||||
"6GB or 8GB if any issues occur.<br><br>Press \"OK\" to continue launching, or "
|
|
||||||
"\"Cancel\" to cancel the launch."));
|
|
||||||
|
|
||||||
msg->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
|
||||||
|
|
||||||
QCheckBox* dontShowAgain = new QCheckBox(msg);
|
|
||||||
dontShowAgain->setText(tr("Don't show again for this game"));
|
|
||||||
msg->setCheckBox(dontShowAgain);
|
|
||||||
|
|
||||||
int result = msg->exec();
|
|
||||||
|
|
||||||
// wtf
|
|
||||||
QMessageBox::ButtonRole role =
|
|
||||||
msg->buttonRole(msg->button((QMessageBox::StandardButton)result));
|
|
||||||
|
|
||||||
switch (role) {
|
|
||||||
case QMessageBox::RejectRole:
|
|
||||||
return false;
|
|
||||||
case QMessageBox::AcceptRole:
|
|
||||||
default:
|
|
||||||
if (dontShowAgain->isChecked()) {
|
|
||||||
currentIgnored << QString::number(params.program_id);
|
|
||||||
settings.setValue("ignoredBadUpdates", currentIgnored);
|
|
||||||
settings.sync();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FirmwareManager::GameRequiresFirmware(params.program_id) &&
|
|
||||||
!FirmwareManager::CheckFirmwarePresence(*system)) {
|
|
||||||
QMessageBox* msg = new QMessageBox(this);
|
|
||||||
msg->setWindowTitle(tr("Game Requires Firmware"));
|
|
||||||
msg->setIcon(QMessageBox::Warning);
|
|
||||||
msg->setText(
|
|
||||||
tr("The game you are trying to launch requires firmware to boot or to get past the "
|
|
||||||
"opening menu. Please <a href='https://yuzu-mirror.github.io/help/quickstart'>"
|
|
||||||
"dump and install firmware</a>, or press \"OK\" to launch anyways."));
|
|
||||||
|
|
||||||
msg->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
|
||||||
|
|
||||||
int exec_result = msg->exec();
|
|
||||||
|
|
||||||
QMessageBox::ButtonRole role =
|
|
||||||
msg->buttonRole(msg->button((QMessageBox::StandardButton)exec_result));
|
|
||||||
|
|
||||||
switch (role) {
|
|
||||||
case QMessageBox::RejectRole:
|
|
||||||
return false;
|
|
||||||
case QMessageBox::AcceptRole:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OnCheckNcaVerification()) {
|
if (!OnCheckNcaVerification()) {
|
||||||
|
@ -2459,6 +2335,7 @@ void GMainWindow::ShutdownGame() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(crueter): make this common as well (frontend_common?)
|
||||||
play_time_manager->Stop();
|
play_time_manager->Stop();
|
||||||
OnShutdownBegin();
|
OnShutdownBegin();
|
||||||
OnEmulationStopTimeExpired();
|
OnEmulationStopTimeExpired();
|
||||||
|
@ -2503,6 +2380,7 @@ void GMainWindow::OnGameListLoadFile(QString game_path, u64 program_id) {
|
||||||
BootGame(game_path, params);
|
BootGame(game_path, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(crueter): Common profile selector
|
||||||
void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target,
|
void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target,
|
||||||
const std::string& game_path) {
|
const std::string& game_path) {
|
||||||
std::filesystem::path path;
|
std::filesystem::path path;
|
||||||
|
@ -2611,13 +2489,6 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(qpath));
|
QDesktopServices::openUrl(QUrl::fromLocalFile(qpath));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(crueter): Transfer ts to showmessage
|
|
||||||
void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
|
|
||||||
if (!QtCommon::PathUtil::OpenShaderCache(program_id)) {
|
|
||||||
QMessageBox::warning(this, tr("Error Opening Shader Cache"), tr("Failed to create or open shader cache for this title, ensure your app data directory has write permissions."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog& dialog,
|
static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog& dialog,
|
||||||
const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest,
|
const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest,
|
||||||
bool full) {
|
bool full) {
|
||||||
|
@ -2683,26 +2554,14 @@ static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog&
|
||||||
// TODO(crueter): All this can be transfered to qt_common
|
// TODO(crueter): All this can be transfered to qt_common
|
||||||
// Aldoe I need to decide re: message boxes for QML
|
// Aldoe I need to decide re: message boxes for QML
|
||||||
// translations_common? strings_common? qt_strings? who knows
|
// translations_common? strings_common? qt_strings? who knows
|
||||||
QString GMainWindow::GetGameListErrorRemoving(InstalledEntryType type) const {
|
void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, QtCommon::Game::InstalledEntryType type) {
|
||||||
switch (type) {
|
|
||||||
case InstalledEntryType::Game:
|
|
||||||
return tr("Error Removing Contents");
|
|
||||||
case InstalledEntryType::Update:
|
|
||||||
return tr("Error Removing Update");
|
|
||||||
case InstalledEntryType::AddOnContent:
|
|
||||||
return tr("Error Removing DLC");
|
|
||||||
default:
|
|
||||||
return QStringLiteral("Error Removing <Invalid Type>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type) {
|
|
||||||
const QString entry_question = [type] {
|
const QString entry_question = [type] {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case InstalledEntryType::Game:
|
case QtCommon::Game::InstalledEntryType::Game:
|
||||||
return tr("Remove Installed Game Contents?");
|
return tr("Remove Installed Game Contents?");
|
||||||
case InstalledEntryType::Update:
|
case QtCommon::Game::InstalledEntryType::Update:
|
||||||
return tr("Remove Installed Game Update?");
|
return tr("Remove Installed Game Update?");
|
||||||
case InstalledEntryType::AddOnContent:
|
case QtCommon::Game::InstalledEntryType::AddOnContent:
|
||||||
return tr("Remove Installed Game DLC?");
|
return tr("Remove Installed Game DLC?");
|
||||||
default:
|
default:
|
||||||
return QStringLiteral("Remove Installed Game <Invalid Type>?");
|
return QStringLiteral("Remove Installed Game <Invalid Type>?");
|
||||||
|
@ -2714,18 +2573,19 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(crueter): move this to QtCommon (populate async?)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case InstalledEntryType::Game:
|
case QtCommon::Game::InstalledEntryType::Game:
|
||||||
RemoveBaseContent(program_id, type);
|
QtCommon::Game::RemoveBaseContent(program_id, type);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case InstalledEntryType::Update:
|
case QtCommon::Game::InstalledEntryType::Update:
|
||||||
RemoveUpdateContent(program_id, type);
|
QtCommon::Game::RemoveUpdateContent(program_id, type);
|
||||||
if (type != InstalledEntryType::Game) {
|
if (type != QtCommon::Game::InstalledEntryType::Game) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case InstalledEntryType::AddOnContent:
|
case QtCommon::Game::InstalledEntryType::AddOnContent:
|
||||||
RemoveAddOnContent(program_id, type);
|
QtCommon::Game::RemoveAddOnContent(program_id, type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Common::FS::RemoveDirRecursively(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) /
|
Common::FS::RemoveDirRecursively(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) /
|
||||||
|
@ -2733,55 +2593,19 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT
|
||||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) {
|
void GMainWindow::OnGameListRemoveFile(u64 program_id, QtCommon::Game::GameListRemoveTarget target,
|
||||||
const auto res =
|
|
||||||
ContentManager::RemoveBaseContent(system->GetFileSystemController(), program_id);
|
|
||||||
if (res) {
|
|
||||||
QMessageBox::information(this, tr("Successfully Removed"),
|
|
||||||
tr("Successfully removed the installed base game."));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(
|
|
||||||
this, GetGameListErrorRemoving(type),
|
|
||||||
tr("The base game is not installed in the NAND and cannot be removed."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) {
|
|
||||||
const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id);
|
|
||||||
if (res) {
|
|
||||||
QMessageBox::information(this, tr("Successfully Removed"),
|
|
||||||
tr("Successfully removed the installed update."));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(this, GetGameListErrorRemoving(type),
|
|
||||||
tr("There is no update installed for this title."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) {
|
|
||||||
const size_t count = ContentManager::RemoveAllDLC(*system, program_id);
|
|
||||||
if (count == 0) {
|
|
||||||
QMessageBox::warning(this, GetGameListErrorRemoving(type),
|
|
||||||
tr("There are no DLC installed for this title."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMessageBox::information(this, tr("Successfully Removed"),
|
|
||||||
tr("Successfully removed %1 installed DLC.").arg(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target,
|
|
||||||
const std::string& game_path) {
|
const std::string& game_path) {
|
||||||
const QString question = [target] {
|
const QString question = [target] {
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case GameListRemoveTarget::GlShaderCache:
|
case QtCommon::Game::GameListRemoveTarget::GlShaderCache:
|
||||||
return tr("Delete OpenGL Transferable Shader Cache?");
|
return tr("Delete OpenGL Transferable Shader Cache?");
|
||||||
case GameListRemoveTarget::VkShaderCache:
|
case QtCommon::Game::GameListRemoveTarget::VkShaderCache:
|
||||||
return tr("Delete Vulkan Transferable Shader Cache?");
|
return tr("Delete Vulkan Transferable Shader Cache?");
|
||||||
case GameListRemoveTarget::AllShaderCache:
|
case QtCommon::Game::GameListRemoveTarget::AllShaderCache:
|
||||||
return tr("Delete All Transferable Shader Caches?");
|
return tr("Delete All Transferable Shader Caches?");
|
||||||
case GameListRemoveTarget::CustomConfiguration:
|
case QtCommon::Game::GameListRemoveTarget::CustomConfiguration:
|
||||||
return tr("Remove Custom Game Configuration?");
|
return tr("Remove Custom Game Configuration?");
|
||||||
case GameListRemoveTarget::CacheStorage:
|
case QtCommon::Game::GameListRemoveTarget::CacheStorage:
|
||||||
return tr("Remove Cache Storage?");
|
return tr("Remove Cache Storage?");
|
||||||
default:
|
default:
|
||||||
return QString{};
|
return QString{};
|
||||||
|
@ -2794,20 +2618,20 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget targ
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case GameListRemoveTarget::VkShaderCache:
|
case QtCommon::Game::GameListRemoveTarget::VkShaderCache:
|
||||||
RemoveVulkanDriverPipelineCache(program_id);
|
QtCommon::Game::RemoveVulkanDriverPipelineCache(program_id);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case GameListRemoveTarget::GlShaderCache:
|
case QtCommon::Game::GameListRemoveTarget::GlShaderCache:
|
||||||
RemoveTransferableShaderCache(program_id, target);
|
QtCommon::Game::RemoveTransferableShaderCache(program_id, target);
|
||||||
break;
|
break;
|
||||||
case GameListRemoveTarget::AllShaderCache:
|
case QtCommon::Game::GameListRemoveTarget::AllShaderCache:
|
||||||
RemoveAllTransferableShaderCaches(program_id);
|
QtCommon::Game::RemoveAllTransferableShaderCaches(program_id);
|
||||||
break;
|
break;
|
||||||
case GameListRemoveTarget::CustomConfiguration:
|
case QtCommon::Game::GameListRemoveTarget::CustomConfiguration:
|
||||||
RemoveCustomConfiguration(program_id, game_path);
|
QtCommon::Game::RemoveCustomConfiguration(program_id, game_path);
|
||||||
break;
|
break;
|
||||||
case GameListRemoveTarget::CacheStorage:
|
case QtCommon::Game::GameListRemoveTarget::CacheStorage:
|
||||||
RemoveCacheStorage(program_id);
|
QtCommon::Game::RemoveCacheStorage(program_id, vfs.get());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2823,107 +2647,6 @@ void GMainWindow::OnGameListRemovePlayTimeData(u64 program_id) {
|
||||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target) {
|
|
||||||
const auto target_file_name = [target] {
|
|
||||||
switch (target) {
|
|
||||||
case GameListRemoveTarget::GlShaderCache:
|
|
||||||
return "opengl.bin";
|
|
||||||
case GameListRemoveTarget::VkShaderCache:
|
|
||||||
return "vulkan.bin";
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
|
||||||
const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id);
|
|
||||||
const auto target_file = shader_cache_folder_path / target_file_name;
|
|
||||||
|
|
||||||
if (!Common::FS::Exists(target_file)) {
|
|
||||||
QMessageBox::warning(this, tr("Error Removing Transferable Shader Cache"),
|
|
||||||
tr("A shader cache for this title does not exist."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Common::FS::RemoveFile(target_file)) {
|
|
||||||
QMessageBox::information(this, tr("Successfully Removed"),
|
|
||||||
tr("Successfully removed the transferable shader cache."));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(this, tr("Error Removing Transferable Shader Cache"),
|
|
||||||
tr("Failed to remove the transferable shader cache."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::RemoveVulkanDriverPipelineCache(u64 program_id) {
|
|
||||||
static constexpr std::string_view target_file_name = "vulkan_pipelines.bin";
|
|
||||||
|
|
||||||
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
|
||||||
const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id);
|
|
||||||
const auto target_file = shader_cache_folder_path / target_file_name;
|
|
||||||
|
|
||||||
if (!Common::FS::Exists(target_file)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!Common::FS::RemoveFile(target_file)) {
|
|
||||||
QMessageBox::warning(this, tr("Error Removing Vulkan Driver Pipeline Cache"),
|
|
||||||
tr("Failed to remove the driver pipeline cache."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::RemoveAllTransferableShaderCaches(u64 program_id) {
|
|
||||||
const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
|
||||||
const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id);
|
|
||||||
|
|
||||||
if (!Common::FS::Exists(program_shader_cache_dir)) {
|
|
||||||
QMessageBox::warning(this, tr("Error Removing Transferable Shader Caches"),
|
|
||||||
tr("A shader cache for this title does not exist."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Common::FS::RemoveDirRecursively(program_shader_cache_dir)) {
|
|
||||||
QMessageBox::information(this, tr("Successfully Removed"),
|
|
||||||
tr("Successfully removed the transferable shader caches."));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(this, tr("Error Removing Transferable Shader Caches"),
|
|
||||||
tr("Failed to remove the transferable shader cache directory."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::RemoveCustomConfiguration(u64 program_id, const std::string& game_path) {
|
|
||||||
const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path));
|
|
||||||
const auto config_file_name =
|
|
||||||
program_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()).append(".ini")
|
|
||||||
: fmt::format("{:016X}.ini", program_id);
|
|
||||||
const auto custom_config_file_path =
|
|
||||||
Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir) / "custom" / config_file_name;
|
|
||||||
|
|
||||||
if (!Common::FS::Exists(custom_config_file_path)) {
|
|
||||||
QMessageBox::warning(this, tr("Error Removing Custom Configuration"),
|
|
||||||
tr("A custom configuration for this title does not exist."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Common::FS::RemoveFile(custom_config_file_path)) {
|
|
||||||
QMessageBox::information(this, tr("Successfully Removed"),
|
|
||||||
tr("Successfully removed the custom game configuration."));
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(this, tr("Error Removing Custom Configuration"),
|
|
||||||
tr("Failed to remove the custom game configuration."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::RemoveCacheStorage(u64 program_id) {
|
|
||||||
const auto nand_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir);
|
|
||||||
auto vfs_nand_dir =
|
|
||||||
vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read);
|
|
||||||
|
|
||||||
const auto cache_storage_path = FileSys::SaveDataFactory::GetFullPath(
|
|
||||||
{}, vfs_nand_dir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Cache,
|
|
||||||
0 /* program_id */, {}, 0);
|
|
||||||
|
|
||||||
const auto path = Common::FS::ConcatPathSafe(nand_dir, cache_storage_path);
|
|
||||||
|
|
||||||
// Not an error if it wasn't cleared.
|
|
||||||
Common::FS::RemoveDirRecursively(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_path,
|
void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_path,
|
||||||
DumpRomFSTarget target) {
|
DumpRomFSTarget target) {
|
||||||
const auto failed = [this] {
|
const auto failed = [this] {
|
||||||
|
@ -3052,22 +2775,7 @@ void GMainWindow::OnGameListVerifyIntegrity(const std::string& game_path) {
|
||||||
return progress.wasCanceled();
|
return progress.wasCanceled();
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto result = ContentManager::VerifyGameContents(*system, game_path, QtProgressCallback);
|
QtCommon::Content::VerifyGameContents(game_path, QtProgressCallback);
|
||||||
const QString resultString = tr(QtCommon::GetGameVerificationResultString(result));
|
|
||||||
progress.close();
|
|
||||||
switch (result) {
|
|
||||||
case ContentManager::GameVerificationResult::Success:
|
|
||||||
QMessageBox::information(this, tr("Integrity verification succeeded!"),
|
|
||||||
resultString);
|
|
||||||
break;
|
|
||||||
case ContentManager::GameVerificationResult::Failed:
|
|
||||||
QMessageBox::critical(this, tr("Integrity verification failed!"),
|
|
||||||
resultString);
|
|
||||||
break;
|
|
||||||
case ContentManager::GameVerificationResult::NotImplemented:
|
|
||||||
QMessageBox::warning(this, tr("Integrity verification couldn't be performed"),
|
|
||||||
resultString);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnGameListCopyTID(u64 program_id) {
|
void GMainWindow::OnGameListCopyTID(u64 program_id) {
|
||||||
|
@ -4103,6 +3811,7 @@ void GMainWindow::OnLoadAmiibo() {
|
||||||
LoadAmiibo(filename);
|
LoadAmiibo(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(crueter): does this need to be ported to QML?
|
||||||
bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text,
|
bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text,
|
||||||
QMessageBox::StandardButtons buttons,
|
QMessageBox::StandardButtons buttons,
|
||||||
QMessageBox::StandardButton defaultButton) {
|
QMessageBox::StandardButton defaultButton) {
|
||||||
|
@ -4154,27 +3863,27 @@ void GMainWindow::LoadAmiibo(const QString& filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnOpenRootDataFolder() {
|
void GMainWindow::OnOpenRootDataFolder() {
|
||||||
QtCommon::OpenRootDataFolder();
|
QtCommon::Game::OpenRootDataFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnOpenNANDFolder()
|
void GMainWindow::OnOpenNANDFolder()
|
||||||
{
|
{
|
||||||
QtCommon::OpenNANDFolder();
|
QtCommon::Game::OpenNANDFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnOpenSDMCFolder()
|
void GMainWindow::OnOpenSDMCFolder()
|
||||||
{
|
{
|
||||||
QtCommon::OpenSDMCFolder();
|
QtCommon::Game::OpenSDMCFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnOpenModFolder()
|
void GMainWindow::OnOpenModFolder()
|
||||||
{
|
{
|
||||||
QtCommon::OpenModFolder();
|
QtCommon::Game::OpenModFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnOpenLogFolder()
|
void GMainWindow::OnOpenLogFolder()
|
||||||
{
|
{
|
||||||
QtCommon::OpenLogFolder();
|
QtCommon::Game::OpenLogFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnVerifyInstalledContents() {
|
void GMainWindow::OnVerifyInstalledContents() {
|
||||||
|
@ -4221,11 +3930,11 @@ void GMainWindow::InstallFirmware(const QString& location, bool recursive) {
|
||||||
return progress.wasCanceled();
|
return progress.wasCanceled();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto result = QtCommon::InstallFirmware(location, recursive, QtProgressCallback, system.get(), vfs.get(), this);
|
auto result = QtCommon::Content::InstallFirmware(location, recursive, QtProgressCallback, vfs.get());
|
||||||
|
|
||||||
progress.close();
|
progress.close();
|
||||||
|
|
||||||
if (result != QtCommon::FirmwareInstallResult::Success) return;
|
if (result != QtCommon::Content::FirmwareInstallResult::Success) return;
|
||||||
|
|
||||||
auto VerifyFirmwareCallback = [&](size_t total_size, size_t processed_size) {
|
auto VerifyFirmwareCallback = [&](size_t total_size, size_t processed_size) {
|
||||||
progress.setValue(90 + static_cast<int>((processed_size * 10) / total_size));
|
progress.setValue(90 + static_cast<int>((processed_size * 10) / total_size));
|
||||||
|
@ -4292,7 +4001,7 @@ void GMainWindow::OnInstallFirmwareFromZIP() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString qCacheDir = QtCommon::UnzipFirmwareToTmp(firmware_zip_location);
|
const QString qCacheDir = QtCommon::Content::UnzipFirmwareToTmp(firmware_zip_location);
|
||||||
|
|
||||||
// In this case, it has to be done recursively, since sometimes people
|
// In this case, it has to be done recursively, since sometimes people
|
||||||
// will pack it into a subdirectory after dumping
|
// will pack it into a subdirectory after dumping
|
||||||
|
@ -4370,7 +4079,7 @@ void GMainWindow::OnToggleStatusBar() {
|
||||||
void GMainWindow::OnGameListRefresh()
|
void GMainWindow::OnGameListRefresh()
|
||||||
{
|
{
|
||||||
// Resets metadata cache and reloads
|
// Resets metadata cache and reloads
|
||||||
QtCommon::ResetMetadata();
|
QtCommon::Game::ResetMetadata();
|
||||||
game_list->RefreshGameDirectory();
|
game_list->RefreshGameDirectory();
|
||||||
SetFirmwareVersion();
|
SetFirmwareVersion();
|
||||||
}
|
}
|
||||||
|
@ -4640,7 +4349,7 @@ void GMainWindow::CreateShortcut(const std::string &game_path, const u64 program
|
||||||
QImage icon_data =
|
QImage icon_data =
|
||||||
QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
|
QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
|
||||||
std::filesystem::path out_icon_path;
|
std::filesystem::path out_icon_path;
|
||||||
if (QtCommon::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) {
|
if (QtCommon::Game::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) {
|
||||||
if (!SaveIconToFile(out_icon_path, icon_data)) {
|
if (!SaveIconToFile(out_icon_path, icon_data)) {
|
||||||
LOG_ERROR(Frontend, "Could not write icon to file");
|
LOG_ERROR(Frontend, "Could not write icon to file");
|
||||||
}
|
}
|
||||||
|
@ -4674,7 +4383,7 @@ void GMainWindow::CreateShortcut(const std::string &game_path, const u64 program
|
||||||
const std::string categories = "Game;Emulator;Qt;";
|
const std::string categories = "Game;Emulator;Qt;";
|
||||||
const std::string keywords = "Switch;Nintendo;";
|
const std::string keywords = "Switch;Nintendo;";
|
||||||
|
|
||||||
if (QtCommon::CreateShortcutLink(shortcut_path, comment, out_icon_path, command,
|
if (QtCommon::Game::CreateShortcutLink(shortcut_path, comment, out_icon_path, command,
|
||||||
arguments, categories, keywords, game_title)) {
|
arguments, categories, keywords, game_title)) {
|
||||||
GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS,
|
GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS,
|
||||||
qgame_title);
|
qgame_title);
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "qt_common/qt_config.h"
|
|
||||||
#include "frontend_common/content_manager.h"
|
#include "frontend_common/content_manager.h"
|
||||||
#include "input_common/drivers/tas_input.h"
|
#include "input_common/drivers/tas_input.h"
|
||||||
|
#include "qt_common/qt_config.h"
|
||||||
|
#include "qt_common/qt_game_util.h"
|
||||||
#include "user_data_migration.h"
|
#include "user_data_migration.h"
|
||||||
#include "yuzu/compatibility_list.h"
|
#include "yuzu/compatibility_list.h"
|
||||||
#include "yuzu/hotkeys.h"
|
#include "yuzu/hotkeys.h"
|
||||||
|
@ -53,10 +54,8 @@ class QSlider;
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
class WaitTreeWidget;
|
class WaitTreeWidget;
|
||||||
enum class GameListOpenTarget;
|
enum class GameListOpenTarget;
|
||||||
enum class GameListRemoveTarget;
|
|
||||||
enum class GameListShortcutTarget;
|
enum class GameListShortcutTarget;
|
||||||
enum class DumpRomFSTarget;
|
enum class DumpRomFSTarget;
|
||||||
enum class InstalledEntryType;
|
|
||||||
class GameListPlaceholder;
|
class GameListPlaceholder;
|
||||||
|
|
||||||
class QtAmiiboSettingsDialog;
|
class QtAmiiboSettingsDialog;
|
||||||
|
@ -258,8 +257,6 @@ private:
|
||||||
void LinkActionShortcut(QAction* action, const QString& action_name,
|
void LinkActionShortcut(QAction* action, const QString& action_name,
|
||||||
const bool tas_allowed = false);
|
const bool tas_allowed = false);
|
||||||
|
|
||||||
void RegisterMetaTypes();
|
|
||||||
|
|
||||||
void InitializeWidgets();
|
void InitializeWidgets();
|
||||||
void InitializeDebugWidgets();
|
void InitializeDebugWidgets();
|
||||||
void InitializeRecentFileMenuActions();
|
void InitializeRecentFileMenuActions();
|
||||||
|
@ -353,9 +350,8 @@ private slots:
|
||||||
void OnGameListLoadFile(QString game_path, u64 program_id);
|
void OnGameListLoadFile(QString game_path, u64 program_id);
|
||||||
void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target,
|
void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target,
|
||||||
const std::string& game_path);
|
const std::string& game_path);
|
||||||
void OnTransferableShaderCacheOpenFile(u64 program_id);
|
void OnGameListRemoveInstalledEntry(u64 program_id, QtCommon::Game::InstalledEntryType type);
|
||||||
void OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type);
|
void OnGameListRemoveFile(u64 program_id, QtCommon::Game::GameListRemoveTarget target,
|
||||||
void OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target,
|
|
||||||
const std::string& game_path);
|
const std::string& game_path);
|
||||||
void OnGameListRemovePlayTimeData(u64 program_id);
|
void OnGameListRemovePlayTimeData(u64 program_id);
|
||||||
void OnGameListDumpRomFS(u64 program_id, const std::string& game_path, DumpRomFSTarget target);
|
void OnGameListDumpRomFS(u64 program_id, const std::string& game_path, DumpRomFSTarget target);
|
||||||
|
@ -436,16 +432,7 @@ private slots:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString GetGameListErrorRemoving(InstalledEntryType type) const;
|
|
||||||
void RemoveBaseContent(u64 program_id, InstalledEntryType type);
|
|
||||||
void RemoveUpdateContent(u64 program_id, InstalledEntryType type);
|
|
||||||
void RemoveAddOnContent(u64 program_id, InstalledEntryType type);
|
|
||||||
void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target);
|
|
||||||
void RemoveVulkanDriverPipelineCache(u64 program_id);
|
|
||||||
void RemoveAllTransferableShaderCaches(u64 program_id);
|
|
||||||
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path);
|
|
||||||
void RemovePlayTimeData(u64 program_id);
|
void RemovePlayTimeData(u64 program_id);
|
||||||
void RemoveCacheStorage(u64 program_id);
|
|
||||||
bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id,
|
bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id,
|
||||||
u64* selected_title_id, u8* selected_content_record_type);
|
u64* selected_title_id, u8* selected_content_record_type);
|
||||||
ContentManager::InstallResult InstallNCA(const QString& filename);
|
ContentManager::InstallResult InstallNCA(const QString& filename);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue