Compare commits
3 commits
f60e99915a
...
1dec879ec8
Author | SHA1 | Date | |
---|---|---|---|
1dec879ec8 | |||
e8149b77ae | |||
221d9c71ac |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
dist/qt_themes/colorful/icons/48x48/download.png
vendored
Before Width: | Height: | Size: 1.4 KiB |
BIN
dist/qt_themes/colorful/icons/48x48/trash.png
vendored
Normal file
After Width: | Height: | Size: 744 B |
BIN
dist/qt_themes/colorful/icons/48x48/upload.png
vendored
Before Width: | Height: | Size: 1.4 KiB |
BIN
dist/qt_themes/colorful/icons/48x48/user-trash.png
vendored
Before Width: | Height: | Size: 1.4 KiB |
4
dist/qt_themes/colorful/style.qrc
vendored
|
@ -18,9 +18,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">icons/48x48/upload.png</file>
|
||||
<file alias="48x48/trash.png">icons/48x48/trash.png</file>
|
||||
<file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
|
|
|
@ -11,9 +11,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">../colorful/icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">../colorful/icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">../colorful/icons/48x48/upload.png</file>
|
||||
<file alias="48x48/trash.png">../colorful/icons/48x48/trash.png</file>
|
||||
<file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
|
||||
<file alias="256x256/plus_folder.png">../colorful/icons/256x256/plus_folder.png</file>
|
||||
|
|
4
dist/qt_themes/default/default.qrc
vendored
|
@ -14,9 +14,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">icons/48x48/upload.png</file>
|
||||
<file alias="48x48/trash.png">icons/48x48/trash.png</file>
|
||||
<file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
<file alias="48x48/star.png">icons/48x48/star.png</file>
|
||||
|
|
BIN
dist/qt_themes/default/icons/256x256/eden.png
vendored
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
dist/qt_themes/default/icons/48x48/download.png
vendored
Before Width: | Height: | Size: 853 B |
BIN
dist/qt_themes/default/icons/48x48/trash.png
vendored
Normal file
After Width: | Height: | Size: 598 B |
BIN
dist/qt_themes/default/icons/48x48/upload.png
vendored
Before Width: | Height: | Size: 820 B |
BIN
dist/qt_themes/default/icons/48x48/user-trash.png
vendored
Before Width: | Height: | Size: 584 B |
4
dist/qt_themes/default_dark/style.qrc
vendored
|
@ -13,9 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
<file alias="48x48/bad_folder.png">../colorful/icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">../colorful/icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">../colorful/icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">../colorful/icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">../colorful/icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">../colorful/icons/48x48/upload.png</file>
|
||||
<file alias="48x48/trash.png">../colorful/icons/48x48/trash.png</file>
|
||||
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/list-add.png">../colorful/icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">../colorful/icons/48x48/sd_card.png</file>
|
||||
|
|
BIN
dist/qt_themes/qdarkstyle/icons/48x48/download.png
vendored
Before Width: | Height: | Size: 883 B |
BIN
dist/qt_themes/qdarkstyle/icons/48x48/trash.png
vendored
Normal file
After Width: | Height: | Size: 612 B |
BIN
dist/qt_themes/qdarkstyle/icons/48x48/upload.png
vendored
Before Width: | Height: | Size: 853 B |
BIN
dist/qt_themes/qdarkstyle/icons/48x48/user-trash.png
vendored
Before Width: | Height: | Size: 584 B |
4
dist/qt_themes/qdarkstyle/style.qrc
vendored
|
@ -9,9 +9,7 @@
|
|||
<file alias="48x48/bad_folder.png">icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">icons/48x48/upload.png</file>
|
||||
<file alias="48x48/trash.png">icons/48x48/trash.png</file>
|
||||
<file alias="48x48/no_avatar.png">icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/list-add.png">icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">icons/48x48/sd_card.png</file>
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
<file alias="48x48/bad_folder.png">../qdarkstyle/icons/48x48/bad_folder.png</file>
|
||||
<file alias="48x48/chip.png">../qdarkstyle/icons/48x48/chip.png</file>
|
||||
<file alias="48x48/folder.png">../qdarkstyle/icons/48x48/folder.png</file>
|
||||
<file alias="48x48/user-trash.png">../qdarkstyle/icons/48x48/user-trash.png</file>
|
||||
<file alias="48x48/download.png">../qdarkstyle/icons/48x48/download.png</file>
|
||||
<file alias="48x48/upload.png">../qdarkstyle/icons/48x48/upload.png</file>
|
||||
<file alias="48x48/no_avatar.png">../qdarkstyle/icons/48x48/no_avatar.png</file>
|
||||
<file alias="48x48/list-add.png">../qdarkstyle/icons/48x48/list-add.png</file>
|
||||
<file alias="48x48/sd_card.png">../qdarkstyle/icons/48x48/sd_card.png</file>
|
||||
|
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 244 KiB After Width: | Height: | Size: 438 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
@ -109,6 +112,9 @@ public:
|
|||
|
||||
void ReadBlock(DAddr address, void* dest_pointer, size_t size);
|
||||
void ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size);
|
||||
#ifdef YUZU_DEBUG
|
||||
bool ReadBlockFastChecked(DAddr address, void* dest_pointer, size_t size);
|
||||
#endif
|
||||
void WriteBlock(DAddr address, const void* src_pointer, size_t size);
|
||||
void WriteBlockUnsafe(DAddr address, const void* src_pointer, size_t size);
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
@ -467,6 +470,29 @@ void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_poin
|
|||
});
|
||||
}
|
||||
|
||||
#ifdef YUZU_DEBUG
|
||||
template <typename Traits>
|
||||
bool DeviceMemoryManager<Traits>::ReadBlockFastChecked(DAddr address, void* dest_pointer,
|
||||
size_t size) {
|
||||
bool success = true;
|
||||
WalkBlock(
|
||||
address, size,
|
||||
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||
LOG_CRITICAL(Render, "DeviceMemory OOB/unmapped: addr=0x{:x} size={}", current_vaddr,
|
||||
size);
|
||||
std::memset(dest_pointer, 0, copy_amount);
|
||||
success = false;
|
||||
},
|
||||
[&](size_t copy_amount, const u8* const src_ptr) {
|
||||
std::memcpy(dest_pointer, src_ptr, copy_amount);
|
||||
},
|
||||
[&](const std::size_t copy_amount) {
|
||||
dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount;
|
||||
});
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::WriteBlockUnsafe(DAddr address, const void* src_pointer,
|
||||
size_t size) {
|
||||
|
|
|
@ -21,9 +21,7 @@ const std::string GetDataDir(DataDir dir)
|
|||
case DataDir::UserNand:
|
||||
return (nand_dir / "user" / "Contents" / "registered").string();
|
||||
case DataDir::SysNand:
|
||||
// NB: do NOT delete save
|
||||
// that contains profile data and other stuff
|
||||
return (nand_dir / "system" / "Contents" / "registered").string();
|
||||
return (nand_dir / "system").string();
|
||||
case DataDir::Mods:
|
||||
return Common::FS::GetEdenPathString(Common::FS::EdenPath::LoadDir);
|
||||
case DataDir::Shaders:
|
||||
|
|
|
@ -35,28 +35,9 @@ if (ENABLE_QT)
|
|||
target_link_libraries(qt_common PRIVATE Qt6::Widgets)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(qt_common PUBLIC
|
||||
# Use QStringBuilder for string concatenation to reduce
|
||||
# the overall number of temporary strings created.
|
||||
QT_USE_QSTRINGBUILDER
|
||||
|
||||
# Disable implicit conversions from/to C strings
|
||||
QT_NO_CAST_FROM_ASCII
|
||||
QT_NO_CAST_TO_ASCII
|
||||
|
||||
# Disable implicit type narrowing in signal/slot connect() calls.
|
||||
QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
|
||||
|
||||
# Disable unsafe overloads of QProcess' start() function.
|
||||
QT_NO_PROCESS_COMBINED_ARGUMENT_START
|
||||
|
||||
# Disable implicit QString->QUrl conversions to enforce use of proper resolving functions.
|
||||
QT_NO_URL_CAST_FROM_STRING
|
||||
)
|
||||
|
||||
add_subdirectory(externals)
|
||||
|
||||
target_link_libraries(qt_common PRIVATE core Qt6::Core Qt6::Concurrent SimpleIni::SimpleIni QuaZip::QuaZip)
|
||||
target_link_libraries(qt_common PRIVATE core Qt6::Core SimpleIni::SimpleIni QuaZip::QuaZip)
|
||||
target_link_libraries(qt_common PUBLIC frozen::frozen)
|
||||
|
||||
if (NOT APPLE AND ENABLE_OPENGL)
|
||||
|
|
1
src/qt_common/externals/CMakeLists.txt
vendored
|
@ -16,4 +16,5 @@ set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
|||
AddJsonPackage(quazip)
|
||||
|
||||
# frozen
|
||||
# TODO(crueter): Qt String Lookup
|
||||
AddJsonPackage(frozen)
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "frontend_common/data_manager.h"
|
||||
#include "qt_common/qt_game_util.h"
|
||||
#include "qt_content_util.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "frontend_common/content_manager.h"
|
||||
#include "frontend_common/firmware_manager.h"
|
||||
#include "qt_common/qt_common.h"
|
||||
#include "qt_common/qt_game_util.h"
|
||||
#include "qt_common/qt_progress_dialog.h"
|
||||
#include "qt_frontend_util.h"
|
||||
|
||||
#include <QFuture>
|
||||
#include <QtConcurrentRun>
|
||||
#include <JlCompress.h>
|
||||
#include <qfuturewatcher.h>
|
||||
|
||||
namespace QtCommon::Content {
|
||||
|
||||
|
@ -25,10 +21,10 @@ bool CheckGameFirmware(u64 program_id, QObject* parent)
|
|||
&& !FirmwareManager::CheckFirmwarePresence(*system)) {
|
||||
auto result = QtCommon::Frontend::ShowMessage(
|
||||
QMessageBox::Warning,
|
||||
tr("Game Requires Firmware"),
|
||||
tr("The game you are trying to launch requires firmware to boot or to get past the "
|
||||
"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."),
|
||||
"dump and install firmware</a>, or press \"OK\" to launch anyways.",
|
||||
QMessageBox::Ok | QMessageBox::Cancel,
|
||||
parent);
|
||||
|
||||
|
@ -64,8 +60,8 @@ void InstallFirmware(const QString& location, bool recursive)
|
|||
|
||||
const auto ShowMessage = [&]() {
|
||||
QtCommon::Frontend::ShowMessage(icon,
|
||||
tr(failedTitle),
|
||||
tr(GetFirmwareInstallResultString(result)));
|
||||
failedTitle,
|
||||
GetFirmwareInstallResultString(result));
|
||||
};
|
||||
|
||||
LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString());
|
||||
|
@ -129,8 +125,8 @@ void InstallFirmware(const QString& location, bool recursive)
|
|||
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());
|
||||
auto firmware_dst_vfile = firmware_vdir
|
||||
->CreateFileRelative(firmware_src_path.filename().string());
|
||||
|
||||
if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) {
|
||||
LOG_ERROR(Frontend,
|
||||
|
@ -172,9 +168,9 @@ void InstallFirmware(const QString& location, bool recursive)
|
|||
const auto failed_names = QString::fromStdString(
|
||||
fmt::format("{}", fmt::join(results, "\n")));
|
||||
progress.close();
|
||||
QtCommon::Frontend::Critical(
|
||||
tr("Firmware integrity verification failed!"),
|
||||
tr("Verification failed for the following files:\n\n%1").arg(failed_names));
|
||||
QtCommon::Frontend::Critical(tr("Firmware integrity verification failed!"),
|
||||
tr("Verification failed for the following files:\n\n%1")
|
||||
.arg(failed_names));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -185,10 +181,10 @@ void InstallFirmware(const QString& location, bool recursive)
|
|||
const std::string display_version(firmware_data.display_version.data());
|
||||
|
||||
result = FirmwareInstallResult::Success;
|
||||
QtCommon::Frontend::Information(
|
||||
rootObject,
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr(successTitle),
|
||||
tr(GetFirmwareInstallResultString(result)).arg(QString::fromStdString(display_version)));
|
||||
tr(GetFirmwareInstallResultString(result))
|
||||
.arg(QString::fromStdString(display_version)));
|
||||
}
|
||||
|
||||
QString UnzipFirmwareToTmp(const QString& location)
|
||||
|
@ -197,7 +193,7 @@ QString UnzipFirmwareToTmp(const QString& location)
|
|||
fs::path tmp{fs::temp_directory_path()};
|
||||
|
||||
if (!fs::create_directories(tmp / "eden" / "firmware")) {
|
||||
return QString();
|
||||
return "";
|
||||
}
|
||||
|
||||
tmp /= "eden";
|
||||
|
@ -209,7 +205,7 @@ QString UnzipFirmwareToTmp(const QString& location)
|
|||
|
||||
QStringList result = JlCompress::extractDir(&zip, qCacheDir);
|
||||
if (result.isEmpty()) {
|
||||
return QString();
|
||||
return "";
|
||||
}
|
||||
|
||||
return qCacheDir;
|
||||
|
@ -268,8 +264,9 @@ void InstallKeys()
|
|||
return;
|
||||
}
|
||||
|
||||
FirmwareManager::KeyInstallResult result
|
||||
= FirmwareManager::InstallKeys(key_source_location.toStdString(), "keys");
|
||||
FirmwareManager::KeyInstallResult result = FirmwareManager::InstallKeys(key_source_location
|
||||
.toStdString(),
|
||||
"keys");
|
||||
|
||||
system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
|
||||
|
||||
|
@ -285,14 +282,9 @@ void InstallKeys()
|
|||
}
|
||||
}
|
||||
|
||||
void VerifyInstalledContents()
|
||||
{
|
||||
void VerifyInstalledContents() {
|
||||
// Initialize a progress dialog.
|
||||
QtCommon::Frontend::QtProgressDialog progress(tr("Verifying integrity..."),
|
||||
tr("Cancel"),
|
||||
0,
|
||||
100,
|
||||
QtCommon::rootObject);
|
||||
QtCommon::Frontend::QtProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, QtCommon::rootObject);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
progress.setMinimumDuration(100);
|
||||
progress.setAutoClose(false);
|
||||
|
@ -304,17 +296,16 @@ void VerifyInstalledContents()
|
|||
return progress.wasCanceled();
|
||||
};
|
||||
|
||||
const std::vector<std::string> result
|
||||
= ContentManager::VerifyInstalledContents(*QtCommon::system,
|
||||
*QtCommon::provider,
|
||||
QtProgressCallback);
|
||||
const std::vector<std::string> result =
|
||||
ContentManager::VerifyInstalledContents(*QtCommon::system, *QtCommon::provider, QtProgressCallback);
|
||||
progress.close();
|
||||
|
||||
if (result.empty()) {
|
||||
QtCommon::Frontend::Information(tr("Integrity verification succeeded!"),
|
||||
tr("The operation completed successfully."));
|
||||
} else {
|
||||
const auto failed_names = QString::fromStdString(fmt::format("{}", fmt::join(result, "\n")));
|
||||
const auto failed_names =
|
||||
QString::fromStdString(fmt::format("{}", fmt::join(result, "\n")));
|
||||
QtCommon::Frontend::Critical(
|
||||
tr("Integrity verification failed!"),
|
||||
tr("Verification failed for the following files:\n\n%1").arg(failed_names));
|
||||
|
@ -341,7 +332,7 @@ void FixProfiles()
|
|||
qorphaned.reserve(8 * 33);
|
||||
|
||||
for (const std::string& s : orphaned) {
|
||||
qorphaned = qorphaned % QStringLiteral("\n") % QString::fromStdString(s);
|
||||
qorphaned += "\n" + QString::fromStdString(s);
|
||||
}
|
||||
|
||||
QtCommon::Frontend::Critical(
|
||||
|
@ -357,19 +348,18 @@ void FixProfiles()
|
|||
QtCommon::Game::OpenSaveFolder();
|
||||
}
|
||||
|
||||
void ClearDataDir(FrontendCommon::DataManager::DataDir dir)
|
||||
{
|
||||
auto result = QtCommon::Frontend::Warning(tr("Really clear data?"),
|
||||
tr("Important data may be lost!"),
|
||||
void ClearDataDir(FrontendCommon::DataManager::DataDir dir) {
|
||||
auto result = QtCommon::Frontend::Warning("Really clear data?",
|
||||
"Important data may be lost!",
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
|
||||
if (result != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
result = QtCommon::Frontend::Warning(
|
||||
tr("Are you REALLY sure?"),
|
||||
tr("Once deleted, your data will NOT come back!\n"
|
||||
"Only do this if you're 100% sure you want to delete this data."),
|
||||
"Are you REALLY sure?",
|
||||
"Once deleted, your data will NOT come back!\n"
|
||||
"Only do this if you're 100% sure you want to delete this data.",
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
|
||||
if (result != QMessageBox::Yes)
|
||||
|
@ -383,130 +373,4 @@ void ClearDataDir(FrontendCommon::DataManager::DataDir dir)
|
|||
dialog.close();
|
||||
}
|
||||
|
||||
void ExportDataDir(FrontendCommon::DataManager::DataDir data_dir, std::function<void()> callback)
|
||||
{
|
||||
const std::string dir = FrontendCommon::DataManager::GetDataDir(data_dir);
|
||||
|
||||
const QString zip_dump_location
|
||||
= QtCommon::Frontend::GetSaveFileName(tr("Select Export Location"),
|
||||
QStringLiteral("export.zip"),
|
||||
tr("Zipped Archives (*.zip)"));
|
||||
|
||||
if (zip_dump_location.isEmpty())
|
||||
return;
|
||||
|
||||
QMetaObject::Connection* connection = new QMetaObject::Connection;
|
||||
*connection = QObject::connect(qApp, &QGuiApplication::aboutToQuit, rootObject, [=]() mutable {
|
||||
QtCommon::Frontend::Warning(tr("Still Exporting"),
|
||||
tr("Eden is still exporting some data, and will continue "
|
||||
"running in the background until it's done."));
|
||||
});
|
||||
|
||||
QtCommon::Frontend::QtProgressDialog* progress = new QtCommon::Frontend::QtProgressDialog(
|
||||
tr("Compressing, this may take a while..."), tr("Background"), 0, 0, rootObject);
|
||||
|
||||
progress->setWindowModality(Qt::WindowModal);
|
||||
progress->show();
|
||||
QGuiApplication::processEvents();
|
||||
|
||||
QFuture<bool> future = QtConcurrent::run([&]() {
|
||||
return JlCompress::compressDir(zip_dump_location,
|
||||
QString::fromStdString(dir),
|
||||
true,
|
||||
QDir::Hidden | QDir::Files | QDir::Dirs);
|
||||
});
|
||||
|
||||
QFutureWatcher<bool>* watcher = new QFutureWatcher<bool>(rootObject);
|
||||
|
||||
QObject::connect(watcher, &QFutureWatcher<bool>::finished, rootObject, [=]() {
|
||||
progress->close();
|
||||
progress->deleteLater();
|
||||
QObject::disconnect(*connection);
|
||||
delete connection;
|
||||
|
||||
if (watcher->result()) {
|
||||
QtCommon::Frontend::Information(tr("Exported Successfully"),
|
||||
tr("Data was exported successfully."));
|
||||
} else {
|
||||
QtCommon::Frontend::Critical(
|
||||
tr("Export Failed"),
|
||||
tr("Ensure you have write permissions on the targeted directory and try again."));
|
||||
}
|
||||
|
||||
watcher->deleteLater();
|
||||
callback();
|
||||
});
|
||||
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
void ImportDataDir(FrontendCommon::DataManager::DataDir data_dir, std::function<void()> callback)
|
||||
{
|
||||
const std::string dir = FrontendCommon::DataManager::GetDataDir(data_dir);
|
||||
|
||||
using namespace QtCommon::Frontend;
|
||||
|
||||
const QString zip_dump_location = GetOpenFileName(tr("Select Import Location"),
|
||||
{},
|
||||
tr("Zipped Archives (*.zip)"));
|
||||
|
||||
if (zip_dump_location.isEmpty())
|
||||
return;
|
||||
|
||||
StandardButton button = Warning(
|
||||
tr("Import Warning"),
|
||||
tr("All previous data in this directory will be deleted. Are you sure you wish to "
|
||||
"proceed?"),
|
||||
StandardButton::Yes | StandardButton::No);
|
||||
|
||||
if (button != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
FrontendCommon::DataManager::ClearDir(data_dir);
|
||||
|
||||
QMetaObject::Connection* connection = new QMetaObject::Connection;
|
||||
*connection = QObject::connect(qApp, &QGuiApplication::aboutToQuit, rootObject, [=]() mutable {
|
||||
Warning(tr("Still Importing"),
|
||||
tr("Eden is still importing some data, and will continue "
|
||||
"running in the background until it's done."));
|
||||
});
|
||||
|
||||
QtProgressDialog* progress = new QtProgressDialog(tr("Decompressing, this may take a while..."),
|
||||
tr("Background"),
|
||||
0,
|
||||
0,
|
||||
rootObject);
|
||||
|
||||
progress->setWindowModality(Qt::WindowModal);
|
||||
progress->show();
|
||||
QGuiApplication::processEvents();
|
||||
|
||||
QFuture<bool> future = QtConcurrent::run([=]() {
|
||||
return !JlCompress::extractDir(zip_dump_location,
|
||||
QString::fromStdString(dir)).empty();
|
||||
});
|
||||
|
||||
QFutureWatcher<bool>* watcher = new QFutureWatcher<bool>(rootObject);
|
||||
|
||||
QObject::connect(watcher, &QFutureWatcher<bool>::finished, rootObject, [=]() {
|
||||
progress->close();
|
||||
progress->deleteLater();
|
||||
QObject::disconnect(*connection);
|
||||
delete connection;
|
||||
|
||||
if (watcher->result()) {
|
||||
Information(tr("Imported Successfully"), tr("Data was imported successfully."));
|
||||
} else {
|
||||
Critical(
|
||||
tr("Import Failed"),
|
||||
tr("Ensure you have read permissions on the targeted directory and try again."));
|
||||
}
|
||||
|
||||
watcher->deleteLater();
|
||||
callback();
|
||||
});
|
||||
|
||||
watcher->setFuture(future);
|
||||
}
|
||||
|
||||
} // namespace QtCommon::Content
|
||||
|
|
|
@ -48,8 +48,6 @@ void VerifyGameContents(const std::string &game_path);
|
|||
void VerifyInstalledContents();
|
||||
|
||||
void ClearDataDir(FrontendCommon::DataManager::DataDir dir);
|
||||
void ExportDataDir(FrontendCommon::DataManager::DataDir dir, std::function<void()> callback = {});
|
||||
void ImportDataDir(FrontendCommon::DataManager::DataDir dir, std::function<void()> callback = {});
|
||||
|
||||
// Profiles //
|
||||
void FixProfiles();
|
||||
|
|
|
@ -32,15 +32,4 @@ const QString GetOpenFileName(const QString &title,
|
|||
#endif
|
||||
}
|
||||
|
||||
const QString GetSaveFileName(const QString &title,
|
||||
const QString &dir,
|
||||
const QString &filter,
|
||||
QString *selectedFilter,
|
||||
Options options)
|
||||
{
|
||||
#ifdef YUZU_QT_WIDGETS
|
||||
return QFileDialog::getSaveFileName((QWidget *) rootObject, title, dir, filter, selectedFilter, options);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace QtCommon::Frontend
|
||||
|
|
|
@ -110,6 +110,21 @@ StandardButton ShowMessage(Icon icon,
|
|||
{ \
|
||||
return ShowMessage(Icon::level, title, text, buttons, parent); \
|
||||
} \
|
||||
inline StandardButton level(QObject *parent, \
|
||||
const char *title, \
|
||||
const char *text, \
|
||||
StandardButtons buttons \
|
||||
= StandardButton::Ok) \
|
||||
{ \
|
||||
return ShowMessage(Icon::level, tr(title), tr(text), buttons, parent); \
|
||||
} \
|
||||
inline StandardButton level(const char *title, \
|
||||
const char *text, \
|
||||
StandardButtons buttons \
|
||||
= StandardButton::Ok) \
|
||||
{ \
|
||||
return ShowMessage(Icon::level, tr(title), tr(text), buttons, rootObject); \
|
||||
} \
|
||||
inline StandardButton level(const QString title, \
|
||||
const QString &text, \
|
||||
StandardButtons buttons \
|
||||
|
@ -129,11 +144,5 @@ const QString GetOpenFileName(const QString &title,
|
|||
QString *selectedFilter = nullptr,
|
||||
Options options = Options());
|
||||
|
||||
const QString GetSaveFileName(const QString &title,
|
||||
const QString &dir,
|
||||
const QString &filter,
|
||||
QString *selectedFilter = nullptr,
|
||||
Options options = Options());
|
||||
|
||||
} // namespace QtCommon::Frontend
|
||||
#endif // QT_FRONTEND_UTIL_H
|
||||
|
|
|
@ -220,8 +220,8 @@ void RemoveBaseContent(u64 program_id, InstalledEntryType type)
|
|||
program_id);
|
||||
if (res) {
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr("Successfully Removed"),
|
||||
tr("Successfully removed the installed base game."));
|
||||
"Successfully Removed",
|
||||
"Successfully removed the installed base game.");
|
||||
} else {
|
||||
QtCommon::Frontend::Warning(
|
||||
rootObject,
|
||||
|
@ -235,8 +235,8 @@ void RemoveUpdateContent(u64 program_id, InstalledEntryType type)
|
|||
const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id);
|
||||
if (res) {
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr("Successfully Removed"),
|
||||
tr("Successfully removed the installed update."));
|
||||
"Successfully Removed",
|
||||
"Successfully removed the installed update.");
|
||||
} else {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
GetGameListErrorRemoving(type),
|
||||
|
|
|
@ -17,12 +17,7 @@ bool OpenShaderCache(u64 program_id, QObject *parent)
|
|||
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)};
|
||||
if (!Common::FS::CreateDirs(shader_cache_folder_path)) {
|
||||
QtCommon::Frontend::ShowMessage(QMessageBox::Warning,
|
||||
tr("Error Opening Shader Cache"),
|
||||
tr("Failed to create or open shader cache for this title, "
|
||||
"ensure your app data directory has write permissions."),
|
||||
QMessageBox::Ok,
|
||||
parent);
|
||||
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)};
|
||||
|
|
|
@ -386,11 +386,10 @@ void BufferCache<P>::BindHostComputeBuffers() {
|
|||
template <class P>
|
||||
void BufferCache<P>::SetUniformBuffersState(const std::array<u32, NUM_STAGES>& mask,
|
||||
const UniformBufferSizes* sizes) {
|
||||
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
|
||||
if (channel_state->enabled_uniform_buffer_masks != mask) {
|
||||
if constexpr (IS_OPENGL) {
|
||||
const bool mask_changed = channel_state->enabled_uniform_buffer_masks != mask;
|
||||
if (mask_changed) {
|
||||
channel_state->fast_bound_uniform_buffers.fill(0);
|
||||
}
|
||||
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
|
||||
channel_state->dirty_uniform_buffers.fill(~u32{0});
|
||||
channel_state->uniform_buffer_binding_sizes.fill({});
|
||||
}
|
||||
|
@ -806,7 +805,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
|||
channel_state->uniform_buffer_binding_sizes[stage][binding_index] != size;
|
||||
if (should_fast_bind) {
|
||||
// We only have to bind when the currently bound buffer is not the fast version
|
||||
channel_state->fast_bound_uniform_buffers[stage] |= 1U << binding_index;
|
||||
channel_state->fast_bound_uniform_buffers[stage] |= 1u << binding_index;
|
||||
channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size;
|
||||
runtime.BindFastUniformBuffer(stage, binding_index, size);
|
||||
}
|
||||
|
@ -815,13 +814,22 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
|||
return;
|
||||
}
|
||||
}
|
||||
if constexpr (IS_OPENGL) {
|
||||
channel_state->fast_bound_uniform_buffers[stage] |= 1U << binding_index;
|
||||
channel_state->fast_bound_uniform_buffers[stage] |= 1u << binding_index;
|
||||
channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size;
|
||||
}
|
||||
// Stream buffer path to avoid stalling on non-Nvidia drivers or Vulkan
|
||||
const std::span<u8> span = runtime.BindMappedUniformBuffer(stage, binding_index, size);
|
||||
#ifdef YUZU_DEBUG
|
||||
ASSERT(binding_index < NUM_GRAPHICS_UNIFORM_BUFFERS);
|
||||
ASSERT(span.size() >= size && "UBO stream span too small");
|
||||
if (!device_memory.ReadBlockFastChecked(device_addr, span.data(), size)) {
|
||||
LOG_CRITICAL(Render, "DeviceMemory OOB/unmapped: addr=0x{:x} size={}", device_addr, size);
|
||||
channel_state->fast_bound_uniform_buffers[stage] &= ~(1u << binding_index);
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
device_memory.ReadBlockUnsafe(device_addr, span.data(), size);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
// Classic cached path
|
||||
|
@ -830,7 +838,8 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
|||
}
|
||||
// Skip binding if it's not needed and if the bound buffer is not the fast version
|
||||
// This exists to avoid instances where the fast buffer is bound and a GPU write happens
|
||||
needs_bind |= HasFastUniformBufferBound(stage, binding_index);
|
||||
const bool was_fast_bound = HasFastUniformBufferBound(stage, binding_index);
|
||||
needs_bind |= was_fast_bound;
|
||||
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
|
||||
needs_bind |= channel_state->uniform_buffer_binding_sizes[stage][binding_index] != size;
|
||||
}
|
||||
|
@ -839,9 +848,6 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
|||
}
|
||||
const u32 offset = buffer.Offset(device_addr);
|
||||
if constexpr (IS_OPENGL) {
|
||||
// Fast buffer will be unbound
|
||||
channel_state->fast_bound_uniform_buffers[stage] &= ~(1U << binding_index);
|
||||
|
||||
// Mark the index as dirty if offset doesn't match
|
||||
const bool is_copy_bind = offset != 0 && !runtime.SupportsNonZeroUniformOffset();
|
||||
channel_state->dirty_uniform_buffers[stage] |= (is_copy_bind ? 1U : 0U) << index;
|
||||
|
@ -855,6 +861,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
|
|||
} else {
|
||||
runtime.BindUniformBuffer(buffer, offset, size);
|
||||
}
|
||||
channel_state->fast_bound_uniform_buffers[stage] &= ~(1u << binding_index);
|
||||
}
|
||||
|
||||
template <class P>
|
||||
|
@ -1789,12 +1796,7 @@ std::span<u8> BufferCache<P>::ImmediateBuffer(size_t wanted_capacity) {
|
|||
|
||||
template <class P>
|
||||
bool BufferCache<P>::HasFastUniformBufferBound(size_t stage, u32 binding_index) const noexcept {
|
||||
if constexpr (IS_OPENGL) {
|
||||
return ((channel_state->fast_bound_uniform_buffers[stage] >> binding_index) & 1) != 0;
|
||||
} else {
|
||||
// Only OpenGL has fast uniform buffers
|
||||
return false;
|
||||
}
|
||||
return ((channel_state->fast_bound_uniform_buffers[stage] >> binding_index) & 1u) != 0;
|
||||
}
|
||||
|
||||
template <class P>
|
||||
|
|
|
@ -53,6 +53,7 @@ constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
|
|||
constexpr u32 NUM_STORAGE_BUFFERS = 16;
|
||||
constexpr u32 NUM_TEXTURE_BUFFERS = 32;
|
||||
constexpr u32 NUM_STAGES = 5;
|
||||
static_assert(NUM_GRAPHICS_UNIFORM_BUFFERS <= 32, "fast bitmask must fit u32");
|
||||
|
||||
using UniformBufferSizes = std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>;
|
||||
using ComputeUniformBufferSizes = std::array<u32, NUM_COMPUTE_UNIFORM_BUFFERS>;
|
||||
|
@ -137,8 +138,8 @@ public:
|
|||
u32 written_compute_texture_buffers = 0;
|
||||
u32 image_compute_texture_buffers = 0;
|
||||
|
||||
std::array<u32, 16> uniform_cache_hits{};
|
||||
std::array<u32, 16> uniform_cache_shots{};
|
||||
std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS> uniform_cache_hits{};
|
||||
std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS> uniform_cache_shots{};
|
||||
|
||||
u32 uniform_buffer_skip_cache_size = DEFAULT_SKIP_CACHE_SIZE;
|
||||
|
||||
|
|
|
@ -25,12 +25,12 @@ namespace {
|
|||
|
||||
using namespace Common::Literals;
|
||||
|
||||
// Maximum potential alignment of a Vulkan buffer
|
||||
constexpr VkDeviceSize MAX_ALIGNMENT = 256;
|
||||
// Minimum alignment we want to enforce for the streaming ring
|
||||
constexpr VkDeviceSize MIN_STREAM_ALIGNMENT = 256;
|
||||
// Stream buffer size in bytes
|
||||
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB;
|
||||
|
||||
size_t GetStreamBufferSize(const Device& device) {
|
||||
size_t GetStreamBufferSize(const Device& device, VkDeviceSize alignment) {
|
||||
VkDeviceSize size{0};
|
||||
if (device.HasDebuggingToolAttached()) {
|
||||
bool found_heap = false;
|
||||
|
@ -53,8 +53,9 @@ size_t GetStreamBufferSize(const Device& device) {
|
|||
|
||||
// Clamp to the configured maximum, align up for safety, and ensure a sane minimum so
|
||||
// region_size (stream_buffer_size / NUM_SYNCS) never becomes zero.
|
||||
const VkDeviceSize aligned = (std::min)(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE);
|
||||
const VkDeviceSize min_size = MAX_ALIGNMENT * StagingBufferPool::NUM_SYNCS;
|
||||
const VkDeviceSize aligned =
|
||||
(std::min)(Common::AlignUp(size, alignment), MAX_STREAM_BUFFER_SIZE);
|
||||
const VkDeviceSize min_size = alignment * StagingBufferPool::NUM_SYNCS;
|
||||
return static_cast<size_t>((std::max)(aligned, min_size));
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
@ -62,8 +63,10 @@ size_t GetStreamBufferSize(const Device& device) {
|
|||
StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
|
||||
Scheduler& scheduler_)
|
||||
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
|
||||
stream_buffer_size{GetStreamBufferSize(device)}, region_size{stream_buffer_size /
|
||||
StagingBufferPool::NUM_SYNCS} {
|
||||
stream_alignment{std::max<VkDeviceSize>(device_.GetUniformBufferAlignment(),
|
||||
MIN_STREAM_ALIGNMENT)},
|
||||
stream_buffer_size{GetStreamBufferSize(device_, stream_alignment)},
|
||||
region_size{stream_buffer_size / StagingBufferPool::NUM_SYNCS} {
|
||||
VkBufferCreateInfo stream_ci = {
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
|
@ -116,10 +119,11 @@ void StagingBufferPool::TickFrame() {
|
|||
}
|
||||
|
||||
StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
|
||||
const size_t aligned_size = Common::AlignUp(size, MAX_ALIGNMENT);
|
||||
const size_t alignment = static_cast<size_t>(stream_alignment);
|
||||
const size_t aligned_size = Common::AlignUp(size, alignment);
|
||||
const bool wraps = iterator + size >= stream_buffer_size;
|
||||
const size_t new_iterator =
|
||||
wraps ? aligned_size : Common::AlignUp(iterator + size, MAX_ALIGNMENT);
|
||||
wraps ? aligned_size : Common::AlignUp(iterator + size, alignment);
|
||||
const size_t begin_region = wraps ? 0 : Region(iterator);
|
||||
const size_t last_byte = new_iterator == 0 ? 0 : new_iterator - 1;
|
||||
const size_t end_region = (std::min)(Region(last_byte) + 1, NUM_SYNCS);
|
||||
|
@ -145,7 +149,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
|
|||
current_tick);
|
||||
used_iterator = 0;
|
||||
iterator = 0;
|
||||
free_iterator = size;
|
||||
free_iterator = aligned_size;
|
||||
const size_t head_last_byte = aligned_size == 0 ? 0 : aligned_size - 1;
|
||||
const size_t head_end_region = (std::min)(Region(head_last_byte) + 1, NUM_SYNCS);
|
||||
if (AreRegionsActive(0, head_end_region)) {
|
||||
|
@ -160,7 +164,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
|
|||
iterator = new_iterator;
|
||||
|
||||
if (!wraps) {
|
||||
free_iterator = (std::max)(free_iterator, offset + size);
|
||||
free_iterator = (std::max)(free_iterator, offset + aligned_size);
|
||||
}
|
||||
|
||||
return StagingBufferRef{
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
@ -102,6 +105,7 @@ private:
|
|||
MemoryAllocator& memory_allocator;
|
||||
Scheduler& scheduler;
|
||||
|
||||
VkDeviceSize stream_alignment;
|
||||
vk::Buffer stream_buffer;
|
||||
std::span<u8> stream_pointer;
|
||||
VkDeviceSize stream_buffer_size;
|
||||
|
|
|
@ -393,7 +393,7 @@ endif()
|
|||
|
||||
target_link_libraries(yuzu PRIVATE nlohmann_json::nlohmann_json)
|
||||
target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core qt_common)
|
||||
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt6::Widgets Qt6::Concurrent)
|
||||
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt6::Widgets)
|
||||
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
|
||||
|
||||
if (NOT WIN32)
|
||||
|
@ -408,6 +408,25 @@ if (UNIX AND NOT APPLE)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
target_compile_definitions(yuzu PRIVATE
|
||||
# Use QStringBuilder for string concatenation to reduce
|
||||
# the overall number of temporary strings created.
|
||||
QT_USE_QSTRINGBUILDER
|
||||
|
||||
# Disable implicit conversions from/to C strings
|
||||
QT_NO_CAST_FROM_ASCII
|
||||
QT_NO_CAST_TO_ASCII
|
||||
|
||||
# Disable implicit type narrowing in signal/slot connect() calls.
|
||||
QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
|
||||
|
||||
# Disable unsafe overloads of QProcess' start() function.
|
||||
QT_NO_PROCESS_COMBINED_ARGUMENT_START
|
||||
|
||||
# Disable implicit QString->QUrl conversions to enforce use of proper resolving functions.
|
||||
QT_NO_URL_CAST_FROM_STRING
|
||||
)
|
||||
|
||||
if (YUZU_ENABLE_COMPATIBILITY_REPORTING)
|
||||
target_compile_definitions(yuzu PRIVATE YUZU_ENABLE_COMPATIBILITY_REPORTING)
|
||||
endif()
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <QButtonGroup>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <qtconcurrentrun.h>
|
||||
#include <QtConcurrent/qtconcurrentrun.h>
|
||||
#include "common/logging/log.h"
|
||||
#include "ui_compatdb.h"
|
||||
#include "yuzu/compatdb.h"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <QRegExpValidator>
|
||||
#endif
|
||||
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include "common/settings.h"
|
||||
#include "ui_configure_web.h"
|
||||
#include "qt_common/uisettings.h"
|
||||
|
|
|
@ -4,16 +4,12 @@
|
|||
#include "data_dialog.h"
|
||||
#include "frontend_common/data_manager.h"
|
||||
#include "qt_common/qt_content_util.h"
|
||||
#include "qt_common/qt_frontend_util.h"
|
||||
#include "qt_common/qt_progress_dialog.h"
|
||||
#include "qt_common/qt_string_lookup.h"
|
||||
#include "ui_data_dialog.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
#include <QFutureWatcher>
|
||||
#include <QProgressDialog>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
|
||||
DataDialog::DataDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
|
@ -53,41 +49,25 @@ DataWidget::DataWidget(FrontendCommon::DataManager::DataDir data_dir,
|
|||
|
||||
ui->tooltip->setText(QtCommon::StringLookup::Lookup(tooltip));
|
||||
|
||||
ui->clear->setIcon(QIcon::fromTheme(QStringLiteral("user-trash")));
|
||||
ui->clear->setIcon(QIcon::fromTheme(QStringLiteral("trash")));
|
||||
ui->open->setIcon(QIcon::fromTheme(QStringLiteral("folder")));
|
||||
ui->upload->setIcon(QIcon::fromTheme(QStringLiteral("upload")));
|
||||
ui->download->setIcon(QIcon::fromTheme(QStringLiteral("download")));
|
||||
|
||||
connect(ui->clear, &QPushButton::clicked, this, &DataWidget::clear);
|
||||
connect(ui->open, &QPushButton::clicked, this, &DataWidget::open);
|
||||
connect(ui->upload, &QPushButton::clicked, this, &DataWidget::upload);
|
||||
connect(ui->download, &QPushButton::clicked, this, &DataWidget::download);
|
||||
|
||||
scan();
|
||||
}
|
||||
|
||||
void DataWidget::clear()
|
||||
{
|
||||
void DataWidget::clear() {
|
||||
QtCommon::Content::ClearDataDir(m_dir);
|
||||
scan();
|
||||
}
|
||||
|
||||
void DataWidget::open()
|
||||
{
|
||||
void DataWidget::open() {
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(
|
||||
QString::fromStdString(FrontendCommon::DataManager::GetDataDir(m_dir))));
|
||||
}
|
||||
|
||||
void DataWidget::upload()
|
||||
{
|
||||
QtCommon::Content::ExportDataDir(m_dir);
|
||||
}
|
||||
|
||||
void DataWidget::download()
|
||||
{
|
||||
QtCommon::Content::ImportDataDir(m_dir, std::bind(&DataWidget::scan, this));
|
||||
}
|
||||
|
||||
void DataWidget::scan() {
|
||||
ui->size->setText(tr("Calculating..."));
|
||||
|
||||
|
|
|
@ -37,9 +37,6 @@ public:
|
|||
public slots:
|
||||
void clear();
|
||||
void open();
|
||||
void upload();
|
||||
void download();
|
||||
|
||||
void scan();
|
||||
|
||||
private:
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,2">
|
||||
<item>
|
||||
<widget class="QLabel" name="tooltip">
|
||||
|
@ -50,8 +50,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,1">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>25</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="open">
|
||||
<property name="sizePolicy">
|
||||
|
@ -63,7 +69,7 @@
|
|||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>52</width>
|
||||
<height>47</height>
|
||||
<height>42</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
|
@ -71,10 +77,14 @@
|
|||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
border-style: solid;
|
||||
border-width:1px;
|
||||
border-radius:25px;
|
||||
border-color: transparent;
|
||||
max-width:50px;
|
||||
max-height: 45px;
|
||||
max-height:40px;
|
||||
min-width:50px;
|
||||
min-height: 45px;
|
||||
min-height:40px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
@ -82,8 +92,8 @@ min-height: 45px;
|
|||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -99,7 +109,7 @@ min-height: 45px;
|
|||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>52</width>
|
||||
<height>47</height>
|
||||
<height>42</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
|
@ -107,10 +117,14 @@ min-height: 45px;
|
|||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
border-style: solid;
|
||||
border-width:1px;
|
||||
border-radius:25px;
|
||||
border-color: transparent;
|
||||
max-width:50px;
|
||||
max-height: 45px;
|
||||
max-height:40px;
|
||||
min-width:50px;
|
||||
min-height: 45px;
|
||||
min-height:40px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
|
@ -118,80 +132,8 @@ min-height: 45px;
|
|||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="upload">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>52</width>
|
||||
<height>47</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Export all data in this directory. This may take a while!</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
max-width: 50px;
|
||||
max-height: 45px;
|
||||
min-width: 50px;
|
||||
min-height: 45px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="download">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>52</width>
|
||||
<height>47</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Import data for this directory. This may take a while, and will delete ALL EXISTING DATA!</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
max-width: 50px;
|
||||
max-height: 45px;
|
||||
min-width: 50px;
|
||||
min-height: 45px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
|
|
|
@ -3939,10 +3939,6 @@ void GMainWindow::OnEdenDependencies() {
|
|||
void GMainWindow::OnDataDialog() {
|
||||
DataDialog dataDialog(this);
|
||||
dataDialog.exec();
|
||||
|
||||
// refresh stuff in case it was cleared
|
||||
OnGameListRefresh();
|
||||
|
||||
}
|
||||
|
||||
void GMainWindow::OnToggleFilterBar() {
|
||||
|
@ -4485,15 +4481,11 @@ void GMainWindow::SetFirmwareVersion() {
|
|||
|
||||
if (result.IsError() || !CheckFirmwarePresence()) {
|
||||
LOG_INFO(Frontend, "Installed firmware: No firmware available");
|
||||
ui->menu_Applets->setEnabled(false);
|
||||
ui->menu_Create_Shortcuts->setEnabled(false);
|
||||
firmware_label->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
firmware_label->setVisible(true);
|
||||
ui->menu_Applets->setEnabled(true);
|
||||
ui->menu_Create_Shortcuts->setEnabled(true);
|
||||
|
||||
const std::string display_version(firmware_data.display_version.data());
|
||||
const std::string display_title(firmware_data.display_title.data());
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <QMetaType>
|
||||
#include <QTime>
|
||||
#include <QUrl>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include "common/logging/log.h"
|
||||
#include "network/announce_multiplayer_session.h"
|
||||
#include "ui_chat_room.h"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <QLocale>
|
||||
#include <QMetaType>
|
||||
#include <QTime>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include "common/logging/log.h"
|
||||
#include "network/announce_multiplayer_session.h"
|
||||
#include "ui_client_room.h"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <QIntValidator>
|
||||
#include <QRegularExpressionValidator>
|
||||
#include <QString>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/internal_network/network_interface.h"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <QMessageBox>
|
||||
#include <QMetaType>
|
||||
#include <QTime>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <QInputDialog>
|
||||
#include <QList>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
|
|