diff --git a/CMakeLists.txt b/CMakeLists.txt index 42e8615e57..9406dd64a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -396,7 +396,71 @@ function(set_suyu_qt_components) set(SUYU_QT_COMPONENTS ${SUYU_QT_COMPONENTS2} PARENT_SCOPE) endfunction(set_suyu_qt_components) +# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the suyu_find_package +if (ENABLE_SDL2) + if (SUYU_USE_BUNDLED_SDL2) + # Detect toolchain and platform + if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64) + set(SDL2_VER "SDL2-2.28.2") + else() + message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable SUYU_USE_BUNDLED_SDL2 and provide your own.") + endif() + + if (DEFINED SDL2_VER) + download_bundled_external("sdl2/" ${SDL2_VER} SDL2_PREFIX) + endif() + + set(SDL2_FOUND YES) + set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers") + set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library") + set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll") + + add_library(SDL2::SDL2 INTERFACE IMPORTED) + target_link_libraries(SDL2::SDL2 INTERFACE "${SDL2_LIBRARY}") + target_include_directories(SDL2::SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") + elseif (SUYU_USE_EXTERNAL_SDL2) + message(STATUS "Using SDL2 from externals.") + else() + find_package(SDL2 2.26.4 REQUIRED) + endif() +endif() + +# List of all FFmpeg components required +set(FFmpeg_COMPONENTS + avcodec + avfilter + avutil + swscale) + +if (UNIX AND NOT APPLE AND NOT ANDROID) + find_package(PkgConfig REQUIRED) + pkg_check_modules(LIBVA libva) +endif() +if (NOT SUYU_USE_BUNDLED_FFMPEG) + # Use system installed FFmpeg + find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS}) +endif() + +if (WIN32 AND SUYU_CRASH_DUMPS) + set(BREAKPAD_VER "breakpad-c89f9dd") + download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX) + + set(BREAKPAD_CLIENT_INCLUDE_DIR "${BREAKPAD_PREFIX}/include") + set(BREAKPAD_CLIENT_LIBRARY "${BREAKPAD_PREFIX}/lib/libbreakpad_client.lib") + + add_library(libbreakpad_client INTERFACE IMPORTED) + target_link_libraries(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_LIBRARY}") + target_include_directories(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_INCLUDE_DIR}") +endif() + +# Prefer the -pthread flag on Linux. +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) + +add_subdirectory(externals) + # Qt5 requires that we find components, so it doesn't fit our pretty little find package function +# Qt6 sets Vulkan::Headers, so Qt search has to come after externals, so it doesn't get to do it. if(ENABLE_QT) set(QT_VERSION 5.15) # These are used to specify minimum versions @@ -535,67 +599,6 @@ if(ENABLE_QT) endif() -# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the suyu_find_package -if (ENABLE_SDL2) - if (SUYU_USE_BUNDLED_SDL2) - # Detect toolchain and platform - if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64) - set(SDL2_VER "SDL2-2.28.2") - else() - message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable SUYU_USE_BUNDLED_SDL2 and provide your own.") - endif() - - if (DEFINED SDL2_VER) - download_bundled_external("sdl2/" ${SDL2_VER} SDL2_PREFIX) - endif() - - set(SDL2_FOUND YES) - set(SDL2_INCLUDE_DIR "${SDL2_PREFIX}/include" CACHE PATH "Path to SDL2 headers") - set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library") - set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll") - - add_library(SDL2::SDL2 INTERFACE IMPORTED) - target_link_libraries(SDL2::SDL2 INTERFACE "${SDL2_LIBRARY}") - target_include_directories(SDL2::SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") - elseif (SUYU_USE_EXTERNAL_SDL2) - message(STATUS "Using SDL2 from externals.") - else() - find_package(SDL2 2.26.4 REQUIRED) - endif() -endif() - -# List of all FFmpeg components required -set(FFmpeg_COMPONENTS - avcodec - avfilter - avutil - swscale) - -if (UNIX AND NOT APPLE AND NOT ANDROID) - find_package(PkgConfig REQUIRED) - pkg_check_modules(LIBVA libva) -endif() -if (NOT SUYU_USE_BUNDLED_FFMPEG) - # Use system installed FFmpeg - find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS}) -endif() - -if (WIN32 AND SUYU_CRASH_DUMPS) - set(BREAKPAD_VER "breakpad-c89f9dd") - download_bundled_external("breakpad/" ${BREAKPAD_VER} BREAKPAD_PREFIX) - - set(BREAKPAD_CLIENT_INCLUDE_DIR "${BREAKPAD_PREFIX}/include") - set(BREAKPAD_CLIENT_LIBRARY "${BREAKPAD_PREFIX}/lib/libbreakpad_client.lib") - - add_library(libbreakpad_client INTERFACE IMPORTED) - target_link_libraries(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_LIBRARY}") - target_include_directories(libbreakpad_client INTERFACE "${BREAKPAD_CLIENT_INCLUDE_DIR}") -endif() - -# Prefer the -pthread flag on Linux. -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) - # Platform-specific library requirements # ====================================== @@ -710,7 +713,6 @@ if (SUYU_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() endif() -add_subdirectory(externals) add_subdirectory(src) # Set suyu project or suyu-cmd project as default StartUp Project in Visual Studio depending on whether QT is enabled or not diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index fd16197749..2cdd6cf06a 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -231,8 +232,15 @@ public: if (!filter.CheckMessage(log_class, log_level)) { return; } - message_queue.EmplaceWait( - CreateEntry(log_class, log_level, filename, line_num, function, std::move(message))); + + auto entry = + CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)); + if (Settings::values.log_async) { + message_queue.EmplaceWait(entry); + } else { + std::scoped_lock l{sync_mutex}; + ForEachBackend([&entry](Backend& backend) { backend.Write(entry); }); + } } private: @@ -313,6 +321,7 @@ private: #endif MPSCQueue message_queue{}; + std::mutex sync_mutex; std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; std::jthread backend_thread; }; @@ -345,9 +354,11 @@ void SetColorConsoleBackendEnabled(bool enabled) { 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) { - Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, - fmt::vformat(format, args)); + if (initialization_in_progress_suppress_logging) { + return; } + + 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 4e3a614a45..ae866c7a50 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -171,6 +171,7 @@ const char* GetLogClassName(Class log_class) { #define SUB(x, y) \ case Class::x##_##y: \ return #x "." #y; + // return #x "_" #y; ALL_LOG_CLASSES() #undef CLS #undef SUB diff --git a/src/common/settings.h b/src/common/settings.h index 48f127bde8..829759c94b 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -604,6 +604,7 @@ struct Values { // Miscellaneous Setting log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous}; + Setting log_async{linkage, true, "log_async", Category::Miscellaneous}; Setting use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous}; // Network diff --git a/src/core/hle/service/am/process_creation.cpp b/src/core/hle/service/am/process_creation.cpp index 237151d061..e6e2fad2c6 100644 --- a/src/core/hle/service/am/process_creation.cpp +++ b/src/core/hle/service/am/process_creation.cpp @@ -106,6 +106,7 @@ std::unique_ptr CreateApplicationProcess(std::vector& out_control, out_control = nacp.GetRawBytes(); } else { out_control.resize(sizeof(FileSys::RawNACP)); + memset(out_control.data(), 0, sizeof(u8) * out_control.size()); } auto& storage = system.GetContentProviderUnion(); diff --git a/src/core/hle/service/am/service/library_applet_accessor.cpp b/src/core/hle/service/am/service/library_applet_accessor.cpp index cda8c3eb87..b7ea464ff2 100644 --- a/src/core/hle/service/am/service/library_applet_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_accessor.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2024 suyu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/am/applet_data_broker.h" @@ -101,6 +102,22 @@ Result ILibraryAppletAccessor::PushInData(SharedPointer storage) { Result ILibraryAppletAccessor::PopOutData(Out> out_storage) { LOG_DEBUG(Service_AM, "called"); + // suyu todo: move library applet fix to another function + // since this function is only called for applets that give a result, + // applets that don't (e.g. info applets in 1st party games) simply freeze + if (auto caller = m_applet->caller_applet.lock(); caller != nullptr) { + caller->SetInteractibleLocked(true); + + caller->lifecycle_manager.SetFocusState(FocusState::InFocus); + caller->lifecycle_manager.UpdateRequestedFocusState(); + + caller->lifecycle_manager.SetResumeNotificationEnabled(true); + caller->lifecycle_manager.RequestResumeNotification(); + caller->UpdateSuspensionStateLocked(true); + } else { + LOG_CRITICAL(Service_AM, "Caller applet pointer is invalid."); + LOG_CRITICAL(Service_AM, "The emulator will freeze!"); + } R_RETURN(m_broker->GetOutData().Pop(out_storage.Get())); } diff --git a/src/suyu/configuration/configure_debug.cpp b/src/suyu/configuration/configure_debug.cpp index b4fa4eca09..6f9bb36340 100644 --- a/src/suyu/configuration/configure_debug.cpp +++ b/src/suyu/configuration/configure_debug.cpp @@ -73,6 +73,7 @@ void ConfigureDebug::SetConfiguration() { ui->disable_loop_safety_checks->setChecked( Settings::values.disable_shader_loop_safety_checks.GetValue()); ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); + ui->log_async->setChecked(Settings::values.log_async.GetValue()); ui->perform_vulkan_check->setChecked(Settings::values.perform_vulkan_check.GetValue()); #ifdef SUYU_USE_QT_WEB_ENGINE @@ -115,6 +116,7 @@ void ConfigureDebug::ApplyConfiguration() { Common::Log::Filter filter; filter.ParseFilterString(Settings::values.log_filter.GetValue()); Common::Log::SetGlobalFilter(filter); + Settings::values.log_async = ui->log_async->isChecked(); } void ConfigureDebug::changeEvent(QEvent* event) { diff --git a/src/suyu/configuration/configure_debug.ui b/src/suyu/configuration/configure_debug.ui index ed48b2f8f6..e5b76290e6 100644 --- a/src/suyu/configuration/configure_debug.ui +++ b/src/suyu/configuration/configure_debug.ui @@ -164,6 +164,20 @@ + + + + true + + + When checked, logging will run asynchronously. This may cut the log on crashes. +When unchecked, logging will run synchronously. This will slow down the emulator, but allow all logs to be written. Useful for debugging. + + + Log asynchronously + + + @@ -199,7 +213,14 @@ - + + + Log filter in the form <class>:<level>. +Separate multiple filters with a space. +Levels: Trace, Debug, Info, Warning, Error, Critical +Classes: See Common/logging/types.h + +