diff --git a/CMakeLists.txt b/CMakeLists.txt index a9ff2e9458..3599105020 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,7 +224,7 @@ set(YUZU_TZDB_PATH "" CACHE STRING "Path to a pre-downloaded timezone database") cmake_dependent_option(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "LINUX" OFF) -cmake_dependent_option(YUZU_USE_BUNDLED_MOLTENVK "Download bundled MoltenVK lib" ON "APPLE" OFF) +cmake_dependent_option(YUZU_APPLE_USE_BUNDLED_MONTENVK "Download bundled MoltenVK lib" ON "APPLE" OFF) option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF) @@ -319,18 +319,6 @@ if (YUZU_ROOM) add_compile_definitions(YUZU_ROOM) endif() -if (ANDROID OR PLATFORM_FREEBSD OR PLATFORM_OPENBSD OR PLATFORM_SUN OR APPLE) - if(CXX_APPLE OR CXX_CLANG) - # libc++ has stop_token and jthread as experimental - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexperimental-library") - else() - # Uses glibc, mostly? - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LIBCPP_ENABLE_EXPERIMENTAL=1") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LIBCPP_ENABLE_EXPERIMENTAL=1") - endif() -endif() - # Build/optimization presets if (PLATFORM_LINUX OR CXX_CLANG) if (ARCHITECTURE_x86_64) diff --git a/CMakeModules/GenerateSCMRev.cmake b/CMakeModules/GenerateSCMRev.cmake index 1ae608c085..2d7081b7db 100644 --- a/CMakeModules/GenerateSCMRev.cmake +++ b/CMakeModules/GenerateSCMRev.cmake @@ -31,11 +31,7 @@ set(GIT_DESC ${BUILD_VERSION}) set(REPO_NAME "Eden") set(BUILD_ID ${GIT_REFSPEC}) set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ") + set(CXX_COMPILER "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") -# Auto-updater metadata! Must somewhat mirror GitHub API endpoint -set(BUILD_AUTO_UPDATE_WEBSITE "https://github.com") -set(BUILD_AUTO_UPDATE_API "http://api.github.com") -set(BUILD_AUTO_UPDATE_REPO "eden-emulator/Releases") - configure_file(scm_rev.cpp.in scm_rev.cpp @ONLY) diff --git a/docs/Options.md b/docs/Options.md index 3dd84ea645..6af91e4918 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -31,7 +31,7 @@ Notes: * Currently, build fails without this - `YUZU_USE_FASTER_LD` (ON) Check if a faster linker is available * Only available on UNIX -- `YUZU_USE_BUNDLED_MOLTENVK` (ON, macOS only) Download bundled MoltenVK lib) +- `YUZU_APPLE_USE_BUNDLED_MONTENVK` (ON, macOS only) Download bundled MoltenVK lib) - `YUZU_TZDB_PATH` (string) Path to a pre-downloaded timezone database (useful for nixOS) - `ENABLE_OPENSSL` (ON for Linux and *BSD) Enable OpenSSL backend for the ssl service * Always enabled if the web service is enabled diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index e8d8141711..d3a05cf3e2 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -59,7 +59,7 @@ android { defaultConfig { // TODO If this is ever modified, change application_id in strings.xml applicationId = "dev.eden.eden_emulator" - minSdk = 28 + minSdk = 30 targetSdk = 36 versionName = getGitVersion() diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt index 2c35e7349a..8a66ebf11f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/CarouselRecyclerView.kt @@ -19,7 +19,6 @@ import org.yuzu.yuzu_emu.adapters.GameAdapter import androidx.core.view.doOnNextLayout import org.yuzu.yuzu_emu.YuzuApplication import androidx.preference.PreferenceManager -import androidx.core.view.WindowInsetsCompat /** * CarouselRecyclerView encapsulates all carousel logic for the games UI. @@ -206,8 +205,8 @@ class CarouselRecyclerView @JvmOverloads constructor( if (enabled) { useCustomDrawingOrder = true - val insets = rootWindowInsets?.let { WindowInsetsCompat.toWindowInsetsCompat(it, this) } - val bottomInset = insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.bottom ?: 0 + val insets = rootWindowInsets + val bottomInset = insets?.getInsets(android.view.WindowInsets.Type.systemBars())?.bottom ?: 0 val internalFactor = resources.getFraction(R.fraction.carousel_card_size_factor, 1, 1) val userFactor = preferences.getFloat(CAROUSEL_CARD_SIZE_FACTOR, internalFactor).coerceIn( 0f, diff --git a/src/audio_core/renderer/behavior/info_updater.cpp b/src/audio_core/renderer/behavior/info_updater.cpp index 20f6cda3a2..3dae6069f7 100644 --- a/src/audio_core/renderer/behavior/info_updater.cpp +++ b/src/audio_core/renderer/behavior/info_updater.cpp @@ -1,6 +1,3 @@ -// 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-2.0-or-later diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp index 87eab1adda..46b85b8945 100644 --- a/src/audio_core/renderer/command/effect/reverb.cpp +++ b/src/audio_core/renderer/command/effect/reverb.cpp @@ -191,6 +191,8 @@ static void InitializeReverbEffect(const ReverbInfo::ParameterVersion2& params, const auto center_delay_time{(5 * delay).to_uint_floor()}; state.center_delay_line.Initialize(center_delay_time, 1.0f); + UpdateReverbEffectParameter(params, state); + for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) { std::ranges::fill(state.fdn_delay_lines[i].buffer, 0); std::ranges::fill(state.decay_delay_lines[i].buffer, 0); diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index b75d743494..4d7f0c1d5d 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -293,7 +293,8 @@ void SinkStream::WaitFreeSpace(std::stop_token stop_token) { release_cv.wait_for(lk, std::chrono::milliseconds(5), [this]() { return paused || queued_buffers < max_queue_size; }); if (queued_buffers > max_queue_size + 3) { - release_cv.wait(lk, stop_token, [this] { return paused || queued_buffers < max_queue_size; }); + Common::CondvarWait(release_cv, lk, stop_token, + [this] { return paused || queued_buffers < max_queue_size; }); } } diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h index 80f32e2553..b36fc1de96 100644 --- a/src/common/bounded_threadsafe_queue.h +++ b/src/common/bounded_threadsafe_queue.h @@ -1,6 +1,3 @@ -// 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 @@ -126,7 +123,7 @@ private: } else if constexpr (Mode == PopMode::WaitWithStopToken) { // Wait until the queue is not empty. std::unique_lock lock{consumer_cv_mutex}; - consumer_cv.wait(lock, stop_token, [this, read_index] { + Common::CondvarWait(consumer_cv, lock, stop_token, [this, read_index] { return read_index != m_write_index.load(std::memory_order::acquire); }); if (stop_token.stop_requested()) { diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp index 722ba41949..b0b25eb432 100644 --- a/src/common/fs/file.cpp +++ b/src/common/fs/file.cpp @@ -3,7 +3,6 @@ #include -#include "common/assert.h" #include "common/fs/file.h" #include "common/fs/fs.h" #ifdef ANDROID diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index a095e0c239..318f311891 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp @@ -9,7 +9,6 @@ #include #include -#include "common/assert.h" #include "common/fs/fs.h" #ifdef ANDROID #include "common/fs/fs_android.h" diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 3838c12903..2e36d59569 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -56,16 +56,6 @@ #include "common/host_memory.h" #include "common/logging/log.h" -#if defined(__ANDROID__) && __ANDROID_API__ < 30 -#include -#ifndef MFD_CLOEXEC -#define MFD_CLOEXEC 0x0001U -#endif -static int memfd_create(const char* name, unsigned int flags) { - return syscall(__NR_memfd_create, name, flags); -} -#endif - namespace Common { constexpr size_t PageAlignment = 0x1000; diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index c2cbf3f4a5..4621771090 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -39,17 +39,9 @@ namespace Common::Log { namespace { -/// @brief Trims up to and including the last of ../, ..\, src/, src\ in a string -/// do not be fooled this isn't generating new strings on .rodata :) -constexpr const char* TrimSourcePath(std::string_view source) { - const auto rfind = [source](const std::string_view match) { - return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size()); - }; - auto idx = (std::max)({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")}); - return source.data() + idx; -} - -/// @brief Interface for logging backends. +/** + * Interface for logging backends. + */ class Backend { public: virtual ~Backend() = default; @@ -61,7 +53,9 @@ public: virtual void Flush() = 0; }; -/// @brief Backend that writes to stderr and with color +/** + * Backend that writes to stderr and with color + */ class ColorConsoleBackend final : public Backend { public: explicit ColorConsoleBackend() = default; @@ -90,7 +84,9 @@ private: std::atomic_bool enabled{false}; }; -/// @brief Backend that writes to a file passed into the constructor +/** + * Backend that writes to a file passed into the constructor + */ class FileBackend final : public Backend { public: explicit FileBackend(const std::filesystem::path& filename) { @@ -252,14 +248,13 @@ public: color_console_backend.SetEnabled(enabled); } - bool CanPushEntry(Class log_class, Level log_level) const noexcept { - return filter.CheckMessage(log_class, log_level); - } - void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, - const char* function, std::string&& message) noexcept { + const char* function, std::string&& message) { + if (!filter.CheckMessage(log_class, log_level)) { + return; + } message_queue.EmplaceWait( - CreateEntry(log_class, log_level, TrimSourcePath(filename), line_num, function, std::move(message))); + CreateEntry(log_class, log_level, filename, line_num, function, std::move(message))); } private: @@ -373,9 +368,8 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) { if (!initialization_in_progress_suppress_logging) { - auto& instance = Impl::Instance(); - if (instance.CanPushEntry(log_class, log_level)) - instance.PushEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); + Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, + fmt::vformat(format, args)); } } } // namespace Common::Log diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 813e812780..4e3a614a45 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -12,20 +9,22 @@ namespace Common::Log { namespace { template Level GetLevelByName(const It begin, const It end) { - for (u32 i = 0; i < u32(Level::Count); ++i) { - const char* level_name = GetLevelName(Level(i)); - if (Common::ComparePartialString(begin, end, level_name)) - return Level(i); + for (u8 i = 0; i < static_cast(Level::Count); ++i) { + const char* level_name = GetLevelName(static_cast(i)); + if (Common::ComparePartialString(begin, end, level_name)) { + return static_cast(i); + } } return Level::Count; } template Class GetClassByName(const It begin, const It end) { - for (u32 i = 0; i < u32(Class::Count); ++i) { - const char* level_name = GetLogClassName(Class(i)); - if (Common::ComparePartialString(begin, end, level_name)) - return Class(i); + for (u8 i = 0; i < static_cast(Class::Count); ++i) { + const char* level_name = GetLogClassName(static_cast(i)); + if (Common::ComparePartialString(begin, end, level_name)) { + return static_cast(i); + } } return Class::Count; } @@ -230,12 +229,13 @@ void Filter::ParseFilterString(std::string_view filter_view) { } bool Filter::CheckMessage(Class log_class, Level level) const { - return u8(level) >= u8(class_levels[std::size_t(log_class)]); + return static_cast(level) >= + static_cast(class_levels[static_cast(log_class)]); } bool Filter::IsDebug() const { return std::any_of(class_levels.begin(), class_levels.end(), [](const Level& l) { - return u8(l) <= u8(Level::Debug); + return static_cast(l) <= static_cast(Level::Debug); }); } diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 7b23b59aab..bd7a7d7f49 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -16,6 +16,15 @@ namespace Common::Log { +// trims up to and including the last of ../, ..\, src/, src\ in a string +constexpr const char* TrimSourcePath(std::string_view source) { + const auto rfind = [source](const std::string_view match) { + return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size()); + }; + auto idx = (std::max)({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")}); + return source.data() + idx; +} + /// Logs a message to the global logger, using fmt void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, unsigned int line_num, const char* function, fmt::string_view format, @@ -33,7 +42,7 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig #ifdef _DEBUG #define LOG_TRACE(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Trace, \ - __FILE__, __LINE__, __func__, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ __VA_ARGS__) #else #define LOG_TRACE(log_class, fmt, ...) (void(0)) @@ -41,21 +50,21 @@ void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsig #define LOG_DEBUG(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \ - __FILE__, __LINE__, __func__, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ __VA_ARGS__) #define LOG_INFO(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \ - __FILE__, __LINE__, __func__, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ __VA_ARGS__) #define LOG_WARNING(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \ - __FILE__, __LINE__, __func__, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ __VA_ARGS__) #define LOG_ERROR(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \ - __FILE__, __LINE__, __func__, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ __VA_ARGS__) #define LOG_CRITICAL(log_class, ...) \ Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \ - __FILE__, __LINE__, __func__, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ __VA_ARGS__) diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h index 0d3c963d25..12e59a8939 100644 --- a/src/common/polyfill_thread.h +++ b/src/common/polyfill_thread.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,13 +7,23 @@ #pragma once +#include + +#ifdef __cpp_lib_jthread + #include #include +#include #include #include namespace Common { +template +void CondvarWait(Condvar& cv, std::unique_lock& lk, std::stop_token token, Pred&& pred) { + cv.wait(lk, token, std::forward(pred)); +} + template bool StoppableTimedWait(std::stop_token token, const std::chrono::duration& rel_time) { std::condition_variable_any cv; @@ -28,3 +35,341 @@ bool StoppableTimedWait(std::stop_token token, const std::chrono::duration +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace std { +namespace polyfill { + +using stop_state_callback = size_t; + +class stop_state { +public: + stop_state() = default; + ~stop_state() = default; + + bool request_stop() { + unique_lock lk{m_lock}; + + if (m_stop_requested) { + // Already set, nothing to do. + return false; + } + + // Mark stop requested. + m_stop_requested = true; + + while (!m_callbacks.empty()) { + // Get an iterator to the first element. + const auto it = m_callbacks.begin(); + + // Move the callback function out of the map. + function f; + swap(it->second, f); + + // Erase the now-empty map element. + m_callbacks.erase(it); + + // Run the callback. + if (f) { + f(); + } + } + + return true; + } + + bool stop_requested() const { + unique_lock lk{m_lock}; + return m_stop_requested; + } + + stop_state_callback insert_callback(function f) { + unique_lock lk{m_lock}; + + if (m_stop_requested) { + // Stop already requested. Don't insert anything, + // just run the callback synchronously. + if (f) { + f(); + } + return 0; + } + + // Insert the callback. + stop_state_callback ret = ++m_next_callback; + m_callbacks.emplace(ret, std::move(f)); + return ret; + } + + void remove_callback(stop_state_callback cb) { + unique_lock lk{m_lock}; + m_callbacks.erase(cb); + } + +private: + mutable recursive_mutex m_lock; + map> m_callbacks; + stop_state_callback m_next_callback{0}; + bool m_stop_requested{false}; +}; + +} // namespace polyfill + +class stop_token; +class stop_source; +struct nostopstate_t { + explicit nostopstate_t() = default; +}; +inline constexpr nostopstate_t nostopstate{}; + +template +class stop_callback; + +class stop_token { +public: + stop_token() noexcept = default; + + stop_token(const stop_token&) noexcept = default; + stop_token(stop_token&&) noexcept = default; + stop_token& operator=(const stop_token&) noexcept = default; + stop_token& operator=(stop_token&&) noexcept = default; + ~stop_token() = default; + + void swap(stop_token& other) noexcept { + m_stop_state.swap(other.m_stop_state); + } + + [[nodiscard]] bool stop_requested() const noexcept { + return m_stop_state && m_stop_state->stop_requested(); + } + [[nodiscard]] bool stop_possible() const noexcept { + return m_stop_state != nullptr; + } + +private: + friend class stop_source; + template + friend class stop_callback; + stop_token(shared_ptr stop_state) : m_stop_state(std::move(stop_state)) {} + +private: + shared_ptr m_stop_state; +}; + +class stop_source { +public: + stop_source() : m_stop_state(make_shared()) {} + explicit stop_source(nostopstate_t) noexcept {} + + stop_source(const stop_source&) noexcept = default; + stop_source(stop_source&&) noexcept = default; + stop_source& operator=(const stop_source&) noexcept = default; + stop_source& operator=(stop_source&&) noexcept = default; + ~stop_source() = default; + void swap(stop_source& other) noexcept { + m_stop_state.swap(other.m_stop_state); + } + + [[nodiscard]] stop_token get_token() const noexcept { + return stop_token(m_stop_state); + } + [[nodiscard]] bool stop_possible() const noexcept { + return m_stop_state != nullptr; + } + [[nodiscard]] bool stop_requested() const noexcept { + return m_stop_state && m_stop_state->stop_requested(); + } + bool request_stop() noexcept { + return m_stop_state && m_stop_state->request_stop(); + } + +private: + friend class jthread; + explicit stop_source(shared_ptr stop_state) + : m_stop_state(std::move(stop_state)) {} + +private: + shared_ptr m_stop_state; +}; + +template +class stop_callback { + static_assert(is_nothrow_destructible_v); + static_assert(is_invocable_v); + +public: + using callback_type = Callback; + + template + requires constructible_from + explicit stop_callback(const stop_token& st, + C&& cb) noexcept(is_nothrow_constructible_v) + : m_stop_state(st.m_stop_state) { + if (m_stop_state) { + m_callback = m_stop_state->insert_callback(std::move(cb)); + } + } + template + requires constructible_from + explicit stop_callback(stop_token&& st, + C&& cb) noexcept(is_nothrow_constructible_v) + : m_stop_state(std::move(st.m_stop_state)) { + if (m_stop_state) { + m_callback = m_stop_state->insert_callback(std::move(cb)); + } + } + ~stop_callback() { + if (m_stop_state && m_callback) { + m_stop_state->remove_callback(m_callback); + } + } + + stop_callback(const stop_callback&) = delete; + stop_callback(stop_callback&&) = delete; + stop_callback& operator=(const stop_callback&) = delete; + stop_callback& operator=(stop_callback&&) = delete; + +private: + shared_ptr m_stop_state; + polyfill::stop_state_callback m_callback; +}; + +template +stop_callback(stop_token, Callback) -> stop_callback; + +class jthread { +public: + using id = thread::id; + using native_handle_type = thread::native_handle_type; + + jthread() noexcept = default; + + template , jthread>>> + explicit jthread(F&& f, Args&&... args) + : m_stop_state(make_shared()), + m_thread(make_thread(std::forward(f), std::forward(args)...)) {} + + ~jthread() { + if (joinable()) { + request_stop(); + join(); + } + } + + jthread(const jthread&) = delete; + jthread(jthread&&) noexcept = default; + jthread& operator=(const jthread&) = delete; + + jthread& operator=(jthread&& other) noexcept { + m_thread.swap(other.m_thread); + m_stop_state.swap(other.m_stop_state); + return *this; + } + + void swap(jthread& other) noexcept { + m_thread.swap(other.m_thread); + m_stop_state.swap(other.m_stop_state); + } + [[nodiscard]] bool joinable() const noexcept { + return m_thread.joinable(); + } + void join() { + m_thread.join(); + } + void detach() { + m_thread.detach(); + m_stop_state.reset(); + } + + [[nodiscard]] id get_id() const noexcept { + return m_thread.get_id(); + } + [[nodiscard]] native_handle_type native_handle() { + return m_thread.native_handle(); + } + [[nodiscard]] stop_source get_stop_source() noexcept { + return stop_source(m_stop_state); + } + [[nodiscard]] stop_token get_stop_token() const noexcept { + return stop_source(m_stop_state).get_token(); + } + bool request_stop() noexcept { + return get_stop_source().request_stop(); + } + [[nodiscard]] static unsigned int hardware_concurrency() noexcept { + return thread::hardware_concurrency(); + } + +private: + template + thread make_thread(F&& f, Args&&... args) { + if constexpr (is_invocable_v, stop_token, decay_t...>) { + return thread(std::forward(f), get_stop_token(), std::forward(args)...); + } else { + return thread(std::forward(f), std::forward(args)...); + } + } + + shared_ptr m_stop_state; + thread m_thread; +}; + +} // namespace std + +namespace Common { + +template +void CondvarWait(Condvar& cv, std::unique_lock& lk, std::stop_token token, Pred pred) { + if (token.stop_requested()) { + return; + } + + std::stop_callback callback(token, [&] { + { std::scoped_lock lk2{*lk.mutex()}; } + cv.notify_all(); + }); + + cv.wait(lk, [&] { return pred() || token.stop_requested(); }); +} + +template +bool StoppableTimedWait(std::stop_token token, const std::chrono::duration& rel_time) { + if (token.stop_requested()) { + return false; + } + + bool stop_requested = false; + std::condition_variable cv; + std::mutex m; + + std::stop_callback cb(token, [&] { + // Wake up the waiting thread. + { + std::scoped_lock lk{m}; + stop_requested = true; + } + cv.notify_one(); + }); + + // Perform the timed wait. + std::unique_lock lk{m}; + return !cv.wait_for(lk, rel_time, [&] { return stop_requested; }); +} + +} // namespace Common + +#endif diff --git a/src/common/scm_rev.cpp.in b/src/common/scm_rev.cpp.in index 60c9c119f9..1630ceae83 100644 --- a/src/common/scm_rev.cpp.in +++ b/src/common/scm_rev.cpp.in @@ -18,9 +18,6 @@ #define TITLE_BAR_FORMAT_RUNNING "@TITLE_BAR_FORMAT_RUNNING@" #define IS_DEV_BUILD @IS_DEV_BUILD@ #define COMPILER_ID "@CXX_COMPILER@" -#define BUILD_AUTO_UPDATE_WEBSITE "@BUILD_AUTO_UPDATE_WEBSITE@" -#define BUILD_AUTO_UPDATE_API "@BUILD_AUTO_UPDATE_API@" -#define BUILD_AUTO_UPDATE_REPO "@BUILD_AUTO_UPDATE_REPO@" namespace Common { @@ -37,8 +34,4 @@ constexpr const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING; constexpr const char g_compiler_id[] = COMPILER_ID; constexpr const bool g_is_dev_build = IS_DEV_BUILD; -constexpr const char g_build_auto_update_website[] = BUILD_AUTO_UPDATE_WEBSITE; -constexpr const char g_build_auto_update_api[] = BUILD_AUTO_UPDATE_API; -constexpr const char g_build_auto_update_repo[] = BUILD_AUTO_UPDATE_REPO; - } // namespace Common diff --git a/src/common/scm_rev.h b/src/common/scm_rev.h index b89de95a3d..8f48241557 100644 --- a/src/common/scm_rev.h +++ b/src/common/scm_rev.h @@ -21,8 +21,5 @@ extern const char g_title_bar_format_running[]; extern const char g_shader_cache_version[]; extern const char g_compiler_id[]; extern const bool g_is_dev_build; -extern const char g_build_auto_update_website[]; -extern const char g_build_auto_update_api[]; -extern const char g_build_auto_update_repo[]; } // namespace Common diff --git a/src/common/thread.h b/src/common/thread.h index 5ab495baaa..c6976fb6cd 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -1,6 +1,3 @@ -// 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 @@ -83,7 +80,7 @@ public: condvar.notify_all(); return true; } else { - condvar.wait(lk, token, + CondvarWait(condvar, lk, token, [this, current_generation] { return current_generation != generation; }); return !token.stop_requested(); } diff --git a/src/common/thread_worker.h b/src/common/thread_worker.h index 6ec9d6a2bd..260ad44e45 100644 --- a/src/common/thread_worker.h +++ b/src/common/thread_worker.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -50,8 +47,8 @@ public: if (requests.empty()) { wait_condition.notify_all(); } - condition.wait(lock, stop_token, - [this] { return !requests.empty(); }); + Common::CondvarWait(condition, lock, stop_token, + [this] { return !requests.empty(); }); if (stop_token.stop_requested()) { break; } diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h index f9fc0ca171..2ef1da0644 100644 --- a/src/common/threadsafe_queue.h +++ b/src/common/threadsafe_queue.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2010 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -102,11 +99,7 @@ public: T PopWait(std::stop_token stop_token) { if (Empty()) { std::unique_lock lock{cv_mutex}; - if constexpr (with_stop_token) { - cv.wait(lock, stop_token, [this] { return !Empty(); }); - } else { - cv.wait(lock, [this] { return !Empty(); }); - } + Common::CondvarWait(cv, lock, stop_token, [this] { return !Empty(); }); } if (stop_token.stop_requested()) { return T{}; diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 4e3313f83c..edd25644ac 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -38,6 +38,9 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca) reader = std::make_shared(); if (Result rc = reader->Initialize(file, GetCryptoConfiguration(), GetNcaCompressionConfiguration()); R_FAILED(rc)) { + if (rc != ResultInvalidNcaSignature) { + LOG_ERROR(Loader, "File reader errored out during header read: {:#x}", rc.GetInnerValue()); + } status = Loader::ResultStatus::ErrorBadNCAHeader; return; } @@ -82,6 +85,7 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca) for (s32 i = 0; i < fs_count; i++) { NcaFsHeaderReader header_reader; if (Result rc = fs.OpenStorage(&filesystems[i], &header_reader, i); R_FAILED(rc)) { + LOG_DEBUG(Loader, "File reader errored out during read of section {}: {:#x}", i, rc.GetInnerValue()); status = Loader::ResultStatus::ErrorBadNCAHeader; return; } diff --git a/src/core/file_sys/fssystem/fs_types.h b/src/core/file_sys/fssystem/fs_types.h index f11b7f1dae..43aeaf447b 100644 --- a/src/core/file_sys/fssystem/fs_types.h +++ b/src/core/file_sys/fssystem/fs_types.h @@ -1,6 +1,3 @@ -// 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 diff --git a/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp b/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp index d496d58cec..25036b02c1 100644 --- a/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp +++ b/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp @@ -1049,11 +1049,13 @@ Result NcaFileSystemDriver::CreatePatchMetaStorage( ASSERT(out_aes_ctr_ex_meta != nullptr); ASSERT(out_indirect_meta != nullptr); ASSERT(base_storage != nullptr); + //ASSERT(patch_info.HasAesCtrExTable()); + //ASSERT(patch_info.HasIndirectTable()); ASSERT(Common::IsAligned(patch_info.aes_ctr_ex_size, NcaHeader::XtsBlockSize)); // Validate patch info extents. - R_UNLESS(patch_info.aes_ctr_ex_size >= 0 && patch_info.HasAesCtrExTable(), ResultInvalidNcaPatchInfoAesCtrExSize); - R_UNLESS(patch_info.indirect_size > 0 && patch_info.HasIndirectTable(), ResultInvalidNcaPatchInfoIndirectSize); + R_UNLESS(patch_info.indirect_size > 0, ResultInvalidNcaPatchInfoIndirectSize); + R_UNLESS(patch_info.aes_ctr_ex_size >= 0, ResultInvalidNcaPatchInfoAesCtrExSize); R_UNLESS(patch_info.indirect_size + patch_info.indirect_offset <= patch_info.aes_ctr_ex_offset, ResultInvalidNcaPatchInfoAesCtrExOffset); R_UNLESS(patch_info.aes_ctr_ex_offset + patch_info.aes_ctr_ex_size <= @@ -1331,30 +1333,10 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl( R_UNLESS(last_layer_info_offset + layer_info.size <= layer_info_offset, ResultRomNcaInvalidIntegrityLayerInfoOffset); } - - switch (level_hash_info.max_layers - 1) { - case FileSys::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation::MasterStorage: - storage_info.SetMasterHashStorage(std::make_shared(std::move(base_storage), layer_info.size, last_layer_info_offset)); - break; - case FileSys::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation::Layer1Storage: - storage_info.SetLayer1HashStorage(std::make_shared(std::move(base_storage), layer_info.size, last_layer_info_offset)); - break; - case FileSys::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation::Layer2Storage: - storage_info.SetLayer2HashStorage(std::make_shared(std::move(base_storage), layer_info.size, last_layer_info_offset)); - break; - case FileSys::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation::Layer3Storage: - storage_info.SetLayer3HashStorage(std::make_shared(std::move(base_storage), layer_info.size, last_layer_info_offset)); - break; - case FileSys::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation::Layer4Storage: - storage_info.SetLayer4HashStorage(std::make_shared(std::move(base_storage), layer_info.size, last_layer_info_offset)); - break; - case FileSys::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation::Layer5Storage: - storage_info.SetLayer5HashStorage(std::make_shared(std::move(base_storage), layer_info.size, last_layer_info_offset)); - break; - case FileSys::HierarchicalIntegrityVerificationStorage::HierarchicalStorageInformation::DataStorage: - storage_info.SetDataStorage(std::make_shared(std::move(base_storage), layer_info.size, last_layer_info_offset)); - break; - } + storage_info[level_hash_info.max_layers - 1] + = std::make_shared(std::move(base_storage), + layer_info.size, + last_layer_info_offset); // Make the integrity romfs storage. auto integrity_storage = std::make_shared(); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index f7d6c33f77..de4197c52d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -135,8 +135,8 @@ NvResult nvhost_nvdec_common::GetSyncpoint(IoctlGetSyncpoint& params) { } NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) { - LOG_DEBUG(Service_NVDRV, "called WAITBASE"); - params.value = 0; + LOG_CRITICAL(Service_NVDRV, "called WAITBASE"); + params.value = 0; // Seems to be hard coded at 0 return NvResult::Success; } diff --git a/src/core/hle/service/ssl/ssl_backend_openssl.cpp b/src/core/hle/service/ssl/ssl_backend_openssl.cpp index 795b69a873..5714e6f3c5 100644 --- a/src/core/hle/service/ssl/ssl_backend_openssl.cpp +++ b/src/core/hle/service/ssl/ssl_backend_openssl.cpp @@ -1,6 +1,3 @@ -// 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 @@ -289,7 +286,7 @@ Result CheckOpenSSLErrors() { msg.append(data); } Common::Log::FmtLogMessage(Common::Log::Class::Service_SSL, Common::Log::Level::Error, - file, line, func, "OpenSSL: {}", + Common::Log::TrimSourcePath(file), line, func, "OpenSSL: {}", msg); } return ResultInternalError; diff --git a/src/dynarmic/src/dynarmic/interface/optimization_flags.h b/src/dynarmic/src/dynarmic/interface/optimization_flags.h index 9e58197b47..743d902767 100644 --- a/src/dynarmic/src/dynarmic/interface/optimization_flags.h +++ b/src/dynarmic/src/dynarmic/interface/optimization_flags.h @@ -1,6 +1,3 @@ -// 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) 2020 MerryMage * SPDX-License-Identifier: 0BSD @@ -37,8 +34,6 @@ enum class OptimizationFlag : std::uint32_t { MiscIROpt = 0x00000020, /// Optimize for code speed rather than for code size (this serves well for tight loops) CodeSpeed = 0x00000040, - /// Disable verification passes - DisableVerification = 0x00000080, /// This is an UNSAFE optimization that reduces accuracy of fused multiply-add operations. /// This unfuses fused instructions to improve performance on host CPUs without FMA support. diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index e9175f0e6b..844e29023c 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -1491,9 +1491,9 @@ void Optimize(IR::Block& block, const A32::UserConfig& conf, const Optimization: Optimization::DeadCodeElimination(block); } Optimization::IdentityRemovalPass(block); - if (!conf.HasOptimization(OptimizationFlag::DisableVerification)) { + //if (!conf.HasOptimization(OptimizationFlag::DisableVerification)) { Optimization::VerificationPass(block); - } + //} } void Optimize(IR::Block& block, const A64::UserConfig& conf, const Optimization::PolyfillOptions& polyfill_options) { @@ -1511,9 +1511,9 @@ void Optimize(IR::Block& block, const A64::UserConfig& conf, const Optimization: if (conf.HasOptimization(OptimizationFlag::MiscIROpt)) [[likely]] { Optimization::A64MergeInterpretBlocksPass(block, conf.callbacks); } - if (!conf.HasOptimization(OptimizationFlag::DisableVerification)) { + //if (!conf.HasOptimization(OptimizationFlag::DisableVerification)) { Optimization::VerificationPass(block); - } + //} } } // namespace Dynarmic::Optimization diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index 6d325b4aad..b5e1e70b4c 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -991,7 +991,6 @@ IR::AbstractSyntaxList BuildASL(ObjectPool& inst_pool, ObjectPool 0; }); + Common::CondvarWait(command_cv, l, stop_token, + [this]() { return command_lists.size() > 0; }); if (stop_token.stop_requested()) { return; } diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 8739905d99..9392534e7d 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -116,7 +116,7 @@ u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) { state.queue.EmplaceWait(std::move(command_data), fence, block); if (block) { - state.cv.wait(lk, thread.get_stop_token(), [this, fence] { + Common::CondvarWait(state.cv, lk, thread.get_stop_token(), [this, fence] { return fence <= state.signaled_fence.load(std::memory_order_relaxed); }); } diff --git a/src/video_core/host1x/codecs/decoder.cpp b/src/video_core/host1x/codecs/decoder.cpp index 887eb28c8c..cb17784b19 100755 --- a/src/video_core/host1x/codecs/decoder.cpp +++ b/src/video_core/host1x/codecs/decoder.cpp @@ -38,10 +38,6 @@ void Decoder::Decode() { // Receive output frames from decoder. auto frame = decode_api.ReceiveFrame(); - if (!frame) { - return; - } - if (IsInterlaced()) { auto [luma_top, luma_bottom, chroma_top, chroma_bottom] = GetInterlacedOffsets(); auto frame_copy = frame; diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.cpp b/src/video_core/host1x/ffmpeg/ffmpeg.cpp index bbbbe615ce..536a01fcc8 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.cpp +++ b/src/video_core/host1x/ffmpeg/ffmpeg.cpp @@ -233,7 +233,7 @@ bool DecoderContext::OpenContext(const Decoder& decoder) { } bool DecoderContext::SendPacket(const Packet& packet) { - if (const int ret = avcodec_send_packet(m_codec_context, packet.GetPacket()); ret < 0 && ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) { + if (const int ret = avcodec_send_packet(m_codec_context, packet.GetPacket()); ret < 0 && ret != AVERROR_EOF) { LOG_ERROR(HW_GPU, "avcodec_send_packet error: {}", AVError(ret)); return false; } @@ -242,31 +242,31 @@ bool DecoderContext::SendPacket(const Packet& packet) { } std::shared_ptr DecoderContext::ReceiveFrame() { - auto ReceiveImpl = [&](AVFrame* frame) -> int { - const int ret = avcodec_receive_frame(m_codec_context, frame); - if (ret < 0 && ret != AVERROR_EOF && ret != AVERROR(EAGAIN)) { + auto ReceiveImpl = [&](AVFrame* frame) -> bool { + if (const int ret = avcodec_receive_frame(m_codec_context, frame); ret < 0 && ret != AVERROR_EOF) { LOG_ERROR(HW_GPU, "avcodec_receive_frame error: {}", AVError(ret)); + return false; } - return ret; + return true; }; std::shared_ptr intermediate_frame = std::make_shared(); - if (ReceiveImpl(intermediate_frame->GetFrame()) < 0) { + if (!ReceiveImpl(intermediate_frame->GetFrame())) { return {}; } - m_final_frame = std::make_shared(); + m_temp_frame = std::make_shared(); if (m_codec_context->hw_device_ctx) { - m_final_frame->SetFormat(PreferredGpuFormat); - if (const int ret = av_hwframe_transfer_data(m_final_frame->GetFrame(), intermediate_frame->GetFrame(), 0); ret < 0) { + m_temp_frame->SetFormat(PreferredGpuFormat); + if (int ret = av_hwframe_transfer_data(m_temp_frame->GetFrame(), intermediate_frame->GetFrame(), 0); ret < 0) { LOG_ERROR(HW_GPU, "av_hwframe_transfer_data error: {}", AVError(ret)); return {}; } } else { - m_final_frame = std::move(intermediate_frame); + m_temp_frame = std::move(intermediate_frame); } - return std::move(m_final_frame); + return std::move(m_temp_frame); } void DecodeApi::Reset() { diff --git a/src/video_core/host1x/ffmpeg/ffmpeg.h b/src/video_core/host1x/ffmpeg/ffmpeg.h index d60a8ac4a7..0dd7c7cb04 100644 --- a/src/video_core/host1x/ffmpeg/ffmpeg.h +++ b/src/video_core/host1x/ffmpeg/ffmpeg.h @@ -194,7 +194,7 @@ public: private: const Decoder& m_decoder; AVCodecContext* m_codec_context{}; - std::shared_ptr m_final_frame{}; + std::shared_ptr m_temp_frame{}; bool m_decode_order{}; }; diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index 3dbbfa5552..9c33370337 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -146,11 +146,6 @@ void Vic::Execute() { } auto frame = frame_queue.GetFrame(nvdec_id, luma_offset); - - if (!frame) { - continue; - } - if (!frame.get()) { LOG_ERROR(HW_GPU, "Vic {} failed to get frame with offset {:#X}", id, luma_offset); continue; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 45f729698e..c2ead26bd9 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -54,7 +54,7 @@ using VideoCommon::LoadPipelines; using VideoCommon::SerializePipeline; using Context = ShaderContext::Context; -constexpr u32 CACHE_VERSION = 13; +constexpr u32 CACHE_VERSION = 10; template auto MakeSpan(Container& container) { diff --git a/src/video_core/renderer_vulkan/present/layer.cpp b/src/video_core/renderer_vulkan/present/layer.cpp index 5676dfe62a..fa7c457573 100644 --- a/src/video_core/renderer_vulkan/present/layer.cpp +++ b/src/video_core/renderer_vulkan/present/layer.cpp @@ -280,7 +280,6 @@ void Layer::UpdateRawImage(const Tegra::FramebufferConfig& framebuffer, size_t i Tegra::Texture::UnswizzleTexture( mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size), bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0); - buffer.Flush(); // Ensure host writes are visible before the GPU copy. } const VkBufferImageCopy copy{ diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp index e65755de64..6761127582 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp @@ -208,7 +208,7 @@ void MasterSemaphore::WaitThread(std::stop_token token) { vk::Fence fence; { std::unique_lock lock{wait_mutex}; - wait_cv.wait(lock, token, [this] { return !wait_queue.empty(); }); + Common::CondvarWait(wait_cv, lock, token, [this] { return !wait_queue.empty(); }); if (token.stop_requested()) { return; } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 9cdbe5611b..2fd0b59b3a 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -55,7 +55,7 @@ using VideoCommon::FileEnvironment; using VideoCommon::GenericEnvironment; using VideoCommon::GraphicsEnvironment; -constexpr u32 CACHE_VERSION = 13; +constexpr u32 CACHE_VERSION = 12; constexpr std::array VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'}; template diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 0b29ad1389..23279e49b9 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -279,7 +279,7 @@ void PresentManager::PresentThread(std::stop_token token) { std::unique_lock lock{queue_mutex}; // Wait for presentation frames - frame_cv.wait(lock, token, [this] { return !present_queue.empty(); }); + Common::CondvarWait(frame_cv, lock, token, [this] { return !present_queue.empty(); }); if (token.stop_requested()) { return; } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index d109d22cab..530d161dfe 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -166,7 +166,7 @@ void Scheduler::WorkerThread(std::stop_token stop_token) { std::unique_lock lk{queue_mutex}; // Wait for work. - event_cv.wait(lk, stop_token, [&] { return TryPopQueue(work); }); + Common::CondvarWait(event_cv, lk, stop_token, [&] { return TryPopQueue(work); }); // If we've been asked to stop, we're done. if (stop_token.stop_requested()) { diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp index 54183be12c..04a51f2d1e 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp @@ -1,6 +1,3 @@ -// 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-2.0-or-later @@ -227,7 +224,7 @@ void TurboMode::Run(std::stop_token stop_token) { #endif // Wait for the next graphics queue submission if necessary. std::unique_lock lk{m_submission_lock}; - m_submission_cv.wait(lk, stop_token, [this] { + Common::CondvarWait(m_submission_cv, lk, stop_token, [this] { return (std::chrono::steady_clock::now() - m_submission_time) <= std::chrono::milliseconds{100}; }); diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 00e03bd935..c3d8f5387a 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -366,7 +366,7 @@ if (APPLE) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE TRUE) set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) - if (YUZU_USE_BUNDLED_MOLTENVK) + if (YUZU_APPLE_USE_BUNDLED_MONTENVK) set(MOLTENVK_PLATFORM "macOS") set(MOLTENVK_VERSION "v1.3.0") download_moltenvk(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index 9f7597f471..b7c0cd58d5 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp @@ -14,12 +14,11 @@ AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent) , ui{std::make_unique()} { + static const std::string description = std::string{Common::g_build_version}; static const std::string build_id = std::string{Common::g_build_id}; - static const std::string yuzu_build = fmt::format("{} | {} | {}", - std::string{Common::g_build_name}, - std::string{Common::g_build_version}, - std::string{Common::g_compiler_id} - ); + static const std::string compiler = std::string{Common::g_compiler_id}; + + static const std::string yuzu_build = fmt::format("Eden | {} | {}", description, compiler); const auto override_build = fmt::format(fmt::runtime( std::string(Common::g_title_bar_format_idle)), diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index cdc4e4024a..7b5f2a314f 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -108,13 +108,13 @@ void EmuThread::run() { m_system.Run(); m_stopped.Reset(); - m_should_run_cv.wait(lk, stop_token, [&] { return !m_should_run; }); + Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return !m_should_run; }); } else { m_system.Pause(); m_stopped.Set(); EmulationPaused(lk); - m_should_run_cv.wait(lk, stop_token, [&] { return m_should_run; }); + Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; }); EmulationResumed(lk); } } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index fc7a953d77..d2c12c9d40 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -4192,25 +4192,23 @@ void GMainWindow::OnEmulatorUpdateAvailable() { update_prompt.addButton(QMessageBox::Yes); update_prompt.addButton(QMessageBox::Ignore); update_prompt.setText( - tr("Download the %1 update?").arg(version_string)); + 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()) { - auto const full_url = fmt::format("{}/{}/releases/tag/", - std::string{Common::g_build_auto_update_website}, - std::string{Common::g_build_auto_update_repo} - ); - QDesktopServices::openUrl(QUrl(QString::fromStdString(full_url) + version_string)); + QDesktopServices::openUrl( + QUrl(QString::fromStdString("https://github.com/eden-emulator/Releases/releases/tag/") + + version_string)); } } #endif -void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_view title_version, std::string_view gpu_vendor) { +void GMainWindow::UpdateWindowTitle(std::string_view title_name, std::string_view title_version, + std::string_view gpu_vendor) { + static const std::string description = std::string{Common::g_build_version}; static const std::string build_id = std::string{Common::g_build_id}; - static const std::string yuzu_title = fmt::format("{} | {} | {}", - std::string{Common::g_build_name}, - std::string{Common::g_build_version}, - std::string{Common::g_compiler_id} - ); + static const std::string compiler = std::string{Common::g_compiler_id}; + + static const std::string yuzu_title = fmt::format("Eden | {} | {}", description, compiler); const auto override_title = fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id); diff --git a/src/yuzu/update_checker.cpp b/src/yuzu/update_checker.cpp index e54eb8d7f8..8291987d73 100644 --- a/src/yuzu/update_checker.cpp +++ b/src/yuzu/update_checker.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -15,7 +12,6 @@ #include #include #include -#include "common/scm_rev.h" std::optional UpdateChecker::GetResponse(std::string url, std::string path) { @@ -58,8 +54,8 @@ std::optional UpdateChecker::GetResponse(std::string url, std::stri std::optional UpdateChecker::GetLatestRelease(bool include_prereleases) { - const auto update_check_url = std::string{Common::g_build_auto_update_api}; - std::string update_check_path = fmt::format("/repos/{}", std::string{Common::g_build_auto_update_repo}); + constexpr auto update_check_url = "http://api.github.com"; + std::string update_check_path = "/repos/eden-emulator/Releases"; try { if (include_prereleases) { // This can return either a prerelease or a stable release, // whichever is more recent. diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 4b56f3794b..9ec6b1d594 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -229,7 +229,7 @@ void EmuWindow_SDL2::WaitEvent() { const u32 current_time = SDL_GetTicks(); if (current_time > last_time + 2000) { const auto results = system.GetAndResetPerfStats(); - const auto title = fmt::format("{} | {}-{} | FPS: {:.0f} ({:.0f}%)", + const auto title = fmt::format("Eden {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc, diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index 32f365e0d0..4b012fe134 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -93,7 +90,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste } SDL_GL_SetSwapInterval(0); - std::string window_title = fmt::format("{} | {}-{}", Common::g_build_fullname, + std::string window_title = fmt::format("Eden {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc); render_window = SDL_CreateWindow(window_title.c_str(), @@ -141,7 +138,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste OnResize(); OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); SDL_PumpEvents(); - LOG_INFO(Frontend, "Build string: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, + LOG_INFO(Frontend, "Eden Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc); Settings::LogSettings(); }