diff --git a/.ci/windows/install-msvc.ps1 b/.ci/windows/install-msvc.ps1 index 788b2848ad..b88f727ed8 100755 --- a/.ci/windows/install-msvc.ps1 +++ b/.ci/windows/install-msvc.ps1 @@ -10,7 +10,7 @@ if (-not ([bool](net session 2>$null))) { } $VSVer = "17" -$ExeFile = "vs_community.exe" +$ExeFile = "vs_BuildTools.exe" $Uri = "https://aka.ms/vs/$VSVer/release/$ExeFile" $Destination = "./$ExeFile" @@ -19,39 +19,21 @@ $WebClient = New-Object System.Net.WebClient $WebClient.DownloadFile($Uri, $Destination) Write-Host "Finished downloading $ExeFile" +$VSROOT = "C:/VSBuildTools/$VSVer" $Arguments = @( - "--quiet", # Suppress installer UI - "--wait", # Wait for installation to complete - "--norestart", # Prevent automatic restart - "--force", # Force installation even if components are already installed - "--add Microsoft.VisualStudio.Workload.NativeDesktop", # Desktop development with C++ - "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64", # Core C++ compiler/tools for x86/x64 - "--add Microsoft.VisualStudio.Component.Windows11SDK.26100",# Windows 11 SDK (26100) - "--add Microsoft.VisualStudio.Component.Windows10SDK.19041",# Windows 10 SDK (19041) - "--add Microsoft.VisualStudio.Component.VC.Llvm.Clang", # LLVM Clang compiler - "--add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset", # LLVM Clang integration toolset - "--add Microsoft.VisualStudio.Component.Windows11SDK.22621",# Windows 11 SDK (22621) - "--add Microsoft.VisualStudio.Component.VC.CMake.Project", # CMake project support - "--add Microsoft.VisualStudio.ComponentGroup.VC.Tools.142.x86.x64", # VC++ 14.2 toolset - "--add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Llvm.Clang" # LLVM Clang for native desktop + "--installPath `"$VSROOT`"", # set custom installation path + "--quiet", # suppress UI + "--wait", # wait for installation to complete + "--norestart", # prevent automatic restart + "--add Microsoft.VisualStudio.Workload.VCTools", # add C++ build tools workload + "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64", # add core x86/x64 C++ tools + "--add Microsoft.VisualStudio.Component.Windows10SDK.19041" # add specific Windows SDK ) Write-Host "Installing Visual Studio Build Tools" -$InstallProcess = Start-Process -FilePath $Destination -NoNewWindow -PassThru -ArgumentList $Arguments - -# Spinner while installing -$Spinner = "|/-\" -$i = 0 -while (-not $InstallProcess.HasExited) { - Write-Host -NoNewline ("`rInstalling... " + $Spinner[$i % $Spinner.Length]) - Start-Sleep -Milliseconds 250 - $i++ -} - -# Clear spinner line -Write-Host "`rSetup completed! " - +$InstallProcess = Start-Process -FilePath $Destination -NoNewWindow -PassThru -Wait -ArgumentList $Arguments $ExitCode = $InstallProcess.ExitCode + if ($ExitCode -ne 0) { Write-Host "Error installing Visual Studio Build Tools (Error: $ExitCode)" Exit $ExitCode diff --git a/CMakeLists.txt b/CMakeLists.txt index b397ba01aa..ef3c0bef6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,55 +139,65 @@ endif() # Set bundled sdl2/qt as dependent options. # On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion -cmake_dependent_option(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF) - -if (ENABLE_SDL2) - # TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system - cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF) - option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") -endif() - -# qt stuff -option(ENABLE_QT "Enable the Qt frontend" ON) -option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) -option(ENABLE_QT_UPDATE_CHECKER "Enable update checker for the Qt frontend" OFF) -cmake_dependent_option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) -option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) -option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) -set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundled Qt libraries") - -option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) +CMAKE_DEPENDENT_OPTION(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF) set(EXT_DEFAULT OFF) + if (MSVC OR ANDROID) set(EXT_DEFAULT ON) endif() -option(YUZU_USE_CPM "Use CPM to fetch system dependencies (fmt, boost, etc) if needed. Externals will still be fetched." ${EXT_DEFAULT}) -# ffmpeg -option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT}) -cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from source" "${PLATFORM_SUN}" "NOT WIN32 AND NOT ANDROID" OFF) - -# sirit -option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${EXT_DEFAULT}) +if (ENABLE_SDL2) + # TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system + CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF) + option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") +endif() cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF) cmake_dependent_option(ENABLE_OPENGL "Enable OpenGL" ON "NOT WIN32 OR NOT ARCHITECTURE_arm64" OFF) mark_as_advanced(FORCE ENABLE_OPENGL) +option(ENABLE_QT "Enable the Qt frontend" ON) +option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) +option(ENABLE_QT_UPDATE_CHECKER "Enable update checker for the Qt frontend" OFF) + +CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) + +option(YUZU_USE_CPM "Use CPM to fetch system dependencies (fmt, boost, etc) if needed. Externals will still be fetched." ${EXT_DEFAULT}) + option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) option(ENABLE_WIFI_SCAN "Enable WiFi scanning" OFF) -cmake_dependent_option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF "ENABLE_QT" OFF) +option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT}) +cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from source" OFF "NOT WIN32 AND NOT ANDROID" OFF) + +option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) + +option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF) + +set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundled Qt libraries") + +option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) + +CMAKE_DEPENDENT_OPTION(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF "ENABLE_QT" OFF) option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}") -option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF) -if (YUZU_USE_PRECOMPILED_HEADERS) - message(STATUS "Using Precompiled Headers.") - set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON) -endif() +option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ${EXT_DEFAULT}) + +# TODO(crueter): CI this? +option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) + + +CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) + +CMAKE_DEPENDENT_OPTION(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF) + +CMAKE_DEPENDENT_OPTION(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL2;NOT ANDROID" OFF) + +CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) + option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) if(YUZU_ENABLE_LTO) include(CheckIPOSupported) @@ -195,42 +205,17 @@ if(YUZU_ENABLE_LTO) if(NOT COMPILER_SUPPORTS_LTO) message(FATAL_ERROR "Your compiler does not support interprocedural optimization (IPO). Re-run CMake with -DYUZU_ENABLE_LTO=OFF.") endif() - set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) endif() -option(USE_CCACHE "Use ccache for compilation" OFF) -set(CCACHE_PATH "ccache" CACHE STRING "Path to ccache binary") -if(USE_CCACHE) - find_program(CCACHE_BINARY ${CCACHE_PATH}) - if(CCACHE_BINARY) - message(STATUS "Found ccache at: ${CCACHE_BINARY}") - set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_BINARY}) - set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_BINARY}) - if (YUZU_USE_PRECOMPILED_HEADERS) - message(FATAL_ERROR "Precompiled headers are incompatible with ccache. Re-run CMake with -DYUZU_USE_PRECOMPILED_HEADERS=OFF.") - endif() - else() - message(WARNING "USE_CCACHE enabled, but no executable found at: ${CCACHE_PATH}") - endif() -endif() - -# TODO(crueter): CI this? -option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) - -cmake_dependent_option(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) -cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF) - -cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL2;NOT ANDROID" OFF) - -cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" ON) + +CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF) + +CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF) + 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) - option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF) set(DEFAULT_ENABLE_OPENSSL ON) @@ -243,12 +228,15 @@ if (ANDROID OR WIN32 OR APPLE OR PLATFORM_SUN) # your own copy of it. set(DEFAULT_ENABLE_OPENSSL OFF) endif() + if (ENABLE_WEB_SERVICE) set(DEFAULT_ENABLE_OPENSSL ON) endif() + option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL}) + if (ENABLE_OPENSSL) - cmake_dependent_option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" "${MSVC}" "NOT ANDROID" ON) + CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" "${MSVC}" "NOT ANDROID" ON) endif() if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL) @@ -275,6 +263,21 @@ if (ANDROID) set(CMAKE_POLICY_VERSION_MINIMUM 3.5) # Workaround for Oboe endif() +if (YUZU_USE_PRECOMPILED_HEADERS) + if (MSVC AND CCACHE) + # buildcache does not properly cache PCH files, leading to compilation errors. + # See https://github.com/mbitsnbites/buildcache/discussions/230 + message(WARNING "buildcache does not properly support Precompiled Headers. Disabling PCH") + set(DYNARMIC_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE) + set(YUZU_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE) + endif() +endif() + +if (YUZU_USE_PRECOMPILED_HEADERS) + message(STATUS "Using Precompiled Headers.") + set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON) +endif() + # Default to a Release build get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE) @@ -317,24 +320,13 @@ endif() if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX)) set(HAS_NCE 1) add_compile_definitions(HAS_NCE=1) + find_package(oaknut 2.0.1) endif() 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) @@ -456,6 +448,22 @@ if (YUZU_USE_CPM) add_library(zstd::zstd ALIAS libzstd_static) endif() + # Catch2 + if (YUZU_TESTS OR DYNARMIC_TESTS) + AddJsonPackage(catch2) + endif() + + # ENet + AddJsonPackage(enet) + + if (enet_ADDED) + target_include_directories(enet INTERFACE ${enet_SOURCE_DIR}/include) + endif() + + if (NOT TARGET enet::enet) + add_library(enet::enet ALIAS enet) + endif() + # Opus AddJsonPackage(opus) @@ -470,10 +478,31 @@ if (YUZU_USE_CPM) if (NOT TARGET Opus::opus) add_library(Opus::opus ALIAS opus) endif() + + # VulkanUtilityHeaders - pulls in headers and utility libs + AddJsonPackage(vulkan-utility-headers) + + # small hack + if (NOT VulkanUtilityLibraries_ADDED) + find_package(VulkanHeaders 1.3.274 REQUIRED) + endif() + + # SPIRV Headers + AddJsonPackage(spirv-headers) + + # SPIRV Tools + AddJsonPackage(spirv-tools) + + if (SPIRV-Tools_ADDED) + add_library(SPIRV-Tools::SPIRV-Tools ALIAS SPIRV-Tools-static) + target_link_libraries(SPIRV-Tools-static PRIVATE SPIRV-Tools-opt SPIRV-Tools-link) + endif() + + # mbedtls + AddJsonPackage(mbedtls) else() # Enforce the search mode of non-required packages for better and shorter failure messages find_package(fmt 8 REQUIRED) - if (NOT YUZU_DISABLE_LLVM) find_package(LLVM MODULE COMPONENTS Demangle) endif() @@ -482,7 +511,7 @@ else() find_package(lz4 REQUIRED) find_package(RenderDoc MODULE) find_package(stb MODULE) - + find_package(enet 1.3 MODULE REQUIRED) find_package(Opus 1.3 MODULE REQUIRED) find_package(ZLIB 1.2 REQUIRED) find_package(zstd 1.5 REQUIRED MODULE) @@ -494,6 +523,29 @@ else() find_package(Boost 1.57.0 REQUIRED) endif() + # OpenBSD does not package mbedtls3 (only 2) + if (PLATFORM_OPENBSD) + AddJsonPackage(mbedtls) + else() + find_package(MbedTLS 3 REQUIRED) + endif() + + find_package(VulkanUtilityLibraries REQUIRED) + find_package(VulkanHeaders 1.3.274 REQUIRED) + + # FreeBSD does not package spirv-headers + if (PLATFORM_FREEBSD) + AddJsonPackage(spirv-headers) + else() + find_package(SPIRV-Headers 1.3.274 REQUIRED) + endif() + + find_package(SPIRV-Tools MODULE REQUIRED) + + if (YUZU_TESTS) + find_package(Catch2 3.0.1 REQUIRED) + endif() + if (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR ANDROID) find_package(gamemode 1.7 MODULE) endif() @@ -507,6 +559,90 @@ if(NOT TARGET Boost::headers) AddJsonPackage(boost_headers) endif() +# DiscordRPC +if (USE_DISCORD_PRESENCE) + if (ARCHITECTURE_arm64) + add_compile_definitions(RAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN) + endif() + + AddJsonPackage(discord-rpc) + + target_include_directories(discord-rpc INTERFACE ${discord-rpc_SOURCE_DIR}/include) + add_library(DiscordRPC::discord-rpc ALIAS discord-rpc) +endif() + +# SimpleIni +AddJsonPackage(simpleini) + +# Most linux distros don't package cubeb, so enable regardless of cpm settings +if(ENABLE_CUBEB) + AddJsonPackage(cubeb) + + if (cubeb_ADDED) + if (NOT MSVC) + if (TARGET speex) + target_compile_options(speex PRIVATE -Wno-sign-compare) + endif() + + set_target_properties(cubeb PROPERTIES COMPILE_OPTIONS "") + target_compile_options(cubeb INTERFACE + -Wno-implicit-const-int-float-conversion + -Wno-shadow + -Wno-missing-declarations + -Wno-return-type + -Wno-uninitialized + ) + else() + target_compile_options(cubeb PRIVATE + /wd4456 + /wd4458 + ) + endif() + endif() + + if (NOT TARGET cubeb::cubeb) + add_library(cubeb::cubeb ALIAS cubeb) + endif() +endif() + +# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package +if (ENABLE_SDL2) + if (YUZU_USE_EXTERNAL_SDL2) + message(STATUS "Using SDL2 from externals.") + if (NOT WIN32) + # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers + # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095) + # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) + # CPUinfo also required for SDL Audio, at least until 2.28.0 (see https://github.com/libsdl-org/SDL/issues/7809) + set(SDL_UNUSED_SUBSYSTEMS + File Filesystem + Locale Power Render) + foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) + string(TOUPPER ${_SUB} _OPT) + set(SDL_${_OPT} OFF) + endforeach() + + set(HIDAPI ON) + endif() + + if (APPLE) + set(SDL_FILE ON) + endif() + + if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") + set(SDL_PIPEWIRE OFF) # build errors out with this on + AddJsonPackage("sdl2_steamdeck") + else() + AddJsonPackage("sdl2_generic") + endif() + elseif (YUZU_USE_BUNDLED_SDL2) + message(STATUS "Using bundled SDL2") + AddJsonPackage(sdl2) + endif() + + find_package(SDL2 2.26.4 REQUIRED) +endif() + # List of all FFmpeg components required set(FFmpeg_COMPONENTS avcodec @@ -537,11 +673,6 @@ add_subdirectory(externals) # pass targets from externals find_package(libusb) find_package(VulkanMemoryAllocator) -find_package(enet) -find_package(MbedTLS) -find_package(VulkanUtilityLibraries) -find_package(SimpleIni) -find_package(SPIRV-Tools) if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) find_package(xbyak) @@ -555,26 +686,6 @@ if (ENABLE_WEB_SERVICE OR ENABLE_QT_UPDATE_CHECKER) find_package(cpp-jwt) endif() -if (ARCHITECTURE_arm64 OR DYNARMIC_TESTS) - find_package(oaknut) -endif() - -if (ENABLE_SDL2) - find_package(SDL2) -endif() - -if (USE_DISCORD_PRESENCE) - find_package(DiscordRPC) -endif() - -if (ENABLE_CUBEB) - find_package(cubeb) -endif() - -if (YUZU_TESTS OR DYNARMIC_TESTS) - find_package(Catch2) -endif() - if (ENABLE_QT) if (YUZU_USE_BUNDLED_QT) download_qt(6.8.3) @@ -783,47 +894,25 @@ if (MSVC AND CXX_CLANG) link_libraries(llvm-mingw-runtime) endif() -#[[ - search order: - - gold (GCC only) - the best, generally, but unfortunately not packaged anymore - - mold (GCC only) - generally does well on GCC - - ldd - preferred on clang - - bfd - the final fallback - - If none are found (macOS uses ld.prime, etc) just use the default linker -]] if (YUZU_USE_FASTER_LD) - find_program(LINKER_BFD bfd) - if (LINKER_BFD) - set(LINKER bfd) - endif() + # clang should always use lld + find_program(LLD lld) - find_program(LINKER_LLD lld) - if (LINKER_LLD) + if (LLD) set(LINKER lld) endif() + # GNU appears to work better with mold + # TODO: mold has been slow lately, see if better options exist (search for gold?) if (CXX_GCC) - find_program(LINKER_MOLD mold) - if (LINKER_MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") + find_program(MOLD mold) + if (MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") set(LINKER mold) endif() - - find_program(LINKER_GOLD gold) - if (LINKER_GOLD) - set(LINKER gold) - endif() endif() - if (LINKER) - message(NOTICE "Selecting ${LINKER} as linker") - add_link_options("-fuse-ld=${LINKER}") - else() - message(WARNING "No faster linker found--using default") - endif() - - if (LINKER STREQUAL "lld" AND CXX_GCC) - message(WARNING "Using lld on GCC may cause issues with certain LTO settings. If the program fails to compile, disable YUZU_USE_FASTER_LD, or install mold or GNU gold.") - endif() + message(NOTICE "Selecting ${LINKER} as linker") + add_link_options("-fuse-ld=${LINKER}") endif() # Set runtime library to MD/MDd for all configurations diff --git a/CMakeModules/CPMUtil.cmake b/CMakeModules/CPMUtil.cmake index 3347c7e884..d84c069399 100644 --- a/CMakeModules/CPMUtil.cmake +++ b/CMakeModules/CPMUtil.cmake @@ -107,6 +107,7 @@ function(AddJsonPackage) get_json_element("${object}" name name "${JSON_NAME}") get_json_element("${object}" extension extension "tar.zst") get_json_element("${object}" min_version min_version "") + get_json_element("${object}" cmake_filename cmake_filename "") get_json_element("${object}" raw_disabled disabled_platforms "") if (raw_disabled) @@ -123,6 +124,7 @@ function(AddJsonPackage) EXTENSION ${extension} MIN_VERSION ${min_version} DISABLED_PLATFORMS ${disabled_platforms} + CMAKE_FILENAME ${cmake_filename} ) # pass stuff to parent scope @@ -137,7 +139,6 @@ function(AddJsonPackage) endif() get_json_element("${object}" hash hash "") - get_json_element("${object}" hash_suffix hash_suffix "") get_json_element("${object}" sha sha "") get_json_element("${object}" url url "") get_json_element("${object}" key key "") @@ -207,7 +208,6 @@ function(AddJsonPackage) VERSION "${version}" URL "${url}" HASH "${hash}" - HASH_SUFFIX "${hash_suffix}" SHA "${sha}" REPO "${repo}" KEY "${key}" @@ -533,6 +533,7 @@ function(AddCIPackage) EXTENSION MIN_VERSION DISABLED_PLATFORMS + CMAKE_FILENAME ) cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "" ${ARGN}) @@ -588,28 +589,25 @@ function(AddCIPackage) add_ci_package(android) endif() - if(PLATFORM_SUN AND NOT "solaris-amd64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(solaris-amd64) + if(PLATFORM_SUN AND NOT "solaris" IN_LIST DISABLED_PLATFORMS) + add_ci_package(solaris) endif() - if(PLATFORM_FREEBSD AND NOT "freebsd-amd64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(freebsd-amd64) + if(PLATFORM_FREEBSD AND NOT "freebsd" IN_LIST DISABLED_PLATFORMS) + add_ci_package(freebsd) endif() - if((PLATFORM_LINUX AND ARCHITECTURE_x86_64) AND NOT "linux-amd64" IN_LIST DISABLED_PLATFORMS) - add_ci_package(linux-amd64) + if((PLATFORM_LINUX AND ARCHITECTURE_x86_64) AND NOT "linux" IN_LIST DISABLED_PLATFORMS) + add_ci_package(linux) endif() if((PLATFORM_LINUX AND ARCHITECTURE_arm64) AND NOT "linux-aarch64" IN_LIST DISABLED_PLATFORMS) add_ci_package(linux-aarch64) endif() - # TODO(crueter): macOS amd64/aarch64 split mayhaps - if (APPLE AND NOT "macos-universal" IN_LIST DISABLED_PLATFORMS) - add_ci_package(macos-universal) - endif() - if (DEFINED ARTIFACT_DIR) + include(${ARTIFACT_DIR}/${ARTIFACT_CMAKE}.cmake) + set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE) set(${ARTIFACT_PACKAGE}_SOURCE_DIR "${ARTIFACT_DIR}" PARENT_SCOPE) else() diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index f6e3aaa4ad..6c4afc03be 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -10,7 +10,6 @@ function(download_bundled_external remote_path lib_name cpm_key prefix_var versi set(package_base_url "https://github.com/eden-emulator/") set(package_repo "no_platform") set(package_extension "no_platform") - set(CACHE_KEY "") # TODO(crueter): Need to convert ffmpeg to a CI. if (WIN32 OR FORCE_WIN_ARCHIVES) @@ -34,9 +33,8 @@ function(download_bundled_external remote_path lib_name cpm_key prefix_var versi else() message(FATAL_ERROR "No package available for this platform") endif() - string(CONCAT package_url "${package_base_url}" "${package_repo}") - string(CONCAT full_url "${package_url}" "${remote_path}" "${lib_name}" "${package_extension}") - message(STATUS "Resolved bundled URL: ${full_url}") + set(package_url "${package_base_url}${package_repo}") + set(full_url ${package_url}${remote_path}${lib_name}${package_extension}) # TODO(crueter): DELETE THIS ENTIRELY, GLORY BE TO THE CI! AddPackage( @@ -49,12 +47,26 @@ function(download_bundled_external remote_path lib_name cpm_key prefix_var versi # TODO(crueter): hash ) - if (DEFINED ${cpm_key}_SOURCE_DIR) - set(${prefix_var} "${${cpm_key}_SOURCE_DIR}" PARENT_SCOPE) - message(STATUS "Using bundled binaries at ${${cpm_key}_SOURCE_DIR}") - else() - message(FATAL_ERROR "AddPackage did not set ${cpm_key}_SOURCE_DIR") + set(${prefix_var} "${${cpm_key}_SOURCE_DIR}" PARENT_SCOPE) + message(STATUS "Using bundled binaries at ${${cpm_key}_SOURCE_DIR}") +endfunction() + +function(download_moltenvk_external platform version) + set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") + set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") + if (NOT EXISTS ${MOLTENVK_DIR}) + if (NOT EXISTS ${MOLTENVK_TAR}) + file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/${version}/MoltenVK-${platform}.tar + ${MOLTENVK_TAR} SHOW_PROGRESS) + endif() + + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals") endif() + + # Add the MoltenVK library path to the prefix so find_library can locate it. + list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}") + set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() # Determine installation parameters for OS, architecture, and compiler @@ -96,7 +108,7 @@ function(determine_qt_parameters target host_out type_out arch_out arch_path_out set(host "linux") set(type "desktop") set(arch "linux_gcc_64") - set(arch_path "gcc_64") + set(arch_path "linux") endif() set(${host_out} "${host}" PARENT_SCOPE) @@ -131,79 +143,56 @@ function(download_qt_configuration prefix_out target host type arch arch_path ba set(install_args -c "${CURRENT_MODULE_DIR}/aqt_config.ini") if (tool) set(prefix "${base_path}/Tools") - list(APPEND install_args install-tool --outputdir "${base_path}" "${host}" desktop "${target}") + set(install_args ${install_args} install-tool --outputdir ${base_path} ${host} desktop ${target}) else() set(prefix "${base_path}/${target}/${arch_path}") - list(APPEND install_args install-qt --outputdir "${base_path}" "${host}" "${type}" "${target}" "${arch}" -m qt_base) + set(install_args ${install_args} install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} -m qt_base) if (YUZU_USE_QT_MULTIMEDIA) - list(APPEND install_args qtmultimedia) + set(install_args ${install_args} qtmultimedia) endif() if (YUZU_USE_QT_WEB_ENGINE) - list(APPEND install_args qtpositioning qtwebchannel qtwebengine) + set(install_args ${install_args} qtpositioning qtwebchannel qtwebengine) endif() - if (NOT "${YUZU_QT_MIRROR}" STREQUAL "") + if (NOT ${YUZU_QT_MIRROR} STREQUAL "") message(STATUS "Using Qt mirror ${YUZU_QT_MIRROR}") - list(APPEND install_args -b "${YUZU_QT_MIRROR}") + set(install_args ${install_args} -b ${YUZU_QT_MIRROR}) endif() endif() - message(STATUS "Install Args: ${install_args}") - + message(STATUS "Install Args ${install_args}") if (NOT EXISTS "${prefix}") message(STATUS "Downloading Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path}") set(AQT_PREBUILD_BASE_URL "https://github.com/miurahr/aqtinstall/releases/download/v3.3.0") if (WIN32) set(aqt_path "${base_path}/aqt.exe") if (NOT EXISTS "${aqt_path}") - file(DOWNLOAD "${AQT_PREBUILD_BASE_URL}/aqt.exe" "${aqt_path}" SHOW_PROGRESS) - endif() - execute_process(COMMAND "${aqt_path}" ${install_args} - WORKING_DIRECTORY "${base_path}" - RESULT_VARIABLE aqt_res - OUTPUT_VARIABLE aqt_out - ERROR_VARIABLE aqt_err) - if (NOT aqt_res EQUAL 0) - message(FATAL_ERROR "aqt.exe failed: ${aqt_err}") + file(DOWNLOAD + ${AQT_PREBUILD_BASE_URL}/aqt.exe + ${aqt_path} SHOW_PROGRESS) endif() + execute_process(COMMAND ${aqt_path} ${install_args} + WORKING_DIRECTORY ${base_path}) elseif (APPLE) set(aqt_path "${base_path}/aqt-macos") if (NOT EXISTS "${aqt_path}") - file(DOWNLOAD "${AQT_PREBUILD_BASE_URL}/aqt-macos" "${aqt_path}" SHOW_PROGRESS) - endif() - execute_process(COMMAND chmod +x "${aqt_path}") - execute_process(COMMAND "${aqt_path}" ${install_args} - WORKING_DIRECTORY "${base_path}" - RESULT_VARIABLE aqt_res - ERROR_VARIABLE aqt_err) - if (NOT aqt_res EQUAL 0) - message(FATAL_ERROR "aqt-macos failed: ${aqt_err}") + file(DOWNLOAD + ${AQT_PREBUILD_BASE_URL}/aqt-macos + ${aqt_path} SHOW_PROGRESS) endif() + execute_process(COMMAND chmod +x ${aqt_path}) + execute_process(COMMAND ${aqt_path} ${install_args} + WORKING_DIRECTORY ${base_path}) else() - find_program(PYTHON3_EXECUTABLE python3) - if (NOT PYTHON3_EXECUTABLE) - message(FATAL_ERROR "python3 is required to install Qt using aqt (pip mode).") - endif() set(aqt_install_path "${base_path}/aqt") file(MAKE_DIRECTORY "${aqt_install_path}") - execute_process(COMMAND "${PYTHON3_EXECUTABLE}" -m pip install --target="${aqt_install_path}" aqtinstall - WORKING_DIRECTORY "${base_path}" - RESULT_VARIABLE pip_res - ERROR_VARIABLE pip_err) - if (NOT pip_res EQUAL 0) - message(FATAL_ERROR "pip install aqtinstall failed: ${pip_err}") - endif() - - execute_process(COMMAND "${CMAKE_COMMAND}" -E env PYTHONPATH="${aqt_install_path}" "${PYTHON3_EXECUTABLE}" -m aqt ${install_args} - WORKING_DIRECTORY "${base_path}" - RESULT_VARIABLE aqt_res - ERROR_VARIABLE aqt_err) - if (NOT aqt_res EQUAL 0) - message(FATAL_ERROR "aqt (python) failed: ${aqt_err}") - endif() + execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall + WORKING_DIRECTORY ${base_path}) + execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args} + WORKING_DIRECTORY ${base_path}) endif() message(STATUS "Downloaded Qt binaries for ${target}:${host}:${type}:${arch}:${arch_path} to ${prefix}") @@ -221,7 +210,7 @@ endfunction() function(download_qt target) determine_qt_parameters("${target}" host type arch arch_path host_type host_arch host_arch_path) - set(base_path "${CMAKE_BINARY_DIR}/externals/qt") + get_external_prefix(qt base_path) file(MAKE_DIRECTORY "${base_path}") download_qt_configuration(prefix "${target}" "${host}" "${type}" "${arch}" "${arch_path}" "${base_path}") @@ -238,34 +227,26 @@ function(download_qt target) set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() -function(download_moltenvk version platform) - if(NOT version) - message(FATAL_ERROR "download_moltenvk: version argument is required") - endif() - if(NOT platform) - message(FATAL_ERROR "download_moltenvk: platform argument is required") - endif() +function(download_moltenvk) +set(MOLTENVK_PLATFORM "macOS") - set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") - set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") +set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK") +set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar") +if (NOT EXISTS ${MOLTENVK_DIR}) +if (NOT EXISTS ${MOLTENVK_TAR}) + file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.10-rc2/MoltenVK-all.tar + ${MOLTENVK_TAR} SHOW_PROGRESS) +endif() - if(NOT EXISTS "${MOLTENVK_DIR}") - if(NOT EXISTS "${MOLTENVK_TAR}") - file(DOWNLOAD "https://github.com/KhronosGroup/MoltenVK/releases/download/${version}/MoltenVK-${platform}.tar" - "${MOLTENVK_TAR}" SHOW_PROGRESS) - endif() +execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals") +endif() - execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals" - RESULT_VARIABLE tar_res - ERROR_VARIABLE tar_err - ) - if(NOT tar_res EQUAL 0) - message(FATAL_ERROR "Extracting MoltenVK failed: ${tar_err}") - endif() - endif() - list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${platform}") - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) +# Add the MoltenVK library path to the prefix so find_library can locate it. +list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${MOLTENVK_PLATFORM}") +set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) endfunction() +function(get_external_prefix lib_name prefix_var) + set(${prefix_var} "${CMAKE_BINARY_DIR}/externals/${lib_name}" PARENT_SCOPE) +endfunction() 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/cpmfile.json b/cpmfile.json index 4cf61f0ffc..f1fd5ce1cf 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -4,11 +4,8 @@ "package": "OpenSSL", "name": "openssl", "repo": "crueter-ci/OpenSSL", - "version": "3.6.0", - "min_version": "1.1.1", - "disabled_platforms": [ - "macos-universal" - ] + "version": "3.5.3", + "min_version": "1.1.1" }, "boost": { "package": "Boost", @@ -69,6 +66,20 @@ "ZSTD_BUILD_SHARED OFF" ] }, + "catch2": { + "package": "Catch2", + "repo": "catchorg/Catch2", + "sha": "644821ce28", + "hash": "f8795f98acf2c02c0db8e734cc866d5caebab4b4a306e93598b97cb3c0c728dafe8283dce27ffe8d42460e5ae7302f3f32e7e274a7f991b73511ac88eef21b1f", + "version": "3.0.1" + }, + "enet": { + "repo": "lsalzman/enet", + "sha": "2662c0de09", + "hash": "3de1beb4fa3d6b1e03eda8dd1e7580694f854af3ed3975dcdabfdcdf76b97f322b9734d35ea7f185855bb490d957842b938b26da4dd2dfded509390f8d2794dd", + "version": "1.3", + "find_args": "MODULE" + }, "opus": { "package": "Opus", "repo": "crueter/opus", @@ -80,12 +91,97 @@ "OPUS_PRESUME_NEON ON" ] }, + "vulkan-utility-headers": { + "package": "VulkanUtilityLibraries", + "repo": "scripts/VulkanUtilityHeaders", + "tag": "1.4.326", + "artifact": "VulkanUtilityHeaders.tar.zst", + "git_host": "git.crueter.xyz", + "hash": "5924629755cb1605c4aa4eee20ef7957a9dd8d61e4df548be656d98054f2730c4109693c1bd35811f401f4705d2ccff9fc849be32b0d8480bc3f73541a5e0964" + }, + "spirv-tools": { + "package": "SPIRV-Tools", + "repo": "KhronosGroup/SPIRV-Tools", + "sha": "40eb301f32", + "hash": "58d0fb1047d69373cf24c73e6f78c73a72a6cca3b4df1d9f083b9dcc0962745ef154abf3dbe9b3623b835be20c6ec769431cf11733349f45e7568b3525f707aa", + "find_args": "MODULE", + "options": [ + "SPIRV_SKIP_EXECUTABLES ON" + ] + }, + "spirv-headers": { + "package": "SPIRV-Headers", + "repo": "KhronosGroup/SPIRV-Headers", + "sha": "4e209d3d7e", + "hash": "f48bbe18341ed55ea0fe280dbbbc0a44bf222278de6e716e143ca1e95ca320b06d4d23d6583fbf8d03e1428f3dac8fa00e5b82ddcd6b425e6236d85af09550a4", + "options": [ + "SPIRV_WERROR OFF" + ] + }, + "mbedtls": { + "package": "MbedTLS", + "repo": "Mbed-TLS/mbedtls", + "tag": "mbedtls-%VERSION%", + "hash": "6671fb8fcaa832e5b115dfdce8f78baa6a4aea71f5c89a640583634cdee27aefe3bf4be075744da91f7c3ae5ea4e0c765c8fc3937b5cfd9ea73d87ef496524da", + "version": "3", + "git_version": "3.6.4", + "artifact": "%TAG%.tar.bz2" + }, + "cubeb": { + "repo": "mozilla/cubeb", + "sha": "fa02160712", + "hash": "82d808356752e4064de48c8fecbe7856715ade1e76b53937116bf07129fc1cc5b3de5e4b408de3cd000187ba8dc32ca4109661cb7e0355a52e54bd81b9be1c61", + "find_args": "CONFIG", + "options": [ + "USE_SANITIZERS OFF", + "BUILD_TESTS OFF", + "BUILD_TOOLS OFF", + "BUNDLE_SPEEX ON" + ] + }, "boost_headers": { "repo": "boostorg/headers", "sha": "95930ca8f5", "hash": "d1dece16f3b209109de02123c537bfe1adf07a62b16c166367e7e5d62e0f7c323bf804c89b3192dd6871bc58a9d879d25a1cc3f7b9da0e497cf266f165816e2a", "bundled": true }, + "discord-rpc": { + "repo": "eden-emulator/discord-rpc", + "sha": "1cf7772bb6", + "hash": "e9b35e6f2c075823257bcd59f06fe7bb2ccce1976f44818d2e28810435ef79c712a3c4f20f40da41f691342a4058cf86b078eb7f9d9e4dae83c0547c21ec4f97" + }, + "simpleini": { + "package": "SimpleIni", + "repo": "brofield/simpleini", + "sha": "09c21bda1d", + "hash": "99779ca9b6e040d36558cadf484f9ffdab5b47bcc8fc72e4d33639d1d60c0ceb4410d335ba445d72a4324e455167fd6769d99b459943aa135bec085dff2d4b7c", + "find_args": "MODULE" + }, + "sdl2_generic": { + "package": "SDL2", + "repo": "libsdl-org/SDL", + "sha": "54772f345a", + "hash": "2a68a0e01c390043aa9d9df63d8a20a52076c88bb460ac4e0f33194ca7d9bc8fadbbcc04e7506872ac4b6354a73fbc267c036f82200da59465789b87c7d9e3a4", + "key": "generic", + "bundled": true + }, + "sdl2_steamdeck": { + "package": "SDL2", + "repo": "libsdl-org/SDL", + "sha": "cc016b0046", + "hash": "34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b", + "key": "steamdeck", + "bundled": true + }, + "sdl2": { + "ci": true, + "package": "SDL2", + "name": "SDL2", + "repo": "crueter-ci/SDL2", + "version": "2.32.8", + "min_version": "2.26.4", + "cmake_filename": "sdl2" + }, "llvm-mingw": { "repo": "misc/llvm-mingw", "git_host": "git.crueter.xyz", diff --git a/docs/CPM.md b/docs/CPM.md index c01376469d..03d8a039f9 100644 --- a/docs/CPM.md +++ b/docs/CPM.md @@ -108,9 +108,7 @@ All dependencies must be identifiable in some way for usage in the dependency vi URLs: - `GIT_URL` -- `REPO` as a Git repository - * You may optionally specify `GIT_HOST` to use a custom host, e.g. `GIT_HOST git.crueter.xyz`. Note that the git host MUST be GitHub-like in its artifact/archive downloads, e.g. Forgejo - * If `GIT_HOST` is unspecified, defaults to `github.com` +- `REPO` as a GitHub repository - `URL` Versions (bundled): @@ -137,11 +135,11 @@ Adds a package that follows crueter's CI repository spec. * `windows-amd64` * `windows-arm64` * `android` - * `solaris-amd64` - * `freebsd-amd64` - * `linux-amd64` + * `solaris` + * `freebsd` + * `linux` * `linux-aarch64` - * `macos-universal` +- `CMAKE_FILENAME`: Custom CMake filename, relative to the package root (default `${PACKAGE_ROOT}/${NAME}.cmake`) ### AddJsonPackage @@ -157,17 +155,10 @@ The cpmfile is an object of objects, with each sub-object being named according If `ci` is `false`: - `hash` -> `HASH` -- `hash_suffix` -> `HASH_SUFFIX` - `sha` -> `SHA` -- `key` -> `KEY` - `tag` -> `TAG` - * If the tag contains `%VERSION%`, that part will be replaced by the `git_version`, OR `version` if `git_version` is not specified -- `url` -> `URL` - `artifact` -> `ARTIFACT` - * If the artifact contains `%VERSION%`, that part will be replaced by the `git_version`, OR `version` if `git_version` is not specified - * If the artifact contains `%TAG%`, that part will be replaced by the `tag` (with its replacement already done) - `git_version` -> `GIT_VERSION` -- `git_host` -> `GIT_HOST` - `source_subdir` -> `SOURCE_SUBDIR` - `bundled` -> `BUNDLED_PACKAGE` - `find_args` -> `FIND_PACKAGE_ARGUMENTS` @@ -181,6 +172,7 @@ If `ci` is `true`: - `name` -> `NAME`, defaults to the object key - `extension` -> `EXTENSION`, defaults to `tar.zst` - `min_version` -> `MIN_VERSION` +- `cmake_filename` -> `CMAKE_FILENAME` - `extension` -> `EXTENSION` ### Examples @@ -200,8 +192,8 @@ In order: OpenSSL CI, Boost (tag + artifact), Opus (options + find_args), discor "boost": { "package": "Boost", "repo": "boostorg/boost", - "tag": "boost-%VERSION%", - "artifact": "%TAG%-cmake.7z", + "tag": "boost-1.88.0", + "artifact": "boost-1.88.0-cmake.7z", "hash": "e5b049e5b61964480ca816395f63f95621e66cb9bcf616a8b10e441e0e69f129e22443acb11e77bc1e8170f8e4171b9b7719891efc43699782bfcd4b3a365f01", "git_version": "1.88.0", "version": "1.57" diff --git a/docs/Deps.md b/docs/Deps.md index 573d1fe14a..cfc6f0365b 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -4,8 +4,8 @@ To build Eden, you MUST have a C++ compiler. * On Linux, this is usually [GCC](https://gcc.gnu.org/) 11+ or [Clang](https://clang.llvm.org/) v14+ - GCC 12 also requires Clang 14+ * On Windows, this is either: - - **[MSVC](https://visualstudio.microsoft.com/downloads/)** (you should select *Community* option), - * *A convenience script to install the Visual Community Studio 2022 with necessary tools is provided in `.ci/windows/install-msvc.ps1`* + - **[MSVC](https://visualstudio.microsoft.com/downloads/)**, + * *A convenience script to install the **minimal** version (Visual Build Tools) is provided in `.ci/windows/install-msvc.ps1`* - clang-cl - can be downloaded from the MSVC installer, - or **[MSYS2](https://www.msys2.org)** * On macOS, this is Apple Clang @@ -101,7 +101,7 @@ sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glsl Ubuntu, Debian, Mint Linux ```sh -sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2t64 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev libzydis-dev zydis-tools libzycore-dev vulkan-utility-libraries-dev libvulkan-dev spirv-tools spirv-headers libusb-1.0-0-dev libxbyak-dev +sudo apt-get install autoconf cmake g++ gcc git glslang-tools libasound2 libboost-context-dev libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev libzydis-dev zydis-tools libzycore-dev ``` * Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required. @@ -211,4 +211,4 @@ Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/l ## All Done -You may now return to the **[root build guide](Build.md)**. +You may now return to the **[root build guide](Build.md)**. \ No newline at end of file diff --git a/docs/Development.md b/docs/Development.md index c223409243..1ed75a7c23 100644 --- a/docs/Development.md +++ b/docs/Development.md @@ -36,28 +36,6 @@ Pull requests are only to be merged by core developers when properly tested and - Maintainers are permitted to change namespaces at will. - Commits within PRs are not required to be namespaced, but it is highly recommended. -## Adding new settings - -When adding new settings, use `tr("Setting:")` if the setting is meant to be a field, otherwise use `tr("Setting")` if the setting is meant to be a Yes/No or checkmark type of setting, see [this short style guide](https://learn.microsoft.com/en-us/style-guide/punctuation/colons#in-ui). - -- The majority of software must work with the default option selected for such setting. Unless the setting significantly degrades performance. -- Debug settings must never be turned on by default. -- Provide reasonable bounds (for example, a setting controlling the amount of VRAM should never be 0). -- The description of the setting must be short and concise, if the setting "does a lot of things" consider splitting the setting into multiple if possible. -- Try to avoid excessive/redundant explainations "recommended for most users and games" can just be "(recommended)". -- Try to not write "slow/fast" options unless it clearly degrades/increases performance for a given case, as most options may modify behaviour that result in different metrics accross different systems. If for example the option is an "accuracy" option, writing "High" is sufficient to imply "Slow". No need to write "High (Slow)". - -Some examples: -- "[...] negatively affecting image quality", "[...] degrading image quality": Same wording but with less filler. -- "[...] this may cause some glitches or crashes in some games", "[...] this may cause soft-crashes": Crashes implies there may be glitches (as crashes are technically a form of a fatal glitch). The entire sentence is structured as "may cause [...] on some games", which is redundant, because "may cause [...] in games" has the same semantic meaning ("may" is a chance that it will occur on "some" given set). -- "FIFO Relaxed is similar to FIFO [...]", "FIFO Relaxed [...]": The name already implies similarity. -- "[...] but may also reduce performance in some cases", "[...] but may degrade performance": Again, "some cases" and "may" implies there is a probability. -- "[...] it can [...] in some cases", "[...] it can [...]": Implied probability. - -Before adding a new setting, consider: -- Does the piece of code that the setting pertains to, make a significant difference if it's on/off? -- Can it be auto-detected? - # IDE setup ## VSCode diff --git a/docs/Options.md b/docs/Options.md index 3dd84ea645..d19aab63f6 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) +- `USE_SYSTEM_MOLTENVK` (OFF, macOS only) Use the system MoltenVK lib (instead of the bundled one) - `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/externals/CMakeLists.txt b/externals/CMakeLists.txt index f22b8753f8..754ba61a0b 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -39,144 +39,6 @@ if (ARCHITECTURE_arm64 OR DYNARMIC_TESTS) AddJsonPackage(oaknut) endif() -# enet -AddJsonPackage(enet) - -if (enet_ADDED) - target_include_directories(enet INTERFACE ${enet_SOURCE_DIR}/include) -endif() - -if (NOT TARGET enet::enet) - add_library(enet::enet ALIAS enet) -endif() - -# mbedtls -AddJsonPackage(mbedtls) - -# VulkanUtilityHeaders - pulls in headers and utility libs -AddJsonPackage(vulkan-utility-headers) - -# small hack -if (NOT VulkanUtilityLibraries_ADDED) - find_package(VulkanHeaders 1.3.274 REQUIRED) -endif() - -# DiscordRPC -if (USE_DISCORD_PRESENCE) - if (ARCHITECTURE_arm64) - add_compile_definitions(RAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN) - endif() - - AddJsonPackage(discord-rpc) - - if (DiscordRPC_ADDED) - target_include_directories(discord-rpc INTERFACE ${DiscordRPC_SOURCE_DIR}/include) - add_library(DiscordRPC::discord-rpc ALIAS discord-rpc) - endif() -endif() - -# SimpleIni -AddJsonPackage(simpleini) - -# Most linux distros don't package cubeb, so enable regardless of cpm settings -if(ENABLE_CUBEB) - AddJsonPackage(cubeb) - - if (cubeb_ADDED) - if (NOT MSVC) - if (TARGET speex) - target_compile_options(speex PRIVATE -Wno-sign-compare) - endif() - - set_target_properties(cubeb PROPERTIES COMPILE_OPTIONS "") - target_compile_options(cubeb INTERFACE - -Wno-implicit-const-int-float-conversion - -Wno-shadow - -Wno-missing-declarations - -Wno-return-type - -Wno-uninitialized - ) - else() - target_compile_options(cubeb PRIVATE - /wd4456 - /wd4458 - ) - endif() - endif() - - if (NOT TARGET cubeb::cubeb) - add_library(cubeb::cubeb ALIAS cubeb) - endif() -endif() - -# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package -if (ENABLE_SDL2) - if (YUZU_USE_EXTERNAL_SDL2) - message(STATUS "Using SDL2 from externals.") - if (NOT WIN32) - # Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers - # Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095) - # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) - # CPUinfo also required for SDL Audio, at least until 2.28.0 (see https://github.com/libsdl-org/SDL/issues/7809) - set(SDL_UNUSED_SUBSYSTEMS - File Filesystem - Locale Power Render) - foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) - string(TOUPPER ${_SUB} _OPT) - set(SDL_${_OPT} OFF) - endforeach() - - set(HIDAPI ON) - endif() - - if (APPLE) - set(SDL_FILE ON) - endif() - - if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck") - set(SDL_PIPEWIRE OFF) # build errors out with this on - AddJsonPackage("sdl2_steamdeck") - else() - AddJsonPackage("sdl2_generic") - endif() - elseif (YUZU_USE_BUNDLED_SDL2) - message(STATUS "Using bundled SDL2") - AddJsonPackage(sdl2) - endif() - - find_package(SDL2 2.26.4 REQUIRED) -endif() - -# SPIRV Headers -# We only need SPIRV-Headers iff spirv-tools is bundled -if (SPIRV-Tools_FORCE_BUNDLED OR CPMUTIL_FORCE_BUNDLED) - set(NEED_SPIRV_HEADERS ON) -else() - find_package(SPIRV-Tools MODULE QUIET) - if (NOT SPIRV-Tools_FOUND) - set(NEED_SPIRV_HEADERS ON) - else() - set(NEED_SPIRV_HEADERS OFF) - endif() -endif() - -if (NEED_SPIRV_HEADERS) - AddJsonPackage(spirv-headers) -endif() - -# SPIRV Tools -AddJsonPackage(spirv-tools) - -if (SPIRV-Tools_ADDED) - add_library(SPIRV-Tools::SPIRV-Tools ALIAS SPIRV-Tools-static) - target_link_libraries(SPIRV-Tools-static PRIVATE SPIRV-Tools-opt SPIRV-Tools-link) -endif() - -# Catch2 -if (YUZU_TESTS OR DYNARMIC_TESTS) - AddJsonPackage(catch2) -endif() - # getopt if (MSVC) add_subdirectory(getopt) @@ -206,18 +68,15 @@ if (VulkanMemoryAllocator_ADDED) endif() # Sirit -if (YUZU_USE_BUNDLED_SIRIT) - AddJsonPackage(sirit-ci) -else() - AddJsonPackage(sirit) - if(MSVC AND USE_CCACHE AND sirit_ADDED) - get_target_property(_opts sirit COMPILE_OPTIONS) - list(FILTER _opts EXCLUDE REGEX "/Zi") - list(APPEND _opts "/Z7") - set_target_properties(siritobj PROPERTIES COMPILE_OPTIONS "${_opts}") - elseif(MSVC AND CXX_CLANG) - target_compile_options(siritobj PRIVATE -Wno-error=unused-command-line-argument) - endif() +AddJsonPackage(sirit) + +if(MSVC AND USE_CCACHE AND sirit_ADDED) + get_target_property(_opts sirit COMPILE_OPTIONS) + list(FILTER _opts EXCLUDE REGEX "/Zi") + list(APPEND _opts "/Z7") + set_target_properties(sirit PROPERTIES COMPILE_OPTIONS "${_opts}") +elseif(MSVC AND CXX_CLANG) + target_compile_options(sirit PRIVATE -Wno-error=unused-command-line-argument) endif() # httplib diff --git a/externals/cpmfile.json b/externals/cpmfile.json index cb32a75ed5..dcafc8f97d 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -8,18 +8,12 @@ }, "sirit": { "repo": "eden-emulator/sirit", - "version": "1.0.1", - "tag": "v%VERSION%", - "artifact": "sirit-source-%VERSION%.tar.zst", - "hash_suffix": "sha512sum", - "find_args": "CONFIG" - }, - "sirit-ci": { - "ci": true, - "package": "sirit", - "name": "sirit", - "repo": "eden-emulator/sirit", - "version": "1.0.0" + "sha": "db1f1e8ab5", + "hash": "73eb3a042848c63a10656545797e85f40d142009dfb7827384548a385e1e28e1ac72f42b25924ce530d58275f8638554281e884d72f9c7aaf4ed08690a414b05", + "find_args": "CONFIG", + "options": [ + "SIRIT_USE_SYSTEM_SPIRV_HEADERS ON" + ] }, "httplib": { "repo": "yhirose/cpp-httplib", @@ -76,107 +70,5 @@ "sha": "73f3cbb237", "hash": "c08c03063938339d61392b687562909c1a92615b6ef39ec8df19ea472aa6b6478e70d7d5e33d4a27b5d23f7806daf57fe1bacb8124c8a945c918c7663a9e8532", "find_args": "CONFIG" - }, - "mbedtls": { - "package": "MbedTLS", - "repo": "Mbed-TLS/mbedtls", - "tag": "mbedtls-%VERSION%", - "hash": "6671fb8fcaa832e5b115dfdce8f78baa6a4aea71f5c89a640583634cdee27aefe3bf4be075744da91f7c3ae5ea4e0c765c8fc3937b5cfd9ea73d87ef496524da", - "version": "3", - "git_version": "3.6.4", - "artifact": "%TAG%.tar.bz2" - }, - "enet": { - "repo": "lsalzman/enet", - "sha": "2662c0de09", - "hash": "3de1beb4fa3d6b1e03eda8dd1e7580694f854af3ed3975dcdabfdcdf76b97f322b9734d35ea7f185855bb490d957842b938b26da4dd2dfded509390f8d2794dd", - "version": "1.3", - "find_args": "MODULE" - }, - "vulkan-utility-headers": { - "package": "VulkanUtilityLibraries", - "repo": "scripts/VulkanUtilityHeaders", - "tag": "1.4.326", - "artifact": "VulkanUtilityHeaders.tar.zst", - "git_host": "git.crueter.xyz", - "hash": "5924629755cb1605c4aa4eee20ef7957a9dd8d61e4df548be656d98054f2730c4109693c1bd35811f401f4705d2ccff9fc849be32b0d8480bc3f73541a5e0964" - }, - "spirv-tools": { - "package": "SPIRV-Tools", - "repo": "KhronosGroup/SPIRV-Tools", - "sha": "40eb301f32", - "hash": "58d0fb1047d69373cf24c73e6f78c73a72a6cca3b4df1d9f083b9dcc0962745ef154abf3dbe9b3623b835be20c6ec769431cf11733349f45e7568b3525f707aa", - "find_args": "MODULE", - "options": [ - "SPIRV_SKIP_EXECUTABLES ON" - ] - }, - "spirv-headers": { - "package": "SPIRV-Headers", - "repo": "KhronosGroup/SPIRV-Headers", - "sha": "4e209d3d7e", - "hash": "f48bbe18341ed55ea0fe280dbbbc0a44bf222278de6e716e143ca1e95ca320b06d4d23d6583fbf8d03e1428f3dac8fa00e5b82ddcd6b425e6236d85af09550a4", - "options": [ - "SPIRV_WERROR OFF" - ] - }, - "cubeb": { - "repo": "mozilla/cubeb", - "sha": "fa02160712", - "hash": "82d808356752e4064de48c8fecbe7856715ade1e76b53937116bf07129fc1cc5b3de5e4b408de3cd000187ba8dc32ca4109661cb7e0355a52e54bd81b9be1c61", - "find_args": "CONFIG", - "options": [ - "USE_SANITIZERS OFF", - "BUILD_TESTS OFF", - "BUILD_TOOLS OFF", - "BUNDLE_SPEEX ON" - ] - }, - "discord-rpc": { - "package": "DiscordRPC", - "repo": "eden-emulator/discord-rpc", - "sha": "1cf7772bb6", - "hash": "e9b35e6f2c075823257bcd59f06fe7bb2ccce1976f44818d2e28810435ef79c712a3c4f20f40da41f691342a4058cf86b078eb7f9d9e4dae83c0547c21ec4f97" - }, - "simpleini": { - "package": "SimpleIni", - "repo": "brofield/simpleini", - "sha": "09c21bda1d", - "hash": "99779ca9b6e040d36558cadf484f9ffdab5b47bcc8fc72e4d33639d1d60c0ceb4410d335ba445d72a4324e455167fd6769d99b459943aa135bec085dff2d4b7c", - "find_args": "MODULE" - }, - "sdl2_generic": { - "package": "SDL2", - "repo": "libsdl-org/SDL", - "sha": "54772f345a", - "hash": "2a68a0e01c390043aa9d9df63d8a20a52076c88bb460ac4e0f33194ca7d9bc8fadbbcc04e7506872ac4b6354a73fbc267c036f82200da59465789b87c7d9e3a4", - "key": "generic", - "bundled": true - }, - "sdl2_steamdeck": { - "package": "SDL2", - "repo": "libsdl-org/SDL", - "sha": "cc016b0046", - "hash": "34d5ef58da6a4f9efa6689c82f67badcbd741f5a4f562a9c2c30828fa839830fb07681c5dc6a7851520e261c8405a416ac0a2c2513b51984fb3b4fa4dcb3e20b", - "key": "steamdeck", - "bundled": true - }, - "sdl2": { - "ci": true, - "package": "SDL2", - "name": "SDL2", - "repo": "crueter-ci/SDL2", - "version": "2.32.10", - "min_version": "2.26.4", - "disabled_platforms": [ - "macos-universal" - ] - }, - "catch2": { - "package": "Catch2", - "repo": "catchorg/Catch2", - "sha": "644821ce28", - "hash": "f8795f98acf2c02c0db8e734cc866d5caebab4b4a306e93598b97cb3c0c728dafe8283dce27ffe8d42460e5ae7302f3f32e7e274a7f991b73511ac88eef21b1f", - "version": "3.0.1" } } diff --git a/externals/ffmpeg/cpmfile.json b/externals/ffmpeg/cpmfile.json index ff48ce742d..9b9efaadde 100644 --- a/externals/ffmpeg/cpmfile.json +++ b/externals/ffmpeg/cpmfile.json @@ -13,9 +13,8 @@ "version": "8.0", "min_version": "4.1", "disabled_platforms": [ - "freebsd-amd64", - "solaris-amd64", - "macos-universal" + "freebsd", + "solaris" ] } } 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/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index da40453497..2046af42c8 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt @@ -68,9 +68,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { var isActivityRecreated = false private lateinit var nfcReader: NfcReader - private var touchDownTime: Long = 0 - private val maxTapDuration = 500L - private val gyro = FloatArray(3) private val accel = FloatArray(3) private var motionTimestamp: Long = 0 @@ -492,38 +489,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { } } - override fun dispatchTouchEvent(event: MotionEvent): Boolean { - val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment - val emulationFragment = navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment - - emulationFragment?.let { fragment -> - when (event.action) { - MotionEvent.ACTION_DOWN -> { - touchDownTime = System.currentTimeMillis() - // show overlay immediately on touch and cancel timer - if (!emulationViewModel.drawerOpen.value) { - fragment.handler.removeCallbacksAndMessages(null) - fragment.showOverlay() - } - } - MotionEvent.ACTION_UP -> { - if (!emulationViewModel.drawerOpen.value) { - val touchDuration = System.currentTimeMillis() - touchDownTime - - if (touchDuration <= maxTapDuration) { - fragment.handleScreenTap(false) - } else { - // just start the auto-hide timer without toggling visibility - fragment.handleScreenTap(true) - } - } - } - } - } - - return super.dispatchTouchEvent(event) - } - fun onEmulationStarted() { emulationViewModel.setEmulationStarted(true) } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 638e1101db..3c5b9003de 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -55,8 +55,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { FRAME_INTERPOLATION("frame_interpolation"), // FRAME_SKIPPING("frame_skipping"), - ENABLE_INPUT_OVERLAY_AUTO_HIDE("enable_input_overlay_auto_hide"), - PERF_OVERLAY_BACKGROUND("perf_overlay_background"), SHOW_PERFORMANCE_OVERLAY("show_performance_overlay"), diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt index d5556a337b..21aad8b5d1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt @@ -59,8 +59,7 @@ enum class IntSetting(override val key: String) : AbstractIntSetting { OFFLINE_WEB_APPLET("offline_web_applet_mode"), LOGIN_SHARE_APPLET("login_share_applet_mode"), WIFI_WEB_AUTH_APPLET("wifi_web_auth_applet_mode"), - MY_PAGE_APPLET("my_page_applet_mode"), - INPUT_OVERLAY_AUTO_HIDE("input_overlay_auto_hide") + MY_PAGE_APPLET("my_page_applet_mode") ; override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index 454d0e4807..a52f582031 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt @@ -12,7 +12,6 @@ object Settings { SECTION_SYSTEM(R.string.preferences_system), SECTION_RENDERER(R.string.preferences_graphics), SECTION_PERFORMANCE_STATS(R.string.stats_overlay_options), - SECTION_INPUT_OVERLAY(R.string.input_overlay_options), SECTION_SOC_OVERLAY(R.string.soc_overlay_options), SECTION_AUDIO(R.string.preferences_audio), SECTION_INPUT(R.string.preferences_controls), diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 5f7f7a43f9..1f2ba81a73 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -96,7 +96,6 @@ abstract class SettingsItem( const val TYPE_INT_SINGLE_CHOICE = 9 const val TYPE_INPUT_PROFILE = 10 const val TYPE_STRING_INPUT = 11 - const val TYPE_SPINBOX = 12 const val FASTMEM_COMBINED = "fastmem_combined" @@ -386,22 +385,6 @@ abstract class SettingsItem( warningMessage = R.string.warning_resolution ) ) - put( - SwitchSetting( - BooleanSetting.ENABLE_INPUT_OVERLAY_AUTO_HIDE, - titleId = R.string.enable_input_overlay_auto_hide, - ) - ) - put( - SpinBoxSetting( - IntSetting.INPUT_OVERLAY_AUTO_HIDE, - titleId = R.string.overlay_auto_hide, - descriptionId = R.string.overlay_auto_hide_description, - min = 1, - max = 999, - valueHint = R.string.seconds - ) - ) put( SwitchSetting( diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SpinBoxSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SpinBoxSetting.kt deleted file mode 100644 index 0b0d01dfe0..0000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SpinBoxSetting.kt +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -package org.yuzu.yuzu_emu.features.settings.model.view - -import androidx.annotation.StringRes -import org.yuzu.yuzu_emu.features.settings.model.AbstractByteSetting -import org.yuzu.yuzu_emu.features.settings.model.AbstractFloatSetting -import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting -import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting -import org.yuzu.yuzu_emu.features.settings.model.AbstractShortSetting - -class SpinBoxSetting( - setting: AbstractSetting, - @StringRes titleId: Int = 0, - titleString: String = "", - @StringRes descriptionId: Int = 0, - descriptionString: String = "", - val valueHint: Int, - val min: Int, - val max: Int -) : SettingsItem(setting, titleId, titleString, descriptionId, descriptionString) { - override val type = TYPE_SPINBOX - - fun getSelectedValue(needsGlobal: Boolean = false) = - when (setting) { - is AbstractByteSetting -> setting.getByte(needsGlobal).toInt() - is AbstractShortSetting -> setting.getShort(needsGlobal).toInt() - is AbstractIntSetting -> setting.getInt(needsGlobal) - is AbstractFloatSetting -> setting.getFloat(needsGlobal).toInt() - else -> 0 - } - - fun setSelectedValue(value: Int) = - when (setting) { - is AbstractByteSetting -> setting.setByte(value.toByte()) - is AbstractShortSetting -> setting.setShort(value.toShort()) - is AbstractFloatSetting -> setting.setFloat(value.toFloat()) - else -> (setting as AbstractIntSetting).setInt(value) - } -} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt index bdc51b7070..500ac6e66e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later package org.yuzu.yuzu_emu.features.settings.ui @@ -61,10 +61,6 @@ class SettingsAdapter( SliderViewHolder(ListItemSettingBinding.inflate(inflater), this) } - SettingsItem.TYPE_SPINBOX -> { - SpinBoxViewHolder(ListItemSettingBinding.inflate(inflater), this) - } - SettingsItem.TYPE_SUBMENU -> { SubmenuViewHolder(ListItemSettingBinding.inflate(inflater), this) } @@ -195,14 +191,6 @@ class SettingsAdapter( position ).show(fragment.childFragmentManager, SettingsDialogFragment.TAG) } - fun onSpinBoxClick(item: SpinBoxSetting, position: Int) { - SettingsDialogFragment.newInstance( - settingsViewModel, - item, - SettingsItem.TYPE_SPINBOX, - position - ).show(fragment.childFragmentManager, SettingsDialogFragment.TAG) - } fun onSubmenuClick(item: SubmenuSetting) { val action = SettingsNavigationDirections.actionGlobalSettingsFragment(item.menuKey, null) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt index 2a97f15892..dc9f561eca 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt @@ -14,7 +14,6 @@ import android.text.TextWatcher import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels @@ -23,7 +22,6 @@ import com.google.android.material.slider.Slider import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.databinding.DialogEditTextBinding import org.yuzu.yuzu_emu.databinding.DialogSliderBinding -import org.yuzu.yuzu_emu.databinding.DialogSpinboxBinding import org.yuzu.yuzu_emu.features.input.NativeInput import org.yuzu.yuzu_emu.features.input.model.AnalogDirection import org.yuzu.yuzu_emu.features.settings.model.view.AnalogInputSetting @@ -32,7 +30,6 @@ import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting -import org.yuzu.yuzu_emu.features.settings.model.view.SpinBoxSetting import org.yuzu.yuzu_emu.features.settings.model.view.StringInputSetting import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting import org.yuzu.yuzu_emu.utils.ParamPackage @@ -49,7 +46,6 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener private lateinit var sliderBinding: DialogSliderBinding private lateinit var stringInputBinding: DialogEditTextBinding - private lateinit var spinboxBinding: DialogSpinboxBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -146,76 +142,6 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener .create() } - SettingsItem.TYPE_SPINBOX -> { - spinboxBinding = DialogSpinboxBinding.inflate(layoutInflater) - val item = settingsViewModel.clickedItem as SpinBoxSetting - - val currentValue = item.getSelectedValue() - spinboxBinding.editValue.setText(currentValue.toString()) - spinboxBinding.textInputLayout.hint = getString(item.valueHint) - - val dialog = MaterialAlertDialogBuilder(requireContext()) - .setTitle(item.title) - .setView(spinboxBinding.root) - .setPositiveButton(android.R.string.ok, this) - .setNegativeButton(android.R.string.cancel, defaultCancelListener) - .create() - - val updateButtonState = { enabled: Boolean -> - dialog.setOnShowListener { dialogInterface -> - (dialogInterface as AlertDialog).getButton(DialogInterface.BUTTON_POSITIVE)?.isEnabled = enabled - } - if (dialog.isShowing) { - dialog.getButton(DialogInterface.BUTTON_POSITIVE)?.isEnabled = enabled - } - } - - val updateValidity = { value: Int -> - val isValid = value in item.min..item.max - if (isValid) { - spinboxBinding.textInputLayout.error = null - } else { - spinboxBinding.textInputLayout.error = getString( - if (value < item.min) R.string.value_too_low else R.string.value_too_high, - if (value < item.min) item.min else item.max - ) - } - updateButtonState(isValid) - } - - spinboxBinding.buttonDecrement.setOnClickListener { - val current = spinboxBinding.editValue.text.toString().toIntOrNull() ?: currentValue - val newValue = current - 1 - spinboxBinding.editValue.setText(newValue.toString()) - updateValidity(newValue) - } - - spinboxBinding.buttonIncrement.setOnClickListener { - val current = spinboxBinding.editValue.text.toString().toIntOrNull() ?: currentValue - val newValue = current + 1 - spinboxBinding.editValue.setText(newValue.toString()) - updateValidity(newValue) - } - - spinboxBinding.editValue.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} - override fun afterTextChanged(s: Editable?) { - val value = s.toString().toIntOrNull() - if (value != null) { - updateValidity(value) - } else { - spinboxBinding.textInputLayout.error = getString(R.string.invalid_value) - updateButtonState(false) - } - } - }) - - updateValidity(currentValue) - - dialog - } - SettingsItem.TYPE_STRING_INPUT -> { stringInputBinding = DialogEditTextBinding.inflate(layoutInflater) val item = settingsViewModel.clickedItem as StringInputSetting @@ -355,14 +281,6 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener sliderSetting.setSelectedValue(settingsViewModel.sliderProgress.value) } - is SpinBoxSetting -> { - val spinBoxSetting = settingsViewModel.clickedItem as SpinBoxSetting - val value = spinboxBinding.editValue.text.toString().toIntOrNull() - if (value != null && value in spinBoxSetting.min..spinBoxSetting.max) { - spinBoxSetting.setSelectedValue(value) - } - } - is StringInputSetting -> { val stringInputSetting = settingsViewModel.clickedItem as StringInputSetting stringInputSetting.setSelectedValue( diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 715baec72f..14d62ceec3 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -97,7 +97,6 @@ class SettingsFragmentPresenter( MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl) MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl) MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl) - MenuTag.SECTION_INPUT_OVERLAY -> addInputOverlaySettings(sl) MenuTag.SECTION_AUDIO -> addAudioSettings(sl) MenuTag.SECTION_INPUT -> addInputSettings(sl) MenuTag.SECTION_INPUT_PLAYER_ONE -> addInputPlayer(sl, 0) @@ -157,14 +156,6 @@ class SettingsFragmentPresenter( menuKey = MenuTag.SECTION_SOC_OVERLAY ) ) - add( - SubmenuSetting( - titleId = R.string.input_overlay_options, - iconId = R.drawable.ic_controller, - descriptionId = R.string.input_overlay_options_description, - menuKey = MenuTag.SECTION_INPUT_OVERLAY - ) - ) } add( SubmenuSetting( @@ -273,13 +264,6 @@ class SettingsFragmentPresenter( } } - private fun addInputOverlaySettings(sl: ArrayList) { - sl.apply { - add(BooleanSetting.ENABLE_INPUT_OVERLAY_AUTO_HIDE.key) - add(IntSetting.INPUT_OVERLAY_AUTO_HIDE.key) - } - } - private fun addSocOverlaySettings(sl: ArrayList) { sl.apply { add(HeaderSetting(R.string.stats_overlay_customization)) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SpinBoxViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SpinBoxViewHolder.kt deleted file mode 100644 index 1f9a16b798..0000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SpinBoxViewHolder.kt +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -package org.yuzu.yuzu_emu.features.settings.ui.viewholder - -import android.view.View -import org.yuzu.yuzu_emu.R -import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding -import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem -import org.yuzu.yuzu_emu.features.settings.model.view.SpinBoxSetting -import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible - -class SpinBoxViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : - SettingViewHolder(binding.root, adapter) { - private lateinit var setting: SpinBoxSetting - - override fun bind(item: SettingsItem) { - setting = item as SpinBoxSetting - binding.textSettingName.text = setting.title - binding.textSettingDescription.setVisible(item.description.isNotEmpty()) - binding.textSettingDescription.text = setting.description - binding.textSettingValue.setVisible(true) - binding.textSettingValue.text = setting.getSelectedValue().toString() - - binding.buttonClear.setVisible(setting.clearable) - binding.buttonClear.setOnClickListener { - adapter.onClearClick(setting, bindingAdapterPosition) - } - - setStyle(setting.isEditable, binding) - } - override fun onClick(clicked: View) { - if (setting.isEditable) { - adapter.onSpinBoxClick(setting, bindingAdapterPosition) - } - } - override fun onLongClick(clicked: View): Boolean { - if (setting.isEditable) { - return adapter.onLongClick(setting, bindingAdapterPosition) - } - return false - } -} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index b2d6135372..8162098caa 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -96,9 +96,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { private var perfStatsUpdater: (() -> Unit)? = null private var socUpdater: (() -> Unit)? = null - val handler = Handler(Looper.getMainLooper()) - private var isOverlayVisible = true - private var _binding: FragmentEmulationBinding? = null private val binding get() = _binding!! @@ -455,10 +452,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { /** * Ask user if they want to launch with default settings when custom settings fail */ - private suspend fun askUserToLaunchWithDefaultSettings( - gameTitle: String, - errorMessage: String - ): Boolean { + private suspend fun askUserToLaunchWithDefaultSettings(gameTitle: String, errorMessage: String): Boolean { return suspendCoroutine { continuation -> requireActivity().runOnUiThread { MaterialAlertDialogBuilder(requireContext()) @@ -734,8 +728,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { updateShowStatsOverlay() updateSocOverlay() - initializeOverlayAutoHide() - // Re update binding when the specs values get initialized properly binding.inGameMenu.getHeaderView(0).apply { val titleView = findViewById(R.id.text_game_title) @@ -925,11 +917,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { updatePauseMenuEntry(emulationState.isPaused) } } - - // if the overlay auto-hide setting is changed while paused, - // we need to reinitialize the auto-hide timer - initializeOverlayAutoHide() - } private fun resetInputOverlay() { @@ -937,7 +924,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { IntSetting.OVERLAY_OPACITY.reset() binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.resetLayoutVisibilityAndPlacement() - binding.surfaceInputOverlay.resetIndividualControlScale() } } @@ -1048,7 +1034,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { val status = batteryIntent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || - status == BatteryManager.BATTERY_STATUS_FULL + status == BatteryManager.BATTERY_STATUS_FULL if (isCharging) { sb.append(" ${getString(R.string.charging)}") @@ -1560,7 +1546,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { .setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int -> setControlScale(50) setControlOpacity(100) - binding.surfaceInputOverlay.resetIndividualControlScale() } .show() } @@ -1741,61 +1726,4 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!) private val socUpdateHandler = Handler(Looper.myLooper()!!) } - - private fun startOverlayAutoHideTimer(seconds: Int) { - handler.removeCallbacksAndMessages(null) - - handler.postDelayed({ - if (isOverlayVisible) { - hideOverlay() - } - }, seconds * 1000L) - } - - fun handleScreenTap(isLongTap: Boolean) { - val autoHideSeconds = IntSetting.INPUT_OVERLAY_AUTO_HIDE.getInt() - val shouldProceed = BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean() && BooleanSetting.ENABLE_INPUT_OVERLAY_AUTO_HIDE.getBoolean() - - if (!shouldProceed) { - return - } - - // failsafe - if (autoHideSeconds == 0) { - showOverlay() - return - } - - if (!isOverlayVisible && !isLongTap) { - showOverlay() - } - - startOverlayAutoHideTimer(autoHideSeconds) - } - - private fun initializeOverlayAutoHide() { - val autoHideSeconds = IntSetting.INPUT_OVERLAY_AUTO_HIDE.getInt() - val autoHideEnabled = BooleanSetting.ENABLE_INPUT_OVERLAY_AUTO_HIDE.getBoolean() - val showOverlay = BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean() - - if (autoHideEnabled && showOverlay) { - showOverlay() - startOverlayAutoHideTimer(autoHideSeconds) - } - } - - - fun showOverlay() { - if (!isOverlayVisible) { - isOverlayVisible = true - ViewUtils.showView(binding.surfaceInputOverlay, 500) - } - } - - private fun hideOverlay() { - if (isOverlayVisible) { - isOverlayVisible = false - ViewUtils.hideView(binding.surfaceInputOverlay, 500) - } - } -} +} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt index 9f050a5053..737e035840 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later package org.yuzu.yuzu_emu.overlay @@ -13,8 +13,6 @@ import android.graphics.Rect import android.graphics.drawable.Drawable import android.graphics.drawable.VectorDrawable import android.os.Build -import android.os.Handler -import android.os.Looper import android.util.AttributeSet import android.view.HapticFeedbackConstants import android.view.MotionEvent @@ -54,12 +52,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : private var dpadBeingConfigured: InputOverlayDrawableDpad? = null private var joystickBeingConfigured: InputOverlayDrawableJoystick? = null - private var scaleDialog: OverlayScaleDialog? = null - private var touchStartX = 0f - private var touchStartY = 0f - private var hasMoved = false - private val moveThreshold = 20f - private lateinit var windowInsets: WindowInsets var layout = OverlayLayout.Landscape @@ -262,44 +254,23 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : ) { buttonBeingConfigured = button buttonBeingConfigured!!.onConfigureTouch(event) - touchStartX = event.getX(pointerIndex) - touchStartY = event.getY(pointerIndex) - hasMoved = false } MotionEvent.ACTION_MOVE -> if (buttonBeingConfigured != null) { - val moveDistance = kotlin.math.sqrt( - (event.getX(pointerIndex) - touchStartX).let { it * it } + - (event.getY(pointerIndex) - touchStartY).let { it * it } - ) - - if (moveDistance > moveThreshold) { - hasMoved = true - buttonBeingConfigured!!.onConfigureTouch(event) - invalidate() - return true - } + buttonBeingConfigured!!.onConfigureTouch(event) + invalidate() + return true } MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) { - if (!hasMoved) { - showScaleDialog( - buttonBeingConfigured, - null, - null, - fingerPositionX, - fingerPositionY - ) - } else { - saveControlPosition( - buttonBeingConfigured!!.overlayControlData.id, - buttonBeingConfigured!!.bounds.centerX(), - buttonBeingConfigured!!.bounds.centerY(), - individuaScale = buttonBeingConfigured!!.overlayControlData.individualScale, - layout - ) - } + // Persist button position by saving new place. + saveControlPosition( + buttonBeingConfigured!!.overlayControlData.id, + buttonBeingConfigured!!.bounds.centerX(), + buttonBeingConfigured!!.bounds.centerY(), + layout + ) buttonBeingConfigured = null } } @@ -316,46 +287,23 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : ) { dpadBeingConfigured = dpad dpadBeingConfigured!!.onConfigureTouch(event) - touchStartX = event.getX(pointerIndex) - touchStartY = event.getY(pointerIndex) - hasMoved = false } MotionEvent.ACTION_MOVE -> if (dpadBeingConfigured != null) { - val moveDistance = kotlin.math.sqrt( - (event.getX(pointerIndex) - touchStartX).let { it * it } + - (event.getY(pointerIndex) - touchStartY).let { it * it } - ) - - if (moveDistance > moveThreshold) { - hasMoved = true - dpadBeingConfigured!!.onConfigureTouch(event) - invalidate() - return true - } + dpadBeingConfigured!!.onConfigureTouch(event) + invalidate() + return true } MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> if (dpadBeingConfigured === dpad) { - if (!hasMoved) { - // This was a click, show scale dialog for dpad - showScaleDialog( - null, - dpadBeingConfigured, - null, - fingerPositionX, - fingerPositionY - ) - } else { - // This was a move, save position - saveControlPosition( - OverlayControl.COMBINED_DPAD.id, - dpadBeingConfigured!!.bounds.centerX(), - dpadBeingConfigured!!.bounds.centerY(), - individuaScale = dpadBeingConfigured!!.individualScale, - layout - ) - } + // Persist button position by saving new place. + saveControlPosition( + OverlayControl.COMBINED_DPAD.id, + dpadBeingConfigured!!.bounds.centerX(), + dpadBeingConfigured!!.bounds.centerY(), + layout + ) dpadBeingConfigured = null } } @@ -369,43 +317,21 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : ) { joystickBeingConfigured = joystick joystickBeingConfigured!!.onConfigureTouch(event) - touchStartX = event.getX(pointerIndex) - touchStartY = event.getY(pointerIndex) - hasMoved = false } MotionEvent.ACTION_MOVE -> if (joystickBeingConfigured != null) { - val moveDistance = kotlin.math.sqrt( - (event.getX(pointerIndex) - touchStartX).let { it * it } + - (event.getY(pointerIndex) - touchStartY).let { it * it } - ) - - if (moveDistance > moveThreshold) { - hasMoved = true - joystickBeingConfigured!!.onConfigureTouch(event) - invalidate() - } + joystickBeingConfigured!!.onConfigureTouch(event) + invalidate() } MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP -> if (joystickBeingConfigured != null) { - if (!hasMoved) { - showScaleDialog( - null, - null, - joystickBeingConfigured, - fingerPositionX, - fingerPositionY - ) - } else { - saveControlPosition( - joystickBeingConfigured!!.prefId, - joystickBeingConfigured!!.bounds.centerX(), - joystickBeingConfigured!!.bounds.centerY(), - individuaScale = joystickBeingConfigured!!.individualScale, - layout - ) - } + saveControlPosition( + joystickBeingConfigured!!.prefId, + joystickBeingConfigured!!.bounds.centerX(), + joystickBeingConfigured!!.bounds.centerY(), + layout + ) joystickBeingConfigured = null } } @@ -681,117 +607,25 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : invalidate() } - private fun saveControlPosition( - id: String, - x: Int, - y: Int, - individuaScale: Float, - layout: OverlayLayout - ) { + private fun saveControlPosition(id: String, x: Int, y: Int, layout: OverlayLayout) { val windowSize = getSafeScreenSize(context, Pair(measuredWidth, measuredHeight)) val min = windowSize.first val max = windowSize.second val overlayControlData = NativeConfig.getOverlayControlData() val data = overlayControlData.firstOrNull { it.id == id } val newPosition = Pair((x - min.x).toDouble() / max.x, (y - min.y).toDouble() / max.y) - when (layout) { OverlayLayout.Landscape -> data?.landscapePosition = newPosition OverlayLayout.Portrait -> data?.portraitPosition = newPosition OverlayLayout.Foldable -> data?.foldablePosition = newPosition - } - - data?.individualScale = individuaScale - NativeConfig.setOverlayControlData(overlayControlData) } fun setIsInEditMode(editMode: Boolean) { inEditMode = editMode - if (!editMode) { - scaleDialog?.dismiss() - scaleDialog = null - } } - private fun showScaleDialog( - button: InputOverlayDrawableButton?, - dpad: InputOverlayDrawableDpad?, - joystick: InputOverlayDrawableJoystick?, - x: Int, y: Int - ) { - val overlayControlData = NativeConfig.getOverlayControlData() - // prevent dialog from being spam opened - scaleDialog?.dismiss() - - - when { - button != null -> { - val buttonData = - overlayControlData.firstOrNull { it.id == button.overlayControlData.id } - if (buttonData != null) { - scaleDialog = - OverlayScaleDialog(context, button.overlayControlData) { newScale -> - saveControlPosition( - button.overlayControlData.id, - button.bounds.centerX(), - button.bounds.centerY(), - individuaScale = newScale, - layout - ) - refreshControls() - } - - scaleDialog?.showDialog(x,y, button.bounds.width(), button.bounds.height()) - - } - } - - dpad != null -> { - val dpadData = - overlayControlData.firstOrNull { it.id == OverlayControl.COMBINED_DPAD.id } - if (dpadData != null) { - scaleDialog = OverlayScaleDialog(context, dpadData) { newScale -> - saveControlPosition( - OverlayControl.COMBINED_DPAD.id, - dpad.bounds.centerX(), - dpad.bounds.centerY(), - newScale, - layout - ) - - refreshControls() - } - - scaleDialog?.showDialog(x,y, dpad.bounds.width(), dpad.bounds.height()) - - } - } - - joystick != null -> { - val joystickData = overlayControlData.firstOrNull { it.id == joystick.prefId } - if (joystickData != null) { - scaleDialog = OverlayScaleDialog(context, joystickData) { newScale -> - saveControlPosition( - joystick.prefId, - joystick.bounds.centerX(), - joystick.bounds.centerY(), - individuaScale = newScale, - layout - ) - - refreshControls() - } - - scaleDialog?.showDialog(x,y, joystick.bounds.width(), joystick.bounds.height()) - - } - } - } - } - - /** * Applies and saves all default values for the overlay */ @@ -830,24 +664,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : val overlayControlData = NativeConfig.getOverlayControlData() overlayControlData.forEach { it.enabled = OverlayControl.from(it.id)?.defaultVisibility == true - it.individualScale = OverlayControl.from(it.id)?.defaultIndividualScaleResource!! } NativeConfig.setOverlayControlData(overlayControlData) refreshControls() } - fun resetIndividualControlScale() { - val overlayControlData = NativeConfig.getOverlayControlData() - overlayControlData.forEach { data -> - val defaultControlData = OverlayControl.from(data.id) ?: return@forEach - data.individualScale = defaultControlData.defaultIndividualScaleResource - } - NativeConfig.setOverlayControlData(overlayControlData) - NativeConfig.saveGlobalConfig() - refreshControls() - } - private fun defaultOverlayPositionByLayout(layout: OverlayLayout) { val overlayControlData = NativeConfig.getOverlayControlData() for (data in overlayControlData) { @@ -1038,9 +860,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat() scale /= 100f - // Apply individual scale - scale *= overlayControlData.individualScale - // Initialize the InputOverlayDrawableButton. val defaultStateBitmap = getBitmap(context, defaultResId, scale) val pressedStateBitmap = getBitmap(context, pressedResId, scale) @@ -1103,20 +922,11 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : // Resources handle for fetching the initial Drawable resource. val res = context.resources - // Get the dpad control data for individual scale - val overlayControlData = NativeConfig.getOverlayControlData() - val dpadData = overlayControlData.firstOrNull { it.id == OverlayControl.COMBINED_DPAD.id } - // Decide scale based on button ID and user preference var scale = 0.25f scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat() scale /= 100f - // Apply individual scale - if (dpadData != null) { - scale *= dpadData.individualScale - } - // Initialize the InputOverlayDrawableDpad. val defaultStateBitmap = getBitmap(context, defaultResId, scale) @@ -1190,9 +1000,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat() scale /= 100f - // Apply individual scale - scale *= overlayControlData.individualScale - // Initialize the InputOverlayDrawableJoystick. val bitmapOuter = getBitmap(context, resOuter, scale) val bitmapInnerDefault = getBitmap(context, defaultResInner, 1.0f) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt index 01f07e4f36..0cb6ff2440 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later package org.yuzu.yuzu_emu.overlay @@ -42,8 +42,6 @@ class InputOverlayDrawableDpad( val width: Int val height: Int - var individualScale: Float = 1.0f - private val defaultStateBitmap: BitmapDrawable private val pressedOneDirectionStateBitmap: BitmapDrawable private val pressedTwoDirectionsStateBitmap: BitmapDrawable diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt index bc3ff15b21..4b07107fca 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later package org.yuzu.yuzu_emu.overlay @@ -51,8 +51,6 @@ class InputOverlayDrawableJoystick( val width: Int val height: Int - var individualScale: Float = 1.0f - private var opacity: Int = 0 private var virtBounds: Rect diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/OverlayScaleDialog.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/OverlayScaleDialog.kt deleted file mode 100644 index f489ef3b7c..0000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/OverlayScaleDialog.kt +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -package org.yuzu.yuzu_emu.overlay - -import android.app.Dialog -import android.content.Context -import android.view.Gravity -import android.view.LayoutInflater -import android.view.WindowManager -import android.widget.TextView -import com.google.android.material.button.MaterialButton -import com.google.android.material.slider.Slider -import org.yuzu.yuzu_emu.R -import org.yuzu.yuzu_emu.overlay.model.OverlayControlData - -class OverlayScaleDialog( - context: Context, - private val overlayControlData: OverlayControlData, - private val onScaleChanged: (Float) -> Unit -) : Dialog(context) { - - private var currentScale = overlayControlData.individualScale - private val originalScale = overlayControlData.individualScale - private lateinit var scaleValueText: TextView - private lateinit var scaleSlider: Slider - - init { - setupDialog() - } - - private fun setupDialog() { - val view = LayoutInflater.from(context).inflate(R.layout.dialog_overlay_scale, null) - setContentView(view) - - window?.setBackgroundDrawable(null) - - window?.apply { - attributes = attributes.apply { - flags = flags and WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv() - flags = flags or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - } - } - - scaleValueText = view.findViewById(R.id.scaleValueText) - scaleSlider = view.findViewById(R.id.scaleSlider) - val resetButton = view.findViewById(R.id.resetButton) - val confirmButton = view.findViewById(R.id.confirmButton) - val cancelButton = view.findViewById(R.id.cancelButton) - - scaleValueText.text = String.format("%.1fx", currentScale) - scaleSlider.value = currentScale - - scaleSlider.addOnChangeListener { _, value, input -> - if (input) { - currentScale = value - scaleValueText.text = String.format("%.1fx", currentScale) - } - } - - scaleSlider.addOnSliderTouchListener(object : Slider.OnSliderTouchListener { - override fun onStartTrackingTouch(slider: Slider) { - // pass - } - - override fun onStopTrackingTouch(slider: Slider) { - onScaleChanged(currentScale) - } - }) - - resetButton.setOnClickListener { - currentScale = 1.0f - scaleSlider.value = 1.0f - scaleValueText.text = String.format("%.1fx", currentScale) - onScaleChanged(currentScale) - } - - confirmButton.setOnClickListener { - overlayControlData.individualScale = currentScale - //slider value is already saved on touch dispatch but just to be sure - onScaleChanged(currentScale) - dismiss() - } - - // both cancel button and back gesture should revert the scale change - cancelButton.setOnClickListener { - onScaleChanged(originalScale) - dismiss() - } - - setOnCancelListener { - onScaleChanged(originalScale) - dismiss() - } - } - - fun showDialog(anchorX: Int, anchorY: Int, anchorHeight: Int, anchorWidth: Int) { - show() - - show() - - // TODO: this calculation is a bit rough, improve it later on - window?.let { window -> - val layoutParams = window.attributes - layoutParams.gravity = Gravity.TOP or Gravity.START - - val density = context.resources.displayMetrics.density - val dialogWidthPx = (320 * density).toInt() - val dialogHeightPx = (400 * density).toInt() // set your estimated dialog height - - val screenHeight = context.resources.displayMetrics.heightPixels - - - layoutParams.x = anchorX + anchorWidth / 2 - dialogWidthPx / 2 - layoutParams.y = anchorY + anchorHeight / 2 - dialogHeightPx / 2 - layoutParams.width = dialogWidthPx - - - window.attributes = layoutParams - } - - } - -} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControl.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControl.kt index 10cc547d0b..a0eeadf4bc 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControl.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControl.kt @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later package org.yuzu.yuzu_emu.overlay.model @@ -12,144 +12,126 @@ enum class OverlayControl( val defaultVisibility: Boolean, @IntegerRes val defaultLandscapePositionResources: Pair, @IntegerRes val defaultPortraitPositionResources: Pair, - @IntegerRes val defaultFoldablePositionResources: Pair, - val defaultIndividualScaleResource: Float, + @IntegerRes val defaultFoldablePositionResources: Pair ) { BUTTON_A( "button_a", true, Pair(R.integer.BUTTON_A_X, R.integer.BUTTON_A_Y), Pair(R.integer.BUTTON_A_X_PORTRAIT, R.integer.BUTTON_A_Y_PORTRAIT), - Pair(R.integer.BUTTON_A_X_FOLDABLE, R.integer.BUTTON_A_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_A_X_FOLDABLE, R.integer.BUTTON_A_Y_FOLDABLE) ), BUTTON_B( "button_b", true, Pair(R.integer.BUTTON_B_X, R.integer.BUTTON_B_Y), Pair(R.integer.BUTTON_B_X_PORTRAIT, R.integer.BUTTON_B_Y_PORTRAIT), - Pair(R.integer.BUTTON_B_X_FOLDABLE, R.integer.BUTTON_B_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_B_X_FOLDABLE, R.integer.BUTTON_B_Y_FOLDABLE) ), BUTTON_X( "button_x", true, Pair(R.integer.BUTTON_X_X, R.integer.BUTTON_X_Y), Pair(R.integer.BUTTON_X_X_PORTRAIT, R.integer.BUTTON_X_Y_PORTRAIT), - Pair(R.integer.BUTTON_X_X_FOLDABLE, R.integer.BUTTON_X_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_X_X_FOLDABLE, R.integer.BUTTON_X_Y_FOLDABLE) ), BUTTON_Y( "button_y", true, Pair(R.integer.BUTTON_Y_X, R.integer.BUTTON_Y_Y), Pair(R.integer.BUTTON_Y_X_PORTRAIT, R.integer.BUTTON_Y_Y_PORTRAIT), - Pair(R.integer.BUTTON_Y_X_FOLDABLE, R.integer.BUTTON_Y_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_Y_X_FOLDABLE, R.integer.BUTTON_Y_Y_FOLDABLE) ), BUTTON_PLUS( "button_plus", true, Pair(R.integer.BUTTON_PLUS_X, R.integer.BUTTON_PLUS_Y), Pair(R.integer.BUTTON_PLUS_X_PORTRAIT, R.integer.BUTTON_PLUS_Y_PORTRAIT), - Pair(R.integer.BUTTON_PLUS_X_FOLDABLE, R.integer.BUTTON_PLUS_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_PLUS_X_FOLDABLE, R.integer.BUTTON_PLUS_Y_FOLDABLE) ), BUTTON_MINUS( "button_minus", true, Pair(R.integer.BUTTON_MINUS_X, R.integer.BUTTON_MINUS_Y), Pair(R.integer.BUTTON_MINUS_X_PORTRAIT, R.integer.BUTTON_MINUS_Y_PORTRAIT), - Pair(R.integer.BUTTON_MINUS_X_FOLDABLE, R.integer.BUTTON_MINUS_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_MINUS_X_FOLDABLE, R.integer.BUTTON_MINUS_Y_FOLDABLE) ), BUTTON_HOME( "button_home", false, Pair(R.integer.BUTTON_HOME_X, R.integer.BUTTON_HOME_Y), Pair(R.integer.BUTTON_HOME_X_PORTRAIT, R.integer.BUTTON_HOME_Y_PORTRAIT), - Pair(R.integer.BUTTON_HOME_X_FOLDABLE, R.integer.BUTTON_HOME_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_HOME_X_FOLDABLE, R.integer.BUTTON_HOME_Y_FOLDABLE) ), BUTTON_CAPTURE( "button_capture", false, Pair(R.integer.BUTTON_CAPTURE_X, R.integer.BUTTON_CAPTURE_Y), Pair(R.integer.BUTTON_CAPTURE_X_PORTRAIT, R.integer.BUTTON_CAPTURE_Y_PORTRAIT), - Pair(R.integer.BUTTON_CAPTURE_X_FOLDABLE, R.integer.BUTTON_CAPTURE_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_CAPTURE_X_FOLDABLE, R.integer.BUTTON_CAPTURE_Y_FOLDABLE) ), BUTTON_L( "button_l", true, Pair(R.integer.BUTTON_L_X, R.integer.BUTTON_L_Y), Pair(R.integer.BUTTON_L_X_PORTRAIT, R.integer.BUTTON_L_Y_PORTRAIT), - Pair(R.integer.BUTTON_L_X_FOLDABLE, R.integer.BUTTON_L_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_L_X_FOLDABLE, R.integer.BUTTON_L_Y_FOLDABLE) ), BUTTON_R( "button_r", true, Pair(R.integer.BUTTON_R_X, R.integer.BUTTON_R_Y), Pair(R.integer.BUTTON_R_X_PORTRAIT, R.integer.BUTTON_R_Y_PORTRAIT), - Pair(R.integer.BUTTON_R_X_FOLDABLE, R.integer.BUTTON_R_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_R_X_FOLDABLE, R.integer.BUTTON_R_Y_FOLDABLE) ), BUTTON_ZL( "button_zl", true, Pair(R.integer.BUTTON_ZL_X, R.integer.BUTTON_ZL_Y), Pair(R.integer.BUTTON_ZL_X_PORTRAIT, R.integer.BUTTON_ZL_Y_PORTRAIT), - Pair(R.integer.BUTTON_ZL_X_FOLDABLE, R.integer.BUTTON_ZL_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_ZL_X_FOLDABLE, R.integer.BUTTON_ZL_Y_FOLDABLE) ), BUTTON_ZR( "button_zr", true, Pair(R.integer.BUTTON_ZR_X, R.integer.BUTTON_ZR_Y), Pair(R.integer.BUTTON_ZR_X_PORTRAIT, R.integer.BUTTON_ZR_Y_PORTRAIT), - Pair(R.integer.BUTTON_ZR_X_FOLDABLE, R.integer.BUTTON_ZR_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_ZR_X_FOLDABLE, R.integer.BUTTON_ZR_Y_FOLDABLE) ), BUTTON_STICK_L( "button_stick_l", true, Pair(R.integer.BUTTON_STICK_L_X, R.integer.BUTTON_STICK_L_Y), Pair(R.integer.BUTTON_STICK_L_X_PORTRAIT, R.integer.BUTTON_STICK_L_Y_PORTRAIT), - Pair(R.integer.BUTTON_STICK_L_X_FOLDABLE, R.integer.BUTTON_STICK_L_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_STICK_L_X_FOLDABLE, R.integer.BUTTON_STICK_L_Y_FOLDABLE) ), BUTTON_STICK_R( "button_stick_r", true, Pair(R.integer.BUTTON_STICK_R_X, R.integer.BUTTON_STICK_R_Y), Pair(R.integer.BUTTON_STICK_R_X_PORTRAIT, R.integer.BUTTON_STICK_R_Y_PORTRAIT), - Pair(R.integer.BUTTON_STICK_R_X_FOLDABLE, R.integer.BUTTON_STICK_R_Y_FOLDABLE), - 1.0f + Pair(R.integer.BUTTON_STICK_R_X_FOLDABLE, R.integer.BUTTON_STICK_R_Y_FOLDABLE) ), STICK_L( "stick_l", true, Pair(R.integer.STICK_L_X, R.integer.STICK_L_Y), Pair(R.integer.STICK_L_X_PORTRAIT, R.integer.STICK_L_Y_PORTRAIT), - Pair(R.integer.STICK_L_X_FOLDABLE, R.integer.STICK_L_Y_FOLDABLE), - 1.0f + Pair(R.integer.STICK_L_X_FOLDABLE, R.integer.STICK_L_Y_FOLDABLE) ), STICK_R( "stick_r", true, Pair(R.integer.STICK_R_X, R.integer.STICK_R_Y), Pair(R.integer.STICK_R_X_PORTRAIT, R.integer.STICK_R_Y_PORTRAIT), - Pair(R.integer.STICK_R_X_FOLDABLE, R.integer.STICK_R_Y_FOLDABLE), - 1.0f + Pair(R.integer.STICK_R_X_FOLDABLE, R.integer.STICK_R_Y_FOLDABLE) ), COMBINED_DPAD( "combined_dpad", true, Pair(R.integer.COMBINED_DPAD_X, R.integer.COMBINED_DPAD_Y), Pair(R.integer.COMBINED_DPAD_X_PORTRAIT, R.integer.COMBINED_DPAD_Y_PORTRAIT), - Pair(R.integer.COMBINED_DPAD_X_FOLDABLE, R.integer.COMBINED_DPAD_Y_FOLDABLE), - 1.0f + Pair(R.integer.COMBINED_DPAD_X_FOLDABLE, R.integer.COMBINED_DPAD_Y_FOLDABLE) ); fun getDefaultPositionForLayout(layout: OverlayLayout): Pair { @@ -191,8 +173,7 @@ enum class OverlayControl( defaultVisibility, getDefaultPositionForLayout(OverlayLayout.Landscape), getDefaultPositionForLayout(OverlayLayout.Portrait), - getDefaultPositionForLayout(OverlayLayout.Foldable), - defaultIndividualScaleResource + getDefaultPositionForLayout(OverlayLayout.Foldable) ) companion object { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlData.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlData.kt index 6cc5a59c98..26cfeb1db5 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlData.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlData.kt @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later package org.yuzu.yuzu_emu.overlay.model @@ -8,8 +8,7 @@ data class OverlayControlData( var enabled: Boolean, var landscapePosition: Pair, var portraitPosition: Pair, - var foldablePosition: Pair, - var individualScale: Float + var foldablePosition: Pair ) { fun positionFromLayout(layout: OverlayLayout): Pair = when (layout) { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt index 5325f688b6..de0794a17f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later package org.yuzu.yuzu_emu.utils @@ -170,8 +170,7 @@ object DirectoryInitialization { buttonEnabled, Pair(landscapeXPosition, landscapeYPosition), Pair(portraitXPosition, portraitYPosition), - Pair(foldableXPosition, foldableYPosition), - OverlayControl.map[buttonId]?.defaultIndividualScaleResource ?: 1.0f + Pair(foldableXPosition, foldableYPosition) ) overlayControlDataMap[buttonId] = controlData setOverlayData = true 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/android/app/src/main/jni/android_config.cpp b/src/android/app/src/main/jni/android_config.cpp index 41ac680d6b..a79a64afbb 100644 --- a/src/android/app/src/main/jni/android_config.cpp +++ b/src/android/app/src/main/jni/android_config.cpp @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include #include @@ -103,7 +103,6 @@ void AndroidConfig::ReadOverlayValues() { ReadDoubleSetting(std::string("foldable\\x_position")); control_data.foldable_position.second = ReadDoubleSetting(std::string("foldable\\y_position")); - control_data.individual_scale = static_cast(ReadDoubleSetting(std::string("individual_scale"))); AndroidSettings::values.overlay_control_data.push_back(control_data); } EndArray(); @@ -256,7 +255,6 @@ void AndroidConfig::SaveOverlayValues() { control_data.foldable_position.first); WriteDoubleSetting(std::string("foldable\\y_position"), control_data.foldable_position.second); - WriteDoubleSetting(std::string("individual_scale"), static_cast(control_data.individual_scale)); } EndArray(); diff --git a/src/android/app/src/main/jni/android_settings.h b/src/android/app/src/main/jni/android_settings.h index c9e59ce105..cd18f1e5b3 100644 --- a/src/android/app/src/main/jni/android_settings.h +++ b/src/android/app/src/main/jni/android_settings.h @@ -24,7 +24,6 @@ namespace AndroidSettings { std::pair landscape_position; std::pair portrait_position; std::pair foldable_position; - float individual_scale; }; struct Values { @@ -80,15 +79,6 @@ namespace AndroidSettings { Settings::Category::Overlay, Settings::Specialization::Paired, true, true}; - Settings::Setting enable_input_overlay_auto_hide{linkage, false, - "enable_input_overlay_auto_hide", - Settings::Category::Overlay, - Settings::Specialization::Default, true, - true,}; - - Settings::Setting input_overlay_auto_hide{linkage, 5, "input_overlay_auto_hide", - Settings::Category::Overlay, - Settings::Specialization::Default, true, true, &enable_input_overlay_auto_hide}; Settings::Setting perf_overlay_background{linkage, false, "perf_overlay_background", Settings::Category::Overlay, Settings::Specialization::Default, true, diff --git a/src/android/app/src/main/jni/native_config.cpp b/src/android/app/src/main/jni/native_config.cpp index e6021ed217..0b26280c6c 100644 --- a/src/android/app/src/main/jni/native_config.cpp +++ b/src/android/app/src/main/jni/native_config.cpp @@ -1,5 +1,5 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include @@ -369,9 +369,7 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getOverlayControlData(JN env->NewObject(Common::Android::GetOverlayControlDataClass(), Common::Android::GetOverlayControlDataConstructor(), Common::Android::ToJString(env, control_data.id), control_data.enabled, - jlandscapePosition, jportraitPosition, jfoldablePosition, - control_data.individual_scale); - + jlandscapePosition, jportraitPosition, jfoldablePosition); env->SetObjectArrayElement(joverlayControlDataArray, i, jcontrolData); } return joverlayControlDataArray; @@ -420,12 +418,9 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setOverlayControlData( env, env->GetObjectField(jfoldablePosition, Common::Android::GetPairSecondField()))); - float individual_scale = static_cast(env->GetFloatField( - joverlayControlData, Common::Android::GetOverlayControlDataIndividualScaleField())); - AndroidSettings::values.overlay_control_data.push_back(AndroidSettings::OverlayControlData{ Common::Android::GetJString(env, jidString), enabled, landscape_position, - portrait_position, foldable_position, individual_scale}); + portrait_position, foldable_position}); } } diff --git a/src/android/app/src/main/res/layout/dialog_overlay_scale.xml b/src/android/app/src/main/res/layout/dialog_overlay_scale.xml deleted file mode 100644 index 9e047f211e..0000000000 --- a/src/android/app/src/main/res/layout/dialog_overlay_scale.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/android/app/src/main/res/layout/dialog_spinbox.xml b/src/android/app/src/main/res/layout/dialog_spinbox.xml deleted file mode 100644 index 2f18ab750d..0000000000 --- a/src/android/app/src/main/res/layout/dialog_spinbox.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 1b66c191d3..08ca53ad81 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -251,9 +251,7 @@ @string/scaling_filter_nearest_neighbor @string/scaling_filter_bilinear @string/scaling_filter_bicubic - @string/scaling_filter_spline1 @string/scaling_filter_gaussian - @string/scaling_filter_lanczos @string/scaling_filter_scale_force @string/scaling_filter_fsr @string/scaling_filter_area @@ -267,8 +265,6 @@ 4 5 6 - 7 - 8 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 2a5cc48bb1..48ea3ed99b 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -12,24 +12,6 @@ Eden Eden Switch emulator notifications Eden is Running - Seconds - - - Increment - Decrement - Value - Value must be at least %1$d - Value must be at most %1$d - Invalid value - - - - Overlay Auto Hide - Automatically hide the touch controls overlay after the specified time of inactivity. - Enable Overlay Auto Hide - - Input Overlay - Configure on-screen controls @@ -873,7 +855,6 @@ Touchscreen Lock drawer Unlock drawer - Reset Loading settings… @@ -884,12 +865,12 @@ Abort Continue System Archive Not Found - %s is missing. Please dump your system archives.\nContinuing emulation may result in crashes. + %s is missing. Please dump your system archives.\nContinuing emulation may result in crashes and bugs. A system archive Save/Load Error Fatal Error - A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes. - Turning off this setting will significantly degrade performance. It"s recommended that you leave this setting enabled. + A fatal error occurred. Check the log for details.\nContinuing emulation may result in crashes and bugs. + Turning off this setting will significantly reduce emulation performance! For the best experience, it is recommended that you leave this setting enabled. Device RAM: %1$s\nRecommended: %2$s %1$s %2$s No bootable game present! @@ -960,12 +941,12 @@ Normal High - Extreme + Extreme (Slow) Default - Unsafe - Safe + Unsafe (fast) + Safe (stable) ASTC Decoding Method @@ -1011,9 +992,7 @@ Nearest Neighbor Bilinear Bicubic - Spline-1 Gaussian - Lanczos ScaleForce AMD FidelityFX™ Super Resolution Area 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/android/id_cache.cpp b/src/common/android/id_cache.cpp index 1198833996..e0edd006a5 100644 --- a/src/common/android/id_cache.cpp +++ b/src/common/android/id_cache.cpp @@ -1,4 +1,7 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// SPDX-FileCopyrightText: 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include @@ -46,7 +49,6 @@ static jclass s_overlay_control_data_class; static jmethodID s_overlay_control_data_constructor; static jfieldID s_overlay_control_data_id_field; static jfieldID s_overlay_control_data_enabled_field; -static jfieldID s_overlay_control_data_individual_scale_field; static jfieldID s_overlay_control_data_landscape_position_field; static jfieldID s_overlay_control_data_portrait_position_field; static jfieldID s_overlay_control_data_foldable_position_field; @@ -242,10 +244,6 @@ namespace Common::Android { return s_overlay_control_data_enabled_field; } - jfieldID GetOverlayControlDataIndividualScaleField() { - return s_overlay_control_data_individual_scale_field; - } - jfieldID GetOverlayControlDataLandscapePositionField() { return s_overlay_control_data_landscape_position_field; } @@ -496,7 +494,7 @@ namespace Common::Android { reinterpret_cast(env->NewGlobalRef(overlay_control_data_class)); s_overlay_control_data_constructor = env->GetMethodID(overlay_control_data_class, "", - "(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;F)V"); + "(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;)V"); s_overlay_control_data_id_field = env->GetFieldID(overlay_control_data_class, "id", "Ljava/lang/String;"); s_overlay_control_data_enabled_field = @@ -507,8 +505,6 @@ namespace Common::Android { env->GetFieldID(overlay_control_data_class, "portraitPosition", "Lkotlin/Pair;"); s_overlay_control_data_foldable_position_field = env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); - s_overlay_control_data_individual_scale_field = - env->GetFieldID(overlay_control_data_class, "individualScale", "F"); env->DeleteLocalRef(overlay_control_data_class); const jclass patch_class = env->FindClass("org/yuzu/yuzu_emu/model/Patch"); diff --git a/src/common/android/id_cache.h b/src/common/android/id_cache.h index 6b48f471b7..c56ffcf5c6 100644 --- a/src/common/android/id_cache.h +++ b/src/common/android/id_cache.h @@ -1,4 +1,7 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +// SPDX-FileCopyrightText: 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once @@ -64,7 +67,6 @@ jclass GetOverlayControlDataClass(); jmethodID GetOverlayControlDataConstructor(); jfieldID GetOverlayControlDataIdField(); jfieldID GetOverlayControlDataEnabledField(); -jfieldID GetOverlayControlDataIndividualScaleField(); jfieldID GetOverlayControlDataLandscapePositionField(); jfieldID GetOverlayControlDataPortraitPositionField(); jfieldID GetOverlayControlDataFoldablePositionField(); 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/settings.h b/src/common/settings.h index 59e75d3ee0..8605445837 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -178,7 +178,7 @@ struct Values { SwitchableSetting audio_input_device_id{ linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList}; SwitchableSetting sound_index{ - linkage, AudioMode::Stereo, + linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, "sound_index", Category::SystemAudio, Specialization::Default, true, true}; SwitchableSetting volume{linkage, @@ -199,6 +199,8 @@ struct Values { SwitchableSetting use_multi_core{linkage, true, "use_multi_core", Category::Core}; SwitchableSetting memory_layout_mode{linkage, MemoryLayout::Memory_4Gb, + MemoryLayout::Memory_4Gb, + MemoryLayout::Memory_12Gb, "memory_layout_mode", Category::Core, Specialization::Default, @@ -238,8 +240,9 @@ struct Values { #endif "cpu_backend", Category::Cpu}; - SwitchableSetting cpu_accuracy{linkage, CpuAccuracy::Auto, - "cpu_accuracy", Category::Cpu}; + SwitchableSetting cpu_accuracy{linkage, CpuAccuracy::Auto, + CpuAccuracy::Auto, CpuAccuracy::Paranoid, + "cpu_accuracy", Category::Cpu}; SwitchableSetting use_fast_cpu_time{linkage, false, @@ -320,19 +323,11 @@ struct Values { linkage, true, "cpuopt_unsafe_ignore_global_monitor", Category::CpuUnsafe}; // Renderer - SwitchableSetting renderer_backend{linkage, -#if defined(__sun__) || defined(__managarm__) - RendererBackend::OpenGL, -#else - RendererBackend::Vulkan, -#endif + SwitchableSetting renderer_backend{ + linkage, RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend", Category::Renderer}; - SwitchableSetting shader_backend{linkage, -#if defined(__sun__) || defined(__managarm__) - ShaderBackend::Glsl, -#else - ShaderBackend::SpirV, -#endif + SwitchableSetting shader_backend{ + linkage, ShaderBackend::SpirV, ShaderBackend::Glsl, ShaderBackend::SpirV, "shader_backend", Category::Renderer, Specialization::RuntimeList}; SwitchableSetting vulkan_device{linkage, 0, "vulkan_device", Category::Renderer, Specialization::RuntimeList}; @@ -347,6 +342,8 @@ struct Values { Category::Renderer}; SwitchableSetting optimize_spirv_output{linkage, SpirvOptimizeMode::Never, + SpirvOptimizeMode::Never, + SpirvOptimizeMode::Always, "optimize_spirv_output", Category::Renderer}; SwitchableSetting use_asynchronous_gpu_emulation{ @@ -357,10 +354,12 @@ struct Values { #else AstcDecodeMode::Gpu, #endif + AstcDecodeMode::Cpu, + AstcDecodeMode::CpuAsynchronous, "accelerate_astc", Category::Renderer}; SwitchableSetting vsync_mode{ - linkage, VSyncMode::Fifo, + linkage, VSyncMode::Fifo, VSyncMode::Immediate, VSyncMode::FifoRelaxed, "use_vsync", Category::Renderer, Specialization::RuntimeList, true, true}; SwitchableSetting nvdec_emulation{linkage, NvdecEmulation::Gpu, @@ -373,6 +372,8 @@ struct Values { #else FullscreenMode::Exclusive, #endif + FullscreenMode::Borderless, + FullscreenMode::Exclusive, "fullscreen_mode", Category::Renderer, Specialization::Default, @@ -380,6 +381,8 @@ struct Values { true}; SwitchableSetting aspect_ratio{linkage, AspectRatio::R16_9, + AspectRatio::R16_9, + AspectRatio::Stretch, "aspect_ratio", Category::Renderer, Specialization::Default, @@ -427,6 +430,8 @@ struct Values { #else GpuAccuracy::High, #endif + GpuAccuracy::Normal, + GpuAccuracy::Extreme, "gpu_accuracy", Category::RendererAdvanced, Specialization::Default, @@ -437,6 +442,8 @@ struct Values { SwitchableSetting dma_accuracy{linkage, DmaAccuracy::Default, + DmaAccuracy::Default, + DmaAccuracy::Safe, "dma_accuracy", Category::RendererAdvanced, Specialization::Default, @@ -449,14 +456,20 @@ struct Values { #else AnisotropyMode::Automatic, #endif + AnisotropyMode::Automatic, + AnisotropyMode::X16, "max_anisotropy", Category::RendererAdvanced}; SwitchableSetting astc_recompression{linkage, AstcRecompression::Uncompressed, + AstcRecompression::Uncompressed, + AstcRecompression::Bc3, "astc_recompression", Category::RendererAdvanced}; SwitchableSetting vram_usage_mode{linkage, VramUsageMode::Conservative, + VramUsageMode::Conservative, + VramUsageMode::Aggressive, "vram_usage_mode", Category::RendererAdvanced}; SwitchableSetting skip_cpu_inner_invalidation{linkage, @@ -582,10 +595,14 @@ struct Values { // System SwitchableSetting language_index{linkage, Language::EnglishAmerican, + Language::Japanese, + Language::Serbian, "language_index", Category::System}; - SwitchableSetting region_index{linkage, Region::Usa, "region_index", Category::System}; - SwitchableSetting time_zone_index{linkage, TimeZone::Auto, + SwitchableSetting region_index{linkage, Region::Usa, Region::Japan, + Region::Taiwan, "region_index", Category::System}; + SwitchableSetting time_zone_index{linkage, TimeZone::Auto, + TimeZone::Auto, TimeZone::Zulu, "time_zone_index", Category::System}; // Measured in seconds since epoch SwitchableSetting custom_rtc_enabled{ diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 0e5a08d845..ebfa4ceb9e 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -10,7 +10,6 @@ #pragma once #include -#include #include #include #include "common/common_types.h" @@ -19,10 +18,8 @@ namespace Settings { template struct EnumMetadata { - static std::vector> Canonicalizations(); + static std::vector> Canonicalizations(); static u32 Index(); - static constexpr T GetFirst(); - static constexpr T GetLast(); }; #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) @@ -72,101 +69,138 @@ struct EnumMetadata { #define PAIR_1(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_2(N, __VA_ARGS__)) #define PAIR(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_1(N, __VA_ARGS__)) -#define PP_HEAD(A, ...) A - -#define ENUM(NAME, ...) \ - enum class NAME : u32 { __VA_ARGS__ }; \ - template<> inline std::vector> EnumMetadata::Canonicalizations() { \ - return {PAIR(NAME, __VA_ARGS__)}; \ - } \ - template<> inline u32 EnumMetadata::Index() { \ - return __COUNTER__; \ - } \ - template<> inline constexpr NAME EnumMetadata::GetFirst() { \ - return NAME::PP_HEAD(__VA_ARGS__); \ - } \ - template<> inline constexpr NAME EnumMetadata::GetLast() { \ - return (std::vector>{PAIR(NAME, __VA_ARGS__)}).back().second; \ +#define ENUM(NAME, ...) \ + enum class NAME : u32 { __VA_ARGS__ }; \ + template <> \ + inline std::vector> EnumMetadata::Canonicalizations() { \ + return {PAIR(NAME, __VA_ARGS__)}; \ + } \ + template <> \ + inline u32 EnumMetadata::Index() { \ + return __COUNTER__; \ } // AudioEngine must be specified discretely due to having existing but slightly different // canonicalizations // TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id -enum class AudioEngine : u32 { Auto, Cubeb, Sdl2, Null, Oboe, }; -template<> -inline std::vector> EnumMetadata::Canonicalizations() { +enum class AudioEngine : u32 { + Auto, + Cubeb, + Sdl2, + Null, + Oboe, +}; + +template <> +inline std::vector> +EnumMetadata::Canonicalizations() { return { {"auto", AudioEngine::Auto}, {"cubeb", AudioEngine::Cubeb}, {"sdl2", AudioEngine::Sdl2}, {"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe}, }; } -/// @brief This is just a sufficiently large number that is more than the number of other enums declared here -template<> + +template <> inline u32 EnumMetadata::Index() { + // This is just a sufficiently large number that is more than the number of other enums declared + // here return 100; } -template<> -inline constexpr AudioEngine EnumMetadata::GetFirst() { - return AudioEngine::Auto; -} -template<> -inline constexpr AudioEngine EnumMetadata::GetLast() { - return AudioEngine::Oboe; -} ENUM(AudioMode, Mono, Stereo, Surround); -static_assert(EnumMetadata::GetFirst() == AudioMode::Mono); -static_assert(EnumMetadata::GetLast() == AudioMode::Surround); ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch, Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin, ChineseSimplified, ChineseTraditional, PortugueseBrazilian, Serbian); + ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan); + ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt, Gb, GbEire, Gmt, - GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica, - Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt, - Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu); + GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica, + Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt, + Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu); + ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16); + ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous); + ENUM(AstcRecompression, Uncompressed, Bc1, Bc3); + ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed); + ENUM(VramUsageMode, Conservative, Aggressive); + ENUM(RendererBackend, OpenGL, Vulkan, Null); + ENUM(ShaderBackend, Glsl, Glasm, SpirV); + ENUM(GpuAccuracy, Normal, High, Extreme); + ENUM(DmaAccuracy, Default, Unsafe, Safe); + ENUM(CpuBackend, Dynarmic, Nce); + ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid); + ENUM(CpuClock, Boost, Fast) + ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb, Memory_10Gb, Memory_12Gb); + ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never); + ENUM(FullscreenMode, Borderless, Exclusive); + ENUM(NvdecEmulation, Off, Cpu, Gpu); -ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, Res8X); + +ENUM(ResolutionSetup, + Res1_4X, + Res1_2X, + Res3_4X, + Res1X, + Res3_2X, + Res2X, + Res3X, + Res4X, + Res5X, + Res6X, + Res7X, + Res8X); + ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Spline1, Gaussian, Lanczos, ScaleForce, Fsr, Area, MaxEnum); + ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); + ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); + ENUM(ConsoleMode, Handheld, Docked); + ENUM(AppletMode, HLE, LLE); + ENUM(SpirvOptimizeMode, Never, OnLoad, Always); + ENUM(GpuOverclock, Low, Medium, High) + ENUM(TemperatureUnits, Celsius, Fahrenheit) template -inline std::string_view CanonicalizeEnum(Type id) { +inline std::string CanonicalizeEnum(Type id) { const auto group = EnumMetadata::Canonicalizations(); - for (auto& [name, value] : group) - if (value == id) + for (auto& [name, value] : group) { + if (value == id) { return name; + } + } return "unknown"; } template inline Type ToEnum(const std::string& canonicalization) { const auto group = EnumMetadata::Canonicalizations(); - for (auto& [name, value] : group) - if (name == canonicalization) + for (auto& [name, value] : group) { + if (name == canonicalization) { return value; + } + } return {}; } } // namespace Settings diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h index a7e6bb6168..0aba2e11c9 100644 --- a/src/common/settings_setting.h +++ b/src/common/settings_setting.h @@ -72,17 +72,10 @@ public: u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr) requires(ranged) - : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, other_setting_), + : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, + other_setting_), value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val} {} - explicit Setting(Linkage& linkage, const Type& default_val, - const std::string& name, Category category_, - u32 specialization_ = Specialization::Default, bool save_ = true, - bool runtime_modifiable_ = false, BasicSetting* other_setting_ = nullptr) - requires(ranged && std::is_enum_v) - : BasicSetting(linkage, name, category_, save_, runtime_modifiable_, specialization_, other_setting_), - value{default_val}, default_value{default_val}, maximum{EnumMetadata::GetLast()}, minimum{EnumMetadata::GetFirst()} {} - /** * Returns a reference to the setting's value. * @@ -126,6 +119,9 @@ protected: return value_.has_value() ? std::to_string(*value_) : "none"; } else if constexpr (std::is_same_v) { return value_ ? "true" : "false"; + } else if constexpr (std::is_same_v) { + // Compatibility with old AudioEngine setting being a string + return CanonicalizeEnum(value_); } else if constexpr (std::is_floating_point_v) { return fmt::format("{:f}", value_); } else if constexpr (std::is_enum_v) { @@ -211,7 +207,7 @@ public: [[nodiscard]] std::string Canonicalize() const override final { if constexpr (std::is_enum_v) { - return std::string{CanonicalizeEnum(this->GetValue())}; + return CanonicalizeEnum(this->GetValue()); } else { return ToString(this->GetValue()); } @@ -292,32 +288,41 @@ public: * @param other_setting_ A second Setting to associate to this one in metadata */ template - explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(!ranged) - : Setting{ linkage, default_val, name, category_, specialization_, save_, runtime_modifiable_, other_setting_} { + explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, + Category category_, u32 specialization_ = Specialization::Default, + bool save_ = true, bool runtime_modifiable_ = false, + typename std::enable_if::type other_setting_ = nullptr) + : Setting{ + linkage, default_val, name, category_, specialization_, + save_, runtime_modifiable_, other_setting_} { linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); } virtual ~SwitchableSetting() = default; - /// @brief Sets a default value, minimum value, maximum value, and label. - /// @param linkage Setting registry - /// @param default_val Initial value of the setting, and default value of the setting - /// @param min_val Sets the minimum allowed value of the setting - /// @param max_val Sets the maximum allowed value of the setting - /// @param name Label for the setting - /// @param category_ Category of the setting AKA INI group - /// @param specialization_ Suggestion for how frontend implementations represent this in a config - /// @param save_ Suggests that this should or should not be saved to a frontend config file - /// @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded - /// @param other_setting_ A second Setting to associate to this one in metadata + /** + * Sets a default value, minimum value, maximum value, and label. + * + * @param linkage Setting registry + * @param default_val Initial value of the setting, and default value of the setting + * @param min_val Sets the minimum allowed value of the setting + * @param max_val Sets the maximum allowed value of the setting + * @param name Label for the setting + * @param category_ Category of the setting AKA INI group + * @param specialization_ Suggestion for how frontend implementations represent this in a config + * @param save_ Suggests that this should or should not be saved to a frontend config file + * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded + * @param other_setting_ A second Setting to associate to this one in metadata + */ template - explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, const Type& max_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(ranged) - : Setting{linkage, default_val, min_val, max_val, name, category_, specialization_, save_, runtime_modifiable_, other_setting_} { - linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); - } - - template - explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, Category category_, u32 specialization_ = Specialization::Default, bool save_ = true, bool runtime_modifiable_ = false, T* other_setting_ = nullptr) requires(ranged) - : Setting{linkage, default_val, EnumMetadata::GetFirst(), EnumMetadata::GetLast(), name, category_, specialization_, save_, runtime_modifiable_, other_setting_} { + explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, + const Type& max_val, const std::string& name, Category category_, + u32 specialization_ = Specialization::Default, bool save_ = true, + bool runtime_modifiable_ = false, + typename std::enable_if::type other_setting_ = nullptr) + : Setting{linkage, default_val, min_val, + max_val, name, category_, + specialization_, save_, runtime_modifiable_, + other_setting_} { linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); }); } 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/am/applet.h b/src/core/hle/service/am/applet.h index ad84f39dc7..6cc8cdf741 100644 --- a/src/core/hle/service/am/applet.h +++ b/src/core/hle/service/am/applet.h @@ -8,7 +8,6 @@ #include #include -#include #include "common/math_util.h" #include "core/hle/service/apm/apm_controller.h" @@ -24,7 +23,6 @@ #include "core/hle/service/am/hid_registration.h" #include "core/hle/service/am/lifecycle_manager.h" #include "core/hle/service/am/process_holder.h" -#include "core/hle/service/am/service/storage.h" namespace Service::AM { @@ -99,9 +97,6 @@ struct Applet { std::deque> preselected_user_launch_parameter{}; std::deque> friend_invitation_storage_channel{}; - // Context Stack - std::stack> context_stack{}; - // Caller applet std::weak_ptr caller_applet{}; std::shared_ptr caller_applet_broker{}; diff --git a/src/core/hle/service/am/service/process_winding_controller.cpp b/src/core/hle/service/am/service/process_winding_controller.cpp index 30529de550..10df830d70 100644 --- a/src/core/hle/service/am/service/process_winding_controller.cpp +++ b/src/core/hle/service/am/service/process_winding_controller.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,12 +15,12 @@ IProcessWindingController::IProcessWindingController(Core::System& system_, static const FunctionInfo functions[] = { {0, D<&IProcessWindingController::GetLaunchReason>, "GetLaunchReason"}, {11, D<&IProcessWindingController::OpenCallingLibraryApplet>, "OpenCallingLibraryApplet"}, - {21, D<&IProcessWindingController::PushContext>, "PushContext"}, - {22, D<&IProcessWindingController::PopContext>, "PopContext"}, - {23, D<&IProcessWindingController::CancelWindingReservation>, "CancelWindingReservation"}, - {30, D<&IProcessWindingController::WindAndDoReserved>, "WindAndDoReserved"}, - {40, D<&IProcessWindingController::ReserveToStartAndWaitAndUnwindThis>, "ReserveToStartAndWaitAndUnwindThis"}, - {41, D<&IProcessWindingController::ReserveToStartAndWait>, "ReserveToStartAndWait"}, + {21, nullptr, "PushContext"}, + {22, nullptr, "PopContext"}, + {23, nullptr, "CancelWindingReservation"}, + {30, nullptr, "WindAndDoReserved"}, + {40, nullptr, "ReserveToStartAndWaitAndUnwindThis"}, + {41, nullptr, "ReserveToStartAndWait"}, }; // clang-format on @@ -54,43 +51,4 @@ Result IProcessWindingController::OpenCallingLibraryApplet( R_SUCCEED(); } -Result IProcessWindingController::PushContext(SharedPointer context) { - LOG_INFO(Service_AM, "called"); - m_applet->context_stack.push(context); - R_SUCCEED(); -} - -Result IProcessWindingController::PopContext(Out> out_context) { - LOG_INFO(Service_AM, "called"); - - if (m_applet->context_stack.empty()) { - LOG_ERROR(Service_AM, "Context stack is empty"); - R_THROW(ResultUnknown); - } - - *out_context = m_applet->context_stack.top(); - m_applet->context_stack.pop(); - R_SUCCEED(); -} - -Result IProcessWindingController::CancelWindingReservation() { - LOG_WARNING(Service_AM, "STUBBED"); - R_SUCCEED(); -} - -Result IProcessWindingController::WindAndDoReserved() { - LOG_WARNING(Service_AM, "STUBBED"); - R_SUCCEED(); -} - -Result IProcessWindingController::ReserveToStartAndWaitAndUnwindThis() { - LOG_WARNING(Service_AM, "STUBBED"); - R_SUCCEED(); -} - -Result IProcessWindingController::ReserveToStartAndWait() { - LOG_WARNING(Service_AM, "STUBBED"); - R_SUCCEED(); -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/service/process_winding_controller.h b/src/core/hle/service/am/service/process_winding_controller.h index 0d53223033..4408af1f1d 100644 --- a/src/core/hle/service/am/service/process_winding_controller.h +++ b/src/core/hle/service/am/service/process_winding_controller.h @@ -1,12 +1,8 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include "core/hle/service/am/service/storage.h" #include "core/hle/service/am/am_types.h" #include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" @@ -25,12 +21,6 @@ private: Result GetLaunchReason(Out out_launch_reason); Result OpenCallingLibraryApplet( Out> out_calling_library_applet); - Result PushContext(SharedPointer in_context); - Result PopContext(Out> out_context); - Result CancelWindingReservation(); - Result WindAndDoReserved(); - Result ReserveToStartAndWaitAndUnwindThis(); - Result ReserveToStartAndWait(); const std::shared_ptr m_applet; }; diff --git a/src/core/hle/service/am/service/self_controller.cpp b/src/core/hle/service/am/service/self_controller.cpp index 1b58cbea27..1db02b88fd 100644 --- a/src/core/hle/service/am/service/self_controller.cpp +++ b/src/core/hle/service/am/service/self_controller.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -70,7 +67,6 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr {110, nullptr, "SetApplicationAlbumUserData"}, {120, D<&ISelfController::SaveCurrentScreenshot>, "SaveCurrentScreenshot"}, {130, D<&ISelfController::SetRecordVolumeMuted>, "SetRecordVolumeMuted"}, - {230, D<&ISelfController::Unknown230>, "Unknown230"}, {1000, nullptr, "GetDebugStorageChannel"}, }; // clang-format on @@ -408,12 +404,4 @@ Result ISelfController::SetRecordVolumeMuted(bool muted) { R_SUCCEED(); } -Result ISelfController::Unknown230(u32 in_val, Out out_val) { - LOG_WARNING(Service_AM, "(STUBBED) called, in_val={}", in_val); - - *out_val = 0; - - R_SUCCEED(); -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/service/self_controller.h b/src/core/hle/service/am/service/self_controller.h index 86cd9f1118..eca083cfe5 100644 --- a/src/core/hle/service/am/service/self_controller.h +++ b/src/core/hle/service/am/service/self_controller.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -66,7 +63,6 @@ private: Result SetAlbumImageTakenNotificationEnabled(bool enabled); Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option); Result SetRecordVolumeMuted(bool muted); - Result Unknown230(u32 in_val, Out out_val); Kernel::KProcess* const m_process; const std::shared_ptr m_applet; 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/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index 68d73f0a59..b07bd3e58e 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -53,19 +53,6 @@ enum class NetDbError : s32 { NoData = 4, }; -static const constexpr std::array blockedDomains = {"srv.nintendo.net", - "battle.net", - "microsoft.com", - "mojang.com", - "xboxlive.com", - "minecraftservices.com"}; - -static bool IsBlockedHost(const std::string& host) { - return std::any_of( - blockedDomains.begin(), blockedDomains.end(), - [&host](const std::string& domain) { return host.find(domain) != std::string::npos; }); -} - static NetDbError GetAddrInfoErrorToNetDbError(GetAddrInfoError result) { // These combinations have been verified on console (but are not // exhaustive). @@ -167,7 +154,7 @@ static std::pair GetHostByNameRequestImpl(HLERequestConte // For now, ignore options, which are in input buffer 1 for GetHostByNameRequestWithOptions. // Prevent resolution of Nintendo servers - if (IsBlockedHost(host)) { + if (host.find("srv.nintendo.net") != std::string::npos) { LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host); return {0, GetAddrInfoError::AGAIN}; } @@ -284,7 +271,7 @@ static std::pair GetAddrInfoRequestImpl(HLERequestContext const std::string host = Common::StringFromBuffer(host_buffer); // Prevent resolution of Nintendo servers - if (IsBlockedHost(host)) { + if (host.find("srv.nintendo.net") != std::string::npos) { LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host); return {0, GetAddrInfoError::AGAIN}; } @@ -372,4 +359,5 @@ void SFDNSRES::ResolverSetOptionRequest(HLERequestContext& ctx) { rb.Push(ResultSuccess); rb.Push(0); // bsd errno } + } // namespace Service::Sockets 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/dynarmic/tests/CMakeLists.txt b/src/dynarmic/tests/CMakeLists.txt index df90168a52..4ace6c2afd 100644 --- a/src/dynarmic/tests/CMakeLists.txt +++ b/src/dynarmic/tests/CMakeLists.txt @@ -135,8 +135,6 @@ target_include_directories(dynarmic_tests PRIVATE . ../src) target_compile_options(dynarmic_tests PRIVATE ${DYNARMIC_CXX_FLAGS}) target_compile_definitions(dynarmic_tests PRIVATE FMT_USE_USER_DEFINED_LITERALS=1) -if ("x86_64" IN_LIST ARCHITECTURE) - target_compile_options(dynarmic_tests PRIVATE -mavx2) -endif() +target_compile_options(dynarmic_tests PRIVATE -mavx2) add_test(dynarmic_tests dynarmic_tests --durations yes) diff --git a/src/qt_common/CMakeLists.txt b/src/qt_common/CMakeLists.txt index aa931f113e..eb36de4cf2 100644 --- a/src/qt_common/CMakeLists.txt +++ b/src/qt_common/CMakeLists.txt @@ -39,7 +39,7 @@ endif() add_subdirectory(externals) -target_link_libraries(qt_common PRIVATE core Qt6::Core SimpleIni::SimpleIni QuaZip::QuaZip) +target_link_libraries(qt_common PRIVATE core Qt6::Core SimpleIni::SimpleIni QuaZip::QuaZip frozen::frozen) if (NOT APPLE AND ENABLE_OPENGL) target_compile_definitions(qt_common PUBLIC HAS_OPENGL) diff --git a/src/qt_common/externals/CMakeLists.txt b/src/qt_common/externals/CMakeLists.txt index e7b2e7b3e6..189a52c0a6 100644 --- a/src/qt_common/externals/CMakeLists.txt +++ b/src/qt_common/externals/CMakeLists.txt @@ -17,4 +17,4 @@ AddJsonPackage(quazip) # frozen # TODO(crueter): Qt String Lookup -# AddJsonPackage(frozen) +AddJsonPackage(frozen) diff --git a/src/qt_common/shared_translation.cpp b/src/qt_common/shared_translation.cpp index 8f5d929b74..98a55e1fcf 100644 --- a/src/qt_common/shared_translation.cpp +++ b/src/qt_common/shared_translation.cpp @@ -62,20 +62,22 @@ std::unique_ptr InitializeTranslations(QObject* parent) Settings, use_multi_core, tr("Multicore CPU Emulation"), - tr("This option increases CPU emulation thread use from 1 to the maximum of 4.\n" - "This is mainly a debug option and shouldn't be disabled.")); + tr("This option increases CPU emulation thread use from 1 to the Switch’s maximum of 4.\n" + "This is mainly a debug option and shouldn’t be disabled.")); INSERT( Settings, memory_layout_mode, tr("Memory Layout"), - tr("Increases the amount of emulated RAM from 4GB of the board to the " - "devkit 8/6GB.\nDoesn't affect performance/stability but may allow HD texture " - "mods to load.")); + tr("Increases the amount of emulated RAM from the stock 4GB of the retail Switch to the " + "developer kit's 8/6GB.\nIt’s doesn’t improve stability or performance and is intended " + "to let big texture mods fit in emulated RAM.\nEnabling it will increase memory " + "use. It is not recommended to enable unless a specific game with a texture mod needs " + "it.")); INSERT(Settings, use_speed_limit, QString(), QString()); INSERT(Settings, speed_limit, tr("Limit Speed Percent"), - tr("Controls the game's maximum rendering speed, but it's up to each game if it runs " + tr("Controls the game's maximum rendering speed, but it’s up to each game if it runs " "faster or not.\n200% for a 30 FPS game is 60 FPS, and for a " "60 FPS game it will be 120 FPS.\nDisabling it means unlocking the framerate to the " "maximum your PC can reach.")); @@ -84,13 +86,15 @@ std::unique_ptr InitializeTranslations(QObject* parent) tr("Synchronize Core Speed"), tr("Synchronizes CPU core speed with the game's maximum rendering speed to boost FPS " "without affecting game speed (animations, physics, etc.).\n" + "Compatibility varies by game; many (especially older ones) may not respond well.\n" "Can help reduce stuttering at lower framerates.")); // Cpu INSERT(Settings, cpu_accuracy, tr("Accuracy:"), - tr("Change the accuracy of the emulated CPU (for debugging only).")); + tr("This setting controls the accuracy of the emulated CPU.\nDon't change this unless " + "you know what you are doing.")); INSERT(Settings, cpu_backend, tr("Backend:"), QString()); INSERT(Settings, use_fast_cpu_time, QString(), QString()); @@ -106,7 +110,7 @@ std::unique_ptr InitializeTranslations(QObject* parent) cpu_ticks, tr("Custom CPU Ticks"), tr("Set a custom value of CPU ticks. Higher values can increase performance, but may " - "cause deadlocks. A range of 77-21000 is recommended.")); + "also cause the game to freeze. A range of 77–21000 is recommended.")); INSERT(Settings, cpu_backend, tr("Backend:"), QString()); // Cpu Debug @@ -140,7 +144,8 @@ std::unique_ptr InitializeTranslations(QObject* parent) cpuopt_unsafe_fastmem_check, tr("Disable address space checks"), tr("This option improves speed by eliminating a safety check before every memory " - "operation.\nDisabling it may allow arbitrary code execution.")); + "read/write in guest.\nDisabling it may allow a game to read/write the emulator's " + "memory.")); INSERT( Settings, cpuopt_unsafe_ignore_global_monitor, @@ -154,31 +159,36 @@ std::unique_ptr InitializeTranslations(QObject* parent) Settings, renderer_backend, tr("API:"), - tr("Changes the output graphics API.\nVulkan is recommended.")); + tr("Switches between the available graphics APIs.\nVulkan is recommended in most cases.")); INSERT(Settings, vulkan_device, tr("Device:"), - tr("This setting selects the GPU to use (Vulkan only).")); + tr("This setting selects the GPU to use with the Vulkan backend.")); INSERT(Settings, shader_backend, tr("Shader Backend:"), - tr("The shader backend to use with OpenGL.\nGLSL is recommended.")); + tr("The shader backend to use for the OpenGL renderer.\nGLSL is the fastest in " + "performance and the best in rendering accuracy.\n" + "GLASM is a deprecated NVIDIA-only backend that offers much better shader building " + "performance at the cost of FPS and rendering accuracy.\n" + "SPIR-V compiles the fastest, but yields poor results on most GPU drivers.")); INSERT(Settings, resolution_setup, tr("Resolution:"), - tr("Forces to render at a different resolution.\n" - "Higher resolutions require more VRAM and bandwidth.\n" - "Options lower than 1X can cause artifacts.")); + tr("Forces the game to render at a different resolution.\nHigher resolutions require " + "much more VRAM and bandwidth.\n" + "Options lower than 1X can cause rendering issues.")); INSERT(Settings, scaling_filter, tr("Window Adapting Filter:"), QString()); INSERT(Settings, fsr_sharpening_slider, tr("FSR Sharpness:"), - tr("Determines how sharpened the image will look using FSR's dynamic contrast.")); + tr("Determines how sharpened the image will look while using FSR’s dynamic contrast.")); INSERT(Settings, anti_aliasing, tr("Anti-Aliasing Method:"), - tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA " - "can produce a more stable picture in lower resolutions.")); + tr("The anti-aliasing method to use.\nSMAA offers the best quality.\nFXAA has a " + "lower performance impact and can produce a better and more stable picture under " + "very low resolutions.")); INSERT(Settings, fullscreen_mode, tr("Fullscreen Mode:"), @@ -189,17 +199,18 @@ std::unique_ptr InitializeTranslations(QObject* parent) INSERT(Settings, aspect_ratio, tr("Aspect Ratio:"), - tr("Stretches the renderer to fit the specified aspect ratio.\nMost games only support " - "16:9, so modifications are required to get other ratios.\nAlso controls the " + tr("Stretches the game to fit the specified aspect ratio.\nSwitch games only support " + "16:9, so custom game mods are required to get other ratios.\nAlso controls the " "aspect ratio of captured screenshots.")); INSERT(Settings, use_disk_shader_cache, - tr("Use persistent pipeline cache"), + tr("Use disk pipeline cache"), tr("Allows saving shaders to storage for faster loading on following game " - "boots.\nDisabling it is only intended for debugging.")); + "boots.\nDisabling " + "it is only intended for debugging.")); INSERT(Settings, optimize_spirv_output, - tr("Optimize SPIRV output"), + tr("Optimize SPIRV output shader"), tr("Runs an additional optimization pass over generated SPIRV shaders.\n" "Will increase time required for shader compilation.\nMay slightly improve " "performance.\nThis feature is experimental.")); @@ -218,35 +229,37 @@ std::unique_ptr InitializeTranslations(QObject* parent) accelerate_astc, tr("ASTC Decoding Method:"), tr("This option controls how ASTC textures should be decoded.\n" - "CPU: Use the CPU for decoding.\n" - "GPU: Use the GPU's compute shaders to decode ASTC textures (recommended).\n" - "CPU Asynchronously: Use the CPU to decode ASTC textures on demand. Eliminates" - "ASTC decoding\nstuttering but may present artifacts.")); + "CPU: Use the CPU for decoding, slowest but safest method.\n" + "GPU: Use the GPU's compute shaders to decode ASTC textures, recommended for most " + "games and users.\n" + "CPU Asynchronously: Use the CPU to decode ASTC textures as they arrive. Completely " + "eliminates ASTC decoding\nstuttering at the cost of rendering issues while the " + "texture is being decoded.")); INSERT( Settings, astc_recompression, tr("ASTC Recompression Method:"), - tr("Most GPUs lack support for ASTC textures and must decompress to an" - "intermediate format: RGBA8.\n" - "BC1/BC3: The intermediate format will be recompressed to BC1 or BC3 format,\n" - " saving VRAM but degrading image quality.")); + tr("Almost all desktop and laptop dedicated GPUs lack support for ASTC textures, forcing " + "the emulator to decompress to an intermediate format any card supports, RGBA8.\n" + "This option recompresses RGBA8 to either the BC1 or BC3 format, saving VRAM but " + "negatively affecting image quality.")); INSERT(Settings, vram_usage_mode, tr("VRAM Usage Mode:"), - tr("Selects whether the emulator should prefer to conserve memory or make maximum usage of available video memory for performance.\nAggressive mode may impact performance of other applications such as recording software.")); + tr("Selects whether the emulator should prefer to conserve memory or make maximum usage of available video memory for performance.\nAggressive mode may severely impact the performance of other applications such as recording software.")); INSERT(Settings, skip_cpu_inner_invalidation, tr("Skip CPU Inner Invalidation"), - tr("Skips certain cache invalidations during memory updates, reducing CPU usage and " - "improving latency. This may cause soft-crashes.")); + tr("Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and " + "improving it's performance. This may cause glitches or crashes on some games.")); INSERT( Settings, vsync_mode, tr("VSync Mode:"), tr("FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen " - "refresh rate.\nFIFO Relaxed allows tearing as it recovers from a slow down.\n" - "Mailbox can have lower latency than FIFO and does not tear but may drop " - "frames.\nImmediate (no synchronization) presents whatever is available and can " + "refresh rate.\nFIFO Relaxed is similar to FIFO but allows tearing as it recovers from " + "a slow down.\nMailbox can have lower latency than FIFO and does not tear but may drop " + "frames.\nImmediate (no synchronization) just presents whatever is available and can " "exhibit tearing.")); INSERT(Settings, bg_red, QString(), QString()); INSERT(Settings, bg_green, QString(), QString()); @@ -254,7 +267,7 @@ std::unique_ptr InitializeTranslations(QObject* parent) // Renderer (Advanced Graphics) INSERT(Settings, sync_memory_operations, tr("Sync Memory Operations"), - tr("Ensures data consistency between compute and memory operations.\nThis option fixes issues in games, but may degrade performance.\nUnreal Engine 4 games often see the most significant changes thereof.")); + tr("Ensures data consistency between compute and memory operations.\nThis option should fix issues in some games, but may also reduce performance in some cases.\nUnreal Engine 4 games often see the most significant changes thereof.")); INSERT(Settings, async_presentation, tr("Enable asynchronous presentation (Vulkan only)"), @@ -268,7 +281,8 @@ std::unique_ptr InitializeTranslations(QObject* parent) INSERT(Settings, max_anisotropy, tr("Anisotropic Filtering:"), - tr("Controls the quality of texture rendering at oblique angles.\nSafe to set at 16x on most GPUs.")); + tr("Controls the quality of texture rendering at oblique angles.\nIt’s a light setting " + "and safe to set at 16x on most GPUs.")); INSERT(Settings, gpu_accuracy, tr("GPU Accuracy:"), @@ -278,11 +292,11 @@ std::unique_ptr InitializeTranslations(QObject* parent) INSERT(Settings, dma_accuracy, tr("DMA Accuracy:"), - tr("Controls the DMA precision accuracy. Safe precision fixes issues in some games but may degrade performance.")); + tr("Controls the DMA precision accuracy. Safe precision can fix issues in some games, but it can also impact performance in some cases.\nIf unsure, leave this on Default.")); INSERT(Settings, use_asynchronous_shaders, - tr("Enable asynchronous shader compilation (Hack)"), - tr("May reduce shader stutter.")); + tr("Use asynchronous shader building (Hack)"), + tr("Enables asynchronous shader compilation, which may reduce shader stutter.")); INSERT(Settings, use_fast_gpu_time, QString(), QString()); INSERT(Settings, fast_gpu_time, @@ -300,8 +314,8 @@ std::unique_ptr InitializeTranslations(QObject* parent) Settings, enable_compute_pipelines, tr("Enable Compute Pipelines (Intel Vulkan Only)"), - tr("Required by some games.\nThis setting only exists for Intel " - "proprietary drivers and may crash if enabled.\nCompute pipelines are always enabled " + tr("Enable compute pipelines, required by some games.\nThis setting only exists for Intel " + "proprietary drivers, and may crash if enabled.\nCompute pipelines are always enabled " "on all other drivers.")); INSERT( Settings, @@ -329,12 +343,12 @@ std::unique_ptr InitializeTranslations(QObject* parent) INSERT(Settings, dyna_state, tr("Extended Dynamic State"), - tr("Controls the number of features that can be used in Extended Dynamic State.\nHigher numbers allow for more features and can increase performance, but may cause issues.\nThe default value is per-system.")); + tr("Controls the number of features that can be used in Extended Dynamic State.\nHigher numbers allow for more features and can increase performance, but may cause issues with some drivers and vendors.\nThe default value may vary depending on your system and hardware capabilities.\nThis value can be changed until stability and a better visual quality are achieved.")); INSERT(Settings, provoking_vertex, tr("Provoking Vertex"), - tr("Improves lighting and vertex handling in some games.\n" + tr("Improves lighting and vertex handling in certain games.\n" "Only Vulkan 1.0+ devices support this extension.")); INSERT(Settings, @@ -349,8 +363,8 @@ std::unique_ptr InitializeTranslations(QObject* parent) sample_shading_fraction, tr("Sample Shading"), tr("Allows the fragment shader to execute per sample in a multi-sampled fragment " - "instead of once per fragment. Improves graphics quality at the cost of performance.\n" - "Higher values improve quality but degrade performance.")); + "instead once per fragment. Improves graphics quality at the cost of some performance.\n" + "Higher values improve quality more but also reduce performance to a greater extent.")); // Renderer (Debug) @@ -358,30 +372,31 @@ std::unique_ptr InitializeTranslations(QObject* parent) INSERT(Settings, rng_seed, tr("RNG Seed"), - tr("Controls the seed of the random number generator.\nMainly used for speedrunning.")); + tr("Controls the seed of the random number generator.\nMainly used for speedrunning " + "purposes.")); INSERT(Settings, rng_seed_enabled, QString(), QString()); - INSERT(Settings, device_name, tr("Device Name"), tr("The name of the console.")); + INSERT(Settings, device_name, tr("Device Name"), tr("The name of the emulated Switch.")); INSERT(Settings, custom_rtc, tr("Custom RTC Date:"), - tr("This option allows to change the clock of the console.\n" + tr("This option allows to change the emulated clock of the Switch.\n" "Can be used to manipulate time in games.")); INSERT(Settings, custom_rtc_enabled, QString(), QString()); INSERT(Settings, custom_rtc_offset, QStringLiteral(" "), - tr("The number of seconds from the current unix time")); + QStringLiteral("The number of seconds from the current unix time")); INSERT(Settings, language_index, tr("Language:"), - tr("This option can be overridden when region setting is auto-select")); - INSERT(Settings, region_index, tr("Region:"), tr("The region of the console.")); - INSERT(Settings, time_zone_index, tr("Time Zone:"), tr("The time zone of the console.")); + tr("Note: this can be overridden when region setting is auto-select")); + INSERT(Settings, region_index, tr("Region:"), tr("The region of the emulated Switch.")); + INSERT(Settings, time_zone_index, tr("Time Zone:"), tr("The time zone of the emulated Switch.")); INSERT(Settings, sound_index, tr("Sound Output Mode:"), QString()); INSERT(Settings, use_docked_mode, tr("Console Mode:"), - tr("Selects if the console is in Docked or Handheld mode.\nGames will change " + tr("Selects if the console is emulated in Docked or Handheld mode.\nGames will change " "their resolution, details and supported controllers and depending on this setting.\n" "Setting to Handheld can help improve performance for low end systems.")); INSERT(Settings, current_user, QString(), QString()); @@ -403,26 +418,27 @@ std::unique_ptr InitializeTranslations(QObject* parent) // Ui General INSERT(UISettings, select_user_on_boot, - tr("Prompt for user profile on boot"), - tr("Useful if multiple people use the same PC.")); + tr("Prompt for user on game boot"), + tr("Ask to select a user profile on each boot, useful if multiple people use Eden on " + "the same PC.")); INSERT(UISettings, pause_when_in_background, - tr("Pause when not in focus"), - tr("Pauses emulation when focusing on other windows.")); + tr("Pause emulation when in background"), + tr("This setting pauses Eden when focusing other windows.")); INSERT(UISettings, confirm_before_stopping, tr("Confirm before stopping emulation"), - tr("Overrides prompts asking to confirm stopping the emulation.\nEnabling " + tr("This setting overrides game prompts asking to confirm stopping the game.\nEnabling " "it bypasses such prompts and directly exits the emulation.")); INSERT(UISettings, hide_mouse, tr("Hide mouse on inactivity"), - tr("Hides the mouse after 2.5s of inactivity.")); + tr("This setting hides the mouse after 2.5s of inactivity.")); INSERT(UISettings, controller_applet_disabled, tr("Disable controller applet"), - tr("Forcibly disables the use of the controller applet in emulated programs.\n" - "When a program attempts to open the controller applet, it is immediately closed.")); + tr("Forcibly disables the use of the controller applet by guests.\nWhen a guest " + "attempts to open the controller applet, it is immediately closed.")); INSERT(UISettings, check_for_updates, tr("Check for updates"), diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 79a4bf4fd2..55cdc17c1f 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -246,7 +246,7 @@ add_library(shader_recompiler STATIC ) -target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit::sirit SPIRV-Tools::SPIRV-Tools) +target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit SPIRV-Tools::SPIRV-Tools) if (MSVC) target_compile_options(shader_recompiler PRIVATE 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/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 52ca9bbdb6..1a8a7c8dce 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -64,6 +64,7 @@ void MaxwellDMA::Launch() { // TODO(Subv): Perform more research and implement all features of this engine. const LaunchDMA& launch = regs.launch_dma; ASSERT(launch.interrupt_type == LaunchDMA::InterruptType::NONE); + ASSERT(launch.data_transfer_type == LaunchDMA::DataTransferType::NON_PIPELINED); if (launch.multi_line_enable) { const bool is_src_pitch = launch.src_memory_layout == LaunchDMA::MemoryLayout::PITCH; @@ -156,6 +157,8 @@ void MaxwellDMA::Launch() { } void MaxwellDMA::CopyBlockLinearToPitch() { + UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0); + u32 bytes_per_pixel = 1; DMA::ImageOperand src_operand; src_operand.bytes_per_pixel = bytes_per_pixel; 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 c03f7a3abf..b16c1d99ce 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -366,10 +366,10 @@ 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 (NOT USE_SYSTEM_MOLTENVK) set(MOLTENVK_PLATFORM "macOS") set(MOLTENVK_VERSION "v1.3.0") - download_moltenvk(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) + download_moltenvk_external(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) endif() find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.") @@ -397,6 +397,8 @@ if (NOT WIN32) target_include_directories(yuzu PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) endif() +target_link_libraries(yuzu PRIVATE Vulkan::Headers) + if (UNIX AND NOT APPLE) target_link_libraries(yuzu PRIVATE Qt6::DBus) diff --git a/src/yuzu/Info.plist b/src/yuzu/Info.plist index 773c4ee302..96096c84d1 100644 --- a/src/yuzu/Info.plist +++ b/src/yuzu/Info.plist @@ -45,31 +45,9 @@ SPDX-License-Identifier: GPL-2.0-or-later NSHumanReadableCopyright - - LSApplicationCategoryType - public.app-category.games - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - nsp - xci - nro - - CFBundleTypeName - Switch File - CFBundleTypeRole - Viewer - LSHandlerRank - Default - - NSPrincipalClass NSApplication NSHighResolutionCapable True - UIDesignRequiresCompatibility - 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/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index af81ef552e..a7ebae91f8 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -270,8 +270,10 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) { void ConfigureAudio::InitializeAudioSinkComboBox() { sink_combo_box->clear(); sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); - for (const auto& id : AudioCore::Sink::GetSinkIDs()) - sink_combo_box->addItem(QString::fromStdString(std::string{Settings::CanonicalizeEnum(id)})); + + for (const auto& id : AudioCore::Sink::GetSinkIDs()) { + sink_combo_box->addItem(QString::fromStdString(Settings::CanonicalizeEnum(id))); + } } void ConfigureAudio::RetranslateUI() { diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index df74738df4..f5de08a676 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -373,13 +373,13 @@ bool ConfigureProfileManager::LoadAvatarData() { const auto romfs = nca->GetRomFS(); if (!romfs) { QMessageBox::warning(this, tr("Error loading archive"), - tr("Could not locate RomFS. Your file or decryption keys may be corrupted.")); + tr("Archive does not contain romfs. It is probably corrupt.")); return false; } const auto extracted = FileSys::ExtractRomFS(romfs); if (!extracted) { QMessageBox::warning(this, tr("Error extracting archive"), - tr("Could not extract RomFS. Your file or decryption keys may be corrupted.")); + tr("Archive could not be extracted. It is probably corrupt.")); return false; } const auto chara_dir = extracted->GetSubdirectory("chara"); diff --git a/src/yuzu/configuration/shared_widget.h b/src/yuzu/configuration/shared_widget.h index dd5d5b7257..9e718098a3 100644 --- a/src/yuzu/configuration/shared_widget.h +++ b/src/yuzu/configuration/shared_widget.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include "qt_common/shared_translation.h" diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index cd71fb2139..94e7b2dc42 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -58,11 +58,11 @@ class GameList : public QWidget { public: enum { COLUMN_NAME, + COLUMN_COMPATIBILITY, + COLUMN_ADD_ONS, COLUMN_FILE_TYPE, COLUMN_SIZE, COLUMN_PLAY_TIME, - COLUMN_ADD_ONS, - COLUMN_COMPATIBILITY, COLUMN_COUNT, // Number of columns }; diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 2914c275a8..538c7ab822 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -204,24 +204,36 @@ QList MakeGameListEntry(const std::string& path, const PlayTime::PlayTimeManager& play_time_manager, const FileSys::PatchManager& patch) { - auto const it = FindMatchingCompatibilityEntry(compatibility_list, program_id); - // The game list uses 99 as compatibility number for untested games - QString compatibility = it != compatibility_list.end() ? it->second.first : QStringLiteral("99"); + const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); - auto const file_type = loader.GetFileType(); - auto const file_type_string = QString::fromStdString(Loader::GetFileTypeString(file_type)); + // The game list uses this as compatibility number for untested games + QString compatibility{QStringLiteral("99")}; + if (it != compatibility_list.end()) { + compatibility = it->second.first; + } - QString patch_versions = GetGameListCachedObject(fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] { - return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()); - }); - return QList{ - new GameListItemPath(FormatGameName(path), icon, QString::fromStdString(name), file_type_string, program_id), + const auto file_type = loader.GetFileType(); + const auto file_type_string = QString::fromStdString(Loader::GetFileTypeString(file_type)); + + QList list{ + new GameListItemPath(FormatGameName(path), icon, QString::fromStdString(name), + file_type_string, program_id), + new GameListItemCompat(compatibility), new GameListItem(file_type_string), new GameListItemSize(size), new GameListItemPlayTime(play_time_manager.GetPlayTime(program_id)), - new GameListItem(patch_versions), - new GameListItemCompat(compatibility), }; + + QString patch_versions; + + patch_versions = GetGameListCachedObject( + fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] { + return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()); + }); + + list.insert(2, new GameListItem(patch_versions)); + + return list; } } // Anonymous namespace diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 4d5238643c..d2c12c9d40 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1770,25 +1770,16 @@ void GMainWindow::OnDisplayTitleBars(bool show) { void GMainWindow::SetupPrepareForSleep() { #ifdef __unix__ - if (auto bus = QDBusConnection::systemBus(); bus.isConnected()) { - // See https://github.com/ConsoleKit2/ConsoleKit2/issues/150 -#ifdef __linux__ - const auto dbus_logind_service = QStringLiteral("org.freedesktop.login1"); - const auto dbus_logind_path = QStringLiteral("/org/freedesktop/login1"); - const auto dbus_logind_manager_if = QStringLiteral("org.freedesktop.login1.Manager"); - //const auto dbus_logind_session_if = QStringLiteral("org.freedesktop.login1.Session"); -#else - const auto dbus_logind_service = QStringLiteral("org.freedesktop.ConsoleKit"); - const auto dbus_logind_path = QStringLiteral("/org/freedesktop/ConsoleKit/Manager"); - const auto dbus_logind_manager_if = QStringLiteral("org.freedesktop.ConsoleKit.Manager"); - //const auto dbus_logind_session_if = QStringLiteral("org.freedesktop.ConsoleKit.Session"); -#endif + auto bus = QDBusConnection::systemBus(); + if (bus.isConnected()) { const bool success = bus.connect( - dbus_logind_service, dbus_logind_path, - dbus_logind_manager_if, QStringLiteral("PrepareForSleep"), + QStringLiteral("org.freedesktop.login1"), QStringLiteral("/org/freedesktop/login1"), + QStringLiteral("org.freedesktop.login1.Manager"), QStringLiteral("PrepareForSleep"), QStringLiteral("b"), this, SLOT(OnPrepareForSleep(bool))); - if (!success) + + if (!success) { LOG_WARNING(Frontend, "Couldn't register PrepareForSleep signal"); + } } else { LOG_WARNING(Frontend, "QDBusConnection system bus is not connected"); } @@ -4201,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(); } diff --git a/tools/cpm-fetch.sh b/tools/cpm-fetch.sh index 0219845707..088df8464e 100755 --- a/tools/cpm-fetch.sh +++ b/tools/cpm-fetch.sh @@ -84,7 +84,7 @@ ci_package() { echo "-- CI package $PACKAGE" - for platform in windows-amd64 windows-arm64 android solaris-amd64 freebsd-amd64 linux-amd64 linux-aarch64 macos-universal; do + for platform in windows-amd64 windows-arm64 android solaris freebsd linux linux-aarch64; do echo "-- * platform $platform" case $DISABLED in @@ -227,7 +227,7 @@ do HASH_URL="${DOWNLOAD}.${HASH_SUFFIX}" fi - HASH=$(curl "$HASH_URL" -sS -L -o -) + HASH=$(curl "$HASH_URL" -L -o -) fi download_package