From 8e387dc156c1fdedde7752a0d90723aa7089cf18 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 30 Aug 2025 13:43:05 +0000 Subject: [PATCH 01/11] [compat] improve thread naming logic Signed-off-by: lizzie --- src/common/thread.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 34cc1527bf..516a5893ec 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -1,3 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,9 +17,8 @@ #else #if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) #include -#else -#include #endif +#include #include #endif #ifndef _WIN32 @@ -90,33 +91,35 @@ void SetCurrentThreadName(const char* name) { #else // !MSVC_VER, so must be POSIX threads // MinGW with the POSIX threading model does not support pthread_setname_np -#if !defined(_WIN32) || defined(_MSC_VER) void SetCurrentThreadName(const char* name) { + // See for reference + // https://gitlab.freedesktop.org/mesa/mesa/-/blame/main/src/util/u_thread.c?ref_type=heads#L75 #ifdef __APPLE__ pthread_setname_np(name); +#elif defined(__HAIKU__) + rename_thread(find_thread(NULL), name); #elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) pthread_set_name_np(pthread_self(), name); #elif defined(__NetBSD__) pthread_setname_np(pthread_self(), "%s", (void*)name); -#elif defined(__linux__) - // Linux limits thread names to 15 characters and will outright reject any - // attempt to set a longer name with ERANGE. - std::string truncated(name, std::min(strlen(name), static_cast(15))); - if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) { - errno = e; - LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg()); +#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun__) || defined(__glibc__) || defined(__managarm__) + int ret = pthread_setname_np(pthread_self(), name); + if (ret == ERANGE) { + // Linux limits thread names to 15 characters and will outright reject any + // attempt to set a longer name with ERANGE. + char buf[16]; + size_t const len = std::min(std::strlen(name), sizeof(buf) - 1); + std::memcpy(buf, name, len); + buf[len] = '\0'; + pthread_setname_np(pthread_self(), buf); } +#elif !defined(_WIN32) || defined(_MSC_VER) + // mingw stub + (void)name; #else pthread_setname_np(pthread_self(), name); #endif } -#endif - -#if defined(_WIN32) -void SetCurrentThreadName(const char* name) { - // Do Nothing on MingW -} -#endif #endif From f005f6a3abcf59641af47f420569457d20c58d05 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 30 Aug 2025 17:03:56 +0200 Subject: [PATCH 02/11] [compat] fix freebsd mmap virtual base (#354) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/354 Reviewed-by: Shinmegumi Co-authored-by: lizzie Co-committed-by: lizzie --- src/common/host_memory.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index edb64de8ec..e70ac216cb 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -417,14 +417,11 @@ static void* ChooseVirtualBase(size_t virtual_size) { #else static void* ChooseVirtualBase(size_t virtual_size) { -#if defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__managarm__) +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__managarm__) || defined(__AIX__) void* virtual_base = mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER, -1, 0); - - if (virtual_base != MAP_FAILED) { + if (virtual_base != MAP_FAILED) return virtual_base; - } #endif - return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); } From ab015bc7305d7eec23451ec2f7b577e26f1e1ba1 Mon Sep 17 00:00:00 2001 From: JPikachu Date: Sat, 30 Aug 2025 19:35:53 +0200 Subject: [PATCH 03/11] [VK] Fix asserts with incorrect memory allocations (#357) This fixes many assertions with incorrect memory allocations. Regression introduced in PR 334. Co-authored-by: JPikachu Co-authored-by: MaranBr Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/357 Reviewed-by: Lizzie Reviewed-by: crueter Co-authored-by: JPikachu Co-committed-by: JPikachu --- src/video_core/vulkan_common/vulkan_device.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index cfa88850a0..95c0d974cc 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1378,13 +1378,13 @@ void Device::CollectPhysicalMemoryInfo() { device_access_memory += mem_properties.memoryHeaps[element].size; } if (!is_integrated) { - const u64 reserve_memory = std::min(device_access_memory / 4, 2_GiB); + const u64 reserve_memory = std::min(device_access_memory / 8, 1_GiB); device_access_memory -= reserve_memory; if (Settings::values.vram_usage_mode.GetValue() != Settings::VramUsageMode::Aggressive) { // Account for resolution scaling in memory limits - const size_t normal_memory = 8_GiB; - const size_t scaler_memory = 2_GiB * Settings::values.resolution_info.ScaleUp(1); + const size_t normal_memory = 6_GiB; + const size_t scaler_memory = 1_GiB * Settings::values.resolution_info.ScaleUp(1); device_access_memory = std::min(device_access_memory, normal_memory + scaler_memory); } @@ -1393,7 +1393,7 @@ void Device::CollectPhysicalMemoryInfo() { } const s64 available_memory = static_cast(device_access_memory - device_initial_usage); device_access_memory = static_cast(std::max( - std::min(available_memory - 4_GiB, 6_GiB), std::min(local_memory, 6_GiB))); + std::min(available_memory - 8_GiB, 6_GiB), std::min(local_memory, 6_GiB))); } void Device::CollectToolingInfo() { From 76de9d6c8c5adf73170d99ba74f8d0c61f0c60dd Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 30 Aug 2025 20:32:21 +0200 Subject: [PATCH 04/11] [cmake, compat] fix solaris boost build once and for all (#364) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/364 Reviewed-by: CamilleLaVey Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d11b58bf1f..55ed83c929 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -406,8 +406,10 @@ if (YUZU_USE_CPM) if (NOT MSVC) # boost sucks - if (NOT PLATFORM_LINUX AND NOT ANDROID) - target_compile_definitions(boost_container INTERFACE BOOST_HAS_PTHREADS) + # Solaris (and probably other NIXes) need explicit pthread definition + if (PLATFORM_SUN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthreads") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthreads") endif() target_compile_options(boost_heap INTERFACE -Wno-shadow) From 3b4c1beb0c400c566058063b9a77af033532d080 Mon Sep 17 00:00:00 2001 From: crueter Date: Sat, 30 Aug 2025 20:32:28 +0200 Subject: [PATCH 05/11] [desktop] only warn on firmware for qlaunch/games (#363) - only warns about too new/missing for home menu - only warns about missing for games that need it (mk8dx) Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/363 Reviewed-by: CamilleLaVey Reviewed-by: MaranBr --- src/yuzu/main.cpp | 58 ++++++++++++++++++++++++++----------------- src/yuzu/main.h | 1 - src/yuzu/uisettings.h | 3 +++ 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 2c3c46114d..a080132958 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -553,9 +553,6 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) // Gen keys if necessary OnCheckFirmwareDecryption(); - // Check firmware - OnCheckFirmware(); - game_list->LoadCompatibilityList(); // force reload on first load to ensure add-ons get updated game_list->PopulateAsync(UISettings::values.game_dirs, false); @@ -4459,7 +4456,6 @@ void GMainWindow::InstallFirmware(const QString& location, bool recursive) { progress.close(); OnCheckFirmwareDecryption(); - OnCheckFirmware(); } void GMainWindow::OnInstallFirmware() { @@ -4580,7 +4576,6 @@ void GMainWindow::OnInstallDecryptionKeys() { } OnCheckFirmwareDecryption(); - OnCheckFirmware(); } void GMainWindow::OnAbout() { @@ -4609,6 +4604,7 @@ void GMainWindow::OnToggleStatusBar() { void GMainWindow::OnGameListRefresh() { // force reload add-ons etc game_list->ForceRefreshGameDirectory(); + SetFirmwareVersion(); } void GMainWindow::OnAlbum() { @@ -4707,13 +4703,42 @@ void GMainWindow::OnOpenControllerMenu() { } void GMainWindow::OnHomeMenu() { + auto result = FirmwareManager::VerifyFirmware(*system.get()); + + switch (result) { + case FirmwareManager::ErrorFirmwareMissing: + QMessageBox::warning(this, tr("No firmware available"), + tr("Please install firmware to use the Home Menu.")); + return; + case FirmwareManager::ErrorFirmwareCorrupted: + QMessageBox::warning(this, tr("Firmware Corrupted"), + tr(FirmwareManager::GetFirmwareCheckString(result))); + return; + case FirmwareManager::ErrorFirmwareTooNew: { + if (!UISettings::values.show_fw_warning.GetValue()) break; + + QMessageBox box(QMessageBox::Warning, + tr("Firmware Too New"), + tr(FirmwareManager::GetFirmwareCheckString(result)) + tr("\nContinue anyways?"), + QMessageBox::Yes | QMessageBox::No, + this); + + QCheckBox *checkbox = new QCheckBox(tr("Don't show again")); + box.setCheckBox(checkbox); + + int button = box.exec(); + if (checkbox->isChecked()) { + UISettings::values.show_fw_warning.SetValue(false); + } + + if (button == static_cast(QMessageBox::No)) return; + break; + } default: + break; + } + constexpr u64 QLaunchId = static_cast(Service::AM::AppletProgramId::QLaunch); auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); - if (!bis_system) { - QMessageBox::warning(this, tr("No firmware available"), - tr("Please install the firmware to use the Home Menu.")); - return; - } auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); if (!qlaunch_applet_nca) { @@ -5240,19 +5265,6 @@ void GMainWindow::OnCheckFirmwareDecryption() { UpdateMenuState(); } -void GMainWindow::OnCheckFirmware() { - auto result = FirmwareManager::VerifyFirmware(*system.get()); - - switch (result) { - case FirmwareManager::FirmwareGood: - break; - default: - QMessageBox::warning(this, tr("Firmware Read Error"), - tr(FirmwareManager::GetFirmwareCheckString(result))); - break; - } -} - bool GMainWindow::CheckFirmwarePresence() { return FirmwareManager::CheckFirmwarePresence(*system.get()); } diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 8a34a9f075..b1c5669a41 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -424,7 +424,6 @@ private slots: void OnCreateHomeMenuShortcut(GameListShortcutTarget target); void OnCaptureScreenshot(); void OnCheckFirmwareDecryption(); - void OnCheckFirmware(); void OnLanguageChanged(const QString& locale); void OnMouseActivity(); bool OnShutdownBegin(); diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index 85de0ae72d..3322b31ca3 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -212,6 +212,9 @@ struct Values { // Play time Setting show_play_time{linkage, true, "show_play_time", Category::UiGameList}; + // misc + Setting show_fw_warning{linkage, true, "show_fw_warning", Category::Miscellaneous}; + bool configuration_applied; bool reset_to_defaults; bool shortcut_already_warned{false}; From 7ca197d90084406b07fe3b9b1b65780a6c7147ff Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 30 Aug 2025 23:08:04 +0200 Subject: [PATCH 06/11] [qt, compat] fix freedesktop stuffs on Solaris/OpenBSD (#360) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/360 Reviewed-by: crueter Co-authored-by: lizzie Co-committed-by: lizzie --- src/yuzu/main.cpp | 72 ++++++++++++++++++++---------------------- src/yuzu/util/util.cpp | 5 ++- 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index a080132958..7600b8b5da 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -3091,34 +3091,7 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::filesystem::path& command, const std::string& arguments, const std::string& categories, const std::string& keywords, const std::string& name) try { -#if defined(__linux__) || defined(__FreeBSD__) // Linux and FreeBSD - std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop"); - std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); - if (!shortcut_stream.is_open()) { - LOG_ERROR(Frontend, "Failed to create shortcut"); - return false; - } - // TODO: Migrate fmt::print to std::print in futures STD C++ 23. - fmt::print(shortcut_stream, "[Desktop Entry]\n"); - fmt::print(shortcut_stream, "Type=Application\n"); - fmt::print(shortcut_stream, "Version=1.0\n"); - fmt::print(shortcut_stream, "Name={}\n", name); - if (!comment.empty()) { - fmt::print(shortcut_stream, "Comment={}\n", comment); - } - if (std::filesystem::is_regular_file(icon_path)) { - fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); - } - fmt::print(shortcut_stream, "TryExec={}\n", command.string()); - fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments); - if (!categories.empty()) { - fmt::print(shortcut_stream, "Categories={}\n", categories); - } - if (!keywords.empty()) { - fmt::print(shortcut_stream, "Keywords={}\n", keywords); - } - return true; -#elif defined(_WIN32) // Windows +#ifdef _WIN32 // Windows HRESULT hr = CoInitialize(nullptr); if (FAILED(hr)) { LOG_ERROR(Frontend, "CoInitialize failed"); @@ -3180,7 +3153,34 @@ bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, return false; } return true; -#else // Unsupported platform +#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) // Any desktop NIX + std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop"); + std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); + if (!shortcut_stream.is_open()) { + LOG_ERROR(Frontend, "Failed to create shortcut"); + return false; + } + // TODO: Migrate fmt::print to std::print in futures STD C++ 23. + fmt::print(shortcut_stream, "[Desktop Entry]\n"); + fmt::print(shortcut_stream, "Type=Application\n"); + fmt::print(shortcut_stream, "Version=1.0\n"); + fmt::print(shortcut_stream, "Name={}\n", name); + if (!comment.empty()) { + fmt::print(shortcut_stream, "Comment={}\n", comment); + } + if (std::filesystem::is_regular_file(icon_path)) { + fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); + } + fmt::print(shortcut_stream, "TryExec={}\n", command.string()); + fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments); + if (!categories.empty()) { + fmt::print(shortcut_stream, "Categories={}\n", categories); + } + if (!keywords.empty()) { + fmt::print(shortcut_stream, "Keywords={}\n", keywords); + } + return true; +#else // Unsupported platform return false; #endif } catch (const std::exception& e) { @@ -3225,7 +3225,7 @@ bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_vi #if defined(_WIN32) out_icon_path = Common::FS::GetEdenPath(Common::FS::EdenPath::IconsDir); ico_extension = "ico"; -#elif defined(__linux__) || defined(__FreeBSD__) +#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; #endif // Create icons directory if it doesn't exist @@ -4878,7 +4878,7 @@ void GMainWindow::CreateShortcut(const std::string& game_path, const u64 program } } -#if defined(__linux__) +#if defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) // Special case for AppImages // Warn once if we are making a shortcut to a volatile AppImage if (command.string().ends_with(".AppImage") && !UISettings::values.shortcut_already_warned) { @@ -4888,7 +4888,7 @@ void GMainWindow::CreateShortcut(const std::string& game_path, const u64 program } UISettings::values.shortcut_already_warned = true; } -#endif // __linux__ +#endif // Create shortcut std::string arguments{arguments_}; @@ -5742,17 +5742,13 @@ int main(int argc, char* argv[]) { #ifdef _WIN32 // Increases the maximum open file limit to 8192 _setmaxstdio(8192); -#endif - -#ifdef __APPLE__ +#elif defined(__APPLE__) // If you start a bundle (binary) on OSX without the Terminal, the working directory is "/". // But since we require the working directory to be the executable path for the location of // the user folder in the Qt Frontend, we need to cd into that working directory const auto bin_path = Common::FS::GetBundleDirectory() / ".."; chdir(Common::FS::PathToUTF8String(bin_path).c_str()); -#endif - -#ifdef __linux__ +#elif defined(__unix__) && !defined(__ANDROID__) // Set the DISPLAY variable in order to open web browsers // TODO (lat9nq): Find a better solution for AppImages to start external applications if (QString::fromLocal8Bit(qgetenv("DISPLAY")).isEmpty()) { diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index e22cf84bf1..551df7b4cd 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2015 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -138,7 +141,7 @@ bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image) icon_file.Close(); return true; -#elif defined(__linux__) || defined(__FreeBSD__) +#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) // Convert and write the icon as a PNG if (!image.save(QString::fromStdString(icon_path.string()))) { LOG_ERROR(Frontend, "Could not write icon as PNG to file"); From 1c3ca17cfb0beaf4696598115ca0c80473a929d0 Mon Sep 17 00:00:00 2001 From: crueter Date: Sun, 31 Aug 2025 00:12:06 +0200 Subject: [PATCH 07/11] [dynarmic] fix annoying gcc/clang error (#365) caused qt creator to crash somehow geg Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/365 Reviewed-by: Lizzie Reviewed-by: MaranBr --- .../src/dynarmic/common/lut_from_list.h | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/dynarmic/src/dynarmic/common/lut_from_list.h b/src/dynarmic/src/dynarmic/common/lut_from_list.h index ed9e3dc046..c904e2c041 100644 --- a/src/dynarmic/src/dynarmic/common/lut_from_list.h +++ b/src/dynarmic/src/dynarmic/common/lut_from_list.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -19,6 +22,16 @@ namespace Dynarmic::Common { +// prevents this function from printing 56,000 character warning messages +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wno-stack-usage" +#endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wno-stack-usage" +#endif + template inline auto GenerateLookupTableFromList(Function f, mcl::mp::list) { #ifdef _MSC_VER @@ -34,4 +47,11 @@ inline auto GenerateLookupTableFromList(Function f, mcl::mp::list) { return MapT(pair_array.begin(), pair_array.end()); } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } // namespace Dynarmic::Common From 21c77bdcac2390c6b15091296786a9239c6ca529 Mon Sep 17 00:00:00 2001 From: crueter Date: Sun, 31 Aug 2025 03:10:34 +0200 Subject: [PATCH 08/11] [cmake] fix ffmpeg libdrm on macos (#367) Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/367 Reviewed-by: Shinmegumi Reviewed-by: Lizzie --- externals/ffmpeg/CMakeLists.txt | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt index 54c852f831..ff35c8dc2c 100644 --- a/externals/ffmpeg/CMakeLists.txt +++ b/externals/ffmpeg/CMakeLists.txt @@ -63,20 +63,22 @@ if (NOT WIN32 AND NOT ANDROID) set(FFmpeg_HWACCEL_INCLUDE_DIRS) set(FFmpeg_HWACCEL_LDFLAGS) - # In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so - if(PLATFORM_SUN) - list(APPEND FFmpeg_HWACCEL_LIBRARIES - X11 - "/usr/lib/xorg/amd64/libdrm.so") - else() - pkg_check_modules(LIBDRM libdrm REQUIRED) - list(APPEND FFmpeg_HWACCEL_LIBRARIES - ${LIBDRM_LIBRARIES}) - list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS - ${LIBDRM_INCLUDE_DIRS}) + if (NOT APPLE) + # In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so + if(PLATFORM_SUN) + list(APPEND FFmpeg_HWACCEL_LIBRARIES + X11 + "/usr/lib/xorg/amd64/libdrm.so") + else() + pkg_check_modules(LIBDRM libdrm REQUIRED) + list(APPEND FFmpeg_HWACCEL_LIBRARIES + ${LIBDRM_LIBRARIES}) + list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS + ${LIBDRM_INCLUDE_DIRS}) + endif() + list(APPEND FFmpeg_HWACCEL_FLAGS + --enable-libdrm) endif() - list(APPEND FFmpeg_HWACCEL_FLAGS - --enable-libdrm) if(LIBVA_FOUND) find_package(X11 REQUIRED) From 39e27bc954dd16d296266eaa08ea613e8e5da38d Mon Sep 17 00:00:00 2001 From: Producdevity Date: Sun, 31 Aug 2025 03:33:54 +0200 Subject: [PATCH 09/11] [android] fix intent-auto-driver-install (#369) Resolving drivers based on the artifact name was too buggy and inconsistent, this PR improves it. Well, I like to think it does Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/369 Reviewed-by: crueter Reviewed-by: Lizzie Co-authored-by: Producdevity Co-committed-by: Producdevity --- .../yuzu_emu/utils/CustomSettingsHandler.kt | 27 ++++-- .../org/yuzu/yuzu_emu/utils/DriverResolver.kt | 94 +++++++++++++++++-- 2 files changed, 102 insertions(+), 19 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/CustomSettingsHandler.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/CustomSettingsHandler.kt index a317be14d5..377313d0aa 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/CustomSettingsHandler.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/CustomSettingsHandler.kt @@ -124,11 +124,16 @@ object CustomSettingsHandler { // Check for driver requirements if activity and driverViewModel are provided if (activity != null && driverViewModel != null) { - val driverPath = extractDriverPath(customSettings) - if (driverPath != null) { - Log.info("[CustomSettingsHandler] Custom settings specify driver: $driverPath") + val rawDriverPath = extractDriverPath(customSettings) + if (rawDriverPath != null) { + // Normalize to local storage path (we only store drivers under driverStoragePath) + val driverFilename = rawDriverPath.substringAfterLast('/') + .substringAfterLast('\\') + val localDriverPath = "${GpuDriverHelper.driverStoragePath}$driverFilename" + Log.info("[CustomSettingsHandler] Custom settings specify driver: $rawDriverPath (normalized: $localDriverPath)") + // Check if driver exists in the driver storage - val driverFile = File(driverPath) + val driverFile = File(localDriverPath) if (!driverFile.exists()) { Log.info("[CustomSettingsHandler] Driver not found locally: ${driverFile.name}") @@ -182,7 +187,7 @@ object CustomSettingsHandler { } // Attempt to download and install the driver - val driverUri = DriverResolver.ensureDriverAvailable(driverPath, activity) { progress -> + val driverUri = DriverResolver.ensureDriverAvailable(driverFilename, activity) { progress -> progressChannel.trySend(progress.toInt()) } @@ -209,12 +214,12 @@ object CustomSettingsHandler { return null } - // Verify the downloaded driver - val installedFile = File(driverPath) + // Verify the downloaded driver (from normalized local path) + val installedFile = File(localDriverPath) val metadata = GpuDriverHelper.getMetadataFromZip(installedFile) if (metadata.name == null) { Log.error( - "[CustomSettingsHandler] Downloaded driver is invalid: $driverPath" + "[CustomSettingsHandler] Downloaded driver is invalid: $localDriverPath" ) Toast.makeText( activity, @@ -232,7 +237,7 @@ object CustomSettingsHandler { } // Add to driver list - driverViewModel.onDriverAdded(Pair(driverPath, metadata)) + driverViewModel.onDriverAdded(Pair(localDriverPath, metadata)) Log.info( "[CustomSettingsHandler] Successfully downloaded and installed driver: ${metadata.name}" ) @@ -268,7 +273,7 @@ object CustomSettingsHandler { // Driver exists, verify it's valid val metadata = GpuDriverHelper.getMetadataFromZip(driverFile) if (metadata.name == null) { - Log.error("[CustomSettingsHandler] Invalid driver file: $driverPath") + Log.error("[CustomSettingsHandler] Invalid driver file: $localDriverPath") Toast.makeText( activity, activity.getString( @@ -459,6 +464,8 @@ object CustomSettingsHandler { if (inGpuDriverSection && trimmed.startsWith("driver_path=")) { return trimmed.substringAfter("driver_path=") + .trim() + .removeSurrounding("\"", "\"") } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DriverResolver.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DriverResolver.kt index 74f98ccbd2..2072344bdf 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DriverResolver.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DriverResolver.kt @@ -68,6 +68,48 @@ object DriverResolver { val filename: String ) + // Matching helpers + private val KNOWN_SUFFIXES = listOf( + ".adpkg.zip", + ".zip", + ".7z", + ".tar.gz", + ".tar.xz", + ".rar" + ) + + private fun stripKnownSuffixes(name: String): String { + var result = name + var changed: Boolean + do { + changed = false + for (s in KNOWN_SUFFIXES) { + if (result.endsWith(s, ignoreCase = true)) { + result = result.dropLast(s.length) + changed = true + } + } + } while (changed) + return result + } + + private fun normalizeName(name: String): String { + val base = stripKnownSuffixes(name.lowercase()) + // Remove non-alphanumerics to make substring checks resilient + return base.replace(Regex("[^a-z0-9]+"), " ").trim() + } + + private fun tokenize(name: String): Set = + normalizeName(name).split(Regex("\\s+")).filter { it.isNotBlank() }.toSet() + + // Jaccard similarity between two sets + private fun jaccard(a: Set, b: Set): Double { + if (a.isEmpty() || b.isEmpty()) return 0.0 + val inter = a.intersect(b).size.toDouble() + val uni = a.union(b).size.toDouble() + return if (uni == 0.0) 0.0 else inter / uni + } + /** * Resolve a driver download URL from its filename * @param filename The driver filename (e.g., "turnip_mrpurple-T19-toasted.adpkg.zip") @@ -98,7 +140,7 @@ object DriverResolver { async { searchRepository(repoPath, filename) } - }.mapNotNull { it.await() }.firstOrNull().also { resolved -> + }.firstNotNullOfOrNull { it.await() }.also { resolved -> // Cache the result if found resolved?.let { urlCache[filename] = it @@ -119,22 +161,56 @@ object DriverResolver { releaseCache[repoPath] = it } - // Search through all releases and artifacts + // First pass: exact name (case-insensitive) against asset filenames + val target = filename.lowercase() for (release in releases) { for (artifact in release.artifacts) { - if (artifact.name == filename) { - Log.info( - "[DriverResolver] Found $filename in $repoPath/${release.tagName}" - ) + if (artifact.name.equals(filename, ignoreCase = true) || artifact.name.lowercase() == target) { + Log.info("[DriverResolver] Found $filename in $repoPath/${release.tagName}") return@withContext ResolvedDriver( downloadUrl = artifact.url.toString(), repoPath = repoPath, releaseTag = release.tagName, - filename = filename + filename = artifact.name ) } } } + + // Second pass: fuzzy match by asset filenames only + val reqNorm = normalizeName(filename) + val reqTokens = tokenize(filename) + var best: ResolvedDriver? = null + var bestScore = 0.0 + + for (release in releases) { + for (artifact in release.artifacts) { + val artNorm = normalizeName(artifact.name) + val artTokens = tokenize(artifact.name) + + var score = jaccard(reqTokens, artTokens) + // Boost if one normalized name contains the other + if (artNorm.contains(reqNorm) || reqNorm.contains(artNorm)) { + score = maxOf(score, 0.92) + } + + if (score > bestScore) { + bestScore = score + best = ResolvedDriver( + downloadUrl = artifact.url.toString(), + repoPath = repoPath, + releaseTag = release.tagName, + filename = artifact.name + ) + } + } + } + + // Threshold to avoid bad guesses, this worked fine in testing but might need tuning + if (best != null && bestScore >= 0.6) { + Log.info("[DriverResolver] Fuzzy matched $filename -> ${best.filename} in ${best.repoPath} (score=%.2f)".format(bestScore)) + return@withContext best + } null } catch (e: Exception) { Log.error("[DriverResolver] Failed to search $repoPath: ${e.message}") @@ -296,8 +372,8 @@ object DriverResolver { context: Context, onProgress: ((Float) -> Unit)? = null ): Uri? { - // Extract filename from path - val filename = driverPath.substringAfterLast('/') + // Extract filename from path (support both separators) + val filename = driverPath.substringAfterLast('/').substringAfterLast('\\') // Check if driver already exists locally val localPath = "${GpuDriverHelper.driverStoragePath}$filename" From 4b5a8e06219ad0de3d27faac19b7ecb986175bbc Mon Sep 17 00:00:00 2001 From: Guo Yunhe Date: Sun, 31 Aug 2025 04:56:23 +0200 Subject: [PATCH 10/11] [cmake] changed app id from org.eden_emu.eden to dev.eden_emu.eden (#237) it is better to match app id with website domain Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/237 Reviewed-by: crueter Co-authored-by: Guo Yunhe Co-committed-by: Guo Yunhe --- .ci/linux/eden.dwfsprof | 2 +- .ci/linux/package.sh | 8 ++++---- .ci/update-icons.sh | 2 +- CMakeLists.txt | 8 ++++---- ...rg.eden_emu.eden.desktop => dev.eden_emu.eden.desktop} | 2 +- ...u.eden.metainfo.xml => dev.eden_emu.eden.metainfo.xml} | 0 dist/{org.eden_emu.eden.svg => dev.eden_emu.eden.svg} | 0 dist/{org.eden_emu.eden.xml => dev.eden_emu.eden.xml} | 0 src/yuzu/main.cpp | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) rename dist/{org.eden_emu.eden.desktop => dev.eden_emu.eden.desktop} (95%) rename dist/{org.eden_emu.eden.metainfo.xml => dev.eden_emu.eden.metainfo.xml} (100%) rename dist/{org.eden_emu.eden.svg => dev.eden_emu.eden.svg} (100%) rename dist/{org.eden_emu.eden.xml => dev.eden_emu.eden.xml} (100%) diff --git a/.ci/linux/eden.dwfsprof b/.ci/linux/eden.dwfsprof index bc360f0d46..9a3bee6f14 100644 --- a/.ci/linux/eden.dwfsprof +++ b/.ci/linux/eden.dwfsprof @@ -1,6 +1,6 @@ AppRun eden.desktop -org.eden_emu.eden.desktop +dev.eden_emu.eden.desktop shared/bin/eden shared/lib/lib.path shared/lib/ld-linux-x86-64.so.2 diff --git a/.ci/linux/package.sh b/.ci/linux/package.sh index 911fea2f7b..837cfe07ef 100755 --- a/.ci/linux/package.sh +++ b/.ci/linux/package.sh @@ -59,15 +59,15 @@ VERSION="$(echo "$EDEN_TAG")" mkdir -p ./AppDir cd ./AppDir -cp ../dist/org.eden_emu.eden.desktop . -cp ../dist/org.eden_emu.eden.svg . +cp ../dist/dev.eden_emu.eden.desktop . +cp ../dist/dev.eden_emu.eden.svg . -ln -sf ./org.eden_emu.eden.svg ./.DirIcon +ln -sf ./dev.eden_emu.eden.svg ./.DirIcon UPINFO='gh-releases-zsync|eden-emulator|Releases|latest|*.AppImage.zsync' if [ "$DEVEL" = 'true' ]; then - sed -i 's|Name=Eden|Name=Eden Nightly|' ./org.eden_emu.eden.desktop + sed -i 's|Name=Eden|Name=Eden Nightly|' ./dev.eden_emu.eden.desktop UPINFO="$(echo "$UPINFO" | sed 's|Releases|nightly|')" fi diff --git a/.ci/update-icons.sh b/.ci/update-icons.sh index 99adbfae66..4feb2abd24 100755 --- a/.ci/update-icons.sh +++ b/.ci/update-icons.sh @@ -6,7 +6,7 @@ which png2icns || [ which yay && yay libicns ] || exit which magick || exit -export EDEN_SVG_ICO="dist/org.eden_emu.eden.svg" +export EDEN_SVG_ICO="dist/dev.eden_emu.eden.svg" svgo --multipass $EDEN_SVG_ICO magick -density 256x256 -background transparent $EDEN_SVG_ICO \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 55ed83c929..9abca561f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -858,14 +858,14 @@ endif() # https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html # https://www.freedesktop.org/software/appstream/docs/ if(ENABLE_QT AND UNIX AND NOT APPLE) - install(FILES "dist/org.eden_emu.eden.desktop" + install(FILES "dist/dev.eden_emu.eden.desktop" DESTINATION "share/applications") - install(FILES "dist/org.eden_emu.eden.svg" + install(FILES "dist/dev.eden_emu.eden.svg" DESTINATION "share/icons/hicolor/scalable/apps") # TODO: these files need to be updated. - install(FILES "dist/org.eden_emu.eden.xml" + install(FILES "dist/dev.eden_emu.eden.xml" DESTINATION "share/mime/packages") - install(FILES "dist/org.eden_emu.eden.metainfo.xml" + install(FILES "dist/dev.eden_emu.eden.metainfo.xml" DESTINATION "share/metainfo") endif() diff --git a/dist/org.eden_emu.eden.desktop b/dist/dev.eden_emu.eden.desktop similarity index 95% rename from dist/org.eden_emu.eden.desktop rename to dist/dev.eden_emu.eden.desktop index d012ab6d07..5d2d7cd8c5 100644 --- a/dist/org.eden_emu.eden.desktop +++ b/dist/dev.eden_emu.eden.desktop @@ -10,7 +10,7 @@ Type=Application Name=Eden GenericName=Switch Emulator Comment=Nintendo Switch video game console emulator -Icon=org.eden_emu.eden +Icon=dev.eden_emu.eden TryExec=eden Exec=eden %f Categories=Game;Emulator;Qt; diff --git a/dist/org.eden_emu.eden.metainfo.xml b/dist/dev.eden_emu.eden.metainfo.xml similarity index 100% rename from dist/org.eden_emu.eden.metainfo.xml rename to dist/dev.eden_emu.eden.metainfo.xml diff --git a/dist/org.eden_emu.eden.svg b/dist/dev.eden_emu.eden.svg similarity index 100% rename from dist/org.eden_emu.eden.svg rename to dist/dev.eden_emu.eden.svg diff --git a/dist/org.eden_emu.eden.xml b/dist/dev.eden_emu.eden.xml similarity index 100% rename from dist/org.eden_emu.eden.xml rename to dist/dev.eden_emu.eden.xml diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 7600b8b5da..4c6b176c56 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -5757,7 +5757,7 @@ int main(int argc, char* argv[]) { // Fix the Wayland appId. This needs to match the name of the .desktop file without the .desktop // suffix. - QGuiApplication::setDesktopFileName(QStringLiteral("org.eden_emu.eden")); + QGuiApplication::setDesktopFileName(QStringLiteral("dev.eden_emu.eden")); #endif SetHighDPIAttributes(); From 7c19195e490b19ef0902c36e55e8583b00874aee Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 30 Aug 2025 13:43:05 +0000 Subject: [PATCH 11/11] [compat] improve thread naming logic Signed-off-by: lizzie --- src/common/thread.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 34cc1527bf..516a5893ec 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -1,3 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -15,9 +17,8 @@ #else #if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) #include -#else -#include #endif +#include #include #endif #ifndef _WIN32 @@ -90,33 +91,35 @@ void SetCurrentThreadName(const char* name) { #else // !MSVC_VER, so must be POSIX threads // MinGW with the POSIX threading model does not support pthread_setname_np -#if !defined(_WIN32) || defined(_MSC_VER) void SetCurrentThreadName(const char* name) { + // See for reference + // https://gitlab.freedesktop.org/mesa/mesa/-/blame/main/src/util/u_thread.c?ref_type=heads#L75 #ifdef __APPLE__ pthread_setname_np(name); +#elif defined(__HAIKU__) + rename_thread(find_thread(NULL), name); #elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) pthread_set_name_np(pthread_self(), name); #elif defined(__NetBSD__) pthread_setname_np(pthread_self(), "%s", (void*)name); -#elif defined(__linux__) - // Linux limits thread names to 15 characters and will outright reject any - // attempt to set a longer name with ERANGE. - std::string truncated(name, std::min(strlen(name), static_cast(15))); - if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) { - errno = e; - LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg()); +#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun__) || defined(__glibc__) || defined(__managarm__) + int ret = pthread_setname_np(pthread_self(), name); + if (ret == ERANGE) { + // Linux limits thread names to 15 characters and will outright reject any + // attempt to set a longer name with ERANGE. + char buf[16]; + size_t const len = std::min(std::strlen(name), sizeof(buf) - 1); + std::memcpy(buf, name, len); + buf[len] = '\0'; + pthread_setname_np(pthread_self(), buf); } +#elif !defined(_WIN32) || defined(_MSC_VER) + // mingw stub + (void)name; #else pthread_setname_np(pthread_self(), name); #endif } -#endif - -#if defined(_WIN32) -void SetCurrentThreadName(const char* name) { - // Do Nothing on MingW -} -#endif #endif