Add ENABLE_WIFI_SCAN option. Use libzip instead of QuaZip.

This commit is contained in:
weakboson 2025-07-23 18:21:59 +08:00
parent 8cd0d78269
commit 772352f047
10 changed files with 617 additions and 673 deletions

View file

@ -1,80 +0,0 @@
diff --git a/quazip/quazipdir.cpp b/quazip/quazipdir.cpp
index d43f1c1..eb24bf1 100644
--- a/quazip/quazipdir.cpp
+++ b/quazip/quazipdir.cpp
@@ -293,8 +293,8 @@ bool QuaZipDirComparator::operator()(const QuaZipFileInfo64 &info1,
}
template<typename TFileInfoList>
-bool QuaZipDirPrivate::entryInfoList(QStringList nameFilters,
- QDir::Filters filter, QDir::SortFlags sort, TFileInfoList &result) const
+bool QuaZipDirPrivate::entryInfoList(QStringList _nameFilters,
+ QDir::Filters _filter, QDir::SortFlags sort, TFileInfoList &result) const
{
QString basePath = simplePath();
if (!basePath.isEmpty())
@@ -305,12 +305,12 @@ bool QuaZipDirPrivate::entryInfoList(QStringList nameFilters,
if (!zip->goToFirstFile()) {
return zip->getZipError() == UNZ_OK;
}
- QDir::Filters fltr = filter;
+ QDir::Filters fltr = _filter;
if (fltr == QDir::NoFilter)
fltr = this->filter;
if (fltr == QDir::NoFilter)
fltr = QDir::AllEntries;
- QStringList nmfltr = nameFilters;
+ QStringList nmfltr = _nameFilters;
if (nmfltr.isEmpty())
nmfltr = this->nameFilters;
QSet<QString> dirsFound;
diff --git a/quazip/quazipfile.cpp b/quazip/quazipfile.cpp
index 4a5f2f9..f7865f5 100644
--- a/quazip/quazipfile.cpp
+++ b/quazip/quazipfile.cpp
@@ -241,14 +241,14 @@ void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs
p->caseSensitivity=cs;
}
-void QuaZipFilePrivate::setZipError(int zipError) const
+void QuaZipFilePrivate::setZipError(int _zipError) const
{
QuaZipFilePrivate *fakeThis = const_cast<QuaZipFilePrivate*>(this); // non-const
- fakeThis->zipError=zipError;
- if(zipError==UNZ_OK)
+ fakeThis->zipError = _zipError;
+ if(_zipError == UNZ_OK)
q->setErrorString(QString());
else
- q->setErrorString(QuaZipFile::tr("ZIP/UNZIP API error %1").arg(zipError));
+ q->setErrorString(QuaZipFile::tr("ZIP/UNZIP API error %1").arg(_zipError));
}
bool QuaZipFile::open(OpenMode mode)
diff --git a/quazip/unzip.c b/quazip/unzip.c
index a39365d..ee7b487 100644
--- a/quazip/unzip.c
+++ b/quazip/unzip.c
@@ -1054,7 +1054,7 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
/* ZIP64 extra fields */
if (headerId == 0x0001)
{
- uLong uL;
+ uLong _uL;
if(file_info.uncompressed_size == (ZPOS64_T)0xFFFFFFFFu)
{
@@ -1078,7 +1078,7 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
if(file_info.disk_num_start == 0xFFFFFFFFu)
{
/* Disk Start Number */
- if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ if (unz64local_getLong(&s->z_filefunc, s->filestream, &_uL) != UNZ_OK)
err=UNZ_ERRNO;
}
@@ -2151,3 +2151,4 @@ int ZEXPORT unzClearFlags(unzFile file, unsigned flags)
s->flags &= ~flags;
return UNZ_OK;
}
+

View file

@ -1,13 +0,0 @@
diff --git a/cmake/clone-repo.cmake b/cmake/clone-repo.cmake
index 2ffb4b2..77974dc 100644
--- a/cmake/clone-repo.cmake
+++ b/cmake/clone-repo.cmake
@@ -26,7 +26,7 @@ macro(clone_repo name url)
FetchContent_GetProperties(${name} POPULATED ${name_lower}_POPULATED)
if(NOT ${name_lower}_POPULATED)
- FetchContent_Populate(${name})
+ FetchContent_MakeAvailable(${name})
endif()
set(${name_upper}_SOURCE_DIR ${${name_lower}_SOURCE_DIR})

View file

@ -50,6 +50,7 @@ option(ENABLE_QT_UPDATE_CHECKER "Enable update checker for the Qt frontend" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(ENABLE_WIFI_SCAN "Enable WiFi scanning" OFF)
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" OFF)
@ -416,6 +417,10 @@ if (UNIX AND NOT APPLE)
find_package(gamemode 1.7 MODULE)
endif()
if (ENABLE_QT)
find_package(libzip CONFIG REQUIRED)
endif()
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package
if (ENABLE_SDL2)
if (YUZU_USE_BUNDLED_SDL2)
@ -458,19 +463,22 @@ if (ENABLE_QT)
if (YUZU_USE_BUNDLED_QT)
download_qt(6.8.3)
else()
message(STATUS "Using system Qt")
if (NOT Qt6_DIR)
set(Qt6_DIR "" CACHE PATH "Additional path to search for Qt6 libraries like C:/Qt/6.8.3/msvc2022_64/lib/cmake/Qt6")
endif()
list(APPEND CMAKE_PREFIX_PATH "${Qt6_DIR}")
endif()
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent)
if (Qt6_FOUND)
message(STATUS "Found Qt6: ${Qt6_DIR}")
endif()
# QT6 Multimedia pulls in unneeded audio systems (ALSA, Pulseaudio) for FreeBSD
# ALSA is the default sound system on Linux, but FreeBSD uses OSS which works well enough
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent)
else()
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent)
if (YUZU_USE_QT_MULTIMEDIA)
find_package(Qt6 REQUIRED COMPONENTS Multimedia)
endif()
if (UNIX AND NOT APPLE)

View file

@ -91,11 +91,11 @@ function(determine_qt_parameters target host_out type_out arch_out arch_path_out
set(type "desktop")
set(arch "clang_64")
set(arch_path "macos")
else()
elseif (LINUX)
set(host "linux")
set(type "desktop")
set(arch "gcc_64")
set(arch_path "linux")
set(arch "linux_gcc_64")
set(arch_path "gcc_64")
endif()
set(${host_out} "${host}" PARENT_SCOPE)
@ -129,16 +129,29 @@ function(download_qt_configuration prefix_out target host type arch arch_path ba
set(install_args -c "${CURRENT_MODULE_DIR}/aqt_config.ini")
if (tool)
set(prefix "${base_path}/Tools")
set(prefix "${base_path}/tools")
set(install_args ${install_args} install-tool --outputdir ${base_path} ${host} desktop ${target})
else()
set(prefix "${base_path}/${target}/${arch_path}")
set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} -m qt3d qt5compat qtactiveqt qtcharts qtconnectivity qtdatavis3d qtgraphs qtgrpc qthttpserver qtimageformats qtlanguageserver qtlocation qtlottie qtmultimedia qtnetworkauth qtpdf qtpositioning qtquick3d qtquick3dphysics qtquickeffectmaker qtquicktimeline qtremoteobjects qtscxml qtsensors qtserialbus qtserialport qtshadertools qtspeech qtvirtualkeyboard qtwebchannel qtwebengine qtwebsockets qtwebview)
set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} -m qt_base)
if (YUZU_USE_QT_MULTIMEDIA)
set(install_args ${install_args} qtmultimedia)
endif()
if (YUZU_USE_QT_WEB_ENGINE)
set(install_args ${install_args} qtpositioning qtwebchannel qtwebengine)
endif()
if (NOT ${YUZU_QT_MIRROR} STREQUAL "")
message(STATUS "Using Qt mirror ${YUZU_QT_MIRROR}")
set(install_args ${install_args} -b ${YUZU_QT_MIRROR})
endif()
endif()
if (NOT EXISTS "${prefix}")
message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}")
set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.2.1")
set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.3.0")
if (WIN32)
set(aqt_path "${base_path}/aqt.exe")
if (NOT EXISTS "${aqt_path}")
@ -158,14 +171,28 @@ function(download_qt_configuration prefix_out target host type arch arch_path ba
execute_process(COMMAND chmod +x ${aqt_path})
execute_process(COMMAND ${aqt_path} ${install_args}
WORKING_DIRECTORY ${base_path})
else()
elseif (LINUX)
set(aqt_install_path "${base_path}/aqt")
file(MAKE_DIRECTORY "${aqt_install_path}")
execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall
WORKING_DIRECTORY ${base_path})
execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args}
WORKING_DIRECTORY ${base_path})
find_package(Python3 COMPONENTS Interpreter)
execute_process(
COMMAND ${Python3_EXECUTABLE} -m venv .venv
WORKING_DIRECTORY ${base_path}
)
set(ENV{VIRTUAL_ENV} "${base_path}/.venv")
set(Python3_FIND_VIRTUALENV FIRST)
unset(Python3_EXECUTABLE)
find_package(Python3 COMPONENTS Interpreter)
execute_process(
COMMAND ${Python3_EXECUTABLE} -m pip install aqtinstall
WORKING_DIRECTORY ${base_path}
)
execute_process(
COMMAND ${Python3_EXECUTABLE} -m aqt ${install_args}
WORKING_DIRECTORY ${base_path}
)
endif()
message(STATUS "Downloaded Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path} to ${prefix}")

View file

@ -1150,18 +1150,19 @@ add_library(core STATIC
tools/renderdoc.h
)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_WIFI_SCAN)
# find_package(libiw REQUIRED)
target_compile_definitions(core PRIVATE -DENABLE_WIFI_SCAN)
target_link_libraries(core PRIVATE iw)
endif()
if (WIN32)
target_compile_definitions(core PRIVATE _WIN32_WINNT=0x0A00 WINVER=0x0A00)
if(TARGET iw)
target_link_libraries(core PRIVATE iw)
message(STATUS "Linking 'core' with iw on Linux.")
endif()
# if(TARGET iw)
# target_link_libraries(core PRIVATE iw)
# message(STATUS "Linking 'core' with iw on Linux.")
# endif()
endif()
if (MSVC)

View file

@ -20,6 +20,7 @@ using namespace std::chrono_literals;
namespace Network {
#ifdef ENABLE_WIFI_SCAN
#ifdef _WIN32
static u8 QualityToPercent(DWORD q) {
return static_cast<u8>(q);
@ -95,8 +96,7 @@ static u8 QualityToPercent(const iwrange& r, const wireless_scan* ws) {
return static_cast<u8>(std::clamp(100 * lvl / max, 0, 100));
}
static int wifi_callback(int skfd, char* ifname, char* args[], int count)
{
static int wifi_callback(int skfd, char* ifname, char* args[], int count) {
iwrange range;
int res = iw_get_range_info(skfd, ifname, &range);
@ -173,16 +173,20 @@ static std::vector<Network::ScanData> ScanWifiLinux(std::chrono::milliseconds de
return out;
}
#endif /* linux */
#endif
std::vector<Network::ScanData> ScanWifiNetworks(std::chrono::milliseconds deadline) {
#ifdef ENABLE_WIFI_SCAN
#ifdef _WIN32
return ScanWifiWin(deadline);
#elif defined(__linux__) && !defined(ANDROID)
return ScanWifiLinux(deadline);
#else
std::this_thread::sleep_for(deadline);
return {}; // unsupported host, pretend no results
#endif
#else
return {};
#endif
}
} // namespace Network

View file

@ -19,4 +19,4 @@ struct ScanData {
static_assert(sizeof(ScanData) <= 0x2C, "ScanData layout changed update conversions!");
std::vector<Network::ScanData> ScanWifiNetworks(std::chrono::milliseconds deadline);
}
} // namespace Network

View file

@ -494,8 +494,6 @@ if (YUZU_ROOM)
target_link_libraries(yuzu PRIVATE yuzu-room)
endif()
# Extra deps
add_subdirectory(externals)
target_link_libraries(yuzu PRIVATE QuaZip::QuaZip)
target_link_libraries(yuzu PRIVATE libzip::zip)
create_target_directory_groups(yuzu)

View file

@ -1,31 +0,0 @@
# Disable tests in all externals supporting the standard option name
set(BUILD_TESTING OFF)
# Build only static externals
set(BUILD_SHARED_LIBS OFF)
# QuaZip
set(QUAZIP_QT_MAJOR_VERSION 6)
set(QUAZIP_BZIP2 OFF)
include(CPM)
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm)
set(CPM_USE_LOCAL_PACKAGES ON)
CPMAddPackage(
NAME QuaZip-Qt6
VERSION 1.3
GIT_REPOSITORY "https://github.com/stachenov/quazip.git"
GIT_TAG v1.5
PATCHES
${CMAKE_SOURCE_DIR}/.ci/patch/0001-quazip-strict.patch
${CMAKE_SOURCE_DIR}/.ci/patch/0002-quazip-fetchcontent.patch
)
if (NOT MSVC AND NOT "QuaZip-Qt6" IN_LIST CPM_PACKAGES)
message(STATUS "QUAZIP DIR: ${CPM_PACKAGES}")
target_compile_options(QuaZip PRIVATE
-Wno-error=shadow
-Wno-error=missing-declarations
)
endif()

View file

@ -12,7 +12,7 @@
#include "core/tools/renderdoc.h"
#include "frontend_common/firmware_manager.h"
#include <JlCompress.h>
#include "zip.h"
#ifdef __APPLE__
#include <unistd.h> // for chdir
@ -37,8 +37,8 @@
#include "configuration/configure_input.h"
#include "configuration/configure_per_game.h"
#include "configuration/configure_tas.h"
#include "core/file_sys/romfs_factory.h"
#include "core/core_timing.h"
#include "core/file_sys/romfs_factory.h"
#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_real.h"
#include "core/frontend/applets/cabinet.h"
@ -313,8 +313,7 @@ bool GMainWindow::CheckDarkMode() {
GMainWindow::GMainWindow(bool has_broken_vulkan)
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
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>()},
provider{std::make_unique<FileSys::ManualContentProvider>()} {
Common::FS::CreateEdenPaths();
@ -322,7 +321,8 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
if (user_data_migrator.migrated) {
// Sort-of hack whereby we only move the old dir if it's a subfolder of the user dir
#define MIGRATE_DIR(type) std::string type##path = Common::FS::GetEdenPathString(Common::FS::EdenPath::type##Dir); \
#define MIGRATE_DIR(type) \
std::string type##path = Common::FS::GetEdenPathString(Common::FS::EdenPath::type##Dir); \
if (type##path.starts_with(user_data_migrator.selected_emu.get_user_dir())) { \
boost::replace_all(type##path, user_data_migrator.selected_emu.lower_name(), "eden"); \
Common::FS::SetEdenPath(Common::FS::EdenPath::type##Dir, type##path); \
@ -436,8 +436,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
#ifdef ENABLE_QT_UPDATE_CHECKER
if (UISettings::values.check_for_updates) {
update_future = QtConcurrent::run([]() -> QString {
const bool is_prerelease =
((strstr(Common::g_build_version, "pre-alpha") != NULL) ||
const bool is_prerelease = ((strstr(Common::g_build_version, "pre-alpha") != NULL) ||
(strstr(Common::g_build_version, "alpha") != NULL) ||
(strstr(Common::g_build_version, "beta") != NULL) ||
(strstr(Common::g_build_version, "rc") != NULL));
@ -1667,7 +1666,8 @@ void GMainWindow::ConnectMenuEvents() {
connect_menu(ui->action_Load_Home_Menu, &GMainWindow::OnHomeMenu);
connect_menu(ui->action_Open_Setup, &GMainWindow::OnInitialSetup);
connect_menu(ui->action_Desktop, &GMainWindow::OnCreateHomeMenuDesktopShortcut);
connect_menu(ui->action_Application_Menu, &GMainWindow::OnCreateHomeMenuApplicationMenuShortcut);
connect_menu(ui->action_Application_Menu,
&GMainWindow::OnCreateHomeMenuApplicationMenuShortcut);
connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
// TAS
@ -1872,7 +1872,6 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
system->GetUserChannel().clear();
}
system->SetFrontendAppletSet({
std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings
(UISettings::values.controller_applet_disabled.GetValue() == true)
@ -1894,12 +1893,14 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
QSettings settings;
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))) {
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 "
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."));
@ -1913,7 +1914,8 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
int result = msg->exec();
// wtf
QMessageBox::ButtonRole role = msg->buttonRole(msg->button((QMessageBox::StandardButton) result));
QMessageBox::ButtonRole role =
msg->buttonRole(msg->button((QMessageBox::StandardButton)result));
switch (role) {
case QMessageBox::RejectRole:
@ -1929,11 +1931,13 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
}
}
if (FirmwareManager::GameRequiresFirmware(params.program_id) && !FirmwareManager::CheckFirmwarePresence(*system)) {
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 "
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."));
@ -1941,7 +1945,8 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
int exec_result = msg->exec();
QMessageBox::ButtonRole role = msg->buttonRole(msg->button((QMessageBox::StandardButton) exec_result));
QMessageBox::ButtonRole role =
msg->buttonRole(msg->button((QMessageBox::StandardButton)exec_result));
switch (role) {
case QMessageBox::RejectRole:
@ -1970,7 +1975,8 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
"outdated format that has been superseded by others such as NCA, NAX, XCI, or "
"NSP. Deconstructed ROM directories lack icons, metadata, and update "
"support.<br><br>For an explanation of the various Switch formats eden supports, <a "
"href='https://eden-emulator.github.io/wiki/overview-of-switch-game-formats'>check out our "
"href='https://eden-emulator.github.io/wiki/overview-of-switch-game-formats'>check "
"out our "
"wiki</a>. This message will not be shown again."));
}
@ -2996,7 +3002,8 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
directory = it->second.second;
}
QDesktopServices::openUrl(QUrl(QStringLiteral("https://eden-emulator.github.io/game/") + directory));
QDesktopServices::openUrl(
QUrl(QStringLiteral("https://eden-emulator.github.io/game/") + directory));
}
bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path,
@ -3653,8 +3660,7 @@ void GMainWindow::OnOpenFAQ() {
OpenURL(QUrl(QStringLiteral("https://eden-emulator.github.io/")));
}
void GMainWindow::OnOpenDiscord()
{
void GMainWindow::OnOpenDiscord() {
OpenURL(QUrl(QStringLiteral("https://discord.gg/edenemu")));
}
@ -4185,30 +4191,26 @@ void GMainWindow::LoadAmiibo(const QString& filename) {
}
void GMainWindow::OnOpenRootDataFolder() {
QDesktopServices::openUrl(QUrl(
QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::EdenDir))));
QDesktopServices::openUrl(
QUrl(QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::EdenDir))));
}
void GMainWindow::OnOpenNANDFolder()
{
void GMainWindow::OnOpenNANDFolder() {
QDesktopServices::openUrl(QUrl::fromLocalFile(
QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::NANDDir))));
}
void GMainWindow::OnOpenSDMCFolder()
{
void GMainWindow::OnOpenSDMCFolder() {
QDesktopServices::openUrl(QUrl::fromLocalFile(
QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::SDMCDir))));
}
void GMainWindow::OnOpenModFolder()
{
void GMainWindow::OnOpenModFolder() {
QDesktopServices::openUrl(QUrl::fromLocalFile(
QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::LoadDir))));
}
void GMainWindow::OnOpenLogFolder()
{
void GMainWindow::OnOpenLogFolder() {
QDesktopServices::openUrl(QUrl::fromLocalFile(
QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::LogDir))));
}
@ -4243,8 +4245,7 @@ void GMainWindow::OnVerifyInstalledContents() {
}
}
void GMainWindow::InstallFirmware(const QString &location, bool recursive)
{
void GMainWindow::InstallFirmware(const QString& location, bool recursive) {
QProgressDialog progress(tr("Installing Firmware..."), tr("Cancel"), 0, 100, this);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(100);
@ -4281,9 +4282,11 @@ void GMainWindow::InstallFirmware(const QString &location, bool recursive)
QtProgressCallback(100, 10);
if (recursive) {
Common::FS::IterateDirEntriesRecursively(firmware_source_path, callback, Common::FS::DirEntryFilter::File);
Common::FS::IterateDirEntriesRecursively(firmware_source_path, callback,
Common::FS::DirEntryFilter::File);
} else {
Common::FS::IterateDirEntries(firmware_source_path, callback, Common::FS::DirEntryFilter::File);
Common::FS::IterateDirEntries(firmware_source_path, callback,
Common::FS::DirEntryFilter::File);
}
if (out.size() <= 0) {
@ -4391,8 +4394,7 @@ void GMainWindow::OnInstallFirmware() {
InstallFirmware(firmware_source_location);
}
void GMainWindow::OnInstallFirmwareFromZIP()
{
void GMainWindow::OnInstallFirmwareFromZIP() {
// Don't do this while emulation is running, that'd probably be a bad idea.
if (emu_thread != nullptr && emu_thread->IsRunning()) {
return;
@ -4413,28 +4415,67 @@ void GMainWindow::OnInstallFirmwareFromZIP()
}
namespace fs = std::filesystem;
fs::path tmp{std::filesystem::temp_directory_path()};
if (!std::filesystem::create_directories(tmp / "eden" / "firmware")) {
goto unzipFailed;
}
fs::path tmp = std::filesystem::temp_directory_path() / "eden" / "firmware";
QString cache_dir = QString::fromStdString(tmp.string());
{
tmp /= "eden";
tmp /= "firmware";
QString qCacheDir = QString::fromStdString(tmp.string());
QFile zip(firmware_zip_location);
QStringList result = JlCompress::extractDir(&zip, qCacheDir);
if (result.isEmpty()) {
goto unzipFailed;
if (!QDir().mkpath(cache_dir)) {
QMessageBox::critical(
this, tr("Firmware unzip failed"),
tr("Failed to create temp directory.\n"
"Check write permissions in the system temp directory and try again."));
return;
}
int err = 0;
zip_t* zip = zip_open(firmware_zip_location.toUtf8(), 0, &err);
if (zip == nullptr) {
QMessageBox::critical(
this, tr("Firmware unzip failed"),
tr("Failed to open the firmware zip file.\n"
"Check file format and avoid special characters in file path."));
return;
}
zip_int64_t num_entries = zip_get_num_entries(zip, 0);
for (zip_int64_t i = 0; i < num_entries; i++) {
const char* name = zip_get_name(zip, i, 0);
if (!name) {
continue;
}
zip_file_t* zip_file = zip_fopen_index(zip, i, 0);
if (!zip_file) {
continue;
}
QString file_path = QString::fromStdString(tmp / name);
QFileInfo file_info(file_path);
QDir().mkpath(file_info.path());
QFile file(file_path);
if (!file.open(QIODevice::WriteOnly)) {
zip_fclose(zip_file);
continue;
}
zip_stat_t sb;
zip_stat_index(zip, i, 0, &sb);
char* contents = new char[sb.size];
zip_fread(zip_file, contents, sb.size);
file.write(contents, sb.size);
delete[] contents;
file.close();
zip_fclose(zip_file);
}
zip_close(zip);
// In this case, it has to be done recursively, since sometimes people
// will pack it into a subdirectory after dumping
InstallFirmware(qCacheDir, true);
InstallFirmware(cache_dir, true);
std::error_code ec;
std::filesystem::remove_all(tmp, ec);
@ -4442,17 +4483,13 @@ void GMainWindow::OnInstallFirmwareFromZIP()
if (ec) {
QMessageBox::warning(this, tr("Firmware cleanup failed"),
tr("Failed to clean up extracted firmware cache.\n"
"Check write permissions in the system temp directory and try again.\nOS reported error: %1")
"Check write permissions in the system temp directory and try "
"again.\nOS reported error: %1")
.arg(QString::fromStdString(ec.message())));
}
return;
}
unzipFailed:
QMessageBox::critical(this, tr("Firmware unzip failed"),
tr("Check write permissions in the system temp directory and try again."));
return;
}
void GMainWindow::OnInstallDecryptionKeys() {
@ -4468,7 +4505,8 @@ void GMainWindow::OnInstallDecryptionKeys() {
return;
}
FirmwareManager::KeyInstallResult result = FirmwareManager::InstallKeys(key_source_location.toStdString(), "keys");
FirmwareManager::KeyInstallResult result =
FirmwareManager::InstallKeys(key_source_location.toStdString(), "keys");
system->GetFileSystemController().CreateFactories(*vfs);
game_list->PopulateAsync(UISettings::values.game_dirs);
@ -4479,8 +4517,7 @@ void GMainWindow::OnInstallDecryptionKeys() {
tr("Decryption Keys were successfully installed"));
break;
default:
QMessageBox::critical(
this, tr("Decryption Keys install failed"),
QMessageBox::critical(this, tr("Decryption Keys install failed"),
tr(FirmwareManager::GetKeyInstallResultString(result)));
break;
}
@ -4507,8 +4544,7 @@ void GMainWindow::OnToggleStatusBar() {
statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
}
void GMainWindow::OnGameListRefresh()
{
void GMainWindow::OnGameListRefresh() {
// force reload add-ons etc
game_list->ForceRefreshGameDirectory();
}
@ -4631,8 +4667,7 @@ void GMainWindow::OnHomeMenu() {
BootGame(filename, LibraryAppletParameters(QLaunchId, Service::AM::AppletId::QLaunch));
}
void GMainWindow::OnInitialSetup()
{
void GMainWindow::OnInitialSetup() {
constexpr u64 Starter = static_cast<u64>(Service::AM::AppletProgramId::Starter);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
@ -4655,18 +4690,15 @@ void GMainWindow::OnInitialSetup()
BootGame(filename, LibraryAppletParameters(Starter, Service::AM::AppletId::Starter));
}
void GMainWindow::OnCreateHomeMenuDesktopShortcut()
{
void GMainWindow::OnCreateHomeMenuDesktopShortcut() {
OnCreateHomeMenuShortcut(GameListShortcutTarget::Desktop);
}
void GMainWindow::OnCreateHomeMenuApplicationMenuShortcut()
{
void GMainWindow::OnCreateHomeMenuApplicationMenuShortcut() {
OnCreateHomeMenuShortcut(GameListShortcutTarget::Applications);
}
std::filesystem::path GMainWindow::GetEdenCommand()
{
std::filesystem::path GMainWindow::GetEdenCommand() {
std::filesystem::path command;
QString appimage = QString::fromLocal8Bit(getenv("APPIMAGE"));
@ -4685,8 +4717,7 @@ std::filesystem::path GMainWindow::GetEdenCommand()
return command;
}
std::filesystem::path GMainWindow::GetShortcutPath(GameListShortcutTarget target)
{
std::filesystem::path GMainWindow::GetShortcutPath(GameListShortcutTarget target) {
std::filesystem::path shortcut_path{};
if (target == GameListShortcutTarget::Desktop) {
shortcut_path =
@ -4699,7 +4730,9 @@ std::filesystem::path GMainWindow::GetShortcutPath(GameListShortcutTarget target
return shortcut_path;
}
void GMainWindow::CreateShortcut(const std::string &game_path, const u64 program_id, const std::string& game_title_, GameListShortcutTarget target, std::string arguments_, const bool needs_title) {
void GMainWindow::CreateShortcut(const std::string& game_path, const u64 program_id,
const std::string& game_title_, GameListShortcutTarget target,
std::string arguments_, const bool needs_title) {
// Get path to yuzu executable
std::filesystem::path command = GetEdenCommand();
@ -4780,8 +4813,8 @@ void GMainWindow::CreateShortcut(const std::string &game_path, const u64 program
const std::string categories = "Game;Emulator;Qt;";
const std::string keywords = "Switch;Nintendo;";
if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, command,
arguments, categories, keywords, game_title)) {
if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, command, arguments,
categories, keywords, game_title)) {
GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS,
qgame_title);
return;
@ -4790,8 +4823,7 @@ void GMainWindow::CreateShortcut(const std::string &game_path, const u64 program
qgame_title);
}
void GMainWindow::OnCreateHomeMenuShortcut(GameListShortcutTarget target)
{
void GMainWindow::OnCreateHomeMenuShortcut(GameListShortcutTarget target) {
constexpr u64 QLaunchId = static_cast<u64>(Service::AM::AppletProgramId::QLaunch);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
@ -4884,8 +4916,8 @@ void GMainWindow::OnEmulatorUpdateAvailable() {
update_prompt.setIcon(QMessageBox::Information);
update_prompt.addButton(QMessageBox::Yes);
update_prompt.addButton(QMessageBox::Ignore);
update_prompt.setText(tr("Update %1 for Eden is available.\nWould you like to download it?")
.arg(version_string));
update_prompt.setText(
tr("Update %1 for Eden is available.\nWould you like to download it?").arg(version_string));
update_prompt.exec();
if (update_prompt.button(QMessageBox::Yes) == update_prompt.clickedButton()) {
QDesktopServices::openUrl(
@ -5015,7 +5047,8 @@ void GMainWindow::UpdateStatusBar() {
}
game_fps_label->setText(
tr("Game: %1 FPS").arg(std::round(results.average_game_fps), 0, 'f', 0) + tr(Settings::values.use_speed_limit ? "" : " (Unlocked)"));
tr("Game: %1 FPS").arg(std::round(results.average_game_fps), 0, 'f', 0) +
tr(Settings::values.use_speed_limit ? "" : " (Unlocked)"));
emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
@ -5142,24 +5175,21 @@ void GMainWindow::OnMouseActivity() {
void GMainWindow::OnCheckFirmwareDecryption() {
system->GetFileSystemController().CreateFactories(*vfs);
if (!ContentManager::AreKeysPresent()) {
QMessageBox::warning(
this, tr("Derivation Components Missing"),
QMessageBox::warning(this, tr("Derivation Components Missing"),
tr("Encryption keys are missing."));
}
SetFirmwareVersion();
UpdateMenuState();
}
void GMainWindow::OnCheckFirmware()
{
void GMainWindow::OnCheckFirmware() {
auto result = FirmwareManager::VerifyFirmware(*system.get());
switch (result) {
case FirmwareManager::FirmwareGood:
break;
default:
QMessageBox::warning(
this, tr("Firmware Read Error"),
QMessageBox::warning(this, tr("Firmware Read Error"),
tr(FirmwareManager::GetFirmwareCheckString(result)));
break;
}