diff --git a/.ci/license-header.sh b/.ci/license-header.sh index 3d4929d1c1..d14d5adf42 100755 --- a/.ci/license-header.sh +++ b/.ci/license-header.sh @@ -1,102 +1,53 @@ #!/bin/sh -e HEADER="$(cat "$PWD/.ci/license/header.txt")" -HEADER_HASH="$(cat "$PWD/.ci/license/header-hash.txt")" echo "Getting branch changes" -# BRANCH=`git rev-parse --abbrev-ref HEAD` -# COMMITS=`git log ${BRANCH} --not master --pretty=format:"%h"` -# RANGE="${COMMITS[${#COMMITS[@]}-1]}^..${COMMITS[0]}" -# FILES=`git diff-tree --no-commit-id --name-only ${RANGE} -r` - -BASE=`git merge-base master HEAD` -FILES=`git diff --name-only $BASE` +BRANCH=`git rev-parse --abbrev-ref HEAD` +COMMITS=`git log ${BRANCH} --not master --pretty=format:"%h"` +RANGE="${COMMITS[${#COMMITS[@]}-1]}^..${COMMITS[0]}" +FILES=`git diff-tree --no-commit-id --name-only ${RANGE} -r` #FILES=$(git diff --name-only master) echo "Done" -check_header() { - CONTENT="`head -n3 < $1`" - case "$CONTENT" in - "$HEADER"*) ;; - *) BAD_FILES="$BAD_FILES $1" ;; - esac -} - -check_cmake_header() { - CONTENT="`head -n3 < $1`" - - case "$CONTENT" in - "$HEADER_HASH"*) ;; - *) - BAD_CMAKE="$BAD_CMAKE $1" ;; - esac -} for file in $FILES; do [ -f "$file" ] || continue - if [ `basename -- "$file"` = "CMakeLists.txt" ]; then - check_cmake_header "$file" - continue - fi - EXTENSION="${file##*.}" case "$EXTENSION" in kts|kt|cpp|h) - check_header "$file" - ;; - cmake) - check_cmake_header "$file" + CONTENT="`cat $file`" + case "$CONTENT" in + "$HEADER"*) ;; + *) BAD_FILES="$BAD_FILES $file" ;; + esac ;; esac done -if [ "$BAD_FILES" = "" ] && [ "$BAD_CMAKE" = "" ]; then +if [ "$BAD_FILES" = "" ]; then echo echo "All good." exit fi -if [ "$BAD_FILES" != "" ]; then - echo "The following source files have incorrect license headers:" - echo +echo "The following files have incorrect license headers:" +echo - for file in $BAD_FILES; do echo $file; done +for file in $BAD_FILES; do echo $file; done - cat << EOF +cat << EOF -The following license header should be added to the start of all offending SOURCE files: +The following license header should be added to the start of all offending files: === BEGIN === $HEADER === END === -EOF - -fi - -if [ "$BAD_CMAKE" != "" ]; then - echo "The following CMake files have incorrect license headers:" - echo - - for file in $BAD_CMAKE; do echo $file; done - - cat << EOF - -The following license header should be added to the start of all offending CMake files: - -=== BEGIN === -$HEADER_HASH -=== END === - -EOF - -fi - -cat << EOF If some of the code in this PR is not being contributed by the original author, the files which have been exclusively changed by that code can be ignored. If this happens, this PR requirement can be bypassed once all other files are addressed. @@ -119,17 +70,6 @@ if [ "$FIX" = "true" ]; then git add $file done - for file in $BAD_CMAKE; do - cat $file > $file.bak - - cat .ci/license/header-hash.txt > $file - echo >> $file - cat $file.bak >> $file - - rm $file.bak - - git add $file - done echo "License headers fixed." if [ "$COMMIT" = "true" ]; then diff --git a/.ci/license/header-hash.txt b/.ci/license/header-hash.txt deleted file mode 100644 index 91bc195e23..0000000000 --- a/.ci/license/header-hash.txt +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later diff --git a/.ci/linux/build.sh b/.ci/linux/build.sh index 8e3a452809..7c8bed1279 100755 --- a/.ci/linux/build.sh +++ b/.ci/linux/build.sh @@ -104,7 +104,6 @@ cmake .. -G Ninja \ -DYUZU_USE_QT_WEB_ENGINE=$WEBENGINE \ -DYUZU_USE_FASTER_LD=ON \ -DYUZU_ENABLE_LTO=ON \ - -DDYNARMIC_ENABLE_LTO=ON \ "${EXTRA_CMAKE_FLAGS[@]}" ninja -j${NPROC} diff --git a/.ci/windows/build.sh b/.ci/windows/build.sh index a0ab69a440..7504630a57 100644 --- a/.ci/windows/build.sh +++ b/.ci/windows/build.sh @@ -1,45 +1,58 @@ -#!/bin/bash -ex +#!/bin/bash -e -# SPDX-FileCopyrightText: 2025 Eden Emulator Project +# SPDX-FileCopyrightText: 2025 eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later -if [ "$COMPILER" == "clang" ] -then - EXTRA_CMAKE_FLAGS+=( - -DCMAKE_CXX_COMPILER=clang-cl - -DCMAKE_C_COMPILER=clang-cl - -DCMAKE_CXX_FLAGS="-O3" - -DCMAKE_C_FLAGS="-O3" - ) - - BUILD_TYPE="RelWithDebInfo" +if [ "$DEVEL" != "true" ]; then + export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" -DENABLE_QT_UPDATE_CHECKER=ON) fi -[ -z "$WINDEPLOYQT" ] && { echo "WINDEPLOYQT environment variable required."; exit 1; } +if [ "$CCACHE" = "true" ]; then + export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" -DUSE_CCACHE=ON) +fi -echo $EXTRA_CMAKE_FLAGS +if [ "$BUNDLE_QT" = "true" ]; then + export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" -DYUZU_USE_BUNDLED_QT=ON) +else + export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" -DYUZU_USE_BUNDLED_QT=OFF) +fi + +if [ -z "$BUILD_TYPE" ]; then + export BUILD_TYPE="Release" +fi + +if [ "$WINDEPLOYQT" == "" ]; then + echo "You must supply the WINDEPLOYQT environment variable." + exit 1 +fi + +if [ "$USE_WEBENGINE" = "true" ]; then + WEBENGINE=ON +else + WEBENGINE=OFF +fi + +if [ "$USE_MULTIMEDIA" = "false" ]; then + MULTIMEDIA=OFF +else + MULTIMEDIA=ON +fi + +export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" $@) mkdir -p build && cd build cmake .. -G Ninja \ - -DCMAKE_BUILD_TYPE="${BUILD_TYPE:-Release}" \ - -DENABLE_QT_TRANSLATION=ON \ + -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ + -DENABLE_QT_TRANSLATION=ON \ -DUSE_DISCORD_PRESENCE=ON \ -DYUZU_USE_BUNDLED_SDL2=ON \ - -DBUILD_TESTING=OFF \ -DYUZU_TESTS=OFF \ - -DDYNARMIC_TESTS=OFF \ -DYUZU_CMD=OFF \ -DYUZU_ROOM_STANDALONE=OFF \ - -DYUZU_USE_QT_MULTIMEDIA=${USE_MULTIMEDIA:-false} \ - -DYUZU_USE_QT_WEB_ENGINE=${USE_WEBENGINE:-false} \ + -DYUZU_USE_QT_MULTIMEDIA=$MULTIMEDIA \ + -DYUZU_USE_QT_WEB_ENGINE=$WEBENGINE \ -DYUZU_ENABLE_LTO=ON \ - -DCMAKE_EXE_LINKER_FLAGS=" /LTCG" \ - -DDYNARMIC_ENABLE_LTO=ON \ - -DYUZU_USE_BUNDLED_QT=${BUNDLE_QT:-false} \ - -DUSE_CCACHE=${CCACHE:-false} \ - -DENABLE_QT_UPDATE_CHECKER=${DEVEL:-true} \ - "${EXTRA_CMAKE_FLAGS[@]}" \ - "$@" + "${EXTRA_CMAKE_FLAGS[@]}" ninja @@ -48,5 +61,4 @@ rm -f bin/*.pdb set -e $WINDEPLOYQT --release --no-compiler-runtime --no-opengl-sw --no-system-dxc-compiler --no-system-d3d-compiler --dir pkg bin/eden.exe - cp bin/* pkg diff --git a/.ci/windows/install-msvc.ps1 b/.ci/windows/install-msvc.ps1 deleted file mode 100755 index b88f727ed8..0000000000 --- a/.ci/windows/install-msvc.ps1 +++ /dev/null @@ -1,42 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - -$ErrorActionPreference = "Stop" - -# Check if running as administrator -if (-not ([bool](net session 2>$null))) { - Write-Host "This script must be run with administrator privileges!" - Exit 1 -} - -$VSVer = "17" -$ExeFile = "vs_BuildTools.exe" -$Uri = "https://aka.ms/vs/$VSVer/release/$ExeFile" -$Destination = "./$ExeFile" - -Write-Host "Downloading Visual Studio Build Tools from $Uri" -$WebClient = New-Object System.Net.WebClient -$WebClient.DownloadFile($Uri, $Destination) -Write-Host "Finished downloading $ExeFile" - -$VSROOT = "C:/VSBuildTools/$VSVer" -$Arguments = @( - "--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 -Wait -ArgumentList $Arguments -$ExitCode = $InstallProcess.ExitCode - -if ($ExitCode -ne 0) { - Write-Host "Error installing Visual Studio Build Tools (Error: $ExitCode)" - Exit $ExitCode -} - -Write-Host "Finished installing Visual Studio Build Tools" diff --git a/.ci/windows/install-vulkan-sdk.ps1 b/.ci/windows/install-vulkan-sdk.ps1 index 4c5274d1b7..1d4e1b20bf 100755 --- a/.ci/windows/install-vulkan-sdk.ps1 +++ b/.ci/windows/install-vulkan-sdk.ps1 @@ -3,12 +3,6 @@ $ErrorActionPreference = "Stop" -# Check if running as administrator -if (-not ([bool](net session 2>$null))) { - Write-Host "This script must be run with administrator privileges!" - Exit 1 -} - $VulkanSDKVer = "1.4.321.1" $ExeFile = "vulkansdk-windows-X64-$VulkanSDKVer.exe" $Uri = "https://sdk.lunarg.com/sdk/download/$VulkanSDKVer/windows/$ExeFile" diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..94ac4d33f3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2014 Citra Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +[submodule "libusb"] + path = externals/libusb/libusb + url = https://github.com/libusb/libusb.git diff --git a/.patch/boost/0001-clang-cl.patch b/.patch/boost/0001-clang-cl.patch deleted file mode 100644 index cdabc712cb..0000000000 --- a/.patch/boost/0001-clang-cl.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/libs/cobalt/include/boost/cobalt/concepts.hpp b/libs/cobalt/include/boost/cobalt/concepts.hpp -index d49f2ec..a9bdb80 100644 ---- a/libs/cobalt/include/boost/cobalt/concepts.hpp -+++ b/libs/cobalt/include/boost/cobalt/concepts.hpp -@@ -62,7 +62,7 @@ struct enable_awaitables - template - concept with_get_executor = requires (T& t) - { -- {t.get_executor()} -> asio::execution::executor; -+ t.get_executor(); - }; - - diff --git a/.patch/boost/0002-use-marmasm.patch b/.patch/boost/0002-use-marmasm.patch deleted file mode 100644 index 10f490b878..0000000000 --- a/.patch/boost/0002-use-marmasm.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/libs/context/CMakeLists.txt 2025-09-08 00:42:31.303651800 -0400 -+++ b/libs/context/CMakeLists.txt 2025-09-08 00:42:40.592184300 -0400 -@@ -146,7 +146,7 @@ - set(ASM_LANGUAGE ASM) - endif() - elseif(BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) -- set(ASM_LANGUAGE ASM_ARMASM) -+ set(ASM_LANGUAGE ASM_MARMASM) - else() - set(ASM_LANGUAGE ASM_MASM) - endif() diff --git a/.patch/boost/0003-armasm-options.patch b/.patch/boost/0003-armasm-options.patch deleted file mode 100644 index 3869f95f6f..0000000000 --- a/.patch/boost/0003-armasm-options.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/libs/context/CMakeLists.txt b/libs/context/CMakeLists.txt -index 8210f65..0e59dd7 100644 ---- a/libs/context/CMakeLists.txt -+++ b/libs/context/CMakeLists.txt -@@ -186,7 +186,8 @@ if(BOOST_CONTEXT_IMPLEMENTATION STREQUAL "fcontext") - set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "/safeseh") - endif() - -- else() # masm -+ # armasm doesn't support most of these options -+ elseif(NOT BOOST_CONTEXT_ASSEMBLER STREQUAL armasm) # masm - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") diff --git a/.patch/cpp-jwt/0001-no-install.patch b/.patch/cpp-jwt/0001-no-install.patch new file mode 100644 index 0000000000..b5be557a53 --- /dev/null +++ b/.patch/cpp-jwt/0001-no-install.patch @@ -0,0 +1,47 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 8c1761f..52c4ca4 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -69,42 +69,3 @@ endif() + if(CPP_JWT_BUILD_EXAMPLES) + add_subdirectory(examples) + endif() +- +-# ############################################################################## +-# INSTALL +-# ############################################################################## +- +-include(GNUInstallDirs) +-include(CMakePackageConfigHelpers) +-set(CPP_JWT_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}) +- +-install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets) +-install( +- EXPORT ${PROJECT_NAME}Targets +- DESTINATION ${CPP_JWT_CONFIG_INSTALL_DIR} +- NAMESPACE ${PROJECT_NAME}:: +- COMPONENT dev) +-configure_package_config_file(cmake/Config.cmake.in ${PROJECT_NAME}Config.cmake +- INSTALL_DESTINATION ${CPP_JWT_CONFIG_INSTALL_DIR} +- NO_SET_AND_CHECK_MACRO) +-write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake +- COMPATIBILITY SameMajorVersion +- ARCH_INDEPENDENT) +-install( +- FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake +- ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake +- DESTINATION ${CPP_JWT_CONFIG_INSTALL_DIR} +- COMPONENT dev) +- +-if(NOT CPP_JWT_USE_VENDORED_NLOHMANN_JSON) +- set(CPP_JWT_VENDORED_NLOHMANN_JSON_INSTALL_PATTERN PATTERN "json" EXCLUDE) +-endif() +-install( +- DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/jwt/ +- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/jwt +- COMPONENT dev +- FILES_MATCHING +- PATTERN "*.hpp" +- PATTERN "*.ipp" +- PATTERN "test" EXCLUDE +- ${CPP_JWT_VENDORED_NLOHMANN_JSON_INSTALL_PATTERN}) diff --git a/.patch/cpp-jwt/0002-missing-decl.patch b/.patch/cpp-jwt/0002-missing-decl.patch new file mode 100644 index 0000000000..cd5175dbe0 --- /dev/null +++ b/.patch/cpp-jwt/0002-missing-decl.patch @@ -0,0 +1,13 @@ +diff --git a/include/jwt/algorithm.hpp b/include/jwt/algorithm.hpp +index 0e3b843..1156e6a 100644 +--- a/include/jwt/algorithm.hpp ++++ b/include/jwt/algorithm.hpp +@@ -64,6 +64,8 @@ using verify_func_t = verify_result_t (*) (const jwt::string_view key, + const jwt::string_view head, + const jwt::string_view jwt_sign); + ++verify_result_t is_secret_a_public_key(const jwt::string_view secret); ++ + namespace algo { + + //Me: TODO: All these can be done using code generaion. diff --git a/.patch/discord-rpc/0001-cmake-version.patch b/.patch/discord-rpc/0001-cmake-version.patch new file mode 100644 index 0000000000..6a1609fadf --- /dev/null +++ b/.patch/discord-rpc/0001-cmake-version.patch @@ -0,0 +1,10 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 5dad9e9..760a1b2 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required (VERSION 3.2.0) ++cmake_minimum_required (VERSION 3.10) + project (DiscordRPC) + + include(GNUInstallDirs) diff --git a/.patch/discord-rpc/0002-no-clang-format.patch b/.patch/discord-rpc/0002-no-clang-format.patch new file mode 100644 index 0000000000..4b1e37c29f --- /dev/null +++ b/.patch/discord-rpc/0002-no-clang-format.patch @@ -0,0 +1,40 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 760a1b2..540d643 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -12,20 +12,6 @@ file(GLOB_RECURSE ALL_SOURCE_FILES + src/*.cpp src/*.h src/*.c + ) + +-# Set CLANG_FORMAT_SUFFIX if you are using custom clang-format, e.g. clang-format-5.0 +-find_program(CLANG_FORMAT_CMD clang-format${CLANG_FORMAT_SUFFIX}) +- +-if (CLANG_FORMAT_CMD) +- add_custom_target( +- clangformat +- COMMAND ${CLANG_FORMAT_CMD} +- -i -style=file -fallback-style=none +- ${ALL_SOURCE_FILES} +- DEPENDS +- ${ALL_SOURCE_FILES} +- ) +-endif(CLANG_FORMAT_CMD) +- + # thirdparty stuff + execute_process( + COMMAND mkdir ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 290d761..cd2cc92 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -120,10 +120,6 @@ if (${BUILD_SHARED_LIBS}) + target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK) + endif(${BUILD_SHARED_LIBS}) + +-if (CLANG_FORMAT_CMD) +- add_dependencies(discord-rpc clangformat) +-endif(CLANG_FORMAT_CMD) +- + # install + + install( diff --git a/.patch/discord-rpc/0003-fix-cpp17.patch b/.patch/discord-rpc/0003-fix-cpp17.patch new file mode 100644 index 0000000000..35b725d307 --- /dev/null +++ b/.patch/discord-rpc/0003-fix-cpp17.patch @@ -0,0 +1,31 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 540d643..5d12f3d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -17,12 +17,14 @@ execute_process( + COMMAND mkdir ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty + ERROR_QUIET + ) ++# new commit that fixes c++17 ++set(RAPIDJSON_SHA 3b2441b87f99ab65f37b141a7b548ebadb607b96) + +-find_file(RAPIDJSONTEST NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH) ++find_file(RAPIDJSONTEST NAMES rapidjson rapidjson-${RAPIDJSON_SHA} PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH) + if (NOT RAPIDJSONTEST) + message("no rapidjson, download") +- set(RJ_TAR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/v1.1.0.tar.gz) +- file(DOWNLOAD https://github.com/miloyip/rapidjson/archive/v1.1.0.tar.gz ${RJ_TAR_FILE}) ++ set(RJ_TAR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/${RAPIDJSON_SHA}.tar.gz) ++ file(DOWNLOAD https://github.com/miloyip/rapidjson/archive/${RAPIDJSON_SHA}.tar.gz ${RJ_TAR_FILE}) + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xzf ${RJ_TAR_FILE} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty +@@ -30,7 +32,7 @@ if (NOT RAPIDJSONTEST) + file(REMOVE ${RJ_TAR_FILE}) + endif(NOT RAPIDJSONTEST) + +-find_file(RAPIDJSON NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH) ++find_file(RAPIDJSON NAMES rapidjson rapidjson-${RAPIDJSON_SHA} PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH) + + add_library(rapidjson STATIC IMPORTED ${RAPIDJSON}) + diff --git a/CMakeLists.txt b/CMakeLists.txt index 6abdeb16a5..667b53df26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,21 +15,6 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(PLATFORM_LINUX ON) endif() -if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - set(CXX_CLANG ON) - if (MSVC) - set(CXX_CLANG_CL ON) - endif() -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CXX_GCC ON) -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CXX_CL ON) -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") - set(CXX_ICC ON) -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - set(CXX_APPLE ON) -endif() - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") if (PLATFORM_SUN) @@ -44,84 +29,6 @@ if (PLATFORM_SUN) endif() endif() -# Needed for FFmpeg w/ VAAPI and DRM -if (PLATFORM_OPENBSD) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/X11R6/include") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/X11R6/include") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/X11R6/lib") -endif() - -# Detect current compilation architecture and create standard definitions -# ======================================================================= - -include(CheckSymbolExists) -function(detect_architecture symbol arch) - if (NOT DEFINED ARCHITECTURE) - set(CMAKE_REQUIRED_QUIET 1) - check_symbol_exists("${symbol}" "" ARCHITECTURE_${arch}) - unset(CMAKE_REQUIRED_QUIET) - - # The output variable needs to be unique across invocations otherwise - # CMake's crazy scope rules will keep it defined - if (ARCHITECTURE_${arch}) - set(ARCHITECTURE "${arch}" PARENT_SCOPE) - set(ARCHITECTURE_${arch} 1 PARENT_SCOPE) - add_definitions(-DARCHITECTURE_${arch}=1) - endif() - endif() -endfunction() - -if (NOT ENABLE_GENERIC) - if (MSVC) - detect_architecture("_M_AMD64" x86_64) - detect_architecture("_M_IX86" x86) - detect_architecture("_M_ARM" arm) - detect_architecture("_M_ARM64" arm64) - else() - detect_architecture("__x86_64__" x86_64) - detect_architecture("__i386__" x86) - detect_architecture("__arm__" arm) - detect_architecture("__aarch64__" arm64) - endif() -endif() - -if (NOT DEFINED ARCHITECTURE) - set(ARCHITECTURE "GENERIC") - set(ARCHITECTURE_GENERIC 1) - add_definitions(-DARCHITECTURE_GENERIC=1) -endif() - -message(STATUS "Target architecture: ${ARCHITECTURE}") - -if (MSVC AND ARCHITECTURE_x86) - message(FATAL_ERROR "Attempting to build with the x86 environment is not supported. \ - This can typically happen if you used the Developer Command Prompt from the start menu; \ - instead, run vcvars64.bat directly, located at C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat") -endif() - -if (CXX_CLANG_CL) - add_compile_options( - # clang-cl prints literally 10000+ warnings without this - $<$:-Wno-unused-command-line-argument> - $<$:-Wno-unsafe-buffer-usage> - $<$:-Wno-unused-value> - $<$:-Wno-extra-semi-stmt> - $<$:-Wno-sign-conversion> - $<$:-Wno-reserved-identifier> - $<$:-Wno-deprecated-declarations> - $<$:-Wno-cast-function-type-mismatch> - $<$:/EHsc> # thanks microsoft - ) - - if (ARCHITECTURE_x86_64) - add_compile_options( - # Required CPU features for amd64 - $<$:-msse4.1> - $<$:-mcx16> - ) - endif() -endif() - set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm) include(DownloadExternals) @@ -129,7 +36,7 @@ include(CMakeDependentOption) include(CTest) # Disable Warnings as Errors for MSVC -if (MSVC AND NOT CXX_CLANG) +if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX-") endif() @@ -141,17 +48,17 @@ endif() # 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) -set(EXT_DEFAULT OFF) +set(EXT_DEFAULT ON) -if (MSVC OR ANDROID) - set(EXT_DEFAULT ON) +if (PLATFORM_FREEBSD) + set(EXT_DEFAULT OFF) endif() CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ${EXT_DEFAULT} "ENABLE_SDL2;NOT MSVC" OFF) 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) +option(ENABLE_OPENGL "Enable OpenGL" ON) mark_as_advanced(FORCE ENABLE_OPENGL) option(ENABLE_QT "Enable the Qt frontend" ON) @@ -160,12 +67,15 @@ 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(YUZU_USE_CPM "Use CPM to fetch Eden dependencies if needed" ON) option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON) option(ENABLE_WIFI_SCAN "Enable WiFi scanning" OFF) option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" ${EXT_DEFAULT}) +option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ${EXT_DEFAULT}) +option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ${EXT_DEFAULT}) +option(YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS "Use SPIRV-Tools from externals" ${EXT_DEFAULT}) option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) @@ -177,16 +87,16 @@ option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) CMAKE_DEPENDENT_OPTION(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF "ENABLE_QT" OFF) +option(ENABLE_MICROPROFILE "Enables microprofile capabilities" OFF) + option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}") 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) option(FORCE_DOWNLOAD_WIN_BUNDLES "Forcefully download bundled Windows dependencies (useful for CI)" OFF) -# TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system if (YUZU_USE_CPM AND ENABLE_SDL2) option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") endif() @@ -195,20 +105,22 @@ CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Enable dedicated room functionality" ON "NOT A 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_CMD "Compile the eden-cli executable" ON "NOT ANDROID" OFF) CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) +option(YUZU_CHECK_SUBMODULES "Check if submodules are present" ${EXT_DEFAULT}) + option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" ON) +option(YUZU_ENABLE_PORTABLE "Allow yuzu to enable portable mode if a user folder is found in the CWD" 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") - set(DEFAULT_ENABLE_OPENSSL ON) if (ANDROID OR WIN32 OR APPLE OR PLATFORM_SUN) # - Windows defaults to the Schannel backend. @@ -282,6 +194,53 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/hooks/pre-commit AND NOT EXISTS ${PROJECT_SOURCE endif() endif() +# Sanity check : Check that all submodules are present +# ======================================================================= + +function(check_submodules_present) + file(READ "${PROJECT_SOURCE_DIR}/.gitmodules" gitmodules) + string(REGEX MATCHALL "path *= *[^ \t\r\n]*" gitmodules ${gitmodules}) + foreach(module ${gitmodules}) + string(REGEX REPLACE "path *= *" "" module ${module}) + + file(GLOB RESULT "${PROJECT_SOURCE_DIR}/${module}/*") + list(LENGTH RESULT RES_LEN) + if(RES_LEN EQUAL 0) + message(FATAL_ERROR "Git submodule ${module} not found. " + "Please run: \ngit submodule update --init --recursive") + endif() + if (EXISTS "${PROJECT_SOURCE_DIR}/${module}/.git") + set(SUBMODULE_DIR "${PROJECT_SOURCE_DIR}/${module}") + + execute_process( + COMMAND git rev-parse --short=10 HEAD + WORKING_DIRECTORY ${SUBMODULE_DIR} + OUTPUT_VARIABLE SUBMODULE_SHA + ) + + # would probably be better to do string parsing, but whatever + execute_process( + COMMAND git remote get-url origin + WORKING_DIRECTORY ${SUBMODULE_DIR} + OUTPUT_VARIABLE SUBMODULE_URL + ) + + string(REGEX REPLACE "\n|\r" "" SUBMODULE_SHA ${SUBMODULE_SHA}) + string(REGEX REPLACE "\n|\r|\\.git" "" SUBMODULE_URL ${SUBMODULE_URL}) + + get_filename_component(SUBMODULE_NAME ${SUBMODULE_DIR} NAME) + + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_NAMES ${SUBMODULE_NAME}) + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${SUBMODULE_SHA}) + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_URLS ${SUBMODULE_URL}) + endif() + endforeach() +endfunction() + +if(EXISTS ${PROJECT_SOURCE_DIR}/.gitmodules AND YUZU_CHECK_SUBMODULES) + check_submodules_present() +endif() + configure_file(${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc COPYONLY) @@ -303,21 +262,69 @@ if (NOT EXISTS ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list. file(WRITE ${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json "") endif() +# Detect current compilation architecture and create standard definitions +# ======================================================================= + +include(CheckSymbolExists) +function(detect_architecture symbol arch) + if (NOT DEFINED ARCHITECTURE) + set(CMAKE_REQUIRED_QUIET 1) + check_symbol_exists("${symbol}" "" ARCHITECTURE_${arch}) + unset(CMAKE_REQUIRED_QUIET) + + # The output variable needs to be unique across invocations otherwise + # CMake's crazy scope rules will keep it defined + if (ARCHITECTURE_${arch}) + set(ARCHITECTURE "${arch}" PARENT_SCOPE) + set(ARCHITECTURE_${arch} 1 PARENT_SCOPE) + add_definitions(-DARCHITECTURE_${arch}=1) + endif() + endif() +endfunction() + +if (NOT ENABLE_GENERIC) + if (MSVC) + detect_architecture("_M_AMD64" x86_64) + detect_architecture("_M_IX86" x86) + detect_architecture("_M_ARM" arm) + detect_architecture("_M_ARM64" arm64) + else() + detect_architecture("__x86_64__" x86_64) + detect_architecture("__i386__" x86) + detect_architecture("__arm__" arm) + detect_architecture("__aarch64__" arm64) + endif() +endif() + +if (NOT DEFINED ARCHITECTURE) + set(ARCHITECTURE "GENERIC") + set(ARCHITECTURE_GENERIC 1) + add_definitions(-DARCHITECTURE_GENERIC=1) +endif() + +message(STATUS "Target architecture: ${ARCHITECTURE}") + +if (MSVC AND ARCHITECTURE_x86) + message(FATAL_ERROR "Attempting to build with the x86 environment is not supported. \ + This can typically happen if you used the Developer Command Prompt from the start menu;\ + instead, run vcvars64.bat directly, located at C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvars64.bat") +endif() + if (UNIX) - add_compile_definitions(YUZU_UNIX=1) + add_definitions(-DYUZU_UNIX=1) endif() if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX)) set(HAS_NCE 1) - add_compile_definitions(HAS_NCE=1) + add_definitions(-DHAS_NCE=1) endif() if (YUZU_ROOM) - add_compile_definitions(YUZU_ROOM) + add_definitions(-DYUZU_ROOM) endif() # Build/optimization presets -if (PLATFORM_LINUX OR CXX_CLANG) +if (PLATFORM_LINUX) if (ARCHITECTURE_x86_64) set(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, generic, v3, zen2, zen4, native") if (${YUZU_BUILD_PRESET} STREQUAL "generic") @@ -394,7 +401,6 @@ if (YUZU_USE_CPM) # boost set(BOOST_INCLUDE_LIBRARIES algorithm icl pool container heap asio headers process filesystem crc variant) - AddJsonPackage(boost) # really annoying thing where boost::headers doesn't work with cpm @@ -404,10 +410,13 @@ if (YUZU_USE_CPM) if (Boost_ADDED) if (MSVC OR ANDROID) add_compile_definitions(YUZU_BOOST_v1) + else() + message(WARNING "Using bundled Boost on a non-MSVC or Android system is not recommended. You are strongly encouraged to install Boost through your system's package manager.") endif() - if (NOT MSVC OR CXX_CLANG) + if (NOT MSVC) # boost sucks + # Solaris (and probably other NIXes) need explicit pthread definition if (PLATFORM_SUN) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthreads") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthreads") @@ -460,36 +469,6 @@ if (YUZU_USE_CPM) # Opus AddJsonPackage(opus) - - if (Opus_ADDED) - if (MSVC AND CXX_CLANG) - target_compile_options(opus PRIVATE - -Wno-implicit-function-declaration - ) - endif() - 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) @@ -503,32 +482,6 @@ else() find_package(ZLIB 1.2 REQUIRED) find_package(zstd 1.5 REQUIRED MODULE) - # wow - if (PLATFORM_LINUX) - find_package(Boost 1.57.0 REQUIRED headers context system fiber) - 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() @@ -546,12 +499,16 @@ if(NOT TARGET Boost::headers) AddJsonPackage(boost_headers) endif() +if (ENABLE_LIBUSB) + if (PLATFORM_FREEBSD) + find_package(libusb MODULE) + else() + find_package(libusb 1.0.24 MODULE) + endif() +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) @@ -654,12 +611,10 @@ endfunction() add_subdirectory(externals) # pass targets from externals -find_package(libusb) +find_package(VulkanHeaders) +find_package(VulkanUtilityLibraries) find_package(VulkanMemoryAllocator) - -if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) - find_package(xbyak) -endif() +find_package(SPIRV-Tools) if (ENABLE_WEB_SERVICE) find_package(httplib) @@ -791,7 +746,7 @@ if (APPLE) list(APPEND PLATFORM_LIBRARIES ${ICONV_LIBRARY}) elseif (WIN32) # Target Windows 10 - add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00) + add_definitions(-D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00) set(PLATFORM_LIBRARIES winmm ws2_32 iphlpapi) if (MINGW) # PSAPI is the Process Status API @@ -861,27 +816,6 @@ if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja") ) endif() -# Adjustments for clang-cl -if (MSVC AND CXX_CLANG) - if (ARCHITECTURE_x86_64) - set(FILE_ARCH x86_64) - elseif (ARCHITECTURE_arm64) - set(FILE_ARCH aarch64) - else() - message(FATAL_ERROR "clang-cl: Unsupported architecture ${ARCHITECTURE}") - endif() - - AddJsonPackage(llvm-mingw) - set(LIB_PATH "${llvm-mingw_SOURCE_DIR}/libclang_rt.builtins-${FILE_ARCH}.a") - - add_library(llvm-mingw-runtime STATIC IMPORTED) - set_target_properties(llvm-mingw-runtime PROPERTIES - IMPORTED_LOCATION "${LIB_PATH}" - ) - - link_libraries(llvm-mingw-runtime) -endif() - if (YUZU_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # We will assume that if the compiler is GCC, it will attempt to use ld.bfd by default. # Try to pick a faster linker. diff --git a/CMakeModules/CPMUtil.cmake b/CMakeModules/CPMUtil.cmake index f76a16c103..4d7db6ed61 100644 --- a/CMakeModules/CPMUtil.cmake +++ b/CMakeModules/CPMUtil.cmake @@ -1,10 +1,20 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-FileCopyrightText: Copyright 2025 crueter # SPDX-License-Identifier: GPL-3.0-or-later +# Created-By: crueter +# Docs will come at a later date, mostly this is to just reduce boilerplate +# and some cmake magic to allow for runtime viewing of dependency versions + +# Future crueter: Wow this was a lie and a half, at this point I might as well make my own CPN +# haha just kidding... unless? + if (MSVC OR ANDROID) - set(BUNDLED_DEFAULT ON) -else() set(BUNDLED_DEFAULT OFF) +else() + set(BUNDLED_DEFAULT ON) endif() option(CPMUTIL_FORCE_BUNDLED @@ -16,8 +26,8 @@ option(CPMUTIL_FORCE_SYSTEM cmake_minimum_required(VERSION 3.22) include(CPM) -# cpmfile parsing -set(CPMUTIL_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json") +# TODO(crueter): Better solution for separate cpmfiles e.g. per-directory +set(CPMUTIL_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json" CACHE STRING "Location of cpmfile.json") if (EXISTS ${CPMUTIL_JSON_FILE}) file(READ ${CPMUTIL_JSON_FILE} CPMFILE_CONTENT) @@ -25,11 +35,12 @@ else() message(WARNING "[CPMUtil] cpmfile ${CPMUTIL_JSON_FILE} does not exist, AddJsonPackage will be a no-op") endif() -# Utility stuff +# utility function(cpm_utils_message level name message) message(${level} "[CPMUtil] ${name}: ${message}") endfunction() +# utility function(array_to_list array length out) math(EXPR range "${length} - 1") @@ -42,6 +53,7 @@ function(array_to_list array length out) set("${out}" "${NEW_LIST}" PARENT_SCOPE) endfunction() +# utility function(get_json_element object out member default) string(JSON out_type ERROR_VARIABLE err TYPE "${object}" ${member}) @@ -61,13 +73,14 @@ function(get_json_element object out member default) set("${out}" "${outvar}" PARENT_SCOPE) endfunction() -# The preferred usage +# Kinda cancerous but whatever function(AddJsonPackage) set(oneValueArgs NAME # these are overrides that can be generated at runtime, so can be defined separately from the json DOWNLOAD_ONLY + SYSTEM_PACKAGE BUNDLED_PACKAGE ) @@ -77,7 +90,6 @@ function(AddJsonPackage) "${ARGN}") list(LENGTH ARGN argnLength) - # single name argument if(argnLength EQUAL 1) set(JSON_NAME "${ARGV0}") @@ -136,32 +148,11 @@ function(AddJsonPackage) get_json_element("${object}" tag tag "") get_json_element("${object}" artifact artifact "") get_json_element("${object}" git_version git_version "") - get_json_element("${object}" git_host git_host "") get_json_element("${object}" source_subdir source_subdir "") get_json_element("${object}" bundled bundled "unset") get_json_element("${object}" find_args find_args "") get_json_element("${object}" raw_patches patches "") - # okay here comes the fun part: REPLACEMENTS! - # first: tag gets %VERSION% replaced if applicable, with either git_version (preferred) or version - # second: artifact gets %VERSION% and %TAG% replaced accordingly (same rules for VERSION) - - if (git_version) - set(version_replace ${git_version}) - else() - set(version_replace ${version}) - endif() - - # TODO(crueter): fmt module for cmake - if (tag) - string(REPLACE "%VERSION%" "${version_replace}" tag ${tag}) - endif() - - if (artifact) - string(REPLACE "%VERSION%" "${version_replace}" artifact ${artifact}) - string(REPLACE "%TAG%" "${tag}" artifact ${artifact}) - endif() - # format patchdir if (raw_patches) math(EXPR range "${raw_patches_LENGTH} - 1") @@ -187,11 +178,14 @@ function(AddJsonPackage) endif() set(options ${options} ${JSON_OPTIONS}) + # end options # system/bundled if (bundled STREQUAL "unset" AND DEFINED JSON_BUNDLED_PACKAGE) set(bundled ${JSON_BUNDLED_PACKAGE}) + else() + set(bundled ON) endif() AddPackage( @@ -209,8 +203,6 @@ function(AddJsonPackage) SOURCE_SUBDIR "${source_subdir}" GIT_VERSION ${git_version} - GIT_HOST ${git_host} - ARTIFACT ${artifact} TAG ${tag} ) @@ -228,7 +220,7 @@ endfunction() function(AddPackage) cpm_set_policies() - # TODO(crueter): git clone? + # TODO(crueter): docs, git clone #[[ URL configurations, descending order of precedence: @@ -250,7 +242,6 @@ function(AddPackage) NAME VERSION GIT_VERSION - GIT_HOST REPO TAG @@ -268,7 +259,6 @@ function(AddPackage) KEY BUNDLED_PACKAGE - FIND_PACKAGE_ARGUMENTS ) set(multiValueArgs OPTIONS PATCHES) @@ -283,17 +273,11 @@ function(AddPackage) option(${PKG_ARGS_NAME}_FORCE_SYSTEM "Force the system package for ${PKG_ARGS_NAME}") option(${PKG_ARGS_NAME}_FORCE_BUNDLED "Force the bundled package for ${PKG_ARGS_NAME}") - if (NOT DEFINED PKG_ARGS_GIT_HOST) - set(git_host github.com) - else() - set(git_host ${PKG_ARGS_GIT_HOST}) - endif() - if (DEFINED PKG_ARGS_URL) set(pkg_url ${PKG_ARGS_URL}) if (DEFINED PKG_ARGS_REPO) - set(pkg_git_url https://${git_host}/${PKG_ARGS_REPO}) + set(pkg_git_url https://github.com/${PKG_ARGS_REPO}) else() if (DEFINED PKG_ARGS_GIT_URL) set(pkg_git_url ${PKG_ARGS_GIT_URL}) @@ -302,7 +286,7 @@ function(AddPackage) endif() endif() elseif (DEFINED PKG_ARGS_REPO) - set(pkg_git_url https://${git_host}/${PKG_ARGS_REPO}) + set(pkg_git_url https://github.com/${PKG_ARGS_REPO}) if (DEFINED PKG_ARGS_TAG) set(pkg_key ${PKG_ARGS_TAG}) @@ -333,23 +317,25 @@ function(AddPackage) cpm_utils_message(STATUS ${PKG_ARGS_NAME} "Download URL is ${pkg_url}") + if (DEFINED PKG_ARGS_GIT_VERSION) + set(git_version ${PKG_ARGS_GIT_VERSION}) + elseif(DEFINED PKG_ARGS_VERSION) + set(git_version ${PKG_ARGS_VERSION}) + endif() + if (NOT DEFINED PKG_ARGS_KEY) if (DEFINED PKG_ARGS_SHA) string(SUBSTRING ${PKG_ARGS_SHA} 0 4 pkg_key) cpm_utils_message(DEBUG ${PKG_ARGS_NAME} "No custom key defined, using ${pkg_key} from sha") - elseif(DEFINED PKG_ARGS_GIT_VERSION) - set(pkg_key ${PKG_ARGS_GIT_VERSION}) + elseif (DEFINED git_version) + set(pkg_key ${git_version}) cpm_utils_message(DEBUG ${PKG_ARGS_NAME} "No custom key defined, using ${pkg_key}") elseif (DEFINED PKG_ARGS_TAG) set(pkg_key ${PKG_ARGS_TAG}) cpm_utils_message(DEBUG ${PKG_ARGS_NAME} "No custom key defined, using ${pkg_key}") - elseif (DEFINED PKG_ARGS_VERSION) - set(pkg_key ${PKG_ARGS_VERSION}) - cpm_utils_message(DEBUG ${PKG_ARGS_NAME} - "No custom key defined, using ${pkg_key}") else() cpm_utils_message(WARNING ${PKG_ARGS_NAME} "Could not determine cache key, using CPM defaults") @@ -423,9 +409,9 @@ function(AddPackage) set_precedence(OFF OFF) elseif (CPMUTIL_FORCE_SYSTEM) set_precedence(ON ON) - elseif(CPMUTIL_FORCE_BUNDLED) + elseif(NOT CPMUTIL_FORCE_BUNDLED) set_precedence(OFF OFF) - elseif (DEFINED PKG_ARGS_BUNDLED_PACKAGE AND NOT PKG_ARGS_BUNDLED_PACKAGE STREQUAL "unset") + elseif (DEFINED PKG_ARGS_BUNDLED_PACKAGE) if (PKG_ARGS_BUNDLED_PACKAGE) set(local OFF) else() @@ -460,15 +446,12 @@ function(AddPackage) if (DEFINED PKG_ARGS_SHA) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${PKG_ARGS_SHA}) - elseif (DEFINED PKG_ARGS_GIT_VERSION) - set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS - ${PKG_ARGS_GIT_VERSION}) + elseif(DEFINED git_version) + set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS + ${git_version}) elseif (DEFINED PKG_ARGS_TAG) set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS ${PKG_ARGS_TAG}) - elseif(DEFINED PKG_ARGS_VERSION) - set_property(GLOBAL APPEND PROPERTY CPM_PACKAGE_SHAS - ${PKG_ARGS_VERSION}) else() cpm_utils_message(WARNING ${PKG_ARGS_NAME} "Package has no specified sha, tag, or version") @@ -513,7 +496,6 @@ function(add_ci_package key) set(ARTIFACT_DIR ${${ARTIFACT_PACKAGE}_SOURCE_DIR} PARENT_SCOPE) endfunction() -# TODO(crueter): we could do an AddMultiArchPackage, multiplatformpackage? # name is the artifact name, package is for find_package override function(AddCIPackage) set(oneValueArgs diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index 88fa183061..de45d15d2a 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -11,17 +11,10 @@ function(download_bundled_external remote_path lib_name cpm_key prefix_var versi set(package_repo "no_platform") set(package_extension "no_platform") - # TODO(crueter): Need to convert ffmpeg to a CI. if (WIN32 OR FORCE_WIN_ARCHIVES) - if (ARCHITECTURE_arm64) - set(CACHE_KEY "windows") - set(package_repo "ext-windows-arm64-bin/raw/master/") - set(package_extension ".zip") - elseif(ARCHITECTURE_x86_64) - set(CACHE_KEY "windows") - set(package_repo "ext-windows-bin/raw/master/") - set(package_extension ".7z") - endif() + set(CACHE_KEY "windows") + set(package_repo "ext-windows-bin/raw/master/") + set(package_extension ".7z") elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(CACHE_KEY "linux") set(package_repo "ext-linux-bin/raw/master/") diff --git a/CMakeModules/Findsirit.cmake b/CMakeModules/Findsirit.cmake deleted file mode 100644 index 1611efaad8..0000000000 --- a/CMakeModules/Findsirit.cmake +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - -include(FindPackageHandleStandardArgs) - -find_package(PkgConfig QUIET) -pkg_search_module(sirit QUIET IMPORTED_TARGET sirit) -find_package_handle_standard_args(sirit - REQUIRED_VARS sirit_LINK_LIBRARIES - VERSION_VAR sirit_VERSION -) diff --git a/CMakeModules/GenerateSCMRev.cmake b/CMakeModules/GenerateSCMRev.cmake index bcb5dc466a..3b8e996751 100644 --- a/CMakeModules/GenerateSCMRev.cmake +++ b/CMakeModules/GenerateSCMRev.cmake @@ -35,6 +35,4 @@ set(REPO_NAME "Eden") set(BUILD_ID ${GIT_BRANCH}) set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ") -set(CXX_COMPILER "${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") - configure_file(scm_rev.cpp.in scm_rev.cpp @ONLY) diff --git a/CMakeModules/WindowsCopyFiles.cmake b/CMakeModules/WindowsCopyFiles.cmake index 8d37bd5c2c..08b598365d 100644 --- a/CMakeModules/WindowsCopyFiles.cmake +++ b/CMakeModules/WindowsCopyFiles.cmake @@ -12,25 +12,16 @@ set(__windows_copy_files YES) # Any number of files to copy from SOURCE_DIR to DEST_DIR can be specified after DEST_DIR. # This copying happens post-build. -if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") - function(windows_copy_files TARGET SOURCE_DIR DEST_DIR) - # windows commandline expects the / to be \ so switch them - string(REPLACE "/" "\\\\" SOURCE_DIR ${SOURCE_DIR}) - string(REPLACE "/" "\\\\" DEST_DIR ${DEST_DIR}) +function(windows_copy_files TARGET SOURCE_DIR DEST_DIR) + # windows commandline expects the / to be \ so switch them + string(REPLACE "/" "\\\\" SOURCE_DIR ${SOURCE_DIR}) + string(REPLACE "/" "\\\\" DEST_DIR ${DEST_DIR}) - # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output - # cmake adds an extra check for command success which doesn't work too well with robocopy - # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" - add_custom_command(TARGET ${TARGET} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory ${DEST_DIR} - COMMAND robocopy ${SOURCE_DIR} ${DEST_DIR} ${ARGN} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" - ) - endfunction() -else() - function(windows_copy_files TARGET SOURCE_DIR DEST_DIR) - add_custom_command(TARGET ${TARGET} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory ${DEST_DIR} - COMMAND cp -ra ${SOURCE_DIR}/. ${DEST_DIR} - ) - endfunction() -endif() + # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output + # cmake adds an extra check for command success which doesn't work too well with robocopy + # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${DEST_DIR} + COMMAND robocopy ${SOURCE_DIR} ${DEST_DIR} ${ARGN} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" + ) +endfunction() diff --git a/README.md b/README.md index 959b903385..70f2c81296 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,12 @@ If you would like to contribute, we are open to new developers and pull requests ## Building -See the [General Build Guide](docs/Build.md) +* **Windows**: [Windows Building Guide](./docs/build/Windows.md) +* **Linux**: [Linux Building Guide](./docs/build/Linux.md) +* **Android**: [Android Building Guide](./docs/build/Android.md) +* **Solaris**: [Solaris Building Guide](./docs/build/Solaris.md) +* **FreeBSD**: [FreeBSD Building Guide](./docs/build/FreeBSD.md) +* **macOS**: [macOS Building Guide](./docs/build/macOS.md) ## Download diff --git a/cpmfile.json b/cpmfile.json index 887e958533..495382fed0 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -10,16 +10,11 @@ "boost": { "package": "Boost", "repo": "boostorg/boost", - "tag": "boost-%VERSION%", - "artifact": "%TAG%-cmake.tar.xz", - "hash": "4fb7f6fde92762305aad8754d7643cd918dd1f3f67e104e9ab385b18c73178d72a17321354eb203b790b6702f2cf6d725a5d6e2dfbc63b1e35f9eb59fb42ece9", - "git_version": "1.89.0", - "version": "1.57", - "patches": [ - "0001-clang-cl.patch", - "0002-use-marmasm.patch", - "0003-armasm-options.patch" - ] + "tag": "boost-1.88.0", + "artifact": "boost-1.88.0-cmake.7z", + "hash": "e5b049e5b61964480ca816395f63f95621e66cb9bcf616a8b10e441e0e69f129e22443acb11e77bc1e8170f8e4171b9b7719891efc43699782bfcd4b3a365f01", + "git_version": "1.88.0", + "version": "1.57" }, "fmt": { "repo": "fmtlib/fmt", @@ -82,51 +77,18 @@ }, "opus": { "package": "Opus", - "repo": "crueter/opus", - "sha": "ab19c44fad", - "hash": "79d0d015b19e74ce6076197fc32b86fe91d724a0b5a79e86adfc4bdcb946ece384e252adbbf742b74d03040913b70bb0e9556eafa59ef20e42d2f3f4d6f2859a", + "repo": "xiph/opus", + "sha": "5ded705cf4", + "hash": "0dc89e58ddda1f3bc6a7037963994770c5806c10e66f5cc55c59286fc76d0544fe4eca7626772b888fd719f434bc8a92f792bdb350c807968b2ac14cfc04b203", "version": "1.3", "find_args": "MODULE", "options": [ - "OPUS_PRESUME_NEON ON" + "OPUS_BUILD_TESTING OFF", + "OPUS_BUILD_PROGRAMS OFF", + "OPUS_INSTALL_PKG_CONFIG_MODULE OFF", + "OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF" ] }, - "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", @@ -141,8 +103,8 @@ }, "boost_headers": { "repo": "boostorg/headers", - "sha": "95930ca8f5", - "hash": "d1dece16f3b209109de02123c537bfe1adf07a62b16c166367e7e5d62e0f7c323bf804c89b3192dd6871bc58a9d879d25a1cc3f7b9da0e497cf266f165816e2a", + "sha": "0456900fad", + "hash": "50cd75dcdfc5f082225cdace058f47b4fb114a47585f7aee1d22236a910a80b667186254c214fa2fcebac67ae6d37ba4b6e695e1faea8affd6fd42a03cf996e3", "bundled": true }, "discord-rpc": { @@ -181,13 +143,5 @@ "version": "2.32.8", "min_version": "2.26.4", "cmake_filename": "sdl2" - }, - "llvm-mingw": { - "repo": "misc/llvm-mingw", - "git_host": "git.crueter.xyz", - "tag": "20250828", - "version": "20250828", - "artifact": "clang-rt-builtins.tar.zst", - "hash": "d902392caf94e84f223766e2cc51ca5fab6cae36ab8dc6ef9ef6a683ab1c483bfcfe291ef0bd38ab16a4ecc4078344fa8af72da2f225ab4c378dee23f6186181" } } diff --git a/docs/Build.md b/docs/Build.md deleted file mode 100644 index 52a671ab1e..0000000000 --- a/docs/Build.md +++ /dev/null @@ -1,160 +0,0 @@ -# Building Eden - -> [!WARNING] -> This guide is intended for developers ONLY. If you are not a developer or packager, you are unlikely to receive support. - -This is a full-fledged guide to build Eden on all supported platforms. - -## Dependencies -First, you must [install some dependencies](Deps.md). - -## Clone -Next, you will want to clone Eden via the terminal: - -```sh -git clone https://git.eden-emu.dev/eden-emu/eden.git -cd eden -``` - -Or use Qt Creator (Create Project -> Import Project -> Git Clone). - -## Android - -Android has a completely different build process than other platforms. See its [dedicated page](build/Android.md). - -## Initial Configuration - -If the configure phase fails, see the `Troubleshooting` section below. Usually, as long as you followed the dependencies guide, the defaults *should* successfully configure and build. - -### Qt Creator - -This is the recommended GUI method for Linux, macOS, and Windows. - -
-Click to Open - -> [!WARNING] -> On MSYS2, to use Qt Creator you are recommended to *also* install Qt from the online installer, ensuring to select the "MinGW" version. - -Open the CMakeLists.txt file in your cloned directory via File -> Open File or Project (Ctrl+O), if you didn't clone Eden via the project import tool. - -Select your desired "kit" (usually, the default is okay). RelWithDebInfo or Release is recommended: - -![Qt Creator kits](img/creator-1.png) - -Hit "Configure Project", then wait for CMake to finish configuring (may take a while on Windows). - -
- -### Command Line - -This is recommended for *BSD, Solaris, Linux, and MSYS2. MSVC is possible, but not recommended. - -
-Click to Open - -Note that CMake must be in your PATH, and you must be in the cloned Eden directory. On Windows, you must also set up a Visual C++ development environment. This can be done by running `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat` in the same terminal. - -Recommended generators: - -- MSYS2: `MSYS Makefiles` -- MSVC: Install **[ninja](https://ninja-build.org/)** and use `Ninja`, OR use `Visual Studio 17 2022` -- macOS: `Ninja` (preferred) or `Xcode` -- Others: `Ninja` (preferred) or `UNIX Makefiles` - -BUILD_TYPE should usually be `Release` or `RelWithDebInfo` (debug symbols--compiled executable will be large). If you are using a debugger and annoyed with stuff getting optimized out, try `Debug`. - -Also see the [Options](Options.md) page for additional CMake options. - -```sh -cmake -S . -B build -G "GENERATOR" -DCMAKE_BUILD_TYPE= -DYUZU_TESTS=OFF -``` - -If you are on Windows and prefer to use Clang: - -```sh -cmake -S . -B build -G "GENERATOR" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -``` - -
- -### [CLion](https://www.jetbrains.com/clion/) - -
-Click to Open - -* Clone the Repository: - - - - - ---- - -### Building & Setup - -* Once Cloned, You will be taken to a prompt like the image below: - - - -* Set the settings to the image below: -* Change `Build type: Release` -* Change `Name: Release` -* Change `Toolchain Visual Studio` -* Change `Generator: Let CMake decide` -* Change `Build directory: build` - - - -* Click OK; now Clion will build a directory and index your code to allow for IntelliSense. Please be patient. -* Once this process has been completed (No loading bar bottom right), you can now build eden -* In the top right, click on the drop-down menu, select all configurations, then select eden - - - -* Now run by clicking the play button or pressing Shift+F10, and eden will auto-launch once built. - - -
- -## Troubleshooting - -If your initial configure failed: -- *Carefully* re-read the [dependencies guide](Deps.md) -- Clear the CPM cache (`.cache/cpm`) and CMake cache (`/CMakeCache.txt`) -- Evaluate the error and find any related settings -- See the [CPM docs](CPM.md) to see if you may need to forcefully bundle any packages - -Otherwise, feel free to ask for help in Revolt or Discord. - -## Caveats - -Many platforms have quirks, bugs, and other fun stuff that may cause issues when building OR running. See the [Caveats page](Caveats.md) before continuing. - -## Building & Running - -### Qt Creator - -Simply hit Ctrl+B, or the "hammer" icon in the bottom left. To run, hit the "play" icon, or Ctrl+R. - -### Command Line - -If you are not on Windows and are using the `UNIX Makefiles` generator, you must also add `-j$(nproc)` to this command. - -``` -cmake --build build -``` - -Your compiled executable will be in: -- `build/bin/eden.exe` for Windows, -- `build/bin/eden.app/Contents/MacOS/eden` for macOS, -- and `build/bin/eden` for others. - -## Scripts - -Some platforms have convenience scripts provided for building. - -- **[Linux](scripts/Linux.md)** -- **[Windows](scripts/Windows.md)** - -macOS scripts will come soon. \ No newline at end of file diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS deleted file mode 100644 index 503f9ec1fe..0000000000 --- a/docs/CODEOWNERS +++ /dev/null @@ -1,26 +0,0 @@ -# ui stuff -/src/android @AleksandrPopovich @nyxynx @Producdevity -/src/yuzu @crueter -/src/eden @crueter -/src/frontend_common @crueter -/src/qt_common @crueter - -# docs, meta -/docs @Lizzie @crueter -/.ci @crueter - -# cmake -*.cmake @crueter -*/CMakeLists.txt @crueter -*.in @crueter - -# individual stuff -/src/web_service @AleksandrPopovich -/src/dynarmic @Lizzie -/src/core @Lizzie @Maufeat @PavelBARABANOV @MrPurple666 -/src/core/hle @Maufeat @PavelBARABANOV @SDK-Chan -/src/*_room @AleksandrPopovich -/src/video_core @CamilleLaVey @MaranBr @Wildcard @weakboson - -# Global owners/triage -* @CamilleLaVey @Maufeat @crueter @MrPurple666 @MaranBr @Lizzie \ No newline at end of file diff --git a/docs/CPM.md b/docs/CPM.md index 03d8a039f9..f90002891c 100644 --- a/docs/CPM.md +++ b/docs/CPM.md @@ -23,7 +23,7 @@ CPMUtil is a wrapper around CPM that aims to reduce boilerplate and add useful u - `NAME` (required): The package name (must be the same as the `find_package` name if applicable) - `VERSION`: The minimum version of this package that can be used on the system -- `GIT_VERSION`: The "version" found within git +- `GIT_VERSION`: The version found within git, only used for identification - `URL`: The URL to fetch. - `REPO`: The GitHub repo to use (`owner/repo`). * Only GitHub is supported for now, though other platforms will see support at some point @@ -71,9 +71,8 @@ Hashing strategies, descending order of precedence: - `KEY`: Custom cache key to use (stored as `.cache/cpm/${packagename_lower}/${key}`) * Default is based on, in descending order of precedence: - First 4 characters of the sha - - `GIT_VERSION` + - `GIT_VERSION`, or `VERSION` if not specified - Tag - - `VERSION` - Otherwise, CPM defaults will be used. This is not recommended as it doesn't produce reproducible caches - `DOWNLOAD_ONLY`: Whether or not to configure the downloaded package via CMake * Useful to turn `OFF` if the project doesn't use CMake @@ -177,7 +176,7 @@ If `ci` is `true`: ### Examples -In order: OpenSSL CI, Boost (tag + artifact), Opus (options + find_args), discord-rpc (sha + options + patches) +In order: OpenSSL CI, Boost (tag + artifact), discord-rpc (sha + options + patches), Opus (options + find_args) ```json { @@ -233,9 +232,12 @@ In order: OpenSSL CI, Boost (tag + artifact), Opus (options + find_args), discor To include CPMUtil: ```cmake +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) ``` +You may omit the first line if you are not utilizing cpmfile. + ## Prefetching - To prefetch a CPM dependency (requires cpmfile): @@ -243,8 +245,8 @@ include(CPMUtil) - To prefetch all CPM dependencies: * `tools/cpm-fetch-all.sh` -Currently, `cpm-fetch.sh` defines the following directories for cpmfiles (max depth of 2, so subdirs are caught as well): +Currently, `cpm-fetch.sh` defines the following directories for cpmfiles: -`externals src/qt_common src/dynarmic .` +`externals src/yuzu/externals externals/ffmpeg src/dynarmic/externals externals/nx_tzdb` Whenever you add a new cpmfile, update the script accordingly \ No newline at end of file diff --git a/docs/Caveats.md b/docs/Caveats.md deleted file mode 100644 index 7bc2428bab..0000000000 --- a/docs/Caveats.md +++ /dev/null @@ -1,52 +0,0 @@ -# Caveats - -## Arch Linux - -- httplib AUR package is broken. Set `httplib_FORCE_BUNDLED=ON` if you have it installed. -- Eden is also available as an [AUR package](https://aur.archlinux.org/packages/eden-git). If you are unable to build, either use that or compare your process to the PKGBUILD. - -## Gentoo Linux - -Do not use the system sirit or xbyak packages. - -## macOS - -macOS is largely untested. Expect crashes, significant Vulkan issues, and other fun stuff. - -## Solaris - -Qt Widgets appears to be broken. For now, add `-DENABLE_QT=OFF` to your configure command. In the meantime, a Qt Quick frontend is in the works--check back later! - -This is needed for some dependencies that call cc directly (tz): - -```sh -echo '#!/bin/sh' >cc -echo 'gcc $@' >>cc -chmod +x cc -export PATH="$PATH:$PWD" -``` - -Default MESA is a bit outdated, the following environment variables should be set for a smoother experience: -```sh -export MESA_GL_VERSION_OVERRIDE=4.6 -export MESA_GLSL_VERSION_OVERRIDE=460 -export MESA_EXTENSION_MAX_YEAR=2025 -export MESA_DEBUG=1 -export MESA_VK_VERSION_OVERRIDE=1.3 -# Only if nvidia/intel drm drivers cause crashes, will severely hinder performance -export LIBGL_ALWAYS_SOFTWARE=1 -``` - -- Modify the generated ffmpeg.make (in build dir) if using multiple threads (base system `make` doesn't use `-j4`, so change for `gmake`). -- If using OpenIndiana, due to a bug in SDL2's CMake configuration, audio driver defaults to SunOS ``, which does not exist on OpenIndiana. Using external or bundled SDL2 may solve this. -- System OpenSSL generally does not work. Instead, use `-DYUZU_USE_BUNDLED_OPENSSL=ON` to use a bundled static OpenSSL, or build a system dependency from source. - -## OpenBSD - -After configuration, you may need to modify `externals/ffmpeg/CMakeFiles/ffmpeg-build/build.make` to use `-j$(nproc)` instead of just `-j`. - -## FreeBSD - -Eden is not currently available as a port on FreeBSD, though it is in the works. For now, the recommended method of usage is to compile it yourself. - -The available OpenSSL port (3.0.17) is out-of-date, and using a bundled static library instead is recommended; to do so, add `-DYUZU_USE_BUNDLED_OPENSSL=ON` to your CMake configure command. \ No newline at end of file diff --git a/docs/Deps.md b/docs/Deps.md deleted file mode 100644 index cfc6f0365b..0000000000 --- a/docs/Deps.md +++ /dev/null @@ -1,214 +0,0 @@ -# Dependencies - -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/)**, - * *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 - - This can be installed with `xcode-select --install` - -The following additional tools are also required: - -* **[CMake](https://www.cmake.org/)** 3.22+ - already included with the Android SDK -* **[Git](https://git-scm.com/)** for version control - - **[Windows installer](https://gitforwindows.org)** -* On Windows, you must install the **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** as well - - *A convenience script to install the latest SDK is provided in `.ci/windows/install-vulkan-sdk.ps1`* - -If you are on desktop and plan to use the Qt frontend, you *must* install Qt 6, and optionally Qt Creator (the recommended IDE for building) -* On Linux, *BSD and macOS, this can be done by the package manager - - If you wish to use Qt Creator, append `qtcreator` or `qt-creator` to the commands seen below. -* MSVC/clang-cl users on Windows must install through the [official installer](https://www.qt.io/download-qt-installer-oss) -* Linux and macOS users may choose to use the installer as well. -* MSYS2 can also install Qt 6 via the package manager - -If you are on Windows and NOT building with MSYS2, you may go [back home](Build.md) and continue. - -## Externals -The following are handled by Eden's externals: - -* [FFmpeg](https://ffmpeg.org/) (should use `-DYUZU_USE_EXTERNAL_FFMPEG=ON`) -* [SDL2](https://www.libsdl.org/download-2.0.php) 2.0.18+ (should use `-DYUZU_USE_EXTERNAL_SDL2=ON` OR `-DYUZU_USE_BUNDLED_SDL2=ON` to reduce compile time) - -All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available (UNIX-like only): - -* [Boost](https://www.boost.org/users/download/) 1.57.0+ -* [Catch2](https://github.com/catchorg/Catch2) 3.0.1 if `YUZU_TESTS` or `DYNARMIC_TESTS` are on -* [fmt](https://fmt.dev/) 8.0.1+ -* [lz4](http://www.lz4.org) -* [nlohmann\_json](https://github.com/nlohmann/json) 3.8+ -* [OpenSSL](https://www.openssl.org/source/) 1.1.1+ -* [ZLIB](https://www.zlib.net/) 1.2+ -* [zstd](https://facebook.github.io/zstd/) 1.5+ -* [enet](http://enet.bespin.org/) 1.3+ -* [Opus](https://opus-codec.org/) 1.3+ -* [MbedTLS](https://github.com/Mbed-TLS/mbedtls) 3+ - -Vulkan 1.3.274+ is also needed: -* [VulkanUtilityLibraries](https://github.com/KhronosGroup/Vulkan-Utility-Libraries) -* [VulkanHeaders](https://github.com/KhronosGroup/Vulkan-Headers) -* [SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools) -* [SPIRV-Headers](https://github.com/KhronosGroup/SPIRV-Headers) - -Certain other dependencies will be fetched by CPM regardless. System packages *can* be used for these libraries, but many are either not packaged by most distributions OR have issues when used by the system: - -* [SimpleIni](https://github.com/brofield/simpleini) -* [DiscordRPC](https://github.com/eden-emulator/discord-rpc) -* [cubeb](https://github.com/mozilla/cubeb) -* [libusb](https://github.com/libusb/libusb) -* [VulkanMemoryAllocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) -* [sirit](https://github.com/eden-emulator/sirit) -* [httplib](https://github.com/yhirose/cpp-httplib) - if `ENABLE_QT_UPDATE_CHECKER` or `ENABLE_WEB_SERVICE` are on -* [cpp-jwt](https://github.com/arun11299/cpp-jwt) 1.4+ - if `ENABLE_WEB_SERVICE` is on -* [unordered-dense](https://github.com/martinus/unordered_dense) -* [mcl](https://github.com/azahar-emu/mcl) - subject to removal - -On amd64: -* [xbyak](https://github.com/herumi/xbyak) - 7.22 or earlier is recommended -* [zycore](https://github.com/zyantific/zycore-c) -* [zydis](https://github.com/zyantific/zydis) 4+ -* Note: zydis and zycore-c MUST match. Using one as a system dependency and the other as a bundled dependency WILL break things - -On aarch64 OR if `DYNARMIC_TESTS` is on: -* [oaknut](https://github.com/merryhime/oaknut) 2.0.1+ - -On riscv64: -* [biscuit](https://github.com/lioncash/biscuit) 0.9.1+ - -## Commands - -These are commands to install all necessary dependencies on various Linux and BSD distributions, as well as macOS. Always review what you're running before you hit Enter! - -Click on the arrows to expand. - -
-Arch Linux - -```sh -sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl2 zlib zstd zip unzip zydis zycore vulkan-headers vulkan-utility-libraries libusb spirv-tools spirv-headers -``` - -* Building with QT Web Engine requires `qt6-webengine` as well. -* Proper Wayland support requires `qt6-wayland` -* GCC 11 or later is required. -
- -
-Ubuntu, Debian, Mint Linux - -```sh -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. -* To enable QT Web Engine, add `-DYUZU_USE_QT_WEB_ENGINE=ON` when running CMake. -
- -
-Fedora Linux - -```sh -sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel json-devel libtool libusb1-devel libzstd-devel lz4-devel nasm ninja-build openssl-devel pulseaudio-libs-devel qt6-linguist qt6-qtbase{-private,}-devel qt6-qtwebengine-devel qt6-qtmultimedia-devel speexdsp-devel wayland-devel zlib-devel ffmpeg-devel libXext-devel -``` - -* Force system libraries via CMake arguments: - * SDL2: `-DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF` - * FFmpeg: `-DYUZU_USE_EXTERNAL_FFMPEG=OFF` -* [RPM Fusion](https://rpmfusion.org/) is required for `ffmpeg-devel` -* Fedora 32 or later is required. -* Fedora 36+ users with GCC 12 need Clang and should configure CMake with: -
- -
-macOS - -Install dependencies from **[Homebrew](https://brew.sh/)** - -```sh -brew install autoconf automake boost ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zstd cmake Catch2 molten-vk vulkan-loader spirv-tools -``` - -If you are compiling on Intel Mac, or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` with `/usr/local`. - -To run with MoltenVK, install additional dependencies: -```sh -brew install molten-vk vulkan-loader -``` - -
- -
-FreeBSD - -``` -devel/cmake -devel/sdl20 -devel/boost-libs -devel/catch2 -devel/libfmt -devel/nlohmann-json -devel/ninja -devel/nasm -devel/autoconf -devel/pkgconf -devel/qt6-base - -net/enet - -multimedia/ffnvcodec-headers -multimedia/ffmpeg - -audio/opus - -archivers/liblz4 - -lang/gcc12 - -graphics/glslang -graphics/vulkan-utility-libraries -``` - -If using FreeBSD 12 or prior, use `devel/pkg-config` instead. -
- -
-OpenBSD - -```sh -pkg_add -u -pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gmake llvm-19.1.7p3 qt6 jq fmt nlohmann-json enet boost vulkan-utility-libraries vulkan-headers spirv-headers spirv-tools catch2 sdl2 libusb1.1.0.27 -``` -
- -
-Solaris / OpenIndiana - -Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability. - -Run the usual update + install of essential toolings: `sudo pkg update && sudo pkg install git cmake`. - -- **gcc**: `sudo pkg install developer/gcc-14`. -- **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`. - -Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`. -
- -
-MSYS2 - -* Open the `MSYS2 MinGW 64-bit` shell (`mingw64.exe`) -* Download and install all dependencies using: - * `pacman -Syu git make mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` -* Add MinGW binaries to the PATH: - * `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc` -* Add VulkanSDK to the PATH: - * `echo 'PATH=$(readlink -e /c/VulkanSDK/*/Bin/):$PATH' >> ~/.bashrc` -
- -## All Done - -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 d170818d10..e60384e8ab 100644 --- a/docs/Development.md +++ b/docs/Development.md @@ -1,3 +1,22 @@ +# Development + +* **Windows**: [Windows Building Guide](./build/Windows.md) +* **Linux**: [Linux Building Guide](./build/Linux.md) +* **Android**: [Android Building Guide](./build/Android.md) +* **Solaris**: [Solaris Building Guide](./build/Solaris.md) +* **FreeBSD**: [FreeBSD Building Guide](./build/FreeBSD.md) +* **macOS**: [macOS Building Guide](./build/macOS.md) + +# CPM + +CPM (CMake Package Manager) is the preferred method of managing dependencies within Eden. Documentation on adding dependencies/using CPMUtil is in the works. + +Notes: +- `YUZU_USE_CPM` is set by default on MSVC and Android. Other platforms should use this if certain "required" system dependencies (e.g. OpenSSL) are broken or missing +- `CPMUTIL_DEFAULT_SYSTEM` can be set to `OFF` to force the usage of bundled dependencies. This can marginally decrease the final package size. +- When adding new prebuilt dependencies a la OpenSSL, SDL2, or FFmpeg, there *must* be a CMake option made available to forcefully download this bundle. See the OpenSSL implementation in the root CMakeLists for an example. + * This is necessary to allow for creation of fully-qualified source packs that allow for offline builds after download (some package managers and distros enforce this) + # Guidelines ## License Headers @@ -17,8 +36,6 @@ FIX=true .ci/license-header.sh git commit --amend -a --no-edit ``` -If the work is licensed/vendored from other people or projects, you may omit the license headers. Additionally, if you wish to retain authorship over a piece of code, you may attribute it to yourself; however, the code may be changed at any given point and brought under the attribution of Eden. - ## Pull Requests Pull requests are only to be merged by core developers when properly tested and discussions conclude on Discord or other communication channels. Labels are recommended but not required. However, all PRs MUST be namespaced and optionally typed: ``` @@ -31,7 +48,7 @@ Pull requests are only to be merged by core developers when properly tested and - The level of namespacing is generally left to the committer's choice. - However, we never recommend going more than two levels *except* in `hle`, in which case you may go as many as four levels depending on the specificity of your changes. -- Ocassionally, up to two additional namespaces may be provided for more clarity. +- Ocassionally, up to two namespaces may be provided for more clarity. * Changes that affect the entire project (sans CMake changes) should be namespaced as `meta`. - Maintainers are permitted to change namespaces at will. - Commits within PRs are not required to be namespaced, but it is highly recommended. diff --git a/docs/Options.md b/docs/Options.md deleted file mode 100644 index d19aab63f6..0000000000 --- a/docs/Options.md +++ /dev/null @@ -1,69 +0,0 @@ -# CMake Options - -To change these options, add `-DOPTION_NAME=NEWVALUE` to the command line. - -- On Qt Creator, go to Project -> Current Configuration - -Notes: -- Defaults are marked per-platform. -- "Non-UNIX" just means Windows/MSVC and Android (yes, macOS is UNIX -- Android generally doesn't need to change anything; if you do, go to `src/android/app/build.gradle.kts` -- To set a boolean variable to on, use `ON` for the value; to turn it off, use `OFF` -- If a variable is mentioned as being e.g. "ON" for a specific platform(s), that means it is defaulted to OFF on others -- TYPE is always boolean unless otherwise specified -- Format: - * `OPTION_NAME` (TYPE DEFAULT) DESCRIPTION - -## Options - -- `YUZU_USE_CPM` (ON for non-UNIX) Use CPM to fetch system dependencies (fmt, boost, etc) if needed. Externals will still be fetched. See the [CPM](CPM.md) and [Deps](Deps.md) docs for more info. -- `ENABLE_WEB_SERVICE` (ON) Enable multiplayer service -- `ENABLE_WIFI_SCAN` (OFF) Enable WiFi scanning (requires iw on Linux) - experimental -- `YUZU_USE_BUNDLED_FFMPEG` (ON for non-UNIX) Download (Windows, Android) or build (UNIX) bundled FFmpeg -- `ENABLE_CUBEB` (ON) Enables the cubeb audio backend -- `YUZU_TESTS` (ON) Compile tests - requires Catch2 -- `YUZU_USE_PRECOMPILED_HEADERS` (ON for non-UNIX) Use precompiled headers -- `YUZU_DOWNLOAD_ANDROID_VVL` (ON) Download validation layer binary for Android -- `YUZU_ENABLE_LTO` (OFF) Enable link-time optimization - * Not recommended on Windows - * UNIX may be better off appending `-flto=thin` to compiler args -- `YUZU_DOWNLOAD_TIME_ZONE_DATA` (ON) Always download time zone binaries - * Currently, build fails without this -- `YUZU_USE_FASTER_LD` (ON) Check if a faster linker is available - * Only available on UNIX -- `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 -- `YUZU_USE_BUNDLED_OPENSSL` (ON for MSVC) Download bundled OpenSSL build - * Always on for Android - * Unavailable on OpenBSD - -The following options are desktop only: -- `ENABLE_SDL2` (ON) Enable the SDL2 desktop, audio, and input frontend (HIGHLY RECOMMENDED!) - * Unavailable on Android -- `YUZU_USE_EXTERNAL_SDL2` (ON for non-UNIX) Compiles SDL2 from source -- `YUZU_USE_BUNDLED_SDL2` (ON for MSVC) Download a prebuilt SDL2 - * Unavailable on OpenBSD - * Only enabled if YUZU_USE_CPM and ENABLE_SDL2 are both ON -- `ENABLE_LIBUSB` (ON) Enable the use of the libusb input frontend (HIGHLY RECOMMENDED) -- `ENABLE_OPENGL` (ON) Enable the OpenGL graphics frontend - * Unavailable on Windows/ARM64 and Android -- `ENABLE_QT` (ON) Enable the Qt frontend (recommended) -- `ENABLE_QT_TRANSLATION` (OFF) Enable translations for the Qt frontend -- `ENABLE_QT_UPDATE_CHECKER` (OFF) Enable update checker for the Qt frontend -- `YUZU_USE_BUNDLED_QT` (ON for MSVC) Download bundled Qt binaries - * Note that using **system Qt** requires you to include the Qt CMake directory in `CMAKE_PREFIX_PATH`, e.g: - * `-DCMAKE_PREFIX_PATH=C:/Qt/6.9.0/msvc2022_64/lib/cmake/Qt6` -- `YUZU_QT_MIRROR` (string) What mirror to use for downloading the bundled Qt libraries -- `YUZU_USE_QT_MULTIMEDIA` (OFF) Use QtMultimedia for camera support -- `YUZU_USE_QT_WEB_ENGINE` (OFF) Use QtWebEngine for web applet implementation (requires the huge QtWebEngine dependency; not recommended) -- `USE_DISCORD_PRESENCE` (OFF) Enables Discord Rich Presence (Qt frontend only) -- `YUZU_ROOM` (ON) Enable dedicated room functionality -- `YUZU_ROOM_STANDALONE` (ON) Enable standalone room executable (eden-room) - * Requires `YUZU_ROOM` -- `YUZU_CMD` (ON) Compile the SDL2 frontend (eden-cli) - requires SDL2 -- `YUZU_CRASH_DUMPS` Compile crash dump (Minidump) support" - * Currently only available on Windows and Linux - -See `src/dynarmic/CMakeLists.txt` for additional options--usually, these don't need changed \ No newline at end of file diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 71e79e15ea..0000000000 --- a/docs/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Eden Build Documentation - -This contains documentation created by developers. This contains build instructions, guidelines, instructions/layouts for [cool stuff we made](CPM.md), and more. - -- **[General Build Instructions](Build.md)** -- **[Development Guidelines](Development.md)** -- **[Dependencies](Deps.md)** -- **[CPM - CMake Package Manager](CPM.md)** -- **[Platform-Specific Caveats](Caveats.md)** -- **[User Directory Handling](User.md)** \ No newline at end of file diff --git a/docs/User.md b/docs/User.md deleted file mode 100644 index cfc81063f8..0000000000 --- a/docs/User.md +++ /dev/null @@ -1,11 +0,0 @@ -# User configuration - -## Configuration directories - -Eden will store configuration in the following directories: - -- **Windows**: `%AppData%\Roaming`. -- **Android**: Data is stored internally. -- **Linux, macOS, FreeBSD, Solaris, OpenBSD**: `$XDG_DATA_HOME`, `$XDG_CACHE_HOME`, `$XDG_CONFIG_HOME`. - -If a `user` directory is present in the current working directory, that will override all global configuration directories and the emulator will use that instead. diff --git a/docs/build/Android.md b/docs/build/Android.md index c8ff3a3b1e..4bb1c868b6 100644 --- a/docs/build/Android.md +++ b/docs/build/Android.md @@ -1,41 +1,42 @@ -# Note: These build instructions are a work-in-progress. - -## Dependencies -* [Android Studio](https://developer.android.com/studio) -* [NDK 27+ and CMake 3.22.1](https://developer.android.com/studio/projects/install-ndk#default-version) -* [Git](https://git-scm.com/download) - -### WINDOWS ONLY - Additional Dependencies - * **[Visual Studio 2022 Community](https://visualstudio.microsoft.com/downloads/)** - **Make sure to select "Desktop development with C++" support in the installer. Make sure to update to the latest version if already installed.** - * **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** - **Make sure to select Latest SDK.** - - A convenience script to install the latest SDK is provided in `.ci\windows\install-vulkan-sdk.ps1`. - -## Cloning Eden with Git -``` -git clone --recursive https://git.eden-emu.dev/eden-emu/eden.git -``` -Eden by default will be cloned into - -* `C:\Users\\eden` on Windows -* `~/eden` on Linux and macOS - -## Building -1. Start Android Studio, on the startup dialog select `Open`. -2. Navigate to the `eden/src/android` directory and click on `OK`. -3. In `Build > Select Build Variant`, select `release` or `relWithDebInfo` as the "Active build variant". -4. Build the project with `Build > Make Project` or run it on an Android device with `Run > Run 'app'`. - -## Building with Terminal -1. Download the SDK and NDK from Android Studio. -2. Navigate to SDK and NDK paths. -3. Then set ANDROID_SDK_ROOT and ANDROID_NDK_ROOT in terminal via -`export ANDROID_SDK_ROOT=path/to/sdk` -`export ANDROID_NDK_ROOT=path/to/ndk`. -4. Navigate to `eden/src/android`. -5. Then Build with `./gradlew assembleRelWithDebInfo`. -6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`. - -### Script -A convenience script for building is provided in `.ci/android/build.sh`. The built APK can be put into an `artifacts` directory via `.ci/android/package.sh`. On Windows, these must be done in the Git Bash or MinGW terminal. - -### Additional Resources -https://developer.android.com/studio/intro +# Note: These build instructions are a work-in-progress. + +## Dependencies +* [Android Studio](https://developer.android.com/studio) +* [NDK 25.2.9519653 and CMake 3.22.1](https://developer.android.com/studio/projects/install-ndk#default-version) +* [Git](https://git-scm.com/download) + +### WINDOWS ONLY - Additional Dependencies + * **[Visual Studio 2022 Community](https://visualstudio.microsoft.com/downloads/)** - **Make sure to select "Desktop development with C++" support in the installer. Make sure to update to the latest version if already installed.** + * **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** - **Make sure to select Latest SDK.** + - A convenience script to install the latest SDK is provided in `.ci\windows\install-vulkan-sdk.ps1`. + +## Cloning Eden with Git +``` +git clone --recursive https://git.eden-emu.dev/eden-emu/eden.git +``` +Eden by default will be cloned into - +* `C:\Users\\eden` on Windows +* `~/eden` on Linux +* And wherever on macOS + +## Building +1. Start Android Studio, on the startup dialog select `Open`. +2. Navigate to the `eden/src/android` directory and click on `OK`. +3. In `Build > Select Build Variant`, select `release` or `relWithDebInfo` as the "Active build variant". +4. Build the project with `Build > Make Project` or run it on an Android device with `Run > Run 'app'`. + +## Building with Terminal +1. Download the SDK and NDK from Android Studio. +2. Navigate to SDK and NDK paths. +3. Then set ANDROID_SDK_ROOT and ANDROID_NDK_ROOT in terminal via +`export ANDROID_SDK_ROOT=path/to/sdk` +`export ANDROID_NDK_ROOT=path/to/ndk`. +4. Navigate to `eden/src/android`. +5. Then Build with `./gradlew assemblerelWithDebInfo`. +6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`. + +### Script +A convenience script for building is provided in `.ci/android/build.sh`. The built APK can be put into an `artifacts` directory via `.ci/android/package.sh`. On Windows, these must be done in the Git Bash or MinGW terminal. + +### Additional Resources +https://developer.android.com/studio/intro diff --git a/docs/build/FreeBSD.md b/docs/build/FreeBSD.md new file mode 100644 index 0000000000..475378125c --- /dev/null +++ b/docs/build/FreeBSD.md @@ -0,0 +1,85 @@ +## One word of caution before proceeding. + +This is not the usual or preferred way to build programs on FreeBSD. +As of writing there is no official fresh port available for Eden, but it is in the works. +After it is available you can find a link to the eden-emu fresh port here and on Escary's github repo. +See this build as an AppImage alternative for FreeBSD. + +## Dependencies. +Before we start we need some dependencies. +These dependencies are generally needed to build Eden on FreeBSD. + +``` +devel/cmake +devel/sdl20 +devel/boost-libs +devel/catch2 +devel/libfmt +devel/nlohmann-json +devel/ninja +devel/nasm +devel/autoconf +devel/pkgconf +devel/qt6-base + +multimedia/ffnvcodec-headers +multimedia/ffmpeg + +audio/opus + +archivers/liblz4 + +lang/gcc12 + +graphics/glslang +graphics/vulkan-utility-libraries +``` + +If using FreeBSD 12 or prior, use `devel/pkg-config` instead. + +--- + +### Build preparations: +Run the following command to clone eden with git: +```sh +git clone --recursive https://git.eden-emu.dev/eden-emu/eden +``` +You usually want to add the `--recursive` parameter as it also takes care of the external dependencies for you. + +Now change into the eden directory and create a build directory there: +```sh +cd eden +mkdir build +``` + +Change into that build directory: +```sh +cd build +``` + +#### 1. Building in Release Mode (usually preferred and the most performant choice): +```sh +cmake .. -GNinja -DYUZU_TESTS=OFF +``` + +#### 2. Building in Release Mode with debugging symbols (useful if you want to debug errors for a eventual fix): +```sh +cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_TESTS=ON +``` + +Build the emulator locally: +```sh +ninja +``` + +Optional: If you wish to install eden globally onto your system issue the following command: +```sh +sudo ninja install +``` +OR +```sh +doas -- ninja install +``` + +## OpenSSL +The available OpenSSL port (3.0.17) is out-of-date, and using a bundled static library instead is recommended; to do so, add `-DYUZU_USE_CPM=ON` to your CMake configure command. \ No newline at end of file diff --git a/docs/build/Linux.md b/docs/build/Linux.md new file mode 100644 index 0000000000..be58b451fa --- /dev/null +++ b/docs/build/Linux.md @@ -0,0 +1,138 @@ +### Dependencies + +You'll need to download and install the following to build Eden: + + * [GCC](https://gcc.gnu.org/) v11+ (for C++20 support) & misc + * If GCC 12 is installed, [Clang](https://clang.llvm.org/) v14+ is required for compiling + * [CMake](https://www.cmake.org/) 3.22+ + +The following are handled by Eden's externals: + + * [FFmpeg](https://ffmpeg.org/) + * [SDL2](https://www.libsdl.org/download-2.0.php) 2.0.18+ + * [opus](https://opus-codec.org/downloads/) 1.3+ + +All other dependencies will be downloaded and built by [CPM](https://github.com/cpm-cmake/CPM.cmake/) if `YUZU_USE_CPM` is on, but will always use system dependencies if available: + + * [Boost](https://www.boost.org/users/download/) 1.79.0+ + * [Catch2](https://github.com/catchorg/Catch2) 2.13.7 - 2.13.9 + * [fmt](https://fmt.dev/) 8.0.1+ + * [lz4](http://www.lz4.org) 1.8+ + * [nlohmann_json](https://github.com/nlohmann/json) 3.8+ + * [OpenSSL](https://www.openssl.org/source/) 1.1.1+ + * [ZLIB](https://www.zlib.net/) 1.2+ + * [zstd](https://facebook.github.io/zstd/) 1.5+ + * [enet](http://enet.bespin.org/) 1.3+ + * [cubeb](https://github.com/mozilla/cubeb) + * [SimpleIni](https://github.com/brofield/simpleini) + +Certain other dependencies (httplib, jwt, sirit, etc.) will be fetched by CPM regardless. System packages *can* be used for these libraries but this is generally not recommended. + +Dependencies are listed here as commands that can be copied/pasted. Of course, they should be inspected before being run. + +- Arch / Manjaro: + - `sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia sdl2 zlib zstd zip unzip` + - Building with QT Web Engine requires `qt6-webengine` as well. + - Proper wayland support requires `qt6-wayland` + - GCC 11 or later is required. + +- Ubuntu / Linux Mint / Debian: + - `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` + - Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required. + - Users need to manually specify building with QT Web Engine enabled. This is done using the parameter `-DYUZU_USE_QT_WEB_ENGINE=ON` when running CMake. + - Users need to manually disable building SDL2 from externals if they intend to use the version provided by their system by adding the parameters `-DYUZU_USE_EXTERNAL_SDL2=OFF` + +```sh +git submodule update --init --recursive +cmake .. -GNinja -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11 +``` + +- Fedora: + - `sudo dnf install autoconf ccache cmake fmt-devel gcc{,-c++} glslang hidapi-devel json-devel libtool libusb1-devel libzstd-devel lz4-devel nasm ninja-build openssl-devel pulseaudio-libs-devel qt6-linguist qt6-qtbase{-private,}-devel qt6-qtwebengine-devel qt6-qtmultimedia-devel speexdsp-devel wayland-devel zlib-devel ffmpeg-devel libXext-devel` + - Fedora 32 or later is required. + - Due to GCC 12, Fedora 36 or later users need to install `clang`, and configure CMake to use it via `-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang` + - CMake arguments to force system libraries: + - SDL2: `-DYUZU_USE_BUNDLED_SDL2=OFF -DYUZU_USE_EXTERNAL_SDL2=OFF` + - FFmpeg: `-DYUZU_USE_EXTERNAL_FFMPEG=OFF` + - [RPM Fusion](https://rpmfusion.org/) (free) is required to install `ffmpeg-devel` + +### Cloning Eden with Git + +**Master:** + +```bash +git clone --recursive https://git.eden-emu.dev/eden-emu/eden +cd eden +``` + +The `--recursive` option automatically clones the required Git submodules. + +### Building Eden in Release Mode (Optimised) + +If you need to run ctests, you can disable `-DYUZU_TESTS=OFF` and install Catch2. + +```bash +mkdir build && cd build +cmake .. -GNinja -DYUZU_TESTS=OFF +ninja +sudo ninja install +``` +You may also want to include support for Discord Rich Presence by adding `-DUSE_DISCORD_PRESENCE=ON` after `cmake ..` + +`-DYUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS=OFF` might be needed if ninja command failed with `undefined reference to symbol 'spvOptimizerOptionsCreate`, reason currently unknown + +Optionally, you can use `cmake-gui ..` to adjust various options (e.g. disable the Qt GUI). + +### Building Eden in Debug Mode (Slow) + +```bash +mkdir build && cd build +cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DYUZU_TESTS=OFF +ninja +``` + +### Building with debug symbols + +```bash +mkdir build && cd build +cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU -DYUZU_TESTS=OFF +ninja +``` + +### Building with Scripts +A convenience script for building is provided in `.ci/linux/build.sh`. You must provide an arch target for optimization, e.g. `.ci/linux/build.sh amd64`. Valid targets: +- `legacy`: x86_64 generic, only needed for CPUs older than 2013 or so +- `amd64`: x86_64-v3, for CPUs newer than 2013 or so +- `steamdeck` / `zen2`: For Steam Deck or Zen >= 2 AMD CPUs (untested on Intel) +- `rog-ally` / `allyx` / `zen4`: For ROG Ally X or Zen >= 4 AMD CPUs (untested on Intel) +- `aarch64`: For armv8-a CPUs, older than mid-2021 or so +- `armv9`: For armv9-a CPUs, newer than mid-2021 or so +- `native`: Optimize to your native host architecture + +Extra flags to pass to CMake should be passed after the arch target. + +Additional environment variables can be used to control building: +- `NPROC`: Number of threads to use for compilation (defaults to all) +- `TARGET`: Set to `appimage` to disable standalone `eden-cli` and `eden-room` executables +- `BUILD_TYPE`: Sets the build type to use. Defaults to `Release` + +The following environment variables are boolean flags. Set to `true` to enable or `false` to disable: +- `DEVEL` (default FALSE): Disable Qt update checker +- `USE_WEBENGINE` (default FALSE): Enable Qt WebEngine +- `USE_MULTIMEDIA` (default TRUE): Enable Qt Multimedia + +After building, an AppImage can be packaged via `.ci/linux/package.sh`. This script takes the same arch targets as the build script. If the build was created in a different directory, you can specify its path relative to the source directory, e.g. `.ci/linux/package.sh amd64 build-appimage`. Additionally, set the `DEVEL` environment variable to `true` to change the app name to `Eden Nightly`. + +### Running without installing + +After building, the binaries `eden` and `eden-cmd` (depending on your build options) will end up in `build/bin/`. + +```bash +# SDL +cd build/bin/ +./eden-cmd + +# Qt +cd build/bin/ +./eden +``` diff --git a/docs/build/Solaris.md b/docs/build/Solaris.md new file mode 100644 index 0000000000..d4cfdbb6a9 --- /dev/null +++ b/docs/build/Solaris.md @@ -0,0 +1,51 @@ +# Building for Solaris + +## Dependencies. +Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability. + +Run the usual update + install of essential toolings: `sudo pkg update && sudo pkg install git cmake`. + +- **gcc**: `sudo pkg install developer/gcc-14`. +- **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`. + +Then install the libraies: `sudo pkg install qt6 boost glslang libzip library/lz4 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`. + +### Building + +Clone eden with git `git clone --recursive https://git.eden-emu.dev/eden-emu/eden` + +```sh +# Needed for some dependencies that call cc directly (tz) +echo '#!/bin/sh' >cc +echo 'gcc $@' >>cc +chmod +x cc +export PATH="$PATH:$PWD" +``` + +Patch for FFmpeg: +```sh +sed -i 's/ make / gmake /' externals/ffmpeg/CMakeFiles/ffmpeg-build.dir/build.make +``` + +- **Configure**: `cmake -B build -DYUZU_USE_CPM=ON -DCMAKE_CXX_FLAGS="-I/usr/include/SDL2" -DCMAKE_C_FLAGS="-I/usr/include/SDL2"`. +- **Build**: `cmake --build build`. +- **Installing**: `sudo cmake --install build`. + +### Running + +Default Mesa is a bit outdated, the following environment variables should be set for a smoother experience: +```sh +export MESA_GL_VERSION_OVERRIDE=4.6 +export MESA_GLSL_VERSION_OVERRIDE=460 +export MESA_EXTENSION_MAX_YEAR=2025 +export MESA_DEBUG=1 +export MESA_VK_VERSION_OVERRIDE=1.3 +# Only if nvidia/intel drm drivers cause crashes, will severely hinder performance +export LIBGL_ALWAYS_SOFTWARE=1 +``` + +### Notes + +- Modify the generated ffmpeg.make (in build dir) if using multiple threads (base system `make` doesn't use `-j4`, so change for `gmake`). +- If using OpenIndiana, due to a bug in SDL2 cmake configuration; Audio driver defaults to SunOS ``, which does not exist on OpenIndiana. +- System OpenSSL generally does not work. Instead, use `-DYUZU_USE_CPM=ON` to use a bundled static OpenSSL, or build a system dependency from source. \ No newline at end of file diff --git a/docs/build/Windows.md b/docs/build/Windows.md new file mode 100644 index 0000000000..3b8c459073 --- /dev/null +++ b/docs/build/Windows.md @@ -0,0 +1,193 @@ +# THIS GUIDE IS INTENDED FOR DEVELOPERS ONLY, SUPPORT WILL ONLY BE GIVEN IF YOU'RE A DEVELOPER. + +## Method I: MSVC Build for Windows + +### Minimal Dependencies + +On Windows, all library dependencies are automatically included within the `externals` folder, or can be downloaded on-demand. To build Eden, you need to install: + + * **[Visual Studio 2022 Community](https://visualstudio.microsoft.com/downloads/)** - **Make sure to select C++ support in the installer. Make sure to update to the latest version if already installed.** + * **[CMake](https://cmake.org/download/)** - Used to generate Visual Studio project files. Does not matter if either 32-bit or 64-bit version is installed. + * **[Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows)** - **Make sure to select Latest SDK.** + - A convenience script to install the latest SDK is provided in `.ci\windows\install-vulkan-sdk.ps1`. + + ![2](https://i.imgur.com/giDwuTm.png) + + * **Git** - We recommend [Git for Windows](https://gitforwindows.org). + + ![3](https://i.imgur.com/UeSzkBw.png) + + * While installing Git Bash, you should tell it to include Git in your system path. (Choose the "Git from the command line and also from 3rd-party software" option.) If you missed that, don't worry, you'll just have to manually tell CMake where your git.exe is, since it's used to include version info into the built executable. + + ![4](https://i.imgur.com/x0rRs1t.png) + +### Cloning Eden with Git + +**Master:** + ```cmd + git clone --recursive https://git.eden-emu.dev/eden-emu/eden + cd eden + ``` + + ![9](https://i.imgur.com/CcxIAht.png) + +* *(Note: eden by default downloads to `C:\Users\\eden` (Master) + +### Building + +* Open the CMake GUI application and point it to the `eden` (Master) + + ![10](https://i.imgur.com/qOslIWv.png) + +* For the build directory, use a `/build` subdirectory inside the source directory or some other directory of your choice. (Tell CMake to create it.) + +* Click the "Configure" button and choose `Visual Studio 17 2022`, with `x64` for the optional platform. + + ![12](https://i.imgur.com/DKiREaK.png) + + * *(Note: If you used GitHub's own app to clone, run `git submodule update --init --recursive` to get the remaining dependencies)* + + * *(You may also want to disable `YUZU_TESTS` in this case since Catch2 is not yet supported with this.)* + + ![13](https://user-images.githubusercontent.com/22451773/180585999-07316d6e-9751-4d11-b957-1cf57cd7cd58.png) + +* Click "Generate" to create the project files. + + ![15](https://i.imgur.com/5LKg92k.png) + +* Open the solution file `yuzu.sln` in Visual Studio 2022, which is located in the build folder. + + ![16](https://i.imgur.com/208yMml.png) + +* Depending if you want a graphical user interface or not (`eden` has the graphical user interface, while `eden-cmd` doesn't), select `eden` or `eden-cmd` in the Solution Explorer, right-click and `Set as StartUp Project`. + + ![17](https://i.imgur.com/nPMajnn.png) ![18](https://i.imgur.com/BDMLzRZ.png) + +* Select the appropriate build type, Debug for debug purposes or Release for performance (in case of doubt choose Release). + + ![19](https://i.imgur.com/qxg4roC.png) + +* Right-click the project you want to build and press Build in the submenu or press F5. + + ![20](https://i.imgur.com/CkQgOFW.png) + +## Method II: MinGW-w64 Build with MSYS2 + +### Prerequisites to install + +* [MSYS2](https://www.msys2.org) +* [Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows) - **Make sure to select Latest SDK.** +* Make sure to follow the instructions and update to the latest version by running `pacman -Syu` as many times as needed. + +### Install eden dependencies for MinGW-w64 + +* Open the `MSYS2 MinGW 64-bit` (mingw64.exe) shell +* Download and install all dependencies using: `pacman -Syu git make mingw-w64-x86_64-SDL2 mingw-w64-x86_64-cmake mingw-w64-x86_64-python-pip mingw-w64-x86_64-qt6 mingw-w64-x86_64-toolchain autoconf libtool automake-wrapper` +* Add MinGW binaries to the PATH: `echo 'PATH=/mingw64/bin:$PATH' >> ~/.bashrc` +* Add glslangValidator to the PATH: `echo 'PATH=$(readlink -e /c/VulkanSDK/*/Bin/):$PATH' >> ~/.bashrc` + +### Clone the eden repository with Git + + ```bash + git clone --recursive https://git.eden-emu.dev/eden-emu/eden + cd eden + ``` + +### Run the following commands to build eden (dynamically linked build) + +```bash +mkdir build && cd build +cmake -G "MSYS Makefiles" -DYUZU_TESTS=OFF .. +make -j$(nproc) +# test eden out with +./bin/eden.exe +``` + +* *(Note: This build is not a static build meaning that you need to include all of the DLLs with the .exe in order to use it!)* + +e.g. +```Bash +cp externals/ffmpeg-*/bin/*.dll bin/ +``` + +Bonus Note: Running programs from inside `MSYS2 MinGW x64` shell has a different %PATH% than directly from explorer. This different %PATH% has the locations of the other DLLs required. +![image](https://user-images.githubusercontent.com/190571/165000848-005e8428-8a82-41b1-bb4d-4ce7797cdac8.png) + + +### Building without Qt (Optional) + +Doesn't require the rather large Qt dependency, but you will lack a GUI frontend: + + * Pass the `-DENABLE_QT=no` flag to cmake + +## Method III: CLion Environment Setup + +### Minimal Dependencies + +To build eden, you need to install the following: + +* [CLion](https://www.jetbrains.com/clion/) - This IDE is not free; for a free alternative, check Method I +* [Vulkan SDK](https://vulkan.lunarg.com/sdk/home#windows) - Make sure to select the Latest SDK. + +### Cloning eden with CLion + +* Clone the Repository: + +![1](https://user-images.githubusercontent.com/42481638/216899046-0d41d7d6-8e4d-4ed2-9587-b57088af5214.png) +![2](https://user-images.githubusercontent.com/42481638/216899061-b2ea274a-e88c-40ae-bf0b-4450b46e9fea.png) +![3](https://user-images.githubusercontent.com/42481638/216899076-0e5988c4-d431-4284-a5ff-9ecff973db76.png) + + + +### Building & Setup + +* Once Cloned, You will be taken to a prompt like the image below: + +![4](https://user-images.githubusercontent.com/42481638/216899092-3fe4cec6-a540-44e3-9e1e-3de9c2fffc2f.png) + +* Set the settings to the image below: +* Change `Build type: Release` +* Change `Name: Release` +* Change `Toolchain Visual Studio` +* Change `Generator: Let CMake decide` +* Change `Build directory: build` + +![5](https://user-images.githubusercontent.com/42481638/216899164-6cee8482-3d59-428f-b1bc-e6dc793c9b20.png) + +* Click OK; now Clion will build a directory and index your code to allow for IntelliSense. Please be patient. +* Once this process has been completed (No loading bar bottom right), you can now build eden +* In the top right, click on the drop-down menu, select all configurations, then select eden + +![6](https://user-images.githubusercontent.com/42481638/216899226-975048e9-bc6d-4ec1-bc2d-bd8a1e15ed04.png) + +* Now run by clicking the play button or pressing Shift+F10, and eden will auto-launch once built. + +![7](https://user-images.githubusercontent.com/42481638/216899275-d514ec6a-e563-470e-81e2-3e04f0429b68.png) + +## Building from the command line with MSVC + +```cmd +git clone --recursive https://git.eden-emu.dev/eden-emu/eden +cd eden +mkdir build +cd build +cmake .. -G "Visual Studio 17 2022" -A x64 +cmake --build . --config Release +``` + +### Building with Scripts +A convenience script for building is provided in `.ci/windows/build.sh`. You must run this with Bash, e.g. Git Bash or MinGW TTY. To use this script, you must have windeployqt installed (usually bundled with Qt) and set the `WINDEPLOYQT` environment variable to its canonical Bash location, e.g. `WINDEPLOYQT="/c/Qt/6.9.1/msvc2022_64/bin/windeployqt6.exe" .ci/windows/build.sh`. + +Extra CMake flags should be placed in the arguments of the script. + +Additional environment variables can be used to control building: +- `BUILD_TYPE`: Sets the build type to use. Defaults to `Release` + +The following environment variables are boolean flags. Set to `true` to enable or `false` to disable: +- `DEVEL` (default FALSE): Disable Qt update checker +- `USE_WEBENGINE` (default FALSE): Enable Qt WebEngine +- `USE_MULTIMEDIA` (default TRUE): Enable Qt Multimedia +- `BUNDLE_QT` (default FALSE): Use bundled Qt + * Note that using system Qt requires you to include the Qt CMake directory in `CMAKE_PREFIX_PATH`, e.g. `.ci/windows/build.sh -DCMAKE_PREFIX_PATH=C:/Qt/6.9.0/msvc2022_64/lib/cmake/Qt6` + +After building, a zip can be packaged via `.ci/windows/package.sh`. Note that you must have 7-zip installed and in your PATH. The resulting zip will be placed into `artifacts` in the source directory. diff --git a/docs/build/macOS.md b/docs/build/macOS.md new file mode 100644 index 0000000000..6cb62273cb --- /dev/null +++ b/docs/build/macOS.md @@ -0,0 +1,105 @@ +Please note this article is intended for development, and eden on macOS is not currently ready for regular use. + +This article was written for developers. eden support for macOS is not ready for casual use. + +## Method I: ninja +--- +If you are compiling on Intel Mac or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` to `/usr/local`. + +Install dependencies from Homebrew: +```sh +brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zlib zstd cmake Catch2 molten-vk vulkan-loader +``` + +Clone the repo +```sh +git clone --recursive https://git.eden-emu.dev/eden-emu/eden + +cd eden +``` + +Build for release +```sh +mkdir build && cd build + +export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake" + +export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib + +cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=ON -DENABLE_LIBUSB=OFF -DCLANG_FORMAT=ON -DSDL2_DISABLE_INSTALL=ON -DSDL_ALTIVEC=ON + +ninja +``` + +You may also want to include support for Discord Rich Presence by adding `-DUSE_DISCORD_PRESENCE=ON` after `cmake ..` + +Build with debug symbols (vcpkg is not currently used due to broken boost-context library): +```sh +mkdir build && cd build +export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake" +cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF +ninja +``` + +Run the output: +``` +bin/eden.app/Contents/MacOS/eden +``` + +## Method II: Xcode + +--- +If you are compiling on Intel Mac or are using a Rosetta Homebrew installation, you must replace all references of `/opt/homebrew` to `/usr/local`. + +Install dependencies from Homebrew: +```sh +brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@6 sdl2 speexdsp zlib zlib zstd cmake Catch2 molten-vk vulkan-loader +``` + +Clone the repo +```sh +git clone --recursive https://git.eden-emu.dev/eden-emu/eden + +cd eden +``` + +Build for release +```sh +mkdir build && cd build + +export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake" + +export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib + +cmake .. -GXcode -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=ON -DENABLE_LIBUSB=OFF -DCLANG_FORMAT=ON -DSDL2_DISABLE_INSTALL=ON -DSDL_ALTIVEC=ON + +xcodebuild build -project eden.xcodeproj -scheme "eden" -configuration "RelWithDebInfo" +``` + +You may also want to include support for Discord Rich Presence by adding `-DUSE_DISCORD_PRESENCE=ON` after `cmake ..` + +Build with debug symbols (vcpkg is not currently used due to broken boost-context library): +```sh +mkdir build && cd build +export Qt6_DIR="/opt/homebrew/opt/qt@6/lib/cmake" +cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF +ninja +``` + +Run the output: +``` +bin/eden.app/Contents/MacOS/eden +``` + +--- + +To run with MoltenVK, install additional dependencies: +```sh +brew install molten-vk vulkan-loader +``` + +Run with Vulkan loader path: +```sh +export LIBVULKAN_PATH=/opt/homebrew/lib/libvulkan.dylib +bin/eden.app/Contents/MacOS/eden +``` \ No newline at end of file diff --git a/docs/img/creator-1.png b/docs/img/creator-1.png deleted file mode 100644 index 14d679cfbb..0000000000 Binary files a/docs/img/creator-1.png and /dev/null differ diff --git a/docs/scripts/Linux.md b/docs/scripts/Linux.md deleted file mode 100644 index 8b18e41ced..0000000000 --- a/docs/scripts/Linux.md +++ /dev/null @@ -1,31 +0,0 @@ -# Linux Build Scripts - -* Provided script: `.ci/linux/build.sh` -* Must specify arch target, e.g.: `.ci/linux/build.sh amd64` -* Valid targets: - * `native`: Optimize to your native host architecture - * `legacy`: x86\_64 generic, only needed for CPUs older than 2013 or so - * `amd64`: x86\_64-v3, for CPUs newer than 2013 or so - * `steamdeck` / `zen2`: For Steam Deck or Zen >= 2 AMD CPUs (untested on Intel) - * `rog-ally` / `allyx` / `zen4`: For ROG Ally X or Zen >= 4 AMD CPUs (untested on Intel) - * `aarch64`: For armv8-a CPUs, older than mid-2021 or so - * `armv9`: For armv9-a CPUs, newer than mid-2021 or so -* Extra CMake flags go after the arch target. - -### Environment Variables - -* `NPROC`: Number of compilation threads (default: all cores) -* `TARGET`: Set `appimage` to disable standalone `eden-cli` and `eden-room` -* `BUILD_TYPE`: Build type (default: `Release`) - -Boolean flags (set `true` to enable, `false` to disable): - -* `DEVEL` (default `FALSE`): Disable Qt update checker -* `USE_WEBENGINE` (default `FALSE`): Enable Qt WebEngine -* `USE_MULTIMEDIA` (default `FALSE`): Enable Qt Multimedia - -* AppImage packaging script: `.ci/linux/package.sh` - - * Accepts same arch targets as build script - * Use `DEVEL=true` to rename app to `Eden Nightly` - * This should generally not be used unless in a tailor-made packaging environment (e.g. Actions/CI) \ No newline at end of file diff --git a/docs/scripts/Windows.md b/docs/scripts/Windows.md deleted file mode 100644 index e60c2119a2..0000000000 --- a/docs/scripts/Windows.md +++ /dev/null @@ -1,29 +0,0 @@ -# Windows Build Scripts - -* A convenience script for building is provided in `.ci/windows/build.sh`. -* You must run this with Bash, e.g. Git Bash or the MinGW TTY. -* To use this script, you must have `windeployqt` installed (usually bundled with Qt) and set the `WINDEPLOYQT` environment variable to its canonical Bash location: - * `WINDEPLOYQT="/c/Qt/6.9.1/msvc2022_64/bin/windeployqt6.exe" .ci/windows/build.sh`. -* You can use `aqtinstall`, more info on and - - -* Extra CMake flags should be placed in the arguments of the script. - -#### Additional environment variables can be used to control building: - -* `BUILD_TYPE` (default `Release`): Sets the build type to use. - -* The following environment variables are boolean flags. Set to `true` to enable or `false` to disable: - - * `DEVEL` (default FALSE): Disable Qt update checker - * `USE_WEBENGINE` (default FALSE): Enable Qt WebEngine - * `USE_MULTIMEDIA` (default FALSE): Enable Qt Multimedia - * `BUNDLE_QT` (default FALSE): Use bundled Qt - - * Note that using **system Qt** requires you to include the Qt CMake directory in `CMAKE_PREFIX_PATH` - * `.ci/windows/build.sh -DCMAKE_PREFIX_PATH=C:/Qt/6.9.0/msvc2022_64/lib/cmake/Qt6` - -* After building, a zip can be packaged via `.ci/windows/package.sh`. You must have 7-zip installed and in your PATH. - * The resulting zip will be placed into `artifacts` in the source directory. - - diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index aba5451b6d..b209b48db9 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -1,6 +1,3 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - # SPDX-FileCopyrightText: 2025 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later @@ -10,6 +7,8 @@ # TODO(crueter): A lot of this should be moved to the root. # otherwise we have to do weird shenanigans with library linking and stuff +# Explicitly include CPMUtil here since we have a separate cpmfile for externals +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) # Explicitly declare this option here to propagate to the oaknut CPM call @@ -34,7 +33,7 @@ endif() # Xbyak (also used by Dynarmic, so needs to be added first) if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) - if (PLATFORM_SUN OR PLATFORM_OPENBSD) + if (PLATFORM_SUN) AddJsonPackage(xbyak_sun) else() AddJsonPackage(xbyak) @@ -54,27 +53,29 @@ endif() # Glad add_subdirectory(glad) -# libusb -if (ENABLE_LIBUSB) - add_subdirectory(libusb) -endif() +# mbedtls +AddJsonPackage(mbedtls) -# VMA -AddJsonPackage(vulkan-memory-allocator) +if (mbedtls_ADDED) + target_include_directories(mbedtls PUBLIC ${mbedtls_SOURCE_DIR}/include) -if (VulkanMemoryAllocator_ADDED) - if (CXX_CLANG) - target_compile_options(VulkanMemoryAllocator INTERFACE - -Wno-unused-variable - ) - elseif(MSVC) - target_compile_options(VulkanMemoryAllocator INTERFACE - /wd4189 - ) + if (NOT MSVC) + target_compile_options(mbedcrypto PRIVATE + -Wno-unused-but-set-variable + -Wno-string-concatenation) endif() endif() +# libusb +if (ENABLE_LIBUSB AND NOT TARGET libusb::usb) + add_subdirectory(libusb) +endif() + # Sirit +# TODO(crueter): spirv-tools doesn't work w/ system +set(SPIRV_WERROR OFF) +AddJsonPackage(spirv-headers) + AddJsonPackage(sirit) if(MSVC AND USE_CCACHE AND sirit_ADDED) @@ -82,8 +83,6 @@ if(MSVC AND USE_CCACHE AND sirit_ADDED) 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 @@ -97,7 +96,15 @@ if (ENABLE_WEB_SERVICE) endif() # unordered_dense -AddJsonPackage(unordered-dense) +AddPackage( + NAME unordered_dense + REPO "Lizzie841/unordered_dense" + SHA e59d30b7b1 + HASH 71eff7bd9ba4b9226967bacd56a8ff000946f8813167cb5664bb01e96fb79e4e220684d824fe9c59c4d1cc98c606f13aff05b7940a1ed8ab3c95d6974ee34fa0 + FIND_PACKAGE_ARGUMENTS "CONFIG" + OPTIONS + "UNORDERED_DENSE_INSTALL OFF" +) # FFMpeg if (YUZU_USE_BUNDLED_FFMPEG) @@ -108,9 +115,38 @@ if (YUZU_USE_BUNDLED_FFMPEG) set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE) endif() +# Vulkan-Headers + +# TODO(crueter): Vk1.4 impl + +AddJsonPackage( + NAME vulkan-headers + BUNDLED_PACKAGE ${YUZU_USE_EXTERNAL_VULKAN_HEADERS} +) + +# Vulkan-Utility-Libraries +AddJsonPackage( + NAME vulkan-utility-libraries + BUNDLED_PACKAGE ${YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES} +) + +# SPIRV Tools +AddJsonPackage( + NAME spirv-tools + BUNDLED_PACKAGE ${YUZU_USE_EXTERNAL_VULKAN_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() + # TZDB (Time Zone Database) add_subdirectory(nx_tzdb) +# VMA +AddJsonPackage(vulkan-memory-allocator) + if (NOT TARGET LLVM::Demangle) add_library(demangle demangle/ItaniumDemangle.cpp) target_include_directories(demangle PUBLIC ./demangle) @@ -207,7 +243,7 @@ if (YUZU_CRASH_DUMPS AND NOT TARGET libbreakpad_client) file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES ${breakpad_SOURCE_DIR}/src/client/mac/*.cc ${breakpad_SOURCE_DIR}/src/common/mac/*.cc) list(APPEND LIBBREAKPAD_CLIENT_SOURCES ${breakpad_SOURCE_DIR}/src/common/mac/MachIPC.mm) else() - target_compile_definitions(libbreakpad_client PUBLIC HAVE_A_OUT_H) + target_compile_definitions(libbreakpad_client PUBLIC -DHAVE_A_OUT_H) file(GLOB_RECURSE LIBBREAKPAD_CLIENT_SOURCES ${breakpad_SOURCE_DIR}/src/client/linux/*.cc ${breakpad_SOURCE_DIR}/src/common/linux/*.cc) endif() list(APPEND LIBBREAKPAD_CLIENT_SOURCES ${LIBBREAKPAD_COMMON_SOURCES}) diff --git a/externals/cpmfile.json b/externals/cpmfile.json index 283da76743..effcbcc01f 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -1,16 +1,22 @@ { - "vulkan-memory-allocator": { - "package": "VulkanMemoryAllocator", - "repo": "GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator", - "sha": "1076b348ab", - "hash": "a46b44e4286d08cffda058e856c47f44c7fed3da55fe9555976eb3907fdcc20ead0b1860b0c38319cda01dbf9b1aa5d4b4038c7f1f8fbd97283d837fa9af9772", - "find_args": "CONFIG" + "mbedtls": { + "repo": "Mbed-TLS/mbedtls", + "sha": "8c88150ca1", + "hash": "769ad1e94c570671071e1f2a5c0f1027e0bf6bcdd1a80ea8ac970f2c86bc45ce4e31aa88d6d8110fc1bed1de81c48bc624df1b38a26f8b340a44e109d784a966", + "patches": [ + "0001-cmake-version.patch" + ] + }, + "spirv-headers": { + "package": "SPIRV-Headers", + "repo": "KhronosGroup/SPIRV-Headers", + "sha": "4e209d3d7e", + "hash": "f48bbe18341ed55ea0fe280dbbbc0a44bf222278de6e716e143ca1e95ca320b06d4d23d6583fbf8d03e1428f3dac8fa00e5b82ddcd6b425e6236d85af09550a4" }, "sirit": { "repo": "eden-emulator/sirit", "sha": "db1f1e8ab5", "hash": "73eb3a042848c63a10656545797e85f40d142009dfb7827384548a385e1e28e1ac72f42b25924ce530d58275f8638554281e884d72f9c7aaf4ed08690a414b05", - "find_args": "MODULE", "options": [ "SIRIT_USE_SYSTEM_SPIRV_HEADERS ON" ] @@ -22,24 +28,60 @@ }, "cpp-jwt": { "version": "1.4", - "repo": "crueter/cpp-jwt", - "sha": "9eaea6328f", - "hash": "e237d92c59ebbf0dc8ac0bae3bc80340e1e9cf430e1c1c9638443001118e16de2b3e9036ac4b98105427667b0386d97831415170b68c432438dcad9ef8052de7", + "repo": "arun11299/cpp-jwt", + "sha": "a54fa08a3b", + "hash": "a90f7e594ada0c7e49d5ff9211c71097534e7742a8e44bf0851b0362642a7271d53f5d83d04eeaae2bad17ef3f35e09e6818434d8eaefa038f3d1f7359d0969a", "find_args": "CONFIG", "options": [ + "CPP_JWT_BUILD_EXAMPLES OFF", + "CPP_JWT_BUILD_TESTS OFF", "CPP_JWT_USE_VENDORED_NLOHMANN_JSON OFF" + ], + "patches": [ + "0001-no-install.patch", + "0002-missing-decl.patch" + ] + }, + "vulkan-headers": { + "package": "VulkanHeaders", + "version": "1.3.274", + "repo": "KhronosGroup/Vulkan-Headers", + "sha": "89268a6d17", + "hash": "3ab349f74298ba72cafb8561015690c0674d428a09fb91ccd3cd3daca83650d190d46d33fd97b0a8fd4223fe6df2bcabae89136fbbf7c0bfeb8776f9448304c8" + }, + "vulkan-utility-libraries": { + "package": "VulkanUtilityLibraries", + "repo": "KhronosGroup/Vulkan-Utility-Libraries", + "sha": "df2e358152", + "hash": "3e468c3d9ff93f6d418d71e5527abe0a12c8c7ab5b0b52278bbbee4d02bb87e99073906729b727e0147242b7e3fd5dedf68b803f1878cb4c0e4f730bc2238d79" + }, + "vulkan-memory-allocator": { + "package": "VulkanMemoryAllocator", + "repo": "GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator", + "sha": "1076b348ab", + "hash": "a46b44e4286d08cffda058e856c47f44c7fed3da55fe9555976eb3907fdcc20ead0b1860b0c38319cda01dbf9b1aa5d4b4038c7f1f8fbd97283d837fa9af9772", + "find_args": "CONFIG" + }, + "spirv-tools": { + "package": "SPIRV-Tools", + "repo": "KhronosGroup/SPIRV-Tools", + "sha": "40eb301f32", + "hash": "58d0fb1047d69373cf24c73e6f78c73a72a6cca3b4df1d9f083b9dcc0962745ef154abf3dbe9b3623b835be20c6ec769431cf11733349f45e7568b3525f707aa", + "find_args": "MODULE", + "options": [ + "SPIRV_SKIP_EXECUTABLES ON" ] }, "xbyak_sun": { "package": "xbyak", - "repo": "herumi/xbyak", - "sha": "9bb219333a", - "hash": "303165d45c8c19387ec49d9fda7d7a4e0d86d4c0153898c23f25ce2d58ece567f44c0bbbfe348239b933edb6e1a1e34f4bc1c0ab3a285bee5da0e548879387b0", + "repo": "Lizzie841/xbyak", + "sha": "51f507b0b3", + "hash": "4a29a3c2f97f7d5adf667a21a008be03c951fb6696b0d7ba27e7e4afa037bc76eb5e059bb84860e01baf741d4d3ac851b840cd54c99d038812fbe0f1fa6d38a4", "bundled": true }, "xbyak": { "package": "xbyak", - "repo": "herumi/xbyak", + "repo": "Lizzie841/xbyak", "sha": "4e44f4614d", "hash": "5824e92159e07fa36a774aedd3b3ef3541d0241371d522cffa4ab3e1f215fa5097b1b77865b47b2481376c704fa079875557ea463ca63d0a7fd6a8a20a589e70", "bundled": true @@ -63,12 +105,5 @@ "sha": "2bc873e53c", "hash": "02329058a7f9cf7d5039afaae5ab170d9f42f60f4c01e21eaf4f46073886922b057a9ae30eeac040b3ac182f51b9c1bfe9fe1050a2c9f6ce567a1a9a0ec2c768", "bundled": true - }, - "unordered-dense": { - "package": "unordered_dense", - "repo": "martinus/unordered_dense", - "sha": "73f3cbb237", - "hash": "c08c03063938339d61392b687562909c1a92615b6ef39ec8df19ea472aa6b6478e70d7d5e33d4a27b5d23f7806daf57fe1bacb8124c8a945c918c7663a9e8532", - "find_args": "CONFIG" } } diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt index 8908aa234f..ff35c8dc2c 100644 --- a/externals/ffmpeg/CMakeLists.txt +++ b/externals/ffmpeg/CMakeLists.txt @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2021 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later +# Explicitly include CPMUtil here since we have a separate cpmfile for ffmpeg +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) if (NOT WIN32 AND NOT ANDROID) diff --git a/externals/libusb/CMakeLists.txt b/externals/libusb/CMakeLists.txt index 4bf2421c53..ec7724e874 100644 --- a/externals/libusb/CMakeLists.txt +++ b/externals/libusb/CMakeLists.txt @@ -1,30 +1,7 @@ -# SPDX-FileCopyrightText: 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - # SPDX-FileCopyrightText: 2020 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later -include(CPMUtil) - -# we love our libraries don't we folks -if (PLATFORM_SUN) - set(libusb_bundled ON) -else() - set(libusb_bundled OFF) -endif() - -# TODO(crueter): Fix on Solaris -AddJsonPackage( - NAME libusb - BUNDLED_PACKAGE ${libusb_bundled} -) - -if (NOT libusb_ADDED) - return() -endif() - -# TODO: *BSD fails to compile--may need different configs/symbols -if (MINGW OR PLATFORM_LINUX OR APPLE) +if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") OR APPLE) set(LIBUSB_FOUND ON CACHE BOOL "libusb is present" FORCE) set(LIBUSB_VERSION "1.0.24" CACHE STRING "libusb version string" FORCE) @@ -42,8 +19,8 @@ if (MINGW OR PLATFORM_LINUX OR APPLE) message(FATAL_ERROR "Required program `libtoolize` not found.") endif() - set(LIBUSB_PREFIX "${libusb_BINARY_DIR}") - set(LIBUSB_SRC_DIR "${libusb_SOURCE_DIR}") + set(LIBUSB_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/libusb") + set(LIBUSB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libusb") # Workarounds for MSYS/MinGW if (MSYS) @@ -141,27 +118,27 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") endif() add_library(usb - ${libusb_SOURCE_DIR}/libusb/core.c - ${libusb_SOURCE_DIR}/libusb/core.c - ${libusb_SOURCE_DIR}/libusb/descriptor.c - ${libusb_SOURCE_DIR}/libusb/hotplug.c - ${libusb_SOURCE_DIR}/libusb/io.c - ${libusb_SOURCE_DIR}/libusb/strerror.c - ${libusb_SOURCE_DIR}/libusb/sync.c + libusb/libusb/core.c + libusb/libusb/core.c + libusb/libusb/descriptor.c + libusb/libusb/hotplug.c + libusb/libusb/io.c + libusb/libusb/strerror.c + libusb/libusb/sync.c ) set_target_properties(usb PROPERTIES VERSION 1.0.24) if(WIN32) target_include_directories(usb BEFORE PUBLIC - ${libusb_SOURCE_DIR}/libusb + libusb/libusb PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" ) if (NOT MINGW) - target_include_directories(usb BEFORE PRIVATE ${libusb_SOURCE_DIR}/msvc) + target_include_directories(usb BEFORE PRIVATE libusb/msvc) endif() else() @@ -171,7 +148,7 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") BEFORE PUBLIC - ${libusb_SOURCE_DIR}/libusb + libusb/libusb PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" @@ -180,15 +157,15 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") if(WIN32 OR CYGWIN) target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/threads_windows.c - ${libusb_SOURCE_DIR}/libusb/os/windows_winusb.c - ${libusb_SOURCE_DIR}/libusb/os/windows_usbdk.c - ${libusb_SOURCE_DIR}/libusb/os/windows_common.c + libusb/libusb/os/threads_windows.c + libusb/libusb/os/windows_winusb.c + libusb/libusb/os/windows_usbdk.c + libusb/libusb/os/windows_common.c ) set(OS_WINDOWS TRUE) elseif(APPLE) target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/darwin_usb.c + libusb/libusb/os/darwin_usb.c ) find_library(COREFOUNDATION_LIBRARY CoreFoundation) find_library(IOKIT_LIBRARY IOKit) @@ -201,20 +178,20 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(OS_DARWIN TRUE) elseif(ANDROID) target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/linux_usbfs.c - ${libusb_SOURCE_DIR}/libusb/os/linux_netlink.c + libusb/libusb/os/linux_usbfs.c + libusb/libusb/os/linux_netlink.c ) find_library(LOG_LIBRARY log) target_link_libraries(usb PRIVATE ${LOG_LIBRARY}) set(OS_LINUX TRUE) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/linux_usbfs.c + libusb/libusb/os/linux_usbfs.c ) find_package(Libudev) if(LIBUDEV_FOUND) target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/linux_udev.c + libusb/libusb/os/linux_udev.c ) target_link_libraries(usb PRIVATE "${LIBUDEV_LIBRARIES}") target_include_directories(usb PRIVATE "${LIBUDEV_INCLUDE_DIR}") @@ -222,26 +199,26 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(USE_UDEV TRUE) else() target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/linux_netlink.c + libusb/libusb/os/linux_netlink.c ) endif() set(OS_LINUX TRUE) elseif(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD") target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/netbsd_usb.c + libusb/libusb/os/netbsd_usb.c ) set(OS_NETBSD TRUE) elseif(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/openbsd_usb.c + libusb/libusb/os/openbsd_usb.c ) set(OS_OPENBSD TRUE) endif() if(UNIX) target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/events_posix.c - ${libusb_SOURCE_DIR}/libusb/os/threads_posix.c + libusb/libusb/os/events_posix.c + libusb/libusb/os/threads_posix.c ) find_package(Threads REQUIRED) if(THREADS_HAVE_PTHREAD_ARG) @@ -253,8 +230,8 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(THREADS_POSIX TRUE) elseif(WIN32) target_sources(usb PRIVATE - ${libusb_SOURCE_DIR}/libusb/os/events_windows.c - ${libusb_SOURCE_DIR}/libusb/os/threads_windows.c + libusb/libusb/os/events_windows.c + libusb/libusb/os/threads_windows.c ) endif() diff --git a/externals/libusb/cpmfile.json b/externals/libusb/cpmfile.json deleted file mode 100644 index 0bfa0d7a86..0000000000 --- a/externals/libusb/cpmfile.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "libusb": { - "repo": "libusb/libusb", - "sha": "c060e9ce30", - "hash": "44647357ba1179020cfa6674d809fc35cf6f89bff1c57252fe3a610110f5013ad678fc6eb5918e751d4384c30e2fe678868dbffc5f85736157e546cb9d10accc", - "find_args": "MODULE" - } -} \ No newline at end of file diff --git a/externals/libusb/libusb b/externals/libusb/libusb new file mode 160000 index 0000000000..c060e9ce30 --- /dev/null +++ b/externals/libusb/libusb @@ -0,0 +1 @@ +Subproject commit c060e9ce30ac2e3ffb49d94209c4dae77b6642f7 diff --git a/externals/nx_tzdb/CMakeLists.txt b/externals/nx_tzdb/CMakeLists.txt index a08c80f2bd..35d3e6d2a8 100644 --- a/externals/nx_tzdb/CMakeLists.txt +++ b/externals/nx_tzdb/CMakeLists.txt @@ -4,6 +4,8 @@ # SPDX-FileCopyrightText: 2023 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later +# Explicitly include CPMUtil here since we have a separate cpmfile for nx_tzdb +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) set(NX_TZDB_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/include") @@ -33,12 +35,9 @@ if (CAN_BUILD_NX_TZDB AND NOT YUZU_DOWNLOAD_TIME_ZONE_DATA) set(NX_TZDB_TZ_DIR "${NX_TZDB_BASE_DIR}/zoneinfo") endif() -if(NOT YUZU_TZDB_PATH STREQUAL "") - set(NX_TZDB_BASE_DIR "${YUZU_TZDB_PATH}") - set(NX_TZDB_TZ_DIR "${NX_TZDB_BASE_DIR}/zoneinfo") -elseif (MSVC) - # TODO(crueter): This is a terrible solution, but MSVC fails to link without it - # Need to investigate further but I still can't reproduce... +# TODO(crueter): This is a terrible solution, but MSVC fails to link without it +# Need to investigate further but I still can't reproduce... +if (MSVC) set(NX_TZDB_VERSION "250725") set(NX_TZDB_ARCHIVE "${CPM_SOURCE_CACHE}/nx_tzdb/${NX_TZDB_VERSION}.zip") diff --git a/externals/nx_tzdb/cpmfile.json b/externals/nx_tzdb/cpmfile.json index feb9daf7da..fc7dd77628 100644 --- a/externals/nx_tzdb/cpmfile.json +++ b/externals/nx_tzdb/cpmfile.json @@ -1,10 +1,7 @@ { "tzdb": { "package": "nx_tzdb", - "repo": "misc/tzdb_to_nx", - "git_host": "git.crueter.xyz", - "artifact": "%VERSION%.zip", - "tag": "%VERSION%", + "url": "https://github.com/crueter/tzdb_to_nx/releases/download/250725/250725.zip", "hash": "8f60b4b29f285e39c0443f3d5572a73780f3dbfcfd5b35004451fadad77f3a215b2e2aa8d0fffe7e348e2a7b0660882b35228b6178dda8804a14ce44509fd2ca", "version": "250725" } diff --git a/externals/sse2neon/sse2neon.h b/externals/sse2neon/sse2neon.h index 67ad0ae6f8..66b93c1c74 100755 --- a/externals/sse2neon/sse2neon.h +++ b/externals/sse2neon/sse2neon.h @@ -183,7 +183,7 @@ } /* Compiler barrier */ -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) #define SSE2NEON_BARRIER() _ReadWriteBarrier() #else #define SSE2NEON_BARRIER() \ @@ -859,7 +859,7 @@ FORCE_INLINE uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b) { poly64_t a = vget_lane_p64(vreinterpret_p64_u64(_a), 0); poly64_t b = vget_lane_p64(vreinterpret_p64_u64(_b), 0); -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) __n64 a1 = {a}, b1 = {b}; return vreinterpretq_u64_p128(vmull_p64(a1, b1)); #else @@ -1770,7 +1770,7 @@ FORCE_INLINE void _mm_free(void *addr) FORCE_INLINE uint64_t _sse2neon_get_fpcr(void) { uint64_t value; -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) value = _ReadStatusReg(ARM64_FPCR); #else __asm__ __volatile__("mrs %0, FPCR" : "=r"(value)); /* read */ @@ -1780,7 +1780,7 @@ FORCE_INLINE uint64_t _sse2neon_get_fpcr(void) FORCE_INLINE void _sse2neon_set_fpcr(uint64_t value) { -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) _WriteStatusReg(ARM64_FPCR, value); #else __asm__ __volatile__("msr FPCR, %0" ::"r"(value)); /* write */ @@ -2249,7 +2249,7 @@ FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b) FORCE_INLINE void _mm_prefetch(char const *p, int i) { (void) i; -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) switch (i) { case _MM_HINT_NTA: __prefetch2(p, 1); @@ -4820,7 +4820,7 @@ FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b) // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_pause FORCE_INLINE void _mm_pause(void) { -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) __isb(_ARM64_BARRIER_SY); #else __asm__ __volatile__("isb\n"); @@ -5716,7 +5716,7 @@ FORCE_INLINE __m128d _mm_undefined_pd(void) #pragma GCC diagnostic ignored "-Wuninitialized" #endif __m128d a; -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) a = _mm_setzero_pd(); #endif return a; @@ -8130,7 +8130,7 @@ FORCE_INLINE int _sse2neon_sido_negative(int res, int lb, int imm8, int bound) FORCE_INLINE int _sse2neon_clz(unsigned int x) { -#if defined(_MSC_VER) && !defined(__clang__) +#ifdef _MSC_VER unsigned long cnt = 0; if (_BitScanReverse(&cnt, x)) return 31 - cnt; @@ -8142,7 +8142,7 @@ FORCE_INLINE int _sse2neon_clz(unsigned int x) FORCE_INLINE int _sse2neon_ctz(unsigned int x) { -#if defined(_MSC_VER) && !defined(__clang__) +#ifdef _MSC_VER unsigned long cnt = 0; if (_BitScanForward(&cnt, x)) return cnt; @@ -9058,7 +9058,7 @@ FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i a, const int rcon) // AESE does ShiftRows and SubBytes on A uint8x16_t u8 = vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0)); -#if !defined(_MSC_VER) || defined(__clang__) +#ifndef _MSC_VER uint8x16_t dest = { // Undo ShiftRows step from AESE and extract X1 and X3 u8[0x4], u8[0x1], u8[0xE], u8[0xB], // SubBytes(X1) @@ -9245,7 +9245,7 @@ FORCE_INLINE uint64_t _rdtsc(void) * bits wide and it is attributed with the flag 'cap_user_time_short' * is true. */ -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) val = _ReadStatusReg(ARM64_SYSREG(3, 3, 14, 0, 2)); #else __asm__ __volatile__("mrs %0, cntvct_el0" : "=r"(val)); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 184b049d06..bd1285b2bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,20 +18,20 @@ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$:_DEBUG> $<$>:NDEBUG>) # Set compilation flags -if (MSVC AND NOT CXX_CLANG) +if (MSVC) set(CMAKE_CONFIGURATION_TYPES Debug Release CACHE STRING "" FORCE) # Silence "deprecation" warnings - add_compile_definitions(_CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE _SCL_SECURE_NO_WARNINGS) + add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS) # Avoid windows.h junk - add_compile_definitions(NOMINMAX) + add_definitions(-DNOMINMAX) # Avoid windows.h from including some usually unused libs like winsocks.h, since this might cause some redefinition errors. - add_compile_definitions(WIN32_LEAN_AND_MEAN) + add_definitions(-DWIN32_LEAN_AND_MEAN) # Ensure that projects are built with Unicode support. - add_compile_definitions(UNICODE _UNICODE) + add_definitions(-DUNICODE -D_UNICODE) # /W4 - Level 4 warnings # /MP - Multi-threaded compilation @@ -69,6 +69,10 @@ if (MSVC AND NOT CXX_CLANG) /external:anglebrackets # Treats all headers included by #include
, where the header file is enclosed in angle brackets (< >), as external headers /external:W0 # Sets the default warning level to 0 for external headers, effectively disabling warnings for them. + # Warnings + /W4 + /WX- + /we4062 # Enumerator 'identifier' in a switch of enum 'enumeration' is not handled /we4189 # 'identifier': local variable is initialized but not referenced /we4265 # 'class': class has virtual functions, but destructor is not virtual @@ -93,14 +97,6 @@ if (MSVC AND NOT CXX_CLANG) /wd4702 # unreachable code (when used with LTO) ) - if (NOT CXX_CLANG) - add_compile_options( - # Warnings - /W4 - /WX- - ) - endif() - if (USE_CCACHE OR YUZU_USE_PRECOMPILED_HEADERS) # when caching, we need to use /Z7 to downgrade debug info to use an older but more cacheable format # Precompiled headers are deleted if not using /Z7. See https://github.com/nanoant/CMakePCHCompiler/issues/21 @@ -122,13 +118,9 @@ if (MSVC AND NOT CXX_CLANG) set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG /MANIFEST:NO" CACHE STRING "" FORCE) set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE) else() - if (NOT MSVC) - add_compile_options( - -fwrapv - ) - endif() - add_compile_options( + -fwrapv + -Werror=all -Werror=extra -Werror=missing-declarations @@ -141,19 +133,14 @@ else() -Wno-missing-field-initializers ) - if (CXX_CLANG OR CXX_ICC) # Clang or AppleClang - if (NOT MSVC) - add_compile_options( - -Werror=shadow-uncaptured-local - -Werror=implicit-fallthrough - -Werror=type-limits - ) - endif() - + if (CMAKE_CXX_COMPILER_ID MATCHES Clang OR CMAKE_CXX_COMPILER_ID MATCHES IntelLLVM) # Clang or AppleClang add_compile_options( -Wno-braced-scalar-init -Wno-unused-private-field -Wno-nullability-completeness + -Werror=shadow-uncaptured-local + -Werror=implicit-fallthrough + -Werror=type-limits ) endif() @@ -161,12 +148,12 @@ else() add_compile_options("-mcx16") endif() - if (APPLE AND CXX_CLANG) + if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) add_compile_options("-stdlib=libc++") endif() # GCC bugs - if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11" AND CXX_GCC) + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # These diagnostics would be great if they worked, but are just completely broken # and produce bogus errors on external libraries like fmt. add_compile_options( @@ -182,15 +169,15 @@ else() # glibc, which may default to 32 bits. glibc allows this to be configured # by setting _FILE_OFFSET_BITS. if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW) - add_compile_definitions(_FILE_OFFSET_BITS=64) + add_definitions(-D_FILE_OFFSET_BITS=64) endif() if (MINGW) - add_compile_definitions(MINGW_HAS_SECURE_API) + add_definitions(-DMINGW_HAS_SECURE_API) add_compile_options("-msse4.1") if (MINGW_STATIC_BUILD) - add_compile_definitions(QT_STATICPLUGIN) + add_definitions(-DQT_STATICPLUGIN) add_compile_options("-static") endif() endif() @@ -234,8 +221,6 @@ if (YUZU_ROOM_STANDALONE) endif() if (ENABLE_QT) - add_definitions(-DYUZU_QT_WIDGETS) - add_subdirectory(qt_common) add_subdirectory(yuzu) endif() diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index c76b5e7162..d907284bb7 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -30,8 +30,8 @@ val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toIn android { namespace = "org.yuzu.yuzu_emu" - compileSdkVersion = "android-36" - ndkVersion = "28.2.13676358" + compileSdkVersion = "android-35" + ndkVersion = "26.1.10909125" buildFeatures { viewBinding = true @@ -173,14 +173,12 @@ android { "-DENABLE_OPENSSL=ON", "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work "-DYUZU_USE_CPM=ON", - "-DCPMUTIL_FORCE_BUNDLED=ON", "-DYUZU_USE_BUNDLED_FFMPEG=ON", "-DYUZU_ENABLE_LTO=ON", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-DBUILD_TESTING=OFF", "-DYUZU_TESTS=OFF", - "-DDYNARMIC_TESTS=OFF", - "-DDYNARMIC_ENABLE_LTO=ON" + "-DDYNARMIC_TESTS=OFF" ) abiFilters("arm64-v8a") diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt index 9ea2a9ee17..11b81a01a6 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt @@ -36,18 +36,14 @@ import androidx.core.net.toUri import androidx.core.content.edit import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.yuzu.yuzu_emu.NativeLibrary -import org.yuzu.yuzu_emu.databinding.CardGameGridCompactBinding -import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting -import org.yuzu.yuzu_emu.features.settings.model.Settings class GameAdapter(private val activity: AppCompatActivity) : AbstractDiffAdapter(exact = false) { companion object { const val VIEW_TYPE_GRID = 0 - const val VIEW_TYPE_GRID_COMPACT = 1 - const val VIEW_TYPE_LIST = 2 - const val VIEW_TYPE_CAROUSEL = 3 + const val VIEW_TYPE_LIST = 1 + const val VIEW_TYPE_CAROUSEL = 2 } private var viewType = 0 @@ -81,7 +77,6 @@ class GameAdapter(private val activity: AppCompatActivity) : listBinding.root.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT listBinding.root.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT } - VIEW_TYPE_GRID -> { val gridBinding = holder.binding as CardGameGridBinding gridBinding.cardGameGrid.scaleX = 1f @@ -91,17 +86,6 @@ class GameAdapter(private val activity: AppCompatActivity) : gridBinding.root.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT gridBinding.root.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT } - - VIEW_TYPE_GRID_COMPACT -> { - val gridCompactBinding = holder.binding as CardGameGridCompactBinding - gridCompactBinding.cardGameGridCompact.scaleX = 1f - gridCompactBinding.cardGameGridCompact.scaleY = 1f - gridCompactBinding.cardGameGridCompact.alpha = 1f - // Reset layout params to XML defaults (same as normal grid) - gridCompactBinding.root.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT - gridCompactBinding.root.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT - } - VIEW_TYPE_CAROUSEL -> { val carouselBinding = holder.binding as CardGameCarouselBinding // soothens transient flickering @@ -118,25 +102,16 @@ class GameAdapter(private val activity: AppCompatActivity) : parent, false ) - VIEW_TYPE_GRID -> CardGameGridBinding.inflate( LayoutInflater.from(parent.context), parent, false ) - - VIEW_TYPE_GRID_COMPACT -> CardGameGridCompactBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false - ) - VIEW_TYPE_CAROUSEL -> CardGameCarouselBinding.inflate( LayoutInflater.from(parent.context), parent, false ) - else -> throw IllegalArgumentException("Invalid view type") } return GameViewHolder(binding, viewType) @@ -152,7 +127,6 @@ class GameAdapter(private val activity: AppCompatActivity) : VIEW_TYPE_LIST -> bindListView(model) VIEW_TYPE_GRID -> bindGridView(model) VIEW_TYPE_CAROUSEL -> bindCarouselView(model) - VIEW_TYPE_GRID_COMPACT -> bindGridCompactView(model) } } @@ -191,23 +165,6 @@ class GameAdapter(private val activity: AppCompatActivity) : gridBinding.root.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT } - private fun bindGridCompactView(model: Game) { - val gridCompactBinding = binding as CardGameGridCompactBinding - - gridCompactBinding.imageGameScreenCompact.scaleType = ImageView.ScaleType.CENTER_CROP - GameIconUtils.loadGameIcon(model, gridCompactBinding.imageGameScreenCompact) - - gridCompactBinding.textGameTitleCompact.text = model.title.replace("[\\t\\n\\r]+".toRegex(), " ") - - gridCompactBinding.textGameTitleCompact.marquee() - gridCompactBinding.cardGameGridCompact.setOnClickListener { onClick(model) } - gridCompactBinding.cardGameGridCompact.setOnLongClickListener { onLongClick(model) } - - // Reset layout params to XML defaults (same as normal grid) - gridCompactBinding.root.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT - gridCompactBinding.root.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT - } - private fun bindCarouselView(model: Game) { val carouselBinding = binding as CardGameCarouselBinding 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 1f2ba81a73..a689b6ce76 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 @@ -297,6 +297,7 @@ abstract class SettingsItem( descriptionId = R.string.use_custom_rtc_description ) ) + put( StringInputSetting( StringSetting.WEB_TOKEN, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverFetcherFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverFetcherFragment.kt index dea762dc17..b8d0f2197e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverFetcherFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverFetcherFragment.kt @@ -79,7 +79,7 @@ class DriverFetcherFragment : Fragment() { IntRange(600, 639) to "Mr. Purple EOL-24.3.4", IntRange(640, 699) to "Mr. Purple T19", IntRange(700, 710) to "KIMCHI 25.2.0_r5", - IntRange(711, 799) to "Mr. Purple T22", + IntRange(711, 799) to "Mr. Purple T21", IntRange(800, 899) to "GameHub Adreno 8xx", IntRange(900, Int.MAX_VALUE) to "Unsupported" ) 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 5cc912fbbe..96015e58ec 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 @@ -509,8 +509,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { gpuModel = GpuDriverHelper.getGpuModel().toString() fwVersion = NativeLibrary.firmwareVersion() - updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) - binding.surfaceEmulation.holder.addCallback(this) binding.doneControlConfig.setOnClickListener { stopConfiguringControls() } @@ -532,7 +530,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) binding.inGameMenu.requestFocus() emulationViewModel.setDrawerOpen(true) - updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) } override fun onDrawerClosed(drawerView: View) { @@ -574,24 +571,25 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { R.id.menu_pause_emulation -> { if (emulationState.isPaused) { emulationState.run(false) - updatePauseMenuEntry(false) + it.title = resources.getString(R.string.emulation_pause) + it.icon = ResourcesCompat.getDrawable( + resources, + R.drawable.ic_pause, + requireContext().theme + ) } else { emulationState.pause() - updatePauseMenuEntry(true) + it.title = resources.getString(R.string.emulation_unpause) + it.icon = ResourcesCompat.getDrawable( + resources, + R.drawable.ic_play, + requireContext().theme + ) } binding.inGameMenu.requestFocus() true } - R.id.menu_quick_overlay -> { - val newState = !BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean() - BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(newState) - updateQuickOverlayMenuEntry(newState) - binding.surfaceInputOverlay.refreshControls() - NativeConfig.saveGlobalConfig() - true - } - R.id.menu_settings -> { val action = HomeNavigationDirections.actionGlobalSettingsActivity( null, @@ -846,50 +844,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { } } - private fun updateQuickOverlayMenuEntry(isVisible: Boolean) { - val menu = binding.inGameMenu.menu - val item = menu.findItem(R.id.menu_quick_overlay) - if (isVisible) { - item.title = getString(R.string.emulation_hide_overlay) - item.icon = ResourcesCompat.getDrawable( - resources, - R.drawable.ic_controller_disconnected, - requireContext().theme - ) - } else { - item.title = getString(R.string.emulation_show_overlay) - item.icon = ResourcesCompat.getDrawable( - resources, - R.drawable.ic_controller, - requireContext().theme - ) - } - } - - private fun updatePauseMenuEntry(isPaused: Boolean) { - val menu = binding.inGameMenu.menu - val pauseItem = menu.findItem(R.id.menu_pause_emulation) - if (isPaused) { - pauseItem.title = getString(R.string.emulation_unpause) - pauseItem.icon = ResourcesCompat.getDrawable( - resources, - R.drawable.ic_play, - requireContext().theme - ) - } else { - pauseItem.title = getString(R.string.emulation_pause) - pauseItem.icon = ResourcesCompat.getDrawable( - resources, - R.drawable.ic_pause, - requireContext().theme - ) - } - } - override fun onPause() { if (emulationState.isRunning && emulationActivity?.isInPictureInPictureMode != true) { emulationState.pause() - updatePauseMenuEntry(true) } super.onPause() } @@ -912,10 +869,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { val socPosition = IntSetting.SOC_OVERLAY_POSITION.getInt() updateSocPosition(socPosition) - - binding.inGameMenu.post { - emulationState?.isPaused?.let { updatePauseMenuEntry(it) } - } } private fun resetInputOverlay() { @@ -1438,7 +1391,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { R.id.menu_show_overlay -> { it.isChecked = !it.isChecked BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(it.isChecked) - updateQuickOverlayMenuEntry(it.isChecked) binding.surfaceInputOverlay.refreshControls() true } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt index a06abb394f..97a60ee184 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/HomeViewModel.kt @@ -31,6 +31,9 @@ class HomeViewModel : ViewModel() { private val _checkKeys = MutableStateFlow(false) val checkKeys = _checkKeys.asStateFlow() + private val _checkFirmware = MutableStateFlow(false) + val checkFirmware = _checkFirmware.asStateFlow() + var navigatedToSetup = false fun setStatusBarShadeVisibility(visible: Boolean) { @@ -63,4 +66,8 @@ class HomeViewModel : ViewModel() { fun setCheckKeys(value: Boolean) { _checkKeys.value = value } + + fun setCheckFirmware(value: Boolean) { + _checkFirmware.value = value + } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt index 80055628e1..03fa1a3a2e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/GamesFragment.kt @@ -194,10 +194,6 @@ class GamesFragment : Fragment() { val columns = resources.getInteger(R.integer.game_columns_grid) GridLayoutManager(context, columns) } - GameAdapter.VIEW_TYPE_GRID_COMPACT -> { - val columns = resources.getInteger(R.integer.game_columns_grid) - GridLayoutManager(context, columns) - } GameAdapter.VIEW_TYPE_LIST -> { val columns = resources.getInteger(R.integer.game_columns_list) GridLayoutManager(context, columns) @@ -304,7 +300,6 @@ class GamesFragment : Fragment() { val currentViewType = getCurrentViewType() when (currentViewType) { GameAdapter.VIEW_TYPE_LIST -> popup.menu.findItem(R.id.view_list).isChecked = true - GameAdapter.VIEW_TYPE_GRID_COMPACT -> popup.menu.findItem(R.id.view_grid_compact).isChecked = true GameAdapter.VIEW_TYPE_GRID -> popup.menu.findItem(R.id.view_grid).isChecked = true GameAdapter.VIEW_TYPE_CAROUSEL -> popup.menu.findItem(R.id.view_carousel).isChecked = true } @@ -319,14 +314,6 @@ class GamesFragment : Fragment() { true } - R.id.view_grid_compact -> { - if (getCurrentViewType() == GameAdapter.VIEW_TYPE_CAROUSEL) onPause() - setCurrentViewType(GameAdapter.VIEW_TYPE_GRID_COMPACT) - applyGridGamesBinding() - item.isChecked = true - true - } - R.id.view_list -> { if (getCurrentViewType() == GameAdapter.VIEW_TYPE_CAROUSEL) onPause() setCurrentViewType(GameAdapter.VIEW_TYPE_LIST) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index cfed4d08ec..fffaa1e3ba 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt @@ -38,7 +38,6 @@ import org.yuzu.yuzu_emu.model.DriverViewModel import org.yuzu.yuzu_emu.model.GamesViewModel import org.yuzu.yuzu_emu.model.HomeViewModel import org.yuzu.yuzu_emu.model.InstallResult -import android.os.Build import org.yuzu.yuzu_emu.model.TaskState import org.yuzu.yuzu_emu.model.TaskViewModel import org.yuzu.yuzu_emu.utils.* @@ -48,7 +47,6 @@ import java.io.BufferedOutputStream import java.util.zip.ZipEntry import java.util.zip.ZipInputStream import androidx.core.content.edit -import kotlin.text.compareTo class MainActivity : AppCompatActivity(), ThemeProvider { private lateinit var binding: ActivityMainBinding @@ -112,19 +110,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider { binding = ActivityMainBinding.inflate(layoutInflater) - // Since Android 15, google automatically forces "games" to be 60 hrz - // This ensures the display's max refresh rate is actually used - display?.let { - val supportedModes = it.supportedModes - val maxRefreshRate = supportedModes.maxByOrNull { mode -> mode.refreshRate } - - if (maxRefreshRate != null) { - val layoutParams = window.attributes - layoutParams.preferredDisplayModeId = maxRefreshRate.modeId - window.attributes = layoutParams - } - } - setContentView(binding.root) checkAndRequestBluetoothPermissions() @@ -142,6 +127,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider { checkedDecryption = true } + if (!checkedFirmware) { + val firstTimeSetup = PreferenceManager.getDefaultSharedPreferences(applicationContext) + .getBoolean(Settings.PREF_FIRST_APP_LAUNCH, true) + if (!firstTimeSetup) { + checkFirmware() + showPreAlphaWarningDialog() + } + checkedFirmware = true + } + WindowCompat.setDecorFitsSystemWindows(window, false) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) @@ -188,6 +183,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider { if (it) checkKeys() } + homeViewModel.checkFirmware.collect( + this, + resetState = { homeViewModel.setCheckFirmware(false) } + ) { + if (it) checkFirmware() + } + setInsets() } @@ -226,6 +228,21 @@ class MainActivity : AppCompatActivity(), ThemeProvider { ).show(supportFragmentManager, MessageDialogFragment.TAG) } } + + private fun checkFirmware() { + val resultCode: Int = NativeLibrary.verifyFirmware() + if (resultCode == 0) return + + val resultString: String = + resources.getStringArray(R.array.verifyFirmwareResults)[resultCode] + + MessageDialogFragment.newInstance( + titleId = R.string.firmware_invalid, + descriptionString = resultString, + helpLinkId = R.string.firmware_missing_help + ).show(supportFragmentManager, MessageDialogFragment.TAG) + } + override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putBoolean(CHECKED_DECRYPTION, checkedDecryption) @@ -402,6 +419,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { cacheFirmwareDir.copyRecursively(firmwarePath, true) NativeLibrary.initializeSystem(true) homeViewModel.setCheckKeys(true) + homeViewModel.setCheckFirmware(true) getString(R.string.save_file_imported_success) } } catch (e: Exception) { @@ -431,6 +449,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { // Optionally reinitialize the system or perform other necessary steps NativeLibrary.initializeSystem(true) homeViewModel.setCheckKeys(true) + homeViewModel.setCheckFirmware(true) messageToShow = getString(R.string.firmware_uninstalled_success) } else { messageToShow = getString(R.string.firmware_uninstalled_failure) diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt index 9ad00d26ee..1e30b16d96 100644 --- a/src/android/app/src/main/jni/CMakeLists.txt +++ b/src/android/app/src/main/jni/CMakeLists.txt @@ -17,7 +17,7 @@ add_library(yuzu-android SHARED set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) -target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common video_core) +target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers) target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log) if (ARCHITECTURE_arm64) target_link_libraries(yuzu-android PRIVATE adrenotools) diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 306b7e2a4c..f8f175d313 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -596,8 +596,6 @@ jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv *env, j const std::string model_name{device.GetModelName()}; - window.release(); - return Common::Android::ToJString(env, model_name); } diff --git a/src/android/app/src/main/res/drawable/gradient_overlay_bottom.xml b/src/android/app/src/main/res/drawable/gradient_overlay_bottom.xml deleted file mode 100644 index f74cfa0d05..0000000000 --- a/src/android/app/src/main/res/drawable/gradient_overlay_bottom.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - diff --git a/src/android/app/src/main/res/layout/card_game_grid.xml b/src/android/app/src/main/res/layout/card_game_grid.xml index f03a77c4f1..3e0bf6005c 100644 --- a/src/android/app/src/main/res/layout/card_game_grid.xml +++ b/src/android/app/src/main/res/layout/card_game_grid.xml @@ -5,32 +5,27 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="false" - android:focusableInTouchMode="false" - android:padding="4dp"> + android:focusableInTouchMode="false"> + app:cardCornerRadius="16dp"> + android:padding="6dp"> - - - - - - - - - - - - - - - - - - - - - diff --git a/src/android/app/src/main/res/menu/menu_game_views.xml b/src/android/app/src/main/res/menu/menu_game_views.xml index 11bf3e695e..241cdcb4b5 100644 --- a/src/android/app/src/main/res/menu/menu_game_views.xml +++ b/src/android/app/src/main/res/menu/menu_game_views.xml @@ -4,9 +4,6 @@ - - - يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقت أثناء تحديثات الذاكرة، مما يقلل استخدام المعالج ويحسن أدائه. قد يسبب هذا أعطالاً أو تعطلًا في بعض الألعاب. تمكين محاكاة MMU المضيف يعمل هذا التحسين على تسريع وصول الذاكرة بواسطة البرنامج الضيف. يؤدي تمكينه إلى إجراء عمليات قراءة/كتابة ذاكرة الضيف مباشرة في الذاكرة والاستفادة من MMU المضيف. يؤدي تعطيل هذا إلى إجبار جميع عمليات الوصول إلى الذاكرة على استخدام محاكاة MMU البرمجية. - دقة DMA - يتحكم في دقة تحديد DMA. يمكن أن تصلح الدقة الآمنة المشاكل في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا كنت غير متأكد، اترك هذا على الوضع الافتراضي. + مستوى DMA + يتحكم في دقة تحديد مستوى DMA. الدقة الأعلى يمكنها إصلاح بعض المشاكل في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا كنت غير متأكد، اتركه على الوضع الافتراضي. 4 جيجابايت (موصى به) @@ -733,8 +733,7 @@ مركز العصا النسبي مزلاق الأسهم الاهتزازات الديناميكية - إظهار وحدة التحكم - إخفاء وحدة التحكم + عرض التراكب الكل ضبط التراكب الحجم @@ -792,8 +791,9 @@ افتراضي - غير آمن (سريع) - آمن (مستقر) + عادي + عالي + مفرط 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml index fe94f97dc5..221a197843 100644 --- a/src/android/app/src/main/res/values-ckb/strings.xml +++ b/src/android/app/src/main/res/values-ckb/strings.xml @@ -128,8 +128,8 @@ هەندێک لە بازنەکردنەکانی هەڵگر لە کاتی نوێکردنەوەی بیرگە دەنێرێت، کەمکردنەوەی بەکارهێنانی CPU و باشترکردنی کارایی. لەوانەیە لە هەندێک یاری کێشە درووست بکات. چالاککردنی میمیکردنی MMU میواندە ئەم باشکردنە خێرایی دەستکەوتنی بیرگە لەلایەن پرۆگرامی میوانەکە زیاد دەکات. چالاککردنی وای لێدەکات کە خوێندنەوە/نووسینەکانی بیرگەی میوانەکە ڕاستەوخۆ لە بیرگە ئەنجام بدرێت و میمیکردنی MMU میواندە بەکاربهێنێت. ناچالاککردنی ئەمە هەموو دەستکەوتنەکانی بیرگە ڕەت دەکاتەوە لە بەکارهێنانی میمیکردنی MMU نەرمەکاڵا. - وردیی DMA - کۆنتڕۆڵی وردیی وردیی DMA دەکات. وردییی پارێزراو دەتوانێت کێشەکان لە هەندێک یاری چارەسەر بکات، بەڵام لە هەندێک حاڵەتدا کاریگەری لەسەر کارایی هەیە. ئەگەر دڵنیا نیت، ئەمە بە سەر ڕەھەوادا بهێڵە. + ئاستی DMA + کۆنتڕۆڵی وردی ڕێکخستنی DMA دەکات. وردی زیاتر دەتوانێ هەندێک کێشە لە هەندێک یاری چارەسەر بکات، بەڵام لە هەندێک حاڵەتدا کاریگەری لەسەر کارایی هەیە. ئەگەر دڵنیا نیت، بە ڕێکخستنی بنەڕەتی بێڵە. 4GB (پێشنیارکراو) 6GB (نائاسایش) @@ -710,8 +710,7 @@ ناوەندی گێڕ بەنزیکەیی خلیسکانی 4 دوگمەکە لەرینەوەی پەنجەلێدان - نیشاندانی کۆنتڕۆڵەر - پیشاندانی کۆنتڕۆڵەر + نیشاندانی داپۆشەر گۆڕینی سەرجەم ڕێکخستنی داپۆشەر پێوەر @@ -761,8 +760,9 @@ بنەڕەتی - نەپارێزراو (خێرا) - پارێزراو (جێگیر) + ئاسایی + بەرز + زۆر بەرز 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-cs/strings.xml b/src/android/app/src/main/res/values-cs/strings.xml index 785f96b84c..61e389f9fc 100644 --- a/src/android/app/src/main/res/values-cs/strings.xml +++ b/src/android/app/src/main/res/values-cs/strings.xml @@ -127,8 +127,8 @@ Přeskočí některé invalidace mezipaměti na straně CPU během aktualizací paměti, čímž sníží zatížení CPU a zlepší jeho výkon. Může způsobit chyby nebo pády v některých hrách. Povolit emulaci hostitelské MMU Tato optimalizace zrychluje přístup do paměti hostovaného programu. Její povolení způsobí, že čtení a zápisy do paměti hosta se provádějí přímo v paměti a využívají hostitelskou MMU. Zakázání této funkce vynutí použití softwarové emulace MMU pro všechny přístupy do paměti. - Přesnost DMA - Ovládá přesnost DMA. Bezpečná přesnost může opravit problémy v některých hrách, ale v některých případech může také ovlivnit výkon. Pokud si nejste jisti, ponechte to na výchozím nastavení. + Úroveň DMA + Ovládá přesnost DMA. Vyšší přesnost může opravit problémy v některých hrách, ale může také ovlivnit výkon. Pokud si nejste jisti, ponechejte výchozí nastavení. 4GB (Doporučeno) 6GB (Nebezpečné) @@ -691,8 +691,7 @@ Relativní střed joysticku D-pad slide Haptická odezva - Zobrazit ovladač - Skrýt ovladač + Zobrazit překryv Přepnout vše Upravit překryv Měřítko @@ -735,8 +734,9 @@ Výchozí - Nebezpečné (rychlé) - Bezpečné (stabilní) + Normální + Vysoká + Extrémní 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml index 495804e328..bff0b0379e 100644 --- a/src/android/app/src/main/res/values-de/strings.xml +++ b/src/android/app/src/main/res/values-de/strings.xml @@ -128,8 +128,8 @@ Überspringt bestimmte Cache-Invalidierungen auf CPU-Seite während Speicherupdates, reduziert die CPU-Auslastung und verbessert die Leistung. Kann in einigen Spielen zu Fehlern oder Abstürzen führen. Host-MMU-Emulation aktivieren Diese Optimierung beschleunigt Speicherzugriffe durch das Gastprogramm. Wenn aktiviert, erfolgen Speicherlese- und -schreibvorgänge des Gastes direkt im Speicher und nutzen die MMU des Hosts. Das Deaktivieren erzwingt die Verwendung der Software-MMU-Emulation für alle Speicherzugriffe. - DMA-Genauigkeit - Steuert die DMA-Präzisionsgenauigkeit. Sichere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel lassen Sie dies auf Standard stehen. + DMA-Level + Steuert die DMA-Präzisionsgenauigkeit. Eine höhere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel auf „Standard“ belassen. 4 GB (Empfohlen) 6 GB (Unsicher) @@ -762,13 +762,6 @@ Wirklich fortfahren? Emulation beenden Fertig FPS Zähler - - Steuerung umschalten - Relativer Stick-Zentrum - D-Pad-Scrollen - Haptisches Feedback - Controller anzeigen - Controller ausblenden Alle umschalten Overlay anpassen Größe @@ -827,8 +820,9 @@ Wirklich fortfahren? Standard - Unsicher (schnell) - Sicher (stabil) + Normal + Hoch + Extrem 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index 2ee0e1783a..888d6d1684 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml @@ -128,8 +128,8 @@ Omite ciertas invalidaciones de caché durante actualizaciones de memoria, reduciendo el uso de CPU y mejorando su rendimiento. Puede causar fallos en algunos juegos. Habilitar emulación de MMU del host Esta optimización acelera los accesos a la memoria por parte del programa invitado. Al habilitarla, las lecturas/escrituras de memoria del invitado se realizan directamente en la memoria y utilizan la MMU del host. Deshabilitar esto obliga a que todos los accesos a la memoria utilicen la emulación de MMU por software. - Precisión de DMA - Controla la precisión de DMA. La precisión segura puede solucionar problemas en algunos juegos, pero también puede afectar al rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado. + Nivel de DMA + Controla la precisión del DMA. Una mayor precisión puede solucionar problemas en algunos juegos, pero también puede afectar el rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado. 4GB (Recomendado) 6GB (Inseguro) @@ -806,8 +806,7 @@ Centro relativo del stick Deslizamiento de la cruceta Toques hápticos - Mostrar controlador - Ocultar controlador + Mostrar overlay Alternar todo Ajustar overlay Escala @@ -870,8 +869,9 @@ Predeterminado - Inseguro (rápido) - Seguro (estable) + Normal + Alto + Extremo 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-fa/strings.xml b/src/android/app/src/main/res/values-fa/strings.xml index 79cf5f49e6..60b1626aa5 100644 --- a/src/android/app/src/main/res/values-fa/strings.xml +++ b/src/android/app/src/main/res/values-fa/strings.xml @@ -128,8 +128,8 @@ بعضی ابطال‌های حافظه نهان در هنگام به‌روزرسانی‌های حافظه را رد می‌کند، استفاده از CPU را کاهش داده و عملکرد آن را بهبود می‌بخشد. ممکن است در برخی بازی‌ها باعث مشکلات یا خرابی شود. فعال‌سازی شبیه‌سازی MMU میزبان این بهینه‌سازی دسترسی‌های حافظه توسط برنامه میهمان را تسریع می‌کند. فعال‌سازی آن باعث می‌شود خواندن/نوشتن حافظه میهمان مستقیماً در حافظه انجام شود و از MMU میزبان استفاده کند. غیرفعال کردن این قابلیت، همه دسترسی‌های حافظه را مجبور به استفاده از شبیه‌سازی نرم‌افزاری MMU می‌کند. - دقت DMA - دقت صحت DMA را کنترل می کند. دقت ایمن می تواند مشکلات برخی بازی ها را برطرف کند، اما در برخی موارد نیز ممکن است بر عملکرد تأثیر بگذارد. اگر مطمئن نیستید، این گزینه را روی پیش فرض بگذارید. + سطح DMA + دقت صحت DMA را کنترل می کند. دقت بالاتر می تواند مشکلات برخی بازی ها را برطرف کند، اما در برخی موارد نیز می تواند بر عملکرد تأثیر بگذارد. اگر مطمئن نیستید، آن را روی پیش فرض بگذارید. 4 گیگابایت (توصیه شده) 6 گیگابایت (ناامن) @@ -805,8 +805,7 @@ مرکز نسبی استیک لغزش دکمه‌های جهتی لرزش لمسی - نمایش کنترلر - پنهان کردن کنترلر + نشان دادن نمایش روی صفحه تغییر همه تنظیم نمایش روی صفحه مقیاس @@ -869,8 +868,9 @@ پیش فرض - ناایمن (سریع) - ایمن (پایدار) + معمولی + بالا + فوق العاده 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml index e9df08a4de..fde02d1aa8 100644 --- a/src/android/app/src/main/res/values-fr/strings.xml +++ b/src/android/app/src/main/res/values-fr/strings.xml @@ -128,8 +128,8 @@ Ignore certaines invalidations de cache côté CPU lors des mises à jour mémoire, réduisant l\'utilisation du CPU et améliorant ses performances. Peut causer des bugs ou plantages sur certains jeux. Activer l\'émulation de la MMU hôte Cette optimisation accélère les accès mémoire par le programme invité. L\'activer entraîne que les lectures/écritures mémoire de l\'invité sont effectuées directement en mémoire et utilisent la MMU de l\'hôte. Désactiver cela force tous les accès mémoire à utiliser l\'émulation logicielle de la MMU. - Précision DMA - Contrôle la précision du DMA. Une précision sûre peut résoudre les problèmes dans certains jeux, mais peut aussi affecter les performances dans certains cas. Si vous n\'êtes pas sûr, laissez ce paramètre sur Par défaut. + Niveau DMA + Contrôle la précision du DMA. Une précision plus élevée peut résoudre les problèmes dans certains jeux, mais peut aussi affecter les performances dans certains cas. Si vous n\'êtes pas sûr, laissez-la sur Défaut. 4 Go (Recommandé) 6 Go (Dangereux) @@ -854,8 +854,7 @@ Centre du stick relatif Glissement du D-pad Toucher haptique - Afficher la manette - Masquer la manette + Afficher l\'overlay Tout basculer Ajuster l\'overlay Échelle @@ -918,8 +917,9 @@ Défaut - Dangereux (rapide) - Sûr (stable) + Normal + Élevé + Extrême 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml index 4e1624a556..59312086e9 100644 --- a/src/android/app/src/main/res/values-he/strings.xml +++ b/src/android/app/src/main/res/values-he/strings.xml @@ -129,8 +129,8 @@ מדלג על איפוסי מטמון מסוימים במהלך עדכוני זיכרון, מפחית שימוש במעבד ומשפר ביצועים. עלול לגרום לתקלות או קריסות בחלק מהמשחקים. הפעל אמולציית MMU מארח אופטימיזציה זו מאיצה את גישת הזיכרון על ידי התוכנית האורחת. הפעלתה גורמת לכך שפעולות קריאה/כתיבה לזיכרון האורח מתבצעות ישירות לזיכרון ומשתמשות ב-MMU של המארח. השבתת זאת מאלצת את כל גישות הזיכרון להשתמש באמולציית MMU תוכנתית. - דיוק DMA - שולט בדיוק הדיוק של DMA. דיוק בטוח יכול לתקן בעיות בחלק מהמשחקים, אך הוא עלול גם להשפיע על הביצועים במקרים מסוימים. אם אינך בטוח, השאר זאת על ברירת מחדל. + רמת DMA + שולטת בדיוק הדיוק של DMA. דיוק גבוה יותר יכול לתקן בעיות בחלק מהמשחקים, אך הוא עלול גם להשפיע על הביצועים במקרים מסוימים. אם אינך בטוח, השאר ברירת מחדל. 4GB (מומלץ) 6GB (לא בטוח) @@ -739,8 +739,7 @@ מרכז ג׳ויסטיק יחסי החלקת D-pad רטט מגע - הצג בקר - הסתר בקר + הצג את שכבת-העל החלף הכל התאם את שכבת-העל קנה מידה @@ -800,8 +799,9 @@ ברירת מחדל - לא בטוח (מהיר) - בטוח (יציב) + רגיל + גבוה + קיצוני 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml index 061ac07388..f95e2d3f97 100644 --- a/src/android/app/src/main/res/values-hu/strings.xml +++ b/src/android/app/src/main/res/values-hu/strings.xml @@ -128,8 +128,8 @@ Kihagy néhány CPU-oldali gyorsítótár-érvénytelenítést memóriafrissítések közben, csökkentve a CPU használatát és javítva a teljesítményt. Néhány játékban hibákat vagy összeomlást okozhat. Gazda MMU emuláció engedélyezése Ez az optimalizáció gyorsítja a vendégprogram memória-hozzáférését. Engedélyezése esetén a vendég memóriaolvasási/írási műveletei közvetlenül a memóriában történnek, és kihasználják a gazda MMU-ját. Letiltás esetén minden memória-hozzáférés a szoftveres MMU emulációt használja. - DMA pontosság - Szabályozza a DMA pontosságát. A biztonságos pontosság megoldhat néhány játék problémáit, de bizonyos esetekben befolyásolhatja a teljesítményt. Ha bizonytalan, hagyja Alapértelmezett beállításon. + DMA szint + Szabályozza a DMA pontosságát. A magasabb pontosság megoldhat néhány játék problémáit, de bizonyos esetekben befolyásolhatja a teljesítményt. Ha bizonytalan, hagyja Alapértelmezett beállításnál. 4GB (Ajánlott) 6GB (Nem biztonságos) @@ -843,8 +843,7 @@ Irányítás átkapcsolása D-pad csúsztatása Érintés haptikája - Vezérlő megjelenítése - Vezérlő elrejtése + Átfedés mutatása Összes átkapcsolása Átfedés testreszabása Skálázás @@ -907,8 +906,9 @@ Alapértelmezett - Nem biztonságos (gyors) - Biztonságos (stabil) + Normál + Magas + Extrém 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-id/strings.xml b/src/android/app/src/main/res/values-id/strings.xml index 6e3b64953f..dae77d53af 100644 --- a/src/android/app/src/main/res/values-id/strings.xml +++ b/src/android/app/src/main/res/values-id/strings.xml @@ -128,8 +128,8 @@ Melewati beberapa pembatalan cache sisi CPU selama pembaruan memori, mengurangi penggunaan CPU dan meningkatkan kinerjanya. Mungkin menyebabkan gangguan atau crash pada beberapa game. Aktifkan Emulasi MMU Host Optimasi ini mempercepat akses memori oleh program tamu. Mengaktifkannya menyebabkan pembacaan/penulisan memori tamu dilakukan langsung ke memori dan memanfaatkan MMU Host. Menonaktifkan ini memaksa semua akses memori menggunakan Emulasi MMU Perangkat Lunak. - Akurasi DMA - Mengontrol keakuratan presisi DMA. Presisi aman dapat memperbaiki masalah di beberapa game, tetapi juga dapat memengaruhi kinerja dalam beberapa kasus. Jika tidak yakin, biarkan ini pada Bawaan. + Level DMA + Mengontrol akurasi presisi DMA. Presisi yang lebih tinggi dapat memperbaiki masalah di beberapa game, tetapi juga dapat memengaruhi performa dalam beberapa kasus. Jika tidak yakin, biarkan di Bawaan. 4GB (Direkomendasikan) 6GB (Tidak Aman) @@ -798,8 +798,7 @@ Pusat stick relatif Geser Dpad Haptik - Tampilkan Kontroler - Sembunyikan Kontroler + Tampilkan Hamparan Alihkan Semua Menyesuaikan Skala @@ -862,8 +861,9 @@ Bawaan - Tidak Aman (cepat) - Aman (stabil) + Normal + Tinggi + Ekstrem 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-it/strings.xml b/src/android/app/src/main/res/values-it/strings.xml index 38a82b3c11..dd184e9d9a 100644 --- a/src/android/app/src/main/res/values-it/strings.xml +++ b/src/android/app/src/main/res/values-it/strings.xml @@ -128,8 +128,8 @@ Salta alcuni invalidamenti della cache lato CPU durante gli aggiornamenti di memoria, riducendo l\'uso della CPU e migliorandone le prestazioni. Potrebbe causare glitch o crash in alcuni giochi. Abilita emulazione MMU host Questa ottimizzazione accelera gli accessi alla memoria da parte del programma guest. Abilitandola, le letture/scritture della memoria guest vengono eseguite direttamente in memoria e sfruttano la MMU host. Disabilitandola, tutti gli accessi alla memoria sono costretti a utilizzare l\'emulazione software della MMU. - Precisione DMA - Controlla la precisione del DMA. La precisione sicura può risolvere problemi in alcuni giochi, ma in alcuni casi può anche influire sulle prestazioni. In caso di dubbi, lascia questo su Predefinito. + Livello DMA + Controlla la precisione del DMA. Una precisione più alta può risolvere problemi in alcuni giochi, ma in alcuni casi può influire sulle prestazioni. Se non sei sicuro, lascia su Predefinito. 4GB (Consigliato) 6GB (Non sicuro) @@ -770,8 +770,7 @@ Centro relativo degli Stick DPad A Scorrimento Feedback Aptico - Mostra l\'controller - Nascondi l\'controller + Mostra l\'overlay Attiva/Disattiva tutto Regola l\'overlay Scala @@ -831,8 +830,9 @@ Predefinito - Non sicuro (veloce) - Sicuro (stabile) + Normale + Alto + Estremo 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml index 179601f182..873d433fc0 100644 --- a/src/android/app/src/main/res/values-ja/strings.xml +++ b/src/android/app/src/main/res/values-ja/strings.xml @@ -128,8 +128,8 @@ メモリ更新時のCPU側キャッシュ無効化をスキップし、CPU使用率を減らして性能を向上させます。一部のゲームで不具合やクラッシュが発生する可能性があります。 ホストMMUエミュレーションを有効化 この最適化により、ゲストプログラムによるメモリアクセスが高速化されます。有効にすると、ゲストのメモリ読み書きが直接メモリ内で実行され、ホストのMMUを利用します。無効にすると、すべてのメモリアクセスでソフトウェアMMUエミュレーションが使用されます。 - DMA精度 - DMAの精度を制御します。安全な精度は一部のゲームの問題を修正できる場合がありますが、場合によってはパフォーマンスに影響を与える可能性もあります。不明な場合は、これをデフォルトのままにしてください。 + DMAレベル + DMAの精度を制御します。精度を高くすると一部のゲームの問題が修正される場合がありますが、場合によってはパフォーマンスに影響を与える可能性もあります。不明な場合は、デフォルトのままにしてください。 4GB (推奨) 6GB (安全でない) @@ -729,8 +729,7 @@ スティックを固定しない 十字キーをスライド操作 タッチ振動 - コントローラーを表示 - コントローラーを非表示 + ボタンを表示 すべて切替 見た目を調整 大きさ @@ -790,8 +789,9 @@ デフォルト - 安全でない(高速) - 安全(安定) + 標準 + + 最高 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml index 6f4dd42af2..3f3a4a96c0 100644 --- a/src/android/app/src/main/res/values-ko/strings.xml +++ b/src/android/app/src/main/res/values-ko/strings.xml @@ -128,8 +128,8 @@ 메모리 업데이트 시 일부 CPU 측 캐시 무효화를 건너뛰어 CPU 사용량을 줄이고 성능을 향상시킵니다. 일부 게임에서 오류 또는 충돌을 일으킬 수 있습니다. 호스트 MMU 에뮬레이션 사용 이 최적화는 게스트 프로그램의 메모리 접근 속도를 높입니다. 활성화하면 게스트의 메모리 읽기/쓰기가 메모리에서 직접 수행되고 호스트의 MMU를 활용합니다. 비활성화하면 모든 메모리 접근에 소프트웨어 MMU 에뮬레이션을 사용하게 됩니다. - DMA 정확도 - DMA 정밀도 정확도를 제어합니다. 안전한 정밀도는 일부 게임의 문제를 해결할 수 있지만 경우에 따라 성능에 영향을 미칠 수도 있습니다. 확실하지 않은 경우 기본값으로 두십시오. + DMA 수준 + DMA 정밀도를 제어합니다. 높은 정밀도는 일부 게임의 문제를 해결할 수 있지만 경우에 따라 성능에 영향을 미칠 수도 있습니다. 확실하지 않다면 기본값으로 두세요. 4GB (권장) 6GB (안전하지 않음) @@ -798,7 +798,6 @@ 십자키 슬라이드 터치 햅틱 컨트롤러 표시 - 컨트롤러 숨기기 모두 선택 컨트롤러 조정 크기 @@ -861,8 +860,9 @@ 기본값 - 안전하지 않음(빠름) - 안전함(안정적) + 보통 + 높음 + 극단적 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-nb/strings.xml b/src/android/app/src/main/res/values-nb/strings.xml index 7f0cffc7c4..1e898fca79 100644 --- a/src/android/app/src/main/res/values-nb/strings.xml +++ b/src/android/app/src/main/res/values-nb/strings.xml @@ -128,8 +128,8 @@ Hopper over enkelte CPU-side cache-invalideringer under minneoppdateringer, reduserer CPU-bruk og forbedrer ytelsen. Kan forårsake feil eller krasj i noen spill. Aktiver verts-MMU-emulering Denne optimaliseringen fremskynder minnetilgang av gjesteprogrammet. Hvis aktivert, utføres gjestens minnelesing/skriving direkte i minnet og bruker vertens MMU. Deaktivering tvinger alle minnetilganger til å bruke programvarebasert MMU-emulering. - DMA-nøyaktighet - Kontrollerer DMA-presisjonsnøyaktigheten. Sikker presisjon kan fikse problemer i noen spill, men kan også påvirke ytelsen i noen tilfeller. Hvis du er usikker, la dette stå på Standard. + DMA-nivå + Styrer DMA-presisjonsnøyaktigheten. Høyere presisjon kan fikse problemer i noen spill, men kan også påvirke ytelsen i noen tilfeller. Hvis du er usikker, la den stå på Standard. 4GB (Anbefalt) 6GB (Usikkert) @@ -720,8 +720,7 @@ Relativt pinnesenter D-pad-skyving Berøringshaptikk - Vis kontroller - Skjul kontroller + Vis overlegg Veksle mellom alle Juster overlegg Skaler @@ -771,8 +770,9 @@ Standard - Usikker (rask) - Sikker (stabil) + Normal + Høy + Ekstrem 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-pl/strings.xml b/src/android/app/src/main/res/values-pl/strings.xml index de9b8f47fc..724d7608b6 100644 --- a/src/android/app/src/main/res/values-pl/strings.xml +++ b/src/android/app/src/main/res/values-pl/strings.xml @@ -128,8 +128,8 @@ Pomija niektóre unieważnienia pamięci podręcznej po stronie CPU podczas aktualizacji pamięci, zmniejszając użycie CPU i poprawiając jego wydajność. Może powodować błędy lub awarie w niektórych grach. Włącz emulację MMU hosta Ta optymalizacja przyspiesza dostęp do pamięci przez program gościa. Włączenie powoduje, że odczyty/zapisy pamięci gościa są wykonywane bezpośrednio w pamięci i wykorzystują MMU hosta. Wyłączenie wymusza użycie programowej emulacji MMU dla wszystkich dostępów do pamięci. - Dokładność DMA - Kontroluje dokładność precyzji DMA. Bezpieczna precyzja może naprawić problemy w niektórych grach, ale w niektórych przypadkach może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość Domyślną. + Poziom DMA + Kontroluje dokładność precyzji DMA. Wyższy poziom może naprawić problemy w niektórych grach, ale może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość «Domyślny». 4GB (Zalecane) 6GB (Niebezpieczne) @@ -718,8 +718,7 @@ Wycentruj gałki Ruchomy D-pad Wibracje haptyczne - Pokaż kontroler - Ukryj kontroler + Pokaż przyciski Włącz wszystkie Dostosuj nakładkę Skala @@ -768,8 +767,9 @@ 預設 - Niezabezpieczone (szybkie) - Bezpieczne (stabilne) + 普通 + + 極高 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml index eec3fdf715..a3fd3fe13a 100644 --- a/src/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml @@ -128,8 +128,8 @@ Ignora algumas invalidações de cache do lado da CPU durante atualizações de memória, reduzindo o uso da CPU e melhorando seu desempenho. Pode causar falhas ou travamentos em alguns jogos. Ativar Emulação de MMU do Host Esta otimização acelera os acessos à memória pelo programa convidado. Ativar isso faz com que as leituras/gravações de memória do convidado sejam feitas diretamente na memória e utilizem a MMU do Host. Desativar isso força todos os acessos à memória a usarem a Emulação de MMU por Software. - Precisão de DMA - Controla a precisão do DMA. A precisão segura pode corrigir problemas em alguns jogos, mas também pode afetar o desempenho em alguns casos. Se não tiver certeza, deixe isso como Padrão. + Nível DMA + Controla a precisão do DMA. Maior precisão pode corrigir problemas em alguns jogos, mas também pode impactar o desempenho em alguns casos. Se não tiver certeza, deixe em Padrão. 4GB (Recomendado) 6GB (Inseguro) @@ -855,8 +855,7 @@ uma tentativa de mapeamento automático Centro Relativo do Analógico Deslizamento dos Botões Direcionais Vibração ao tocar - Mostrar controle - Ocultar controle + Mostrar overlay Marcar/Desmarcar tudo Ajustar overlay Escala @@ -919,8 +918,9 @@ uma tentativa de mapeamento automático Padrão - Inseguro (rápido) - Seguro (estável) + Normal + Alto + Extremo 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml index d45bf4bfc9..7adce075cf 100644 --- a/src/android/app/src/main/res/values-pt-rPT/strings.xml +++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml @@ -128,8 +128,8 @@ Ignora algumas invalidações de cache do lado da CPU durante atualizações de memória, reduzindo a utilização da CPU e melhorando o desempenho. Pode causar falhas ou crashes em alguns jogos. Ativar Emulação de MMU do Anfitrião Esta otimização acelera os acessos à memória pelo programa convidado. Ativar faz com que as leituras/escritas de memória do convidado sejam efetuadas diretamente na memória e utilizem a MMU do Anfitrião. Desativar força todos os acessos à memória a usar a Emulação de MMU por Software. - Precisão da DMA - Controla a precisão da DMA. A precisão segura pode resolver problemas em alguns jogos, mas também pode afetar o desempenho nalguns casos. Se não tiver a certeza, deixe esta opção em Predefinido. + Nível DMA + Controla a precisão do DMA. Maior precisão pode corrigir problemas em alguns jogos, mas também pode afetar o desempenho nalguns casos. Se não tiver a certeza, deixe em Predefinido. 4GB (Recomendado) 6GB (Inseguro) @@ -855,8 +855,7 @@ uma tentativa de mapeamento automático Centro Relativo de Analógico Deslizamento dos Botões Direcionais Vibração ao tocar - Mostrar comando - Ocultar comando + Mostrar overlay Marcar/Desmarcar tudo Ajustar overlay Escala @@ -919,8 +918,9 @@ uma tentativa de mapeamento automático Predefinido - Inseguro (rápido) - Seguro (estável) + Normal + Alto + Extremo 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml index 2f7714257f..8d02ff7b58 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml @@ -128,8 +128,8 @@ Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх. Включить эмуляцию MMU хоста Эта оптимизация ускоряет доступ к памяти гостевой программой. При включении операции чтения/записи памяти гостя выполняются напрямую в памяти с использованием MMU хоста. Отключение заставляет все обращения к памяти использовать программную эмуляцию MMU. - Точность DMA - Управляет точностью DMA. Безопасная точность может исправить проблемы в некоторых играх, но в некоторых случаях также может повлиять на производительность. Если не уверены, оставьте значение По умолчанию. + Уровень DMA + Управляет точностью DMA. Более высокий уровень может исправить проблемы в некоторых играх, но также может повлиять на производительность. Если не уверены, оставьте значение «По умолчанию». 4 ГБ (Рекомендуется) 6 ГБ (Небезопасно) @@ -856,8 +856,7 @@ Относительный центр стика Слайд крестовиной Обратная связь от нажатий - Показать контроллер - Скрыть контроллер + Показать оверлей Переключить всё Регулировка оверлея Масштаб @@ -920,8 +919,9 @@ По умолчанию - Небезопасно (быстро) - Безопасно (стабильно) + Нормальный + Высокий + Экстремальный 0.25X (180p/270p) @@ -955,7 +955,7 @@ Авто Альбомная (сенсор) - Альбомная + Пейзаж Обратная альбомная Портретная (сенсор) Портрет diff --git a/src/android/app/src/main/res/values-sr/strings.xml b/src/android/app/src/main/res/values-sr/strings.xml index e261772fc4..2294033550 100644 --- a/src/android/app/src/main/res/values-sr/strings.xml +++ b/src/android/app/src/main/res/values-sr/strings.xml @@ -121,8 +121,8 @@ Preskače određena poništavanja keša na strani CPU-a tokom ažuriranja memorije, smanjujući opterećenje procesora i poboljšavajući performanse. Može izazvati greške u nekim igrama. Омогући емулацију MMU домаћина Ова оптимизација убрзава приступ меморији од стране гостујућег програма. Укључивање изазива да се читања/уписа меморије госта обављају директно у меморији и користе MMU домаћина. Искључивање присиљава све приступе меморији да користе софтверску емулацију MMU. - DMA тачност - Управља прецизношћу DMA-а. Сигурна прецизност може да исправи проблеме у неким играма, али у неким случајевима може да утиче и на перформансе. Ако нисте сигурни, оставите ово на Подразумевано. + DMA ниво + Контролише тачност DMA прецизности. Виши ниво може да поправи проблеме у неким играма, али може и да утиче на перформансе. Ако нисте сигурни, оставите на «Подразумевано». Схадер Бацкенд @@ -812,8 +812,7 @@ Релативни центар за штапић Д-Пад Слиде Додирните ХАптицс - Приказати контролер - Сакрити контролер + Приказати прекривање Пребацивати све Подесити прекривање Скала @@ -915,8 +914,9 @@ Подразумевано - Небезбедно (брзо) - Безбедно (стабилно) + Нормално + Високо + Екстремно АСТЦ метода декодирања diff --git a/src/android/app/src/main/res/values-uk/strings.xml b/src/android/app/src/main/res/values-uk/strings.xml index 2222402a25..ebb5493f12 100644 --- a/src/android/app/src/main/res/values-uk/strings.xml +++ b/src/android/app/src/main/res/values-uk/strings.xml @@ -128,8 +128,8 @@ Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх. Увімкнути емуляцію MMU хоста Ця оптимізація пришвидшує доступ до пам\'яті гостьовою програмою. Увімкнення призводить до того, що читання/запис пам\'яті гостя виконуються безпосередньо в пам\'яті та використовують MMU хоста. Вимкнення змушує всі звернення до пам\'яті використовувати програмну емуляцію MMU. - Точність DMA - Керує точністю DMA. Безпечна точність може виправити проблеми в деяких іграх, але в деяких випадках також може вплинути на продуктивність. Якщо не впевнені, залиште це значення за замовчуванням. + Рівень DMA + Керує точністю DMA. Вищий рівень може виправити проблеми в деяких іграх, але також може вплинути на продуктивність. Якщо не впевнені, залиште значення «Типово». 4 ГБ (Рекомендовано) 6 ГБ (Небезпечно) @@ -749,8 +749,7 @@ Відносний центр джойстика Ковзання D-pad Тактильний відгук - Показати контролер - Сховати контролер + Показати накладання Перемкнути все Налаштувати накладання Масштаб @@ -809,8 +808,9 @@ Типово - Небезпечно (швидко) - Безпечно (стабільно) + Нормальний + Високий + Екстремальний 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml index 784b2dec14..102c720835 100644 --- a/src/android/app/src/main/res/values-vi/strings.xml +++ b/src/android/app/src/main/res/values-vi/strings.xml @@ -128,8 +128,8 @@ Bỏ qua một số lần vô hiệu hóa bộ nhớ đệm phía CPU trong khi cập nhật bộ nhớ, giảm mức sử dụng CPU và cải thiện hiệu suất. Có thể gây ra lỗi hoặc treo máy trong một số trò chơi. Bật giả lập MMU Máy chủ Tối ưu hóa này tăng tốc độ truy cập bộ nhớ của chương trình khách. Bật nó lên khiến các thao tác đọc/ghi bộ nhớ khách được thực hiện trực tiếp vào bộ nhớ và sử dụng MMU của Máy chủ. Tắt tính năng này buộc tất cả quyền truy cập bộ nhớ phải sử dụng Giả lập MMU Phần mềm. - Độ chính xác DMA - Điều khiển độ chính xác của DMA. Độ chính xác an toàn có thể khắc phục sự cố trong một số trò chơi, nhưng trong một số trường hợp cũng có thể ảnh hưởng đến hiệu suất. Nếu không chắc chắn, hãy để giá trị này ở Mặc định. + Cấp độ DMA + Điều khiển độ chính xác của DMA. Độ chính xác cao hơn có thể sửa lỗi trong một số trò chơi, nhưng cũng có thể ảnh hưởng đến hiệu suất trong một số trường hợp. Nếu không chắc chắn, hãy để ở Mặc định. 4GB (Được đề xuất) 6GB (Không an toàn) @@ -723,8 +723,7 @@ Trung tâm nút cần xoay tương đối Trượt D-pad Chạm haptics - Hiện bộ điều khiển - Ẩn bộ điều khiển + Hiện lớp phủ Chuyển đổi tất cả Điều chỉnh lớp phủ Tỉ lệ thu phóng @@ -774,8 +773,9 @@ Mặc định - Không an toàn (nhanh) - An toàn (ổn định) + Bình thường + Cao + Cực cao 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml index bfdc3af3d3..a0dab375d0 100644 --- a/src/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml @@ -127,8 +127,8 @@ 在内存更新期间跳过某些CPU端缓存无效化,减少CPU使用率并提高其性能。可能会导致某些游戏出现故障或崩溃。 启用主机 MMU 模拟 此优化可加速来宾程序的内存访问。启用后,来宾内存读取/写入将直接在内存中执行并利用主机的 MMU。禁用此功能将强制所有内存访问使用软件 MMU 模拟。 - DMA 精度 - 控制 DMA 精度。安全精度可以修复某些游戏中的问题,但在某些情况下也可能影响性能。如果不确定,请保留为“默认”。 + DMA 级别 + 控制 DMA 精度。更高的精度可以修复某些游戏中的问题,但在某些情况下也可能影响性能。如果不确定,请保留为“默认”。 4GB (推荐) 6GB (不安全) @@ -848,8 +848,7 @@ 相对摇杆中心 十字方向键滑动 触觉反馈 - 显示控制器 - 隐藏控制器 + 显示虚拟按键 全部切换 调整虚拟按键 缩放 @@ -912,8 +911,9 @@ 默认 - 不安全(快速) - 安全(稳定) + 普通 + + 极高 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml index e64aaa9a54..851483668a 100644 --- a/src/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml @@ -120,8 +120,8 @@ 在記憶體更新期間跳過某些CPU端快取無效化,減少CPU使用率並提高其性能。可能會導致某些遊戲出現故障或崩潰。 啟用主機 MMU 模擬 此最佳化可加速來賓程式的記憶體存取。啟用後,來賓記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。 - DMA 精度 - 控制 DMA 精度。安全精度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為「預設」。 + DMA 級別 + 控制 DMA 精確度。更高的精確度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為「預設」。 4GB (推薦) @@ -853,8 +853,7 @@ 相對搖桿中心 方向鍵滑動 觸覺回饋技術 - 顯示控制器 - 隱藏控制器 + 顯示覆疊 全部切換 調整覆疊 縮放 @@ -917,8 +916,9 @@ 預設 - 不安全(快速) - 安全(穩定) + 普通 + + 極高 0.25X (180p/270p) diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 08ca53ad81..2f0392675d 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -454,13 +454,15 @@ @string/dma_accuracy_default - @string/dma_accuracy_unsafe - @string/dma_accuracy_safe + @string/dma_accuracy_normal + @string/dma_accuracy_high + @string/dma_accuracy_extreme 0 1 2 + 3 diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 2cef5903cb..f73fc1d9aa 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -115,8 +115,8 @@ Use Boost (1700MHz) to run at the Switch\'s highest native clock, or Fast (2000MHz) to run at 2x clock. Memory Layout (EXPERIMENTAL) Change the emulated memory layout. This setting will not increase performance, but may help with games utilizing high resolutions via mods. Do not use on phones with 8GB of RAM or less. Only works on the Dynarmic (JIT) backend. - DMA Accuracy - Controls the DMA precision accuracy. Safe precision can fix issues in some games, but it can also impact performance in some cases. If unsure, leave this on Default. + DMA Level + Controls the DMA precision accuracy. Higher precision can fix issues in some games, but it can also impact performance in some cases. If unsure, leave it at Default. Shader Backend @@ -266,7 +266,6 @@ Alphabetical List Grid - Compact Grid Carousel Screenshot for %1$s Folder @@ -836,8 +835,7 @@ Relative stick center D-pad slide Touch haptics - Show controller - Hide controller + Show overlay Toggle all Adjust overlay Scale @@ -940,8 +938,9 @@ Default - Unsafe (fast) - Safe (stable) + Normal + High + Extreme ASTC Decoding Method diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index 389b1044e9..e040ec756d 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -1,6 +1,3 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later @@ -232,10 +229,9 @@ endif() target_include_directories(audio_core PRIVATE ${OPUS_INCLUDE_DIRS}) target_link_libraries(audio_core PUBLIC common core opus) -# what? -# if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) -# target_link_libraries(audio_core PRIVATE dynarmic::dynarmic) -# endif() +if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) + target_link_libraries(audio_core PRIVATE dynarmic::dynarmic) +endif() if (ENABLE_CUBEB) target_sources(audio_core PRIVATE @@ -244,7 +240,7 @@ if (ENABLE_CUBEB) ) target_link_libraries(audio_core PRIVATE cubeb) - target_compile_definitions(audio_core PRIVATE HAVE_CUBEB=1) + target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1) endif() if (ENABLE_SDL2) diff --git a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp index b874f87ae6..d799f3f06f 100644 --- a/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp +++ b/src/audio_core/adsp/apps/audio_renderer/audio_renderer.cpp @@ -193,7 +193,7 @@ void AudioRenderer::Main(std::stop_token stop_token) { } } - max_time = (std::min)(command_buffer.time_limit, max_time); + max_time = std::min(command_buffer.time_limit, max_time); command_list_processor.SetProcessTimeMax(max_time); if (index == 0) { diff --git a/src/audio_core/common/common.h b/src/audio_core/common/common.h index eaf0c6470f..6abd9be45e 100644 --- a/src/audio_core/common/common.h +++ b/src/audio_core/common/common.h @@ -73,9 +73,9 @@ constexpr s32 HighestVoicePriority = 0; constexpr u32 BufferAlignment = 0x40; constexpr u32 WorkbufferAlignment = 0x1000; constexpr s32 FinalMixId = 0; -constexpr s32 InvalidDistanceFromFinalMix = (std::numeric_limits::min)(); +constexpr s32 InvalidDistanceFromFinalMix = std::numeric_limits::min(); constexpr s32 UnusedSplitterId = -1; -constexpr s32 UnusedMixId = (std::numeric_limits::max)(); +constexpr s32 UnusedMixId = std::numeric_limits::max(); constexpr u32 InvalidNodeId = 0xF0000000; constexpr s32 InvalidProcessOrder = -1; constexpr u32 MaxBiquadFilters = 2; diff --git a/src/audio_core/common/feature_support.h b/src/audio_core/common/feature_support.h index 39d50746b8..eef2a844ba 100644 --- a/src/audio_core/common/feature_support.h +++ b/src/audio_core/common/feature_support.h @@ -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 @@ -16,7 +13,7 @@ #include "common/polyfill_ranges.h" namespace AudioCore { -constexpr u32 CurrentRevision = 16; +constexpr u32 CurrentRevision = 13; enum class SupportTags { CommandProcessingTimeEstimatorVersion4, @@ -57,7 +54,6 @@ constexpr u32 GetRevisionNum(u32 user_revision) { user_revision -= Common::MakeMagic('R', 'E', 'V', '0'); user_revision >>= 24; } - return user_revision; }; diff --git a/src/audio_core/device/audio_buffers.h b/src/audio_core/device/audio_buffers.h index 9016246fbf..9e84a9c059 100644 --- a/src/audio_core/device/audio_buffers.h +++ b/src/audio_core/device/audio_buffers.h @@ -51,7 +51,7 @@ public: */ void RegisterBuffers(boost::container::static_vector& out_buffers) { std::scoped_lock l{lock}; - const s32 to_register{(std::min)((std::min)(appended_count, BufferAppendLimit), + const s32 to_register{std::min(std::min(appended_count, BufferAppendLimit), BufferAppendLimit - registered_count)}; for (s32 i = 0; i < to_register; i++) { @@ -175,7 +175,7 @@ public: } size_t buffers_to_flush{ - (std::min)(static_cast(registered_count + appended_count), max_buffers)}; + std::min(static_cast(registered_count + appended_count), max_buffers)}; if (buffers_to_flush == 0) { return 0; } diff --git a/src/audio_core/renderer/audio_device.cpp b/src/audio_core/renderer/audio_device.cpp index 387d23b0b4..5be5594f6f 100644 --- a/src/audio_core/renderer/audio_device.cpp +++ b/src/audio_core/renderer/audio_device.cpp @@ -45,7 +45,7 @@ u32 AudioDevice::ListAudioDeviceName(std::span out_buffer) cons names = device_names; } - const u32 out_count{static_cast((std::min)(out_buffer.size(), names.size()))}; + const u32 out_count{static_cast(std::min(out_buffer.size(), names.size()))}; for (u32 i = 0; i < out_count; i++) { out_buffer[i] = names[i]; } @@ -53,7 +53,7 @@ u32 AudioDevice::ListAudioDeviceName(std::span out_buffer) cons } u32 AudioDevice::ListAudioOutputDeviceName(std::span out_buffer) const { - const u32 out_count{static_cast((std::min)(out_buffer.size(), output_device_names.size()))}; + const u32 out_count{static_cast(std::min(out_buffer.size(), output_device_names.size()))}; for (u32 i = 0; i < out_count; i++) { out_buffer[i] = output_device_names[i]; diff --git a/src/audio_core/renderer/behavior/behavior_info.cpp b/src/audio_core/renderer/behavior/behavior_info.cpp index f139e63ffb..0585390426 100644 --- a/src/audio_core/renderer/behavior/behavior_info.cpp +++ b/src/audio_core/renderer/behavior/behavior_info.cpp @@ -43,7 +43,7 @@ void BehaviorInfo::AppendError(const ErrorInfo& error) { } void BehaviorInfo::CopyErrorInfo(std::span out_errors, u32& out_count) const { - out_count = (std::min)(error_count, MaxErrors); + out_count = std::min(error_count, MaxErrors); for (size_t i = 0; i < MaxErrors; i++) { if (i < out_count) { diff --git a/src/audio_core/renderer/command/command_buffer.cpp b/src/audio_core/renderer/command/command_buffer.cpp index f9e8575691..67d43e69aa 100644 --- a/src/audio_core/renderer/command/command_buffer.cpp +++ b/src/audio_core/renderer/command/command_buffer.cpp @@ -464,7 +464,7 @@ void CommandBuffer::GenerateDeviceSinkCommand(const s32 node_id, const s16 buffe s16 max_input{0}; for (u32 i = 0; i < parameter.input_count; i++) { cmd.inputs[i] = buffer_offset + parameter.inputs[i]; - max_input = (std::max)(max_input, cmd.inputs[i]); + max_input = std::max(max_input, cmd.inputs[i]); } if (state.upsampler_info != nullptr) { diff --git a/src/audio_core/renderer/command/command_generator.h b/src/audio_core/renderer/command/command_generator.h index 497cfa92f2..38ee2a64ee 100644 --- a/src/audio_core/renderer/command/command_generator.h +++ b/src/audio_core/renderer/command/command_generator.h @@ -56,11 +56,11 @@ public: // Voices u64 voice_size{0}; if (behavior.IsWaveBufferVer2Supported()) { - voice_size = (std::max)((std::max)(sizeof(AdpcmDataSourceVersion2Command), + voice_size = std::max(std::max(sizeof(AdpcmDataSourceVersion2Command), sizeof(PcmInt16DataSourceVersion2Command)), sizeof(PcmFloatDataSourceVersion2Command)); } else { - voice_size = (std::max)((std::max)(sizeof(AdpcmDataSourceVersion1Command), + voice_size = std::max(std::max(sizeof(AdpcmDataSourceVersion1Command), sizeof(PcmInt16DataSourceVersion1Command)), sizeof(PcmFloatDataSourceVersion1Command)); } @@ -82,7 +82,7 @@ public: // Sinks size += - params.sinks * (std::max)(sizeof(DeviceSinkCommand), sizeof(CircularBufferSinkCommand)); + params.sinks * std::max(sizeof(DeviceSinkCommand), sizeof(CircularBufferSinkCommand)); // Performance size += (params.effects + params.voices + params.sinks + params.sub_mixes + 1 + diff --git a/src/audio_core/renderer/command/data_source/decode.cpp b/src/audio_core/renderer/command/data_source/decode.cpp index b42ecb961f..905613a5a8 100644 --- a/src/audio_core/renderer/command/data_source/decode.cpp +++ b/src/audio_core/renderer/command/data_source/decode.cpp @@ -29,8 +29,8 @@ constexpr std::array PitchBySrcQuality = {4, 8, 4}; template static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, const DecodeArg& req) { - constexpr s32 min{(std::numeric_limits::min)()}; - constexpr s32 max{(std::numeric_limits::max)()}; + constexpr s32 min{std::numeric_limits::min()}; + constexpr s32 max{std::numeric_limits::max()}; if (req.buffer == 0 || req.buffer_size == 0) { return 0; @@ -41,7 +41,7 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, } auto samples_to_decode{ - (std::min)(req.samples_to_read, req.end_offset - req.start_offset - req.offset)}; + std::min(req.samples_to_read, req.end_offset - req.start_offset - req.offset)}; u32 channel_count{static_cast(req.channel_count)}; switch (req.channel_count) { @@ -55,7 +55,7 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, if constexpr (std::is_floating_point_v) { for (u32 i = 0; i < samples_to_decode; i++) { auto sample{static_cast(samples[i * channel_count + req.target_channel] * - (std::numeric_limits::max)())}; + std::numeric_limits::max())}; out_buffer[i] = static_cast(std::clamp(sample, min, max)); } } else { @@ -79,7 +79,7 @@ static u32 DecodePcm(Core::Memory::Memory& memory, std::span out_buffer, if constexpr (std::is_floating_point_v) { for (u32 i = 0; i < samples_to_decode; i++) { auto sample{static_cast(samples[i * channel_count + req.target_channel] * - (std::numeric_limits::max)())}; + std::numeric_limits::max())}; out_buffer[i] = static_cast(std::clamp(sample, min, max)); } } else { @@ -125,7 +125,7 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span out_buffer, } auto start_pos{req.start_offset + req.offset}; - auto samples_to_process{(std::min)(req.end_offset - start_pos, req.samples_to_read)}; + auto samples_to_process{std::min(req.end_offset - start_pos, req.samples_to_read)}; if (samples_to_process == 0) { return 0; } @@ -139,7 +139,7 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span out_buffer, position_in_frame += 2; } - const auto size{(std::max)((samples_to_process / 8U) * SamplesPerFrame, 8U)}; + const auto size{std::max((samples_to_process / 8U) * SamplesPerFrame, 8U)}; Core::Memory::CpuGuestMemory wavebuffer( memory, req.buffer + position_in_frame / 2, size); @@ -260,7 +260,7 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf auto max_remaining_sample_count{ ((Common::FixedPoint<17, 15>(TempBufferSize) - fraction) / sample_rate_ratio) .to_uint_floor()}; - max_remaining_sample_count = (std::min)(max_remaining_sample_count, remaining_sample_count); + max_remaining_sample_count = std::min(max_remaining_sample_count, remaining_sample_count); auto wavebuffers_consumed{voice_state.wave_buffers_consumed}; auto wavebuffer_index{voice_state.wave_buffer_index}; @@ -273,7 +273,7 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf std::array temp_buffer{}; while (remaining_sample_count > 0) { - const auto samples_to_write{(std::min)(remaining_sample_count, max_remaining_sample_count)}; + const auto samples_to_write{std::min(remaining_sample_count, max_remaining_sample_count)}; const auto samples_to_read{ (fraction + samples_to_write * sample_rate_ratio).to_uint_floor()}; diff --git a/src/audio_core/renderer/command/effect/aux_.cpp b/src/audio_core/renderer/command/effect/aux_.cpp index cb23007a66..74d9c229f3 100644 --- a/src/audio_core/renderer/command/effect/aux_.cpp +++ b/src/audio_core/renderer/command/effect/aux_.cpp @@ -86,7 +86,7 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_, u32 write_count{write_count_}; u32 read_pos{0}; while (write_count > 0) { - u32 to_write{(std::min)(count_max - target_write_offset, write_count)}; + u32 to_write{std::min(count_max - target_write_offset, write_count)}; if (to_write > 0) { const auto write_addr = send_buffer + target_write_offset * sizeof(s32); memory.WriteBlockUnsafe(write_addr, &input[read_pos], to_write * sizeof(s32)); @@ -157,7 +157,7 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_, u32 read_count{read_count_}; u32 write_pos{0}; while (read_count > 0) { - u32 to_read{(std::min)(count_max - target_read_offset, read_count)}; + u32 to_read{std::min(count_max - target_read_offset, read_count)}; if (to_read > 0) { const auto read_addr = return_buffer + target_read_offset * sizeof(s32); memory.ReadBlockUnsafe(read_addr, &output[write_pos], to_read * sizeof(s32)); diff --git a/src/audio_core/renderer/command/effect/biquad_filter.cpp b/src/audio_core/renderer/command/effect/biquad_filter.cpp index dbc7085d16..3392e7747d 100644 --- a/src/audio_core/renderer/command/effect/biquad_filter.cpp +++ b/src/audio_core/renderer/command/effect/biquad_filter.cpp @@ -20,8 +20,8 @@ namespace AudioCore::Renderer { void ApplyBiquadFilterFloat(std::span output, std::span input, std::array& b_, std::array& a_, VoiceState::BiquadFilterState& state, const u32 sample_count) { - constexpr f64 min{(std::numeric_limits::min)()}; - constexpr f64 max{(std::numeric_limits::max)()}; + constexpr f64 min{std::numeric_limits::min()}; + constexpr f64 max{std::numeric_limits::max()}; std::array b{Common::FixedPoint<50, 14>::from_base(b_[0]).to_double(), Common::FixedPoint<50, 14>::from_base(b_[1]).to_double(), Common::FixedPoint<50, 14>::from_base(b_[2]).to_double()}; @@ -61,8 +61,8 @@ void ApplyBiquadFilterFloat(std::span output, std::span input, static void ApplyBiquadFilterInt(std::span output, std::span input, std::array& b, std::array& a, VoiceState::BiquadFilterState& state, const u32 sample_count) { - constexpr s64 min{(std::numeric_limits::min)()}; - constexpr s64 max{(std::numeric_limits::max)()}; + constexpr s64 min{std::numeric_limits::min()}; + constexpr s64 max{std::numeric_limits::max()}; for (u32 i = 0; i < sample_count; i++) { const s64 in_sample{input[i]}; diff --git a/src/audio_core/renderer/command/effect/capture.cpp b/src/audio_core/renderer/command/effect/capture.cpp index 95bc88e464..f235ce027f 100644 --- a/src/audio_core/renderer/command/effect/capture.cpp +++ b/src/audio_core/renderer/command/effect/capture.cpp @@ -79,7 +79,7 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in u32 write_count{write_count_}; u32 write_pos{0}; while (write_count > 0) { - u32 to_write{(std::min)(count_max - target_write_offset, write_count)}; + u32 to_write{std::min(count_max - target_write_offset, write_count)}; if (to_write > 0) { memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32), diff --git a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp index 14e77b3cb2..ecfdfabc61 100644 --- a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp +++ b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp @@ -76,9 +76,9 @@ static void UpdateI3dl2ReverbEffectParameter(const I3dl2ReverbInfo::ParameterVer state.dry_gain = params.dry_gain; Common::FixedPoint<50, 14> early_gain{ - (std::min)(params.room_gain + params.reflection_gain, 5000.0f) / 2000.0f}; + std::min(params.room_gain + params.reflection_gain, 5000.0f) / 2000.0f}; state.early_gain = pow_10(early_gain.to_float()); - Common::FixedPoint<50, 14> late_gain{(std::min)(params.room_gain + params.reverb_gain, 5000.0f) / + Common::FixedPoint<50, 14> late_gain{std::min(params.room_gain + params.reverb_gain, 5000.0f) / 2000.0f}; state.late_gain = pow_10(late_gain.to_float()); @@ -94,7 +94,7 @@ static void UpdateI3dl2ReverbEffectParameter(const I3dl2ReverbInfo::ParameterVer const Common::FixedPoint<50, 14> c{ std::sqrt(std::pow(b.to_float(), 2.0f) + (std::pow(a.to_float(), 2.0f) * -4.0f))}; - state.lowpass_1 = (std::min)(((b - c) / (a * 2.0f)).to_float(), 0.99723f); + state.lowpass_1 = std::min(((b - c) / (a * 2.0f)).to_float(), 0.99723f); state.lowpass_2 = 1.0f - state.lowpass_1; } diff --git a/src/audio_core/renderer/command/effect/light_limiter.cpp b/src/audio_core/renderer/command/effect/light_limiter.cpp index 3488dd37b5..63aa06f5c3 100644 --- a/src/audio_core/renderer/command/effect/light_limiter.cpp +++ b/src/audio_core/renderer/command/effect/light_limiter.cpp @@ -50,8 +50,8 @@ static void ApplyLightLimiterEffect(const LightLimiterInfo::ParameterVersion2& p std::span> inputs, std::span> outputs, const u32 sample_count, LightLimiterInfo::StatisticsInternal* statistics) { - constexpr s64 min{(std::numeric_limits::min)()}; - constexpr s64 max{(std::numeric_limits::max)()}; + constexpr s64 min{std::numeric_limits::min()}; + constexpr s64 max{std::numeric_limits::max()}; const auto recip_estimate = [](f64 a) -> f64 { s32 q, s; @@ -117,9 +117,9 @@ static void ApplyLightLimiterEffect(const LightLimiterInfo::ParameterVersion2& p if (statistics) { statistics->channel_max_sample[channel] = - (std::max)(statistics->channel_max_sample[channel], abs_sample.to_float()); + std::max(statistics->channel_max_sample[channel], abs_sample.to_float()); statistics->channel_compression_gain_min[channel] = - (std::min)(statistics->channel_compression_gain_min[channel], + std::min(statistics->channel_compression_gain_min[channel], state.compression_gain[channel].to_float()); } } diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp index 67b893305a..7f152a9629 100644 --- a/src/audio_core/renderer/command/effect/reverb.cpp +++ b/src/audio_core/renderer/command/effect/reverb.cpp @@ -94,7 +94,7 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par for (u32 i = 0; i < ReverbInfo::MaxDelayTaps; i++) { auto early_delay{ ((pre_delay_time + EarlyDelayTimes[params.early_mode][i]) * sample_rate).to_int()}; - early_delay = (std::min)(early_delay, state.pre_delay_line.sample_count_max); + early_delay = std::min(early_delay, state.pre_delay_line.sample_count_max); state.early_delay_times[i] = early_delay + 1; state.early_gains[i] = Common::FixedPoint<50, 14>::from_base(params.early_gain) * EarlyDelayGains[params.early_mode][i]; @@ -107,7 +107,7 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par auto pre_time{ ((pre_delay_time + EarlyDelayTimes[params.early_mode][10]) * sample_rate).to_int()}; - state.pre_delay_time = (std::min)(pre_time, state.pre_delay_line.sample_count_max); + state.pre_delay_time = std::min(pre_time, state.pre_delay_line.sample_count_max); if (!unk_initialized) { unk_value = cos((1280.0f / sample_rate).to_float()); @@ -117,13 +117,13 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) { const auto fdn_delay{(FdnDelayTimes[params.late_mode][i] * sample_rate).to_int()}; state.fdn_delay_lines[i].sample_count = - (std::min)(fdn_delay, state.fdn_delay_lines[i].sample_count_max); + std::min(fdn_delay, state.fdn_delay_lines[i].sample_count_max); state.fdn_delay_lines[i].buffer_end = &state.fdn_delay_lines[i].buffer[state.fdn_delay_lines[i].sample_count - 1]; const auto decay_delay{(DecayDelayTimes[params.late_mode][i] * sample_rate).to_int()}; state.decay_delay_lines[i].sample_count = - (std::min)(decay_delay, state.decay_delay_lines[i].sample_count_max); + std::min(decay_delay, state.decay_delay_lines[i].sample_count_max); state.decay_delay_lines[i].buffer_end = &state.decay_delay_lines[i].buffer[state.decay_delay_lines[i].sample_count - 1]; diff --git a/src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp b/src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp index f80fb92631..caedb56b79 100644 --- a/src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp +++ b/src/audio_core/renderer/command/mix/depop_for_mix_buffers.cpp @@ -43,7 +43,7 @@ void DepopForMixBuffersCommand::Dump( } void DepopForMixBuffersCommand::Process(const AudioRenderer::CommandListProcessor& processor) { - auto end_index{(std::min)(processor.buffer_count, input + count)}; + auto end_index{std::min(processor.buffer_count, input + count)}; std::span depop_buff{reinterpret_cast(depop_buffer), end_index}; for (u32 index = input; index < end_index; index++) { diff --git a/src/audio_core/renderer/command/resample/upsample.cpp b/src/audio_core/renderer/command/resample/upsample.cpp index add975504c..691d70390f 100644 --- a/src/audio_core/renderer/command/resample/upsample.cpp +++ b/src/audio_core/renderer/command/resample/upsample.cpp @@ -215,7 +215,7 @@ auto UpsampleCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListProc void UpsampleCommand::Process(const AudioRenderer::CommandListProcessor& processor) { const auto info{reinterpret_cast(upsampler_info)}; - const auto input_count{(std::min)(info->input_count, buffer_count)}; + const auto input_count{std::min(info->input_count, buffer_count)}; const std::span inputs_{reinterpret_cast(inputs), input_count}; for (u32 i = 0; i < input_count; i++) { diff --git a/src/audio_core/renderer/command/sink/circular_buffer.cpp b/src/audio_core/renderer/command/sink/circular_buffer.cpp index 8ef48a26df..e056d15a65 100644 --- a/src/audio_core/renderer/command/sink/circular_buffer.cpp +++ b/src/audio_core/renderer/command/sink/circular_buffer.cpp @@ -21,8 +21,8 @@ void CircularBufferSinkCommand::Dump( } void CircularBufferSinkCommand::Process(const AudioRenderer::CommandListProcessor& processor) { - constexpr s32 min{(std::numeric_limits::min)()}; - constexpr s32 max{(std::numeric_limits::max)()}; + constexpr s32 min{std::numeric_limits::min()}; + constexpr s32 max{std::numeric_limits::max()}; std::array output{}; for (u32 channel = 0; channel < input_count; channel++) { diff --git a/src/audio_core/renderer/command/sink/device.cpp b/src/audio_core/renderer/command/sink/device.cpp index 86a257363b..3480ed475c 100644 --- a/src/audio_core/renderer/command/sink/device.cpp +++ b/src/audio_core/renderer/command/sink/device.cpp @@ -20,8 +20,8 @@ void DeviceSinkCommand::Dump([[maybe_unused]] const AudioRenderer::CommandListPr } void DeviceSinkCommand::Process(const AudioRenderer::CommandListProcessor& processor) { - constexpr s32 min = (std::numeric_limits::min)(); - constexpr s32 max = (std::numeric_limits::max)(); + constexpr s32 min = std::numeric_limits::min(); + constexpr s32 max = std::numeric_limits::max(); auto stream{processor.GetOutputSinkStream()}; stream->SetSystemChannels(input_count); diff --git a/src/audio_core/renderer/mix/mix_context.cpp b/src/audio_core/renderer/mix/mix_context.cpp index 1103af910b..c712610bbd 100644 --- a/src/audio_core/renderer/mix/mix_context.cpp +++ b/src/audio_core/renderer/mix/mix_context.cpp @@ -126,7 +126,7 @@ bool MixContext::TSortInfo(const SplitterContext& splitter_context) { } auto sorted_results{node_states.GetSortedResuls()}; - const auto result_size{(std::min)(count, static_cast(sorted_results.second))}; + const auto result_size{std::min(count, static_cast(sorted_results.second))}; for (s32 i = 0; i < result_size; i++) { sorted_mix_infos[i] = &mix_infos[sorted_results.first[i]]; } diff --git a/src/audio_core/renderer/sink/sink_info_base.h b/src/audio_core/renderer/sink/sink_info_base.h index 2a7fd81f68..e10d1cb382 100644 --- a/src/audio_core/renderer/sink/sink_info_base.h +++ b/src/audio_core/renderer/sink/sink_info_base.h @@ -168,9 +168,9 @@ protected: /// Node id for this sink u32 node_id{}; /// State buffer for this sink - std::array state{}; + std::array state{}; /// Parameter buffer for this sink - std::array + std::array parameter{}; }; diff --git a/src/audio_core/renderer/splitter/splitter_context.cpp b/src/audio_core/renderer/splitter/splitter_context.cpp index 583cbaf735..d0f3b60c29 100644 --- a/src/audio_core/renderer/splitter/splitter_context.cpp +++ b/src/audio_core/renderer/splitter/splitter_context.cpp @@ -170,7 +170,7 @@ void SplitterContext::RecomposeDestination(SplitterInfo& out_info, auto dest_count{info_header->destination_count}; if (!splitter_bug_fixed) { - dest_count = (std::min)(dest_count, GetDestCountPerInfoForCompat()); + dest_count = std::min(dest_count, GetDestCountPerInfoForCompat()); } if (dest_count == 0) { diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp index c4a2768b93..c30d68426c 100644 --- a/src/audio_core/renderer/system.cpp +++ b/src/audio_core/renderer/system.cpp @@ -718,7 +718,7 @@ u64 System::GenerateCommand(std::span in_command_buffer, const auto estimated_time{start_estimated_time - end_estimated_time}; - const auto time_limit{static_cast((std::max)(dsp_time_limit + estimated_time, 0.0f))}; + const auto time_limit{static_cast(std::max(dsp_time_limit + estimated_time, 0.0f))}; num_voices_dropped = DropVoices(command_buffer, static_cast(start_estimated_time), time_limit); } diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp index a3a7a89ba4..a33162b806 100644 --- a/src/audio_core/sink/cubeb_sink.cpp +++ b/src/audio_core/sink/cubeb_sink.cpp @@ -73,7 +73,7 @@ public: minimum_latency = TargetSampleCount * 2; } - minimum_latency = (std::max)(minimum_latency, TargetSampleCount * 2); + minimum_latency = std::max(minimum_latency, TargetSampleCount * 2); LOG_INFO(Service_Audio, "Opening cubeb stream {} type {} with: rate {} channels {} (system channels {}) " @@ -372,7 +372,7 @@ u32 GetCubebLatency() { LOG_CRITICAL(Audio_Sink, "Error getting minimum latency, error: {}", latency_error); latency = TargetSampleCount * 2; } - latency = (std::max)(latency, TargetSampleCount * 2); + latency = std::max(latency, TargetSampleCount * 2); cubeb_destroy(ctx); return latency; } @@ -426,7 +426,7 @@ bool IsCubebSuitable() { LOG_ERROR(Audio_Sink, "Cubeb could not get min latency, it is not suitable."); return false; } - latency = (std::max)(latency, TargetSampleCount * 2); + latency = std::max(latency, TargetSampleCount * 2); // Test opening a device with standard parameters cubeb_devid output_device{0}; diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index b75d743494..22653207d3 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -31,8 +31,8 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span samples) { return; } - constexpr s32 min{(std::numeric_limits::min)()}; - constexpr s32 max{(std::numeric_limits::max)()}; + constexpr s32 min{std::numeric_limits::min()}; + constexpr s32 max{std::numeric_limits::max()}; auto yuzu_volume{Settings::Volume()}; if (yuzu_volume > 1.0f) { @@ -123,8 +123,8 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::span samples) { } std::vector SinkStream::ReleaseBuffer(u64 num_samples) { - constexpr s32 min = (std::numeric_limits::min)(); - constexpr s32 max = (std::numeric_limits::max)(); + constexpr s32 min = std::numeric_limits::min(); + constexpr s32 max = std::numeric_limits::max(); auto samples{samples_buffer.Pop(num_samples)}; diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 665143900a..6173e29f45 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -162,6 +162,10 @@ add_library( zstd_compression.h ) +if(YUZU_ENABLE_PORTABLE) + add_compile_definitions(YUZU_ENABLE_PORTABLE) +endif() + if(WIN32) target_sources(common PRIVATE windows/timer_resolution.cpp windows/timer_resolution.h) @@ -237,7 +241,7 @@ else() ) # Get around GCC failing with intrinsics in Debug - if(CXX_GCC AND CMAKE_BUILD_TYPE MATCHES "Debug") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_BUILD_TYPE MATCHES "Debug") set_property( SOURCE stb.cpp APPEND @@ -245,7 +249,7 @@ else() endif() endif() -if(CXX_CLANG) +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_options(common PRIVATE -fsized-deallocation -Werror=unreachable-code-aggressive) target_compile_definitions( @@ -258,18 +262,23 @@ if(CXX_CLANG) endif() if (BOOST_NO_HEADERS) - target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool) + target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool) else() - target_link_libraries(common PUBLIC Boost::headers) + target_link_libraries(common PUBLIC Boost::headers) endif() if (lz4_ADDED) - target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib) + target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib) endif() target_link_libraries(common PUBLIC fmt::fmt stb::headers Threads::Threads) target_link_libraries(common PRIVATE lz4::lz4 LLVM::Demangle zstd::zstd) +if (TARGET unordered_dense::unordered_dense) + # weird quirk of system installs + target_link_libraries(common PUBLIC unordered_dense::unordered_dense) +endif() + if(ANDROID) # For ASharedMemory_create target_link_libraries(common PRIVATE android) diff --git a/src/common/free_region_manager.h b/src/common/free_region_manager.h index 39d52f866c..2e590d6094 100644 --- a/src/common/free_region_manager.h +++ b/src/common/free_region_manager.h @@ -27,8 +27,8 @@ public: // If we are, join with them, ensuring we stay in bounds. if (it != m_free_regions.end()) { - start_address = (std::min)(start_address, it->lower()); - end_address = (std::max)(end_address, it->upper()); + start_address = std::min(start_address, it->lower()); + end_address = std::max(end_address, it->upper()); } // Free the relevant region. diff --git a/src/common/fs/fs_paths.h b/src/common/fs/fs_paths.h index 5cdf9be39d..40891380c9 100644 --- a/src/common/fs/fs_paths.h +++ b/src/common/fs/fs_paths.h @@ -12,6 +12,7 @@ #define PORTABLE_DIR "user" // Sub-directories contained within a yuzu data directory + #define AMIIBO_DIR "amiibo" #define CACHE_DIR "cache" #define CONFIG_DIR "config" @@ -27,12 +28,11 @@ #define SHADER_DIR "shader" #define TAS_DIR "tas" #define ICONS_DIR "icons" - -// Compatibility with other emulators #define CITRON_DIR "citron" #define SUDACHI_DIR "sudachi" #define YUZU_DIR "yuzu" #define SUYU_DIR "suyu" // yuzu-specific files + #define LOG_FILE "eden_log.txt" diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index 318f311891..fa1403225e 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp @@ -101,53 +101,61 @@ public: legacy_paths.insert_or_assign(legacy_path, new_path); } - /// In non-android devices, the current directory will first search for "user" - /// if such directory (and it must be a directory) is found, that takes priority - /// over the global configuration directory (in other words, portable directories - /// take priority over the global ones, always) - /// On Android, the behaviour is to look for the current directory only. void Reinitialize(fs::path eden_path = {}) { fs::path eden_path_cache; fs::path eden_path_config; + #ifdef _WIN32 - // User directory takes priority over global %AppData% directory +#ifdef YUZU_ENABLE_PORTABLE eden_path = GetExeDirectory() / PORTABLE_DIR; - if (!Exists(eden_path) || !IsDir(eden_path)) { +#endif + if (!IsDir(eden_path)) { eden_path = GetAppDataRoamingDirectory() / EDEN_DIR; } + eden_path_cache = eden_path / CACHE_DIR; eden_path_config = eden_path / CONFIG_DIR; + #define LEGACY_PATH(titleName, upperName) GenerateLegacyPath(LegacyPath::titleName##Dir, GetAppDataRoamingDirectory() / upperName##_DIR); \ GenerateLegacyPath(LegacyPath::titleName##ConfigDir, GetAppDataRoamingDirectory() / upperName##_DIR / CONFIG_DIR); \ GenerateLegacyPath(LegacyPath::titleName##CacheDir, GetAppDataRoamingDirectory() / upperName##_DIR / CACHE_DIR); + LEGACY_PATH(Citron, CITRON) LEGACY_PATH(Sudachi, SUDACHI) LEGACY_PATH(Yuzu, YUZU) LEGACY_PATH(Suyu, SUYU) #undef LEGACY_PATH + #elif ANDROID ASSERT(!eden_path.empty()); eden_path_cache = eden_path / CACHE_DIR; eden_path_config = eden_path / CONFIG_DIR; #else +#ifdef YUZU_ENABLE_PORTABLE eden_path = GetCurrentDir() / PORTABLE_DIR; - if (!Exists(eden_path) || !IsDir(eden_path)) { +#endif + if (Exists(eden_path) && IsDir(eden_path)) { + eden_path_cache = eden_path / CACHE_DIR; + eden_path_config = eden_path / CONFIG_DIR; + } else { eden_path = GetDataDirectory("XDG_DATA_HOME") / EDEN_DIR; eden_path_cache = GetDataDirectory("XDG_CACHE_HOME") / EDEN_DIR; eden_path_config = GetDataDirectory("XDG_CONFIG_HOME") / EDEN_DIR; - } else { - eden_path_cache = eden_path / CACHE_DIR; - eden_path_config = eden_path / CONFIG_DIR; } + #define LEGACY_PATH(titleName, upperName) GenerateLegacyPath(LegacyPath::titleName##Dir, GetDataDirectory("XDG_DATA_HOME") / upperName##_DIR); \ GenerateLegacyPath(LegacyPath::titleName##ConfigDir, GetDataDirectory("XDG_CONFIG_HOME") / upperName##_DIR); \ GenerateLegacyPath(LegacyPath::titleName##CacheDir, GetDataDirectory("XDG_CACHE_HOME") / upperName##_DIR); + LEGACY_PATH(Citron, CITRON) LEGACY_PATH(Sudachi, SUDACHI) LEGACY_PATH(Yuzu, YUZU) LEGACY_PATH(Suyu, SUYU) + #undef LEGACY_PATH + #endif + GenerateEdenPath(EdenPath::EdenDir, eden_path); GenerateEdenPath(EdenPath::AmiiboDir, eden_path / AMIIBO_DIR); GenerateEdenPath(EdenPath::CacheDir, eden_path_cache); @@ -484,9 +492,9 @@ std::string GetParentPath(std::string_view path) { std::size_t name_index; if (name_bck_index == std::string_view::npos || name_fwd_index == std::string_view::npos) { - name_index = (std::min)(name_bck_index, name_fwd_index); + name_index = std::min(name_bck_index, name_fwd_index); } else { - name_index = (std::max)(name_bck_index, name_fwd_index); + name_index = std::max(name_bck_index, name_fwd_index); } return std::string(path.substr(0, name_index)); @@ -506,7 +514,7 @@ std::string_view GetPathWithoutTop(std::string_view path) { const auto name_bck_index = path.find('\\'); const auto name_fwd_index = path.find('/'); - return path.substr((std::min)(name_bck_index, name_fwd_index) + 1); + return path.substr(std::min(name_bck_index, name_fwd_index) + 1); } } // namespace Common::FS diff --git a/src/common/heap_tracker.cpp b/src/common/heap_tracker.cpp index 7cce54976e..c147c279bd 100644 --- a/src/common/heap_tracker.cpp +++ b/src/common/heap_tracker.cpp @@ -1,3 +1,5 @@ +// 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 @@ -33,68 +35,60 @@ HeapTracker::~HeapTracker() = default; void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, bool is_separate_heap) { + bool rebuild_required = false; // When mapping other memory, map pages immediately. if (!is_separate_heap) { m_buffer.Map(virtual_offset, host_offset, length, perm, false); return; } - { - // We are mapping part of a separate heap. + // We are mapping part of a separate heap and insert into mappings. std::scoped_lock lk{m_lock}; - - auto* const map = new SeparateHeapMap{ - .vaddr = virtual_offset, + m_map_count++; + const auto it = m_mappings.insert_or_assign(virtual_offset, SeparateHeapMap{ .paddr = host_offset, .size = length, .tick = m_tick++, .perm = perm, .is_resident = false, - }; - - // Insert into mappings. - m_map_count++; - m_mappings.insert(*map); + }); + // Update tick before possible rebuild. + it.first->second.tick = m_tick++; + // Check if we need to rebuild. + if (m_resident_map_count >= m_max_resident_map_count) + rebuild_required = true; + // Map the area. + m_buffer.Map(it.first->first, it.first->second.paddr, it.first->second.size, it.first->second.perm, false); + // This map is now resident. + it.first->second.is_resident = true; + m_resident_map_count++; + m_resident_mappings.insert(*it.first); } - - // Finally, map. - this->DeferredMapSeparateHeap(virtual_offset); + // A rebuild was required, so perform it now. + if (rebuild_required) + this->RebuildSeparateHeapAddressSpace(); } void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) { // If this is a separate heap... if (is_separate_heap) { std::scoped_lock lk{m_lock}; - - const SeparateHeapMap key{ - .vaddr = virtual_offset, - }; - // Split at the boundaries of the region we are removing. this->SplitHeapMapLocked(virtual_offset); this->SplitHeapMapLocked(virtual_offset + size); - // Erase all mappings in range. - auto it = m_mappings.find(key); - while (it != m_mappings.end() && it->vaddr < virtual_offset + size) { - // Get underlying item. - auto* const item = std::addressof(*it); - + auto it = m_mappings.find(virtual_offset); + while (it != m_mappings.end() && it->first < virtual_offset + size) { // If resident, erase from resident map. - if (item->is_resident) { + if (it->second.is_resident) { ASSERT(--m_resident_map_count >= 0); - m_resident_mappings.erase(m_resident_mappings.iterator_to(*item)); + m_resident_mappings.erase(m_resident_mappings.find(it->first)); } - // Erase from map. ASSERT(--m_map_count >= 0); it = m_mappings.erase(it); - - // Free the item. - delete item; } } - // Unmap pages. m_buffer.Unmap(virtual_offset, size, false); } @@ -116,109 +110,51 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p { std::scoped_lock lk2{m_lock}; - - const SeparateHeapMap key{ - .vaddr = next, - }; - // Try to get the next mapping corresponding to this address. - const auto it = m_mappings.nfind(key); - + const auto it = m_mappings.find(next); if (it == m_mappings.end()) { // There are no separate heap mappings remaining. next = end; should_protect = true; - } else if (it->vaddr == cur) { + } else if (it->first == cur) { // We are in range. // Update permission bits. - it->perm = perm; + it->second.perm = perm; // Determine next address and whether we should protect. - next = cur + it->size; - should_protect = it->is_resident; + next = cur + it->second.size; + should_protect = it->second.is_resident; } else /* if (it->vaddr > cur) */ { // We weren't in range, but there is a block coming up that will be. - next = it->vaddr; + next = it->first; should_protect = true; } } // Clamp to end. - next = (std::min)(next, end); + next = std::min(next, end); // Reprotect, if we need to. - if (should_protect) { + if (should_protect) m_buffer.Protect(cur, next - cur, perm); - } - // Advance. cur = next; } } -bool HeapTracker::DeferredMapSeparateHeap(u8* fault_address) { - if (m_buffer.IsInVirtualRange(fault_address)) { - return this->DeferredMapSeparateHeap(fault_address - m_buffer.VirtualBasePointer()); - } - - return false; -} - -bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) { - bool rebuild_required = false; - - { - std::scoped_lock lk{m_lock}; - - // Check to ensure this was a non-resident separate heap mapping. - const auto it = this->GetNearestHeapMapLocked(virtual_offset); - if (it == m_mappings.end() || it->is_resident) { - return false; - } - - // Update tick before possible rebuild. - it->tick = m_tick++; - - // Check if we need to rebuild. - if (m_resident_map_count > m_max_resident_map_count) { - rebuild_required = true; - } - - // Map the area. - m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false); - - // This map is now resident. - it->is_resident = true; - m_resident_map_count++; - m_resident_mappings.insert(*it); - } - - if (rebuild_required) { - // A rebuild was required, so perform it now. - this->RebuildSeparateHeapAddressSpace(); - } - - return true; -} - void HeapTracker::RebuildSeparateHeapAddressSpace() { std::scoped_lock lk{m_rebuild_lock, m_lock}; - ASSERT(!m_resident_mappings.empty()); - // Dump half of the mappings. - // // Despite being worse in theory, this has proven to be better in practice than more // regularly dumping a smaller amount, because it significantly reduces average case // lock contention. - std::size_t const desired_count = (std::min)(m_resident_map_count, m_max_resident_map_count) / 2; + std::size_t const desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2; std::size_t const evict_count = m_resident_map_count - desired_count; auto it = m_resident_mappings.begin(); - - for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) { + for (std::size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) { // Unmark and unmap. - it->is_resident = false; - m_buffer.Unmap(it->vaddr, it->size, false); - + it->second.is_resident = false; + m_buffer.Unmap(it->first, it->second.size, false); // Advance. ASSERT(--m_resident_map_count >= 0); it = m_resident_mappings.erase(it); @@ -227,53 +163,32 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() { void HeapTracker::SplitHeapMap(VAddr offset, size_t size) { std::scoped_lock lk{m_lock}; - this->SplitHeapMapLocked(offset); this->SplitHeapMapLocked(offset + size); } void HeapTracker::SplitHeapMapLocked(VAddr offset) { - const auto it = this->GetNearestHeapMapLocked(offset); - if (it == m_mappings.end() || it->vaddr == offset) { - // Not contained or no split required. - return; + auto it = this->GetNearestHeapMapLocked(offset); + if (it != m_mappings.end() && it->first != offset) { + // Adjust left iterator + auto const orig_size = it->second.size; + auto const left_size = offset - it->first; + it->second.size = left_size; + // Insert the new right map. + auto const right = SeparateHeapMap{ + .paddr = it->second.paddr + left_size, + .size = orig_size - left_size, + .tick = it->second.tick, + .perm = it->second.perm, + .is_resident = it->second.is_resident, + }; + m_map_count++; + auto rit = m_mappings.insert_or_assign(it->first + left_size, right); + if (rit.first->second.is_resident) { + m_resident_map_count++; + m_resident_mappings.insert(*rit.first); + } } - - // Cache the original values. - auto* const left = std::addressof(*it); - const size_t orig_size = left->size; - - // Adjust the left map. - const size_t left_size = offset - left->vaddr; - left->size = left_size; - - // Create the new right map. - auto* const right = new SeparateHeapMap{ - .vaddr = left->vaddr + left_size, - .paddr = left->paddr + left_size, - .size = orig_size - left_size, - .tick = left->tick, - .perm = left->perm, - .is_resident = left->is_resident, - }; - - // Insert the new right map. - m_map_count++; - m_mappings.insert(*right); - - // If resident, also insert into resident map. - if (right->is_resident) { - m_resident_map_count++; - m_resident_mappings.insert(*right); - } -} - -HeapTracker::AddrTree::iterator HeapTracker::GetNearestHeapMapLocked(VAddr offset) { - const SeparateHeapMap key{ - .vaddr = offset, - }; - - return m_mappings.find(key); } } // namespace Common diff --git a/src/common/heap_tracker.h b/src/common/heap_tracker.h index ee5b0bf43a..14b5401c18 100644 --- a/src/common/heap_tracker.h +++ b/src/common/heap_tracker.h @@ -1,93 +1,55 @@ +// 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 #pragma once -#include #include -#include #include - +#include #include "common/host_memory.h" -#include "common/intrusive_red_black_tree.h" namespace Common { struct SeparateHeapMap { - Common::IntrusiveRedBlackTreeNode addr_node{}; - Common::IntrusiveRedBlackTreeNode tick_node{}; - VAddr vaddr{}; - PAddr paddr{}; - size_t size{}; - size_t tick{}; - MemoryPermission perm{}; - bool is_resident{}; -}; - -struct SeparateHeapMapAddrComparator { - static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) { - if (lhs.vaddr < rhs.vaddr) { - return -1; - } else if (lhs.vaddr <= (rhs.vaddr + rhs.size - 1)) { - return 0; - } else { - return 1; - } - } -}; - -struct SeparateHeapMapTickComparator { - static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) { - if (lhs.tick < rhs.tick) { - return -1; - } else if (lhs.tick > rhs.tick) { - return 1; - } else { - return SeparateHeapMapAddrComparator::Compare(lhs, rhs); - } - } + PAddr paddr{}; //8 + std::size_t size{}; //8 (16) + std::size_t tick{}; //8 (24) + // 4 bits needed, sync with host_memory.h if needed + MemoryPermission perm : 4 = MemoryPermission::Read; + bool is_resident : 1 = false; }; +static_assert(sizeof(SeparateHeapMap) == 32); //half a cache line! good for coherency class HeapTracker { public: explicit HeapTracker(Common::HostMemory& buffer); ~HeapTracker(); - - void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, - bool is_separate_heap); + void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, bool is_separate_heap); void Unmap(size_t virtual_offset, size_t size, bool is_separate_heap); void Protect(size_t virtual_offset, size_t length, MemoryPermission perm); - u8* VirtualBasePointer() { + inline u8* VirtualBasePointer() noexcept { return m_buffer.VirtualBasePointer(); } - - bool DeferredMapSeparateHeap(u8* fault_address); - bool DeferredMapSeparateHeap(size_t virtual_offset); - private: - using AddrTreeTraits = - Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::addr_node>; - using AddrTree = AddrTreeTraits::TreeType; - - using TickTreeTraits = - Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::tick_node>; - using TickTree = TickTreeTraits::TreeType; - - AddrTree m_mappings{}; - TickTree m_resident_mappings{}; - + // TODO: You may want to "fake-map" the first 2GB of 64-bit address space + // and dedicate it entirely to a recursive PTE mapping :) + // However Ankerl is way better than using an RB tree, in all senses + using AddrTree = ankerl::unordered_dense::map; + AddrTree m_mappings; + using TicksTree = ankerl::unordered_dense::map; + TicksTree m_resident_mappings; private: void SplitHeapMap(VAddr offset, size_t size); void SplitHeapMapLocked(VAddr offset); - - AddrTree::iterator GetNearestHeapMapLocked(VAddr offset); - void RebuildSeparateHeapAddressSpace(); - + inline HeapTracker::AddrTree::iterator GetNearestHeapMapLocked(VAddr offset) noexcept { + return m_mappings.find(offset); + } private: Common::HostMemory& m_buffer; const s64 m_max_resident_map_count; - std::shared_mutex m_rebuild_lock{}; std::mutex m_lock{}; s64 m_map_count{}; diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 2e36d59569..e70ac216cb 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -12,7 +12,7 @@ #include #include "common/dynamic_library.h" -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__) // ^^^ Windows ^^^ vvv POSIX vvv +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) // ^^^ Windows ^^^ vvv Linux vvv #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -20,18 +20,10 @@ #include #include #include +#include #include #include "common/scope_exit.h" -#if defined(__linux__) -#include -#elif defined(__APPLE__) -#include -#include -#include -#include -#endif - // FreeBSD #ifndef MAP_NORESERVE #define MAP_NORESERVE 0 @@ -40,12 +32,8 @@ #ifndef MAP_ALIGNED_SUPER #define MAP_ALIGNED_SUPER 0 #endif -// macOS -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif -#endif // ^^^ POSIX ^^^ +#endif // ^^^ Linux ^^^ #include #include @@ -199,8 +187,8 @@ public: std::scoped_lock lock{placeholder_mutex}; auto [it, end] = placeholders.equal_range({virtual_offset, virtual_end}); while (it != end) { - const size_t offset = (std::max)(it->lower(), virtual_offset); - const size_t protect_length = (std::min)(it->upper(), virtual_end) - offset; + const size_t offset = std::max(it->lower(), virtual_offset); + const size_t protect_length = std::min(it->upper(), virtual_end) - offset; DWORD old_flags{}; if (!VirtualProtect(virtual_base + offset, protect_length, new_flags, &old_flags)) { LOG_CRITICAL(HW_Memory, "Failed to change virtual memory protect rules"); @@ -266,8 +254,8 @@ private: } const size_t placeholder_begin = it->lower(); const size_t placeholder_end = it->upper(); - const size_t unmap_begin = (std::max)(virtual_offset, placeholder_begin); - const size_t unmap_end = (std::min)(virtual_offset + length, placeholder_end); + const size_t unmap_begin = std::max(virtual_offset, placeholder_begin); + const size_t unmap_end = std::min(virtual_offset + length, placeholder_end); ASSERT(unmap_begin >= placeholder_begin && unmap_begin < placeholder_end); ASSERT(unmap_end <= placeholder_end && unmap_end > placeholder_begin); @@ -384,7 +372,7 @@ private: std::unordered_map placeholder_host_pointers; ///< Placeholder backing offset }; -#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__) // ^^^ Windows ^^^ vvv POSIX vvv +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) // ^^^ Windows ^^^ vvv Linux vvv #ifdef ARCHITECTURE_arm64 @@ -501,13 +489,6 @@ public: #elif defined(__FreeBSD__) && __FreeBSD__ < 13 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 fd = shm_open(SHM_ANON, O_RDWR, 0600); -#elif defined(__APPLE__) - // macOS doesn't have memfd_create, use anonymous temporary file - char template_path[] = "/tmp/eden_mem_XXXXXX"; - fd = mkstemp(template_path); - if (fd >= 0) { - unlink(template_path); - } #else fd = memfd_create("HostMemory", 0); #endif @@ -598,17 +579,12 @@ public: bool ClearBackingRegion(size_t physical_offset, size_t length) { #ifdef __linux__ - // Only incur syscall cost IF memset would be slower (theshold = 16MiB) - // TODO(lizzie): Smarter way to dynamically get this threshold (broadwell != raptor lake) for example - if (length >= 2097152UL * 8) { - // Set MADV_REMOVE on backing map to destroy it instantly. - // This also deletes the area from the backing file. - int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE); - ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno)); - return true; - } else { - return false; - } + // Set MADV_REMOVE on backing map to destroy it instantly. + // This also deletes the area from the backing file. + int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE); + ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno)); + + return true; #else return false; #endif @@ -660,8 +636,8 @@ private: *virtual_offset = 0; *length = 0; } else { - *virtual_offset = (std::max)(intended_start, address_space_start); - *length = (std::min)(intended_end, address_space_end) - *virtual_offset; + *virtual_offset = std::max(intended_start, address_space_start); + *length = std::min(intended_end, address_space_end) - *virtual_offset; } } @@ -669,7 +645,7 @@ private: FreeRegionManager free_manager{}; }; -#else // ^^^ POSIX ^^^ vvv Generic vvv +#else // ^^^ Linux ^^^ vvv Generic vvv class HostMemory::Impl { public: diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 252c83aa2c..6da9e5231a 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -18,7 +18,7 @@ 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("..\\")}); + auto idx = std::max({rfind("src/"), rfind("src\\"), rfind("../"), rfind("..\\")}); return source.data() + idx; } diff --git a/src/common/math_util.h b/src/common/math_util.h index f52a0a35ae..1f5928c15f 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h @@ -85,10 +85,10 @@ struct Rectangle { } [[nodiscard]] constexpr bool Intersect(const Rectangle& with, Rectangle* result) const { - result->left = (std::max)(left, with.left); - result->top = (std::max)(top, with.top); - result->right = (std::min)(right, with.right); - result->bottom = (std::min)(bottom, with.bottom); + result->left = std::max(left, with.left); + result->top = std::max(top, with.top); + result->right = std::min(right, with.right); + result->bottom = std::min(bottom, with.bottom); return !result->IsEmpty(); } }; diff --git a/src/common/overflow.h b/src/common/overflow.h index d39fa24041..e184ead953 100644 --- a/src/common/overflow.h +++ b/src/common/overflow.h @@ -25,9 +25,9 @@ template inline bool CanAddWithoutOverflow(T lhs, T rhs) { #ifdef _MSC_VER if (lhs >= 0 && rhs >= 0) { - return WrappingAdd(lhs, rhs) >= (std::max)(lhs, rhs); + return WrappingAdd(lhs, rhs) >= std::max(lhs, rhs); } else if (lhs < 0 && rhs < 0) { - return WrappingAdd(lhs, rhs) <= (std::min)(lhs, rhs); + return WrappingAdd(lhs, rhs) <= std::min(lhs, rhs); } else { return true; } diff --git a/src/common/range_map.h b/src/common/range_map.h index e9cb50825b..ab73993e3b 100644 --- a/src/common/range_map.h +++ b/src/common/range_map.h @@ -18,7 +18,7 @@ private: public: explicit RangeMap(ValueT null_value_) : null_value{null_value_} { - container.emplace((std::numeric_limits::min)(), null_value); + container.emplace(std::numeric_limits::min(), null_value); }; ~RangeMap() = default; @@ -66,7 +66,7 @@ private: } const auto it_end = std::next(it); if (it_end == container.end()) { - return (std::numeric_limits::max)() - address; + return std::numeric_limits::max() - address; } return it_end->first - address; } diff --git a/src/common/range_sets.inc b/src/common/range_sets.inc index 3edd8c8a43..b83eceb7b0 100644 --- a/src/common/range_sets.inc +++ b/src/common/range_sets.inc @@ -274,7 +274,7 @@ void OverlapRangeSet::Subtract(AddressType base_address, size_t siz template void OverlapRangeSet::DeleteAll(AddressType base_address, size_t size) { - m_impl->template Subtract(base_address, size, (std::numeric_limits::max)(), + m_impl->template Subtract(base_address, size, std::numeric_limits::max(), [](AddressType, AddressType) {}); } diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index e97854f514..86de96b43e 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h @@ -29,7 +29,7 @@ class RingBuffer { // T must be safely memcpy-able and have a trivial default constructor. static_assert(std::is_trivial_v); // Ensure capacity is sensible. - static_assert(capacity < (std::numeric_limits::max)() / 2); + static_assert(capacity < std::numeric_limits::max() / 2); static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two"); // Ensure lock-free. static_assert(std::atomic_size_t::is_always_lock_free); @@ -43,9 +43,9 @@ public: std::lock_guard lock(rb_mutex); const std::size_t slots_free = capacity + read_index - write_index; - const std::size_t push_count = (std::min)(slot_count, slots_free); + const std::size_t push_count = std::min(slot_count, slots_free); const std::size_t pos = write_index % capacity; - const std::size_t first_copy = (std::min)(capacity - pos, push_count); + const std::size_t first_copy = std::min(capacity - pos, push_count); const std::size_t second_copy = push_count - first_copy; const char* in = static_cast(new_slots); @@ -69,9 +69,9 @@ public: std::lock_guard lock(rb_mutex); const std::size_t slots_filled = write_index - read_index; - const std::size_t pop_count = (std::min)(slots_filled, max_slots); + const std::size_t pop_count = std::min(slots_filled, max_slots); const std::size_t pos = read_index % capacity; - const std::size_t first_copy = (std::min)(capacity - pos, pop_count); + const std::size_t first_copy = std::min(capacity - pos, pop_count); const std::size_t second_copy = pop_count - first_copy; char* out = static_cast(output); @@ -84,7 +84,7 @@ public: } std::vector Pop(std::size_t max_slots = ~std::size_t(0)) { - std::vector out((std::min)(max_slots, capacity)); + std::vector out(std::min(max_slots, capacity)); const std::size_t count = Pop(out.data(), out.size()); out.resize(count); return out; diff --git a/src/common/scm_rev.cpp.in b/src/common/scm_rev.cpp.in index a157d03878..b6bff72867 100644 --- a/src/common/scm_rev.cpp.in +++ b/src/common/scm_rev.cpp.in @@ -1,11 +1,12 @@ -// SPDX-FileCopyrightText: 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 #include "common/scm_rev.h" +#include +#include +#include + #define GIT_REV "@GIT_REV@" #define GIT_BRANCH "@GIT_BRANCH@" #define GIT_DESC "@GIT_DESC@" @@ -17,21 +18,64 @@ #define TITLE_BAR_FORMAT_IDLE "@TITLE_BAR_FORMAT_IDLE@" #define TITLE_BAR_FORMAT_RUNNING "@TITLE_BAR_FORMAT_RUNNING@" #define IS_DEV_BUILD @IS_DEV_BUILD@ -#define COMPILER_ID "@CXX_COMPILER@" namespace Common { -constexpr const char g_scm_rev[] = GIT_REV; -constexpr const char g_scm_branch[] = GIT_BRANCH; -constexpr const char g_scm_desc[] = GIT_DESC; -constexpr const char g_build_name[] = BUILD_NAME; -constexpr const char g_build_date[] = BUILD_DATE; -constexpr const char g_build_fullname[] = BUILD_FULLNAME; -constexpr const char g_build_version[] = BUILD_VERSION; -constexpr const char g_build_id[] = BUILD_ID; -constexpr const char g_title_bar_format_idle[] = TITLE_BAR_FORMAT_IDLE; -constexpr const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING; -constexpr const bool g_is_dev_build = IS_DEV_BUILD; -constexpr const char g_compiler_id[] = COMPILER_ID; +const char* g_scm_rev; +const char* g_scm_branch; +const char* g_scm_desc; +const char g_build_name[] = BUILD_NAME; +const char g_build_date[] = BUILD_DATE; +const char g_build_fullname[] = BUILD_FULLNAME; +const char g_build_version[] = BUILD_VERSION; +const char g_build_id[] = BUILD_ID; +const char g_title_bar_format_idle[] = TITLE_BAR_FORMAT_IDLE; +const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING; +const bool g_is_dev_build = IS_DEV_BUILD; +/// Anonymizes SCM data +/// This is quite weak. But better than nothing. +class scm_encrypt { + std::string m_scm_rev, m_scm_branch, m_scm_desc; + +public: + scm_encrypt() { + // Get a key that is easy to obtain when asking the person directly but (usually) hard to + // guess + std::string key; +#ifdef __linux__ + if (!std::getline(std::ifstream("/proc/sys/kernel/hostname"), key)) + key = "linux_error_key"; +#else + // Not a good fallback, but better than nothing I guess? + key = g_build_date; +#endif + // Copy strings in place + m_scm_rev = GIT_REV; + m_scm_branch = GIT_BRANCH; + m_scm_desc = GIT_DESC; + // XOR each string with key + auto key_it = key.begin(); + for (auto& string : {&m_scm_rev, &m_scm_branch, &m_scm_desc}) { + for (auto& c : *string) { + c ^= *key_it; + if (++key_it == key.end()) + key_it = key.begin(); + } + } + // Make each string human-readable + for (auto& string : {&m_scm_rev, &m_scm_branch, &m_scm_desc}) { + const std::string original = *string; + string->clear(); + for (const auto c : original) { + string->append(fmt::format("{:x}", unsigned(c))); + } + string->pop_back(); + } + // Set pointers + g_scm_rev = m_scm_rev.c_str(); + g_scm_branch = m_scm_branch.c_str(); + g_scm_desc = m_scm_desc.c_str(); + } +} scm_encrypt_instance; } // namespace Common diff --git a/src/common/scm_rev.h b/src/common/scm_rev.h index 84356ad64a..ee1997950a 100644 --- a/src/common/scm_rev.h +++ b/src/common/scm_rev.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: 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 @@ -8,9 +5,9 @@ namespace Common { -extern const char g_scm_rev[]; -extern const char g_scm_branch[]; -extern const char g_scm_desc[]; +extern const char* g_scm_rev; +extern const char* g_scm_branch; +extern const char* g_scm_desc; extern const char g_build_name[]; extern const char g_build_date[]; extern const char g_build_fullname[]; @@ -20,6 +17,5 @@ extern const char g_title_bar_format_idle[]; extern const char g_title_bar_format_running[]; extern const char g_shader_cache_version[]; extern const bool g_is_dev_build; -extern const char g_compiler_id[]; } // namespace Common diff --git a/src/common/settings.cpp b/src/common/settings.cpp index b41f4c75f5..d4f16f4853 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -154,19 +154,11 @@ bool IsGPULevelHigh() { values.current_gpu_accuracy == GpuAccuracy::High; } -bool IsDMALevelDefault() { - return values.dma_accuracy.GetValue() == DmaAccuracy::Default; -} - -bool IsDMALevelSafe() { - return values.dma_accuracy.GetValue() == DmaAccuracy::Safe; -} - bool IsFastmemEnabled() { if (values.cpu_debug_mode) { return static_cast(values.cpuopt_fastmem); } - if (values.cpu_accuracy.GetValue() == CpuAccuracy::Unsafe) { + if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Unsafe) { return static_cast(values.cpuopt_unsafe_host_mmu); } #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) diff --git a/src/common/settings.h b/src/common/settings.h index 8605445837..64545d10ff 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -37,14 +37,14 @@ struct ResolutionScalingInfo { if (value == 0) { return 0; } - return (std::max)((value * static_cast(up_scale)) >> static_cast(down_shift), 1); + return std::max((value * static_cast(up_scale)) >> static_cast(down_shift), 1); } u32 ScaleUp(u32 value) const { if (value == 0U) { return 0U; } - return (std::max)((value * up_scale) >> down_shift, 1U); + return std::max((value * up_scale) >> down_shift, 1U); } }; @@ -217,8 +217,7 @@ struct Values { true, true, &use_speed_limit}; - SwitchableSetting sync_core_speed{linkage, false, "sync_core_speed", Category::Core, - Specialization::Default}; + SwitchableSetting sync_core_speed{linkage, false, "sync_core_speed", Category::Core, Specialization::Default}; // Memory #ifdef HAS_NCE @@ -443,7 +442,7 @@ struct Values { SwitchableSetting dma_accuracy{linkage, DmaAccuracy::Default, DmaAccuracy::Default, - DmaAccuracy::Safe, + DmaAccuracy::Extreme, "dma_accuracy", Category::RendererAdvanced, Specialization::Default, @@ -552,8 +551,6 @@ struct Values { 3, #elif defined (ANDROID) 0, -#elif defined (__APPLE__) - 0, #else 2, #endif @@ -612,8 +609,8 @@ struct Values { false, true, &custom_rtc_enabled}; SwitchableSetting custom_rtc_offset{linkage, 0, - (std::numeric_limits::min)(), - (std::numeric_limits::max)(), + std::numeric_limits::min(), + std::numeric_limits::max(), "custom_rtc_offset", Category::System, Specialization::Countable, @@ -625,7 +622,7 @@ struct Values { linkage, 0, "rng_seed", Category::System, Specialization::Hex, true, true, &rng_seed_enabled}; Setting device_name{ - linkage, "Eden", "device_name", Category::System, Specialization::Default, true, true}; + linkage, "Eden", "device_name", Category::System, Specialization::Default, true, true}; Setting current_user{linkage, 0, "current_user", Category::System}; @@ -783,9 +780,6 @@ void UpdateGPUAccuracy(); bool IsGPULevelExtreme(); bool IsGPULevelHigh(); -bool IsDMALevelDefault(); -bool IsDMALevelSafe(); - bool IsFastmemEnabled(); void SetNceEnabled(bool is_64bit); bool IsNceEnabled(); diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 41133a7819..52b4a128f7 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -136,7 +136,7 @@ ENUM(ShaderBackend, Glsl, Glasm, SpirV); ENUM(GpuAccuracy, Normal, High, Extreme); -ENUM(DmaAccuracy, Default, Unsafe, Safe); +ENUM(DmaAccuracy, Default, Normal, High, Extreme); ENUM(CpuBackend, Dynarmic, Nce); diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h index ce7a3e91a6..0b18ca5ecc 100644 --- a/src/common/settings_setting.h +++ b/src/common/settings_setting.h @@ -223,7 +223,7 @@ public: if constexpr (std::is_enum_v) { return EnumMetadata::Index(); } else { - return (std::numeric_limits::max)(); + return std::numeric_limits::max(); } } @@ -237,14 +237,14 @@ public: [[nodiscard]] std::string MinVal() const override final { if constexpr (std::is_arithmetic_v && !ranged) { - return this->ToString((std::numeric_limits::min)()); + return this->ToString(std::numeric_limits::min()); } else { return this->ToString(minimum); } } [[nodiscard]] std::string MaxVal() const override final { if constexpr (std::is_arithmetic_v && !ranged) { - return this->ToString((std::numeric_limits::max)()); + return this->ToString(std::numeric_limits::max()); } else { return this->ToString(maximum); } diff --git a/src/common/slot_vector.h b/src/common/slot_vector.h index 8db4bba30b..34ff7de941 100644 --- a/src/common/slot_vector.h +++ b/src/common/slot_vector.h @@ -17,7 +17,7 @@ namespace Common { struct SlotId { - static constexpr u32 INVALID_INDEX = (std::numeric_limits::max)(); + static constexpr u32 INVALID_INDEX = std::numeric_limits::max(); constexpr auto operator<=>(const SlotId&) const noexcept = default; diff --git a/src/common/string_util.h b/src/common/string_util.h index 4358541b14..8ed87cdadc 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -7,7 +7,6 @@ #pragma once -#include #include #include #include diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 62a3115d5a..34cc1527bf 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -66,7 +66,7 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) { const auto scheduling_type = SCHED_OTHER; s32 max_prio = sched_get_priority_max(scheduling_type); s32 min_prio = sched_get_priority_min(scheduling_type); - u32 level = (std::max)(static_cast(new_priority) + 1, 4U); + u32 level = std::max(static_cast(new_priority) + 1, 4U); struct sched_param params; if (max_prio > min_prio) { @@ -101,7 +101,7 @@ void SetCurrentThreadName(const char* name) { #elif defined(__linux__) // Linux limits thread names to 15 characters and will outright reject any // attempt to set a longer name with ERANGE. - std::string truncated(name, (std::min)(strlen(name), static_cast(15))); + std::string truncated(name, std::min(strlen(name), static_cast(15))); if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) { errno = e; LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg()); diff --git a/src/common/tiny_mt.h b/src/common/tiny_mt.h index a757591c9b..5d5ebf158c 100644 --- a/src/common/tiny_mt.h +++ b/src/common/tiny_mt.h @@ -124,7 +124,7 @@ public: this->state.data[3] = ParamTmat; { - const int num_init_iterations = (std::max)(seed_count + 1, MinimumInitIterations) - 1; + const int num_init_iterations = std::max(seed_count + 1, MinimumInitIterations) - 1; GenerateInitialValuePlus(&this->state, 0, seed_count); diff --git a/src/common/uint128.h b/src/common/uint128.h index 56433096fe..f450a6db99 100644 --- a/src/common/uint128.h +++ b/src/common/uint128.h @@ -20,7 +20,7 @@ namespace Common { // This function multiplies 2 u64 values and divides it by a u64 value. [[nodiscard]] static inline u64 MultiplyAndDivide64(u64 a, u64 b, u64 d) { -#if defined(_MSC_VER) && !defined(__clang__) +#ifdef _MSC_VER u128 r{}; r[0] = _umul128(a, b, &r[1]); u64 remainder; @@ -41,7 +41,7 @@ namespace Common { // This function multiplies 2 u64 values and produces a u128 value; [[nodiscard]] static inline u128 Multiply64Into128(u64 a, u64 b) { u128 result; -#if defined(_MSC_VER) && !defined(__clang__) +#ifdef _MSC_VER result[0] = _umul128(a, b, &result[1]); #else unsigned __int128 tmp = a; @@ -65,7 +65,7 @@ namespace Common { #endif #else // This one is bit more inaccurate. - return MultiplyAndDivide64((std::numeric_limits::max)(), numerator, divisor); + return MultiplyAndDivide64(std::numeric_limits::max(), numerator, divisor); #endif } diff --git a/src/common/x64/cpu_wait.cpp b/src/common/x64/cpu_wait.cpp index b578d75ece..41d385f598 100644 --- a/src/common/x64/cpu_wait.cpp +++ b/src/common/x64/cpu_wait.cpp @@ -24,7 +24,7 @@ constexpr auto PauseCycles = 100'000U; } // Anonymous namespace -#if defined(_MSC_VER) && !defined(__clang__) +#ifdef _MSC_VER __forceinline static void TPAUSE() { static constexpr auto RequestC02State = 0U; _tpause(RequestC02State, FencedRDTSC() + PauseCycles); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4d9566a60f..eab506f194 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,6 +1,3 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later @@ -91,8 +88,6 @@ add_library(core STATIC file_sys/fssystem/fssystem_crypto_configuration.h file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.cpp file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h - file_sys/fssystem/fssystem_hierarchical_sha3_storage.cpp - file_sys/fssystem/fssystem_hierarchical_sha3_storage.h file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp file_sys/fssystem/fssystem_hierarchical_sha256_storage.h file_sys/fssystem/fssystem_indirect_storage.cpp @@ -1157,7 +1152,7 @@ add_library(core STATIC if (ENABLE_WIFI_SCAN) # find_package(libiw REQUIRED) - target_compile_definitions(core PRIVATE ENABLE_WIFI_SCAN) + target_compile_definitions(core PRIVATE -DENABLE_WIFI_SCAN) target_link_libraries(core PRIVATE iw) endif() @@ -1186,7 +1181,6 @@ else() -Wno-cast-function-type $<$:-fsized-deallocation> - $<$:-Wno-cast-function-type-mismatch> ) endif() @@ -1199,13 +1193,13 @@ else() target_link_libraries(core PUBLIC Boost::headers) endif() -target_link_libraries(core PRIVATE fmt::fmt nlohmann_json::nlohmann_json RenderDoc::API MbedTLS::mbedcrypto MbedTLS::mbedtls) +target_link_libraries(core PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API) if (MINGW) target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) endif() if (ENABLE_WEB_SERVICE) - target_compile_definitions(core PUBLIC ENABLE_WEB_SERVICE) + target_compile_definitions(core PUBLIC -DENABLE_WEB_SERVICE) target_link_libraries(core PUBLIC web_service) endif() diff --git a/src/core/arm/debug.cpp b/src/core/arm/debug.cpp index 20f1ea00df..854509463b 100644 --- a/src/core/arm/debug.cpp +++ b/src/core/arm/debug.cpp @@ -283,9 +283,9 @@ Loader::AppLoader::Modules FindModules(Kernel::KProcess* process) { // Ignore leading directories. char* path_pointer = module_path.path.data(); char* path_end = - path_pointer + (std::min)(PathLengthMax, module_path.path_length); + path_pointer + std::min(PathLengthMax, module_path.path_length); - for (s32 i = 0; i < (std::min)(PathLengthMax, module_path.path_length) && + for (s32 i = 0; i < std::min(PathLengthMax, module_path.path_length) && module_path.path[i] != '\0'; i++) { if (module_path.path[i] == '/' || module_path.path[i] == '\\') { diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index e6e9fc45be..9d26db51f7 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -3,47 +3,9 @@ #ifdef __linux__ -#include "common/signal_chain.h" - +//#include "common/signal_chain.h" #include "core/arm/dynarmic/arm_dynarmic.h" -#include "core/hle/kernel/k_process.h" -#include "core/memory.h" - -namespace Core { - -namespace { - -thread_local Core::Memory::Memory* g_current_memory{}; -std::once_flag g_registered{}; -struct sigaction g_old_segv {}; - -void HandleSigSegv(int sig, siginfo_t* info, void* ctx) { - if (g_current_memory && g_current_memory->InvalidateSeparateHeap(info->si_addr)) { - return; - } - - return g_old_segv.sa_sigaction(sig, info, ctx); -} - -} // namespace - -ScopedJitExecution::ScopedJitExecution(Kernel::KProcess* process) { - g_current_memory = std::addressof(process->GetMemory()); -} - -ScopedJitExecution::~ScopedJitExecution() { - g_current_memory = nullptr; -} - -void ScopedJitExecution::RegisterHandler() { - std::call_once(g_registered, [] { - struct sigaction sa {}; - sa.sa_sigaction = &HandleSigSegv; - sa.sa_flags = SA_SIGINFO | SA_ONSTACK; - Common::SigAction(SIGSEGV, std::addressof(sa), std::addressof(g_old_segv)); - }); -} - -} // namespace Core +//#include "core/hle/kernel/k_process.h" +//#include "core/memory.h" #endif diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 53dd188151..eef7c31160 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -26,24 +26,4 @@ constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) { return static_cast(hr); } -#ifdef __linux__ - -class ScopedJitExecution { -public: - explicit ScopedJitExecution(Kernel::KProcess* process); - ~ScopedJitExecution(); - static void RegisterHandler(); -}; - -#else - -class ScopedJitExecution { -public: - explicit ScopedJitExecution(Kernel::KProcess* process) {} - ~ScopedJitExecution() {} - static void RegisterHandler() {} -}; - -#endif - } // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index d2035d0fe0..7123497682 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -305,7 +305,7 @@ std::shared_ptr ArmDynarmic32::MakeJit(Common::PageTable* pa config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; } - // Paranoia mode for debugging optimizations + // Paranoid mode for debugging optimizations if (Settings::values.cpu_accuracy.GetValue() == Settings::CpuAccuracy::Paranoid) { config.unsafe_optimizations = false; config.optimizations = Dynarmic::no_optimizations; @@ -343,15 +343,11 @@ bool ArmDynarmic32::IsInThumbMode() const { } HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Run()); } HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Step()); } @@ -393,7 +389,6 @@ ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProc m_cp15(std::make_shared(*this)), m_core_index{core_index} { auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl(); m_jit = MakeJit(&page_table_impl); - ScopedJitExecution::RegisterHandler(); } ArmDynarmic32::~ArmDynarmic32() = default; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 438b7b691c..2745aeb862 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -374,15 +374,11 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa } HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Run()); } HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Step()); } @@ -422,7 +418,6 @@ ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProc auto& page_table = process->GetPageTable().GetBasePageTable(); auto& page_table_impl = page_table.GetImpl(); m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth()); - ScopedJitExecution::RegisterHandler(); } ArmDynarmic64::~ArmDynarmic64() = default; diff --git a/src/core/arm/dynarmic/dynarmic_cp15.cpp b/src/core/arm/dynarmic/dynarmic_cp15.cpp index 0d5e5912ae..c663adda19 100644 --- a/src/core/arm/dynarmic/dynarmic_cp15.cpp +++ b/src/core/arm/dynarmic/dynarmic_cp15.cpp @@ -58,8 +58,6 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1 _mm_lfence(); #elif defined(ARCHITECTURE_x86_64) asm volatile("mfence\n\tlfence\n\t" : : : "memory"); -#elif defined(_MSC_VER) && defined(ARCHITECTURE_arm64) - _Memory_barrier(); #elif defined(ARCHITECTURE_arm64) asm volatile("dsb sy\n\t" : : : "memory"); #else @@ -77,8 +75,6 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1 _mm_mfence(); #elif defined(ARCHITECTURE_x86_64) asm volatile("mfence\n\t" : : : "memory"); -#elif defined(_MSC_VER) && defined(ARCHITECTURE_arm64) - _Memory_barrier(); #elif defined(ARCHITECTURE_arm64) asm volatile("dmb sy\n\t" : : : "memory"); #else diff --git a/src/core/arm/nce/interpreter_visitor.h b/src/core/arm/nce/interpreter_visitor.h index 9dfbdb2fe9..f90d876abb 100644 --- a/src/core/arm/nce/interpreter_visitor.h +++ b/src/core/arm/nce/interpreter_visitor.h @@ -4,14 +4,9 @@ #pragma once -#include #include #include -#include -#include "core/hle/kernel/k_thread.h" -#include "core/memory.h" -#include "common/logging/log.h" #include "core/arm/nce/visitor_base.h" namespace Core { diff --git a/src/core/arm/nce/patcher.cpp b/src/core/arm/nce/patcher.cpp index 9321258ae9..b8387ce7cb 100644 --- a/src/core/arm/nce/patcher.cpp +++ b/src/core/arm/nce/patcher.cpp @@ -11,8 +11,6 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/svc.h" -#include "core/memory.h" -#include "core/hle/kernel/k_thread.h" namespace Core::NCE { diff --git a/src/core/core.cpp b/src/core/core.cpp index 7315f35e0c..c2852e66f0 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -185,7 +185,7 @@ struct System::Impl { Service::PSC::Time::LocationName name{}; auto new_name = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue()); - std::memcpy(name.data(), new_name.data(), (std::min)(name.size(), new_name.size())); + std::memcpy(name.data(), new_name.data(), std::min(name.size(), new_name.size())); timezone_service->SetDeviceLocationName(name); diff --git a/src/core/crypto/aes_util.h b/src/core/crypto/aes_util.h index 0a2a4e464c..c2fd587a73 100644 --- a/src/core/crypto/aes_util.h +++ b/src/core/crypto/aes_util.h @@ -16,7 +16,7 @@ struct CipherContext; enum class Mode { CTR = 11, ECB = 2, - XTS = 74, + XTS = 70, }; enum class Op { diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 6d0b32ba70..74b1ca04b1 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -34,10 +31,6 @@ #include "core/hle/service/filesystem/filesystem.h" #include "core/loader/loader.h" -#ifndef MBEDTLS_CMAC_C -#error mbedtls was compiled without CMAC support. Check your USE flags (Gentoo) or contact your package maintainer. -#endif - namespace Core::Crypto { namespace { @@ -539,7 +532,7 @@ static std::array MGF1(const std::array& seed) { while (out.size() < target_size) { out.resize(out.size() + 0x20); seed_exp[in_size + 3] = static_cast(i); - mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0); + mbedtls_sha256_ret(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0); ++i; } diff --git a/src/core/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp index 905b8139ef..4b45e72c43 100644 --- a/src/core/crypto/partition_data_manager.cpp +++ b/src/core/crypto/partition_data_manager.cpp @@ -178,7 +178,7 @@ std::array FindKeyFromHex(const std::vector& binary, std::array temp{}; for (size_t i = 0; i < binary.size() - key_size; ++i) { - mbedtls_sha256(binary.data() + i, key_size, temp.data(), 0); + mbedtls_sha256_ret(binary.data() + i, key_size, temp.data(), 0); if (temp != hash) continue; @@ -206,7 +206,7 @@ static std::array FindEncryptedMasterKeyFromHex(const std::vector< AESCipher cipher(key, Mode::ECB); for (size_t i = 0; i < binary.size() - 0x10; ++i) { cipher.Transcode(binary.data() + i, dec_temp.size(), dec_temp.data(), Op::Decrypt); - mbedtls_sha256(dec_temp.data(), dec_temp.size(), temp.data(), 0); + mbedtls_sha256_ret(dec_temp.data(), dec_temp.size(), temp.data(), 0); for (size_t k = 0; k < out.size(); ++k) { if (temp == master_key_hashes[k]) { diff --git a/src/core/crypto/xts_encryption_layer.cpp b/src/core/crypto/xts_encryption_layer.cpp index 34e58463de..b60303412b 100644 --- a/src/core/crypto/xts_encryption_layer.cpp +++ b/src/core/crypto/xts_encryption_layer.cpp @@ -34,8 +34,8 @@ std::size_t XTSEncryptionLayer::Read(u8* data, std::size_t length, std::size_t o buffer.resize(XTS_SECTOR_SIZE); cipher.XTSTranscode(buffer.data(), buffer.size(), buffer.data(), offset / XTS_SECTOR_SIZE, XTS_SECTOR_SIZE, Op::Decrypt); - std::memcpy(data, buffer.data(), (std::min)(buffer.size(), length)); - return (std::min)(buffer.size(), length); + std::memcpy(data, buffer.data(), std::min(buffer.size(), length)); + return std::min(buffer.size(), length); } // offset does not fall on block boundary (0x4000) diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index 460e0d19b4..7fe22fdce2 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp @@ -7,7 +7,7 @@ #include #include -#if BOOST_VERSION > 108400 && (!defined(_WINDOWS) && !defined(ANDROID)) || defined(YUZU_BOOST_v1) +#if BOOST_VERSION > 108300 && (!defined(_WINDOWS) && !defined(ANDROID)) || defined(YUZU_BOOST_v1) #define USE_BOOST_v1 #endif diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index 5c3c045b3c..fcb5787147 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp @@ -664,7 +664,7 @@ void GDBStub::HandleRcmd(const std::vector& command) { if (svc_mem_info.state != Kernel::Svc::MemoryState::Inaccessible || svc_mem_info.base_address + svc_mem_info.size - 1 != - (std::numeric_limits::max)()) { + std::numeric_limits::max()) { const char* state = GetMemoryStateName(svc_mem_info.state); const char* perm = GetMemoryPermissionString(svc_mem_info); const char l = True(svc_mem_info.attribute & MemoryAttribute::Locked) ? 'L' : '-'; @@ -710,7 +710,7 @@ std::vector::const_iterator GDBStub::CommandEnd() const { const auto end{std::find(current_command.begin(), current_command.end(), GDB_STUB_END)}; // Require the checksum to be present - return (std::min)(end + 2, current_command.end()); + return std::min(end + 2, current_command.end()); } std::optional GDBStub::DetachCommand() { diff --git a/src/core/debugger/gdbstub_arch.cpp b/src/core/debugger/gdbstub_arch.cpp index ee7108376a..452f565bec 100644 --- a/src/core/debugger/gdbstub_arch.cpp +++ b/src/core/debugger/gdbstub_arch.cpp @@ -12,7 +12,7 @@ static T HexToValue(std::string_view hex) { static_assert(std::is_trivially_copyable_v); T value{}; const auto mem{Common::HexStringToVector(hex, false)}; - std::memcpy(&value, mem.data(), (std::min)(mem.size(), sizeof(T))); + std::memcpy(&value, mem.data(), std::min(mem.size(), sizeof(T))); return value; } diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc index 52dff5df9a..f104d495bb 100644 --- a/src/core/device_memory_manager.inc +++ b/src/core/device_memory_manager.inc @@ -388,7 +388,7 @@ void DeviceMemoryManager::WalkBlock(DAddr addr, std::size_t size, auto o while (remaining_size) { const size_t next_pages = static_cast(continuity_tracker[page_index]); const std::size_t copy_amount = - (std::min)((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size); + std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size); const auto current_vaddr = static_cast((page_index << Memory::YUZU_PAGEBITS) + page_offset); SCOPE_EXIT{ diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index b961cdb096..6652523589 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -34,9 +34,12 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca) } reader = std::make_shared(); - if (Result rc = reader->Initialize(file, GetCryptoConfiguration(), GetNcaCompressionConfiguration()); R_FAILED(rc)) { + 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()); + LOG_ERROR(Loader, "File reader errored out during header read: {:#x}", + rc.GetInnerValue()); } status = Loader::ResultStatus::ErrorBadNCAHeader; return; @@ -81,8 +84,10 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca) std::vector filesystems(fs_count); 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()); + const Result rc = fs.OpenStorage(&filesystems[i], &header_reader, i); + if (R_FAILED(rc)) { + LOG_ERROR(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/fs_path_utility.h b/src/core/file_sys/fs_path_utility.h index 3af23b0bba..cdfd8c7729 100644 --- a/src/core/file_sys/fs_path_utility.h +++ b/src/core/file_sys/fs_path_utility.h @@ -683,7 +683,7 @@ public: const auto max_mount_len = out_mount_name_buffer_size == 0 ? MountNameLengthMax + 1 - : (std::min)(MountNameLengthMax + 1, out_mount_name_buffer_size); + : std::min(MountNameLengthMax + 1, out_mount_name_buffer_size); // Parse the path until we see a drive separator size_t mount_len = 0; diff --git a/src/core/file_sys/fsa/fs_i_directory.h b/src/core/file_sys/fsa/fs_i_directory.h index a4adcd2beb..c8e895eab0 100644 --- a/src/core/file_sys/fsa/fs_i_directory.h +++ b/src/core/file_sys/fsa/fs_i_directory.h @@ -48,7 +48,7 @@ public: private: Result DoRead(s64* out_count, DirectoryEntry* out_entries, s64 max_entries) { const u64 actual_entries = - (std::min)(static_cast(max_entries), entries.size() - next_entry_index); + std::min(static_cast(max_entries), entries.size() - next_entry_index); const auto* begin = reinterpret_cast(entries.data() + next_entry_index); const auto* end = reinterpret_cast(entries.data() + next_entry_index + actual_entries); const auto range_size = static_cast(std::distance(begin, end)); diff --git a/src/core/file_sys/fsa/fs_i_file.h b/src/core/file_sys/fsa/fs_i_file.h index 99468ef0e2..1188ae8ca7 100644 --- a/src/core/file_sys/fsa/fs_i_file.h +++ b/src/core/file_sys/fsa/fs_i_file.h @@ -93,7 +93,7 @@ protected: R_TRY(this->DoGetSize(std::addressof(file_size))); R_UNLESS(offset <= file_size, ResultOutOfRange); - *out = static_cast((std::min)(file_size - offset, static_cast(size))); + *out = static_cast(std::min(file_size - offset, static_cast(size))); R_SUCCEED(); } diff --git a/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp b/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp index c9fb5f64d6..bc1cddbb0c 100644 --- a/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp +++ b/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp @@ -213,7 +213,7 @@ size_t AesCtrCounterExtendedStorage::Read(u8* buffer, size_t size, size_t offset // Determine how much is left. const auto remaining_size = end_offset - cur_offset; - const auto cur_size = static_cast((std::min)(remaining_size, data_size)); + const auto cur_size = static_cast(std::min(remaining_size, data_size)); ASSERT(cur_size <= size); // If necessary, perform decryption. diff --git a/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.cpp b/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.cpp index c18fde18f4..b65aca18d9 100644 --- a/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.cpp +++ b/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.cpp @@ -94,7 +94,7 @@ size_t AesCtrStorage::Write(const u8* buffer, size_t size, size_t offset) { while (remaining > 0) { // Determine data we're writing and where. const size_t write_size = - use_work_buffer ? (std::min)(pooled_buffer.GetSize(), remaining) : remaining; + use_work_buffer ? std::min(pooled_buffer.GetSize(), remaining) : remaining; void* write_buf; if (use_work_buffer) { diff --git a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp index 5ef2544dfb..efc5aa0b12 100644 --- a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp +++ b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp @@ -65,7 +65,7 @@ size_t AesXtsStorage::Read(u8* buffer, size_t size, size_t offset) const { // Determine the size of the pre-data read. const size_t skip_size = static_cast(offset - Common::AlignDown(offset, m_block_size)); - const size_t data_size = (std::min)(size, m_block_size - skip_size); + const size_t data_size = std::min(size, m_block_size - skip_size); // Decrypt into a pooled buffer. { @@ -84,14 +84,14 @@ size_t AesXtsStorage::Read(u8* buffer, size_t size, size_t offset) const { AddCounter(ctr.data(), IvSize, 1); processed_size += data_size; - ASSERT(processed_size == (std::min)(size, m_block_size - skip_size)); + ASSERT(processed_size == std::min(size, m_block_size - skip_size)); } // Decrypt aligned chunks. char* cur = reinterpret_cast(buffer) + processed_size; size_t remaining = size - processed_size; while (remaining > 0) { - const size_t cur_size = (std::min)(m_block_size, remaining); + const size_t cur_size = std::min(m_block_size, remaining); m_cipher->SetIV(ctr); m_cipher->Transcode(cur, cur_size, cur, Core::Crypto::Op::Decrypt); diff --git a/src/core/file_sys/fssystem/fssystem_alignment_matching_storage_impl.cpp b/src/core/file_sys/fssystem/fssystem_alignment_matching_storage_impl.cpp index 08b77d790a..641c888aed 100644 --- a/src/core/file_sys/fssystem/fssystem_alignment_matching_storage_impl.cpp +++ b/src/core/file_sys/fssystem/fssystem_alignment_matching_storage_impl.cpp @@ -104,7 +104,7 @@ size_t AlignmentMatchingStorageImpl::Read(VirtualFile base_storage, char* work_b while (remaining_tail_size > 0) { const auto aligned_tail_offset = Common::AlignDown(tail_offset, data_alignment); const auto cur_size = - (std::min)(static_cast(aligned_tail_offset + data_alignment - tail_offset), + std::min(static_cast(aligned_tail_offset + data_alignment - tail_offset), remaining_tail_size); base_storage->Read(reinterpret_cast(work_buf), data_alignment, aligned_tail_offset); @@ -186,7 +186,7 @@ size_t AlignmentMatchingStorageImpl::Write(VirtualFile base_storage, char* work_ const auto aligned_tail_offset = Common::AlignDown(tail_offset, data_alignment); const auto cur_size = - (std::min)(static_cast(aligned_tail_offset + data_alignment - tail_offset), + std::min(static_cast(aligned_tail_offset + data_alignment - tail_offset), remaining_tail_size); base_storage->Read(reinterpret_cast(work_buf), data_alignment, aligned_tail_offset); diff --git a/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp b/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp index f58b154968..af8541009e 100644 --- a/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp +++ b/src/core/file_sys/fssystem/fssystem_bucket_tree.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 @@ -236,7 +233,6 @@ Result BucketTree::Initialize(VirtualFile node_storage, VirtualFile entry_storag void BucketTree::Initialize(size_t node_size, s64 end_offset) { ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax); ASSERT(Common::IsPowerOfTwo(node_size)); - ASSERT(end_offset > 0); ASSERT(!this->IsInitialized()); diff --git a/src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp b/src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp index 0a9f28975b..a4f0cde281 100644 --- a/src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp +++ b/src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp @@ -29,12 +29,12 @@ void GenerateKey(void* dst_key, size_t dst_key_size, const void* src_key, size_t key_type == static_cast(KeyType::NcaHeaderKey2)) { const s32 key_index = static_cast(KeyType::NcaHeaderKey2) == key_type; const auto key = instance.GetKey(Core::Crypto::S256KeyType::Header); - std::memcpy(dst_key, key.data() + key_index * 0x10, (std::min)(dst_key_size, key.size() / 2)); + std::memcpy(dst_key, key.data() + key_index * 0x10, std::min(dst_key_size, key.size() / 2)); return; } const s32 key_generation = - (std::max)(key_type / NcaCryptoConfiguration::KeyAreaEncryptionKeyIndexCount, 1) - 1; + std::max(key_type / NcaCryptoConfiguration::KeyAreaEncryptionKeyIndexCount, 1) - 1; const s32 key_index = key_type % NcaCryptoConfiguration::KeyAreaEncryptionKeyIndexCount; Core::Crypto::AESCipher cipher( diff --git a/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp b/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp index e8669a4a7d..a68fd973c9 100644 --- a/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp +++ b/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp @@ -5,10 +5,23 @@ #include "common/scope_exit.h" #include "core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h" -#include - namespace FileSys { +namespace { + +s32 Log2(s32 value) { + ASSERT(value > 0); + ASSERT(Common::IsPowerOfTwo(value)); + + s32 log = 0; + while ((value >>= 1) > 0) { + ++log; + } + return log; +} + +} // namespace + Result HierarchicalSha256Storage::Initialize(VirtualFile* base_storages, s32 layer_count, size_t htbs, void* hash_buf, size_t hash_buf_size) { // Validate preconditions. @@ -18,8 +31,7 @@ Result HierarchicalSha256Storage::Initialize(VirtualFile* base_storages, s32 lay // Set size tracking members. m_hash_target_block_size = static_cast(htbs); - m_log_size_ratio = - static_cast(std::log2(static_cast(m_hash_target_block_size) / HashSize)); + m_log_size_ratio = Log2(m_hash_target_block_size / HashSize); // Get the base storage size. m_base_storage_size = base_storages[2]->GetSize(); diff --git a/src/core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.cpp b/src/core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.cpp deleted file mode 100644 index d58f2ee9be..0000000000 --- a/src/core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "common/alignment.h" -#include "common/scope_exit.h" -#include "core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.h" - -#include - -namespace FileSys { - -Result HierarchicalSha3Storage::Initialize(VirtualFile* base_storages, s32 layer_count, size_t htbs, - void* hash_buf, size_t hash_buf_size) { - ASSERT(layer_count == LayerCount); - ASSERT(Common::IsPowerOfTwo(htbs)); - ASSERT(hash_buf != nullptr); - - m_hash_target_block_size = static_cast(htbs); - m_log_size_ratio = - static_cast(std::log2(static_cast(m_hash_target_block_size) / HashSize)); - - m_base_storage_size = base_storages[2]->GetSize(); - { - auto size_guard = SCOPE_GUARD { - m_base_storage_size = 0; - }; - R_UNLESS(m_base_storage_size <= static_cast(HashSize) - << m_log_size_ratio << m_log_size_ratio, - ResultHierarchicalSha256BaseStorageTooLarge); - size_guard.Cancel(); - } - - m_base_storage = base_storages[2]; - m_hash_buffer = static_cast(hash_buf); - m_hash_buffer_size = hash_buf_size; - - std::array master_hash{}; - base_storages[0]->ReadObject(std::addressof(master_hash)); - - s64 hash_storage_size = base_storages[1]->GetSize(); - ASSERT(Common::IsAligned(hash_storage_size, HashSize)); - ASSERT(hash_storage_size <= m_hash_target_block_size); - ASSERT(hash_storage_size <= static_cast(m_hash_buffer_size)); - - base_storages[1]->Read(reinterpret_cast(m_hash_buffer), - static_cast(hash_storage_size), 0); - R_SUCCEED(); -} - -size_t HierarchicalSha3Storage::Read(u8* buffer, size_t size, size_t offset) const { - if (size == 0) - return size; - ASSERT(buffer != nullptr); - return m_base_storage->Read(buffer, size, offset); -} - -} // namespace FileSys diff --git a/src/core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.h b/src/core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.h deleted file mode 100644 index 2db7bb28e1..0000000000 --- a/src/core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include - -#include "core/file_sys/errors.h" -#include "core/file_sys/fssystem/fs_i_storage.h" -#include "core/file_sys/vfs/vfs.h" - -namespace FileSys { - -class HierarchicalSha3Storage : public IReadOnlyStorage { - YUZU_NON_COPYABLE(HierarchicalSha3Storage); - YUZU_NON_MOVEABLE(HierarchicalSha3Storage); - -public: - static constexpr s32 LayerCount = 3; - static constexpr size_t HashSize = 256 / 8; // SHA3-256 - -public: - HierarchicalSha3Storage() : m_mutex() {} - - Result Initialize(VirtualFile* base_storages, s32 layer_count, size_t htbs, void* hash_buf, - size_t hash_buf_size); - - virtual size_t GetSize() const override { - return m_base_storage->GetSize(); - } - - virtual size_t Read(u8* buffer, size_t length, size_t offset) const override; - -private: - VirtualFile m_base_storage; - s64 m_base_storage_size{}; - char* m_hash_buffer{}; - size_t m_hash_buffer_size{}; - s32 m_hash_target_block_size{}; - s32 m_log_size_ratio{}; - std::mutex m_mutex; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp b/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp index c1bad3ec36..046571e9ef 100644 --- a/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp +++ b/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp @@ -4,18 +4,23 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/alignment.h" #include "core/file_sys/fssystem/fssystem_integrity_verification_storage.h" +#include "common/alignment.h" namespace FileSys { -constexpr inline u32 ILog2(u32 val) { +constexpr inline u32 ILog2(u32 val) +{ ASSERT(val > 0); return static_cast((sizeof(u32) * 8) - 1 - std::countl_zero(val)); } -void IntegrityVerificationStorage::Initialize(VirtualFile hs, VirtualFile ds, s64 verif_block_size, - s64 upper_layer_verif_block_size, bool is_real_data) { +void IntegrityVerificationStorage::Initialize(VirtualFile hs, + VirtualFile ds, + s64 verif_block_size, + s64 upper_layer_verif_block_size, + bool is_real_data) +{ // Validate preconditions. ASSERT(verif_block_size >= HashSize); @@ -29,28 +34,34 @@ void IntegrityVerificationStorage::Initialize(VirtualFile hs, VirtualFile ds, s6 ASSERT(m_verification_block_size == 1ll << m_verification_block_order); // Set upper layer block sizes. - upper_layer_verif_block_size = (std::max)(upper_layer_verif_block_size, HashSize); + upper_layer_verif_block_size = std::max(upper_layer_verif_block_size, HashSize); m_upper_layer_verification_block_size = upper_layer_verif_block_size; m_upper_layer_verification_block_order = ILog2(static_cast(upper_layer_verif_block_size)); ASSERT(m_upper_layer_verification_block_size == 1ll << m_upper_layer_verification_block_order); // Validate sizes. - { + if (m_data_storage != nullptr) { s64 hash_size = m_hash_storage->GetSize(); s64 data_size = m_data_storage->GetSize(); ASSERT(((hash_size / HashSize) * m_verification_block_size) >= data_size); + } else { + LOG_ERROR(Loader, + "Failed to initialize integrity verification store. Game, update, or DLC may not " + "work."); } // Set data. m_is_real_data = is_real_data; } -void IntegrityVerificationStorage::Finalize() { +void IntegrityVerificationStorage::Finalize() +{ m_hash_storage = VirtualFile(); m_data_storage = VirtualFile(); } -size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset) const { +size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset) const +{ // Succeed if zero size. if (size == 0) { return size; @@ -59,7 +70,13 @@ size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset // Validate arguments. ASSERT(buffer != nullptr); - // Validate the offset. + if (m_data_storage == nullptr) { + LOG_ERROR(Loader, + "Integrity verification store failed read operation. Game, update or DLC may not " + "work."); + return 0; + } + s64 data_size = m_data_storage->GetSize(); ASSERT(offset <= static_cast(data_size)); @@ -87,7 +104,8 @@ size_t IntegrityVerificationStorage::Read(u8* buffer, size_t size, size_t offset return m_data_storage->Read(buffer, read_size, offset); } -size_t IntegrityVerificationStorage::GetSize() const { +size_t IntegrityVerificationStorage::GetSize() const +{ return m_data_storage->GetSize(); } 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 25036b02c1..ab5a7984e3 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 @@ -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 @@ -17,7 +14,6 @@ #include "core/file_sys/fssystem/fssystem_nca_file_system_driver.h" #include "core/file_sys/fssystem/fssystem_sparse_storage.h" #include "core/file_sys/fssystem/fssystem_switch_storage.h" -#include "core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.h" #include "core/file_sys/vfs/vfs_offset.h" #include "core/file_sys/vfs/vfs_vector.h" @@ -303,24 +299,18 @@ Result NcaFileSystemDriver::CreateStorageByRawStorage(VirtualFile* out, // Process hash/integrity layer. switch (header_reader->GetHashType()) { case NcaFsHeader::HashType::HierarchicalSha256Hash: - R_TRY(CreateSha256Storage(&storage, std::move(storage), - header_reader->GetHashData().hierarchical_sha256_data)); + R_TRY(this->CreateSha256Storage(std::addressof(storage), std::move(storage), + header_reader->GetHashData().hierarchical_sha256_data)); break; case NcaFsHeader::HashType::HierarchicalIntegrityHash: - R_TRY(CreateIntegrityVerificationStorage(&storage, std::move(storage), - header_reader->GetHashData().integrity_meta_info)); - break; - case NcaFsHeader::HashType::HierarchicalSha3256Hash: - R_TRY(CreateSha3Storage(&storage, std::move(storage), - header_reader->GetHashData().hierarchical_sha256_data)); + R_TRY(this->CreateIntegrityVerificationStorage( + std::addressof(storage), std::move(storage), + header_reader->GetHashData().integrity_meta_info)); break; default: - LOG_ERROR(Loader, "Unhandled Fs HashType enum={}", - static_cast(header_reader->GetHashType())); R_THROW(ResultInvalidNcaFsHeaderHashType); } - // Process compression layer. if (header_reader->ExistsCompressionLayer()) { R_TRY(this->CreateCompressedStorage( @@ -689,7 +679,6 @@ Result NcaFileSystemDriver::CreateSparseStorageMetaStorageWithVerification( // Create the verification storage. VirtualFile integrity_storage; - Result rc = this->CreateIntegrityVerificationStorageForMeta( std::addressof(integrity_storage), out_layer_info_storage, std::move(decrypted_storage), meta_offset, meta_data_hash_data_info); @@ -745,26 +734,8 @@ Result NcaFileSystemDriver::CreateSparseStorageWithVerification( NcaHeader::CtrBlockSize))); // Check the meta data hash type. - if (meta_data_hash_type != NcaFsHeader::MetaDataHashType::HierarchicalIntegrity) { - LOG_ERROR(Loader, "Sparse meta hash type {} not supported for verification; mounting sparse data WITHOUT verification (temporary).", static_cast(meta_data_hash_type)); - - R_TRY(this->CreateBodySubStorage(std::addressof(body_substorage), - sparse_info.physical_offset, - sparse_info.GetPhysicalSize())); - - // Create sparse core directly (no meta verification) - std::shared_ptr sparse_storage_fallback; - R_TRY(this->CreateSparseStorageCore(std::addressof(sparse_storage_fallback), - body_substorage, sparse_info.GetPhysicalSize(), - /*meta_storage*/ body_substorage, // dummy; not used - sparse_info, false)); - - if (out_sparse_storage) - *out_sparse_storage = sparse_storage_fallback; - *out_fs_data_offset = fs_offset; - *out = std::move(sparse_storage_fallback); - R_SUCCEED(); - } + R_UNLESS(meta_data_hash_type == NcaFsHeader::MetaDataHashType::HierarchicalIntegrity, + ResultRomNcaInvalidSparseMetaDataHashType); // Create the meta storage. VirtualFile meta_storage; @@ -1049,8 +1020,8 @@ 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(patch_info.HasAesCtrExTable()); + ASSERT(patch_info.HasIndirectTable()); ASSERT(Common::IsAligned(patch_info.aes_ctr_ex_size, NcaHeader::XtsBlockSize)); // Validate patch info extents. @@ -1122,56 +1093,6 @@ Result NcaFileSystemDriver::CreatePatchMetaStorage( R_SUCCEED(); } -Result NcaFileSystemDriver::CreateSha3Storage( - VirtualFile* out, VirtualFile base_storage, - const NcaFsHeader::HashData::HierarchicalSha256Data& hash_data) { - ASSERT(out != nullptr); - ASSERT(base_storage != nullptr); - - using VerificationStorage = HierarchicalSha3Storage; - - R_UNLESS(Common::IsPowerOfTwo(hash_data.hash_block_size), - ResultInvalidHierarchicalSha256BlockSize); - R_UNLESS(hash_data.hash_layer_count == VerificationStorage::LayerCount - 1, - ResultInvalidHierarchicalSha256LayerCount); - - const auto& hash_region = hash_data.hash_layer_region[0]; - const auto& data_region = hash_data.hash_layer_region[1]; - - constexpr s32 CacheBlockCount = 2; - const auto hash_buffer_size = static_cast(hash_region.size); - const auto cache_buffer_size = CacheBlockCount * hash_data.hash_block_size; - const auto total_buffer_size = hash_buffer_size + cache_buffer_size; - - auto buffer_hold_storage = std::make_shared( - std::move(base_storage), total_buffer_size); - R_UNLESS(buffer_hold_storage != nullptr, ResultAllocationMemoryFailedAllocateShared); - R_UNLESS(buffer_hold_storage->IsValid(), ResultAllocationMemoryFailedInNcaFileSystemDriverI); - - s64 base_size = buffer_hold_storage->GetSize(); - R_UNLESS(hash_region.offset + hash_region.size <= base_size, ResultNcaBaseStorageOutOfRangeC); - R_UNLESS(data_region.offset + data_region.size <= base_size, ResultNcaBaseStorageOutOfRangeC); - - auto master_hash_storage = - std::make_shared>(hash_data.fs_data_master_hash.value); - - auto verification_storage = std::make_shared(); - R_UNLESS(verification_storage != nullptr, ResultAllocationMemoryFailedAllocateShared); - - std::array layer_storages{ - std::make_shared(master_hash_storage, sizeof(Hash), 0), - std::make_shared(buffer_hold_storage, hash_region.size, hash_region.offset), - std::make_shared(buffer_hold_storage, data_region.size, data_region.offset), - }; - - R_TRY(verification_storage->Initialize(layer_storages.data(), VerificationStorage::LayerCount, - hash_data.hash_block_size, - buffer_hold_storage->GetBuffer(), hash_buffer_size)); - - *out = std::move(verification_storage); - R_SUCCEED(); -} - Result NcaFileSystemDriver::CreateSha256Storage( VirtualFile* out, VirtualFile base_storage, const NcaFsHeader::HashData::HierarchicalSha256Data& hash_data) { @@ -1239,7 +1160,6 @@ Result NcaFileSystemDriver::CreateSha256Storage( Result NcaFileSystemDriver::CreateIntegrityVerificationStorage( VirtualFile* out, VirtualFile base_storage, const NcaFsHeader::HashData::IntegrityMetaInfo& meta_info) { - R_RETURN(this->CreateIntegrityVerificationStorageImpl( out, base_storage, meta_info, 0, IntegrityDataCacheCount, IntegrityHashCacheCount, HierarchicalIntegrityVerificationStorage::GetDefaultDataCacheBufferLevel( @@ -1289,7 +1209,7 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl( VirtualFile* out, VirtualFile base_storage, const NcaFsHeader::HashData::IntegrityMetaInfo& meta_info, s64 layer_info_offset, int max_data_cache_entries, int max_hash_cache_entries, s8 buffer_level) { - // Preconditions + // Validate preconditions. ASSERT(out != nullptr); ASSERT(base_storage != nullptr); ASSERT(layer_info_offset >= 0); @@ -1300,8 +1220,7 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl( // Validate the meta info. HierarchicalIntegrityVerificationInformation level_hash_info; - std::memcpy(std::addressof(level_hash_info), - std::addressof(meta_info.level_hash_info), + std::memcpy(std::addressof(level_hash_info), std::addressof(meta_info.level_hash_info), sizeof(level_hash_info)); R_UNLESS(IntegrityMinLayerCount <= level_hash_info.max_layers, @@ -1319,9 +1238,8 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl( R_UNLESS(layer_info_offset + layer_info.offset + layer_info.size <= base_storage_size, ResultNcaBaseStorageOutOfRangeD); - storage_info[i + 1] = std::make_shared(base_storage, - layer_info.size, - layer_info_offset + layer_info.offset); + storage_info[i + 1] = std::make_shared( + base_storage, layer_info.size, layer_info_offset + layer_info.offset); } // Set the last layer info. @@ -1333,21 +1251,16 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl( R_UNLESS(last_layer_info_offset + layer_info.size <= layer_info_offset, ResultRomNcaInvalidIntegrityLayerInfoOffset); } - storage_info[level_hash_info.max_layers - 1] - = std::make_shared(std::move(base_storage), - layer_info.size, - last_layer_info_offset); + storage_info.SetDataStorage(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(); R_UNLESS(integrity_storage != nullptr, ResultAllocationMemoryFailedAllocateShared); // Initialize the integrity storage. - R_TRY(integrity_storage->Initialize(level_hash_info, - meta_info.master_hash, - storage_info, - max_data_cache_entries, - max_hash_cache_entries, + R_TRY(integrity_storage->Initialize(level_hash_info, meta_info.master_hash, storage_info, + max_data_cache_entries, max_hash_cache_entries, buffer_level)); // Set the output. diff --git a/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.h b/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.h index e09bfc588a..5bc838de64 100644 --- a/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.h +++ b/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.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 @@ -332,10 +329,6 @@ private: const NcaPatchInfo& patch_info, const NcaMetaDataHashDataInfo& meta_data_hash_data_info); - - Result CreateSha3Storage(VirtualFile* out, VirtualFile base_storage, - const NcaFsHeader::HashData::HierarchicalSha256Data& hash_data); - Result CreateSha256Storage(VirtualFile* out, VirtualFile base_storage, const NcaFsHeader::HashData::HierarchicalSha256Data& sha256_data); diff --git a/src/core/file_sys/fssystem/fssystem_nca_header.cpp b/src/core/file_sys/fssystem/fssystem_nca_header.cpp index 77042dfd43..bf5742d39f 100644 --- a/src/core/file_sys/fssystem/fssystem_nca_header.cpp +++ b/src/core/file_sys/fssystem/fssystem_nca_header.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 @@ -9,7 +6,7 @@ namespace FileSys { u8 NcaHeader::GetProperKeyGeneration() const { - return (std::max)(this->key_generation, this->key_generation_2); + return std::max(this->key_generation, this->key_generation_2); } bool NcaPatchInfo::HasIndirectTable() const { diff --git a/src/core/file_sys/fssystem/fssystem_pooled_buffer.cpp b/src/core/file_sys/fssystem/fssystem_pooled_buffer.cpp index dcd08dac3e..bbfaab2557 100644 --- a/src/core/file_sys/fssystem/fssystem_pooled_buffer.cpp +++ b/src/core/file_sys/fssystem/fssystem_pooled_buffer.cpp @@ -34,7 +34,7 @@ void PooledBuffer::AllocateCore(size_t ideal_size, size_t required_size, bool la ASSERT(required_size <= GetAllocatableSizeMaxCore(large)); const size_t target_size = - (std::min)((std::max)(ideal_size, required_size), GetAllocatableSizeMaxCore(large)); + std::min(std::max(ideal_size, required_size), GetAllocatableSizeMaxCore(large)); // Dummy implementation for allocate. if (target_size > 0) { diff --git a/src/core/file_sys/fssystem/fssystem_sparse_storage.h b/src/core/file_sys/fssystem/fssystem_sparse_storage.h index 1cc7e7b1eb..6c196ec611 100644 --- a/src/core/file_sys/fssystem/fssystem_sparse_storage.h +++ b/src/core/file_sys/fssystem/fssystem_sparse_storage.h @@ -18,7 +18,7 @@ private: virtual ~ZeroStorage() {} virtual size_t GetSize() const override { - return (std::numeric_limits::max)(); + return std::numeric_limits::max(); } virtual size_t Read(u8* buffer, size_t size, size_t offset) const override { @@ -62,7 +62,7 @@ public: private: void SetZeroStorage() { - return this->SetStorage(1, m_zero_storage, 0, (std::numeric_limits::max)()); + return this->SetStorage(1, m_zero_storage, 0, std::numeric_limits::max()); } private: diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp index 55ea4d0803..9e855c50d1 100644 --- a/src/core/file_sys/nca_metadata.cpp +++ b/src/core/file_sys/nca_metadata.cpp @@ -102,7 +102,7 @@ std::vector CNMT::Serialize() const { header.type >= TitleType::Application && header.type <= TitleType::AOC; const auto dead_zone = header.table_offset + sizeof(CNMTHeader); std::vector out( - (std::max)(sizeof(CNMTHeader) + (has_opt_header ? sizeof(OptionalHeader) : 0), dead_zone) + + std::max(sizeof(CNMTHeader) + (has_opt_header ? sizeof(OptionalHeader) : 0), dead_zone) + content_records.size() * sizeof(ContentRecord) + meta_records.size() * sizeof(MetaRecord)); memcpy(out.data(), &header, sizeof(CNMTHeader)); diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 45390500cc..85d30543c1 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -64,7 +64,7 @@ static std::string GetRelativePathFromNcaID(const std::array& nca_id, bo } Core::Crypto::SHA256Hash hash{}; - mbedtls_sha256(nca_id.data(), nca_id.size(), hash.data(), 0); + mbedtls_sha256_ret(nca_id.data(), nca_id.size(), hash.data(), 0); const auto format_str = fmt::runtime(cnmt_suffix ? "/000000{:02X}/{}.cnmt.nca" : "/000000{:02X}/{}.nca"); @@ -146,7 +146,7 @@ bool PlaceholderCache::Create(const NcaID& id, u64 size) const { } Core::Crypto::SHA256Hash hash{}; - mbedtls_sha256(id.data(), id.size(), hash.data(), 0); + mbedtls_sha256_ret(id.data(), id.size(), hash.data(), 0); const auto dirname = fmt::format("000000{:02X}", hash[0]); const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname); @@ -170,7 +170,7 @@ bool PlaceholderCache::Delete(const NcaID& id) const { } Core::Crypto::SHA256Hash hash{}; - mbedtls_sha256(id.data(), id.size(), hash.data(), 0); + mbedtls_sha256_ret(id.data(), id.size(), hash.data(), 0); const auto dirname = fmt::format("000000{:02X}", hash[0]); const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname); @@ -273,7 +273,7 @@ std::vector PlaceholderCache::List() const { NcaID PlaceholderCache::Generate() { std::random_device device; std::mt19937 gen(device()); - std::uniform_int_distribution distribution(1, (std::numeric_limits::max)()); + std::uniform_int_distribution distribution(1, std::numeric_limits::max()); NcaID out{}; @@ -665,7 +665,7 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, const OptionalHeader opt_header{0, 0}; ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}}; const auto& data = nca.GetBaseFile()->ReadBytes(0x100000); - mbedtls_sha256(data.data(), data.size(), c_rec.hash.data(), 0); + mbedtls_sha256_ret(data.data(), data.size(), c_rec.hash.data(), 0); std::memcpy(&c_rec.nca_id, &c_rec.hash, 16); const CNMT new_cnmt(header, opt_header, {c_rec}, {}); if (!RawInstallYuzuMeta(new_cnmt)) { @@ -776,7 +776,7 @@ InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFuncti id = *override_id; } else { const auto& data = in->ReadBytes(0x100000); - mbedtls_sha256(data.data(), data.size(), hash.data(), 0); + mbedtls_sha256_ret(data.data(), data.size(), hash.data(), 0); memcpy(id.data(), hash.data(), 16); } diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp index fee75f9de6..a2b2809734 100644 --- a/src/core/file_sys/romfs.cpp +++ b/src/core/file_sys/romfs.cpp @@ -75,7 +75,7 @@ std::pair GetEntry(const RomFSTraversalContext& ctx, siz } std::memcpy(&entry, data + offset, sizeof(EntryType)); - const size_t name_length = (std::min)(entry_end + entry.name_length, size) - entry_end; + const size_t name_length = std::min(entry_end + entry.name_length, size) - entry_end; std::string name(reinterpret_cast(data + entry_end), name_length); return {entry, std::move(name)}; diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index edf51e74de..106922e04f 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -129,10 +126,6 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir, std::string out = GetSaveDataSpaceIdPath(space); - LOG_INFO(Common_Filesystem, "Save ID: {:016X}", save_id); - LOG_INFO(Common_Filesystem, "User ID[1]: {:016X}", user_id[1]); - LOG_INFO(Common_Filesystem, "User ID[0]: {:016X}", user_id[0]); - switch (type) { case SaveDataType::System: return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]); diff --git a/src/core/file_sys/vfs/vfs.cpp b/src/core/file_sys/vfs/vfs.cpp index 2be7084209..a04292760f 100644 --- a/src/core/file_sys/vfs/vfs.cpp +++ b/src/core/file_sys/vfs/vfs.cpp @@ -507,9 +507,9 @@ bool VfsRawCopy(const VirtualFile& src, const VirtualFile& dest, std::size_t blo if (!dest->Resize(src->GetSize())) return false; - std::vector temp((std::min)(block_size, src->GetSize())); + std::vector temp(std::min(block_size, src->GetSize())); for (std::size_t i = 0; i < src->GetSize(); i += block_size) { - const auto read = (std::min)(block_size, src->GetSize() - i); + const auto read = std::min(block_size, src->GetSize() - i); if (src->Read(temp.data(), read, i) != read) { return false; diff --git a/src/core/file_sys/vfs/vfs_real.cpp b/src/core/file_sys/vfs/vfs_real.cpp index 4199667171..052684e9db 100644 --- a/src/core/file_sys/vfs/vfs_real.cpp +++ b/src/core/file_sys/vfs/vfs_real.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -445,12 +442,11 @@ std::vector RealVfsDirectory::GetFiles() const { FileTimeStampRaw RealVfsDirectory::GetFileTimeStamp(std::string_view path_) const { const auto full_path = FS::SanitizePath(path + '/' + std::string(path_)); const auto fs_path = std::filesystem::path{FS::ToU8String(full_path)}; + struct stat file_status; #ifdef _WIN32 - struct _stat64 file_status; const auto stat_result = _wstat64(fs_path.c_str(), &file_status); #else - struct stat file_status; const auto stat_result = stat(fs_path.c_str(), &file_status); #endif diff --git a/src/core/file_sys/vfs/vfs_static.h b/src/core/file_sys/vfs/vfs_static.h index 6dc4ef8fbf..bb53560ac7 100644 --- a/src/core/file_sys/vfs/vfs_static.h +++ b/src/core/file_sys/vfs/vfs_static.h @@ -43,7 +43,7 @@ public: } std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override { - const auto read = (std::min)(length, size - offset); + const auto read = std::min(length, size - offset); std::fill(data, data + read, value); return read; } @@ -61,7 +61,7 @@ public: } std::vector ReadBytes(std::size_t length, std::size_t offset) const override { - const auto read = (std::min)(length, size - offset); + const auto read = std::min(length, size - offset); return std::vector(read, value); } diff --git a/src/core/file_sys/vfs/vfs_vector.cpp b/src/core/file_sys/vfs/vfs_vector.cpp index 7576a023cf..0d54461c8f 100644 --- a/src/core/file_sys/vfs/vfs_vector.cpp +++ b/src/core/file_sys/vfs/vfs_vector.cpp @@ -37,7 +37,7 @@ bool VectorVfsFile::IsReadable() const { } std::size_t VectorVfsFile::Read(u8* data_, std::size_t length, std::size_t offset) const { - const auto read = (std::min)(length, data.size() - offset); + const auto read = std::min(length, data.size() - offset); std::memcpy(data_, data.data() + offset, read); return read; } @@ -45,7 +45,7 @@ std::size_t VectorVfsFile::Read(u8* data_, std::size_t length, std::size_t offse std::size_t VectorVfsFile::Write(const u8* data_, std::size_t length, std::size_t offset) { if (offset + length > data.size()) data.resize(offset + length); - const auto write = (std::min)(length, data.size() - offset); + const auto write = std::min(length, data.size() - offset); std::memcpy(data.data() + offset, data_, write); return write; } diff --git a/src/core/file_sys/vfs/vfs_vector.h b/src/core/file_sys/vfs/vfs_vector.h index 27f2c03ca7..587187dd26 100644 --- a/src/core/file_sys/vfs/vfs_vector.h +++ b/src/core/file_sys/vfs/vfs_vector.h @@ -45,7 +45,7 @@ public: } std::size_t Read(u8* data_, std::size_t length, std::size_t offset) const override { - const auto read = (std::min)(length, size - offset); + const auto read = std::min(length, size - offset); std::memcpy(data_, data.data() + offset, read); return read; } diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index c1912b2bda..fd5342021c 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp @@ -68,7 +68,7 @@ NAX::NAX(VirtualFile file_, std::array nca_id) : header(std::make_unique()), file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} { Core::Crypto::SHA256Hash hash{}; - mbedtls_sha256(nca_id.data(), nca_id.size(), hash.data(), 0); + mbedtls_sha256_ret(nca_id.data(), nca_id.size(), hash.data(), 0); status = Parse(fmt::format("/registered/000000{:02X}/{}.nca", hash[0], Common::HexToString(nca_id, false))); } diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index ec5cec8fa0..d1f1ca8c97 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -28,11 +28,11 @@ std::pair EmuWindow::MapToTouchScreen(u32 framebuffer_x, u32 framebuff } std::pair EmuWindow::ClipToTouchScreen(u32 new_x, u32 new_y) const { - new_x = (std::max)(new_x, framebuffer_layout.screen.left); - new_x = (std::min)(new_x, framebuffer_layout.screen.right - 1); + new_x = std::max(new_x, framebuffer_layout.screen.left); + new_x = std::min(new_x, framebuffer_layout.screen.right - 1); - new_y = (std::max)(new_y, framebuffer_layout.screen.top); - new_y = (std::min)(new_y, framebuffer_layout.screen.bottom - 1); + new_y = std::max(new_y, framebuffer_layout.screen.top); + new_y = std::min(new_y, framebuffer_layout.screen.bottom - 1); return std::make_pair(new_x, new_y); } diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 3de975c20f..2590b20da4 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp @@ -14,7 +14,7 @@ namespace Layout { template static Common::Rectangle MaxRectangle(Common::Rectangle window_area, float screen_aspect_ratio) { - const float scale = (std::min)(static_cast(window_area.GetWidth()), + const float scale = std::min(static_cast(window_area.GetWidth()), static_cast(window_area.GetHeight()) / screen_aspect_ratio); return Common::Rectangle{0, 0, static_cast(std::round(scale)), static_cast(std::round(scale * screen_aspect_ratio))}; diff --git a/src/core/hle/kernel/board/nintendo/nx/k_memory_layout.cpp b/src/core/hle/kernel/board/nintendo/nx/k_memory_layout.cpp index fa918ff204..24eb3f8866 100644 --- a/src/core/hle/kernel/board/nintendo/nx/k_memory_layout.cpp +++ b/src/core/hle/kernel/board/nintendo/nx/k_memory_layout.cpp @@ -133,7 +133,7 @@ void SetupPoolPartitionMemoryRegions(KMemoryLayout& memory_layout) { // Decide on starting addresses for our pools. const u64 application_pool_start = pool_end - application_pool_size; const u64 applet_pool_start = application_pool_start - applet_pool_size; - const u64 unsafe_system_pool_start = (std::min)( + const u64 unsafe_system_pool_start = std::min( kernel_dram_start + CarveoutSizeMax, Common::AlignDown(applet_pool_start - unsafe_system_pool_min_size, CarveoutAlignment)); const size_t unsafe_system_pool_size = applet_pool_start - unsafe_system_pool_start; diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp index db654d730d..f62f3e4767 100644 --- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp +++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp @@ -182,13 +182,13 @@ namespace { template u64 GenerateUniformRange(u64 min, u64 max, F f) { // Handle the case where the difference is too large to represent. - if (max == (std::numeric_limits::max)() && min == (std::numeric_limits::min)()) { + if (max == std::numeric_limits::max() && min == std::numeric_limits::min()) { return f(); } // Iterate until we get a value in range. const u64 range_size = ((max + 1) - min); - const u64 effective_max = ((std::numeric_limits::max)() / range_size) * range_size; + const u64 effective_max = (std::numeric_limits::max() / range_size) * range_size; while (true) { if (const u64 rnd = f(); rnd < effective_max) { return min + (rnd % range_size); @@ -201,7 +201,7 @@ u64 GenerateUniformRange(u64 min, u64 max, F f) { u64 KSystemControl::GenerateRandomU64() { std::random_device device; std::mt19937 gen(device()); - std::uniform_int_distribution distribution(1, (std::numeric_limits::max)()); + std::uniform_int_distribution distribution(1, std::numeric_limits::max()); return distribution(gen); } diff --git a/src/core/hle/kernel/k_dynamic_page_manager.h b/src/core/hle/kernel/k_dynamic_page_manager.h index 2357fe0f4d..ad11e84b71 100644 --- a/src/core/hle/kernel/k_dynamic_page_manager.h +++ b/src/core/hle/kernel/k_dynamic_page_manager.h @@ -110,7 +110,7 @@ public: // Update our tracking. m_page_bitmap.ClearBit(offset); - m_peak = (std::max)(m_peak, (++m_used)); + m_peak = std::max(m_peak, (++m_used)); return GetPointer(m_aligned_address) + offset; } @@ -131,7 +131,7 @@ public: // Update our tracking. m_page_bitmap.ClearRange(offset, count); m_used += count; - m_peak = (std::max)(m_peak, m_used); + m_peak = std::max(m_peak, m_used); return GetPointer(m_aligned_address) + offset; } diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 22fdc7e47a..1bf68e6b04 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/src/core/hle/kernel/k_handle_table.h @@ -179,7 +179,7 @@ private: m_free_head_index = m_entry_infos[index].GetNextFreeIndex(); - m_max_count = (std::max)(m_max_count, ++m_count); + m_max_count = std::max(m_max_count, ++m_count); return index; } diff --git a/src/core/hle/kernel/k_hardware_timer.cpp b/src/core/hle/kernel/k_hardware_timer.cpp index f3098a59e0..4e947dd6bc 100644 --- a/src/core/hle/kernel/k_hardware_timer.cpp +++ b/src/core/hle/kernel/k_hardware_timer.cpp @@ -19,7 +19,7 @@ void KHardwareTimer::Initialize() { void KHardwareTimer::Finalize() { m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type); - m_wakeup_time = (std::numeric_limits::max)(); + m_wakeup_time = std::numeric_limits::max(); m_event_type.reset(); } @@ -37,7 +37,7 @@ void KHardwareTimer::DoTask() { // Disable the timer interrupt while we handle this. // Not necessary due to core timing already having popped this event to call it. // this->DisableInterrupt(); - m_wakeup_time = (std::numeric_limits::max)(); + m_wakeup_time = std::numeric_limits::max(); if (const s64 next_time = this->DoInterruptTaskImpl(GetTick()); 0 < next_time && next_time <= m_wakeup_time) { @@ -63,7 +63,7 @@ void KHardwareTimer::EnableInterrupt(s64 wakeup_time) { void KHardwareTimer::DisableInterrupt() { m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, Core::Timing::UnscheduleEventType::NoWait); - m_wakeup_time = (std::numeric_limits::max)(); + m_wakeup_time = std::numeric_limits::max(); } s64 KHardwareTimer::GetTick() const { @@ -71,7 +71,7 @@ s64 KHardwareTimer::GetTick() const { } bool KHardwareTimer::GetInterruptEnabled() { - return m_wakeup_time != (std::numeric_limits::max)(); + return m_wakeup_time != std::numeric_limits::max(); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_hardware_timer.h b/src/core/hle/kernel/k_hardware_timer.h index cb83e9c5b5..27f43cd194 100644 --- a/src/core/hle/kernel/k_hardware_timer.h +++ b/src/core/hle/kernel/k_hardware_timer.h @@ -40,7 +40,7 @@ private: private: // Absolute time in nanoseconds - s64 m_wakeup_time{(std::numeric_limits::max)()}; + s64 m_wakeup_time{std::numeric_limits::max()}; std::shared_ptr m_event_type{}; }; diff --git a/src/core/hle/kernel/k_light_server_session.cpp b/src/core/hle/kernel/k_light_server_session.cpp index 5ea448b998..e5ceb01f2a 100644 --- a/src/core/hle/kernel/k_light_server_session.cpp +++ b/src/core/hle/kernel/k_light_server_session.cpp @@ -11,7 +11,7 @@ namespace Kernel { namespace { -constexpr u64 InvalidThreadId = (std::numeric_limits::max)(); +constexpr u64 InvalidThreadId = std::numeric_limits::max(); class ThreadQueueImplForKLightServerSessionRequest final : public KThreadQueue { private: diff --git a/src/core/hle/kernel/k_light_server_session.h b/src/core/hle/kernel/k_light_server_session.h index 87ec9db016..8eca3eab69 100644 --- a/src/core/hle/kernel/k_light_server_session.h +++ b/src/core/hle/kernel/k_light_server_session.h @@ -19,7 +19,7 @@ private: KLightSession* m_parent{}; KThread::WaiterList m_request_list{}; KThread* m_current_request{}; - u64 m_server_thread_id{(std::numeric_limits::max)()}; + u64 m_server_thread_id{std::numeric_limits::max()}; KThread* m_server_thread{}; public: diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h index acf48cb757..d2b7e9a66e 100644 --- a/src/core/hle/kernel/k_memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h @@ -551,7 +551,7 @@ public: } m_device_disable_merge_left_count = - (std::min)(m_device_disable_merge_left_count, m_device_use_count); + std::min(m_device_disable_merge_left_count, m_device_use_count); if (m_device_disable_merge_left_count == 0) { m_disable_merge_attribute = static_cast( diff --git a/src/core/hle/kernel/k_memory_layout.cpp b/src/core/hle/kernel/k_memory_layout.cpp index 6821f4c07e..bec7146688 100644 --- a/src/core/hle/kernel/k_memory_layout.cpp +++ b/src/core/hle/kernel/k_memory_layout.cpp @@ -66,7 +66,7 @@ bool KMemoryRegionTree::Insert(u64 address, size_t size, u32 type_id, u32 new_at this->insert(*found); // Insert a new region for the split. - const u64 new_pair = (old_pair != (std::numeric_limits::max)()) + const u64 new_pair = (old_pair != std::numeric_limits::max()) ? old_pair + (address - old_address) : old_pair; this->insert(*AllocateRegion(m_memory_region_allocator, address, inserted_region_last, @@ -75,7 +75,7 @@ bool KMemoryRegionTree::Insert(u64 address, size_t size, u32 type_id, u32 new_at // If we need to insert a region after the region, do so. if (old_last != inserted_region_last) { - const u64 after_pair = (old_pair != (std::numeric_limits::max)()) + const u64 after_pair = (old_pair != std::numeric_limits::max()) ? old_pair + (inserted_region_end - old_address) : old_pair; this->insert(*AllocateRegion(m_memory_region_allocator, inserted_region_end, old_last, diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index 2aa393ac06..d6bd272962 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp @@ -323,7 +323,7 @@ Result KMemoryManager::AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 op // Process part or all of the block. const size_t cur_pages = - (std::min)(remaining_pages, manager.GetPageOffsetToEnd(cur_address)); + std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address)); manager.OpenFirst(cur_address, cur_pages); // Advance. @@ -385,7 +385,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32 // Process part or all of the block. const size_t cur_pages = - (std::min)(remaining_pages, manager.GetPageOffsetToEnd(cur_address)); + std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address)); any_new = manager.ProcessOptimizedAllocation(m_system.Kernel(), cur_address, cur_pages, fill_pattern); @@ -409,7 +409,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32 // Track some or all of the current pages. const size_t cur_pages = - (std::min)(remaining_pages, manager.GetPageOffsetToEnd(cur_address)); + std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address)); manager.TrackOptimizedAllocation(m_system.Kernel(), cur_address, cur_pages); // Advance. diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h index 41d33fa55d..c5a487af92 100644 --- a/src/core/hle/kernel/k_memory_manager.h +++ b/src/core/hle/kernel/k_memory_manager.h @@ -68,7 +68,7 @@ public: // Repeatedly open references until we've done so for all pages. while (num_pages) { auto& manager = this->GetManager(address); - const size_t cur_pages = (std::min)(num_pages, manager.GetPageOffsetToEnd(address)); + const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address)); { KScopedLightLock lk(m_pool_locks[static_cast(manager.GetPool())]); @@ -84,7 +84,7 @@ public: // Repeatedly open references until we've done so for all pages. while (num_pages) { auto& manager = this->GetManager(address); - const size_t cur_pages = (std::min)(num_pages, manager.GetPageOffsetToEnd(address)); + const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address)); { KScopedLightLock lk(m_pool_locks[static_cast(manager.GetPool())]); @@ -100,7 +100,7 @@ public: // Repeatedly close references until we've done so for all pages. while (num_pages) { auto& manager = this->GetManager(address); - const size_t cur_pages = (std::min)(num_pages, manager.GetPageOffsetToEnd(address)); + const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address)); { KScopedLightLock lk(m_pool_locks[static_cast(manager.GetPool())]); diff --git a/src/core/hle/kernel/k_memory_region.h b/src/core/hle/kernel/k_memory_region.h index cad7b31126..e3044f0227 100644 --- a/src/core/hle/kernel/k_memory_region.h +++ b/src/core/hle/kernel/k_memory_region.h @@ -28,7 +28,7 @@ public: : m_address(address), m_last_address(last_address), m_pair_address(pair_address), m_attributes(attributes), m_type_id(type_id) {} constexpr KMemoryRegion(u64 address, u64 last_address, u32 attributes, u32 type_id) - : KMemoryRegion(address, last_address, (std::numeric_limits::max)(), attributes, + : KMemoryRegion(address, last_address, std::numeric_limits::max(), attributes, type_id) {} ~KMemoryRegion() = default; diff --git a/src/core/hle/kernel/k_page_bitmap.h b/src/core/hle/kernel/k_page_bitmap.h index 4ad5483b28..0ff9877326 100644 --- a/src/core/hle/kernel/k_page_bitmap.h +++ b/src/core/hle/kernel/k_page_bitmap.h @@ -83,7 +83,7 @@ public: } // Determine how many bits to take this round. - const auto cur_bits = (std::min)(num_bits, m_bits_available); + const auto cur_bits = std::min(num_bits, m_bits_available); // Generate mask for our current bits. const u64 mask = (static_cast(1) << cur_bits) - 1; diff --git a/src/core/hle/kernel/k_page_heap.h b/src/core/hle/kernel/k_page_heap.h index 0d63a6b1f5..c55225bac6 100644 --- a/src/core/hle/kernel/k_page_heap.h +++ b/src/core/hle/kernel/k_page_heap.h @@ -75,7 +75,7 @@ public: } static constexpr s32 GetAlignedBlockIndex(size_t num_pages, size_t align_pages) { - const size_t target_pages = (std::max)(num_pages, align_pages); + const size_t target_pages = std::max(num_pages, align_pages); for (size_t i = 0; i < NumMemoryBlockPageShifts; i++) { if (target_pages <= (static_cast(1) << MemoryBlockPageShifts[i]) / PageSize) { return static_cast(i); diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 6b3f60f52e..5e39fbeb14 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -1731,7 +1731,7 @@ void KPageTableBase::RemapPageGroup(PageLinkedList* page_list, KProcessAddress a } // Map whatever we can. - const size_t cur_pages = (std::min)(pg_pages, map_pages); + const size_t cur_pages = std::min(pg_pages, map_pages); R_ASSERT(this->Operate(page_list, map_address, map_pages, pg_phys_addr, true, map_properties, OperationType::Map, true)); @@ -1929,7 +1929,7 @@ Result KPageTableBase::GetContiguousMemoryRangeWithState( } // Take the minimum size for our region. - size = (std::min)(size, contig_size); + size = std::min(size, contig_size); // Check that the memory is contiguous (modulo the reference count bit). const KMemoryState test_state_mask = state_mask | KMemoryState::FlagReferenceCounted; @@ -5297,7 +5297,7 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { KMemoryPermission::None, false, false, DisableMergeAttribute::None}; const size_t cur_pages = - (std::min)(KProcessAddress(info.GetEndAddress()) - cur_address, + std::min(KProcessAddress(info.GetEndAddress()) - cur_address, last_unmap_address + 1 - cur_address) / PageSize; @@ -5345,7 +5345,7 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { ? DisableMergeAttribute::DisableHead : DisableMergeAttribute::None}; size_t map_pages = - (std::min)(KProcessAddress(info.GetEndAddress()) - cur_address, + std::min(KProcessAddress(info.GetEndAddress()) - cur_address, last_address + 1 - cur_address) / PageSize; @@ -5373,7 +5373,7 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) { } // Add whatever we can to the current block. - const size_t cur_pages = (std::min)(pg_pages, remain_pages); + const size_t cur_pages = std::min(pg_pages, remain_pages); R_TRY(cur_pg.AddBlock(pg_phys_addr + ((pg_pages - cur_pages) * PageSize), cur_pages)); @@ -5535,7 +5535,7 @@ Result KPageTableBase::UnmapPhysicalMemory(KProcessAddress address, size_t size) // Determine the range to unmap. const KPageProperties unmap_properties = {KMemoryPermission::None, false, false, DisableMergeAttribute::None}; - const size_t cur_pages = (std::min)(KProcessAddress(info.GetEndAddress()) - cur_address, + const size_t cur_pages = std::min(KProcessAddress(info.GetEndAddress()) - cur_address, last_address + 1 - cur_address) / PageSize; @@ -5656,7 +5656,7 @@ Result KPageTableBase::UnmapProcessMemory(KProcessAddress dst_address, size_t si } // Update our current size. - m_cur_size = (std::min)(m_remaining_size, m_cur_size + m_entry.block_size); + m_cur_size = std::min(m_remaining_size, m_cur_size + m_entry.block_size); } } }; diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 80566b7e77..cf03353f84 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -1266,10 +1266,6 @@ void KProcess::InitializeInterfaces() { #ifdef HAS_NCE if (this->IsApplication() && Settings::IsNceEnabled()) { - // Register the scoped JIT handler before creating any NCE instances - // so that its signal handler will appear first in the signal chain. - Core::ScopedJitExecution::RegisterHandler(); - for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique(m_kernel.System(), true, i); } diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index d6742f0637..df3e540dc2 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -59,7 +59,7 @@ public: static constexpr u64 InitialProcessIdMax = 0x50; static constexpr u64 ProcessIdMin = InitialProcessIdMax + 1; - static constexpr u64 ProcessIdMax = (std::numeric_limits::max)(); + static constexpr u64 ProcessIdMax = std::numeric_limits::max(); private: using SharedMemoryInfoList = Common::IntrusiveListBaseTraits::ListType; diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index 1403317d72..d8a63aaf8c 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -111,7 +111,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { if (m_current_values[index] + value <= m_limit_values[index]) { m_current_values[index] += value; m_current_hints[index] += value; - m_peak_values[index] = (std::max)(m_peak_values[index], m_current_values[index]); + m_peak_values[index] = std::max(m_peak_values[index], m_current_values[index]); return true; } diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h index 2ec3d185dc..334afebb71 100644 --- a/src/core/hle/kernel/k_slab_heap.h +++ b/src/core/hle/kernel/k_slab_heap.h @@ -149,7 +149,7 @@ public: size_t GetObjectIndex(const void* obj) const { if constexpr (SupportDynamicExpansion) { if (!this->Contains(reinterpret_cast(obj))) { - return (std::numeric_limits::max)(); + return std::numeric_limits::max(); } } diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 6aef191c87..8a360a839b 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -1016,7 +1016,7 @@ void KThread::RestorePriority(KernelCore& kernel, KThread* thread) { s32 new_priority = thread->GetBasePriority(); for (const auto& held_lock : thread->m_held_lock_info_list) { new_priority = - (std::min)(new_priority, held_lock.GetHighestPriorityWaiter()->GetPriority()); + std::min(new_priority, held_lock.GetHighestPriorityWaiter()->GetPriority()); } // If the priority we would inherit is not different from ours, don't do anything. diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0ff81066e9..00177dc943 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -507,7 +507,7 @@ struct KernelCore::Impl { constexpr size_t MiscRegionAlign = KernelAslrAlignment; constexpr size_t MiscRegionMinimumSize = 32_MiB; const size_t misc_region_size = Common::AlignUp( - (std::max)(misc_region_needed_size, MiscRegionMinimumSize), MiscRegionAlign); + std::max(misc_region_needed_size, MiscRegionMinimumSize), MiscRegionAlign); ASSERT(misc_region_size > 0); // Setup the misc region. diff --git a/src/core/hle/kernel/svc/svc_address_arbiter.cpp b/src/core/hle/kernel/svc/svc_address_arbiter.cpp index 688d6abce0..ab91d74433 100644 --- a/src/core/hle/kernel/svc/svc_address_arbiter.cpp +++ b/src/core/hle/kernel/svc/svc_address_arbiter.cpp @@ -58,10 +58,10 @@ Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_typ if (offset_tick > 0) { timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2; if (timeout <= 0) { - timeout = (std::numeric_limits::max)(); + timeout = std::numeric_limits::max(); } } else { - timeout = (std::numeric_limits::max)(); + timeout = std::numeric_limits::max(); } } else { timeout = timeout_ns; diff --git a/src/core/hle/kernel/svc/svc_condition_variable.cpp b/src/core/hle/kernel/svc/svc_condition_variable.cpp index 2aed6a77be..0f4550a795 100644 --- a/src/core/hle/kernel/svc/svc_condition_variable.cpp +++ b/src/core/hle/kernel/svc/svc_condition_variable.cpp @@ -31,10 +31,10 @@ Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u if (offset_tick > 0) { timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2; if (timeout <= 0) { - timeout = (std::numeric_limits::max)(); + timeout = std::numeric_limits::max(); } } else { - timeout = (std::numeric_limits::max)(); + timeout = std::numeric_limits::max(); } } else { timeout = timeout_ns; diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index bc0684e76c..b619bd70ab 100644 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp @@ -61,10 +61,10 @@ Result ReplyAndReceiveImpl(KernelCore& kernel, int32_t* out_index, uintptr_t mes if (offset_tick > 0) { timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2; if (timeout <= 0) { - timeout = (std::numeric_limits::max)(); + timeout = std::numeric_limits::max(); } } else { - timeout = (std::numeric_limits::max)(); + timeout = std::numeric_limits::max(); } } else { timeout = timeout_ns; diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp index 6d63892a94..87845d64a6 100644 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp @@ -82,7 +82,7 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc const auto num_processes = process_list.size(); const auto copy_amount = - (std::min)(static_cast(out_process_ids_size), num_processes); + std::min(static_cast(out_process_ids_size), num_processes); for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) { memory.Write64(out_process_ids, (*it)->GetProcessId()); diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index ca5ce6fe07..77cd634c0d 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -117,10 +117,10 @@ void SleepThread(Core::System& system, s64 ns) { if (offset_tick > 0) { timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2; if (timeout <= 0) { - timeout = (std::numeric_limits::max)(); + timeout = std::numeric_limits::max(); } } else { - timeout = (std::numeric_limits::max)(); + timeout = std::numeric_limits::max(); } // Sleep. @@ -226,7 +226,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_ auto& memory = GetCurrentMemory(system.Kernel()); const auto& thread_list = current_process->GetThreadList(); const auto num_threads = thread_list.size(); - const auto copy_amount = (std::min)(static_cast(out_thread_ids_size), num_threads); + const auto copy_amount = std::min(static_cast(out_thread_ids_size), num_threads); auto list_iter = thread_list.cbegin(); for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) { diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 495e6e32c2..316370266d 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -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 @@ -27,7 +24,6 @@ enum class ErrorModule : u32 { HTCS = 4, NCM = 5, DD = 6, - OSDBG = 7, LR = 8, Loader = 9, CMIF = 10, @@ -55,7 +51,6 @@ enum class ErrorModule : u32 { Util = 33, TIPC = 35, ANIF = 37, - CRT = 39, ETHC = 100, I2C = 101, GPIO = 102, @@ -111,7 +106,6 @@ enum class ErrorModule : u32 { Audio = 153, NPNS = 154, NPNSHTTPSTREAM = 155, - IDLE = 156, ARP = 157, SWKBD = 158, BOOT = 159, @@ -121,7 +115,6 @@ enum class ErrorModule : u32 { Fatal = 163, NIMShop = 164, SPSM = 165, - AOC = 166, BGTC = 167, UserlandCrash = 168, SASBUS = 169, @@ -183,22 +176,13 @@ enum class ErrorModule : u32 { DP2HDMI = 244, Cradle = 245, SProfile = 246, - Icm42607p = 248, NDRM = 250, - Fst2 = 251, - Nex = 306, - NPLN = 321, TSPM = 499, DevMenu = 500, - Nverpt = 520, - Am_StuckMonitor = 521, - Pia = 618, - Eagle = 623, GeneralWebApplet = 800, WifiWebAuthApplet = 809, WhitelistedApplet = 810, ShopN = 811, - Coral = 815 }; /// Encapsulates a Horizon OS error code, allowing it to be separated into its constituent fields. diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 73f54f89b2..51a542e5e6 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -72,7 +72,7 @@ static void SanitizeJPEGImageSize(std::vector& image) { } } - image.resize((std::min)(image.size(), max_jpeg_image_size)); + image.resize(std::min(image.size(), max_jpeg_image_size)); } class IManagerForSystemService final : public ServiceFramework { diff --git a/src/core/hle/service/am/applet.cpp b/src/core/hle/service/am/applet.cpp index aa355b06d5..59ade29c8e 100644 --- a/src/core/hle/service/am/applet.cpp +++ b/src/core/hle/service/am/applet.cpp @@ -1,8 +1,5 @@ -// 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 +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" #include "core/hle/service/am/applet.h" @@ -15,7 +12,7 @@ Applet::Applet(Core::System& system, std::unique_ptr process_, bool is_ process(std::move(process_)), hid_registration(system, *process), gpu_error_detected_event(context), friend_invitation_storage_channel_event(context), notification_storage_channel_event(context), health_warning_disappeared_system_event(context), - unknown_event(context), acquired_sleep_lock_event(context), pop_from_general_channel_event(context), + acquired_sleep_lock_event(context), pop_from_general_channel_event(context), library_applet_launchable_event(context), accumulated_suspended_tick_changed_event(context), sleep_lock_event(context), state_changed_event(context) { diff --git a/src/core/hle/service/am/applet.h b/src/core/hle/service/am/applet.h index 6cc8cdf741..835cfe6ec8 100644 --- a/src/core/hle/service/am/applet.h +++ b/src/core/hle/service/am/applet.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 @@ -123,7 +120,6 @@ struct Applet { Event friend_invitation_storage_channel_event; Event notification_storage_channel_event; Event health_warning_disappeared_system_event; - Event unknown_event; Event acquired_sleep_lock_event; Event pop_from_general_channel_event; Event library_applet_launchable_event; diff --git a/src/core/hle/service/am/frontend/applet_cabinet.cpp b/src/core/hle/service/am/frontend/applet_cabinet.cpp index 58401479d3..4cbc80d639 100644 --- a/src/core/hle/service/am/frontend/applet_cabinet.cpp +++ b/src/core/hle/service/am/frontend/applet_cabinet.cpp @@ -118,7 +118,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name) case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: { Service::NFP::RegisterInfoPrivate register_info{}; std::memcpy(register_info.amiibo_name.data(), amiibo_name.data(), - (std::min)(amiibo_name.size(), register_info.amiibo_name.size() - 1)); + std::min(amiibo_name.size(), register_info.amiibo_name.size() - 1)); register_info.mii_store_data.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All); register_info.mii_store_data.SetNickname({u'y', u'u', u'z', u'u'}); nfp_device->SetRegisterInfoPrivate(register_info); diff --git a/src/core/hle/service/am/frontend/applet_controller.cpp b/src/core/hle/service/am/frontend/applet_controller.cpp index d457885773..66f52686d7 100644 --- a/src/core/hle/service/am/frontend/applet_controller.cpp +++ b/src/core/hle/service/am/frontend/applet_controller.cpp @@ -31,7 +31,7 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters( npad_style_set.raw = private_arg.style_set; return { - .min_players = (std::max)(s8{1}, header.player_count_min), + .min_players = std::max(s8{1}, header.player_count_min), .max_players = header.player_count_max, .keep_controllers_connected = header.enable_take_over_connection, .enable_single_mode = header.enable_single_mode, diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp index d99482a45c..5a787494a8 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.cpp @@ -18,7 +18,6 @@ IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& sys // clang-format off static const FunctionInfo functions[] = { {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, - {110, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxyEx"}, {200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"}, {201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"}, {300, nullptr, "OpenOverlayAppletProxy"}, @@ -26,7 +25,6 @@ IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& sys {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"}, {410, nullptr, "GetSystemAppletControllerForDebug"}, {450, D<&IAllSystemAppletProxiesService::GetSystemProcessCommonFunctions>, "GetSystemProcessCommonFunctions"}, // 19.0.0+ - {460, D<&IAllSystemAppletProxiesService::GetAppletAlternativeFunctions>, "GetAppletAlternativeFunctions"}, // 20.0.0+ {1000, nullptr, "GetDebugFunctions"}, }; // clang-format on @@ -101,14 +99,6 @@ Result IAllSystemAppletProxiesService::GetSystemProcessCommonFunctions() { R_SUCCEED(); } -Result IAllSystemAppletProxiesService::GetAppletAlternativeFunctions() { - LOG_DEBUG(Service_AM, "(STUBBED) called."); - - // TODO (maufeat) - - R_SUCCEED(); -} - std::shared_ptr IAllSystemAppletProxiesService::GetAppletFromProcessId( ProcessId process_id) { return m_window_system.GetByAppletResourceUserId(process_id.pid); diff --git a/src/core/hle/service/am/service/all_system_applet_proxies_service.h b/src/core/hle/service/am/service/all_system_applet_proxies_service.h index 525525c795..a3111c4c9b 100644 --- a/src/core/hle/service/am/service/all_system_applet_proxies_service.h +++ b/src/core/hle/service/am/service/all_system_applet_proxies_service.h @@ -39,7 +39,6 @@ private: InCopyHandle process_handle, InLargeData attribute); Result GetSystemProcessCommonFunctions(); - Result GetAppletAlternativeFunctions(); private: std::shared_ptr GetAppletFromProcessId(ProcessId pid); diff --git a/src/core/hle/service/am/service/applet_common_functions.cpp b/src/core/hle/service/am/service/applet_common_functions.cpp index 6a73a896f9..1c9cd74533 100644 --- a/src/core/hle/service/am/service/applet_common_functions.cpp +++ b/src/core/hle/service/am/service/applet_common_functions.cpp @@ -35,7 +35,6 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_, {310, nullptr, "IsSystemAppletHomeMenu"}, //19.0.0+ {320, nullptr, "SetGpuTimeSliceBoost"}, //19.0.0+ {321, nullptr, "SetGpuTimeSliceBoostDueToApplication"}, //19.0.0+ - {350, D<&IAppletCommonFunctions::Unknown350>, "Unknown350"} //20.0.0+ }; // clang-format on @@ -71,10 +70,4 @@ Result IAppletCommonFunctions::GetCurrentApplicationId(Out out_application_ R_SUCCEED(); } -Result IAppletCommonFunctions::Unknown350(Out out_unknown) { - LOG_WARNING(Service_AM, "(STUBBED) called"); - *out_unknown = 0; - R_SUCCEED(); -} - } // namespace Service::AM diff --git a/src/core/hle/service/am/service/applet_common_functions.h b/src/core/hle/service/am/service/applet_common_functions.h index 623efdb7fc..376f85acf7 100644 --- a/src/core/hle/service/am/service/applet_common_functions.h +++ b/src/core/hle/service/am/service/applet_common_functions.h @@ -20,7 +20,6 @@ private: Result GetHomeButtonDoubleClickEnabled(Out out_home_button_double_click_enabled); Result SetCpuBoostRequestPriority(s32 priority); Result GetCurrentApplicationId(Out out_application_id); - Result Unknown350(Out out_unknown); const std::shared_ptr applet; }; diff --git a/src/core/hle/service/am/service/application_accessor.cpp b/src/core/hle/service/am/service/application_accessor.cpp index 2ac07f838e..986abc716a 100644 --- a/src/core/hle/service/am/service/application_accessor.cpp +++ b/src/core/hle/service/am/service/application_accessor.cpp @@ -115,7 +115,7 @@ Result IApplicationAccessor::GetApplicationControlProperty( R_TRY(system.GetARPManager().GetControlProperty(&nacp, m_applet->program_id)); std::memcpy(out_control_property.data(), nacp.data(), - (std::min)(out_control_property.size(), nacp.size())); + std::min(out_control_property.size(), nacp.size())); R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/application_functions.cpp b/src/core/hle/service/am/service/application_functions.cpp index eacc345e15..560244c714 100644 --- a/src/core/hle/service/am/service/application_functions.cpp +++ b/src/core/hle/service/am/service/application_functions.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 @@ -88,7 +85,6 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ {181, nullptr, "UpgradeLaunchRequiredVersion"}, {190, nullptr, "SendServerMaintenanceOverlayNotification"}, {200, nullptr, "GetLastApplicationExitReason"}, - {210, D<&IApplicationFunctions::GetUnknownEvent210>, "Unknown210"}, {500, nullptr, "StartContinuousRecordingFlushForDebug"}, {1000, nullptr, "CreateMovieMaker"}, {1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"}, @@ -216,7 +212,7 @@ Result IApplicationFunctions::GetDisplayVersion(Out out_display_ if (res.first != nullptr) { const auto& version = res.first->GetVersionString(); std::memcpy(out_display_version->string.data(), version.data(), - (std::min)(version.size(), out_display_version->string.size())); + std::min(version.size(), out_display_version->string.size())); } else { static constexpr char default_version[]{"1.0.0"}; std::memcpy(out_display_version->string.data(), default_version, sizeof(default_version)); @@ -284,7 +280,7 @@ Result IApplicationFunctions::GetCacheStorageMax(Out out_cache_storage_inde R_TRY(system.GetARPManager().GetControlProperty(&nacp, m_applet->program_id)); auto raw_nacp = std::make_unique(); - std::memcpy(raw_nacp.get(), nacp.data(), (std::min)(sizeof(*raw_nacp), nacp.size())); + std::memcpy(raw_nacp.get(), nacp.data(), std::min(sizeof(*raw_nacp), nacp.size())); *out_cache_storage_index_max = static_cast(raw_nacp->cache_storage_max_index); *out_max_journal_size = static_cast(raw_nacp->cache_storage_data_and_journal_max_size); @@ -491,13 +487,6 @@ Result IApplicationFunctions::GetHealthWarningDisappearedSystemEvent( R_SUCCEED(); } -Result IApplicationFunctions::GetUnknownEvent210( - OutCopyHandle out_event) { - LOG_DEBUG(Service_AM, "called"); - *out_event = m_applet->unknown_event.GetHandle(); - R_SUCCEED(); -} - Result IApplicationFunctions::PrepareForJit() { LOG_WARNING(Service_AM, "(STUBBED) called"); diff --git a/src/core/hle/service/am/service/application_functions.h b/src/core/hle/service/am/service/application_functions.h index 35b3e9505d..10025a152b 100644 --- a/src/core/hle/service/am/service/application_functions.h +++ b/src/core/hle/service/am/service/application_functions.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 @@ -79,7 +76,6 @@ private: Result TryPopFromFriendInvitationStorageChannel(Out> out_storage); Result GetNotificationStorageChannelEvent(OutCopyHandle out_event); Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle out_event); - Result GetUnknownEvent210(OutCopyHandle out_event); Result PrepareForJit(); const std::shared_ptr m_applet; diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 54790838e0..413388d40a 100644 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -113,11 +113,9 @@ std::shared_ptr CreateGuestApplet(Core::System& system, Firmware1700 = 17, Firmware1800 = 18, Firmware1900 = 19, - Firmware2000 = 20, - Firmware2100 = 21, }; - auto process = CreateProcess(system, program_id, Firmware1400, Firmware2100); + auto process = CreateProcess(system, program_id, Firmware1400, Firmware1900); if (!process) { // Couldn't initialize the guest process return {}; diff --git a/src/core/hle/service/am/service/library_applet_self_accessor.cpp b/src/core/hle/service/am/service/library_applet_self_accessor.cpp index 091aadc9fc..cbe45189f8 100644 --- a/src/core/hle/service/am/service/library_applet_self_accessor.cpp +++ b/src/core/hle/service/am/service/library_applet_self_accessor.cpp @@ -162,7 +162,7 @@ Result ILibraryAppletSelfAccessor::GetMainAppletApplicationControlProperty( system.GetARPManager().GetControlProperty(&nacp, application.application_id); if (R_SUCCEEDED(result)) { - std::memcpy(out_nacp->data(), nacp.data(), (std::min)(nacp.size(), out_nacp->size())); + std::memcpy(out_nacp->data(), nacp.data(), std::min(nacp.size(), out_nacp->size())); } R_RETURN(result); diff --git a/src/core/hle/service/bcat/bcat_service.cpp b/src/core/hle/service/bcat/bcat_service.cpp index 5c23760113..63b1072d2a 100644 --- a/src/core/hle/service/bcat/bcat_service.cpp +++ b/src/core/hle/service/bcat/bcat_service.cpp @@ -102,7 +102,7 @@ Result IBcatService::SetPassphrase(u64 application_id, Passphrase passphrase{}; std::memcpy(passphrase.data(), passphrase_buffer.data(), - (std::min)(passphrase.size(), passphrase_buffer.size())); + std::min(passphrase.size(), passphrase_buffer.size())); backend.SetPassphrase(application_id, passphrase); R_SUCCEED(); diff --git a/src/core/hle/service/bcat/delivery_cache_directory_service.cpp b/src/core/hle/service/bcat/delivery_cache_directory_service.cpp index 31693cfc33..01f08a2fc5 100644 --- a/src/core/hle/service/bcat/delivery_cache_directory_service.cpp +++ b/src/core/hle/service/bcat/delivery_cache_directory_service.cpp @@ -15,7 +15,7 @@ namespace Service::BCAT { static BcatDigest DigestFile(const FileSys::VirtualFile& file) { BcatDigest out{}; const auto bytes = file->ReadAllBytes(); - mbedtls_md5(bytes.data(), bytes.size(), out.data()); + mbedtls_md5_ret(bytes.data(), bytes.size(), out.data()); return out; } @@ -57,12 +57,12 @@ Result IDeliveryCacheDirectoryService::Read( R_UNLESS(current_dir != nullptr, ResultNoOpenEntry); const auto files = current_dir->GetFiles(); - *out_count = static_cast((std::min)(files.size(), out_buffer.size())); + *out_count = static_cast(std::min(files.size(), out_buffer.size())); std::transform(files.begin(), files.begin() + *out_count, out_buffer.begin(), [](const auto& file) { FileName name{}; std::memcpy(name.data(), file->GetName().data(), - (std::min)(file->GetName().size(), name.size())); + std::min(file->GetName().size(), name.size())); return DeliveryCacheDirectoryEntry{name, file->GetSize(), DigestFile(file)}; }); R_SUCCEED(); diff --git a/src/core/hle/service/bcat/delivery_cache_storage_service.cpp b/src/core/hle/service/bcat/delivery_cache_storage_service.cpp index 0ce798eb75..4c79d71f41 100644 --- a/src/core/hle/service/bcat/delivery_cache_storage_service.cpp +++ b/src/core/hle/service/bcat/delivery_cache_storage_service.cpp @@ -47,7 +47,7 @@ Result IDeliveryCacheStorageService::EnumerateDeliveryCacheDirectory( LOG_DEBUG(Service_BCAT, "called, size={:016X}", out_directories.size()); *out_directory_count = - static_cast((std::min)(out_directories.size(), entries.size() - next_read_index)); + static_cast(std::min(out_directories.size(), entries.size() - next_read_index)); memcpy(out_directories.data(), entries.data() + next_read_index, *out_directory_count * sizeof(DirectoryName)); next_read_index += *out_directory_count; diff --git a/src/core/hle/service/cmif_serialization.h b/src/core/hle/service/cmif_serialization.h index 03b2a130a1..5a5f610f34 100644 --- a/src/core/hle/service/cmif_serialization.h +++ b/src/core/hle/service/cmif_serialization.h @@ -304,7 +304,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE buffer = ctx.ReadBufferX(InBufferIndex); } - std::memcpy(&std::get(args), buffer.data(), (std::min)(BufferSize, buffer.size())); + std::memcpy(&std::get(args), buffer.data(), std::min(BufferSize, buffer.size())); return ReadInArgument(is_domain, args, raw_data, ctx, temp); } else if constexpr (ArgumentTraits::Type == ArgumentType::InBuffer) { diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index 9ad8d0e9b5..9eaae4c4bd 100644 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp @@ -203,7 +203,7 @@ private: std::transform(tickets.begin(), tickets.end(), std::back_inserter(ids), [](const auto& pair) { return pair.first; }); - out_entries = (std::min)(ids.size(), out_entries); + out_entries = std::min(ids.size(), out_entries); ctx.WriteBuffer(ids.data(), out_entries * sizeof(u128)); IPC::ResponseBuilder rb{ctx, 3}; @@ -225,7 +225,7 @@ private: std::transform(tickets.begin(), tickets.end(), std::back_inserter(ids), [](const auto& pair) { return pair.first; }); - out_entries = (std::min)(ids.size(), out_entries); + out_entries = std::min(ids.size(), out_entries); ctx.WriteBuffer(ids.data(), out_entries * sizeof(u128)); IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp b/src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp index 490ac49d42..ff823586b3 100644 --- a/src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp +++ b/src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp @@ -44,7 +44,7 @@ Result ISaveDataInfoReader::ReadSaveDataInfo( const u64 count_entries = out_entries.size(); // Cap at total number of entries. - const u64 actual_entries = (std::min)(count_entries, info.size() - next_entry_index); + const u64 actual_entries = std::min(count_entries, info.size() - next_entry_index); // Determine data start and end const auto* begin = reinterpret_cast(info.data() + next_entry_index); diff --git a/src/core/hle/service/glue/notif.cpp b/src/core/hle/service/glue/notif.cpp index dd3f1954de..5a03d34c12 100644 --- a/src/core/hle/service/glue/notif.cpp +++ b/src/core/hle/service/glue/notif.cpp @@ -67,7 +67,7 @@ Result NotificationServiceImpl::ListAlarmSettings(s32* out_count, std::span out_alarms) { LOG_INFO(Service_NOTIF, "called, alarm_count={}", alarms.size()); - const auto count = (std::min)(out_alarms.size(), alarms.size()); + const auto count = std::min(out_alarms.size(), alarms.size()); for (size_t i = 0; i < count; i++) { out_alarms[i] = alarms[i]; } @@ -90,7 +90,7 @@ Result NotificationServiceImpl::LoadApplicationParameter(u32* out_size, LOG_WARNING(Service_NOTIF, "(STUBBED) called, alarm_setting_id={}", alarm_setting_id); std::memcpy(out_application_parameter.data(), application_parameter.data(), - (std::min)(sizeof(application_parameter), out_application_parameter.size())); + std::min(sizeof(application_parameter), out_application_parameter.size())); *out_size = static_cast(application_parameter.size()); R_SUCCEED(); diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp index bfe57999c8..77bf8896cd 100644 --- a/src/core/hle/service/glue/time/manager.cpp +++ b/src/core/hle/service/glue/time/manager.cpp @@ -29,7 +29,7 @@ static s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) { }; s16 month_s16{calendar.month}; - s8 month{static_cast(((month_s16 * 43) & ~(std::numeric_limits::max)()) + + s8 month{static_cast(((month_s16 * 43) & ~std::numeric_limits::max()) + ((month_s16 * 43) >> 9))}; s8 month_index{static_cast(calendar.month - 12 * month)}; if (month_index == 0) { @@ -71,13 +71,13 @@ static Service::PSC::Time::LocationName GetTimeZoneString( Service::PSC::Time::LocationName configured_name{}; std::memcpy(configured_name.data(), configured_zone.data(), - (std::min)(configured_name.size(), configured_zone.size())); + std::min(configured_name.size(), configured_zone.size())); if (!time_zone_binary.IsValid(configured_name)) { configured_zone = Common::TimeZone::FindSystemTimeZone(); configured_name = {}; std::memcpy(configured_name.data(), configured_zone.data(), - (std::min)(configured_name.size(), configured_zone.size())); + std::min(configured_name.size(), configured_zone.size())); } ASSERT_MSG(time_zone_binary.IsValid(configured_name), "Invalid time zone {}!", diff --git a/src/core/hle/service/hid/hid_debug_server.cpp b/src/core/hle/service/hid/hid_debug_server.cpp index 450c1e953f..738c6d9ae2 100644 --- a/src/core/hle/service/hid/hid_debug_server.cpp +++ b/src/core/hle/service/hid/hid_debug_server.cpp @@ -178,7 +178,7 @@ Result IHidDebugServer::SetTouchScreenAutoPilotState( AutoPilotState auto_pilot{}; auto_pilot.count = - static_cast((std::min)(auto_pilot_buffer.size(), auto_pilot.state.size())); + static_cast(std::min(auto_pilot_buffer.size(), auto_pilot.state.size())); memcpy(auto_pilot.state.data(), auto_pilot_buffer.data(), auto_pilot.count * sizeof(TouchState)); diff --git a/src/core/hle/service/jit/jit_context.cpp b/src/core/hle/service/jit/jit_context.cpp index 06a2368fe5..0090e8568d 100644 --- a/src/core/hle/service/jit/jit_context.cpp +++ b/src/core/hle/service/jit/jit_context.cpp @@ -107,7 +107,7 @@ public: void AddTicks(u64 ticks) override {} u64 GetTicksRemaining() override { - return (std::numeric_limits::max)(); + return std::numeric_limits::max(); } u64 GetCNTPCT() override { return 0; diff --git a/src/core/hle/service/ldn/ldn_types.h b/src/core/hle/service/ldn/ldn_types.h index 56a3cd1b4b..fa0cdcbfa7 100644 --- a/src/core/hle/service/ldn/ldn_types.h +++ b/src/core/hle/service/ldn/ldn_types.h @@ -170,7 +170,7 @@ struct Ssid { Ssid() = default; constexpr explicit Ssid(std::string_view data) { - length = static_cast((std::min)(data.size(), SsidLengthMax)); + length = static_cast(std::min(data.size(), SsidLengthMax)); raw = {}; data.copy(raw.data(), length); raw[length] = 0; diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index 508f91546d..20df002330 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp @@ -180,7 +180,7 @@ private: if (length == 0) { return std::nullopt; } - const auto length_to_read = (std::min)(length, data.size() - offset); + const auto length_to_read = std::min(length, data.size() - offset); std::string output(length_to_read, '\0'); std::memcpy(output.data(), data.data() + offset, length_to_read); diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index c026d47e86..30eab469a1 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -978,7 +978,7 @@ Result NfcDevice::GetApplicationArea(std::span data) const { } memcpy(data.data(), tag_data.application_area.data(), - (std::min)(data.size(), sizeof(NFP::ApplicationArea))); + std::min(data.size(), sizeof(NFP::ApplicationArea))); return ResultSuccess; } diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 7d43677c6f..4710167364 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -33,10 +32,8 @@ #undef interface #include #pragma pop_macro("interface") -#ifdef _MSC_VER #pragma comment(lib, "wlanapi.lib") #endif -#endif namespace { @@ -616,7 +613,7 @@ void IGeneralService::EnumerateNetworkInterfaces(HLERequestContext& ctx) { const size_t guest_bytes = ctx.GetWriteBufferSize(); if (guest_bytes && !blob.empty()) - ctx.WriteBuffer(blob.data(), (std::min)(guest_bytes, blob.size())); + ctx.WriteBuffer(blob.data(), std::min(guest_bytes, blob.size())); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); @@ -642,7 +639,7 @@ void IGeneralService::EnumerateNetworkProfiles(HLERequestContext& ctx) { const size_t guest_sz = ctx.GetWriteBufferSize(); if (guest_sz && uuids.size()) { - const size_t to_copy = (std::min)(guest_sz, uuids.size() * sizeof(u128)); + const size_t to_copy = std::min(guest_sz, uuids.size() * sizeof(u128)); ctx.WriteBuffer(uuids.data(), to_copy); } diff --git a/src/core/hle/service/ns/application_manager_interface.cpp b/src/core/hle/service/ns/application_manager_interface.cpp index 60ecd5c2b9..f1ddba8231 100644 --- a/src/core/hle/service/ns/application_manager_interface.cpp +++ b/src/core/hle/service/ns/application_manager_interface.cpp @@ -306,9 +306,6 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_ {3013, nullptr, "IsGameCardEnabled"}, {3014, nullptr, "IsLocalContentShareEnabled"}, {3050, nullptr, "ListAssignELicenseTaskResult"}, - {4022, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4022"}, - {4023, D<&IApplicationManagerInterface::Unknown4023>, "Unknown4023"}, - {4088, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4088"}, {9999, nullptr, "GetApplicationCertificate"}, }; // clang-format on @@ -410,7 +407,7 @@ Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled( Result IApplicationManagerInterface::GetApplicationView( OutArray out_application_views, InArray application_ids) { - const auto size = (std::min)(out_application_views.size(), application_ids.size()); + const auto size = std::min(out_application_views.size(), application_ids.size()); LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size()); for (size_t i = 0; i < size; i++) { @@ -428,7 +425,7 @@ Result IApplicationManagerInterface::GetApplicationView( Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo( OutArray out_application_views, InArray application_ids) { - const auto size = (std::min)(out_application_views.size(), application_ids.size()); + const auto size = std::min(out_application_views.size(), application_ids.size()); LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size()); for (size_t i = 0; i < size; i++) { @@ -526,17 +523,4 @@ Result IApplicationManagerInterface::GetApplicationTerminateResult(Out o R_SUCCEED(); } -Result IApplicationManagerInterface::Unknown4022( - OutCopyHandle out_event) { - LOG_WARNING(Service_NS, "(STUBBED) called"); - *out_event = gamecard_update_detection_event.GetHandle(); - R_SUCCEED(); -} - -Result IApplicationManagerInterface::Unknown4023(Out out_result) { - LOG_WARNING(Service_NS, "(STUBBED) called."); - *out_result = 0; - R_SUCCEED(); -} - } // namespace Service::NS diff --git a/src/core/hle/service/ns/application_manager_interface.h b/src/core/hle/service/ns/application_manager_interface.h index 251f93ee06..2def50bd5c 100644 --- a/src/core/hle/service/ns/application_manager_interface.h +++ b/src/core/hle/service/ns/application_manager_interface.h @@ -53,8 +53,6 @@ public: u64 application_id); Result CheckApplicationLaunchVersion(u64 application_id); Result GetApplicationTerminateResult(Out out_result, u64 application_id); - Result Unknown4022(OutCopyHandle out_event); - Result Unknown4023(Out out_result); private: KernelHelpers::ServiceContext service_context; diff --git a/src/core/hle/service/ns/platform_service_manager.cpp b/src/core/hle/service/ns/platform_service_manager.cpp index 301cf4ac4f..23cf05005c 100644 --- a/src/core/hle/service/ns/platform_service_manager.cpp +++ b/src/core/hle/service/ns/platform_service_manager.cpp @@ -254,7 +254,7 @@ Result IPlatformServiceManager::GetSharedFontInOrderOfPriority( constexpr size_t MaxElementCount = 6; // TODO(ogniK): Have actual priority order - const auto max_size = (std::min)({MaxElementCount, out_font_codes.size(), out_font_offsets.size(), + const auto max_size = std::min({MaxElementCount, out_font_codes.size(), out_font_offsets.size(), out_font_sizes.size(), impl->shared_font_regions.size()}); for (size_t i = 0; i < max_size; i++) { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 140c6eb6e3..02913a5817 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -504,7 +504,7 @@ NvResult nvhost_as_gpu::GetVARegions3(IoctlGetVaRegions& params, std::span(std::countr_zero(YUZU_PAGESIZE))}; + static constexpr u32 PAGE_SIZE_BITS{std::countr_zero(YUZU_PAGESIZE)}; static constexpr u32 SUPPORTED_BIG_PAGE_SIZES{0x30000}; static constexpr u32 DEFAULT_BIG_PAGE_SIZE{0x20000}; u32 big_page_size{DEFAULT_BIG_PAGE_SIZE}; - u32 big_page_size_bits{static_cast(std::countr_zero(DEFAULT_BIG_PAGE_SIZE))}; + u32 big_page_size_bits{std::countr_zero(DEFAULT_BIG_PAGE_SIZE)}; static constexpr u32 VA_START_SHIFT{10}; static constexpr u64 DEFAULT_VA_SPLIT{1ULL << 34}; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 5f754650d9..95bf18dbf7 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -219,55 +219,28 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx& params, DeviceFD fd) { return NvResult::Success; } -s32_le nvhost_gpu::GetObjectContextClassNumberIndex(CtxClasses class_number) { - constexpr s32_le invalid_class_number_index = -1; - switch (class_number) { - case CtxClasses::Ctx2D: return 0; - case CtxClasses::Ctx3D: return 1; - case CtxClasses::CtxCompute: return 2; - case CtxClasses::CtxKepler: return 3; - case CtxClasses::CtxDMA: return 4; - case CtxClasses::CtxChannelGPFIFO: return 5; - default: return invalid_class_number_index; - } -} - NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) { - LOG_DEBUG(Service_NVDRV, "called, class_num={:#X}, flags={:#X}, obj_id={:#X}", params.class_num, - params.flags, params.obj_id); + LOG_DEBUG(Service_NVDRV, "called, class_num={:X}, flags={:X}, obj_id={:X}", params.class_num, + params.flags, params.obj_id); - if (!channel_state || !channel_state->initialized) { + if (!channel_state->initialized) { LOG_CRITICAL(Service_NVDRV, "No address space bound to allocate a object context!"); return NvResult::NotInitialized; } - std::scoped_lock lk(channel_mutex); - - if (params.flags) { - LOG_WARNING(Service_NVDRV, "non-zero flags={:#X} for class={:#X}", params.flags, - params.class_num); - - constexpr u32 allowed_mask{}; - params.flags = allowed_mask; - } - - s32_le ctx_class_number_index = - GetObjectContextClassNumberIndex(static_cast(params.class_num)); - if (ctx_class_number_index < 0) { - LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:#X}", - params.class_num); + switch (static_cast(params.class_num)) { + case CtxClasses::Ctx2D: + case CtxClasses::Ctx3D: + case CtxClasses::CtxCompute: + case CtxClasses::CtxKepler: + case CtxClasses::CtxDMA: + case CtxClasses::CtxChannelGPFIFO: + ctxObj_params.push_back(params); + return NvResult::Success; + default: + LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:X}", params.class_num); return NvResult::BadParameter; } - - if (ctxObjs[ctx_class_number_index].has_value()) { - LOG_ERROR(Service_NVDRV, "Object context for class {:#X} already allocated on this channel", - params.class_num); - return NvResult::AlreadyAllocated; - } - - ctxObjs[ctx_class_number_index] = params; - - return NvResult::Success; } static boost::container::small_vector BuildWaitCommandList( diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index fb0a5be959..a017cc50d0 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -172,7 +172,7 @@ private: s32_le nvmap_fd{}; u64_le user_data{}; IoctlZCullBind zcull_params{}; - std::array, 6> ctxObjs{}; + std::vector ctxObj_params{}; u32_le channel_priority{}; u32_le channel_timeslice{}; @@ -184,12 +184,9 @@ private: NvResult SetChannelPriority(IoctlChannelSetPriority& params); NvResult AllocGPFIFOEx(IoctlAllocGpfifoEx& params, DeviceFD fd); NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx& params, DeviceFD fd); - - s32_le GetObjectContextClassNumberIndex(CtxClasses class_number); NvResult AllocateObjectContext(IoctlAllocObjCtx& params); NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries); - NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, std::span commands, bool kickoff = false); NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, 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 fa46c2f280..9ca6308e6f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -139,7 +139,7 @@ NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) { NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span entries, DeviceFD fd) { - const size_t num_entries = (std::min)(params.num_entries, static_cast(entries.size())); + const size_t num_entries = std::min(params.num_entries, static_cast(entries.size())); for (size_t i = 0; i < num_entries; i++) { DAddr pin_address = nvmap.PinHandle(entries[i].map_handle, true); entries[i].map_address = static_cast(pin_address); @@ -150,7 +150,7 @@ NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span entries) { - const size_t num_entries = (std::min)(params.num_entries, static_cast(entries.size())); + const size_t num_entries = std::min(params.num_entries, static_cast(entries.size())); for (size_t i = 0; i < num_entries; i++) { nvmap.UnpinHandle(entries[i].map_handle); entries[i] = {}; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index 2913d25819..91ba35aef5 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -100,18 +97,18 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, slots[slot].needs_cleanup_on_release = false; slots[slot].buffer_state = BufferState::Acquired; - // Mark tracked buffer history records as acquired - for (auto& buffer_history_record : core->buffer_history) { - if (buffer_history_record.frame_number == core->frame_counter) { - buffer_history_record.state = BufferState::Acquired; - break; - } - } - // TODO: for now, avoid resetting the fence, so that when we next return this // slot to the producer, it will wait for the fence to pass. We should fix this // by properly waiting for the fence in the BufferItemConsumer. // slots[slot].fence = Fence::NoFence(); + + const auto target_frame_number = slots[slot].frame_number; + for (size_t i = 0; i < core->history.size(); i++) { + if (core->history[i].frame_number == target_frame_number) { + core->history[i].state = BufferState::Acquired; + break; + } + } } // If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to @@ -331,7 +328,7 @@ void BufferQueueConsumer::Transact(u32 code, std::span parcel_data, const auto serialized = parcel_out.Serialize(); std::memcpy(parcel_reply.data(), serialized.data(), - (std::min)(parcel_reply.size(), serialized.size())); + std::min(parcel_reply.size(), serialized.size())); } Kernel::KReadableEvent* BufferQueueConsumer::GetNativeHandle(u32 type_id) { diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp index 6120d8eae1..30095b0f73 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -13,18 +10,11 @@ namespace Service::android { -BufferQueueCore::BufferQueueCore() = default; -BufferQueueCore::~BufferQueueCore() = default; +BufferQueueCore::BufferQueueCore() { + history.resize(8); +}; -void BufferQueueCore::PushHistory(u64 frame_number, s64 queue_time, s64 presentation_time, BufferState state) { - buffer_history_pos = (buffer_history_pos + 1) % BUFFER_HISTORY_SIZE; - buffer_history[buffer_history_pos] = BufferHistoryInfo{ - .frame_number = frame_number, - .queue_time = queue_time, - .presentation_time = presentation_time, - .state = state, - }; -} +BufferQueueCore::~BufferQueueCore() = default; void BufferQueueCore::SignalDequeueCondition() { dequeue_possible.store(true); diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.h b/src/core/hle/service/nvnflinger/buffer_queue_core.h index ed7d4b4069..341634352b 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -18,7 +15,6 @@ #include "core/hle/service/nvnflinger/buffer_item.h" #include "core/hle/service/nvnflinger/buffer_queue_defs.h" -#include "core/hle/service/nvnflinger/buffer_slot.h" #include "core/hle/service/nvnflinger/pixel_format.h" #include "core/hle/service/nvnflinger/status.h" #include "core/hle/service/nvnflinger/window.h" @@ -27,19 +23,22 @@ namespace Service::android { #ifdef _MSC_VER #pragma pack(push, 1) -struct BufferHistoryInfo { -#elif defined(__GNUC__) || defined(__clang__) -struct __attribute__((packed)) BufferHistoryInfo { #endif +struct BufferInfo { u64 frame_number; s64 queue_time; - s64 presentation_time; - BufferState state; -}; + s64 presentation_time{}; + BufferState state{BufferState::Free}; +} +#if defined(__GNUC__) || defined(__clang__) +__attribute__((packed)) +#endif +; #ifdef _MSC_VER #pragma pack(pop) #endif -static_assert(sizeof(BufferHistoryInfo) == 0x1C, "BufferHistoryInfo must be 28 bytes"); +static_assert(sizeof(BufferInfo) == 0x1C, + "BufferInfo is an invalid size"); class IConsumerListener; class IProducerListener; @@ -50,13 +49,10 @@ class BufferQueueCore final { public: static constexpr s32 INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT; - static constexpr u32 BUFFER_HISTORY_SIZE = 8; BufferQueueCore(); ~BufferQueueCore(); - void PushHistory(u64 frame_number, s64 queue_time, s64 presentation_time, BufferState state); - private: void SignalDequeueCondition(); bool WaitForDequeueCondition(std::unique_lock& lk); @@ -92,11 +88,11 @@ private: const s32 max_acquired_buffer_count{}; // This is always zero on HOS bool buffer_has_been_queued{}; u64 frame_counter{}; - std::array buffer_history{}; - u32 buffer_history_pos{BUFFER_HISTORY_SIZE-1}; u32 transform_hint{}; bool is_allocating{}; mutable std::condition_variable_any is_allocating_condition; + + std::vector history{8}; }; } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index bc3076d20b..1bb88a45fa 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -533,6 +530,11 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, item.is_droppable = core->dequeue_buffer_cannot_block || async; item.swap_interval = swap_interval; + position = (position + 1) % 8; + core->history[position] = {.frame_number = core->frame_counter, + .queue_time = slots[slot].queue_time, + .state = BufferState::Queued}; + sticky_transform = sticky_transform_; if (core->queue.empty()) { @@ -549,15 +551,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, // mark it as freed if (core->StillTracking(*front)) { slots[front->slot].buffer_state = BufferState::Free; - - // Mark tracked buffer history records as free - for (auto& buffer_history_record : core->buffer_history) { - if (buffer_history_record.frame_number == front->frame_number) { - buffer_history_record.state = BufferState::Free; - break; - } - } - // Reset the frame number of the freed buffer so that it is the first in line to // be dequeued again slots[front->slot].frame_number = 0; @@ -571,7 +564,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, } } - core->PushHistory(core->frame_counter, slots[slot].queue_time, slots[slot].presentation_time, BufferState::Queued); core->buffer_has_been_queued = true; core->SignalDequeueCondition(); output->Inflate(core->default_width, core->default_height, core->transform_hint, @@ -946,46 +938,33 @@ void BufferQueueProducer::Transact(u32 code, std::span parcel_data, break; } case TransactionId::GetBufferHistory: { - LOG_DEBUG(Service_Nvnflinger, "called, transaction=GetBufferHistory"); + LOG_WARNING(Service_Nvnflinger, "called, transaction=GetBufferHistory"); - const s32 request = parcel_in.Read(); - if (request <= 0) { + std::scoped_lock lock{core->mutex}; + + auto buffer_history_count = std::min(parcel_in.Read(), (s32)core->history.size()); + + if (buffer_history_count <= 0) { parcel_out.Write(Status::BadValue); parcel_out.Write(0); + status = Status::None; break; } - constexpr u32 history_max = BufferQueueCore::BUFFER_HISTORY_SIZE; - std::array buffer_history_snapshot{}; - s32 valid_index{}; - { - std::scoped_lock lk(core->mutex); - - const u32 current_history_pos = core->buffer_history_pos; - u32 index_reversed{}; - for (u32 i = 0; i < history_max; ++i) { - // Wrap values backwards e.g. 7, 6, 5, etc. in the range of 0-7 - index_reversed = (current_history_pos + history_max - i) % history_max; - const auto& current_history_buffer = core->buffer_history[index_reversed]; - - // Here we use the frame number as a terminator. - // Because a buffer without frame_number is not considered complete - if (current_history_buffer.frame_number == 0) { - break; - } - - buffer_history_snapshot[valid_index] = current_history_buffer; - ++valid_index; - } + auto info = new BufferInfo[buffer_history_count]; + auto pos = position; + for (int i = 0; i < buffer_history_count; i++) { + info[i] = core->history[(pos - i) % core->history.size()]; + LOG_WARNING(Service_Nvnflinger, "frame_number={}, state={}", + core->history[(pos - i) % core->history.size()].frame_number, + (u32)core->history[(pos - i) % core->history.size()].state); + pos--; } - const s32 limit = std::min(request, valid_index); parcel_out.Write(Status::NoError); - parcel_out.Write(limit); - for (s32 i = 0; i < limit; ++i) { - parcel_out.Write(buffer_history_snapshot[i]); - } - + parcel_out.Write(buffer_history_count); + parcel_out.WriteFlattenedObject(info); + status = Status::None; break; } default: @@ -993,11 +972,13 @@ void BufferQueueProducer::Transact(u32 code, std::span parcel_data, break; } - parcel_out.Write(status); + if (status != Status::None) { + parcel_out.Write(status); + } const auto serialized = parcel_out.Serialize(); std::memcpy(parcel_reply.data(), serialized.data(), - (std::min)(parcel_reply.size(), serialized.size())); + std::min(parcel_reply.size(), serialized.size())); } diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 6610e0853a..28195cd3c5 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h index d348b331cb..5b5cbb6fbd 100644 --- a/src/core/hle/service/nvnflinger/buffer_slot.h +++ b/src/core/hle/service/nvnflinger/buffer_slot.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -18,7 +15,7 @@ namespace Service::android { class GraphicBuffer; -enum class BufferState : u32 { +enum class BufferState : s32 { Free = 0, Dequeued = 1, Queued = 2, diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp index a262a3dcd5..77622a7832 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.cpp +++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp @@ -4,8 +4,6 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include - #include #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" @@ -103,7 +101,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display, // only swap intervals of 0, 1 and 2 have been observed, but if 3 were // to be introduced, this would cause an issue. if (swap_interval) { - swap_interval = (std::min)(*swap_interval, item_swap_interval); + swap_interval = std::min(*swap_interval, item_swap_interval); } else { swap_interval = item_swap_interval; } diff --git a/src/core/hle/service/pctl/parental_control_service.cpp b/src/core/hle/service/pctl/parental_control_service.cpp index 82c65ac1fd..1d990e66d7 100644 --- a/src/core/hle/service/pctl/parental_control_service.cpp +++ b/src/core/hle/service/pctl/parental_control_service.cpp @@ -80,12 +80,11 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili {1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"}, {1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"}, {1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"}, - {1454, D<&IParentalControlService::GetPlayTimerRemainingTime>, "GetPlayTimerRemainingTime"}, + {1454, nullptr, "GetPlayTimerRemainingTime"}, {1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"}, {1456, D<&IParentalControlService::GetPlayTimerSettingsOld>, "GetPlayTimerSettingsOld"}, {1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"}, {1458, D<&IParentalControlService::IsPlayTimerAlarmDisabled>, "IsPlayTimerAlarmDisabled"}, - {1459, D<&IParentalControlService::GetPlayTimerRemainingTimeDisplayInfo>, "GetPlayTimerRemainingTimeDisplayInfo"}, {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"}, {1472, nullptr, "CancelNetworkRequest"}, {1473, D<&IParentalControlService::GetUnlinkedEvent>, "GetUnlinkedEvent"}, @@ -379,12 +378,6 @@ Result IParentalControlService::IsPlayTimerEnabled(Out out_is_play_timer_e R_SUCCEED(); } -Result IParentalControlService::GetPlayTimerRemainingTime(Out out_remaining_time) { - LOG_WARNING(Service_PCTL, "(STUBBED) called"); - *out_remaining_time = std::numeric_limits::max(); - R_SUCCEED(); -} - Result IParentalControlService::IsRestrictedByPlayTimer(Out out_is_restricted_by_play_timer) { *out_is_restricted_by_play_timer = false; LOG_WARNING(Service_PCTL, "(STUBBED) called, restricted={}", *out_is_restricted_by_play_timer); @@ -419,11 +412,6 @@ Result IParentalControlService::IsPlayTimerAlarmDisabled(Out out_play_time R_SUCCEED(); } -Result IParentalControlService::GetPlayTimerRemainingTimeDisplayInfo(/* Out 0x18 */) { - LOG_INFO(Service_PCTL, "called"); - R_SUCCEED(); -} - Result IParentalControlService::GetUnlinkedEvent(OutCopyHandle out_event) { LOG_INFO(Service_PCTL, "called"); *out_event = unlinked_event.GetHandle(); diff --git a/src/core/hle/service/pctl/parental_control_service.h b/src/core/hle/service/pctl/parental_control_service.h index 9d143fe2e2..1b1884c4de 100644 --- a/src/core/hle/service/pctl/parental_control_service.h +++ b/src/core/hle/service/pctl/parental_control_service.h @@ -49,12 +49,10 @@ private: Result StartPlayTimer(); Result StopPlayTimer(); Result IsPlayTimerEnabled(Out out_is_play_timer_enabled); - Result GetPlayTimerRemainingTime(Out out_remaining_time); Result IsRestrictedByPlayTimer(Out out_is_restricted_by_play_timer); Result GetPlayTimerSettingsOld(Out out_play_timer_settings); Result GetPlayTimerEventToRequestSuspension(OutCopyHandle out_event); Result IsPlayTimerAlarmDisabled(Out out_play_timer_alarm_disabled); - Result GetPlayTimerRemainingTimeDisplayInfo(); Result GetUnlinkedEvent(OutCopyHandle out_event); Result GetStereoVisionRestriction(Out out_stereo_vision_restriction); Result SetStereoVisionRestriction(bool stereo_vision_restriction); diff --git a/src/core/hle/service/psc/time/common.h b/src/core/hle/service/psc/time/common.h index 0ad2ed51f8..954aed666a 100644 --- a/src/core/hle/service/psc/time/common.h +++ b/src/core/hle/service/psc/time/common.h @@ -138,12 +138,12 @@ constexpr inline std::chrono::nanoseconds ConvertToTimeSpan(s64 ticks) { std::chrono::duration_cast(std::chrono::seconds(1)).count()}; constexpr s64 max{Common::WallClock::CNTFRQ * - ((std::numeric_limits::max)() / one_second_ns)}; + (std::numeric_limits::max() / one_second_ns)}; if (ticks > max) { - return std::chrono::nanoseconds((std::numeric_limits::max)()); + return std::chrono::nanoseconds(std::numeric_limits::max()); } else if (ticks < -max) { - return std::chrono::nanoseconds((std::numeric_limits::min)()); + return std::chrono::nanoseconds(std::numeric_limits::min()); } auto a{ticks / Common::WallClock::CNTFRQ * one_second_ns}; @@ -156,9 +156,9 @@ constexpr inline Result GetSpanBetweenTimePoints(s64* out_seconds, const SteadyC const SteadyClockTimePoint& b) { R_UNLESS(out_seconds, ResultInvalidArgument); R_UNLESS(a.IdMatches(b), ResultInvalidArgument); - R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + (std::numeric_limits::max)(), + R_UNLESS(a.time_point >= 0 || b.time_point <= a.time_point + std::numeric_limits::max(), ResultOverflow); - R_UNLESS(a.time_point < 0 || b.time_point >= a.time_point + (std::numeric_limits::min)(), + R_UNLESS(a.time_point < 0 || b.time_point >= a.time_point + std::numeric_limits::min(), ResultOverflow); *out_seconds = b.time_point - a.time_point; diff --git a/src/core/hle/service/psc/time/power_state_request_manager.cpp b/src/core/hle/service/psc/time/power_state_request_manager.cpp index 15fe8e2918..17de0bf4dd 100644 --- a/src/core/hle/service/psc/time/power_state_request_manager.cpp +++ b/src/core/hle/service/psc/time/power_state_request_manager.cpp @@ -17,7 +17,7 @@ PowerStateRequestManager::~PowerStateRequestManager() { void PowerStateRequestManager::UpdatePendingPowerStateRequestPriority(u32 priority) { std::scoped_lock l{m_mutex}; if (m_has_pending_request) { - m_pending_request_priority = (std::max)(m_pending_request_priority, priority); + m_pending_request_priority = std::max(m_pending_request_priority, priority); } else { m_pending_request_priority = priority; m_has_pending_request = true; diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp index 600d0ec4fd..3d3ad2d62c 100644 --- a/src/core/hle/service/ro/ro.cpp +++ b/src/core/hle/service/ro/ro.cpp @@ -178,7 +178,7 @@ struct ProcessContext { std::vector nro_data(size); m_process->GetMemory().ReadBlock(base_address, nro_data.data(), size); - mbedtls_sha256(nro_data.data(), size, hash.data(), 0); + mbedtls_sha256_ret(nro_data.data(), size, hash.data(), 0); } for (size_t i = 0; i < MaxNrrInfos; i++) { diff --git a/src/core/hle/service/set/settings_server.cpp b/src/core/hle/service/set/settings_server.cpp index 7d1869a4e8..aa873bc8c5 100644 --- a/src/core/hle/service/set/settings_server.cpp +++ b/src/core/hle/service/set/settings_server.cpp @@ -122,8 +122,8 @@ Result ISettingsServer::GetAvailableLanguageCodes( Out out_count, OutArray out_language_codes) { LOG_DEBUG(Service_SET, "called"); - const std::size_t max_amount = (std::min)(PRE_4_0_0_MAX_ENTRIES, out_language_codes.size()); - *out_count = static_cast((std::min)(available_language_codes.size(), max_amount)); + const std::size_t max_amount = std::min(PRE_4_0_0_MAX_ENTRIES, out_language_codes.size()); + *out_count = static_cast(std::min(available_language_codes.size(), max_amount)); memcpy(out_language_codes.data(), available_language_codes.data(), static_cast(*out_count) * sizeof(LanguageCode)); @@ -159,8 +159,8 @@ Result ISettingsServer::GetAvailableLanguageCodes2( Out out_count, OutArray language_codes) { LOG_DEBUG(Service_SET, "called"); - const std::size_t max_amount = (std::min)(POST_4_0_0_MAX_ENTRIES, language_codes.size()); - *out_count = static_cast((std::min)(available_language_codes.size(), max_amount)); + const std::size_t max_amount = std::min(POST_4_0_0_MAX_ENTRIES, language_codes.size()); + *out_count = static_cast(std::min(available_language_codes.size(), max_amount)); memcpy(language_codes.data(), available_language_codes.data(), static_cast(*out_count) * sizeof(LanguageCode)); @@ -233,7 +233,7 @@ Result ISettingsServer::GetDeviceNickName( LOG_DEBUG(Service_SET, "called"); const std::size_t string_size = - (std::min)(Settings::values.device_name.GetValue().size(), out_device_name->size()); + std::min(Settings::values.device_name.GetValue().size(), out_device_name->size()); *out_device_name = {}; memcpy(out_device_name->data(), Settings::values.device_name.GetValue().data(), string_size); diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index c70fdea24b..d246b95d0e 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -533,7 +533,7 @@ Result ISystemSettingsServer::GetEulaVersions( LOG_INFO(Service_SET, "called, elements={}", m_system_settings.eula_version_count); *out_count = - (std::min)(m_system_settings.eula_version_count, static_cast(out_eula_versions.size())); + std::min(m_system_settings.eula_version_count, static_cast(out_eula_versions.size())); memcpy(out_eula_versions.data(), m_system_settings.eula_versions.data(), static_cast(*out_count) * sizeof(EulaVersion)); R_SUCCEED(); @@ -599,7 +599,7 @@ Result ISystemSettingsServer::GetAccountNotificationSettings( LOG_INFO(Service_SET, "called, elements={}", m_system_settings.account_notification_settings_count); - *out_count = (std::min)(m_system_settings.account_notification_settings_count, + *out_count = std::min(m_system_settings.account_notification_settings_count, static_cast(out_account_notification_settings.size())); memcpy(out_account_notification_settings.data(), m_system_settings.account_notification_settings.data(), diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 3b63d162c4..9e25eae4d4 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp @@ -74,9 +74,9 @@ void Controller::QueryPointerBufferSize(HLERequestContext& ctx) { ASSERT(process != nullptr); u32 buffer_size = process->GetPointerBufferSize(); - if (buffer_size > (std::numeric_limits::max)()) { + if (buffer_size > std::numeric_limits::max()) { LOG_WARNING(Service, "Pointer buffer size exceeds u16 max, clamping"); - buffer_size = (std::numeric_limits::max)(); + buffer_size = std::numeric_limits::max(); } IPC::ResponseBuilder rb{ctx, 3}; @@ -94,9 +94,9 @@ void Controller::SetPointerBufferSize(HLERequestContext& ctx) { u32 requested_size = rp.PopRaw(); - if (requested_size > (std::numeric_limits::max)()) { + if (requested_size > std::numeric_limits::max()) { LOG_WARNING(Service, "Requested pointer buffer size too large, clamping to 0xFFFF"); - requested_size = (std::numeric_limits::max)(); + requested_size = std::numeric_limits::max(); } process->SetPointerBufferSize(requested_size); diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index a31bf45238..fffbc413bb 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -45,13 +45,13 @@ bool IsConnectionBased(Type type) { template T GetValue(std::span buffer) { T t{}; - std::memcpy(&t, buffer.data(), (std::min)(sizeof(T), buffer.size())); + std::memcpy(&t, buffer.data(), std::min(sizeof(T), buffer.size())); return t; } template void PutValue(std::span buffer, const T& t) { - std::memcpy(buffer.data(), &t, (std::min)(sizeof(T), buffer.size())); + std::memcpy(buffer.data(), &t, std::min(sizeof(T), buffer.size())); } } // Anonymous namespace diff --git a/src/core/hle/service/spl/spl_module.cpp b/src/core/hle/service/spl/spl_module.cpp index f59eeac06c..549e6f4fa8 100644 --- a/src/core/hle/service/spl/spl_module.cpp +++ b/src/core/hle/service/spl/spl_module.cpp @@ -68,7 +68,7 @@ void Module::Interface::GenerateRandomBytes(HLERequestContext& ctx) { const std::size_t size = ctx.GetWriteBufferSize(); - std::uniform_int_distribution distribution(0, (std::numeric_limits::max)()); + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); std::vector data(size); std::generate(data.begin(), data.end(), [&] { return static_cast(distribution(rng)); }); diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 7720c93d5a..2d10bd04d2 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -445,7 +445,7 @@ private: void GetNextAlpnProto(HLERequestContext& ctx) { const size_t writable = ctx.GetWriteBufferSize(); - const size_t to_write = (std::min)(next_alpn_proto.size(), writable); + const size_t to_write = std::min(next_alpn_proto.size(), writable); if (to_write != 0) { ctx.WriteBuffer(std::span(next_alpn_proto.data(), to_write)); diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp index cd28b81dc1..289ad7073c 100644 --- a/src/core/hle/service/vi/application_display_service.cpp +++ b/src/core/hle/service/vi/application_display_service.cpp @@ -192,7 +192,7 @@ Result IApplicationDisplayService::OpenLayer(Out out_size, const auto buffer = parcel.Serialize(); std::memcpy(out_native_window.data(), buffer.data(), - (std::min)(out_native_window.size(), buffer.size())); + std::min(out_native_window.size(), buffer.size())); *out_size = buffer.size(); R_SUCCEED(); @@ -226,7 +226,7 @@ Result IApplicationDisplayService::CreateStrayLayer( const auto buffer = parcel.Serialize(); std::memcpy(out_native_window.data(), buffer.data(), - (std::min)(out_native_window.size(), buffer.size())); + std::min(out_native_window.size(), buffer.size())); *out_size = buffer.size(); diff --git a/src/core/internal_network/emu_net_state.cpp b/src/core/internal_network/emu_net_state.cpp index d6d1a70a60..17fa58fa08 100644 --- a/src/core/internal_network/emu_net_state.cpp +++ b/src/core/internal_network/emu_net_state.cpp @@ -10,10 +10,8 @@ #define NOMINMAX #include #include -#ifdef _MSC_VER #pragma comment(lib, "wlanapi.lib") #endif -#endif #include #include diff --git a/src/core/internal_network/network.cpp b/src/core/internal_network/network.cpp index 400bd04bdf..6a3c6e9c41 100644 --- a/src/core/internal_network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -105,7 +105,7 @@ sockaddr TranslateFromSockAddrIn(SockAddrIn input) { } LINGER MakeLinger(bool enable, u32 linger_value) { - ASSERT(linger_value <= (std::numeric_limits::max)()); + ASSERT(linger_value <= std::numeric_limits::max()); LINGER value; value.l_onoff = enable ? 1 : 0; @@ -798,7 +798,7 @@ Errno Socket::Shutdown(ShutdownHow how) { std::pair Socket::Recv(int flags, std::span message) { ASSERT(flags == 0); - ASSERT(message.size() < static_cast((std::numeric_limits::max)())); + ASSERT(message.size() < static_cast(std::numeric_limits::max())); const auto result = recv(fd, reinterpret_cast(message.data()), static_cast(message.size()), 0); @@ -811,7 +811,7 @@ std::pair Socket::Recv(int flags, std::span message) { std::pair Socket::RecvFrom(int flags, std::span message, SockAddrIn* addr) { ASSERT(flags == 0); - ASSERT(message.size() < static_cast((std::numeric_limits::max)())); + ASSERT(message.size() < static_cast(std::numeric_limits::max())); sockaddr_in addr_in{}; socklen_t addrlen = sizeof(addr_in); @@ -831,7 +831,7 @@ std::pair Socket::RecvFrom(int flags, std::span message, SockAdd } std::pair Socket::Send(std::span message, int flags) { - ASSERT(message.size() < static_cast((std::numeric_limits::max)())); + ASSERT(message.size() < static_cast(std::numeric_limits::max())); ASSERT(flags == 0); int native_flags = 0; diff --git a/src/core/internal_network/network_interface.cpp b/src/core/internal_network/network_interface.cpp index ae9755113a..f62381b9e3 100644 --- a/src/core/internal_network/network_interface.cpp +++ b/src/core/internal_network/network_interface.cpp @@ -147,7 +147,7 @@ std::vector GetAvailableNetworkInterfaces() { } // ignore header - file.ignore((std::numeric_limits::max)(), '\n'); + file.ignore(std::numeric_limits::max(), '\n'); bool gateway_found = false; diff --git a/src/core/internal_network/socket_proxy.cpp b/src/core/internal_network/socket_proxy.cpp index 1600c061f0..c263fb4ca8 100644 --- a/src/core/internal_network/socket_proxy.cpp +++ b/src/core/internal_network/socket_proxy.cpp @@ -105,14 +105,14 @@ Errno ProxySocket::Shutdown(ShutdownHow how) { std::pair ProxySocket::Recv(int flags, std::span message) { LOG_WARNING(Network, "(STUBBED) called"); ASSERT(flags == 0); - ASSERT(message.size() < static_cast((std::numeric_limits::max)())); + ASSERT(message.size() < static_cast(std::numeric_limits::max())); return {static_cast(0), Errno::SUCCESS}; } std::pair ProxySocket::RecvFrom(int flags, std::span message, SockAddrIn* addr) { ASSERT(flags == 0); - ASSERT(message.size() < static_cast((std::numeric_limits::max)())); + ASSERT(message.size() < static_cast(std::numeric_limits::max())); // TODO (flTobi): Verify the timeout behavior and break when connection is lost const auto timestamp = std::chrono::steady_clock::now(); @@ -183,7 +183,7 @@ std::pair ProxySocket::ReceivePacket(int flags, std::span messag std::pair ProxySocket::Send(std::span message, int flags) { LOG_WARNING(Network, "(STUBBED) called"); - ASSERT(message.size() < static_cast((std::numeric_limits::max)())); + ASSERT(message.size() < static_cast(std::numeric_limits::max())); ASSERT(flags == 0); return {static_cast(0), Errno::SUCCESS}; diff --git a/src/core/internal_network/wifi_scanner.cpp b/src/core/internal_network/wifi_scanner.cpp index 127221099f..f4b1738e69 100644 --- a/src/core/internal_network/wifi_scanner.cpp +++ b/src/core/internal_network/wifi_scanner.cpp @@ -15,10 +15,8 @@ using namespace std::chrono_literals; #define NOMINMAX #include #include -#ifdef _MSC_VER #pragma comment(lib, "wlanapi.lib") #endif -#endif namespace Network { #ifdef ENABLE_WIFI_SCAN diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp index 0a9d9dc6f8..4a87ab53e7 100644 --- a/src/core/loader/nca.cpp +++ b/src/core/loader/nca.cpp @@ -150,7 +150,7 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function // Initialize sha256 verification context. mbedtls_sha256_context ctx; mbedtls_sha256_init(&ctx); - mbedtls_sha256_starts(&ctx, 0); + mbedtls_sha256_starts_ret(&ctx, 0); // Ensure we maintain a clean state on exit. SCOPE_EXIT { @@ -164,11 +164,11 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function // Begin iterating the file. while (processed_size < total_size) { // Refill the buffer. - const size_t intended_read_size = (std::min)(buffer.size(), total_size - processed_size); + const size_t intended_read_size = std::min(buffer.size(), total_size - processed_size); const size_t read_size = file->Read(buffer.data(), intended_read_size, processed_size); // Update the hash function with the buffer contents. - mbedtls_sha256_update(&ctx, buffer.data(), read_size); + mbedtls_sha256_update_ret(&ctx, buffer.data(), read_size); // Update counters. processed_size += read_size; @@ -181,7 +181,7 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function // Finalize context and compute the output hash. std::array output_hash; - mbedtls_sha256_finish(&ctx, output_hash.data()); + mbedtls_sha256_finish_ret(&ctx, output_hash.data()); // Compare to expected. if (std::memcmp(input_hash.data(), output_hash.data(), NcaSha256HalfHashLength) != 0) { diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 2583aae867..08391cd815 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -48,7 +48,7 @@ struct Memory::Impl { explicit Impl(Core::System& system_) : system{system_} { // Initialize thread count based on available cores for parallel memory operations const unsigned int hw_concurrency = std::thread::hardware_concurrency(); - thread_count = (std::max)(2u, (std::min)(hw_concurrency, 8u)); // Limit to 8 threads max + thread_count = std::max(2u, std::min(hw_concurrency, 8u)); // Limit to 8 threads max } void SetCurrentPageTable(Kernel::KProcess& process) { @@ -61,8 +61,7 @@ struct Memory::Impl { } #ifdef __linux__ - heap_tracker.emplace(system.DeviceMemory().buffer); - buffer = std::addressof(*heap_tracker); + buffer.emplace(system.DeviceMemory().buffer); #else buffer = std::addressof(system.DeviceMemory().buffer); #endif @@ -263,7 +262,7 @@ struct Memory::Impl { while (remaining_size) { const std::size_t copy_amount = - (std::min)(static_cast(YUZU_PAGESIZE) - page_offset, remaining_size); + std::min(static_cast(YUZU_PAGESIZE) - page_offset, remaining_size); const auto current_vaddr = static_cast((page_index << YUZU_PAGEBITS) + page_offset); @@ -948,7 +947,7 @@ struct Memory::Impl { const auto* p = GetPointerImpl( v_address, []() {}, []() {}); constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1; - const size_t core = (std::min)(system.GetCurrentHostThreadID(), + const size_t core = std::min(system.GetCurrentHostThreadID(), sys_core); // any other calls threads go to syscore. if (!gpu_device_memory) [[unlikely]] { gpu_device_memory = &system.Host1x().MemoryManager(); @@ -989,7 +988,7 @@ struct Memory::Impl { void InvalidateGPUMemory(u8* p, size_t size) { constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1; - const size_t core = (std::min)(system.GetCurrentHostThreadID(), + const size_t core = std::min(system.GetCurrentHostThreadID(), sys_core); // any other calls threads go to syscore. if (!gpu_device_memory) [[unlikely]] { gpu_device_memory = &system.Host1x().MemoryManager(); @@ -1024,9 +1023,8 @@ struct Memory::Impl { std::span gpu_dirty_managers; std::mutex sys_core_guard; - std::optional heap_tracker; #ifdef __linux__ - Common::HeapTracker* buffer{}; + std::optional buffer; #else Common::HostMemory* buffer{}; #endif @@ -1230,22 +1228,7 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { if (rasterizer) { impl->InvalidateGPUMemory(ptr, size); } - -#ifdef __linux__ - if (!rasterizer && mapped) { - impl->buffer->DeferredMapSeparateHeap(GetInteger(vaddr)); - } -#endif - return mapped && ptr != nullptr; } -bool Memory::InvalidateSeparateHeap(void* fault_address) { -#ifdef __linux__ - return impl->buffer->DeferredMapSeparateHeap(static_cast(fault_address)); -#else - return false; -#endif -} - } // namespace Core::Memory diff --git a/src/core/memory.h b/src/core/memory.h index dcca26892b..99108ecf0d 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -487,13 +487,8 @@ public: * marked as debug or non-debug. */ void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug); - void SetGPUDirtyManagers(std::span managers); - bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size); - - bool InvalidateSeparateHeap(void* fault_address); - private: Core::System& system; diff --git a/src/core/tools/renderdoc.cpp b/src/core/tools/renderdoc.cpp index d3a47e1d96..947fa6cb37 100644 --- a/src/core/tools/renderdoc.cpp +++ b/src/core/tools/renderdoc.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 @@ -21,12 +18,10 @@ namespace Tools { RenderdocAPI::RenderdocAPI() { #ifdef WIN32 if (HMODULE mod = GetModuleHandleA("renderdoc.dll")) { - void* proc = reinterpret_cast(GetProcAddress(mod, "RENDERDOC_GetAPI")); - if (proc) { - const auto RENDERDOC_GetAPI = reinterpret_cast(proc); - const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdoc_api); - ASSERT(ret == 1); - } + const auto RENDERDOC_GetAPI = + reinterpret_cast(GetProcAddress(mod, "RENDERDOC_GetAPI")); + const s32 ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, (void**)&rdoc_api); + ASSERT(ret == 1); } #else #ifdef ANDROID diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt index 5166329156..9391a71b6c 100644 --- a/src/dedicated_room/CMakeLists.txt +++ b/src/dedicated_room/CMakeLists.txt @@ -1,6 +1,3 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - # SPDX-FileCopyrightText: 2017 Citra Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later @@ -16,11 +13,11 @@ add_library(yuzu-room STATIC EXCLUDE_FROM_ALL target_link_libraries(yuzu-room PRIVATE common network) if (ENABLE_WEB_SERVICE) - target_compile_definitions(yuzu-room PRIVATE ENABLE_WEB_SERVICE) + target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE) target_link_libraries(yuzu-room PRIVATE web_service) endif() -target_link_libraries(yuzu-room PRIVATE MbedTLS::mbedcrypto MbedTLS::mbedtls) +target_link_libraries(yuzu-room PRIVATE mbedtls mbedcrypto) if (MSVC) target_link_libraries(yuzu-room PRIVATE getopt) endif() diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index 38457deb50..5c28435f72 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -1,6 +1,3 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - cmake_minimum_required(VERSION 3.12) project(dynarmic LANGUAGES C CXX ASM VERSION 6.7.0) @@ -17,28 +14,15 @@ endif() # Dynarmic project options option(DYNARMIC_ENABLE_CPU_FEATURE_DETECTION "Turning this off causes dynarmic to assume the host CPU doesn't support anything later than SSE3" ON) - -if (PLATFORM_OPENBSD) - option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" ON) -else() - option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" OFF) -endif() - +option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" OFF) option(DYNARMIC_FATAL_ERRORS "Errors are fatal" OFF) option(DYNARMIC_IGNORE_ASSERTS "Ignore asserts" OFF) option(DYNARMIC_TESTS_USE_UNICORN "Enable fuzzing tests against unicorn" OFF) option(DYNARMIC_USE_LLVM "Support disassembly of jitted x86_64 code using LLVM" OFF) - -if (PLATFORM_OPENBSD) - option(DYNARMIC_USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF) -else() - option(DYNARMIC_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) -endif() - +option(DYNARMIC_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) option(DYNARMIC_INSTALL "Install dynarmic headers and CMake files" OFF) option(DYNARMIC_USE_BUNDLED_EXTERNALS "Use all bundled externals (useful when e.g. cross-compiling)" OFF) option(DYNARMIC_WARNINGS_AS_ERRORS "Warnings as errors" ${MASTER_PROJECT}) -option(DYNARMIC_ENABLE_LTO "Enable LTO" OFF) if (NOT DEFINED DYNARMIC_FRONTENDS) set(DYNARMIC_FRONTENDS "A32;A64" CACHE STRING "Selects which frontends to enable") endif() @@ -103,7 +87,7 @@ if (MSVC) /WX) endif() - if (CXX_CLANG) + if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") list(APPEND DYNARMIC_CXX_FLAGS -Qunused-arguments -Wno-missing-braces) @@ -131,7 +115,7 @@ else() -Wfatal-errors) endif() - if (CXX_GCC) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") # GCC produces bogus -Warray-bounds warnings from xbyak headers for code paths that are not # actually reachable. Specifically, it happens in cases where some code casts an Operand& # to Address& after first checking isMEM(), and that code is inlined in a situation where @@ -141,7 +125,7 @@ else() list(APPEND DYNARMIC_CXX_FLAGS -Wstack-usage=4096) endif() - if (CXX_CLANG) + if (CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang") # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. # And this in turns limits the size of a std::array. list(APPEND DYNARMIC_CXX_FLAGS -fbracket-depth=1024) @@ -150,26 +134,28 @@ else() endif() endif() +# Forced use of individual bundled libraries for non-REQUIRED library is possible with e.g. cmake -DCMAKE_DISABLE_FIND_PACKAGE_fmt=ON ... + +if (DYNARMIC_USE_BUNDLED_EXTERNALS) + set(CMAKE_DISABLE_FIND_PACKAGE_biscuit ON) + set(CMAKE_DISABLE_FIND_PACKAGE_fmt ON) + set(CMAKE_DISABLE_FIND_PACKAGE_mcl ON) + set(CMAKE_DISABLE_FIND_PACKAGE_oaknut ON) + set(CMAKE_DISABLE_FIND_PACKAGE_unordered_dense ON) + set(CMAKE_DISABLE_FIND_PACKAGE_xbyak ON) + set(CMAKE_DISABLE_FIND_PACKAGE_Zydis ON) + set(CMAKE_DISABLE_FIND_PACKAGE_Zycore ON) +endif() + find_package(Boost 1.57 REQUIRED) find_package(fmt 9 CONFIG) -# Pull in externals CMakeLists for libs where available -add_subdirectory(externals) - -find_package(mcl 0.1.12 REQUIRED) - if ("arm64" IN_LIST ARCHITECTURE OR DYNARMIC_TESTS) find_package(oaknut 2.0.1 CONFIG) endif() -if ("riscv" IN_LIST ARCHITECTURE) - find_package(biscuit 0.9.1 REQUIRED) -endif() - if ("x86_64" IN_LIST ARCHITECTURE) find_package(xbyak 7 CONFIG) - find_package(zycore REQUIRED) - find_package(zydis 4 REQUIRED) endif() if (DYNARMIC_USE_LLVM) @@ -184,6 +170,9 @@ if (DYNARMIC_TESTS) endif() endif() +# Pull in externals CMakeLists for libs where available +add_subdirectory(externals) + # Dynarmic project files add_subdirectory(src/dynarmic) if (DYNARMIC_TESTS) diff --git a/src/dynarmic/externals/CMakeLists.txt b/src/dynarmic/externals/CMakeLists.txt index ea666ddc52..23cfd42236 100644 --- a/src/dynarmic/externals/CMakeLists.txt +++ b/src/dynarmic/externals/CMakeLists.txt @@ -1,6 +1,5 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - +# Explicitly include CPMUtil here since we have a separate cpmfile for dynarmic +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) # Always build externals as static libraries, even when dynarmic is built as shared @@ -21,25 +20,69 @@ set(BUILD_TESTING OFF) # biscuit if ("riscv" IN_LIST ARCHITECTURE) + add_subdirectory(biscuit) + AddJsonPackage( NAME biscuit BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} ) endif() +# catch + +# if (NOT TARGET Catch2::Catch2WithMain) +# if (DYNARMIC_TESTS) +# find_package(Catch2 3.0.1 REQUIRED) +# endif() +# endif() + +# fmt + +# if (NOT TARGET fmt::fmt) +# # fmtlib formatting library +# set(FMT_INSTALL ON) +# add_subdirectory(fmt) +# endif() + # mcl AddJsonPackage( NAME mcl BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} ) +# oaknut + +# if (NOT TARGET merry::oaknut) +# if ("arm64" IN_LIST ARCHITECTURE) +# add_subdirectory(oaknut) +# elseif (DYNARMIC_TESTS) +# add_subdirectory(oaknut EXCLUDE_FROM_ALL) +# endif() +# endif() + +# unordered_dense + +AddJsonPackage( + NAME unordered-dense + BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} +) + +# xbyak +# uncomment if in an independent repo + +# if (NOT TARGET xbyak::xbyak) +# if ("x86_64" IN_LIST ARCHITECTURE) +# add_subdirectory(xbyak) +# endif() +# endif() + +# zydis + # TODO(crueter): maybe it's just Gentoo but zydis system package really sucks if ("x86_64" IN_LIST ARCHITECTURE) set(CMAKE_DISABLE_FIND_PACKAGE_Doxygen ON) - AddJsonPackage( - NAME zycore - BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} - ) + # TODO(crueter): system zycore doesn't work with zydis + AddJsonPackage(zycore) AddJsonPackage( NAME zydis diff --git a/src/dynarmic/externals/cpmfile.json b/src/dynarmic/externals/cpmfile.json index 718163baf5..b934856af2 100644 --- a/src/dynarmic/externals/cpmfile.json +++ b/src/dynarmic/externals/cpmfile.json @@ -14,14 +14,25 @@ "MCL_INSTALL OFF" ] }, + "unordered-dense": { + "package": "unordered_dense", + "repo": "Lizzie841/unordered_dense", + "sha": "e59d30b7b1", + "hash": "71eff7bd9ba4b9226967bacd56a8ff000946f8813167cb5664bb01e96fb79e4e220684d824fe9c59c4d1cc98c606f13aff05b7940a1ed8ab3c95d6974ee34fa0", + "find_args": "CONFIG", + "options": [ + "UNORDERED_DENSE_INSTALL OFF" + ] + }, "zycore": { - "package": "zycore", + "package": "Zycore", "repo": "zyantific/zycore-c", "sha": "75a36c45ae", - "hash": "15aa399f39713e042c4345bc3175c82f14dca849fde2a21d4f591f62c43e227b70d868d8bb86beb5f4eb68b1d6bd3792cdd638acf89009e787e3d10ee7401924" + "hash": "15aa399f39713e042c4345bc3175c82f14dca849fde2a21d4f591f62c43e227b70d868d8bb86beb5f4eb68b1d6bd3792cdd638acf89009e787e3d10ee7401924", + "bundled": true }, "zydis": { - "package": "zydis", + "package": "Zydis", "version": "4", "repo": "zyantific/zydis", "sha": "c2d2bab025", diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index b74626bcd5..e060989f82 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -160,15 +160,11 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS) endif() if ("x86_64" IN_LIST ARCHITECTURE) - # Newer versions of xbyak (>= 7.25.0) have stricter checks that currently - # fail in dynarmic - target_compile_definitions(dynarmic PRIVATE XBYAK_STRICT_CHECK_MEM_REG_SIZE=0) - target_compile_definitions(dynarmic PRIVATE XBYAK_OLD_DISP_CHECK=1) target_link_libraries(dynarmic PRIVATE xbyak::xbyak - Zydis::Zydis + Zydis ) target_architecture_specific_sources(dynarmic "x86_64" @@ -444,10 +440,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") endif() target_compile_definitions(dynarmic PRIVATE FMT_USE_USER_DEFINED_LITERALS=1) -if (DYNARMIC_ENABLE_LTO) - set_property(TARGET dynarmic PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif() - if (DYNARMIC_USE_PRECOMPILED_HEADERS) set(PRECOMPILED_HEADERS "$<$:${CMAKE_CURRENT_SOURCE_DIR}/ir/ir_emitter.h>") if ("x86_64" IN_LIST ARCHITECTURE) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp index d0653eceab..7695df57d2 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -6,13 +6,8 @@ * SPDX-License-Identifier: 0BSD */ -#include -#include -#include -#include -#include -#include -#include +#include "dynarmic/backend/exception_handler.h" + #ifdef __APPLE__ # include # include @@ -26,10 +21,17 @@ # endif #endif -#include +#include +#include +#include +#include +#include +#include -#include "dynarmic/backend/exception_handler.h" +#include "dynarmic/common/assert.h" +#include #include "dynarmic/common/common_types.h" + #if defined(MCL_ARCHITECTURE_X86_64) # include "dynarmic/backend/x64/block_of_code.h" #elif defined(MCL_ARCHITECTURE_ARM64) @@ -41,80 +43,42 @@ #else # error "Invalid architecture" #endif -#include namespace Dynarmic::Backend { namespace { struct CodeBlockInfo { - u64 size; + u64 code_begin, code_end; std::function cb; }; class SigHandler { - auto FindCodeBlockInfo(u64 offset) noexcept { - return std::find_if(code_block_infos.begin(), code_block_infos.end(), [&](auto const& e) { - return e.first <= offset && e.first + e.second.size > offset; - }); +public: + SigHandler(); + ~SigHandler(); + + void AddCodeBlock(CodeBlockInfo info); + void RemoveCodeBlock(u64 host_pc); + + bool SupportsFastmem() const { return supports_fast_mem; } + +private: + auto FindCodeBlockInfo(u64 host_pc) { + return std::find_if(code_block_infos.begin(), code_block_infos.end(), [&](const auto& x) { return x.code_begin <= host_pc && x.code_end > host_pc; }); } - static void SigAction(int sig, siginfo_t* info, void* raw_context); bool supports_fast_mem = true; + void* signal_stack_memory = nullptr; - ankerl::unordered_dense::map code_block_infos; - std::shared_mutex code_block_infos_mutex; + + std::vector code_block_infos; + std::mutex code_block_infos_mutex; + struct sigaction old_sa_segv; struct sigaction old_sa_bus; - std::size_t signal_stack_size; -public: - SigHandler() noexcept { - signal_stack_size = std::max(SIGSTKSZ, 2 * 1024 * 1024); - signal_stack_memory = mmap(nullptr, signal_stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - stack_t signal_stack{}; - signal_stack.ss_sp = signal_stack_memory; - signal_stack.ss_size = signal_stack_size; - signal_stack.ss_flags = 0; - if (sigaltstack(&signal_stack, nullptr) != 0) { - fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n"); - supports_fast_mem = false; - return; - } - - struct sigaction sa{}; - sa.sa_handler = nullptr; - sa.sa_sigaction = &SigHandler::SigAction; - sa.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; - sigemptyset(&sa.sa_mask); - if (sigaction(SIGSEGV, &sa, &old_sa_segv) != 0) { - fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGSEGV handler\n"); - supports_fast_mem = false; - return; - } -#ifdef __APPLE__ - if (sigaction(SIGBUS, &sa, &old_sa_bus) != 0) { - fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGBUS handler\n"); - supports_fast_mem = false; - return; - } -#endif - } - - ~SigHandler() noexcept { - munmap(signal_stack_memory, signal_stack_size); - } - - void AddCodeBlock(u64 offset, CodeBlockInfo cbi) noexcept { - std::unique_lock guard(code_block_infos_mutex); - code_block_infos.insert_or_assign(offset, cbi); - } - void RemoveCodeBlock(u64 offset) noexcept { - std::unique_lock guard(code_block_infos_mutex); - code_block_infos.erase(offset); - } - - bool SupportsFastmem() const noexcept { return supports_fast_mem; } + static void SigAction(int sig, siginfo_t* info, void* raw_context); }; std::mutex handler_lock; @@ -127,8 +91,64 @@ void RegisterHandler() { } } +SigHandler::SigHandler() { + const size_t signal_stack_size = std::max(SIGSTKSZ, 2 * 1024 * 1024); + + signal_stack_memory = std::malloc(signal_stack_size); + + stack_t signal_stack; + signal_stack.ss_sp = signal_stack_memory; + signal_stack.ss_size = signal_stack_size; + signal_stack.ss_flags = 0; + if (sigaltstack(&signal_stack, nullptr) != 0) { + fmt::print(stderr, "dynarmic: POSIX SigHandler: init failure at sigaltstack\n"); + supports_fast_mem = false; + return; + } + + struct sigaction sa; + sa.sa_handler = nullptr; + sa.sa_sigaction = &SigHandler::SigAction; + sa.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGSEGV, &sa, &old_sa_segv) != 0) { + fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGSEGV handler\n"); + supports_fast_mem = false; + return; + } +#ifdef __APPLE__ + if (sigaction(SIGBUS, &sa, &old_sa_bus) != 0) { + fmt::print(stderr, "dynarmic: POSIX SigHandler: could not set SIGBUS handler\n"); + supports_fast_mem = false; + return; + } +#endif +} + +SigHandler::~SigHandler() { + std::free(signal_stack_memory); +} + +void SigHandler::AddCodeBlock(CodeBlockInfo cbi) { + std::lock_guard guard(code_block_infos_mutex); + if (auto iter = FindCodeBlockInfo(cbi.code_begin); iter != code_block_infos.end()) { + code_block_infos.erase(iter); + } + code_block_infos.push_back(cbi); +} + +void SigHandler::RemoveCodeBlock(u64 host_pc) { + std::lock_guard guard(code_block_infos_mutex); + const auto iter = FindCodeBlockInfo(host_pc); + if (iter == code_block_infos.end()) { + return; + } + code_block_infos.erase(iter); +} + void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { - DEBUG_ASSERT(sig == SIGSEGV || sig == SIGBUS); + ASSERT(sig == SIGSEGV || sig == SIGBUS); + #ifndef MCL_ARCHITECTURE_RISCV ucontext_t* ucontext = reinterpret_cast(raw_context); #ifndef __OpenBSD__ @@ -137,6 +157,7 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { #endif #if defined(MCL_ARCHITECTURE_X86_64) + # if defined(__APPLE__) # define CTX_RIP (mctx->__ss.__rip) # define CTX_RSP (mctx->__ss.__rsp) @@ -158,18 +179,26 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { # else # error "Unknown platform" # endif + { - std::shared_lock guard(sig_handler->code_block_infos_mutex); - if (auto const iter = sig_handler->FindCodeBlockInfo(CTX_RIP); iter != sig_handler->code_block_infos.end()) { - FakeCall fc = iter->second.cb(CTX_RIP); + std::lock_guard guard(sig_handler->code_block_infos_mutex); + + const auto iter = sig_handler->FindCodeBlockInfo(CTX_RIP); + if (iter != sig_handler->code_block_infos.end()) { + FakeCall fc = iter->cb(CTX_RIP); + CTX_RSP -= sizeof(u64); *mcl::bit_cast(CTX_RSP) = fc.ret_rip; CTX_RIP = fc.call_rip; + return; } } + fmt::print(stderr, "Unhandled {} at rip {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_RIP); + #elif defined(MCL_ARCHITECTURE_ARM64) + # if defined(__APPLE__) # define CTX_PC (mctx->__ss.__pc) # define CTX_SP (mctx->__ss.__sp) @@ -211,19 +240,30 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { # else # error "Unknown platform" # endif + { - std::shared_lock guard(sig_handler->code_block_infos_mutex); - if (const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); iter != sig_handler->code_block_infos.end()) { - FakeCall fc = iter->second.cb(CTX_PC); + std::lock_guard guard(sig_handler->code_block_infos_mutex); + + const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); + if (iter != sig_handler->code_block_infos.end()) { + FakeCall fc = iter->cb(CTX_PC); + CTX_PC = fc.call_pc; + return; } } + fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC); + #elif defined(MCL_ARCHITECTURE_RISCV) + ASSERT_FALSE("Unimplemented"); + #else + # error "Invalid architecture" + #endif struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus; @@ -244,26 +284,26 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { } // anonymous namespace struct ExceptionHandler::Impl final { - Impl(u64 offset_, u64 size_) - : offset(offset_) - , size(size_) { + Impl(u64 code_begin_, u64 code_end_) + : code_begin(code_begin_) + , code_end(code_end_) { RegisterHandler(); } void SetCallback(std::function cb) { - sig_handler->AddCodeBlock(offset, CodeBlockInfo{ - .size = size, - .cb = cb - }); + CodeBlockInfo cbi; + cbi.code_begin = code_begin; + cbi.code_end = code_end; + cbi.cb = cb; + sig_handler->AddCodeBlock(cbi); } ~Impl() { - sig_handler->RemoveCodeBlock(offset); + sig_handler->RemoveCodeBlock(code_begin); } private: - u64 offset; - u64 size; + u64 code_begin, code_end; }; ExceptionHandler::ExceptionHandler() = default; @@ -271,22 +311,28 @@ ExceptionHandler::~ExceptionHandler() = default; #if defined(MCL_ARCHITECTURE_X86_64) void ExceptionHandler::Register(X64::BlockOfCode& code) { - impl = std::make_unique(mcl::bit_cast(code.getCode()), code.GetTotalCodeSize()); + const u64 code_begin = mcl::bit_cast(code.getCode()); + const u64 code_end = code_begin + code.GetTotalCodeSize(); + impl = std::make_unique(code_begin, code_end); } #elif defined(MCL_ARCHITECTURE_ARM64) void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) { - impl = std::make_unique(mcl::bit_cast(mem.ptr()), size); + const u64 code_begin = mcl::bit_cast(mem.ptr()); + const u64 code_end = code_begin + size; + impl = std::make_unique(code_begin, code_end); } #elif defined(MCL_ARCHITECTURE_RISCV) void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) { - impl = std::make_unique(mcl::bit_cast(mem.ptr()), size); + const u64 code_begin = mcl::bit_cast(mem.ptr()); + const u64 code_end = code_begin + size; + impl = std::make_unique(code_begin, code_end); } #else # error "Invalid architecture" #endif bool ExceptionHandler::SupportsFastmem() const noexcept { - return bool(impl) && sig_handler->SupportsFastmem(); + return static_cast(impl) && sig_handler->SupportsFastmem(); } void ExceptionHandler::SetFastmemCallback(std::function cb) { diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp index d5d5f089ff..5a33ac7727 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp @@ -225,14 +225,8 @@ bool IsUnderRosetta() { } // anonymous namespace -#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT -static const auto default_cg_mode = Xbyak::DontSetProtectRWE; -#else -static const auto default_cg_mode = nullptr; //Allow RWE -#endif - BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, std::function rcp) - : Xbyak::CodeGenerator(total_code_size, default_cg_mode, &s_allocator) + : Xbyak::CodeGenerator(total_code_size, nullptr, &s_allocator) , cb(std::move(cb)) , jsi(jsi) , constant_pool(*this, CONSTANT_POOL_SIZE) diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp index 3bc93e6fd5..a13baa6a97 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp @@ -277,7 +277,7 @@ void EmitX64::EmitNZCVFromPackedFlags(EmitContext& ctx, IR::Inst* inst) { } void EmitX64::EmitAddCycles(size_t cycles) { - ASSERT(cycles < (std::numeric_limits::max)()); + ASSERT(cycles < std::numeric_limits::max()); code.sub(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], static_cast(cycles)); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp index 31231c02aa..e795181872 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp @@ -38,7 +38,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) Xbyak::Reg addend = ctx.reg_alloc.UseGpr(args[1]).changeBit(size); Xbyak::Reg overflow = ctx.reg_alloc.ScratchGpr().changeBit(size); - constexpr u64 int_max = static_cast((std::numeric_limits>::max)()); + constexpr u64 int_max = static_cast(std::numeric_limits>::max()); if constexpr (size < 64) { code.xor_(overflow.cvt32(), overflow.cvt32()); code.bt(result.cvt32(), size - 1); @@ -82,7 +82,7 @@ void EmitUnsignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst Xbyak::Reg op_result = ctx.reg_alloc.UseScratchGpr(args[0]).changeBit(size); Xbyak::Reg addend = ctx.reg_alloc.UseScratchGpr(args[1]).changeBit(size); - constexpr u64 boundary = op == Op::Add ? (std::numeric_limits>::max)() : 0; + constexpr u64 boundary = op == Op::Add ? std::numeric_limits>::max() : 0; if constexpr (op == Op::Add) { code.add(op_result, addend); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp index 99000c2a57..e1b9e54df8 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp @@ -548,7 +548,7 @@ void EmitX64::EmitVectorArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) void EmitX64::EmitVectorArithmeticShiftRight64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); - const u8 shift_amount = (std::min)(args[1].GetImmediateU8(), u8(63)); + const u8 shift_amount = std::min(args[1].GetImmediateU8(), u8(63)); if (code.HasHostFeature(HostFeature::AVX512_Ortho)) { code.vpsraq(result, result, shift_amount); @@ -2139,7 +2139,7 @@ void EmitX64::EmitVectorMaxS64(EmitContext& ctx, IR::Inst* inst) { } EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a, const VectorArray& b) { - std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto x, auto y) { return (std::max)(x, y); }); + std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto x, auto y) { return std::max(x, y); }); }); } @@ -2201,7 +2201,7 @@ void EmitX64::EmitVectorMaxU64(EmitContext& ctx, IR::Inst* inst) { } EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a, const VectorArray& b) { - std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto x, auto y) { return (std::max)(x, y); }); + std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto x, auto y) { return std::max(x, y); }); }); } @@ -2259,7 +2259,7 @@ void EmitX64::EmitVectorMinS64(EmitContext& ctx, IR::Inst* inst) { } EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a, const VectorArray& b) { - std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto x, auto y) { return (std::min)(x, y); }); + std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto x, auto y) { return std::min(x, y); }); }); } @@ -2321,7 +2321,7 @@ void EmitX64::EmitVectorMinU64(EmitContext& ctx, IR::Inst* inst) { } EmitTwoArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a, const VectorArray& b) { - std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto x, auto y) { return (std::min)(x, y); }); + std::transform(a.begin(), a.end(), b.begin(), result.begin(), [](auto x, auto y) { return std::min(x, y); }); }); } @@ -2837,22 +2837,22 @@ static void LowerPairedOperation(VectorArray& result, const VectorArray& x template static void PairedMax(VectorArray& result, const VectorArray& x, const VectorArray& y) { - PairedOperation(result, x, y, [](auto a, auto b) { return (std::max)(a, b); }); + PairedOperation(result, x, y, [](auto a, auto b) { return std::max(a, b); }); } template static void PairedMin(VectorArray& result, const VectorArray& x, const VectorArray& y) { - PairedOperation(result, x, y, [](auto a, auto b) { return (std::min)(a, b); }); + PairedOperation(result, x, y, [](auto a, auto b) { return std::min(a, b); }); } template static void LowerPairedMax(VectorArray& result, const VectorArray& x, const VectorArray& y) { - LowerPairedOperation(result, x, y, [](auto a, auto b) { return (std::max)(a, b); }); + LowerPairedOperation(result, x, y, [](auto a, auto b) { return std::max(a, b); }); } template static void LowerPairedMin(VectorArray& result, const VectorArray& x, const VectorArray& y) { - LowerPairedOperation(result, x, y, [](auto a, auto b) { return (std::min)(a, b); }); + LowerPairedOperation(result, x, y, [](auto a, auto b) { return std::min(a, b); }); } template @@ -4933,7 +4933,7 @@ static bool VectorSignedSaturatedShiftLeft(VectorArray& dst, const VectorArra for (size_t i = 0; i < dst.size(); i++) { const T element = data[i]; const T shift = std::clamp(static_cast(mcl::bit::sign_extend<8>(static_cast(shift_values[i] & 0xFF))), - -static_cast(bit_size_minus_one), (std::numeric_limits::max)()); + -static_cast(bit_size_minus_one), std::numeric_limits::max()); if (element == 0) { dst[i] = 0; @@ -4995,7 +4995,7 @@ static bool VectorSignedSaturatedShiftLeftUnsigned(VectorArray& dst, const Ve const U shifted_test = shifted >> static_cast(shift); if (shifted_test != static_cast(element)) { - dst[i] = static_cast((std::numeric_limits::max)()); + dst[i] = static_cast(std::numeric_limits::max()); qc_flag = true; } else { dst[i] = shifted; @@ -5845,11 +5845,11 @@ static bool EmitVectorUnsignedSaturatedAccumulateSigned(VectorArray& result, const s64 y = static_cast(static_cast>(rhs[i])); const s64 sum = x + y; - if (sum > (std::numeric_limits::max)()) { - result[i] = (std::numeric_limits::max)(); + if (sum > std::numeric_limits::max()) { + result[i] = std::numeric_limits::max(); qc_flag = true; } else if (sum < 0) { - result[i] = (std::numeric_limits::min)(); + result[i] = std::numeric_limits::min(); qc_flag = true; } else { result[i] = static_cast(sum); @@ -5947,20 +5947,20 @@ static bool VectorUnsignedSaturatedShiftLeft(VectorArray& dst, const VectorAr for (size_t i = 0; i < dst.size(); i++) { const T element = data[i]; const S shift = std::clamp(static_cast(mcl::bit::sign_extend<8>(static_cast(shift_values[i] & 0xFF))), - negative_bit_size, (std::numeric_limits::max)()); + negative_bit_size, std::numeric_limits::max()); if (element == 0 || shift <= negative_bit_size) { dst[i] = 0; } else if (shift < 0) { dst[i] = static_cast(element >> -shift); } else if (shift >= static_cast(bit_size)) { - dst[i] = (std::numeric_limits::max)(); + dst[i] = std::numeric_limits::max(); qc_flag = true; } else { const T shifted = element << shift; if ((shifted >> shift) != element) { - dst[i] = (std::numeric_limits::max)(); + dst[i] = std::numeric_limits::max(); qc_flag = true; } else { dst[i] = shifted; diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp index a368e6703f..c8f0d9575c 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp @@ -2116,7 +2116,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { } } else { using FPT = mcl::unsigned_integer_of_size; // WORKAROUND: For issue 678 on MSVC - constexpr u64 integer_max = static_cast((std::numeric_limits>>::max)()); + constexpr u64 integer_max = static_cast(std::numeric_limits>>::max()); code.movaps(xmm0, GetVectorOf(code)); FCODE(cmplep)(xmm0, src); diff --git a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp index 29eab7908b..fa6006ed2a 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp @@ -85,7 +85,7 @@ void HostLocInfo::ReleaseOne() noexcept { if (current_references == 0) return; - ASSERT(size_t(accumulated_uses) + 1 < (std::numeric_limits::max)()); + ASSERT(size_t(accumulated_uses) + 1 < std::numeric_limits::max()); accumulated_uses++; current_references--; @@ -116,7 +116,7 @@ void HostLocInfo::AddValue(IR::Inst* inst) noexcept { values.clear(); } values.push_back(inst); - ASSERT(size_t(total_uses) + inst->UseCount() < (std::numeric_limits::max)()); + ASSERT(size_t(total_uses) + inst->UseCount() < std::numeric_limits::max()); total_uses += inst->UseCount(); max_bit_width = std::max(max_bit_width, GetBitWidth(inst->GetType())); } @@ -400,14 +400,14 @@ void RegAlloc::HostCall(IR::Inst* result_def, } void RegAlloc::AllocStackSpace(const size_t stack_space) noexcept { - ASSERT(stack_space < size_t((std::numeric_limits::max)())); + ASSERT(stack_space < size_t(std::numeric_limits::max())); ASSERT(reserved_stack_space == 0); reserved_stack_space = stack_space; code->sub(code->rsp, u32(stack_space)); } void RegAlloc::ReleaseStackSpace(const size_t stack_space) noexcept { - ASSERT(stack_space < size_t((std::numeric_limits::max)())); + ASSERT(stack_space < size_t(std::numeric_limits::max())); ASSERT(reserved_stack_space == stack_space); reserved_stack_space = 0; code->add(code->rsp, u32(stack_space)); diff --git a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h index bfacdcca52..f70329f471 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.h @@ -52,18 +52,18 @@ public: is_set_last_use = true; } inline void ReadLock() noexcept { - ASSERT(size_t(is_being_used_count) + 1 < (std::numeric_limits::max)()); + ASSERT(size_t(is_being_used_count) + 1 < std::numeric_limits::max()); ASSERT(!is_scratch); is_being_used_count++; } inline void WriteLock() noexcept { - ASSERT(size_t(is_being_used_count) + 1 < (std::numeric_limits::max)()); + ASSERT(size_t(is_being_used_count) + 1 < std::numeric_limits::max()); ASSERT(is_being_used_count == 0); is_being_used_count++; is_scratch = true; } inline void AddArgReference() noexcept { - ASSERT(size_t(current_references) + 1 < (std::numeric_limits::max)()); + ASSERT(size_t(current_references) + 1 < std::numeric_limits::max()); current_references++; ASSERT(accumulated_uses + current_references <= total_uses); } diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp b/src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp index c949ed7de8..474c2f8404 100644 --- a/src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp +++ b/src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp @@ -11,12 +11,6 @@ #include "dynarmic/backend/x64/hostloc.h" #include "dynarmic/common/spin_lock.h" -#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT -static const auto default_cg_mode = Xbyak::DontSetProtectRWE; -#else -static const auto default_cg_mode = nullptr; //Allow RWE -#endif - namespace Dynarmic { void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp) { @@ -43,7 +37,7 @@ namespace { struct SpinLockImpl { void Initialize(); - Xbyak::CodeGenerator code = Xbyak::CodeGenerator(4096, default_cg_mode); + Xbyak::CodeGenerator code; void (*lock)(volatile int*); void (*unlock)(volatile int*); diff --git a/src/dynarmic/src/dynarmic/frontend/A32/a32_types.h b/src/dynarmic/src/dynarmic/frontend/A32/a32_types.h index 3f4501a528..fdadef8257 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/a32_types.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/a32_types.h @@ -106,7 +106,6 @@ inline size_t RegNumber(ExtReg reg) { } ASSERT_MSG(false, "Invalid extended register"); - return 0; } inline Reg operator+(Reg reg, size_t number) { diff --git a/src/frontend_common/firmware_manager.h b/src/frontend_common/firmware_manager.h index 23fce59eb3..20f3b41478 100644 --- a/src/frontend_common/firmware_manager.h +++ b/src/frontend_common/firmware_manager.h @@ -7,7 +7,6 @@ #include "common/common_types.h" #include "core/core.h" #include "core/file_sys/nca_metadata.h" -#include "core/file_sys/content_archive.h" #include "core/file_sys/registered_cache.h" #include "core/hle/service/filesystem/filesystem.h" #include @@ -144,8 +143,6 @@ inline std::pair GetFirmwareVersion return {firmware_data, result}; } - -// TODO(crueter): GET AS STRING } -#endif +#endif // FIRMWARE_MANAGER_H diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index 8a6922c49f..5bdad4a0ad 100644 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp @@ -1308,9 +1308,9 @@ bool EmulatedController::SetVibration(DeviceIndex device_index, const VibrationV : Common::Input::VibrationAmplificationType::Linear; const Common::Input::VibrationStatus status = { - .low_amplitude = (std::min)(vibration.low_amplitude * strength, 1.0f), + .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f), .low_frequency = vibration.low_frequency, - .high_amplitude = (std::min)(vibration.high_amplitude * strength, 1.0f), + .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f), .high_frequency = vibration.high_frequency, .type = type, }; diff --git a/src/hid_core/hidbus/ringcon.cpp b/src/hid_core/hidbus/ringcon.cpp index a2bfd82636..4f5eaa5053 100644 --- a/src/hid_core/hidbus/ringcon.cpp +++ b/src/hid_core/hidbus/ringcon.cpp @@ -283,7 +283,7 @@ u8 RingController::GetCrcValue(const std::vector& data) const { template u64 RingController::GetData(const T& reply, std::span out_data) const { static_assert(std::is_trivially_copyable_v); - const auto data_size = static_cast((std::min)(sizeof(reply), out_data.size())); + const auto data_size = static_cast(std::min(sizeof(reply), out_data.size())); std::memcpy(out_data.data(), &reply, data_size); return data_size; } diff --git a/src/hid_core/irsensor/image_transfer_processor.cpp b/src/hid_core/irsensor/image_transfer_processor.cpp index 9040390946..2b5a50ef6f 100644 --- a/src/hid_core/irsensor/image_transfer_processor.cpp +++ b/src/hid_core/irsensor/image_transfer_processor.cpp @@ -146,7 +146,7 @@ void ImageTransferProcessor::SetTransferMemoryAddress(Common::ProcessAddress t_m Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( std::span data) const { - const auto size = (std::min)(GetDataSize(current_config.trimming_format), data.size()); + const auto size = std::min(GetDataSize(current_config.trimming_format), data.size()); system.ApplicationMemory().ReadBlock(transfer_memory, data.data(), size); return processor_state; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp index b3e17b389d..62fbbb0a7e 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_battery_handler.cpp @@ -30,7 +30,7 @@ void NpadAbstractBatteryHandler::SetPropertiesHandler(NpadAbstractPropertiesHand } Result NpadAbstractBatteryHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp index e4166b3735..5871694335 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_button_handler.cpp @@ -30,7 +30,7 @@ void NpadAbstractButtonHandler::SetPropertiesHandler(NpadAbstractPropertiesHandl } Result NpadAbstractButtonHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp index 4367dcaa56..e399edfd70 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp @@ -24,7 +24,7 @@ void NpadAbstractIrSensorHandler::SetPropertiesHandler(NpadAbstractPropertiesHan } Result NpadAbstractIrSensorHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp index b4375e57f3..0b2bfe88da 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_led_handler.cpp @@ -29,7 +29,7 @@ void NpadAbstractLedHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* } Result NpadAbstractLedHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp index accbfe0def..6f35bd95cc 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_mcu_handler.cpp @@ -22,7 +22,7 @@ void NpadAbstractMcuHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* } Result NpadAbstractMcuHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp index 7a47786d42..bd9b79333c 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_nfc_handler.cpp @@ -24,7 +24,7 @@ void NpadAbstractNfcHandler::SetPropertiesHandler(NpadAbstractPropertiesHandler* } Result NpadAbstractNfcHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp index 39906fe33f..435b095f02 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp @@ -68,7 +68,7 @@ void AbstractPad::SetNpadId(Core::HID::NpadIdType npad_id) { } Result AbstractPad::Activate() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp index 80f86459b9..8334dc34f6 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_pad_holder.cpp @@ -73,7 +73,7 @@ u64 NpadAbstractedPadHolder::RemoveAbstractPadByAssignmentStyle( } u32 NpadAbstractedPadHolder::GetAbstractedPads(std::span list) const { - u32 num_elements = (std::min)(static_cast(list.size()), list_size); + u32 num_elements = std::min(static_cast(list.size()), list_size); for (std::size_t i = 0; i < num_elements; i++) { list[i] = assignment_list[i].abstracted_pad; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp index c10d0c4070..04d276d617 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_palma_handler.cpp @@ -25,7 +25,7 @@ void NpadAbstractPalmaHandler::SetPalmaResource(PalmaResource* resource) { } Result NpadAbstractPalmaHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp index 90c46cbe8c..36b630c7f4 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_properties_handler.cpp @@ -38,7 +38,7 @@ Core::HID::NpadIdType NpadAbstractPropertiesHandler::GetNpadId() const { } Result NpadAbstractPropertiesHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } diff --git a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp index 10c00ef95c..0dde244ef8 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_sixaxis_handler.cpp @@ -33,7 +33,7 @@ void NpadAbstractSixAxisHandler::SetSixaxisResource(SixAxisResource* resource) { } Result NpadAbstractSixAxisHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp index 07a35b2147..ca64b0a437 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp @@ -55,7 +55,7 @@ void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_devi } Result NpadAbstractVibrationHandler::IncrementRefCounter() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadHandlerOverflow; } ref_counter++; diff --git a/src/hid_core/resources/applet_resource.cpp b/src/hid_core/resources/applet_resource.cpp index a533ca4319..243beb1c7f 100644 --- a/src/hid_core/resources/applet_resource.cpp +++ b/src/hid_core/resources/applet_resource.cpp @@ -271,7 +271,7 @@ void AppletResource::EnablePalmaBoostMode(u64 aruid, bool is_enabled) { } Result AppletResource::RegisterCoreAppletResource() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultAppletResourceOverflow; } if (ref_counter == 0) { diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index f1f5ee5e9f..ca1ccd659c 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp @@ -55,7 +55,7 @@ NPad::~NPad() { } Result NPad::Activate() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultNpadResourceOverflow; } diff --git a/src/hid_core/resources/npad/npad_data.cpp b/src/hid_core/resources/npad/npad_data.cpp index fbcc3ef89a..29ad5cb08c 100644 --- a/src/hid_core/resources/npad/npad_data.cpp +++ b/src/hid_core/resources/npad/npad_data.cpp @@ -46,7 +46,7 @@ Result NPadData::SetSupportedNpadIdType(std::span l } std::size_t NPadData::GetSupportedNpadIdType(std::span out_list) const { - std::size_t out_size = (std::min)(supported_npad_id_types_count, out_list.size()); + std::size_t out_size = std::min(supported_npad_id_types_count, out_list.size()); memcpy(out_list.data(), supported_npad_id_types.data(), out_size * sizeof(Core::HID::NpadIdType)); diff --git a/src/hid_core/resources/npad/npad_resource.cpp b/src/hid_core/resources/npad/npad_resource.cpp index 21a514dce6..79f7d74c0c 100644 --- a/src/hid_core/resources/npad/npad_resource.cpp +++ b/src/hid_core/resources/npad/npad_resource.cpp @@ -126,7 +126,7 @@ Result NPadResource::Activate(u64 aruid) { } Result NPadResource::Activate() { - if (ref_counter == (std::numeric_limits::max)() - 1) { + if (ref_counter == std::numeric_limits::max() - 1) { return ResultAppletResourceOverflow; } if (ref_counter == 0) { diff --git a/src/hid_core/resources/palma/palma.cpp b/src/hid_core/resources/palma/palma.cpp index 9210b456e2..be3d3c0edd 100644 --- a/src/hid_core/resources/palma/palma.cpp +++ b/src/hid_core/resources/palma/palma.cpp @@ -62,7 +62,7 @@ Result Palma::GetPalmaOperationInfo(const PalmaConnectionHandle& handle, } operation_type = static_cast(operation.operation); std::memcpy(out_data.data(), operation.data.data(), - (std::min)(out_data.size(), operation.data.size())); + std::min(out_data.size(), operation.data.size())); return ResultSuccess; } diff --git a/src/hid_core/resources/touch_screen/gesture_handler.cpp b/src/hid_core/resources/touch_screen/gesture_handler.cpp index 6309019796..4fcaf6ecf1 100644 --- a/src/hid_core/resources/touch_screen/gesture_handler.cpp +++ b/src/hid_core/resources/touch_screen/gesture_handler.cpp @@ -16,7 +16,7 @@ GestureHandler::~GestureHandler() {} void GestureHandler::SetTouchState(std::span touch_state, u32 count, s64 timestamp) { gesture = {}; - gesture.active_points = (std::min)(MaxPoints, static_cast(count)); + gesture.active_points = std::min(MaxPoints, static_cast(count)); for (size_t id = 0; id < gesture.active_points; ++id) { const auto& [active_x, active_y] = touch_state[id].position; diff --git a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp index 51b94b2466..79ddaa4dfa 100644 --- a/src/hid_core/resources/touch_screen/touch_screen_resource.cpp +++ b/src/hid_core/resources/touch_screen/touch_screen_resource.cpp @@ -25,8 +25,8 @@ TouchResource::~TouchResource() { }; Result TouchResource::ActivateTouch() { - if (global_ref_counter == (std::numeric_limits::max)() - 1 || - touch_ref_counter == (std::numeric_limits::max)() - 1) { + if (global_ref_counter == std::numeric_limits::max() - 1 || + touch_ref_counter == std::numeric_limits::max() - 1) { return ResultTouchOverflow; } @@ -91,8 +91,8 @@ Result TouchResource::ActivateTouch(u64 aruid) { } Result TouchResource::ActivateGesture() { - if (global_ref_counter == (std::numeric_limits::max)() - 1 || - gesture_ref_counter == (std::numeric_limits::max)() - 1) { + if (global_ref_counter == std::numeric_limits::max() - 1 || + gesture_ref_counter == std::numeric_limits::max() - 1) { return ResultGestureOverflow; } diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 34bf877bf5..4af2dd36f5 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -102,11 +102,11 @@ void Mouse::UpdateStickInput() { SetAxis(identifier, mouse_axis_y, -last_mouse_change.y); // Decay input over time - const float clamped_length = (std::min)(1.0f, length); + const float clamped_length = std::min(1.0f, length); const float decay_strength = Settings::values.mouse_panning_decay_strength.GetValue(); const float decay = 1 - clamped_length * clamped_length * decay_strength * 0.01f; const float min_decay = Settings::values.mouse_panning_min_decay.GetValue(); - const float clamped_decay = (std::min)(1 - min_decay / 100.0f, decay); + const float clamped_decay = std::min(1 - min_decay / 100.0f, decay); last_mouse_change *= clamped_decay; } diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 972abec9fe..51169c6f2b 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -120,7 +120,7 @@ public: f32 low_frequency_scale = 1.0f; if (vibration.low_frequency > low_start_sensitivity_limit) { low_frequency_scale = - (std::max)(1.0f - (vibration.low_frequency - low_start_sensitivity_limit) / + std::max(1.0f - (vibration.low_frequency - low_start_sensitivity_limit) / low_width_sensitivity_limit, 0.3f); } @@ -129,7 +129,7 @@ public: f32 high_frequency_scale = 1.0f; if (vibration.high_frequency > high_start_sensitivity_limit) { high_frequency_scale = - (std::max)(1.0f - (vibration.high_frequency - high_start_sensitivity_limit) / + std::max(1.0f - (vibration.high_frequency - high_start_sensitivity_limit) / high_width_sensitivity_limit, 0.3f); } diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index df1819904b..d483cd3490 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -615,8 +615,8 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( } LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x, data.touch[0].y); - min_x = (std::min)(min_x, static_cast(data.touch[0].x)); - min_y = (std::min)(min_y, static_cast(data.touch[0].y)); + min_x = std::min(min_x, static_cast(data.touch[0].x)); + min_y = std::min(min_y, static_cast(data.touch[0].y)); if (current_status == Status::Ready) { // First touch - min data (min_x/min_y) current_status = Status::Stage1Completed; diff --git a/src/input_common/helpers/joycon_protocol/calibration.cpp b/src/input_common/helpers/joycon_protocol/calibration.cpp index 057bf29f71..1300ecaf53 100644 --- a/src/input_common/helpers/joycon_protocol/calibration.cpp +++ b/src/input_common/helpers/joycon_protocol/calibration.cpp @@ -140,8 +140,8 @@ Common::Input::DriverResult CalibrationProtocol::GetRingCalibration(RingCalibrat ring_data_min = current_value - DefaultRingRange; ring_data_default = current_value; } - ring_data_max = (std::max)(ring_data_max, current_value); - ring_data_min = (std::min)(ring_data_min, current_value); + ring_data_max = std::max(ring_data_max, current_value); + ring_data_min = std::min(ring_data_min, current_value); calibration = { .default_value = ring_data_default, .max_value = ring_data_max, diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index bfdaa74a62..db83f9ef48 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.cpp +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp @@ -327,7 +327,7 @@ Common::Input::DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, (output.mcu_data[6] != 0x09 && output.mcu_data[6] != 0x04)); data.type = output.mcu_data[12]; - data.uuid_size = (std::min)(output.mcu_data[14], static_cast(sizeof(TagUUID))); + data.uuid_size = std::min(output.mcu_data[14], static_cast(sizeof(TagUUID))); memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size()); return Common::Input::DriverResult::Success; @@ -433,7 +433,7 @@ Common::Input::DriverResult NfcProtocol::WriteAmiiboData(const TagUUID& tag_uuid // Send Data. Nfc buffer size is 31, Send the data in smaller packages while (current_position < buffer.size() && tries++ < timeout_limit) { const std::size_t next_position = - (std::min)(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); + std::min(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); const std::size_t block_size = next_position - current_position; const bool is_last_packet = block_size < sizeof(NFCRequestState::raw_data); @@ -479,7 +479,7 @@ Common::Input::DriverResult NfcProtocol::GetMifareData( // Send data request. Nfc buffer size is 31, Send the data in smaller packages while (current_position < buffer.size() && tries++ < timeout_limit) { const std::size_t next_position = - (std::min)(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); + std::min(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); const std::size_t block_size = next_position - current_position; const bool is_last_packet = block_size < sizeof(NFCRequestState::raw_data); @@ -559,7 +559,7 @@ Common::Input::DriverResult NfcProtocol::WriteMifareData( // Send data request. Nfc buffer size is 31, Send the data in smaller packages while (current_position < buffer.size() && tries++ < timeout_limit) { const std::size_t next_position = - (std::min)(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); + std::min(current_position + sizeof(NFCRequestState::raw_data), buffer.size()); const std::size_t block_size = next_position - current_position; const bool is_last_packet = block_size < sizeof(NFCRequestState::raw_data); @@ -731,7 +731,7 @@ Common::Input::DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandRe u8 block_id, bool is_last_packet, std::span data) { - const auto data_size = (std::min)(data.size(), sizeof(NFCRequestState::raw_data)); + const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); NFCRequestState request{ .command_argument = NFCCommand::WriteNtag, .block_id = block_id, @@ -754,7 +754,7 @@ Common::Input::DriverResult NfcProtocol::SendWriteDataAmiiboRequest(MCUCommandRe Common::Input::DriverResult NfcProtocol::SendReadDataMifareRequest(MCUCommandResponse& output, u8 block_id, bool is_last_packet, std::span data) { - const auto data_size = (std::min)(data.size(), sizeof(NFCRequestState::raw_data)); + const auto data_size = std::min(data.size(), sizeof(NFCRequestState::raw_data)); NFCRequestState request{ .command_argument = NFCCommand::Mifare, .block_id = block_id, diff --git a/src/input_common/helpers/joycon_protocol/rumble.cpp b/src/input_common/helpers/joycon_protocol/rumble.cpp index db3420dc0b..9fd0b84708 100644 --- a/src/input_common/helpers/joycon_protocol/rumble.cpp +++ b/src/input_common/helpers/joycon_protocol/rumble.cpp @@ -29,7 +29,7 @@ Common::Input::DriverResult RumbleProtocol::SendVibration(const VibrationValue& // Protect joycons from damage from strong vibrations const f32 clamp_amplitude = - 1.0f / (std::max)(1.0f, vibration.high_amplitude + vibration.low_amplitude); + 1.0f / std::max(1.0f, vibration.high_amplitude + vibration.low_amplitude); const u16 encoded_high_frequency = EncodeHighFrequency(vibration.high_frequency); const u8 encoded_high_amplitude = diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 1487033b22..d0787b0936 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -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-3.0-or-later @@ -24,7 +21,7 @@ create_target_directory_groups(network) target_link_libraries(network PRIVATE common enet Boost::headers) if (ENABLE_WEB_SERVICE) - target_compile_definitions(network PRIVATE ENABLE_WEB_SERVICE) + target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE) target_link_libraries(network PRIVATE web_service) endif() diff --git a/src/network/room.cpp b/src/network/room.cpp index 1a3ad75d2b..99dcf0c3b4 100644 --- a/src/network/room.cpp +++ b/src/network/room.cpp @@ -951,7 +951,7 @@ void Room::RoomImpl::HandleChatPacket(const ENetEvent* event) { } // Limit the size of chat messages to MaxMessageSize - message.resize((std::min)(static_cast(message.size()), MaxMessageSize)); + message.resize(std::min(static_cast(message.size()), MaxMessageSize)); Packet out_packet; out_packet.Write(static_cast(IdChatMessage)); diff --git a/src/qt_common/CMakeLists.txt b/src/qt_common/CMakeLists.txt deleted file mode 100644 index 9d292da401..0000000000 --- a/src/qt_common/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ -# 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 - -find_package(Qt6 REQUIRED COMPONENTS Core) -find_package(Qt6 REQUIRED COMPONENTS Core) - -add_library(qt_common STATIC - qt_common.h - qt_common.cpp - - uisettings.cpp - uisettings.h - - qt_config.cpp - qt_config.h - - shared_translation.cpp - shared_translation.h - qt_path_util.h qt_path_util.cpp - qt_game_util.h qt_game_util.cpp - qt_frontend_util.h qt_frontend_util.cpp - qt_meta.h qt_meta.cpp - qt_content_util.h qt_content_util.cpp - qt_rom_util.h qt_rom_util.cpp - qt_applet_util.h qt_applet_util.cpp - qt_progress_dialog.h qt_progress_dialog.cpp - -) - -create_target_directory_groups(qt_common) - -# TODO(crueter) -if (ENABLE_QT) - target_link_libraries(qt_common PRIVATE Qt6::Widgets) -endif() - -add_subdirectory(externals) - -target_link_libraries(qt_common PRIVATE core Qt6::Core SimpleIni::SimpleIni QuaZip::QuaZip frozen::frozen) -target_link_libraries(qt_common PRIVATE Qt6::Core) - -if (NOT WIN32) - target_include_directories(qt_common PRIVATE ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) -endif() diff --git a/src/qt_common/qt_applet_util.cpp b/src/qt_common/qt_applet_util.cpp deleted file mode 100644 index 1b0189392e..0000000000 --- a/src/qt_common/qt_applet_util.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_applet_util.h" diff --git a/src/qt_common/qt_applet_util.h b/src/qt_common/qt_applet_util.h deleted file mode 100644 index 2b48d16698..0000000000 --- a/src/qt_common/qt_applet_util.h +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_APPLET_UTIL_H -#define QT_APPLET_UTIL_H - -// TODO -namespace QtCommon::Applets { - -} -#endif // QT_APPLET_UTIL_H diff --git a/src/qt_common/qt_common.h b/src/qt_common/qt_common.h deleted file mode 100644 index a2700427ab..0000000000 --- a/src/qt_common/qt_common.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_COMMON_H -#define QT_COMMON_H - -#include -#include "core/core.h" -#include "core/file_sys/registered_cache.h" -#include -#include - -#include - -namespace QtCommon { - -#ifdef YUZU_QT_WIDGETS -extern QWidget *rootObject; -#else -extern QObject *rootObject; -#endif - -extern std::unique_ptr system; -extern std::shared_ptr vfs; -extern std::unique_ptr provider; - -typedef std::function QtProgressCallback; - -Core::Frontend::WindowSystemType GetWindowSystemType(); - -Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow *window); - -#ifdef YUZU_QT_WIDGETS -void Init(QWidget *root); -#else -void Init(QObject *root); -#endif - -const QString tr(const char *str); -const QString tr(const std::string &str); - -std::filesystem::path GetEdenCommand(); -} // namespace QtCommon -#endif diff --git a/src/qt_common/qt_content_util.cpp b/src/qt_common/qt_content_util.cpp deleted file mode 100644 index e4625aa423..0000000000 --- a/src/qt_common/qt_content_util.cpp +++ /dev/null @@ -1,313 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_content_util.h" -#include "common/fs/fs.h" -#include "frontend_common/content_manager.h" -#include "frontend_common/firmware_manager.h" -#include "qt_common/qt_common.h" -#include "qt_common/qt_progress_dialog.h" -#include "qt_frontend_util.h" - -#include - -namespace QtCommon::Content { - -bool CheckGameFirmware(u64 program_id, QObject* parent) -{ - if (FirmwareManager::GameRequiresFirmware(program_id) - && !FirmwareManager::CheckFirmwarePresence(*system)) { - auto result = QtCommon::Frontend::ShowMessage( - QMessageBox::Warning, - "Game Requires Firmware", - "The game you are trying to launch requires firmware to boot or to get past the " - "opening menu. Please " - "dump and install firmware, or press \"OK\" to launch anyways.", - QMessageBox::Ok | QMessageBox::Cancel, - parent); - - return result == QMessageBox::Ok; - } - - return true; -} - -void InstallFirmware(const QString& location, bool recursive) -{ - QtCommon::Frontend::QtProgressDialog progress(tr("Installing Firmware..."), - tr("Cancel"), - 0, - 100, - rootObject); - progress.setWindowModality(Qt::WindowModal); - progress.setMinimumDuration(100); - progress.setAutoClose(false); - progress.setAutoReset(false); - progress.show(); - - // Declare progress callback. - auto callback = [&](size_t total_size, size_t processed_size) { - progress.setValue(static_cast((processed_size * 100) / total_size)); - return progress.wasCanceled(); - }; - - static constexpr const char* failedTitle = "Firmware Install Failed"; - static constexpr const char* successTitle = "Firmware Install Succeeded"; - QMessageBox::Icon icon; - FirmwareInstallResult result; - - const auto ShowMessage = [&]() { - QtCommon::Frontend::ShowMessage(icon, - failedTitle, - GetFirmwareInstallResultString(result)); - }; - - LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString()); - - // Check for a reasonable number of .nca files (don't hardcode them, just see if there's some in - // there.) - std::filesystem::path firmware_source_path = location.toStdString(); - if (!Common::FS::IsDir(firmware_source_path)) { - return; - } - - std::vector out; - const Common::FS::DirEntryCallable dir_callback = - [&out](const std::filesystem::directory_entry& entry) { - if (entry.path().has_extension() && entry.path().extension() == ".nca") { - out.emplace_back(entry.path()); - } - - return true; - }; - - callback(100, 10); - - if (recursive) { - Common::FS::IterateDirEntriesRecursively(firmware_source_path, - dir_callback, - Common::FS::DirEntryFilter::File); - } else { - Common::FS::IterateDirEntries(firmware_source_path, - dir_callback, - Common::FS::DirEntryFilter::File); - } - - if (out.size() <= 0) { - result = FirmwareInstallResult::NoNCAs; - icon = QMessageBox::Warning; - ShowMessage(); - return; - } - - // Locate and erase the content of nand/system/Content/registered/*.nca, if any. - auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory(); - if (sysnand_content_vdir->IsWritable() - && !sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) { - result = FirmwareInstallResult::FailedDelete; - icon = QMessageBox::Critical; - ShowMessage(); - return; - } - - LOG_INFO(Frontend, - "Cleaned nand/system/Content/registered folder in preparation for new firmware."); - - callback(100, 20); - - auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered"); - - bool success = true; - int i = 0; - for (const auto& firmware_src_path : out) { - i++; - auto firmware_src_vfile = vfs->OpenFile(firmware_src_path.generic_string(), - FileSys::OpenMode::Read); - auto firmware_dst_vfile = firmware_vdir - ->CreateFileRelative(firmware_src_path.filename().string()); - - if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) { - LOG_ERROR(Frontend, - "Failed to copy firmware file {} to {} in registered folder!", - firmware_src_path.generic_string(), - firmware_src_path.filename().string()); - success = false; - } - - if (callback(100, 20 + static_cast(((i) / static_cast(out.size())) * 70.0))) { - result = FirmwareInstallResult::FailedCorrupted; - icon = QMessageBox::Warning; - ShowMessage(); - return; - } - } - - if (!success) { - result = FirmwareInstallResult::FailedCopy; - icon = QMessageBox::Critical; - ShowMessage(); - return; - } - - // Re-scan VFS for the newly placed firmware files. - system->GetFileSystemController().CreateFactories(*vfs); - - auto VerifyFirmwareCallback = [&](size_t total_size, size_t processed_size) { - progress.setValue(90 + static_cast((processed_size * 10) / total_size)); - return progress.wasCanceled(); - }; - - auto results = ContentManager::VerifyInstalledContents(*QtCommon::system, - *QtCommon::provider, - VerifyFirmwareCallback, - true); - - if (results.size() > 0) { - const auto failed_names = QString::fromStdString( - fmt::format("{}", fmt::join(results, "\n"))); - progress.close(); - QtCommon::Frontend::Critical(tr("Firmware integrity verification failed!"), - tr("Verification failed for the following files:\n\n%1") - .arg(failed_names)); - return; - } - - progress.close(); - - const auto pair = FirmwareManager::GetFirmwareVersion(*system); - const auto firmware_data = pair.first; - const std::string display_version(firmware_data.display_version.data()); - - result = FirmwareInstallResult::Success; - QtCommon::Frontend::Information(rootObject, - tr(successTitle), - tr(GetFirmwareInstallResultString(result)) - .arg(QString::fromStdString(display_version))); -} - -QString UnzipFirmwareToTmp(const QString& location) -{ - namespace fs = std::filesystem; - fs::path tmp{fs::temp_directory_path()}; - - if (!fs::create_directories(tmp / "eden" / "firmware")) { - return ""; - } - - tmp /= "eden"; - tmp /= "firmware"; - - QString qCacheDir = QString::fromStdString(tmp.string()); - - QFile zip(location); - - QStringList result = JlCompress::extractDir(&zip, qCacheDir); - if (result.isEmpty()) { - return ""; - } - - return qCacheDir; -} - -// Content // -void VerifyGameContents(const std::string& game_path) -{ - QtCommon::Frontend::QtProgressDialog progress(tr("Verifying integrity..."), - tr("Cancel"), - 0, - 100, - rootObject); - progress.setWindowModality(Qt::WindowModal); - progress.setMinimumDuration(100); - progress.setAutoClose(false); - progress.setAutoReset(false); - - const auto callback = [&](size_t total_size, size_t processed_size) { - progress.setValue(static_cast((processed_size * 100) / total_size)); - return progress.wasCanceled(); - }; - - const auto result = ContentManager::VerifyGameContents(*system, game_path, callback); - - switch (result) { - case ContentManager::GameVerificationResult::Success: - QtCommon::Frontend::Information(rootObject, - tr("Integrity verification succeeded!"), - tr("The operation completed successfully.")); - break; - case ContentManager::GameVerificationResult::Failed: - QtCommon::Frontend::Critical(rootObject, - tr("Integrity verification failed!"), - tr("File contents may be corrupt or missing.")); - break; - case ContentManager::GameVerificationResult::NotImplemented: - QtCommon::Frontend::Warning( - rootObject, - tr("Integrity verification couldn't be performed"), - tr("Firmware installation cancelled, firmware may be in a bad state or corrupted. " - "File contents could not be checked for validity.")); - } -} - -void InstallKeys() -{ - const QString key_source_location - = QtCommon::Frontend::GetOpenFileName(tr("Select Dumped Keys Location"), - {}, - QStringLiteral("Decryption Keys (*.keys)"), - {}, - QtCommon::Frontend::Option::ReadOnly); - - if (key_source_location.isEmpty()) { - return; - } - - FirmwareManager::KeyInstallResult result = FirmwareManager::InstallKeys(key_source_location - .toStdString(), - "keys"); - - system->GetFileSystemController().CreateFactories(*QtCommon::vfs); - - switch (result) { - case FirmwareManager::KeyInstallResult::Success: - QtCommon::Frontend::Information(tr("Decryption Keys install succeeded"), - tr("Decryption Keys were successfully installed")); - break; - default: - QtCommon::Frontend::Critical(tr("Decryption Keys install failed"), - tr(FirmwareManager::GetKeyInstallResultString(result))); - break; - } -} - -void VerifyInstalledContents() { - // Initialize a progress dialog. - QtCommon::Frontend::QtProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, QtCommon::rootObject); - progress.setWindowModality(Qt::WindowModal); - progress.setMinimumDuration(100); - progress.setAutoClose(false); - progress.setAutoReset(false); - - // Declare progress callback. - auto QtProgressCallback = [&](size_t total_size, size_t processed_size) { - progress.setValue(static_cast((processed_size * 100) / total_size)); - return progress.wasCanceled(); - }; - - const std::vector result = - ContentManager::VerifyInstalledContents(*QtCommon::system, *QtCommon::provider, QtProgressCallback); - progress.close(); - - if (result.empty()) { - QtCommon::Frontend::Information(tr("Integrity verification succeeded!"), - tr("The operation completed successfully.")); - } else { - const auto failed_names = - QString::fromStdString(fmt::format("{}", fmt::join(result, "\n"))); - QtCommon::Frontend::Critical( - tr("Integrity verification failed!"), - tr("Verification failed for the following files:\n\n%1").arg(failed_names)); - } -} - -} // namespace QtCommon::Content diff --git a/src/qt_common/qt_content_util.h b/src/qt_common/qt_content_util.h deleted file mode 100644 index b572c1c4a3..0000000000 --- a/src/qt_common/qt_content_util.h +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_CONTENT_UTIL_H -#define QT_CONTENT_UTIL_H - -#include -#include "common/common_types.h" - -namespace QtCommon::Content { - -// -bool CheckGameFirmware(u64 program_id, QObject *parent); - -static constexpr std::array FIRMWARE_RESULTS - = {"Successfully installed firmware version %1", - "", - "Unable to locate potential firmware NCA files", - "Failed to delete one or more firmware files.", - "One or more firmware files failed to copy into NAND.", - "Firmware installation cancelled, firmware may be in a bad state or corrupted." - "Restart Eden or re-install firmware."}; - -enum class FirmwareInstallResult { - Success, - NoOp, - NoNCAs, - FailedDelete, - FailedCopy, - FailedCorrupted, -}; - -inline constexpr const char *GetFirmwareInstallResultString(FirmwareInstallResult result) -{ - return FIRMWARE_RESULTS.at(static_cast(result)); -} - -void InstallFirmware(const QString &location, bool recursive); - -QString UnzipFirmwareToTmp(const QString &location); - -// Keys // -void InstallKeys(); - -// Content // -void VerifyGameContents(const std::string &game_path); -void VerifyInstalledContents(); -} -#endif // QT_CONTENT_UTIL_H diff --git a/src/qt_common/qt_frontend_util.cpp b/src/qt_common/qt_frontend_util.cpp deleted file mode 100644 index d519669ad5..0000000000 --- a/src/qt_common/qt_frontend_util.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_frontend_util.h" -#include "qt_common/qt_common.h" - -#ifdef YUZU_QT_WIDGETS -#include -#endif - -namespace QtCommon::Frontend { - -StandardButton ShowMessage( - Icon icon, const QString &title, const QString &text, StandardButtons buttons, QObject *parent) -{ -#ifdef YUZU_QT_WIDGETS - QMessageBox *box = new QMessageBox(icon, title, text, buttons, (QWidget *) parent); - return static_cast(box->exec()); -#endif - // TODO(crueter): If Qt Widgets is disabled... - // need a way to reference icon/buttons too -} - -const QString GetOpenFileName(const QString &title, - const QString &dir, - const QString &filter, - QString *selectedFilter, - Options options) -{ -#ifdef YUZU_QT_WIDGETS - return QFileDialog::getOpenFileName((QWidget *) rootObject, title, dir, filter, selectedFilter, options); -#endif -} - -} // namespace QtCommon::Frontend diff --git a/src/qt_common/qt_frontend_util.h b/src/qt_common/qt_frontend_util.h deleted file mode 100644 index f86b9e1357..0000000000 --- a/src/qt_common/qt_frontend_util.h +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_FRONTEND_UTIL_H -#define QT_FRONTEND_UTIL_H - -#include -#include "qt_common/qt_common.h" - -#ifdef YUZU_QT_WIDGETS -#include -#include -#include -#endif - -/** - * manages common functionality e.g. message boxes and such for Qt/QML - */ -namespace QtCommon::Frontend { - -Q_NAMESPACE - -#ifdef YUZU_QT_WIDGETS -using Options = QFileDialog::Options; -using Option = QFileDialog::Option; - -using StandardButton = QMessageBox::StandardButton; -using StandardButtons = QMessageBox::StandardButtons; - -using Icon = QMessageBox::Icon; -#else -enum Option { - ShowDirsOnly = 0x00000001, - DontResolveSymlinks = 0x00000002, - DontConfirmOverwrite = 0x00000004, - DontUseNativeDialog = 0x00000008, - ReadOnly = 0x00000010, - HideNameFilterDetails = 0x00000020, - DontUseCustomDirectoryIcons = 0x00000040 -}; -Q_ENUM_NS(Option) -Q_DECLARE_FLAGS(Options, Option) -Q_FLAG_NS(Options) - -enum StandardButton { - // keep this in sync with QDialogButtonBox::StandardButton and QPlatformDialogHelper::StandardButton - NoButton = 0x00000000, - Ok = 0x00000400, - Save = 0x00000800, - SaveAll = 0x00001000, - Open = 0x00002000, - Yes = 0x00004000, - YesToAll = 0x00008000, - No = 0x00010000, - NoToAll = 0x00020000, - Abort = 0x00040000, - Retry = 0x00080000, - Ignore = 0x00100000, - Close = 0x00200000, - Cancel = 0x00400000, - Discard = 0x00800000, - Help = 0x01000000, - Apply = 0x02000000, - Reset = 0x04000000, - RestoreDefaults = 0x08000000, - - FirstButton = Ok, // internal - LastButton = RestoreDefaults, // internal - - YesAll = YesToAll, // obsolete - NoAll = NoToAll, // obsolete - - Default = 0x00000100, // obsolete - Escape = 0x00000200, // obsolete - FlagMask = 0x00000300, // obsolete - ButtonMask = ~FlagMask // obsolete -}; -Q_ENUM_NS(StandardButton) - -#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) -typedef StandardButton Button; -#endif -Q_DECLARE_FLAGS(StandardButtons, StandardButton) -Q_FLAG_NS(StandardButtons) - -enum Icon { - // keep this in sync with QMessageDialogOptions::StandardIcon - NoIcon = 0, - Information = 1, - Warning = 2, - Critical = 3, - Question = 4 -}; -Q_ENUM_NS(Icon) - -#endif - -// TODO(crueter) widgets-less impl, choices et al. -StandardButton ShowMessage(Icon icon, - const QString &title, - const QString &text, - StandardButtons buttons = StandardButton::NoButton, - QObject *parent = nullptr); - -#define UTIL_OVERRIDES(level) \ - inline StandardButton level(QObject *parent, \ - const QString &title, \ - const QString &text, \ - StandardButtons buttons = StandardButton::Ok) \ - { \ - return ShowMessage(Icon::level, title, text, buttons, parent); \ - } \ - inline StandardButton level(QObject *parent, \ - const char *title, \ - const char *text, \ - StandardButtons buttons \ - = StandardButton::Ok) \ - { \ - return ShowMessage(Icon::level, tr(title), tr(text), buttons, parent); \ - } \ - inline StandardButton level(const char *title, \ - const char *text, \ - StandardButtons buttons \ - = StandardButton::Ok) \ - { \ - return ShowMessage(Icon::level, tr(title), tr(text), buttons, rootObject); \ - } \ - inline StandardButton level(const QString title, \ - const QString &text, \ - StandardButtons buttons \ - = StandardButton::Ok) \ - { \ - return ShowMessage(Icon::level, title, text, buttons, rootObject); \ - } - -UTIL_OVERRIDES(Information) -UTIL_OVERRIDES(Warning) -UTIL_OVERRIDES(Critical) -UTIL_OVERRIDES(Question) - -const QString GetOpenFileName(const QString &title, - const QString &dir, - const QString &filter, - QString *selectedFilter = nullptr, - Options options = Options()); - -} // namespace QtCommon::Frontend -#endif // QT_FRONTEND_UTIL_H diff --git a/src/qt_common/qt_game_util.cpp b/src/qt_common/qt_game_util.cpp deleted file mode 100644 index 5d0b4d8ae7..0000000000 --- a/src/qt_common/qt_game_util.cpp +++ /dev/null @@ -1,577 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_game_util.h" -#include "common/fs/fs.h" -#include "common/fs/path_util.h" -#include "core/file_sys/savedata_factory.h" -#include "core/hle/service/am/am_types.h" -#include "frontend_common/content_manager.h" -#include "qt_common.h" -#include "qt_common/uisettings.h" -#include "qt_frontend_util.h" -#include "yuzu/util/util.h" - -#include -#include -#include - -#ifdef _WIN32 -#include "common/scope_exit.h" -#include "common/string_util.h" -#include -#include -#else -#include "fmt/ostream.h" -#include -#endif - -namespace QtCommon::Game { - -bool CreateShortcutLink(const std::filesystem::path& shortcut_path, - const std::string& comment, - const std::filesystem::path& icon_path, - const std::filesystem::path& command, - const std::string& arguments, - const std::string& categories, - const std::string& keywords, - const std::string& name) -try { -#ifdef _WIN32 // Windows - HRESULT hr = CoInitialize(nullptr); - if (FAILED(hr)) { - LOG_ERROR(Frontend, "CoInitialize failed"); - return false; - } - SCOPE_EXIT - { - CoUninitialize(); - }; - IShellLinkW* ps1 = nullptr; - IPersistFile* persist_file = nullptr; - SCOPE_EXIT - { - if (persist_file != nullptr) { - persist_file->Release(); - } - if (ps1 != nullptr) { - ps1->Release(); - } - }; - HRESULT hres = CoCreateInstance(CLSID_ShellLink, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IShellLinkW, - reinterpret_cast(&ps1)); - if (FAILED(hres)) { - LOG_ERROR(Frontend, "Failed to create IShellLinkW instance"); - return false; - } - hres = ps1->SetPath(command.c_str()); - if (FAILED(hres)) { - LOG_ERROR(Frontend, "Failed to set path"); - return false; - } - if (!arguments.empty()) { - hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data()); - if (FAILED(hres)) { - LOG_ERROR(Frontend, "Failed to set arguments"); - return false; - } - } - if (!comment.empty()) { - hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data()); - if (FAILED(hres)) { - LOG_ERROR(Frontend, "Failed to set description"); - return false; - } - } - if (std::filesystem::is_regular_file(icon_path)) { - hres = ps1->SetIconLocation(icon_path.c_str(), 0); - if (FAILED(hres)) { - LOG_ERROR(Frontend, "Failed to set icon location"); - return false; - } - } - hres = ps1->QueryInterface(IID_IPersistFile, reinterpret_cast(&persist_file)); - if (FAILED(hres)) { - LOG_ERROR(Frontend, "Failed to get IPersistFile interface"); - return false; - } - hres = persist_file->Save(std::filesystem::path{shortcut_path / (name + ".lnk")}.c_str(), TRUE); - if (FAILED(hres)) { - LOG_ERROR(Frontend, "Failed to save shortcut"); - return false; - } - return true; -#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) // Any desktop NIX - std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop"); - std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); - if (!shortcut_stream.is_open()) { - LOG_ERROR(Frontend, "Failed to create shortcut"); - return false; - } - // TODO: Migrate fmt::print to std::print in futures STD C++ 23. - fmt::print(shortcut_stream, "[Desktop Entry]\n"); - fmt::print(shortcut_stream, "Type=Application\n"); - fmt::print(shortcut_stream, "Version=1.0\n"); - fmt::print(shortcut_stream, "Name={}\n", name); - if (!comment.empty()) { - fmt::print(shortcut_stream, "Comment={}\n", comment); - } - if (std::filesystem::is_regular_file(icon_path)) { - fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); - } - fmt::print(shortcut_stream, "TryExec={}\n", command.string()); - fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments); - if (!categories.empty()) { - fmt::print(shortcut_stream, "Categories={}\n", categories); - } - if (!keywords.empty()) { - fmt::print(shortcut_stream, "Keywords={}\n", keywords); - } - return true; -#else // Unsupported platform - return false; -#endif -} catch (const std::exception& e) { - LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); - return false; -} - -bool MakeShortcutIcoPath(const u64 program_id, - const std::string_view game_file_name, - std::filesystem::path& out_icon_path) -{ - // Get path to Yuzu icons directory & icon extension - std::string ico_extension = "png"; -#if defined(_WIN32) - out_icon_path = Common::FS::GetEdenPath(Common::FS::EdenPath::IconsDir); - ico_extension = "ico"; -#elif defined(__linux__) || defined(__FreeBSD__) - out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; -#endif - // Create icons directory if it doesn't exist - if (!Common::FS::CreateDirs(out_icon_path)) { - out_icon_path.clear(); - return false; - } - - // Create icon file path - out_icon_path /= (program_id == 0 ? fmt::format("eden-{}.{}", game_file_name, ico_extension) - : fmt::format("eden-{:016X}.{}", program_id, ico_extension)); - return true; -} - -void OpenEdenFolder(const Common::FS::EdenPath& path) -{ - QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(Common::FS::GetEdenPathString(path)))); -} - -void OpenRootDataFolder() -{ - OpenEdenFolder(Common::FS::EdenPath::EdenDir); -} - -void OpenNANDFolder() -{ - OpenEdenFolder(Common::FS::EdenPath::NANDDir); -} - -void OpenSDMCFolder() -{ - OpenEdenFolder(Common::FS::EdenPath::SDMCDir); -} - -void OpenModFolder() -{ - OpenEdenFolder(Common::FS::EdenPath::LoadDir); -} - -void OpenLogFolder() -{ - OpenEdenFolder(Common::FS::EdenPath::LogDir); -} - -static QString GetGameListErrorRemoving(QtCommon::Game::InstalledEntryType type) -{ - switch (type) { - case QtCommon::Game::InstalledEntryType::Game: - return tr("Error Removing Contents"); - case QtCommon::Game::InstalledEntryType::Update: - return tr("Error Removing Update"); - case QtCommon::Game::InstalledEntryType::AddOnContent: - return tr("Error Removing DLC"); - default: - return QStringLiteral("Error Removing "); - } -} - -// Game Content // -void RemoveBaseContent(u64 program_id, InstalledEntryType type) -{ - const auto res = ContentManager::RemoveBaseContent(system->GetFileSystemController(), - program_id); - if (res) { - QtCommon::Frontend::Information(rootObject, - "Successfully Removed", - "Successfully removed the installed base game."); - } else { - QtCommon::Frontend::Warning( - rootObject, - GetGameListErrorRemoving(type), - tr("The base game is not installed in the NAND and cannot be removed.")); - } -} - -void RemoveUpdateContent(u64 program_id, InstalledEntryType type) -{ - const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id); - if (res) { - QtCommon::Frontend::Information(rootObject, - "Successfully Removed", - "Successfully removed the installed update."); - } else { - QtCommon::Frontend::Warning(rootObject, - GetGameListErrorRemoving(type), - tr("There is no update installed for this title.")); - } -} - -void RemoveAddOnContent(u64 program_id, InstalledEntryType type) -{ - const size_t count = ContentManager::RemoveAllDLC(*system, program_id); - if (count == 0) { - QtCommon::Frontend::Warning(rootObject, - GetGameListErrorRemoving(type), - tr("There are no DLCs installed for this title.")); - return; - } - - QtCommon::Frontend::Information(rootObject, - tr("Successfully Removed"), - tr("Successfully removed %1 installed DLC.").arg(count)); -} - -// Global Content // - -void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target) -{ - const auto target_file_name = [target] { - switch (target) { - case GameListRemoveTarget::GlShaderCache: - return "opengl.bin"; - case GameListRemoveTarget::VkShaderCache: - return "vulkan.bin"; - default: - return ""; - } - }(); - const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir); - const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id); - const auto target_file = shader_cache_folder_path / target_file_name; - - if (!Common::FS::Exists(target_file)) { - QtCommon::Frontend::Warning(rootObject, - tr("Error Removing Transferable Shader Cache"), - tr("A shader cache for this title does not exist.")); - return; - } - if (Common::FS::RemoveFile(target_file)) { - QtCommon::Frontend::Information(rootObject, - tr("Successfully Removed"), - tr("Successfully removed the transferable shader cache.")); - } else { - QtCommon::Frontend::Warning(rootObject, - tr("Error Removing Transferable Shader Cache"), - tr("Failed to remove the transferable shader cache.")); - } -} - -void RemoveVulkanDriverPipelineCache(u64 program_id) -{ - static constexpr std::string_view target_file_name = "vulkan_pipelines.bin"; - - const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir); - const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id); - const auto target_file = shader_cache_folder_path / target_file_name; - - if (!Common::FS::Exists(target_file)) { - return; - } - if (!Common::FS::RemoveFile(target_file)) { - QtCommon::Frontend::Warning(rootObject, - tr("Error Removing Vulkan Driver Pipeline Cache"), - tr("Failed to remove the driver pipeline cache.")); - } -} - -void RemoveAllTransferableShaderCaches(u64 program_id) -{ - const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir); - const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id); - - if (!Common::FS::Exists(program_shader_cache_dir)) { - QtCommon::Frontend::Warning(rootObject, - tr("Error Removing Transferable Shader Caches"), - tr("A shader cache for this title does not exist.")); - return; - } - if (Common::FS::RemoveDirRecursively(program_shader_cache_dir)) { - QtCommon::Frontend::Information(rootObject, - tr("Successfully Removed"), - tr("Successfully removed the transferable shader caches.")); - } else { - QtCommon::Frontend::Warning( - rootObject, - tr("Error Removing Transferable Shader Caches"), - tr("Failed to remove the transferable shader cache directory.")); - } -} - -void RemoveCustomConfiguration(u64 program_id, const std::string& game_path) -{ - const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path)); - const auto config_file_name = program_id == 0 - ? Common::FS::PathToUTF8String(file_path.filename()) - .append(".ini") - : fmt::format("{:016X}.ini", program_id); - const auto custom_config_file_path = Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir) - / "custom" / config_file_name; - - if (!Common::FS::Exists(custom_config_file_path)) { - QtCommon::Frontend::Warning(rootObject, - tr("Error Removing Custom Configuration"), - tr("A custom configuration for this title does not exist.")); - return; - } - - if (Common::FS::RemoveFile(custom_config_file_path)) { - QtCommon::Frontend::Information(rootObject, - tr("Successfully Removed"), - tr("Successfully removed the custom game configuration.")); - } else { - QtCommon::Frontend::Warning(rootObject, - tr("Error Removing Custom Configuration"), - tr("Failed to remove the custom game configuration.")); - } -} - -void RemoveCacheStorage(u64 program_id) -{ - const auto nand_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir); - auto vfs_nand_dir = vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), - FileSys::OpenMode::Read); - - const auto cache_storage_path - = FileSys::SaveDataFactory::GetFullPath({}, - vfs_nand_dir, - FileSys::SaveDataSpaceId::User, - FileSys::SaveDataType::Cache, - 0 /* program_id */, - {}, - 0); - - const auto path = Common::FS::ConcatPathSafe(nand_dir, cache_storage_path); - - // Not an error if it wasn't cleared. - Common::FS::RemoveDirRecursively(path); -} - -// Metadata // -void ResetMetadata() -{ - const QString title = tr("Reset Metadata Cache"); - - if (!Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) - / "game_list/")) { - QtCommon::Frontend::Warning(rootObject, title, tr("The metadata cache is already empty.")); - } else if (Common::FS::RemoveDirRecursively( - Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list")) { - QtCommon::Frontend::Information(rootObject, - title, - tr("The operation completed successfully.")); - UISettings::values.is_game_list_reload_pending.exchange(true); - } else { - QtCommon::Frontend::Warning( - rootObject, - title, - tr("The metadata cache couldn't be deleted. It might be in use or non-existent.")); - } -} - -// Uhhh // - -// Messages in pre-defined message boxes for less code spaghetti -inline constexpr bool CreateShortcutMessagesGUI(ShortcutMessages imsg, const QString& game_title) -{ - int result = 0; - QMessageBox::StandardButtons buttons; - switch (imsg) { - case ShortcutMessages::Fullscreen: - buttons = QMessageBox::Yes | QMessageBox::No; - result - = QtCommon::Frontend::Information(tr("Create Shortcut"), - tr("Do you want to launch the game in fullscreen?"), - buttons); - return result == QMessageBox::Yes; - case ShortcutMessages::Success: - QtCommon::Frontend::Information(tr("Shortcut Created"), - tr("Successfully created a shortcut to %1").arg(game_title)); - return false; - case ShortcutMessages::Volatile: - buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel; - result = QtCommon::Frontend::Warning( - tr("Shortcut may be Volatile!"), - tr("This will create a shortcut to the current AppImage. This may " - "not work well if you update. Continue?"), - buttons); - return result == QMessageBox::Ok; - default: - buttons = QMessageBox::Ok; - QtCommon::Frontend::Critical(tr("Failed to Create Shortcut"), - tr("Failed to create a shortcut to %1").arg(game_title), - buttons); - return false; - } -} - -void CreateShortcut(const std::string& game_path, - const u64 program_id, - const std::string& game_title_, - const ShortcutTarget &target, - std::string arguments_, - const bool needs_title) -{ - // Get path to Eden executable - std::filesystem::path command = GetEdenCommand(); - - // Shortcut path - std::filesystem::path shortcut_path = GetShortcutPath(target); - - if (!std::filesystem::exists(shortcut_path)) { - CreateShortcutMessagesGUI(ShortcutMessages::Failed, - QString::fromStdString(shortcut_path.generic_string())); - LOG_ERROR(Frontend, "Invalid shortcut target {}", shortcut_path.generic_string()); - return; - } - - const FileSys::PatchManager pm{program_id, QtCommon::system->GetFileSystemController(), - QtCommon::system->GetContentProvider()}; - const auto control = pm.GetControlMetadata(); - const auto loader = - Loader::GetLoader(*QtCommon::system, QtCommon::vfs->OpenFile(game_path, FileSys::OpenMode::Read)); - - std::string game_title{game_title_}; - - // Delete illegal characters from title - if (needs_title) { - game_title = fmt::format("{:016X}", program_id); - if (control.first != nullptr) { - game_title = control.first->GetApplicationName(); - } else { - loader->ReadTitle(game_title); - } - } - - const std::string illegal_chars = "<>:\"/\\|?*."; - for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) { - if (illegal_chars.find(*it) != std::string::npos) { - game_title.erase(it.base() - 1); - } - } - - const QString qgame_title = QString::fromStdString(game_title); - - // Get icon from game file - std::vector icon_image_file{}; - if (control.second != nullptr) { - icon_image_file = control.second->ReadAllBytes(); - } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { - LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); - } - - QImage icon_data = - QImage::fromData(icon_image_file.data(), static_cast(icon_image_file.size())); - std::filesystem::path out_icon_path; - if (QtCommon::Game::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) { - if (!SaveIconToFile(out_icon_path, icon_data)) { - LOG_ERROR(Frontend, "Could not write icon to file"); - } - } else { - QtCommon::Frontend::Critical( - tr("Create Icon"), - tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.") - .arg(QString::fromStdString(out_icon_path.string()))); - } - -#if defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) - // Special case for AppImages - // Warn once if we are making a shortcut to a volatile AppImage - if (command.string().ends_with(".AppImage") && !UISettings::values.shortcut_already_warned) { - if (!CreateShortcutMessagesGUI(ShortcutMessages::Volatile, qgame_title)) { - return; - } - UISettings::values.shortcut_already_warned = true; - } -#endif - - // Create shortcut - std::string arguments{arguments_}; - if (CreateShortcutMessagesGUI(ShortcutMessages::Fullscreen, qgame_title)) { - arguments = "-f " + arguments; - } - const std::string comment = fmt::format("Start {:s} with the Eden Emulator", game_title); - const std::string categories = "Game;Emulator;Qt;"; - const std::string keywords = "Switch;Nintendo;"; - - if (QtCommon::Game::CreateShortcutLink(shortcut_path, comment, out_icon_path, command, - arguments, categories, keywords, game_title)) { - CreateShortcutMessagesGUI(ShortcutMessages::Success, - qgame_title); - return; - } - CreateShortcutMessagesGUI(ShortcutMessages::Failed, - qgame_title); -} - -constexpr std::string GetShortcutPath(ShortcutTarget target) { - { - std::string shortcut_path{}; - if (target == ShortcutTarget::Desktop) { - shortcut_path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) - .toStdString(); - } else if (target == ShortcutTarget::Applications) { - shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) - .toStdString(); - } - - return shortcut_path; - } -} - -void CreateHomeMenuShortcut(ShortcutTarget target) { - constexpr u64 QLaunchId = static_cast(Service::AM::AppletProgramId::QLaunch); - auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents(); - if (!bis_system) { - QtCommon::Frontend::Warning(tr("No firmware available"), - tr("Please install firmware to use the home menu.")); - return; - } - - auto qlaunch_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); - if (!qlaunch_nca) { - QtCommon::Frontend::Warning(tr("Home Menu Applet"), - tr("Home Menu is not available. Please reinstall firmware.")); - return; - } - - auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); - const auto game_path = qlaunch_applet_nca->GetFullPath(); - - // TODO(crueter): Make this use the Eden icon - CreateShortcut(game_path, QLaunchId, "Switch Home Menu", target, "-qlaunch", false); -} - - -} // namespace QtCommon::Game diff --git a/src/qt_common/qt_game_util.h b/src/qt_common/qt_game_util.h deleted file mode 100644 index 0a21208659..0000000000 --- a/src/qt_common/qt_game_util.h +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_GAME_UTIL_H -#define QT_GAME_UTIL_H - -#include -#include -#include "common/fs/path_util.h" - -namespace QtCommon::Game { - -enum class InstalledEntryType { - Game, - Update, - AddOnContent, -}; - -enum class GameListRemoveTarget { - GlShaderCache, - VkShaderCache, - AllShaderCache, - CustomConfiguration, - CacheStorage, -}; - -enum class ShortcutTarget { - Desktop, - Applications, -}; - -enum class ShortcutMessages{ - Fullscreen = 0, - Success = 1, - Volatile = 2, - Failed = 3 -}; - -bool CreateShortcutLink(const std::filesystem::path& shortcut_path, - const std::string& comment, - const std::filesystem::path& icon_path, - const std::filesystem::path& command, - const std::string& arguments, - const std::string& categories, - const std::string& keywords, - const std::string& name); - -bool MakeShortcutIcoPath(const u64 program_id, - const std::string_view game_file_name, - std::filesystem::path& out_icon_path); - -void OpenEdenFolder(const Common::FS::EdenPath &path); -void OpenRootDataFolder(); -void OpenNANDFolder(); -void OpenSDMCFolder(); -void OpenModFolder(); -void OpenLogFolder(); - -void RemoveBaseContent(u64 program_id, InstalledEntryType type); -void RemoveUpdateContent(u64 program_id, InstalledEntryType type); -void RemoveAddOnContent(u64 program_id, InstalledEntryType type); - -void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target); -void RemoveVulkanDriverPipelineCache(u64 program_id); -void RemoveAllTransferableShaderCaches(u64 program_id); -void RemoveCustomConfiguration(u64 program_id, const std::string& game_path); -void RemoveCacheStorage(u64 program_id); - -// Metadata // -void ResetMetadata(); - -// Shortcuts // -void CreateShortcut(const std::string& game_path, - const u64 program_id, - const std::string& game_title_, - const ShortcutTarget& target, - std::string arguments_, - const bool needs_title); - -constexpr std::string GetShortcutPath(ShortcutTarget target); -void CreateHomeMenuShortcut(ShortcutTarget target); - -} - -#endif // QT_GAME_UTIL_H diff --git a/src/qt_common/qt_meta.cpp b/src/qt_common/qt_meta.cpp deleted file mode 100644 index 67ae659771..0000000000 --- a/src/qt_common/qt_meta.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_meta.h" -#include "common/common_types.h" -#include "core/core.h" -#include "core/frontend/applets/cabinet.h" -#include "core/frontend/applets/controller.h" -#include "core/frontend/applets/profile_select.h" -#include "core/frontend/applets/software_keyboard.h" -#include "core/hle/service/am/frontend/applet_web_browser_types.h" - -namespace QtCommon::Meta { - -void RegisterMetaTypes() -{ - // Register integral and floating point types - qRegisterMetaType("u8"); - qRegisterMetaType("u16"); - qRegisterMetaType("u32"); - qRegisterMetaType("u64"); - qRegisterMetaType("u128"); - qRegisterMetaType("s8"); - qRegisterMetaType("s16"); - qRegisterMetaType("s32"); - qRegisterMetaType("s64"); - qRegisterMetaType("f32"); - qRegisterMetaType("f64"); - - // Register string types - qRegisterMetaType("std::string"); - qRegisterMetaType("std::wstring"); - qRegisterMetaType("std::u8string"); - qRegisterMetaType("std::u16string"); - qRegisterMetaType("std::u32string"); - qRegisterMetaType("std::string_view"); - qRegisterMetaType("std::wstring_view"); - qRegisterMetaType("std::u8string_view"); - qRegisterMetaType("std::u16string_view"); - qRegisterMetaType("std::u32string_view"); - - // Register applet types - - // Cabinet Applet - qRegisterMetaType("Core::Frontend::CabinetParameters"); - qRegisterMetaType>( - "std::shared_ptr"); - - // Controller Applet - qRegisterMetaType("Core::Frontend::ControllerParameters"); - - // Profile Select Applet - qRegisterMetaType( - "Core::Frontend::ProfileSelectParameters"); - - // Software Keyboard Applet - qRegisterMetaType( - "Core::Frontend::KeyboardInitializeParameters"); - qRegisterMetaType( - "Core::Frontend::InlineAppearParameters"); - qRegisterMetaType("Core::Frontend::InlineTextParameters"); - qRegisterMetaType("Service::AM::Frontend::SwkbdResult"); - qRegisterMetaType( - "Service::AM::Frontend::SwkbdTextCheckResult"); - qRegisterMetaType( - "Service::AM::Frontend::SwkbdReplyType"); - - // Web Browser Applet - qRegisterMetaType("Service::AM::Frontend::WebExitReason"); - - // Register loader types - qRegisterMetaType("Core::SystemResultStatus"); -} - -} diff --git a/src/qt_common/qt_meta.h b/src/qt_common/qt_meta.h deleted file mode 100644 index c0a37db983..0000000000 --- a/src/qt_common/qt_meta.h +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_META_H -#define QT_META_H - -#include - -namespace QtCommon::Meta { - -// -void RegisterMetaTypes(); - -} -#endif // QT_META_H diff --git a/src/qt_common/qt_path_util.cpp b/src/qt_common/qt_path_util.cpp deleted file mode 100644 index 761e6e8405..0000000000 --- a/src/qt_common/qt_path_util.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_path_util.h" -#include -#include -#include -#include "common/fs/fs.h" -#include "common/fs/path_util.h" -#include "qt_common/qt_frontend_util.h" -#include - -namespace QtCommon::Path { - -bool OpenShaderCache(u64 program_id, QObject *parent) -{ - const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir); - const auto shader_cache_folder_path{shader_cache_dir / fmt::format("{:016x}", program_id)}; - if (!Common::FS::CreateDirs(shader_cache_folder_path)) { - QtCommon::Frontend::ShowMessage(QMessageBox::Warning, "Error Opening Shader Cache", "Failed to create or open shader cache for this title, ensure your app data directory has write permissions.", QMessageBox::Ok, parent); - } - - const auto shader_path_string{Common::FS::PathToUTF8String(shader_cache_folder_path)}; - const auto qt_shader_cache_path = QString::fromStdString(shader_path_string); - return QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path)); -} - -} diff --git a/src/qt_common/qt_path_util.h b/src/qt_common/qt_path_util.h deleted file mode 100644 index 855b06caa9..0000000000 --- a/src/qt_common/qt_path_util.h +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_PATH_UTIL_H -#define QT_PATH_UTIL_H - -#include "common/common_types.h" -#include - -namespace QtCommon::Path { bool OpenShaderCache(u64 program_id, QObject *parent); } - -#endif // QT_PATH_UTIL_H diff --git a/src/qt_common/qt_progress_dialog.cpp b/src/qt_common/qt_progress_dialog.cpp deleted file mode 100644 index b4bf74c8bd..0000000000 --- a/src/qt_common/qt_progress_dialog.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_progress_dialog.h" diff --git a/src/qt_common/qt_progress_dialog.h b/src/qt_common/qt_progress_dialog.h deleted file mode 100644 index 17f6817ffa..0000000000 --- a/src/qt_common/qt_progress_dialog.h +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_PROGRESS_DIALOG_H -#define QT_PROGRESS_DIALOG_H - -#include - -#ifdef YUZU_QT_WIDGETS -#include -#endif - -namespace QtCommon::Frontend { -#ifdef YUZU_QT_WIDGETS - -using QtProgressDialog = QProgressDialog; - -// TODO(crueter): QML impl -#else -class QtProgressDialog -{ -public: - QtProgressDialog(const QString &labelText, - const QString &cancelButtonText, - int minimum, - int maximum, - QObject *parent = nullptr, - Qt::WindowFlags f = Qt::WindowFlags()); - - bool wasCanceled() const; - void setWindowModality(Qt::WindowModality modality); - void setMinimumDuration(int durationMs); - void setAutoClose(bool autoClose); - void setAutoReset(bool autoReset); - -public slots: - void setLabelText(QString &text); - void setRange(int min, int max); - void setValue(int progress); - bool close(); - - void show(); -}; -#endif // YUZU_QT_WIDGETS - -} -#endif // QT_PROGRESS_DIALOG_H diff --git a/src/qt_common/qt_rom_util.cpp b/src/qt_common/qt_rom_util.cpp deleted file mode 100644 index 08ccb05a97..0000000000 --- a/src/qt_common/qt_rom_util.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_rom_util.h" - -#include - -namespace QtCommon::ROM { - -bool RomFSRawCopy(size_t total_size, - size_t& read_size, - QtProgressCallback callback, - const FileSys::VirtualDir& src, - const FileSys::VirtualDir& dest, - bool full) -{ - // TODO(crueter) - // if (src == nullptr || dest == nullptr || !src->IsReadable() || !dest->IsWritable()) - // return false; - // if (dialog.wasCanceled()) - // return false; - - // std::vector buffer(CopyBufferSize); - // auto last_timestamp = std::chrono::steady_clock::now(); - - // const auto QtRawCopy = [&](const FileSys::VirtualFile& src_file, - // const FileSys::VirtualFile& dest_file) { - // if (src_file == nullptr || dest_file == nullptr) { - // return false; - // } - // if (!dest_file->Resize(src_file->GetSize())) { - // return false; - // } - - // for (std::size_t i = 0; i < src_file->GetSize(); i += buffer.size()) { - // if (dialog.wasCanceled()) { - // dest_file->Resize(0); - // return false; - // } - - // using namespace std::literals::chrono_literals; - // const auto new_timestamp = std::chrono::steady_clock::now(); - - // if ((new_timestamp - last_timestamp) > 33ms) { - // last_timestamp = new_timestamp; - // dialog.setValue( - // static_cast(std::min(read_size, total_size) * 100 / total_size)); - // QCoreApplication::processEvents(); - // } - - // const auto read = src_file->Read(buffer.data(), buffer.size(), i); - // dest_file->Write(buffer.data(), read, i); - - // read_size += read; - // } - - // return true; - // }; - - // if (full) { - // for (const auto& file : src->GetFiles()) { - // const auto out = VfsDirectoryCreateFileWrapper(dest, file->GetName()); - // if (!QtRawCopy(file, out)) - // return false; - // } - // } - - // for (const auto& dir : src->GetSubdirectories()) { - // const auto out = dest->CreateSubdirectory(dir->GetName()); - // if (!RomFSRawCopy(total_size, read_size, dialog, dir, out, full)) - // return false; - // } - - // return true; - return true; -} - -} diff --git a/src/qt_common/qt_rom_util.h b/src/qt_common/qt_rom_util.h deleted file mode 100644 index f76b09753d..0000000000 --- a/src/qt_common/qt_rom_util.h +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef QT_ROM_UTIL_H -#define QT_ROM_UTIL_H - -#include "qt_common/qt_common.h" -#include - -namespace QtCommon::ROM { - -bool RomFSRawCopy(size_t total_size, - size_t& read_size, - QtProgressCallback callback, - const FileSys::VirtualDir& src, - const FileSys::VirtualDir& dest, - bool full); - -} -#endif // QT_ROM_UTIL_H diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp index 8cd20a2f5c..3919d63268 100644 --- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp +++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp @@ -123,7 +123,7 @@ Id RegAlloc::Alloc(bool is_long) { if (use[reg]) { continue; } - num_regs = (std::max)(num_regs, reg + 1); + num_regs = std::max(num_regs, reg + 1); use[reg] = true; Id ret{}; ret.is_valid.Assign(1); diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp index 99ed4cbc19..49397c9b2e 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_integer.cpp @@ -39,7 +39,7 @@ void EmitIAdd32(EmitContext& ctx, IR::Inst& inst, std::string_view a, std::strin // which may be overwritten by the result of the addition if (IR::Inst * overflow{inst.GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)}) { // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c - constexpr u32 s32_max{static_cast((std::numeric_limits::max)())}; + constexpr u32 s32_max{static_cast(std::numeric_limits::max())}; const auto sub_a{fmt::format("{}u-{}", s32_max, a)}; const auto positive_result{fmt::format("int({})>int({})", b, sub_a)}; const auto negative_result{fmt::format("int({})::max)())), + ctx.OpBitcast(ctx.F32[1], ctx.Const(std::numeric_limits::max())), ctx.f32_zero_value); case IR::Attribute::PointSpriteS: return ctx.OpLoad(ctx.F32[1], diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index bf47d4ee96..960bdea6f1 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -42,7 +42,7 @@ Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { SetSignFlag(ctx, inst, result); if (IR::Inst * overflow{inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)}) { // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c - constexpr u32 s32_max{static_cast((std::numeric_limits::max)())}; + constexpr u32 s32_max{static_cast(std::numeric_limits::max())}; const Id is_positive{ctx.OpSGreaterThanEqual(ctx.U1, a, ctx.u32_zero_value)}; const Id sub_a{ctx.OpISub(ctx.U32[1], ctx.Const(s32_max), a)}; diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 745dead6c4..388ddce2c8 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -1593,7 +1593,7 @@ void EmitContext::DefineOutputs(const IR::Program& program) { throw NotImplementedException("Storing ClipDistance in fragment stage"); } if (profile.max_user_clip_distances > 0) { - const u32 used{(std::min)(profile.max_user_clip_distances, 8u)}; + const u32 used{std::min(profile.max_user_clip_distances, 8u)}; const std::array zero{f32_zero_value, f32_zero_value, f32_zero_value, f32_zero_value, f32_zero_value, f32_zero_value, f32_zero_value, f32_zero_value}; diff --git a/src/shader_recompiler/frontend/maxwell/decode.cpp b/src/shader_recompiler/frontend/maxwell/decode.cpp index 5afe8cbb14..47111a0501 100644 --- a/src/shader_recompiler/frontend/maxwell/decode.cpp +++ b/src/shader_recompiler/frontend/maxwell/decode.cpp @@ -73,7 +73,7 @@ constexpr auto ENCODINGS{SortedEncodings()}; constexpr int WidestLeftBits() { int bits{64}; for (const InstEncoding& encoding : ENCODINGS) { - bits = (std::min)(bits, std::countr_zero(encoding.mask_value.mask)); + bits = std::min(bits, std::countr_zero(encoding.mask_value.mask)); } return 64 - bits; } @@ -87,7 +87,7 @@ constexpr size_t ToFastLookupIndex(u64 value) { constexpr size_t FastLookupSize() { size_t max_width{}; for (const InstEncoding& encoding : ENCODINGS) { - max_width = (std::max)(max_width, ToFastLookupIndex(encoding.mask_value.mask)); + max_width = std::max(max_width, ToFastLookupIndex(encoding.mask_value.mask)); } return max_width + 1; } diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp index 21d3c2fe53..85c18d9422 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp @@ -60,28 +60,28 @@ std::pair ClampBounds(DestFormat format, bool is_signed) { if (is_signed) { switch (format) { case DestFormat::I16: - return {static_cast((std::numeric_limits::max)()), - static_cast((std::numeric_limits::min)())}; + return {static_cast(std::numeric_limits::max()), + static_cast(std::numeric_limits::min())}; case DestFormat::I32: - return {static_cast((std::numeric_limits::max)()), - static_cast((std::numeric_limits::min)())}; + return {static_cast(std::numeric_limits::max()), + static_cast(std::numeric_limits::min())}; case DestFormat::I64: - return {static_cast((std::numeric_limits::max)()), - static_cast((std::numeric_limits::min)())}; + return {static_cast(std::numeric_limits::max()), + static_cast(std::numeric_limits::min())}; default: break; } } else { switch (format) { case DestFormat::I16: - return {static_cast((std::numeric_limits::max)()), - static_cast((std::numeric_limits::min)())}; + return {static_cast(std::numeric_limits::max()), + static_cast(std::numeric_limits::min())}; case DestFormat::I32: - return {static_cast((std::numeric_limits::max)()), - static_cast((std::numeric_limits::min)())}; + return {static_cast(std::numeric_limits::max()), + static_cast(std::numeric_limits::min())}; case DestFormat::I64: - return {static_cast((std::numeric_limits::max)()), - static_cast((std::numeric_limits::min)())}; + return {static_cast(std::numeric_limits::max()), + static_cast(std::numeric_limits::min())}; default: break; } diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp index 9631fd9dfe..a2dc0f4a6e 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp @@ -114,9 +114,9 @@ void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) { // Only negate if the input isn't the lowest value IR::U1 is_least; if (src_bitsize == 64) { - is_least = v.ir.IEqual(src, v.ir.Imm64((std::numeric_limits::min)())); + is_least = v.ir.IEqual(src, v.ir.Imm64(std::numeric_limits::min())); } else if (src_bitsize == 32) { - is_least = v.ir.IEqual(src, v.ir.Imm32((std::numeric_limits::min)())); + is_least = v.ir.IEqual(src, v.ir.Imm32(std::numeric_limits::min())); } else { const IR::U32 least_value{v.ir.Imm32(-(1 << (src_bitsize - 1)))}; is_least = v.ir.IEqual(src, least_value); diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index a9559b0d7a..321ea625bc 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -336,7 +336,7 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b } result.stage = Stage::VertexB; result.info = vertex_a.info; - result.local_memory_size = (std::max)(vertex_a.local_memory_size, vertex_b.local_memory_size); + result.local_memory_size = std::max(vertex_a.local_memory_size, vertex_b.local_memory_size); result.info.loads.mask |= vertex_b.info.loads.mask; result.info.stores.mask |= vertex_b.info.stores.mask; diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index 1fa39034a8..cb82a326c1 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -509,7 +509,7 @@ void VisitUsages(Info& info, IR::Inst& inst) { u32 element_size = GetElementSize(info.used_constant_buffer_types, inst.GetOpcode()); u32& size{info.constant_buffer_used_sizes[index.U32()]}; if (offset.IsImmediate()) { - size = Common::AlignUp((std::max)(size, offset.U32() + element_size), 16u); + size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u); } else { size = 0x10'000; } diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index 160c1aaea5..12d7b2d7fa 100644 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp @@ -905,7 +905,7 @@ void FoldConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst) { } void FoldDriverConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst, u32 which_bank, - u32 offset_start = 0, u32 offset_end = (std::numeric_limits::max)()) { + u32 offset_start = 0, u32 offset_end = std::numeric_limits::max()) { const IR::Value bank{inst.Arg(0)}; const IR::Value offset{inst.Arg(1)}; if (!bank.IsImmediate() || !offset.IsImmediate()) { diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index 7ff1961172..afd880526a 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -7,9 +7,7 @@ #include #include #include -#include -#include -#include + #include #include "shader_recompiler/environment.h" @@ -179,93 +177,6 @@ bool IsBindless(const IR::Inst& inst) { bool IsTextureInstruction(const IR::Inst& inst) { return IndexedInstruction(inst) != IR::Opcode::Void; } -// Per-pass caches - struct CbufWordKey { - u32 index; - u32 offset; - bool operator==(const CbufWordKey& o) const noexcept { - return index == o.index && offset == o.offset; - } - }; - struct CbufWordKeyHash { - size_t operator()(const CbufWordKey& k) const noexcept { - return (static_cast(k.index) << 32) ^ k.offset; - } - }; - - struct HandleKey { - u32 index, offset, shift_left; - u32 sec_index, sec_offset, sec_shift_left; - bool has_secondary; - bool operator==(const HandleKey& o) const noexcept { - return std::tie(index, offset, shift_left, - sec_index, sec_offset, sec_shift_left, has_secondary) - == std::tie(o.index, o.offset, o.shift_left, - o.sec_index, o.sec_offset, o.sec_shift_left, o.has_secondary); - } - }; - struct HandleKeyHash { - size_t operator()(const HandleKey& k) const noexcept { - size_t h = (static_cast(k.index) << 32) ^ k.offset; - h ^= (static_cast(k.shift_left) << 1); - h ^= (static_cast(k.sec_index) << 33) ^ (static_cast(k.sec_offset) << 2); - h ^= (static_cast(k.sec_shift_left) << 3); - h ^= k.has_secondary ? 0x9e3779b97f4a7c15ULL : 0ULL; - return h; - } - }; - -// Thread-local(may implement multithreading in future *wink*) - thread_local std::unordered_map g_cbuf_word_cache; - thread_local std::unordered_map g_handle_cache; - thread_local std::unordered_map g_track_cache; - - static inline u32 ReadCbufCached(Environment& env, u32 index, u32 offset) { - const CbufWordKey k{index, offset}; - if (auto it = g_cbuf_word_cache.find(k); it != g_cbuf_word_cache.end()) return it->second; - const u32 v = env.ReadCbufValue(index, offset); - g_cbuf_word_cache.emplace(k, v); - return v; - } - - static inline u32 GetTextureHandleCached(Environment& env, const ConstBufferAddr& cbuf) { - const u32 sec_idx = cbuf.has_secondary ? cbuf.secondary_index : cbuf.index; - const u32 sec_off = cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset; - const HandleKey hk{cbuf.index, cbuf.offset, cbuf.shift_left, - sec_idx, sec_off, cbuf.secondary_shift_left, cbuf.has_secondary}; - if (auto it = g_handle_cache.find(hk); it != g_handle_cache.end()) return it->second; - - const u32 lhs = ReadCbufCached(env, cbuf.index, cbuf.offset) << cbuf.shift_left; - const u32 rhs = ReadCbufCached(env, sec_idx, sec_off) << cbuf.secondary_shift_left; - const u32 handle = lhs | rhs; - g_handle_cache.emplace(hk, handle); - return handle; - } - -// Cached variants of existing helpers - static inline TextureType ReadTextureTypeCached(Environment& env, const ConstBufferAddr& cbuf) { - return env.ReadTextureType(GetTextureHandleCached(env, cbuf)); - } - static inline TexturePixelFormat ReadTexturePixelFormatCached(Environment& env, - const ConstBufferAddr& cbuf) { - return env.ReadTexturePixelFormat(GetTextureHandleCached(env, cbuf)); - } - static inline bool IsTexturePixelFormatIntegerCached(Environment& env, - const ConstBufferAddr& cbuf) { - return env.IsTexturePixelFormatInteger(GetTextureHandleCached(env, cbuf)); - } - - - std::optional Track(const IR::Value& value, Environment& env); - static inline std::optional TrackCached(const IR::Value& v, Environment& env) { - if (const IR::Inst* key = v.InstRecursive()) { - if (auto it = g_track_cache.find(key); it != g_track_cache.end()) return it->second; - auto found = Track(v, env); - if (found) g_track_cache.emplace(key, *found); - return found; - } - return Track(v, env); - } std::optional TryGetConstBuffer(const IR::Inst* inst, Environment& env); @@ -292,7 +203,7 @@ std::optional TryGetConstant(IR::Value& value, Environment& env) { return std::nullopt; } const auto offset_number = offset.U32(); - return ReadCbufCached(env, index_number, offset_number); + return env.ReadCbufValue(index_number, offset_number); } std::optional TryGetConstBuffer(const IR::Inst* inst, Environment& env) { @@ -300,8 +211,8 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme default: return std::nullopt; case IR::Opcode::BitwiseOr32: { - std::optional lhs{TrackCached(inst->Arg(0), env)}; - std::optional rhs{TrackCached(inst->Arg(1), env)}; + std::optional lhs{Track(inst->Arg(0), env)}; + std::optional rhs{Track(inst->Arg(1), env)}; if (!lhs || !rhs) { return std::nullopt; } @@ -331,7 +242,7 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme if (!shift.IsImmediate()) { return std::nullopt; } - std::optional lhs{TrackCached(inst->Arg(0), env)}; + std::optional lhs{Track(inst->Arg(0), env)}; if (lhs) { lhs->shift_left = shift.U32(); } @@ -360,7 +271,7 @@ std::optional TryGetConstBuffer(const IR::Inst* inst, Environme return std::nullopt; } while (false); } - std::optional lhs{TrackCached(op1, env)}; + std::optional lhs{Track(op1, env)}; if (lhs) { lhs->shift_left = static_cast(std::countr_zero(op2.U32())); } @@ -435,7 +346,7 @@ static ConstBufferAddr last_valid_addr = ConstBufferAddr{ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { ConstBufferAddr addr; if (IsBindless(inst)) { - const std::optional track_addr{TrackCached(inst.Arg(0), env)}; + const std::optional track_addr{Track(inst.Arg(0), env)}; if (!track_addr) { //throw NotImplementedException("Failed to track bindless texture constant buffer"); @@ -473,15 +384,15 @@ u32 GetTextureHandle(Environment& env, const ConstBufferAddr& cbuf) { return lhs_raw | rhs_raw; } - [[maybe_unused]]TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { +TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { return env.ReadTextureType(GetTextureHandle(env, cbuf)); } - [[maybe_unused]]TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) { +TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) { return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf)); } - [[maybe_unused]]bool IsTexturePixelFormatInteger(Environment& env, const ConstBufferAddr& cbuf) { +bool IsTexturePixelFormatInteger(Environment& env, const ConstBufferAddr& cbuf) { return env.IsTexturePixelFormatInteger(GetTextureHandle(env, cbuf)); } @@ -606,11 +517,11 @@ void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_ case TexturePixelFormat::A8B8G8R8_SNORM: case TexturePixelFormat::R8G8_SNORM: case TexturePixelFormat::R8_SNORM: - return 1.f / (std::numeric_limits::max)(); + return 1.f / std::numeric_limits::max(); case TexturePixelFormat::R16G16B16A16_SNORM: case TexturePixelFormat::R16G16_SNORM: case TexturePixelFormat::R16_SNORM: - return 1.f / (std::numeric_limits::max)(); + return 1.f / std::numeric_limits::max(); default: throw InvalidArgument("Invalid texture pixel format"); } @@ -632,10 +543,6 @@ void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_ } // Anonymous namespace void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info) { - // reset per-pass caches - g_cbuf_word_cache.clear(); - g_handle_cache.clear(); - g_track_cache.clear(); TextureInstVector to_replace; for (IR::Block* const block : program.post_order_blocks) { for (IR::Inst& inst : block->Instructions()) { @@ -646,9 +553,11 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo } } // Sort instructions to visit textures by constant buffer index, then by offset - std::ranges::sort(to_replace, [](const auto& a, const auto& b) { - if (a.cbuf.index != b.cbuf.index) return a.cbuf.index < b.cbuf.index; - return a.cbuf.offset < b.cbuf.offset; + std::ranges::sort(to_replace, [](const auto& lhs, const auto& rhs) { + return lhs.cbuf.offset < rhs.cbuf.offset; + }); + std::stable_sort(to_replace.begin(), to_replace.end(), [](const auto& lhs, const auto& rhs) { + return lhs.cbuf.index < rhs.cbuf.index; }); Descriptors descriptors{ program.info.texture_buffer_descriptors, @@ -666,14 +575,14 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo bool is_multisample{false}; switch (inst->GetOpcode()) { case IR::Opcode::ImageQueryDimensions: - flags.type.Assign(ReadTextureTypeCached(env, cbuf)); + flags.type.Assign(ReadTextureType(env, cbuf)); inst->SetFlags(flags); break; case IR::Opcode::ImageSampleImplicitLod: if (flags.type != TextureType::Color2D) { break; } - if (ReadTextureTypeCached(env, cbuf) == TextureType::Color2DRect) { + if (ReadTextureType(env, cbuf) == TextureType::Color2DRect) { PatchImageSampleImplicitLod(*texture_inst.block, *texture_inst.inst); } break; @@ -687,7 +596,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo if (flags.type != TextureType::Color1D) { break; } - if (ReadTextureTypeCached(env, cbuf) == TextureType::Buffer) { + if (ReadTextureType(env, cbuf) == TextureType::Buffer) { // Replace with the bound texture type only when it's a texture buffer // If the instruction is 1D and the bound type is 2D, don't change the code and let // the rasterizer robustness handle it @@ -718,7 +627,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo } const bool is_written{inst->GetOpcode() != IR::Opcode::ImageRead}; const bool is_read{inst->GetOpcode() != IR::Opcode::ImageWrite}; - const bool is_integer{IsTexturePixelFormatIntegerCached(env, cbuf)}; + const bool is_integer{IsTexturePixelFormatInteger(env, cbuf)}; if (flags.type == TextureType::Buffer) { index = descriptors.Add(ImageBufferDescriptor{ .format = flags.image_format, @@ -782,16 +691,16 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo if (cbuf.count > 1) { const auto insert_point{IR::Block::InstructionList::s_iterator_to(*inst)}; IR::IREmitter ir{*texture_inst.block, insert_point}; - const IR::U32 shift{ir.Imm32(DESCRIPTOR_SIZE_SHIFT)}; - inst->SetArg(0, ir.UMin(ir.ShiftRightLogical(cbuf.dynamic_offset, shift), - ir.Imm32(DESCRIPTOR_SIZE - 1))); + const IR::U32 shift{ir.Imm32(std::countr_zero(DESCRIPTOR_SIZE))}; + inst->SetArg(0, ir.UMin(ir.ShiftRightArithmetic(cbuf.dynamic_offset, shift), + ir.Imm32(DESCRIPTOR_SIZE - 1))); } else { inst->SetArg(0, IR::Value{}); } if (!host_info.support_snorm_render_buffer && inst->GetOpcode() == IR::Opcode::ImageFetch && flags.type == TextureType::Buffer) { - const auto pixel_format = ReadTexturePixelFormatCached(env, cbuf); + const auto pixel_format = ReadTexturePixelFormat(env, cbuf); if (IsPixelFormatSNorm(pixel_format)) { PatchTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format); } diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 3c2473266a..89fe7a35f9 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -332,10 +332,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS}) add_dependencies(video_core host_shaders) target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) -target_link_libraries(video_core PRIVATE sirit) - -# Header-only stuff needed by all dependent targets -target_link_libraries(video_core PUBLIC Vulkan::UtilityHeaders GPUOpen::VulkanMemoryAllocator) +target_link_libraries(video_core PRIVATE sirit Vulkan::Headers Vulkan::UtilityHeaders GPUOpen::VulkanMemoryAllocator) if (ENABLE_NSIGHT_AFTERMATH) if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) @@ -373,7 +370,7 @@ else() set_source_files_properties(vulkan_common/vma.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-unused-variable;-Wno-unused-parameter;-Wno-missing-field-initializers") # Get around GCC failing with intrinsics in Debug - if (CXX_GCC AND CMAKE_BUILD_TYPE MATCHES "Debug") + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_BUILD_TYPE MATCHES "Debug") set_source_files_properties(host1x/vic.cpp PROPERTIES COMPILE_OPTIONS "-O2") endif() endif() diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 94ef1a48df..0cd6861b6d 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -36,14 +36,14 @@ BufferCache

::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R const s64 device_local_memory = static_cast(runtime.GetDeviceLocalMemory()); const s64 min_spacing_expected = device_local_memory - 1_GiB; const s64 min_spacing_critical = device_local_memory - 512_MiB; - const s64 mem_threshold = (std::min)(device_local_memory, TARGET_THRESHOLD); + const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD); const s64 min_vacancy_expected = (6 * mem_threshold) / 10; const s64 min_vacancy_critical = (2 * mem_threshold) / 10; minimum_memory = static_cast( - (std::max)((std::min)(device_local_memory - min_vacancy_expected, min_spacing_expected), + std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected), DEFAULT_EXPECTED_MEMORY)); critical_memory = static_cast( - (std::max)((std::min)(device_local_memory - min_vacancy_critical, min_spacing_critical), + std::max(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical), DEFAULT_CRITICAL_MEMORY)); } @@ -553,8 +553,8 @@ void BufferCache

::CommitAsyncFlushesHigh() { ForEachBufferInRange(device_addr, size, [&](BufferId buffer_id, Buffer& buffer) { const DAddr buffer_start = buffer.CpuAddr(); const DAddr buffer_end = buffer_start + buffer.SizeBytes(); - const DAddr new_start = (std::max)(buffer_start, device_addr); - const DAddr new_end = (std::min)(buffer_end, device_addr + size); + const DAddr new_start = std::max(buffer_start, device_addr); + const DAddr new_end = std::min(buffer_end, device_addr + size); memory_tracker.ForEachDownloadRange( new_start, new_end - new_start, false, [&](u64 device_addr_out, u64 range_size) { @@ -574,7 +574,7 @@ void BufferCache

::CommitAsyncFlushesHigh() { constexpr u64 align = 64ULL; constexpr u64 mask = ~(align - 1ULL); total_size_bytes += (new_size + align - 1) & mask; - largest_copy = (std::max)(largest_copy, new_size); + largest_copy = std::max(largest_copy, new_size); }; gpu_modified_ranges.ForEachInRange(device_addr_out, range_size, @@ -729,8 +729,8 @@ void BufferCache

::BindHostVertexBuffers() { } flags[Dirty::VertexBuffer0 + index] = false; - host_bindings.min_index = (std::min)(host_bindings.min_index, index); - host_bindings.max_index = (std::max)(host_bindings.max_index, index); + host_bindings.min_index = std::min(host_bindings.min_index, index); + host_bindings.max_index = std::max(host_bindings.max_index, index); any_valid = true; } @@ -789,7 +789,7 @@ void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 bool needs_bind) { const Binding& binding = channel_state->uniform_buffers[stage][index]; const DAddr device_addr = binding.device_addr; - const u32 size = (std::min)(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); + const u32 size = std::min(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); Buffer& buffer = slot_buffers[binding.buffer_id]; TouchBuffer(buffer, binding.buffer_id); const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && @@ -956,7 +956,7 @@ void BufferCache

::BindHostComputeUniformBuffers() { Buffer& buffer = slot_buffers[binding.buffer_id]; TouchBuffer(buffer, binding.buffer_id); const u32 size = - (std::min)(binding.size, (*channel_state->compute_uniform_buffer_sizes)[index]); + std::min(binding.size, (*channel_state->compute_uniform_buffer_sizes)[index]); SynchronizeBuffer(buffer, binding.device_addr, size); const u32 offset = buffer.Offset(binding.device_addr); @@ -1090,7 +1090,7 @@ void BufferCache

::UpdateIndexBuffer() { const u32 address_size = static_cast(gpu_addr_end - gpu_addr_begin); const u32 draw_size = (index_buffer_ref.count + index_buffer_ref.first) * index_buffer_ref.FormatSizeInBytes(); - const u32 size = (std::min)(address_size, draw_size); + const u32 size = std::min(address_size, draw_size); if (size == 0 || !device_addr) { channel_state->index_buffer = NULL_BINDING; return; @@ -1459,7 +1459,7 @@ bool BufferCache

::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 si .size = range_size, }); total_size_bytes += range_size; - largest_copy = (std::max)(largest_copy, range_size); + largest_copy = std::max(largest_copy, range_size); }); if (total_size_bytes == 0) { return true; @@ -1594,7 +1594,7 @@ void BufferCache

::DownloadBufferMemory(Buffer& buffer, DAddr device_addr, u64 constexpr u64 align = 64ULL; constexpr u64 mask = ~(align - 1ULL); total_size_bytes += (new_size + align - 1) & mask; - largest_copy = (std::max)(largest_copy, new_size); + largest_copy = std::max(largest_copy, new_size); }; gpu_modified_ranges.ForEachInRange(device_addr_out, range_size, add_download); @@ -1715,7 +1715,7 @@ Binding BufferCache

::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index, // cbufs, which do not store the sizes adjacent to the addresses, so use the fully // mapped buffer size for now. const u32 memory_layout_size = static_cast(gpu_memory->GetMemoryLayoutSize(gpu_addr)); - return (std::min)(memory_layout_size, static_cast(8_MiB)); + return std::min(memory_layout_size, static_cast(8_MiB)); }(); // Alignment only applies to the offset of the buffer const u32 alignment = runtime.GetStorageBufferAlignment(); diff --git a/src/video_core/buffer_cache/memory_tracker_base.h b/src/video_core/buffer_cache/memory_tracker_base.h index fe68bdbf23..c95eed1f62 100644 --- a/src/video_core/buffer_cache/memory_tracker_base.h +++ b/src/video_core/buffer_cache/memory_tracker_base.h @@ -230,7 +230,7 @@ private: std::size_t remaining_size{size}; std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS}; u64 page_offset{cpu_address & HIGHER_PAGE_MASK}; - u64 begin = (std::numeric_limits::max)(); + u64 begin = std::numeric_limits::max(); u64 end = 0; while (remaining_size > 0) { const std::size_t copy_amount{ @@ -240,8 +240,8 @@ private: auto [new_begin, new_end] = func(manager, page_offset, copy_amount); if (new_begin != 0 || new_end != 0) { const u64 base_address = page_index << HIGHER_PAGE_BITS; - begin = (std::min)(new_begin + base_address, begin); - end = (std::max)(new_end + base_address, end); + begin = std::min(new_begin + base_address, begin); + end = std::max(new_end + base_address, end); } }; if (manager) { diff --git a/src/video_core/buffer_cache/word_manager.h b/src/video_core/buffer_cache/word_manager.h index 8dc073240e..3db9d8b423 100644 --- a/src/video_core/buffer_cache/word_manager.h +++ b/src/video_core/buffer_cache/word_manager.h @@ -181,7 +181,7 @@ public: static u64 ExtractBits(u64 word, size_t page_start, size_t page_end) { constexpr size_t number_bits = sizeof(u64) * 8; - const size_t limit_page_end = number_bits - (std::min)(page_end, number_bits); + const size_t limit_page_end = number_bits - std::min(page_end, number_bits); u64 bits = (word >> page_start) << page_start; bits = (bits << limit_page_end) >> limit_page_end; return bits; @@ -206,11 +206,11 @@ public: auto [start_word, start_page] = GetWordPage(start); auto [end_word, end_page] = GetWordPage(end + BYTES_PER_PAGE - 1ULL); const size_t num_words = NumWords(); - start_word = (std::min)(start_word, num_words); - end_word = (std::min)(end_word, num_words); + start_word = std::min(start_word, num_words); + end_word = std::min(end_word, num_words); const size_t diff = end_word - start_word; end_word += (end_page + PAGES_PER_WORD - 1ULL) / PAGES_PER_WORD; - end_word = (std::min)(end_word, num_words); + end_word = std::min(end_word, num_words); end_page += diff * PAGES_PER_WORD; constexpr u64 base_mask{~0ULL}; for (size_t word_index = start_word; word_index < end_word; word_index++) { @@ -382,7 +382,7 @@ public: const std::span state_words = words.template Span(); [[maybe_unused]] const std::span untracked_words = words.template Span(); - u64 begin = (std::numeric_limits::max)(); + u64 begin = std::numeric_limits::max(); u64 end = 0; IterateWords(offset, size, [&](size_t index, u64 mask) { if constexpr (type == Type::GPU) { @@ -395,7 +395,7 @@ public: const u64 local_page_begin = std::countr_zero(word); const u64 local_page_end = PAGES_PER_WORD - std::countl_zero(word); const u64 page_index = index * PAGES_PER_WORD; - begin = (std::min)(begin, page_index + local_page_begin); + begin = std::min(begin, page_index + local_page_begin); end = page_index + local_page_end; }); static constexpr std::pair EMPTY{0, 0}; diff --git a/src/video_core/control/channel_state_cache.h b/src/video_core/control/channel_state_cache.h index 038c5b8fd1..7480d60d13 100644 --- a/src/video_core/control/channel_state_cache.h +++ b/src/video_core/control/channel_state_cache.h @@ -73,7 +73,7 @@ public: } protected: - static constexpr size_t UNSET_CHANNEL{(std::numeric_limits::max)()}; + static constexpr size_t UNSET_CHANNEL{std::numeric_limits::max()}; P* channel_state; size_t current_channel_id{UNSET_CHANNEL}; diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index a9bcd150e6..4b9a506cdf 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp @@ -102,10 +102,23 @@ bool DmaPusher::Step() { ProcessCommands(headers); }; - const bool use_safe = Settings::IsDMALevelDefault() ? Settings::IsGPULevelHigh() : Settings::IsDMALevelSafe(); + const Settings::DmaAccuracy accuracy = Settings::values.dma_accuracy.GetValue(); + const bool use_gpu_accuracy = accuracy == Settings::DmaAccuracy::Default; - if (use_safe) { + // reduces eye bleeding but also macros are dumb so idk +#define CHECK_LEVEL(level) use_gpu_accuracy ? Settings::IsGPULevel##level() : accuracy == Settings::DmaAccuracy::level; + const bool force_safe = CHECK_LEVEL(Extreme) + const bool unsafe_compute = CHECK_LEVEL(High) +#undef CHECK_LEVEL + + if (force_safe) { safe_process(); + } else if (unsafe_compute) { + if (dma_state.method >= MacroRegistersStart) { + unsafe_process(); + } else { + safe_process(); + } } else { unsafe_process(); } diff --git a/src/video_core/engines/engine_interface.h b/src/video_core/engines/engine_interface.h index 93de389a90..54631ee6cc 100644 --- a/src/video_core/engines/engine_interface.h +++ b/src/video_core/engines/engine_interface.h @@ -37,7 +37,7 @@ public: ConsumeSinkImpl(); } - std::bitset<(std::numeric_limits::max)()> execution_mask{}; + std::bitset::max()> execution_mask{}; std::vector> method_sink{}; bool current_dirty{}; GPUVAddr current_dma_segment; diff --git a/src/video_core/engines/engine_upload.cpp b/src/video_core/engines/engine_upload.cpp index e6f34c7cca..e5cc04ec4f 100644 --- a/src/video_core/engines/engine_upload.cpp +++ b/src/video_core/engines/engine_upload.cpp @@ -30,7 +30,7 @@ void State::ProcessExec(const bool is_linear_) { } void State::ProcessData(const u32 data, const bool is_last_call) { - const u32 sub_copy_size = (std::min)(4U, copy_size - write_offset); + const u32 sub_copy_size = std::min(4U, copy_size - write_offset); std::memcpy(&inner_buffer[write_offset], &data, sub_copy_size); write_offset += sub_copy_size; if (!is_last_call) { @@ -58,7 +58,7 @@ void State::ProcessData(std::span read_buffer) { u32 x_elements = regs.line_length_in; u32 x_offset = regs.dest.x; const u32 bpp_shift = Common::FoldRight( - 4U, [](u32 x, u32 y) { return (std::min)(x, static_cast(std::countr_zero(y))); }, + 4U, [](u32 x, u32 y) { return std::min(x, static_cast(std::countr_zero(y))); }, width, x_elements, x_offset, static_cast(address)); width >>= bpp_shift; x_elements >>= bpp_shift; diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index c63f908bcc..0d47b032c8 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -245,15 +245,15 @@ u32 Maxwell3D::GetMaxCurrentVertices() { } const auto& attribute = regs.vertex_attrib_format[index]; if (attribute.constant) { - num_vertices = (std::max)(num_vertices, 1U); + num_vertices = std::max(num_vertices, 1U); continue; } const auto& limit = regs.vertex_stream_limits[index]; const GPUVAddr gpu_addr_begin = array.Address(); const GPUVAddr gpu_addr_end = limit.Address() + 1; const u32 address_size = static_cast(gpu_addr_end - gpu_addr_begin); - num_vertices = (std::max)( - num_vertices, address_size / (std::max)(attribute.SizeInBytes(), array.stride.Value())); + num_vertices = std::max( + num_vertices, address_size / std::max(attribute.SizeInBytes(), array.stride.Value())); break; } return num_vertices; @@ -262,9 +262,9 @@ u32 Maxwell3D::GetMaxCurrentVertices() { size_t Maxwell3D::EstimateIndexBufferSize() { GPUVAddr start_address = regs.index_buffer.StartAddress(); GPUVAddr end_address = regs.index_buffer.EndAddress(); - static constexpr std::array max_sizes = {(std::numeric_limits::max)(), - (std::numeric_limits::max)(), - (std::numeric_limits::max)()}; + static constexpr std::array max_sizes = {std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()}; const size_t byte_size = regs.index_buffer.FormatSizeInBytes(); const size_t log2_byte_size = Common::Log2Ceil64(byte_size); const size_t cap{GetMaxCurrentVertices() * 4 * byte_size}; diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index ce0434f3d7..6b4f1c570e 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -1180,11 +1180,11 @@ public: } f32 GetX() const { - return (std::max)(0.0f, translate_x - std::fabs(scale_x)); + return std::max(0.0f, translate_x - std::fabs(scale_x)); } f32 GetY() const { - return (std::max)(0.0f, translate_y - std::fabs(scale_y)); + return std::max(0.0f, translate_y - std::fabs(scale_y)); } f32 GetWidth() const { @@ -3091,7 +3091,7 @@ public: } struct DirtyState { - using Flags = std::bitset<(std::numeric_limits::max)()>; + using Flags = std::bitset::max()>; using Table = std::array; using Tables = std::array; diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 73a62db37d..a4b2c1098b 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -198,7 +198,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { u32 bpp_shift = 0U; if (!is_remapping) { bpp_shift = Common::FoldRight( - 4U, [](u32 x, u32 y) { return (std::min)(x, static_cast(std::countr_zero(y))); }, + 4U, [](u32 x, u32 y) { return std::min(x, static_cast(std::countr_zero(y))); }, width, x_elements, x_offset, static_cast(regs.offset_in)); width >>= bpp_shift; x_elements >>= bpp_shift; @@ -261,7 +261,7 @@ void MaxwellDMA::CopyPitchToBlockLinear() { u32 bpp_shift = 0U; if (!is_remapping) { bpp_shift = Common::FoldRight( - 4U, [](u32 x, u32 y) { return (std::min)(x, static_cast(std::countr_zero(y))); }, + 4U, [](u32 x, u32 y) { return std::min(x, static_cast(std::countr_zero(y))); }, width, x_elements, x_offset, static_cast(regs.offset_out)); width >>= bpp_shift; x_elements >>= bpp_shift; @@ -312,7 +312,7 @@ void MaxwellDMA::CopyBlockLinearToBlockLinear() { u32 bpp_shift = 0U; if (!is_remapping) { bpp_shift = Common::FoldRight( - 4U, [](u32 x, u32 y) { return (std::min)(x, static_cast(std::countr_zero(y))); }, + 4U, [](u32 x, u32 y) { return std::min(x, static_cast(std::countr_zero(y))); }, src_width, dst_width, x_elements, src_x_offset, dst_x_offset, static_cast(regs.offset_in), static_cast(regs.offset_out)); src_width >>= bpp_shift; diff --git a/src/video_core/engines/sw_blitter/converter.cpp b/src/video_core/engines/sw_blitter/converter.cpp index 785d209f98..2419b56321 100644 --- a/src/video_core/engines/sw_blitter/converter.cpp +++ b/src/video_core/engines/sw_blitter/converter.cpp @@ -771,7 +771,7 @@ private: }; const auto to_fp_n = [](f32 base_value, size_t bits, size_t mantissa) { constexpr size_t fp32_mantissa_bits = 23; - u32 tmp_value = Common::BitCast((std::max)(base_value, 0.0f)); + u32 tmp_value = Common::BitCast(std::max(base_value, 0.0f)); size_t shift_towards = fp32_mantissa_bits - mantissa; return tmp_value >> shift_towards; }; diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index a0b13cbffc..782d11d725 100644 --- a/src/video_core/host1x/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp @@ -117,7 +117,7 @@ std::span H264::ComposeFrame() { (current_context.h264_parameter_set.frame_mbs_only_flag ? 1 : 2); u32 max_num_ref_frames = - (std::max)((std::max)(current_context.h264_parameter_set.num_refidx_l0_default_active, + std::max(std::max(current_context.h264_parameter_set.num_refidx_l0_default_active, current_context.h264_parameter_set.num_refidx_l1_default_active) + 1, 4); diff --git a/src/video_core/host1x/codecs/vp9.cpp b/src/video_core/host1x/codecs/vp9.cpp index 7b3dbd7642..c70d0a506f 100644 --- a/src/video_core/host1x/codecs/vp9.cpp +++ b/src/video_core/host1x/codecs/vp9.cpp @@ -228,10 +228,10 @@ constexpr std::array map_lut{ std::size_t index{}; if (old_prob * 2 <= 0xff) { - index = static_cast((std::max)(0, RecenterNonNeg(new_prob, old_prob) - 1)); + index = static_cast(std::max(0, RecenterNonNeg(new_prob, old_prob) - 1)); } else { index = static_cast( - (std::max)(0, RecenterNonNeg(0xff - 1 - new_prob, 0xff - 1 - old_prob) - 1)); + std::max(0, RecenterNonNeg(0xff - 1 - new_prob, 0xff - 1 - old_prob) - 1)); } return static_cast(map_lut[index]); diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index 9c33370337..18b3077f9a 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp @@ -201,8 +201,8 @@ void Vic::ReadProgressiveY8__V8U8_N420(const SlotStruct& slot, slot_surface.resize_destructive(out_luma_width * out_luma_height); - const auto in_luma_width{(std::min)(frame->GetWidth(), static_cast(out_luma_width))}; - const auto in_luma_height{(std::min)(frame->GetHeight(), static_cast(out_luma_height))}; + const auto in_luma_width{std::min(frame->GetWidth(), static_cast(out_luma_width))}; + const auto in_luma_height{std::min(frame->GetHeight(), static_cast(out_luma_height))}; const auto in_luma_stride{frame->GetStride(0)}; const auto in_chroma_stride{frame->GetStride(1)}; @@ -425,9 +425,9 @@ void Vic::ReadInterlacedY8__V8U8_N420(const SlotStruct& slot, std::spanGetWidth(), static_cast(out_luma_width))}; + const auto in_luma_width{std::min(frame->GetWidth(), static_cast(out_luma_width))}; [[maybe_unused]] const auto in_luma_height{ - (std::min)(frame->GetHeight(), static_cast(out_luma_height))}; + std::min(frame->GetHeight(), static_cast(out_luma_height))}; const auto in_luma_stride{frame->GetStride(0)}; [[maybe_unused]] const auto in_chroma_width{(frame->GetWidth() + 1) / 2}; @@ -543,15 +543,15 @@ void Vic::Blend(const ConfigStruct& config, const SlotStruct& slot) { auto rect_top{add_one(config.output_config.target_rect_top.Value())}; auto rect_bottom{add_one(config.output_config.target_rect_bottom.Value())}; - rect_left = (std::max)(rect_left, dest_left); - rect_right = (std::min)(rect_right, dest_right); - rect_top = (std::max)(rect_top, dest_top); - rect_bottom = (std::min)(rect_bottom, dest_bottom); + rect_left = std::max(rect_left, dest_left); + rect_right = std::min(rect_right, dest_right); + rect_top = std::max(rect_top, dest_top); + rect_bottom = std::min(rect_bottom, dest_bottom); - source_left = (std::max)(source_left, rect_left); - source_right = (std::min)(source_right, rect_right); - source_top = (std::max)(source_top, rect_top); - source_bottom = (std::min)(source_bottom, rect_bottom); + source_left = std::max(source_left, rect_left); + source_right = std::min(source_right, rect_right); + source_top = std::max(source_top, rect_top); + source_bottom = std::min(source_bottom, rect_bottom); if (source_left >= source_right || source_top >= source_bottom) { return; @@ -562,14 +562,14 @@ void Vic::Blend(const ConfigStruct& config, const SlotStruct& slot) { 1}; const auto in_surface_width{slot.surface_config.slot_surface_width + 1}; - source_bottom = (std::min)(source_bottom, out_surface_height); - source_right = (std::min)(source_right, out_surface_width); + source_bottom = std::min(source_bottom, out_surface_height); + source_right = std::min(source_right, out_surface_width); // TODO Alpha blending. No games I've seen use more than a single surface or supply an alpha // below max, so it's ignored for now. if (!slot.color_matrix.matrix_enable) { - const auto copy_width = (std::min)(source_right - source_left, rect_right - rect_left); + const auto copy_width = std::min(source_right - source_left, rect_right - rect_left); for (u32 y = source_top; y < source_bottom; y++) { const auto dst_line = y * out_surface_width; @@ -818,8 +818,8 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) { const auto out_chroma_stride = Common::AlignUp(out_chroma_width * BytesPerPixel * 2, 0x10); const auto out_chroma_size = out_chroma_height * out_chroma_stride; - surface_width = (std::min)(surface_width, out_luma_width); - surface_height = (std::min)(surface_height, out_luma_height); + surface_width = std::min(surface_width, out_luma_width); + surface_height = std::min(surface_height, out_luma_height); [[maybe_unused]] auto DecodeLinear = [&](std::span out_luma, std::span out_chroma) { for (u32 y = 0; y < surface_height; ++y) { @@ -1089,8 +1089,8 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config) { const auto out_luma_stride = Common ::AlignUp(out_luma_width * BytesPerPixel, 0x10); const auto out_luma_size = out_luma_height * out_luma_stride; - surface_width = (std::min)(surface_width, out_luma_width); - surface_height = (std::min)(surface_height, out_luma_height); + surface_width = std::min(surface_width, out_luma_width); + surface_height = std::min(surface_height, out_luma_height); [[maybe_unused]] auto DecodeLinear = [&](std::span out_buffer) { for (u32 y = 0; y < surface_height; y++) { diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 328abd0ba4..fb529f88b7 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp @@ -301,7 +301,7 @@ private: const u32 indirect_words = 5 + padding; const std::size_t first_draw = start_indirect; const std::size_t effective_draws = end_indirect - start_indirect; - const std::size_t last_draw = start_indirect + (std::min)(effective_draws, max_draws); + const std::size_t last_draw = start_indirect + std::min(effective_draws, max_draws); for (std::size_t index = first_draw; index < last_draw; index++) { const std::size_t base = index * indirect_words + 5; diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 13f0ea8d96..ffafc48eff 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -293,7 +293,7 @@ const u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) const { return memory.GetPointer(*address); } -#if defined(_MSC_VER) && !defined(__clang__) // no need for gcc / clang but msvc's compiler is more conservative with inlining. +#ifdef _MSC_VER // no need for gcc / clang but msvc's compiler is more conservative with inlining. #pragma inline_recursion(on) #endif @@ -329,7 +329,7 @@ inline void MemoryManager::MemoryOperation(GPUVAddr gpu_src_addr, std::size_t si while (remaining_size > 0) { const std::size_t copy_amount{ - (std::min)(static_cast(used_page_size) - page_offset, remaining_size)}; + std::min(static_cast(used_page_size) - page_offset, remaining_size)}; auto entry = GetEntry(current_address); if (entry == EntryType::Mapped) [[likely]] { if constexpr (BOOL_BREAK_MAPPED) { diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 9be419932c..448624aa99 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h @@ -152,7 +152,7 @@ public: PTEKind GetPageKind(GPUVAddr gpu_addr) const; size_t GetMemoryLayoutSize(GPUVAddr gpu_addr, - size_t max_size = (std::numeric_limits::max)()) const; + size_t max_size = std::numeric_limits::max()) const; void FlushCaching(); diff --git a/src/video_core/renderer_opengl/blit_image.cpp b/src/video_core/renderer_opengl/blit_image.cpp index b9a502577f..3b03e8d5ac 100644 --- a/src/video_core/renderer_opengl/blit_image.cpp +++ b/src/video_core/renderer_opengl/blit_image.cpp @@ -45,8 +45,8 @@ void BlitImageHelper::BlitColor(GLuint dst_framebuffer, GLuint src_image_view, G static_cast(src_region.start.x) / static_cast(src_size.width), static_cast(src_region.start.y) / static_cast(src_size.height)); - glViewport((std::min)(dst_region.start.x, dst_region.end.x), - (std::min)(dst_region.start.y, dst_region.end.y), + glViewport(std::min(dst_region.start.x, dst_region.end.x), + std::min(dst_region.start.y, dst_region.end.y), std::abs(dst_region.end.x - dst_region.start.x), std::abs(dst_region.end.y - dst_region.start.y)); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_framebuffer); diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 9d7089c5de..ade72e1f95 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp @@ -248,7 +248,7 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bi std::ranges::transform(bindings.strides, buffer_strides.begin(), [](u64 stride) { return static_cast(stride); }); const u32 count = - (std::min)(static_cast(bindings.buffers.size()), max_attributes - bindings.min_index); + std::min(static_cast(bindings.buffers.size()), max_attributes - bindings.min_index); if (has_unified_vertex_buffers) { for (u32 index = 0; index < count; ++index) { Buffer& buffer = *bindings.buffers[index]; diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 59d1329d7e..fd471e9795 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h @@ -59,7 +59,7 @@ class BufferCacheRuntime { friend Buffer; public: - static constexpr u8 INVALID_BINDING = (std::numeric_limits::max)(); + static constexpr u8 INVALID_BINDING = std::numeric_limits::max(); explicit BufferCacheRuntime(const Device& device_, StagingBufferPool& staging_buffer_pool_); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 2746177fab..2ea42abf4b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -1266,7 +1266,7 @@ void RasterizerOpenGL::SyncPointState() { oglEnable(GL_PROGRAM_POINT_SIZE, maxwell3d->regs.point_size_attribute.enabled); const bool is_rescaling{texture_cache.IsRescaling()}; const float scale = is_rescaling ? Settings::values.resolution_info.up_factor : 1.0f; - glPointSize((std::max)(1.0f, maxwell3d->regs.point_size * scale)); + glPointSize(std::max(1.0f, maxwell3d->regs.point_size * scale)); } void RasterizerOpenGL::SyncLineState() { diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index b6ce57b819..edf0bdd2f1 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -617,7 +617,7 @@ std::unique_ptr ShaderCache::CreateComputePipeline( } std::unique_ptr ShaderCache::CreateWorkers() const { - return std::make_unique((std::max)(std::thread::hardware_concurrency(), 2U) - 1, + return std::make_unique(std::max(std::thread::hardware_concurrency(), 2U) - 1, "GlShaderBuilder", [this] { return Context{emu_window}; }); } diff --git a/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp b/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp index d9535c277d..5767d6b7de 100644 --- a/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp +++ b/src/video_core/renderer_opengl/gl_staging_buffer_pool.cpp @@ -68,7 +68,7 @@ size_t StagingBuffers::RequestBuffer(size_t requested_size) { std::optional StagingBuffers::FindBuffer(size_t requested_size) { size_t known_unsignaled_index = current_sync_index + 1; - size_t smallest_buffer = (std::numeric_limits::max)(); + size_t smallest_buffer = std::numeric_limits::max(); std::optional found; const size_t num_buffers = allocs.size(); for (size_t index = 0; index < num_buffers; ++index) { @@ -88,7 +88,7 @@ std::optional StagingBuffers::FindBuffer(size_t requested_size) { if (!alloc.sync.IsSignaled()) { // Since this fence hasn't been signaled, it's safe to assume all later // fences haven't been signaled either - known_unsignaled_index = (std::min)(known_unsignaled_index, alloc.sync_index); + known_unsignaled_index = std::min(known_unsignaled_index, alloc.sync_index); continue; } alloc.sync.Release(); @@ -120,7 +120,7 @@ std::pair, size_t> StreamBuffer::Request(size_t size) noexcept { used_iterator = iterator; for (size_t region = Region(free_iterator) + 1, - region_end = (std::min)(Region(iterator + size) + 1, NUM_SYNCS); + region_end = std::min(Region(iterator + size) + 1, NUM_SYNCS); region < region_end; ++region) { glClientWaitSync(fences[region].handle, 0, GL_TIMEOUT_IGNORED); fences[region].Release(); diff --git a/src/video_core/renderer_opengl/gl_state_tracker.h b/src/video_core/renderer_opengl/gl_state_tracker.h index 4027807da1..19bcf3f355 100644 --- a/src/video_core/renderer_opengl/gl_state_tracker.h +++ b/src/video_core/renderer_opengl/gl_state_tracker.h @@ -79,7 +79,7 @@ enum : u8 { Last }; -static_assert(Last <= (std::numeric_limits::max)()); +static_assert(Last <= std::numeric_limits::max()); } // namespace Dirty diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 8b1737ff51..be14494ca5 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp @@ -717,7 +717,7 @@ Image::Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info_, gl_type = tuple.type; } const int max_host_mip_levels = std::bit_width(info.size.width); - gl_num_levels = (std::min)(info.resources.levels, max_host_mip_levels); + gl_num_levels = std::min(info.resources.levels, max_host_mip_levels); texture = MakeImage(info, gl_internal_format, gl_num_levels); current_texture = texture.handle; if (runtime->device.HasDebuggingToolAttached()) { @@ -742,8 +742,8 @@ void Image::UploadMemory(GLuint buffer_handle, size_t buffer_offset, glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - u32 current_row_length = (std::numeric_limits::max)(); - u32 current_image_height = (std::numeric_limits::max)(); + u32 current_row_length = std::numeric_limits::max(); + u32 current_image_height = std::numeric_limits::max(); for (const VideoCommon::BufferImageCopy& copy : copies) { if (copy.image_subresource.base_level >= gl_num_levels) { @@ -788,8 +788,8 @@ void Image::DownloadMemory(std::span buffer_handles, std::span b glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_handle); glPixelStorei(GL_PACK_ALIGNMENT, 1); - u32 current_row_length = (std::numeric_limits::max)(); - u32 current_image_height = (std::numeric_limits::max)(); + u32 current_row_length = std::numeric_limits::max(); + u32 current_image_height = std::numeric_limits::max(); for (const VideoCommon::BufferImageCopy& copy : copies) { if (copy.image_subresource.base_level >= gl_num_levels) { @@ -1033,10 +1033,10 @@ void Image::Scale(bool up_scale) { const GLuint draw_fbo = runtime->rescale_draw_fbos[fbo_index].handle; for (s32 layer = 0; layer < info.resources.layers; ++layer) { for (s32 level = 0; level < info.resources.levels; ++level) { - const u32 src_level_width = (std::max)(1u, src_width >> level); - const u32 src_level_height = (std::max)(1u, src_height >> level); - const u32 dst_level_width = (std::max)(1u, dst_width >> level); - const u32 dst_level_height = (std::max)(1u, dst_height >> level); + const u32 src_level_width = std::max(1u, src_width >> level); + const u32 src_level_height = std::max(1u, src_height >> level); + const u32 dst_level_width = std::max(1u, dst_width >> level); + const u32 dst_level_height = std::max(1u, dst_height >> level); glNamedFramebufferTextureLayer(read_fbo, attachment, src_handle, level, layer); glNamedFramebufferTextureLayer(draw_fbo, attachment, dst_handle, level, layer); diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 7bfcd6503b..596323fb32 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -102,16 +102,13 @@ constexpr VkPipelineVertexInputStateCreateInfo PIPELINE_VERTEX_INPUT_STATE_CREAT .vertexAttributeDescriptionCount = 0, .pVertexAttributeDescriptions = nullptr, }; - -VkPipelineInputAssemblyStateCreateInfo GetPipelineInputAssemblyStateCreateInfo(const Device& device) { - return VkPipelineInputAssemblyStateCreateInfo{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - .primitiveRestartEnable = device.IsMoltenVK() ? VK_TRUE : VK_FALSE, - }; -} +constexpr VkPipelineInputAssemblyStateCreateInfo PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, +}; constexpr VkPipelineViewportStateCreateInfo PIPELINE_VIEWPORT_STATE_CREATE_INFO{ .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pNext = nullptr, @@ -340,8 +337,8 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri void BindBlitState(vk::CommandBuffer cmdbuf, const Region2D& dst_region) { const VkOffset2D offset{ - .x = (std::min)(dst_region.start.x, dst_region.end.x), - .y = (std::min)(dst_region.start.y, dst_region.end.y), + .x = std::min(dst_region.start.x, dst_region.end.x), + .y = std::min(dst_region.start.y, dst_region.end.y), }; const VkExtent2D extent{ .width = static_cast(std::abs(dst_region.end.x - dst_region.start.x)), @@ -805,7 +802,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe .pAttachments = &blend_attachment, .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, }; - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -813,7 +809,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe .stageCount = static_cast(stages.size()), .pStages = stages.data(), .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, @@ -837,7 +833,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip } blit_depth_stencil_keys.push_back(key); const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag); - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -845,7 +840,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip .stageCount = static_cast(stages.size()), .pStages = stages.data(), .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, @@ -890,7 +885,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel .pAttachments = &color_blend_attachment_state, .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, }; - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -898,7 +892,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel .stageCount = static_cast(stages.size()), .pStages = stages.data(), .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, @@ -946,7 +940,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( .minDepthBounds = 0.0f, .maxDepthBounds = 0.0f, }; - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -954,7 +947,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( .stageCount = static_cast(stages.size()), .pStages = stages.data(), .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, @@ -977,7 +970,6 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend } VkShaderModule frag_shader = *convert_float_to_depth_frag; const std::array stages = MakeStages(*full_screen_vert, frag_shader); - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -985,7 +977,7 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend .stageCount = static_cast(stages.size()), .pStages = stages.data(), .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, @@ -1007,7 +999,6 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend } VkShaderModule frag_shader = *convert_depth_to_float_frag; const std::array stages = MakeStages(*full_screen_vert, frag_shader); - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -1015,7 +1006,7 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend .stageCount = static_cast(stages.size()), .pStages = stages.data(), .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, @@ -1038,7 +1029,6 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren return; } const std::array stages = MakeStages(*full_screen_vert, *module); - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -1046,7 +1036,7 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren .stageCount = static_cast(stages.size()), .pStages = stages.data(), .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, @@ -1080,7 +1070,6 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende VkShaderModule frag_shader = is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag; const std::array stages = MakeStages(*full_screen_vert, frag_shader); - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -1088,7 +1077,7 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende .stageCount = static_cast(stages.size()), .pStages = stages.data(), .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .pInputAssemblyState = &input_assembly_ci, + .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pTessellationState = nullptr, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, diff --git a/src/video_core/renderer_vulkan/present/util.cpp b/src/video_core/renderer_vulkan/present/util.cpp index 07b6a41c5c..6874bbae99 100644 --- a/src/video_core/renderer_vulkan/present/util.cpp +++ b/src/video_core/renderer_vulkan/present/util.cpp @@ -400,12 +400,12 @@ static vk::Pipeline CreateWrappedPipelineImpl( .pVertexAttributeDescriptions = nullptr, }; - const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{ + constexpr VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, - .primitiveRestartEnable = device.IsMoltenVK() ? VK_TRUE : VK_FALSE, + .primitiveRestartEnable = VK_FALSE, }; constexpr VkPipelineViewportStateCreateInfo viewport_state_ci{ diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index f61f4456fe..e5e1e3ab63 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -573,8 +573,8 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bi buffer_handles.push_back(handle); } const u32 device_max = device.GetMaxVertexInputBindings(); - const u32 min_binding = (std::min)(bindings.min_index, device_max); - const u32 max_binding = (std::min)(bindings.max_index, device_max); + const u32 min_binding = std::min(bindings.min_index, device_max); + const u32 max_binding = std::min(bindings.max_index, device_max); const u32 binding_count = max_binding - min_binding; if (binding_count == 0) { return; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index f5594450c2..0226eb2c14 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -562,7 +562,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { static_vector vertex_binding_divisors; static_vector vertex_attributes; if (!key.state.dynamic_vertex_input) { - const size_t num_vertex_arrays = (std::min)( + const size_t num_vertex_arrays = std::min( Maxwell::NumVertexArrays, static_cast(device.GetMaxVertexInputBindings())); for (size_t index = 0; index < num_vertex_arrays; ++index) { const bool instanced = key.state.binding_divisors[index] != 0; @@ -635,16 +635,14 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .flags = 0, .topology = input_assembly_topology, .primitiveRestartEnable = - // MoltenVK/Metal always has primitive restart enabled and cannot disable it - device.IsMoltenVK() ? VK_TRUE : - (dynamic.primitive_restart_enable != 0 && + dynamic.primitive_restart_enable != 0 && ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && device.IsTopologyListPrimitiveRestartSupported()) || SupportsPrimitiveRestart(input_assembly_topology) || (input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && device.IsPatchListPrimitiveRestartSupported())) ? VK_TRUE - : VK_FALSE), + : VK_FALSE, }; const VkPipelineTessellationStateCreateInfo tessellation_ci{ .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 72713f4902..dbac7f0805 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp @@ -86,8 +86,8 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form }, .extent = { - .width = (std::min)(frame_width, swapchain_width), - .height = (std::min)(frame_height, swapchain_height), + .width = std::min(frame_width, swapchain_width), + .height = std::min(frame_height, swapchain_height), .depth = 1, }, }; diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 89e0b1114e..d6ecc2b65c 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -202,8 +202,8 @@ public: }); rasterizer->SyncOperation(std::move(func)); accumulation_since_last_sync = false; - first_accumulation_checkpoint = (std::min)(first_accumulation_checkpoint, num_slots_used); - last_accumulation_checkpoint = (std::max)(last_accumulation_checkpoint, num_slots_used); + first_accumulation_checkpoint = std::min(first_accumulation_checkpoint, num_slots_used); + last_accumulation_checkpoint = std::max(last_accumulation_checkpoint, num_slots_used); } void CloseCounter() override { @@ -311,9 +311,9 @@ public: if (has_multi_queries) { const size_t min_accumulation_limit = - (std::min)(first_accumulation_checkpoint, num_slots_used); + std::min(first_accumulation_checkpoint, num_slots_used); const size_t max_accumulation_limit = - (std::max)(last_accumulation_checkpoint, num_slots_used); + std::max(last_accumulation_checkpoint, num_slots_used); const size_t intermediary_buffer_index = ObtainBuffer(num_slots_used); resolve_buffers.push_back(intermediary_buffer_index); queries_prefix_scan_pass->Run(*accumulation_buffer, *buffers[intermediary_buffer_index], @@ -332,7 +332,7 @@ public: rasterizer->SyncOperation(std::move(func)); AbandonCurrentQuery(); num_slots_used = 0; - first_accumulation_checkpoint = (std::numeric_limits::max)(); + first_accumulation_checkpoint = std::numeric_limits::max(); last_accumulation_checkpoint = 0; accumulation_since_last_sync = has_multi_queries; pending_sync.clear(); @@ -414,7 +414,7 @@ private: size_t start_slot = query->start_slot; for (size_t i = 0; i < banks_set; i++) { auto& the_bank = bank_pool.GetBank(bank_id); - size_t amount = (std::min)(the_bank.Size() - start_slot, size_slots); + size_t amount = std::min(the_bank.Size() - start_slot, size_slots); func(&the_bank, start_slot, amount); bank_id = the_bank.next_bank - 1; start_slot = 0; @@ -431,11 +431,11 @@ private: auto* query = GetQuery(q); ApplyBankOp(query, [&indexer](SamplesQueryBank* bank, size_t start, size_t amount) { auto id_ = bank->GetIndex(); - auto pair = indexer.try_emplace(id_, (std::numeric_limits::max)(), - (std::numeric_limits::min)()); + auto pair = indexer.try_emplace(id_, std::numeric_limits::max(), + std::numeric_limits::min()); auto& current_pair = pair.first->second; - current_pair.first = (std::min)(current_pair.first, start); - current_pair.second = (std::max)(current_pair.second, amount + start); + current_pair.first = std::min(current_pair.first, start); + current_pair.second = std::max(current_pair.second, amount + start); }); } for (auto& cont : indexer) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 70ca9583f9..2d12fc658f 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -131,8 +131,8 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3 s32 max_y = lower_left ? (clip_height - src.min_y) : src.max_y.Value(); // Bound to render area - min_y = (std::max)(min_y, 0); - max_y = (std::max)(max_y, 0); + min_y = std::max(min_y, 0); + max_y = std::max(max_y, 0); if (src.enable) { scissor.offset.x = scale_up(src.min_x); @@ -142,8 +142,8 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3 } else { scissor.offset.x = 0; scissor.offset.y = 0; - scissor.extent.width = (std::numeric_limits::max)(); - scissor.extent.height = (std::numeric_limits::max)(); + scissor.extent.width = std::numeric_limits::max(); + scissor.extent.height = std::numeric_limits::max(); } return scissor; } @@ -380,8 +380,8 @@ void RasterizerVulkan::Clear(u32 layer_count) { VkRect2D default_scissor; default_scissor.offset.x = 0; default_scissor.offset.y = 0; - default_scissor.extent.width = (std::numeric_limits::max)(); - default_scissor.extent.height = (std::numeric_limits::max)(); + default_scissor.extent.width = std::numeric_limits::max(); + default_scissor.extent.height = std::numeric_limits::max(); VkClearRect clear_rect{ .rect = regs.clear_control.use_scissor ? GetScissorState(regs, 0, up_scale, down_shift) @@ -393,8 +393,8 @@ void RasterizerVulkan::Clear(u32 layer_count) { return; } clear_rect.rect.extent = VkExtent2D{ - .width = (std::min)(clear_rect.rect.extent.width, render_area.width), - .height = (std::min)(clear_rect.rect.extent.height, render_area.height), + .width = std::min(clear_rect.rect.extent.width, render_area.width), + .height = std::min(clear_rect.rect.extent.height, render_area.height), }; const u32 color_attachment = regs.clear_surface.RT; diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp index 35f497493b..72d5ec35f9 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp @@ -31,7 +31,7 @@ size_t GetStreamBufferSize(const Device& device) { VkDeviceSize size{0}; if (device.HasDebuggingToolAttached()) { ForEachDeviceLocalHostVisibleHeap(device, [&size](size_t index, VkMemoryHeap& heap) { - size = (std::max)(size, heap.size); + size = std::max(size, heap.size); }); // If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be // loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue @@ -42,7 +42,7 @@ size_t GetStreamBufferSize(const Device& device) { } else { size = MAX_STREAM_BUFFER_SIZE; } - return (std::min)(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE); + return std::min(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE); } } // Anonymous namespace @@ -104,7 +104,7 @@ void StagingBufferPool::TickFrame() { StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { if (AreRegionsActive(Region(free_iterator) + 1, - (std::min)(Region(iterator + size) + 1, NUM_SYNCS))) { + std::min(Region(iterator + size) + 1, NUM_SYNCS))) { // Avoid waiting for the previous usages to be free return GetStagingBuffer(size, MemoryUsage::Upload); } @@ -112,7 +112,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + Region(iterator), current_tick); used_iterator = iterator; - free_iterator = (std::max)(free_iterator, iterator + size); + free_iterator = std::max(free_iterator, iterator + size); if (iterator + size >= stream_buffer_size) { std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS, @@ -170,7 +170,7 @@ std::optional StagingBufferPool::TryGetReservedBuffer(size_t s } } cache_level.iterate_index = std::distance(entries.begin(), it) + 1; - it->tick = deferred ? (std::numeric_limits::max)() : scheduler.CurrentTick(); + it->tick = deferred ? std::numeric_limits::max() : scheduler.CurrentTick(); ASSERT(!it->deferred); it->deferred = deferred; return it->Ref(); @@ -206,7 +206,7 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage .usage = usage, .log2_level = log2, .index = unique_ids++, - .tick = deferred ? (std::numeric_limits::max)() : scheduler.CurrentTick(), + .tick = deferred ? std::numeric_limits::max() : scheduler.CurrentTick(), .deferred = deferred, }); return entry.Ref(); @@ -240,7 +240,7 @@ void StagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, size_t log2) { return scheduler.IsFree(entry.tick); }; const size_t begin_offset = staging.delete_index; - const size_t end_offset = (std::min)(begin_offset + deletions_per_tick, old_size); + const size_t end_offset = std::min(begin_offset + deletions_per_tick, old_size); const auto begin = entries.begin() + begin_offset; const auto end = entries.begin() + end_offset; entries.erase(std::remove_if(begin, end, is_deletable), end); diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.h b/src/video_core/renderer_vulkan/vk_state_tracker.h index aef726658a..a78d2113fb 100644 --- a/src/video_core/renderer_vulkan/vk_state_tracker.h +++ b/src/video_core/renderer_vulkan/vk_state_tracker.h @@ -70,7 +70,7 @@ enum : u8 { Last, }; -static_assert(Last <= (std::numeric_limits::max)()); +static_assert(Last <= std::numeric_limits::max()); } // namespace Dirty diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 096b9df087..a002ca83a0 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -79,15 +79,15 @@ static VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox, } VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) { - constexpr auto undefined_size{(std::numeric_limits::max)()}; + constexpr auto undefined_size{std::numeric_limits::max()}; if (capabilities.currentExtent.width != undefined_size) { return capabilities.currentExtent; } VkExtent2D extent; - extent.width = (std::max)(capabilities.minImageExtent.width, - (std::min)(capabilities.maxImageExtent.width, width)); - extent.height = (std::max)(capabilities.minImageExtent.height, - (std::min)(capabilities.maxImageExtent.height, height)); + extent.width = std::max(capabilities.minImageExtent.width, + std::min(capabilities.maxImageExtent.width, width)); + extent.height = std::max(capabilities.minImageExtent.height, + std::min(capabilities.maxImageExtent.height, height)); return extent; } @@ -172,7 +172,7 @@ void Swapchain::Create( bool Swapchain::AcquireNextImage() { const VkResult result = device.GetLogical().AcquireNextImageKHR( - *swapchain, (std::numeric_limits::max)(), *present_semaphores[frame_index], + *swapchain, std::numeric_limits::max(), *present_semaphores[frame_index], VK_NULL_HANDLE, &image_index); switch (result) { case VK_SUCCESS: @@ -261,10 +261,10 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) { requested_image_count = capabilities.maxImageCount; } else { requested_image_count = - (std::max)(requested_image_count, (std::min)(3U, capabilities.maxImageCount)); + std::max(requested_image_count, std::min(3U, capabilities.maxImageCount)); } } else { - requested_image_count = (std::max)(requested_image_count, 3U); + requested_image_count = std::max(requested_image_count, 3U); } VkSwapchainCreateInfoKHR swapchain_ci{ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 466be26577..eda9ff2a5a 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -509,16 +509,16 @@ TransformBufferCopies(std::span copies, size_t bu } } struct RangedBarrierRange { - u32 min_mip = (std::numeric_limits::max)(); - u32 max_mip = (std::numeric_limits::min)(); - u32 min_layer = (std::numeric_limits::max)(); - u32 max_layer = (std::numeric_limits::min)(); + u32 min_mip = std::numeric_limits::max(); + u32 max_mip = std::numeric_limits::min(); + u32 min_layer = std::numeric_limits::max(); + u32 max_layer = std::numeric_limits::min(); void AddLayers(const VkImageSubresourceLayers& layers) { - min_mip = (std::min)(min_mip, layers.mipLevel); - max_mip = (std::max)(max_mip, layers.mipLevel + 1); - min_layer = (std::min)(min_layer, layers.baseArrayLayer); - max_layer = (std::max)(max_layer, layers.baseArrayLayer + layers.layerCount); + min_mip = std::min(min_mip, layers.mipLevel); + max_mip = std::max(max_mip, layers.mipLevel + 1); + min_layer = std::min(min_layer, layers.baseArrayLayer); + max_layer = std::max(max_layer, layers.baseArrayLayer + layers.layerCount); } VkImageSubresourceRange SubresourceRange(VkImageAspectFlags aspect_mask) const noexcept { @@ -747,8 +747,8 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const .z = 0, }, { - .x = (std::max)(1, src_size.x >> level), - .y = (std::max)(1, src_size.y >> level), + .x = std::max(1, src_size.x >> level), + .y = std::max(1, src_size.y >> level), .z = 1, }, }, @@ -765,8 +765,8 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const .z = 0, }, { - .x = (std::max)(1, dst_size.x >> level), - .y = (std::max)(1, dst_size.y >> level), + .x = std::max(1, dst_size.x >> level), + .y = std::max(1, dst_size.y >> level), .z = 1, }, }, @@ -1956,8 +1956,8 @@ bool Image::BlitScaleHelper(bool scale_up) { .end = {static_cast(dst_width), static_cast(dst_height)}, }; const VkExtent2D extent{ - .width = (std::max)(scaled_width, info.size.width), - .height = (std::max)(scaled_height, info.size.height), + .width = std::max(scaled_width, info.size.width), + .height = std::max(scaled_height, info.size.height), }; auto* view_ptr = blit_view.get(); @@ -2160,20 +2160,34 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type, if (!image_handle) { return VK_NULL_HANDLE; } - if (image_format == Shader::ImageFormat::Typeless) { - return Handle(texture_type); - } - const bool is_signed{image_format == Shader::ImageFormat::R8_SINT || - image_format == Shader::ImageFormat::R16_SINT}; + if (!storage_views) { storage_views = std::make_unique(); } - auto& views{is_signed ? storage_views->signeds : storage_views->unsigneds}; - auto& view{views[static_cast(texture_type)]}; - if (view) { + + // Storage images MUST use identity component mapping. + // Typeless: use the underlying image's native format. + if (image_format == Shader::ImageFormat::Typeless) { + auto& view = storage_views->unsigneds[static_cast(texture_type)]; + if (view) { + return *view; + } + const auto fmt_info = + MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, /*is_image=*/true, format); + const VkFormat vk_format = fmt_info.format; + // Storage images are color-aspect only + view = MakeView(vk_format, VK_IMAGE_ASPECT_COLOR_BIT); // identity components inside return *view; } - view = MakeView(Format(image_format), VK_IMAGE_ASPECT_COLOR_BIT); + const bool is_signed = (image_format == Shader::ImageFormat::R8_SINT ||image_format == Shader::ImageFormat::R16_SINT); + auto& views = is_signed ? storage_views->signeds : storage_views->unsigneds; + auto& view = views[static_cast(texture_type)]; + if (view) { + return *view; + } + + const VkFormat vk_format = Format(image_format); + view = MakeView(vk_format, VK_IMAGE_ASPECT_COLOR_BIT);// identity components inside return *view; } @@ -2296,21 +2310,21 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, is_rescaled = is_rescaled_; const auto& resolution = runtime.resolution; - u32 width = (std::numeric_limits::max)(); - u32 height = (std::numeric_limits::max)(); + u32 width = std::numeric_limits::max(); + u32 height = std::numeric_limits::max(); for (size_t index = 0; index < NUM_RT; ++index) { const ImageView* const color_buffer = color_buffers[index]; if (!color_buffer) { renderpass_key.color_formats[index] = PixelFormat::Invalid; continue; } - width = (std::min)(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width) + width = std::min(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width) : color_buffer->size.width); - height = (std::min)(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height) + height = std::min(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height) : color_buffer->size.height); attachments.push_back(color_buffer->RenderTarget()); renderpass_key.color_formats[index] = color_buffer->format; - num_layers = (std::max)(num_layers, color_buffer->range.extent.layers); + num_layers = std::max(num_layers, color_buffer->range.extent.layers); images[num_images] = color_buffer->ImageHandle(); image_ranges[num_images] = MakeSubresourceRange(color_buffer); rt_map[index] = num_images; @@ -2319,13 +2333,13 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, } const size_t num_colors = attachments.size(); if (depth_buffer) { - width = (std::min)(width, is_rescaled ? resolution.ScaleUp(depth_buffer->size.width) + width = std::min(width, is_rescaled ? resolution.ScaleUp(depth_buffer->size.width) : depth_buffer->size.width); - height = (std::min)(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height) + height = std::min(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height) : depth_buffer->size.height); attachments.push_back(depth_buffer->RenderTarget()); renderpass_key.depth_format = depth_buffer->format; - num_layers = (std::max)(num_layers, depth_buffer->range.extent.layers); + num_layers = std::max(num_layers, depth_buffer->range.extent.layers); images[num_images] = depth_buffer->ImageHandle(); const VkImageSubresourceRange subresource_range = MakeSubresourceRange(depth_buffer); image_ranges[num_images] = subresource_range; @@ -2339,8 +2353,8 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, renderpass_key.samples = samples; renderpass = runtime.render_pass_cache.Get(renderpass_key); - render_area.width = (std::min)(render_area.width, width); - render_area.height = (std::min)(render_area.height, height); + render_area.width = std::min(render_area.width, width); + render_area.height = std::min(render_area.height, height); num_color_buffers = static_cast(num_colors); framebuffer = runtime.device.GetLogical().CreateFramebuffer({ @@ -2352,7 +2366,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, .pAttachments = attachments.data(), .width = render_area.width, .height = render_area.height, - .layers = static_cast((std::max)(num_layers, 1)), + .layers = static_cast(std::max(num_layers, 1)), }); } diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 573694a145..baeb8b23a0 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -139,8 +139,8 @@ std::array GenericEnvironment::WorkgroupSize() const { } u64 GenericEnvironment::ReadInstruction(u32 address) { - read_lowest = (std::min)(read_lowest, address); - read_highest = (std::max)(read_highest, address); + read_lowest = std::min(read_lowest, address); + read_highest = std::max(read_highest, address); if (address >= cached_lowest && address < cached_highest) { return code[(address - cached_lowest) / INST_SIZE]; @@ -319,7 +319,7 @@ GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_, break; } const u64 local_size{sph.LocalMemorySize()}; - ASSERT(local_size <= (std::numeric_limits::max)()); + ASSERT(local_size <= std::numeric_limits::max()); local_memory_size = static_cast(local_size) + sph.common3.shader_local_memory_crs_size; texture_bound = maxwell3d->regs.bindless_texture_const_buffer_slot; is_proprietary_driver = texture_bound == 2; diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index 2d781d82f7..6b372e3365 100644 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h @@ -86,10 +86,10 @@ protected: u32 shared_memory_size{}; std::array workgroup_size{}; - u32 read_lowest = (std::numeric_limits::max)(); + u32 read_lowest = std::numeric_limits::max(); u32 read_highest = 0; - u32 cached_lowest = (std::numeric_limits::max)(); + u32 cached_lowest = std::numeric_limits::max(); u32 cached_highest = 0; u32 initial_offset = 0; diff --git a/src/video_core/texture_cache/decode_bc.cpp b/src/video_core/texture_cache/decode_bc.cpp index 5279ff2a0a..a018c6df46 100644 --- a/src/video_core/texture_cache/decode_bc.cpp +++ b/src/video_core/texture_cache/decode_bc.cpp @@ -67,8 +67,8 @@ void DecompressBlocks(std::span input, std::span output, BufferIma const u32 width = copy.image_extent.width; const u32 height = copy.image_extent.height * copy.image_subresource.num_layers; const u32 depth = copy.image_extent.depth; - const u32 block_width = (std::min)(width, BLOCK_SIZE); - const u32 block_height = (std::min)(height, BLOCK_SIZE); + const u32 block_width = std::min(width, BLOCK_SIZE); + const u32 block_height = std::min(height, BLOCK_SIZE); const u32 pitch = width * out_bpp; size_t input_offset = 0; size_t output_offset = 0; diff --git a/src/video_core/texture_cache/image_base.cpp b/src/video_core/texture_cache/image_base.cpp index 01413f0c9d..d79594ce55 100644 --- a/src/video_core/texture_cache/image_base.cpp +++ b/src/video_core/texture_cache/image_base.cpp @@ -185,7 +185,7 @@ bool AddImageAlias(ImageBase& lhs, ImageBase& rhs, ImageId lhs_id, ImageId rhs_i const bool is_rhs_compressed = rhs_block.width > 1 || rhs_block.height > 1; const s32 lhs_mips = lhs.info.resources.levels; const s32 rhs_mips = rhs.info.resources.levels; - const s32 num_mips = (std::min)(lhs_mips - base->level, rhs_mips); + const s32 num_mips = std::min(lhs_mips - base->level, rhs_mips); AliasedImage lhs_alias; AliasedImage rhs_alias; lhs_alias.id = rhs_id; @@ -204,9 +204,9 @@ bool AddImageAlias(ImageBase& lhs, ImageBase& rhs, ImageId lhs_id, ImageId rhs_i rhs_size.height = Common::DivCeil(rhs_size.height, rhs_block.height); } const Extent3D copy_size{ - .width = (std::min)(lhs_size.width, rhs_size.width), - .height = (std::min)(lhs_size.height, rhs_size.height), - .depth = (std::min)(lhs_size.depth, rhs_size.depth), + .width = std::min(lhs_size.width, rhs_size.width), + .height = std::min(lhs_size.height, rhs_size.height), + .depth = std::min(lhs_size.depth, rhs_size.depth), }; if (copy_size.width == 0 || copy_size.height == 0) { LOG_WARNING(HW_GPU, "Copy size is smaller than block size. Mip cannot be aliased."); @@ -218,7 +218,7 @@ bool AddImageAlias(ImageBase& lhs, ImageBase& rhs, ImageId lhs_id, ImageId rhs_i const Offset3D rhs_offset{0, 0, is_rhs_3d ? base->layer : 0}; const s32 lhs_layers = is_lhs_3d ? 1 : lhs.info.resources.layers - base->layer; const s32 rhs_layers = is_rhs_3d ? 1 : rhs.info.resources.layers; - const s32 num_layers = (std::min)(lhs_layers, rhs_layers); + const s32 num_layers = std::min(lhs_layers, rhs_layers); const SubresourceLayers lhs_subresource{ .base_level = mip_level, .base_layer = 0, diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index b7e4049f35..18b9250f91 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp @@ -18,9 +18,9 @@ ImageViewBase::ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_i ImageId image_id_, GPUVAddr addr) : image_id{image_id_}, gpu_addr{addr}, format{info.format}, type{info.type}, range{info.range}, size{ - .width = (std::max)(image_info.size.width >> range.base.level, 1u), - .height = (std::max)(image_info.size.height >> range.base.level, 1u), - .depth = (std::max)(image_info.size.depth >> range.base.level, 1u), + .width = std::max(image_info.size.width >> range.base.level, 1u), + .height = std::max(image_info.size.height >> range.base.level, 1u), + .depth = std::max(image_info.size.depth >> range.base.level, 1u), } { ASSERT_MSG(VideoCore::Surface::IsViewCompatible(image_info.format, info.format, false, true), "Image view format {} is incompatible with image format {}", info.format, diff --git a/src/video_core/texture_cache/image_view_info.cpp b/src/video_core/texture_cache/image_view_info.cpp index 8dac8383e0..0766a3b79a 100644 --- a/src/video_core/texture_cache/image_view_info.cpp +++ b/src/video_core/texture_cache/image_view_info.cpp @@ -19,7 +19,7 @@ namespace { using Tegra::Texture::TextureType; -constexpr u8 RENDER_TARGET_SWIZZLE = (std::numeric_limits::max)(); +constexpr u8 RENDER_TARGET_SWIZZLE = std::numeric_limits::max(); [[nodiscard]] u8 CastSwizzle(SwizzleSource source) { const u8 casted = static_cast(source); diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index e5d559b591..6c733fe902 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -56,14 +56,14 @@ TextureCache

::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag const s64 device_local_memory = static_cast(runtime.GetDeviceLocalMemory()); const s64 min_spacing_expected = device_local_memory - 1_GiB; const s64 min_spacing_critical = device_local_memory - 512_MiB; - const s64 mem_threshold = (std::min)(device_local_memory, TARGET_THRESHOLD); + const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD); const s64 min_vacancy_expected = (6 * mem_threshold) / 10; const s64 min_vacancy_critical = (2 * mem_threshold) / 10; expected_memory = static_cast( - (std::max)((std::min)(device_local_memory - min_vacancy_expected, min_spacing_expected), + std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected), DEFAULT_EXPECTED_MEMORY)); critical_memory = static_cast( - (std::max)((std::min)(device_local_memory - min_vacancy_critical, min_spacing_critical), + std::max(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical), DEFAULT_CRITICAL_MEMORY)); minimum_memory = static_cast((device_local_memory - mem_threshold) / 2); } else { @@ -586,8 +586,8 @@ std::optional TextureCache

::GetFlushArea(D area->end_address = cpu_addr + size; area->preemtive = true; } - area->start_address = (std::min)(area->start_address, image.cpu_addr); - area->end_address = (std::max)(area->end_address, image.cpu_addr_end); + area->start_address = std::min(area->start_address, image.cpu_addr); + area->end_address = std::max(area->end_address, image.cpu_addr_end); for (auto image_view_id : image.image_view_ids) { auto& image_view = slot_image_views[image_view_id]; image_view.flags |= ImageViewFlagBits::PreemtiveDownload; @@ -1273,7 +1273,7 @@ u64 TextureCache

::GetScaledImageSizeBytes(const ImageBase& image) { const u64 down_shift = static_cast(Settings::values.resolution_info.down_shift + Settings::values.resolution_info.down_shift); const u64 image_size_bytes = - static_cast((std::max)(image.guest_size_bytes, image.unswizzled_size_bytes)); + static_cast(std::max(image.guest_size_bytes, image.unswizzled_size_bytes)); const u64 tentative_size = (image_size_bytes * scale_up) >> down_shift; const u64 fitted_size = Common::AlignUp(tentative_size, 1024); return fitted_size; @@ -1994,7 +1994,7 @@ void TextureCache

::RegisterImage(ImageId image_id) { ASSERT_MSG(False(image.flags & ImageFlagBits::Registered), "Trying to register an already registered image"); image.flags |= ImageFlagBits::Registered; - u64 tentative_size = (std::max)(image.guest_size_bytes, image.unswizzled_size_bytes); + u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); if ((IsPixelFormatASTC(image.info.format) && True(image.flags & ImageFlagBits::AcceleratedUpload)) || True(image.flags & ImageFlagBits::Converted)) { @@ -2168,7 +2168,7 @@ void TextureCache

::DeleteImage(ImageId image_id, bool immediate_delete) { if (image.HasScaled()) { total_used_memory -= GetScaledImageSizeBytes(image); } - u64 tentative_size = (std::max)(image.guest_size_bytes, image.unswizzled_size_bytes); + u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); if ((IsPixelFormatASTC(image.info.format) && True(image.flags & ImageFlagBits::AcceleratedUpload)) || True(image.flags & ImageFlagBits::Converted)) { @@ -2302,7 +2302,7 @@ void TextureCache

::SynchronizeAliases(ImageId image_id) { for (const AliasedImage& aliased : image.aliased_images) { ImageBase& aliased_image = slot_images[aliased.id]; if (image.modification_tick < aliased_image.modification_tick) { - most_recent_tick = (std::max)(most_recent_tick, aliased_image.modification_tick); + most_recent_tick = std::max(most_recent_tick, aliased_image.modification_tick); aliased_images.push_back(&aliased); any_rescaled |= True(aliased_image.flags & ImageFlagBits::Rescaled); any_modified |= True(aliased_image.flags & ImageFlagBits::GpuModified); @@ -2443,9 +2443,9 @@ void TextureCache

::CopyImage(ImageId dst_id, ImageId src_id, std::vector::max)()}; + static constexpr size_t UNSET_CHANNEL{std::numeric_limits::max()}; static constexpr s64 TARGET_THRESHOLD = 4_GiB; static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB; diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index ede451b166..e3faa5bf95 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp @@ -327,8 +327,8 @@ template } const SubresourceExtent resources = new_info.resources; return SubresourceExtent{ - .levels = (std::max)(resources.levels, info.resources.levels), - .layers = (std::max)(resources.layers, info.resources.layers), + .levels = std::max(resources.levels, info.resources.levels), + .layers = std::max(resources.layers, info.resources.layers), }; } @@ -354,7 +354,7 @@ template return std::nullopt; } return SubresourceExtent{ - .levels = (std::max)(new_info.resources.levels, info.resources.levels + base.level), + .levels = std::max(new_info.resources.levels, info.resources.levels + base.level), .layers = 1, }; } @@ -388,8 +388,8 @@ template return std::nullopt; } return SubresourceExtent{ - .levels = (std::max)(new_info.resources.levels, info.resources.levels + base.level), - .layers = (std::max)(new_info.resources.layers, info.resources.layers + base.layer), + .levels = std::max(new_info.resources.levels, info.resources.levels + base.level), + .layers = std::max(new_info.resources.layers, info.resources.layers + base.layer), }; } @@ -439,14 +439,14 @@ template } layers = 1; } else { - layers = (std::max)(resources.layers, info.resources.layers + base->layer); + layers = std::max(resources.layers, info.resources.layers + base->layer); } return OverlapResult{ .gpu_addr = overlap.gpu_addr, .cpu_addr = overlap.cpu_addr, .resources = { - .levels = (std::max)(resources.levels + base->level, info.resources.levels), + .levels = std::max(resources.levels + base->level, info.resources.levels), .layers = layers, }, }; diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp index 85fd06957e..fef0be31d8 100644 --- a/src/video_core/textures/astc.cpp +++ b/src/video_core/textures/astc.cpp @@ -1291,7 +1291,7 @@ static void ComputeEndpoints(Pixel& ep1, Pixel& ep2, const u32*& colorValues, case 1: { READ_UINT_VALUES(2) u32 L0 = (v[0] >> 2) | (v[1] & 0xC0); - u32 L1 = (std::min)(L0 + (v[1] & 0x3F), 0xFFU); + u32 L1 = std::min(L0 + (v[1] & 0x3F), 0xFFU); ep1 = Pixel(0xFF, L0, L0, L0); ep2 = Pixel(0xFF, L1, L1, L1); } break; @@ -1522,7 +1522,7 @@ static void DecompressBlock(std::span inBuf, const u32 blockWidth, // Read color data... u32 colorDataBits = remainingBits; while (remainingBits > 0) { - u32 nb = (std::min)(remainingBits, 8); + u32 nb = std::min(remainingBits, 8); u32 b = strm.ReadBits(nb); colorEndpointStream.WriteBits(b, nb); remainingBits -= 8; @@ -1603,7 +1603,7 @@ static void DecompressBlock(std::span inBuf, const u32 blockWidth, texelWeightData[clearByteStart - 1] &= static_cast((1 << (weightParams.GetPackedBitSize() % 8)) - 1); std::memset(texelWeightData.data() + clearByteStart, 0, - (std::min)(16U - clearByteStart, 16U)); + std::min(16U - clearByteStart, 16U)); } IntegerEncodedVector texelWeightValues; @@ -1674,8 +1674,8 @@ void Decompress(std::span data, uint32_t width, uint32_t height, std::array uncompData; DecompressBlock(blockPtr, block_width, block_height, uncompData); - u32 decompWidth = (std::min)(block_width, width - x); - u32 decompHeight = (std::min)(block_height, height - y); + u32 decompWidth = std::min(block_width, width - x); + u32 decompHeight = std::min(block_height, height - y); const std::span outRow = output.subspan(depth_offset + (y * width + x) * 4); for (u32 h = 0; h < decompHeight; ++h) { diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 12e4ddf165..95bcdd37b2 100644 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -111,13 +111,13 @@ void SwizzleSubrectImpl(std::span output, std::span input, u32 wid const u32 x_shift = GOB_SIZE_SHIFT + block_height + block_depth; u32 unprocessed_lines = num_lines; - u32 extent_y = (std::min)(num_lines, height - origin_y); + u32 extent_y = std::min(num_lines, height - origin_y); for (u32 slice = 0; slice < depth; ++slice) { const u32 z = slice + origin_z; const u32 offset_z = (z >> block_depth) * slice_size + ((z & block_depth_mask) << (GOB_SIZE_SHIFT + block_height)); - const u32 lines_in_y = (std::min)(unprocessed_lines, extent_y); + const u32 lines_in_y = std::min(unprocessed_lines, extent_y); for (u32 line = 0; line < lines_in_y; ++line) { const u32 y = line + origin_y; const u32 swizzled_y = pdep(y); @@ -180,7 +180,7 @@ void UnswizzleTexture(std::span output, std::span input, u32 bytes u32 width, u32 height, u32 depth, u32 block_height, u32 block_depth, u32 stride_alignment) { const u32 stride = Common::AlignUpLog2(width, stride_alignment) * bytes_per_pixel; - const u32 new_bpp = (std::min)(4U, static_cast(std::countr_zero(width * bytes_per_pixel))); + const u32 new_bpp = std::min(4U, static_cast(std::countr_zero(width * bytes_per_pixel))); width = (width * bytes_per_pixel) >> new_bpp; bytes_per_pixel = 1U << new_bpp; Swizzle(output, input, bytes_per_pixel, width, height, depth, block_height, block_depth, @@ -191,7 +191,7 @@ void SwizzleTexture(std::span output, std::span input, u32 bytes_p u32 height, u32 depth, u32 block_height, u32 block_depth, u32 stride_alignment) { const u32 stride = Common::AlignUpLog2(width, stride_alignment) * bytes_per_pixel; - const u32 new_bpp = (std::min)(4U, static_cast(std::countr_zero(width * bytes_per_pixel))); + const u32 new_bpp = std::min(4U, static_cast(std::countr_zero(width * bytes_per_pixel))); width = (width * bytes_per_pixel) >> new_bpp; bytes_per_pixel = 1U << new_bpp; Swizzle(output, input, bytes_per_pixel, width, height, depth, block_height, block_depth, diff --git a/src/video_core/textures/texture.cpp b/src/video_core/textures/texture.cpp index 2798d5839f..39c08b5ae1 100644 --- a/src/video_core/textures/texture.cpp +++ b/src/video_core/textures/texture.cpp @@ -75,7 +75,7 @@ float TSCEntry::MaxAnisotropy() const noexcept { if (anisotropic_settings == Settings::AnisotropyMode::Automatic) { added_anisotropic = Settings::values.resolution_info.up_scale >> Settings::values.resolution_info.down_shift; - added_anisotropic = (std::max)(added_anisotropic - 1, 0); + added_anisotropic = std::max(added_anisotropic - 1, 0); } else { added_anisotropic = static_cast(Settings::values.max_anisotropy.GetValue()) - 1U; } diff --git a/src/video_core/textures/workers.cpp b/src/video_core/textures/workers.cpp index 01aa716e11..a71c305f49 100644 --- a/src/video_core/textures/workers.cpp +++ b/src/video_core/textures/workers.cpp @@ -6,7 +6,7 @@ namespace Tegra::Texture { Common::ThreadWorker& GetThreadWorkers() { - static Common::ThreadWorker workers{(std::max)(std::thread::hardware_concurrency(), 2U) / 2, + static Common::ThreadWorker workers{std::max(std::thread::hardware_concurrency(), 2U) / 2, "ImageTranscode"}; return workers; diff --git a/src/video_core/transform_feedback.cpp b/src/video_core/transform_feedback.cpp index 5dda1ffafc..1f353d2df0 100644 --- a/src/video_core/transform_feedback.cpp +++ b/src/video_core/transform_feedback.cpp @@ -104,8 +104,8 @@ std::pair, u32> MakeTransformF } } xfb[attribute] = varying; - count = (std::max)(count, attribute); - highest = (std::max)(highest, (base_offset + varying.components) * 4); + count = std::max(count, attribute); + highest = std::max(highest, (base_offset + varying.components) * 4); } UNIMPLEMENTED_IF(highest != layout.stride); } diff --git a/src/video_core/vulkan_common/vma.h b/src/video_core/vulkan_common/vma.h index 911c1114b2..6e25aa1bdf 100644 --- a/src/video_core/vulkan_common/vma.h +++ b/src/video_core/vulkan_common/vma.h @@ -1,5 +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 @@ -10,4 +8,4 @@ #define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 -#include "vk_mem_alloc.h" +#include diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 6d7c33099b..95c0d974cc 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -699,9 +699,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR LOG_WARNING(Render_Vulkan, "MVK driver breaks when using more than 16 vertex attributes/bindings"); properties.properties.limits.maxVertexInputAttributes = - (std::min)(properties.properties.limits.maxVertexInputAttributes, 16U); + std::min(properties.properties.limits.maxVertexInputAttributes, 16U); properties.properties.limits.maxVertexInputBindings = - (std::min)(properties.properties.limits.maxVertexInputBindings, 16U); + std::min(properties.properties.limits.maxVertexInputBindings, 16U); } if (is_turnip) { @@ -725,11 +725,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR dynamic_state3_enables = true; } - if (is_mvk && Settings::values.dyna_state.GetValue() != 0) { - LOG_WARNING(Render_Vulkan, "MoltenVK detected: Forcing dynamic state to 0 to prevent black screen issues"); - Settings::values.dyna_state.SetValue(0); - } - if (Settings::values.dyna_state.GetValue() == 0) { must_emulate_scaled_formats = true; LOG_INFO(Render_Vulkan, "Dynamic state is disabled (dyna_state = 0), forcing scaled format emulation ON"); @@ -758,24 +753,18 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR functions.vkGetInstanceProcAddr = dld.vkGetInstanceProcAddr; functions.vkGetDeviceProcAddr = dld.vkGetDeviceProcAddr; - VmaAllocatorCreateFlags flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT; - if (extensions.memory_budget) { - flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; - } - const VmaAllocatorCreateInfo allocator_info{ - .flags = flags, - .physicalDevice = physical, - .device = *logical, - .preferredLargeHeapBlockSize = is_integrated - ? (64u * 1024u * 1024u) - : (256u * 1024u * 1024u), - .pAllocationCallbacks = nullptr, - .pDeviceMemoryCallbacks = nullptr, - .pHeapSizeLimit = nullptr, - .pVulkanFunctions = &functions, - .instance = instance, - .vulkanApiVersion = ApiVersion(), - .pTypeExternalMemoryHandleTypes = nullptr, + const VmaAllocatorCreateInfo allocator_info = { + .flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, + .physicalDevice = physical, + .device = *logical, + .preferredLargeHeapBlockSize = 0, + .pAllocationCallbacks = nullptr, + .pDeviceMemoryCallbacks = nullptr, + .pHeapSizeLimit = nullptr, + .pVulkanFunctions = &functions, + .instance = instance, + .vulkanApiVersion = VK_API_VERSION_1_1, + .pTypeExternalMemoryHandleTypes = nullptr, }; vk::Check(vmaCreateAllocator(&allocator_info, &allocator)); @@ -1101,15 +1090,8 @@ bool Device::GetSuitability(bool requires_swapchain) { // Some features are mandatory. Check those. #define CHECK_FEATURE(feature, name) \ if (!features.feature.name) { \ - if (IsMoltenVK() && (strcmp(#name, "geometryShader") == 0 || \ - strcmp(#name, "logicOp") == 0 || \ - strcmp(#name, "shaderCullDistance") == 0 || \ - strcmp(#name, "wideLines") == 0)) { \ - LOG_INFO(Render_Vulkan, "MoltenVK missing feature {} - using fallback", #name); \ - } else { \ - LOG_ERROR(Render_Vulkan, "Missing required feature {}", #name); \ - suitable = false; \ - } \ + LOG_ERROR(Render_Vulkan, "Missing required feature {}", #name); \ + suitable = false; \ } #define LOG_FEATURE(feature, name) \ diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index bd54144480..9b78f2e599 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -717,10 +717,6 @@ public: return properties.driver.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY; } - bool IsMoltenVK() const noexcept { - return properties.driver.driverID == VK_DRIVER_ID_MOLTENVK; - } - NvidiaArchitecture GetNvidiaArch() const noexcept { return nvidia_arch; } diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 119b4be1c8..2e37615f99 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -6,10 +6,7 @@ #include #include -#include #include -#include -#include #include #include "common/alignment.h" @@ -24,305 +21,379 @@ #include "video_core/vulkan_common/vulkan_wrapper.h" namespace Vulkan { - namespace { +namespace { +struct Range { + u64 begin; + u64 end; -// Helpers translating MemoryUsage to flags/usage - - [[maybe_unused]] VkMemoryPropertyFlags MemoryUsagePropertyFlags(MemoryUsage usage) { - switch (usage) { - case MemoryUsage::DeviceLocal: - return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - case MemoryUsage::Upload: - return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - case MemoryUsage::Download: - return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | - VK_MEMORY_PROPERTY_HOST_CACHED_BIT; - case MemoryUsage::Stream: - return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | - VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - } - ASSERT_MSG(false, "Invalid memory usage={}", usage); - return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - } - - [[nodiscard]] VkMemoryPropertyFlags MemoryUsagePreferredVmaFlags(MemoryUsage usage) { - if (usage == MemoryUsage::Download) { - return VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - } - return usage != MemoryUsage::DeviceLocal ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT - : VkMemoryPropertyFlagBits{}; - } - - [[nodiscard]] VmaAllocationCreateFlags MemoryUsageVmaFlags(MemoryUsage usage) { - switch (usage) { - case MemoryUsage::Upload: - case MemoryUsage::Stream: - return VMA_ALLOCATION_CREATE_MAPPED_BIT | - VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; - case MemoryUsage::Download: - return VMA_ALLOCATION_CREATE_MAPPED_BIT | - VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; - case MemoryUsage::DeviceLocal: - return {}; - } - return {}; - } - - [[nodiscard]] VmaMemoryUsage MemoryUsageVma(MemoryUsage usage) { - switch (usage) { - case MemoryUsage::DeviceLocal: - case MemoryUsage::Stream: - return VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; - case MemoryUsage::Upload: - case MemoryUsage::Download: - return VMA_MEMORY_USAGE_AUTO_PREFER_HOST; - } - return VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; - } - - -// This avoids calling vkGetBufferMemoryRequirements* directly. - template - static VkBuffer GetVkHandleFromBuffer(const T &buf) { - if constexpr (requires { static_cast(buf); }) { - return static_cast(buf); - } else if constexpr (requires {{ buf.GetHandle() } -> std::convertible_to; }) { - return buf.GetHandle(); - } else if constexpr (requires {{ buf.Handle() } -> std::convertible_to; }) { - return buf.Handle(); - } else if constexpr (requires {{ buf.vk_handle() } -> std::convertible_to; }) { - return buf.vk_handle(); - } else { - static_assert(sizeof(T) == 0, "Cannot extract VkBuffer handle from vk::Buffer"); - return VK_NULL_HANDLE; - } - } - - } // namespace - -//MemoryCommit is now VMA-backed - MemoryCommit::MemoryCommit(VmaAllocator alloc, VmaAllocation a, - const VmaAllocationInfo &info) noexcept - : allocator{alloc}, allocation{a}, memory{info.deviceMemory}, - offset{info.offset}, size{info.size}, mapped_ptr{info.pMappedData} {} - - MemoryCommit::~MemoryCommit() { Release(); } - - MemoryCommit::MemoryCommit(MemoryCommit &&rhs) noexcept - : allocator{std::exchange(rhs.allocator, nullptr)}, - allocation{std::exchange(rhs.allocation, nullptr)}, - memory{std::exchange(rhs.memory, VK_NULL_HANDLE)}, - offset{std::exchange(rhs.offset, 0)}, - size{std::exchange(rhs.size, 0)}, - mapped_ptr{std::exchange(rhs.mapped_ptr, nullptr)} {} - - MemoryCommit &MemoryCommit::operator=(MemoryCommit &&rhs) noexcept { - if (this != &rhs) { - Release(); - allocator = std::exchange(rhs.allocator, nullptr); - allocation = std::exchange(rhs.allocation, nullptr); - memory = std::exchange(rhs.memory, VK_NULL_HANDLE); - offset = std::exchange(rhs.offset, 0); - size = std::exchange(rhs.size, 0); - mapped_ptr = std::exchange(rhs.mapped_ptr, nullptr); - } - return *this; + [[nodiscard]] bool Contains(u64 iterator, u64 size) const noexcept { + return iterator < end && begin < iterator + size; } +}; - std::span MemoryCommit::Map() - { - if (!allocation) return {}; - if (!mapped_ptr) { - if (vmaMapMemory(allocator, allocation, &mapped_ptr) != VK_SUCCESS) return {}; - } - const size_t n = static_cast(std::min(size, - (std::numeric_limits::max)())); - return std::span{static_cast(mapped_ptr), n}; +[[nodiscard]] u64 AllocationChunkSize(u64 required_size) { + static constexpr std::array sizes{ + 0x1000ULL << 10, 0x1400ULL << 10, 0x1800ULL << 10, 0x1c00ULL << 10, 0x2000ULL << 10, + 0x3200ULL << 10, 0x4000ULL << 10, 0x6000ULL << 10, 0x8000ULL << 10, 0xA000ULL << 10, + 0x10000ULL << 10, 0x18000ULL << 10, 0x20000ULL << 10, + }; + static_assert(std::is_sorted(sizes.begin(), sizes.end())); + + const auto it = std::ranges::lower_bound(sizes, required_size); + return it != sizes.end() ? *it : Common::AlignUp(required_size, 4ULL << 20); +} + +[[nodiscard]] VkMemoryPropertyFlags MemoryUsagePropertyFlags(MemoryUsage usage) { + switch (usage) { + case MemoryUsage::DeviceLocal: + return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + case MemoryUsage::Upload: + return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + case MemoryUsage::Download: + return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | + VK_MEMORY_PROPERTY_HOST_CACHED_BIT; + case MemoryUsage::Stream: + return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; } + ASSERT_MSG(false, "Invalid memory usage={}", usage); + return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; +} - std::span MemoryCommit::Map() const - { - if (!allocation) return {}; - if (!mapped_ptr) { - void *p = nullptr; - if (vmaMapMemory(allocator, allocation, &p) != VK_SUCCESS) return {}; - const_cast(this)->mapped_ptr = p; - } - const size_t n = static_cast(std::min(size, - (std::numeric_limits::max)())); - return std::span{static_cast(mapped_ptr), n}; +[[nodiscard]] VkMemoryPropertyFlags MemoryUsagePreferredVmaFlags(MemoryUsage usage) { + return usage != MemoryUsage::DeviceLocal ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + : VkMemoryPropertyFlagBits{}; +} + +[[nodiscard]] VmaAllocationCreateFlags MemoryUsageVmaFlags(MemoryUsage usage) { + switch (usage) { + case MemoryUsage::Upload: + case MemoryUsage::Stream: + return VMA_ALLOCATION_CREATE_MAPPED_BIT | + VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; + case MemoryUsage::Download: + return VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; + case MemoryUsage::DeviceLocal: + return {}; } + return {}; +} - void MemoryCommit::Unmap() - { - if (allocation && mapped_ptr) { - vmaUnmapMemory(allocator, allocation); - mapped_ptr = nullptr; - } +[[nodiscard]] VmaMemoryUsage MemoryUsageVma(MemoryUsage usage) { + switch (usage) { + case MemoryUsage::DeviceLocal: + case MemoryUsage::Stream: + return VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; + case MemoryUsage::Upload: + case MemoryUsage::Download: + return VMA_MEMORY_USAGE_AUTO_PREFER_HOST; } + return VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; +} - void MemoryCommit::Release() { - if (allocation && allocator) { - if (mapped_ptr) { - vmaUnmapMemory(allocator, allocation); - mapped_ptr = nullptr; - } - vmaFreeMemory(allocator, allocation); +} // Anonymous namespace + +class MemoryAllocation { +public: + explicit MemoryAllocation(MemoryAllocator* const allocator_, vk::DeviceMemory memory_, + VkMemoryPropertyFlags properties, u64 allocation_size_, u32 type) + : allocator{allocator_}, memory{std::move(memory_)}, allocation_size{allocation_size_}, + property_flags{properties}, shifted_memory_type{1U << type} {} + + MemoryAllocation& operator=(const MemoryAllocation&) = delete; + MemoryAllocation(const MemoryAllocation&) = delete; + + MemoryAllocation& operator=(MemoryAllocation&&) = delete; + MemoryAllocation(MemoryAllocation&&) = delete; + + [[nodiscard]] std::optional Commit(VkDeviceSize size, VkDeviceSize alignment) { + const std::optional alloc = FindFreeRegion(size, alignment); + if (!alloc) { + // Signal out of memory, it'll try to do more allocations. + return std::nullopt; } - allocation = nullptr; - allocator = nullptr; - memory = VK_NULL_HANDLE; - offset = 0; - size = 0; - } - - MemoryAllocator::MemoryAllocator(const Device &device_) - : device{device_}, allocator{device.GetAllocator()}, - properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, - buffer_image_granularity{ - device_.GetPhysical().GetProperties().limits.bufferImageGranularity} { - - // Preserve the previous "RenderDoc small heap" trimming behavior that we had in original vma minus the heap bug - if (device.HasDebuggingToolAttached()) - { - using namespace Common::Literals; - ForEachDeviceLocalHostVisibleHeap(device, [this](size_t heap_idx, VkMemoryHeap &heap) { - if (heap.size <= 256_MiB) { - for (u32 t = 0; t < properties.memoryTypeCount; ++t) { - if (properties.memoryTypes[t].heapIndex == heap_idx) { - valid_memory_types &= ~(1u << t); - } - } - } - }); - } - } - - MemoryAllocator::~MemoryAllocator() = default; - - vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo &ci) const - { - const VmaAllocationCreateInfo alloc_ci = { - .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT, - .usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, - .requiredFlags = 0, - .preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .memoryTypeBits = 0, - .pool = VK_NULL_HANDLE, - .pUserData = nullptr, - .priority = 0.f, + const Range range{ + .begin = *alloc, + .end = *alloc + size, }; - - VkImage handle{}; - VmaAllocation allocation{}; - vk::Check(vmaCreateImage(allocator, &ci, &alloc_ci, &handle, &allocation, nullptr)); - return vk::Image(handle, ci.usage, *device.GetLogical(), allocator, allocation, - device.GetDispatchLoader()); + commits.insert(std::ranges::upper_bound(commits, *alloc, {}, &Range::begin), range); + return std::make_optional(this, *memory, *alloc, *alloc + size); } - vk::Buffer - MemoryAllocator::CreateBuffer(const VkBufferCreateInfo &ci, MemoryUsage usage) const - { - const VmaAllocationCreateInfo alloc_ci = { - .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | MemoryUsageVmaFlags(usage), - .usage = MemoryUsageVma(usage), - .requiredFlags = 0, - .preferredFlags = MemoryUsagePreferredVmaFlags(usage), - .memoryTypeBits = usage == MemoryUsage::Stream ? 0u : valid_memory_types, - .pool = VK_NULL_HANDLE, - .pUserData = nullptr, - .priority = 0.f, - }; - - VkBuffer handle{}; - VmaAllocationInfo alloc_info{}; - VmaAllocation allocation{}; - VkMemoryPropertyFlags property_flags{}; - - vk::Check(vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info)); - vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags); - - u8 *data = reinterpret_cast(alloc_info.pMappedData); - const std::span mapped_data = data ? std::span{data, ci.size} : std::span{}; - const bool is_coherent = (property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; - - return vk::Buffer(handle, *device.GetLogical(), allocator, allocation, mapped_data, - is_coherent, - device.GetDispatchLoader()); - } - - MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements &reqs, MemoryUsage usage) - { - const auto vma_usage = MemoryUsageVma(usage); - VmaAllocationCreateInfo ci{}; - ci.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | MemoryUsageVmaFlags(usage); - ci.usage = vma_usage; - ci.memoryTypeBits = reqs.memoryTypeBits & valid_memory_types; - ci.requiredFlags = 0; - ci.preferredFlags = MemoryUsagePreferredVmaFlags(usage); - - VmaAllocation a{}; - VmaAllocationInfo info{}; - - VkResult res = vmaAllocateMemory(allocator, &reqs, &ci, &a, &info); - - if (res != VK_SUCCESS) { - // Relax 1: drop budget constraint - auto ci2 = ci; - ci2.flags &= ~VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT; - res = vmaAllocateMemory(allocator, &reqs, &ci2, &a, &info); - - // Relax 2: if we preferred DEVICE_LOCAL, drop that preference - if (res != VK_SUCCESS && (ci.preferredFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) { - auto ci3 = ci2; - ci3.preferredFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - res = vmaAllocateMemory(allocator, &reqs, &ci3, &a, &info); - } + void Free(u64 begin) { + const auto it = std::ranges::find(commits, begin, &Range::begin); + ASSERT_MSG(it != commits.end(), "Invalid commit"); + commits.erase(it); + if (commits.empty()) { + // Do not call any code involving 'this' after this call, the object will be destroyed + allocator->ReleaseMemory(this); } - - vk::Check(res); - return MemoryCommit(allocator, a, info); } - MemoryCommit MemoryAllocator::Commit(const vk::Buffer &buffer, MemoryUsage usage) { - // Allocate memory appropriate for this buffer automatically - const auto vma_usage = MemoryUsageVma(usage); - - VmaAllocationCreateInfo ci{}; - ci.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | MemoryUsageVmaFlags(usage); - ci.usage = vma_usage; - ci.requiredFlags = 0; - ci.preferredFlags = MemoryUsagePreferredVmaFlags(usage); - ci.pool = VK_NULL_HANDLE; - ci.pUserData = nullptr; - ci.priority = 0.0f; - - const VkBuffer raw = *buffer; - - VmaAllocation a{}; - VmaAllocationInfo info{}; - - // Let VMA infer memory requirements from the buffer - VkResult res = vmaAllocateMemoryForBuffer(allocator, raw, &ci, &a, &info); - - if (res != VK_SUCCESS) { - auto ci2 = ci; - ci2.flags &= ~VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT; - res = vmaAllocateMemoryForBuffer(allocator, raw, &ci2, &a, &info); - - if (res != VK_SUCCESS && (ci.preferredFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) { - auto ci3 = ci2; - ci3.preferredFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - res = vmaAllocateMemoryForBuffer(allocator, raw, &ci3, &a, &info); - } + [[nodiscard]] std::span Map() { + if (memory_mapped_span.empty()) { + u8* const raw_pointer = memory.Map(0, allocation_size); + memory_mapped_span = std::span(raw_pointer, allocation_size); } - - vk::Check(res); - vk::Check(vmaBindBufferMemory2(allocator, a, 0, raw, nullptr)); - return MemoryCommit(allocator, a, info); + return memory_mapped_span; } + /// Returns whether this allocation is compatible with the arguments. + [[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const { + return (flags & property_flags) == flags && (type_mask & shifted_memory_type) != 0; + } + + +private: + [[nodiscard]] static constexpr u32 ShiftType(u32 type) { + return 1U << type; + } + + [[nodiscard]] std::optional FindFreeRegion(u64 size, u64 alignment) noexcept { + ASSERT(std::has_single_bit(alignment)); + const u64 alignment_log2 = std::countr_zero(alignment); + std::optional candidate; + u64 iterator = 0; + auto commit = commits.begin(); + while (iterator + size <= allocation_size) { + candidate = candidate.value_or(iterator); + if (commit == commits.end()) { + break; + } + if (commit->Contains(*candidate, size)) { + candidate = std::nullopt; + } + iterator = Common::AlignUpLog2(commit->end, alignment_log2); + ++commit; + } + return candidate; + } + + MemoryAllocator* const allocator; ///< Parent memory allocation. + const vk::DeviceMemory memory; ///< Vulkan memory allocation handler. + const u64 allocation_size; ///< Size of this allocation. + const VkMemoryPropertyFlags property_flags; ///< Vulkan memory property flags. + const u32 shifted_memory_type; ///< Shifted Vulkan memory type. + std::vector commits; ///< All commit ranges done from this allocation. + std::span memory_mapped_span; ///< Memory mapped span. Empty if not queried before. +}; + +MemoryCommit::MemoryCommit(MemoryAllocation* allocation_, VkDeviceMemory memory_, u64 begin_, + u64 end_) noexcept + : allocation{allocation_}, memory{memory_}, begin{begin_}, end{end_} {} + +MemoryCommit::~MemoryCommit() { + Release(); +} + +MemoryCommit& MemoryCommit::operator=(MemoryCommit&& rhs) noexcept { + Release(); + allocation = std::exchange(rhs.allocation, nullptr); + memory = rhs.memory; + begin = rhs.begin; + end = rhs.end; + span = std::exchange(rhs.span, std::span{}); + return *this; +} + +MemoryCommit::MemoryCommit(MemoryCommit&& rhs) noexcept + : allocation{std::exchange(rhs.allocation, nullptr)}, memory{rhs.memory}, begin{rhs.begin}, + end{rhs.end}, span{std::exchange(rhs.span, std::span{})} {} + +std::span MemoryCommit::Map() { + if (span.empty()) { + span = allocation->Map().subspan(begin, end - begin); + } + return span; +} + +void MemoryCommit::Release() { + if (allocation) { + allocation->Free(begin); + } +} + +MemoryAllocator::MemoryAllocator(const Device& device_) + : device{device_}, allocator{device.GetAllocator()}, + properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, + buffer_image_granularity{ + device_.GetPhysical().GetProperties().limits.bufferImageGranularity} { + // GPUs not supporting rebar may only have a region with less than 256MB host visible/device + // local memory. In that case, opening 2 RenderDoc captures side-by-side is not possible due to + // the heap running out of memory. With RenderDoc attached and only a small host/device region, + // only allow the stream buffer in this memory heap. + if (device.HasDebuggingToolAttached()) { + using namespace Common::Literals; + ForEachDeviceLocalHostVisibleHeap(device, [this](size_t index, VkMemoryHeap& heap) { + if (heap.size <= 256_MiB) { + valid_memory_types &= ~(1u << index); + } + }); + } +} + +MemoryAllocator::~MemoryAllocator() = default; + +vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const { + const VmaAllocationCreateInfo alloc_ci = { + .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT, + .usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, + .requiredFlags = 0, + .preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .memoryTypeBits = 0, + .pool = VK_NULL_HANDLE, + .pUserData = nullptr, + .priority = 0.f, + }; + + VkImage handle{}; + VmaAllocation allocation{}; + + vk::Check(vmaCreateImage(allocator, &ci, &alloc_ci, &handle, &allocation, nullptr)); + + return vk::Image(handle, ci.usage, *device.GetLogical(), allocator, allocation, + device.GetDispatchLoader()); +} + +vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const { + const VmaAllocationCreateInfo alloc_ci = { + .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | MemoryUsageVmaFlags(usage), + .usage = MemoryUsageVma(usage), + .requiredFlags = 0, + .preferredFlags = MemoryUsagePreferredVmaFlags(usage), + .memoryTypeBits = usage == MemoryUsage::Stream ? 0u : valid_memory_types, + .pool = VK_NULL_HANDLE, + .pUserData = nullptr, + .priority = 0.f, + }; + + VkBuffer handle{}; + VmaAllocationInfo alloc_info{}; + VmaAllocation allocation{}; + VkMemoryPropertyFlags property_flags{}; + + vk::Check(vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info)); + vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags); + + u8* data = reinterpret_cast(alloc_info.pMappedData); + const std::span mapped_data = data ? std::span{data, ci.size} : std::span{}; + const bool is_coherent = property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + return vk::Buffer(handle, *device.GetLogical(), allocator, allocation, mapped_data, is_coherent, + device.GetDispatchLoader()); +} + +MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, MemoryUsage usage) { + // Find the fastest memory flags we can afford with the current requirements + const u32 type_mask = requirements.memoryTypeBits; + const VkMemoryPropertyFlags usage_flags = MemoryUsagePropertyFlags(usage); + const VkMemoryPropertyFlags flags = MemoryPropertyFlags(type_mask, usage_flags); + if (std::optional commit = TryCommit(requirements, flags)) { + return std::move(*commit); + } + // Commit has failed, allocate more memory. + const u64 chunk_size = AllocationChunkSize(requirements.size); + if (!TryAllocMemory(flags, type_mask, chunk_size)) { + // TODO(Rodrigo): Handle out of memory situations in some way like flushing to guest memory. + throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY); + } + // Commit again, this time it won't fail since there's a fresh allocation above. + // If it does, there's a bug. + return TryCommit(requirements, flags).value(); + } + +bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) { + const auto type_opt = FindType(flags, type_mask); + if (!type_opt) { + return false; + } + + // Adreno stands firm + const u64 aligned_size = (device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) ? + Common::AlignUp(size, 4096) : + size; + + vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({ + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = nullptr, + .allocationSize = aligned_size, + .memoryTypeIndex = *type_opt, + }); + + if (!memory) { + return false; + } + + allocations.push_back( + std::make_unique(this, std::move(memory), flags, aligned_size, *type_opt)); + return true; +} + +void MemoryAllocator::ReleaseMemory(MemoryAllocation* alloc) { + const auto it = std::ranges::find(allocations, alloc, &std::unique_ptr::get); + ASSERT(it != allocations.end()); + allocations.erase(it); +} + +std::optional MemoryAllocator::TryCommit(const VkMemoryRequirements& requirements, + VkMemoryPropertyFlags flags) { + // Conservative, spec-compliant alignment for suballocation + VkDeviceSize eff_align = requirements.alignment; + const auto& limits = device.GetPhysical().GetProperties().limits; + if ((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && + !(flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { + // Non-coherent memory must be invalidated on atom boundary + if (limits.nonCoherentAtomSize > eff_align) eff_align = limits.nonCoherentAtomSize; + } + // Separate buffers to avoid stalls on tilers + if (buffer_image_granularity > eff_align) { + eff_align = buffer_image_granularity; + } + eff_align = std::bit_ceil(eff_align); + + for (auto& allocation : allocations) { + if (!allocation->IsCompatible(flags, requirements.memoryTypeBits)) { + continue; + } + if (auto commit = allocation->Commit(requirements.size, eff_align)) { + return commit; + } + } + if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) { + // Look for non device local commits on failure + return TryCommit(requirements, flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + return std::nullopt; +} + +VkMemoryPropertyFlags MemoryAllocator::MemoryPropertyFlags(u32 type_mask, + VkMemoryPropertyFlags flags) const { + if (FindType(flags, type_mask)) { + // Found a memory type with those requirements + return flags; + } + if ((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0) { + // Remove host cached bit in case it's not supported + return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_HOST_CACHED_BIT); + } + if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) { + // Remove device local, if it's not supported by the requested resource + return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + ASSERT_MSG(false, "No compatible memory types found"); + return 0; +} + +std::optional MemoryAllocator::FindType(VkMemoryPropertyFlags flags, u32 type_mask) const { + for (u32 type_index = 0; type_index < properties.memoryTypeCount; ++type_index) { + const VkMemoryPropertyFlags type_flags = properties.memoryTypes[type_index].propertyFlags; + if ((type_mask & (1U << type_index)) != 0 && (type_flags & flags) == flags) { + // The type matches in type and in the wanted properties. + return type_index; + } + } + // Failed to find index + return std::nullopt; +} + } // namespace Vulkan diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.h b/src/video_core/vulkan_common/vulkan_memory_allocator.h index 581f2e66d2..38a182bcba 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.h +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h @@ -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 @@ -9,134 +6,138 @@ #include #include #include - #include "common/common_types.h" #include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_wrapper.h" -#include "video_core/vulkan_common/vma.h" + +VK_DEFINE_HANDLE(VmaAllocator) namespace Vulkan { - class Device; +class Device; +class MemoryMap; +class MemoryAllocation; /// Hints and requirements for the backing memory type of a commit - enum class MemoryUsage { - DeviceLocal, ///< Requests device local host visible buffer, falling back to device local memory. - Upload, ///< Requires a host visible memory type optimized for CPU to GPU uploads - Download, ///< Requires a host visible memory type optimized for GPU to CPU readbacks - Stream, ///< Requests device local host visible buffer, falling back host memory. - }; +enum class MemoryUsage { + DeviceLocal, ///< Requests device local host visible buffer, falling back to device local + ///< memory. + Upload, ///< Requires a host visible memory type optimized for CPU to GPU uploads + Download, ///< Requires a host visible memory type optimized for GPU to CPU readbacks + Stream, ///< Requests device local host visible buffer, falling back host memory. +}; - template - void ForEachDeviceLocalHostVisibleHeap(const Device &device, F &&f) { - auto memory_props = device.GetPhysical().GetMemoryProperties().memoryProperties; - for (size_t i = 0; i < memory_props.memoryTypeCount; i++) { - auto &memory_type = memory_props.memoryTypes[i]; - if ((memory_type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) && - (memory_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { - f(memory_type.heapIndex, memory_props.memoryHeaps[memory_type.heapIndex]); - } +template +void ForEachDeviceLocalHostVisibleHeap(const Device& device, F&& f) { + auto memory_props = device.GetPhysical().GetMemoryProperties().memoryProperties; + for (size_t i = 0; i < memory_props.memoryTypeCount; i++) { + auto& memory_type = memory_props.memoryTypes[i]; + if ((memory_type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) && + (memory_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) { + f(memory_type.heapIndex, memory_props.memoryHeaps[memory_type.heapIndex]); } } +} -/// Ownership handle of a memory commitment (real VMA allocation). - class MemoryCommit { - public: - MemoryCommit() noexcept = default; +/// Ownership handle of a memory commitment. +/// Points to a subregion of a memory allocation. +class MemoryCommit { +public: + explicit MemoryCommit() noexcept = default; + explicit MemoryCommit(MemoryAllocation* allocation_, VkDeviceMemory memory_, u64 begin_, + u64 end_) noexcept; + ~MemoryCommit(); - MemoryCommit(VmaAllocator allocator, VmaAllocation allocation, - const VmaAllocationInfo &info) noexcept; + MemoryCommit& operator=(MemoryCommit&&) noexcept; + MemoryCommit(MemoryCommit&&) noexcept; - ~MemoryCommit(); + MemoryCommit& operator=(const MemoryCommit&) = delete; + MemoryCommit(const MemoryCommit&) = delete; - MemoryCommit(const MemoryCommit &) = delete; + /// Returns a host visible memory map. + /// It will map the backing allocation if it hasn't been mapped before. + std::span Map(); - MemoryCommit &operator=(const MemoryCommit &) = delete; + /// Returns the Vulkan memory handler. + VkDeviceMemory Memory() const { + return memory; + } - MemoryCommit(MemoryCommit &&) noexcept; + /// Returns the start position of the commit relative to the allocation. + VkDeviceSize Offset() const { + return static_cast(begin); + } - MemoryCommit &operator=(MemoryCommit &&) noexcept; +private: + void Release(); - [[nodiscard]] std::span Map(); - - [[nodiscard]] std::span Map() const; - - void Unmap(); - - explicit operator bool() const noexcept { return allocation != nullptr; } - - VkDeviceMemory Memory() const noexcept { return memory; } - - VkDeviceSize Offset() const noexcept { return offset; } - - VkDeviceSize Size() const noexcept { return size; } - - VmaAllocation Allocation() const noexcept { return allocation; } - - private: - void Release(); - - VmaAllocator allocator{}; ///< VMA allocator - VmaAllocation allocation{}; ///< VMA allocation handle - VkDeviceMemory memory{}; ///< Underlying VkDeviceMemory chosen by VMA - VkDeviceSize offset{}; ///< Offset of this allocation inside VkDeviceMemory - VkDeviceSize size{}; ///< Size of the allocation - void *mapped_ptr{}; ///< Optional persistent mapped pointer - }; + MemoryAllocation* allocation{}; ///< Pointer to the large memory allocation. + VkDeviceMemory memory{}; ///< Vulkan device memory handler. + u64 begin{}; ///< Beginning offset in bytes to where the commit exists. + u64 end{}; ///< Offset in bytes where the commit ends. + std::span span; ///< Host visible memory span. Empty if not queried before. +}; /// Memory allocator container. /// Allocates and releases memory allocations on demand. - class MemoryAllocator { - public: - /** - * Construct memory allocator - * - * @param device_ Device to allocate from - * - * @throw vk::Exception on failure - */ - explicit MemoryAllocator(const Device &device_); +class MemoryAllocator { + friend MemoryAllocation; - ~MemoryAllocator(); +public: + /** + * Construct memory allocator + * + * @param device_ Device to allocate from + * + * @throw vk::Exception on failure + */ + explicit MemoryAllocator(const Device& device_); + ~MemoryAllocator(); - MemoryAllocator &operator=(const MemoryAllocator &) = delete; + MemoryAllocator& operator=(const MemoryAllocator&) = delete; + MemoryAllocator(const MemoryAllocator&) = delete; - MemoryAllocator(const MemoryAllocator &) = delete; + vk::Image CreateImage(const VkImageCreateInfo& ci) const; - vk::Image CreateImage(const VkImageCreateInfo &ci) const; + vk::Buffer CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const; - vk::Buffer CreateBuffer(const VkBufferCreateInfo &ci, MemoryUsage usage) const; + /** + * Commits a memory with the specified requirements. + * + * @param requirements Requirements returned from a Vulkan call. + * @param usage Indicates how the memory will be used. + * + * @returns A memory commit. + */ + MemoryCommit Commit(const VkMemoryRequirements& requirements, MemoryUsage usage); - /** - * Commits a memory with the specified requirements. - * - * @param requirements Requirements returned from a Vulkan call. - * @param usage Indicates how the memory will be used. - * - * @returns A memory commit. - */ - MemoryCommit Commit(const VkMemoryRequirements &requirements, MemoryUsage usage); + /// Commits memory required by the buffer and binds it. + MemoryCommit Commit(const vk::Buffer& buffer, MemoryUsage usage); - /// Commits memory required by the buffer and binds it (for buffers created outside VMA). - MemoryCommit Commit(const vk::Buffer &buffer, MemoryUsage usage); +private: + /// Tries to allocate a chunk of memory. + bool TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size); - private: - static bool IsAutoUsage(VmaMemoryUsage u) noexcept { - switch (u) { - case VMA_MEMORY_USAGE_AUTO: - case VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE: - case VMA_MEMORY_USAGE_AUTO_PREFER_HOST: - return true; - default: - return false; - } - } + /// Releases a chunk of memory. + void ReleaseMemory(MemoryAllocation* alloc); - const Device &device; ///< Device handle. - VmaAllocator allocator; ///< VMA allocator. - const VkPhysicalDeviceMemoryProperties properties; ///< Physical device memory properties. - VkDeviceSize buffer_image_granularity; ///< Adjacent buffer/image granularity - u32 valid_memory_types{~0u}; - }; + /// Tries to allocate a memory commit. + std::optional TryCommit(const VkMemoryRequirements& requirements, + VkMemoryPropertyFlags flags); + + /// Returns the fastest compatible memory property flags from the wanted flags. + VkMemoryPropertyFlags MemoryPropertyFlags(u32 type_mask, VkMemoryPropertyFlags flags) const; + + /// Returns index to the fastest memory type compatible with the passed requirements. + std::optional FindType(VkMemoryPropertyFlags flags, u32 type_mask) const; + + const Device& device; ///< Device handle. + VmaAllocator allocator; ///< Vma allocator. + const VkPhysicalDeviceMemoryProperties properties; ///< Physical device properties. + std::vector> allocations; ///< Current allocations. + VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers + // and optimal images + u32 valid_memory_types{~0u}; +}; } // namespace Vulkan diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 949b91499d..106630182f 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -580,7 +580,6 @@ DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) c case VK_SUCCESS: return DescriptorSets(std::move(sets), num, owner, handle, *dld); case VK_ERROR_OUT_OF_POOL_MEMORY: - case VK_ERROR_FRAGMENTED_POOL: return {}; default: throw Exception(result); @@ -605,7 +604,6 @@ CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLev case VK_SUCCESS: return CommandBuffers(std::move(buffers), num_buffers, owner, handle, *dld); case VK_ERROR_OUT_OF_POOL_MEMORY: - case VK_ERROR_FRAGMENTED_POOL: return {}; default: throw Exception(result); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 6501094f05..8fd0bff6af 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -860,7 +860,7 @@ public: /// Set object name. void SetObjectNameEXT(const char* name) const; - VkResult Wait(u64 timeout = (std::numeric_limits::max)()) const noexcept { + VkResult Wait(u64 timeout = std::numeric_limits::max()) const noexcept { return dld->vkWaitForFences(owner, 1, &handle, true, timeout); } @@ -961,7 +961,7 @@ public: * @param timeout Time in nanoseconds to timeout * @return True on successful wait, false on timeout */ - bool Wait(u64 value, u64 timeout = (std::numeric_limits::max)()) const { + bool Wait(u64 value, u64 timeout = std::numeric_limits::max()) const { const VkSemaphoreWaitInfo wait_info{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, .pNext = nullptr, diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 8a1d760c50..0ce8f3b898 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -150,8 +150,12 @@ add_executable(yuzu configuration/configure_web.ui configuration/input_profiles.cpp configuration/input_profiles.h + configuration/shared_translation.cpp + configuration/shared_translation.h configuration/shared_widget.cpp configuration/shared_widget.h + configuration/qt_config.cpp + configuration/qt_config.h debugger/console.cpp debugger/console.h debugger/controller.cpp @@ -201,8 +205,12 @@ add_executable(yuzu play_time_manager.cpp play_time_manager.h precompiled_headers.h + qt_common.cpp + qt_common.h startup_checks.cpp startup_checks.h + uisettings.cpp + uisettings.h util/clickable_label.cpp util/clickable_label.h util/controller_navigation.cpp @@ -248,7 +256,7 @@ if (YUZU_CRASH_DUMPS) target_compile_definitions(yuzu PRIVATE YUZU_CRASH_DUMPS) endif() -if (CXX_CLANG) +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") target_compile_definitions(yuzu PRIVATE $<$,15>:CANNOT_EXPLICITLY_INSTANTIATE> ) @@ -388,17 +396,15 @@ elseif(WIN32) endif() endif() +target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core) target_link_libraries(yuzu PRIVATE nlohmann_json::nlohmann_json) -target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core qt_common) target_link_libraries(yuzu PRIVATE Boost::headers glad Qt6::Widgets) target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) +target_link_libraries(yuzu PRIVATE Vulkan::Headers) 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) @@ -410,24 +416,24 @@ endif() target_compile_definitions(yuzu PRIVATE # Use QStringBuilder for string concatenation to reduce # the overall number of temporary strings created. - QT_USE_QSTRINGBUILDER + -DQT_USE_QSTRINGBUILDER # Disable implicit conversions from/to C strings - QT_NO_CAST_FROM_ASCII - QT_NO_CAST_TO_ASCII + -DQT_NO_CAST_FROM_ASCII + -DQT_NO_CAST_TO_ASCII # Disable implicit type narrowing in signal/slot connect() calls. - QT_NO_NARROWING_CONVERSIONS_IN_CONNECT + -DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT # Disable unsafe overloads of QProcess' start() function. - QT_NO_PROCESS_COMBINED_ARGUMENT_START + -DQT_NO_PROCESS_COMBINED_ARGUMENT_START # Disable implicit QString->QUrl conversions to enforce use of proper resolving functions. - QT_NO_URL_CAST_FROM_STRING + -DQT_NO_URL_CAST_FROM_STRING ) if (YUZU_ENABLE_COMPATIBILITY_REPORTING) - target_compile_definitions(yuzu PRIVATE YUZU_ENABLE_COMPATIBILITY_REPORTING) + target_compile_definitions(yuzu PRIVATE -DYUZU_ENABLE_COMPATIBILITY_REPORTING) endif() if (USE_DISCORD_PRESENCE) @@ -435,22 +441,22 @@ if (USE_DISCORD_PRESENCE) discord_impl.cpp discord_impl.h ) - target_link_libraries(yuzu PRIVATE DiscordRPC::discord-rpc httplib::httplib Qt6::Network) - target_compile_definitions(yuzu PRIVATE USE_DISCORD_PRESENCE) + target_link_libraries(yuzu PRIVATE DiscordRPC::discord-rpc httplib::httplib Qt${QT_MAJOR_VERSION}::Network) + target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE) endif() if (ENABLE_WEB_SERVICE) - target_compile_definitions(yuzu PRIVATE ENABLE_WEB_SERVICE) + target_compile_definitions(yuzu PRIVATE -DENABLE_WEB_SERVICE) endif() if (YUZU_USE_QT_MULTIMEDIA) - target_link_libraries(yuzu PRIVATE Qt6::Multimedia) - target_compile_definitions(yuzu PRIVATE YUZU_USE_QT_MULTIMEDIA) + target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::Multimedia) + target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_MULTIMEDIA) endif () if (YUZU_USE_QT_WEB_ENGINE) - target_link_libraries(yuzu PRIVATE Qt6::WebEngineCore Qt6::WebEngineWidgets) - target_compile_definitions(yuzu PRIVATE YUZU_USE_QT_WEB_ENGINE) + target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::WebEngineCore Qt${QT_MAJOR_VERSION}::WebEngineWidgets) + target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_WEB_ENGINE) endif () if(UNIX AND NOT APPLE) @@ -462,7 +468,6 @@ if (WIN32 AND NOT YUZU_USE_BUNDLED_QT AND QT_VERSION VERSION_GREATER_EQUAL 6) add_custom_command(TARGET yuzu POST_BUILD COMMAND ${WINDEPLOYQT_EXECUTABLE} "${YUZU_EXE_DIR}/eden.exe" --dir "${YUZU_EXE_DIR}" --libdir "${YUZU_EXE_DIR}" --plugindir "${YUZU_EXE_DIR}/plugins" --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --no-translations --verbose 0) endif() -# TODO(crueter): this can be done with system qt in a better way if (YUZU_USE_BUNDLED_QT) include(CopyYuzuQt6Deps) copy_yuzu_Qt6_deps(yuzu) @@ -496,4 +501,8 @@ if (YUZU_ROOM) target_link_libraries(yuzu PRIVATE yuzu-room) endif() +# Extra deps +add_subdirectory(externals) +target_link_libraries(yuzu PRIVATE QuaZip::QuaZip) + create_target_directory_groups(yuzu) diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index c8edb90268..5b6e32149d 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp @@ -11,15 +11,14 @@ 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 compiler = std::string(Common::g_compiler_id); + const auto description = std::string(Common::g_build_version); + const auto build_id = std::string(Common::g_build_id); std::string yuzu_build; if (Common::g_is_dev_build) { - yuzu_build = fmt::format("Eden Nightly | {}-{} | {}", description, build_id, compiler); + yuzu_build = fmt::format("Eden Nightly | {}-{}", description, build_id); } else { - yuzu_build = fmt::format("Eden | {} | {}", description, compiler); + yuzu_build = fmt::format("Eden | {}", description); } const auto override_build = fmt::format(fmt::runtime( diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp index a287ea16df..8245c12ba2 100644 --- a/src/yuzu/applets/qt_web_browser.cpp +++ b/src/yuzu/applets/qt_web_browser.cpp @@ -17,16 +17,15 @@ #include "yuzu/applets/qt_web_browser_scripts.h" #endif -#include "yuzu/applets/qt_web_browser.h" -#include "yuzu/main.h" - -#ifdef YUZU_USE_QT_WEB_ENGINE - #include "common/fs/path_util.h" #include "core/core.h" #include "input_common/drivers/keyboard.h" +#include "yuzu/applets/qt_web_browser.h" +#include "yuzu/main.h" #include "yuzu/util/url_request_interceptor.h" +#ifdef YUZU_USE_QT_WEB_ENGINE + namespace { constexpr int HIDButtonToKey(Core::HID::NpadButton button) { diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index cdc4e4024a..4d58a56a6e 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -12,7 +12,7 @@ #include #include "common/settings_enums.h" -#include "qt_common/uisettings.h" +#include "uisettings.h" #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA #include #include @@ -58,7 +58,7 @@ #include "video_core/renderer_base.h" #include "yuzu/bootmanager.h" #include "yuzu/main.h" -#include "qt_common/qt_common.h" +#include "yuzu/qt_common.h" class QObject; class QPaintEngine; @@ -234,7 +234,7 @@ class DummyContext : public Core::Frontend::GraphicsContext {}; class RenderWidget : public QWidget { public: - explicit RenderWidget(GRenderWindow* parent) : QWidget(parent) { + explicit RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) { setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_PaintOnScreen); if (QtCommon::GetWindowSystemType() == Core::Frontend::WindowSystemType::Wayland) { @@ -247,6 +247,9 @@ public: QPaintEngine* paintEngine() const override { return nullptr; } + +private: + GRenderWindow* render_window; }; struct OpenGLRenderWidget : public RenderWidget { @@ -378,8 +381,8 @@ qreal GRenderWindow::windowPixelRatio() const { std::pair GRenderWindow::ScaleTouch(const QPointF& pos) const { const qreal pixel_ratio = windowPixelRatio(); - return {static_cast((std::max)(std::round(pos.x() * pixel_ratio), qreal{0.0})), - static_cast((std::max)(std::round(pos.y() * pixel_ratio), qreal{0.0}))}; + return {static_cast(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})), + static_cast(std::max(std::round(pos.y() * pixel_ratio), qreal{0.0}))}; } void GRenderWindow::closeEvent(QCloseEvent* event) { diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index a7ebae91f8..c235b0fca4 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -19,9 +16,9 @@ #include "ui_configure_audio.h" #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_audio.h" -#include "qt_common/shared_translation.h" +#include "yuzu/configuration/shared_translation.h" #include "yuzu/configuration/shared_widget.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" ConfigureAudio::ConfigureAudio(const Core::System& system_, std::shared_ptr> group_, diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index bbc6096f9b..098e0e397b 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.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 @@ -10,7 +7,7 @@ #include #include #include "yuzu/configuration/configuration_shared.h" -#include "qt_common/shared_translation.h" +#include "yuzu/configuration/shared_translation.h" class QComboBox; diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 18f629f639..733c419c4b 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -15,7 +15,7 @@ #include "ui_configure_debug.h" #include "yuzu/configuration/configure_debug.h" #include "yuzu/debugger/console.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent) : QScrollArea(parent), ui{std::make_unique()}, system{system_} { diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 0816782282..987b1462db 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +27,7 @@ #include "yuzu/configuration/configure_ui.h" #include "yuzu/configuration/configure_web.h" #include "yuzu/hotkeys.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, InputCommon::InputSubsystem* input_subsystem, diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index c1e148fc8e..0b6b285678 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,7 +8,7 @@ #include #include "configuration/shared_widget.h" #include "yuzu/configuration/configuration_shared.h" -#include "qt_common/shared_translation.h" +#include "yuzu/configuration/shared_translation.h" #include "yuzu/vk_device_info.h" namespace Core { diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp index d461bd2cc9..f25f14708b 100644 --- a/src/yuzu/configuration/configure_filesystem.cpp +++ b/src/yuzu/configuration/configure_filesystem.cpp @@ -1,19 +1,14 @@ -// 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 -#include "yuzu/configuration/configure_filesystem.h" #include #include #include "common/fs/fs.h" #include "common/fs/path_util.h" #include "common/settings.h" -#include "qt_common/qt_common.h" -#include "qt_common/qt_game_util.h" -#include "qt_common/uisettings.h" #include "ui_configure_filesystem.h" +#include "yuzu/configuration/configure_filesystem.h" +#include "yuzu/uisettings.h" ConfigureFilesystem::ConfigureFilesystem(QWidget* parent) : QWidget(parent), ui(std::make_unique()) { @@ -131,7 +126,20 @@ void ConfigureFilesystem::SetDirectory(DirectoryTarget target, QLineEdit* edit) } void ConfigureFilesystem::ResetMetadata() { - QtCommon::Game::ResetMetadata(); + if (!Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / + "game_list/")) { + QMessageBox::information(this, tr("Reset Metadata Cache"), + tr("The metadata cache is already empty.")); + } else if (Common::FS::RemoveDirRecursively( + Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list")) { + QMessageBox::information(this, tr("Reset Metadata Cache"), + tr("The operation completed successfully.")); + UISettings::values.is_game_list_reload_pending.exchange(true); + } else { + QMessageBox::warning( + this, tr("Reset Metadata Cache"), + tr("The metadata cache couldn't be deleted. It might be in use or non-existent.")); + } } void ConfigureFilesystem::UpdateEnabledControls() { diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 18c2c9cb77..918fa15d4d 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -14,7 +11,7 @@ #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_general.h" #include "yuzu/configuration/shared_widget.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" ConfigureGeneral::ConfigureGeneral(const Core::System& system_, std::shared_ptr> group_, diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index cd806e5ef8..16846878f9 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -43,8 +40,8 @@ #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_graphics.h" #include "yuzu/configuration/shared_widget.h" -#include "qt_common/qt_common.h" -#include "qt_common/uisettings.h" +#include "yuzu/qt_common.h" +#include "yuzu/uisettings.h" #include "yuzu/vk_device_info.h" static const std::vector default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR, diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index 38d97aae80..b92b4496ba 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,7 +15,7 @@ #include #include "common/common_types.h" #include "common/settings_enums.h" -#include "qt_common/shared_translation.h" +#include "configuration/shared_translation.h" #include "vk_device_info.h" #include "yuzu/configuration/configuration_shared.h" diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index e07ad8c466..4db18673d4 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp @@ -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 @@ -12,7 +9,7 @@ #include "ui_configure_graphics_advanced.h" #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_graphics_advanced.h" -#include "qt_common/shared_translation.h" +#include "yuzu/configuration/shared_translation.h" #include "yuzu/configuration/shared_widget.h" ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced( diff --git a/src/yuzu/configuration/configure_graphics_extensions.cpp b/src/yuzu/configuration/configure_graphics_extensions.cpp index f165e703d9..c8dee6b073 100644 --- a/src/yuzu/configuration/configure_graphics_extensions.cpp +++ b/src/yuzu/configuration/configure_graphics_extensions.cpp @@ -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 @@ -14,7 +11,7 @@ #include "ui_configure_graphics_extensions.h" #include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configure_graphics_extensions.h" -#include "qt_common/shared_translation.h" +#include "yuzu/configuration/shared_translation.h" #include "yuzu/configuration/shared_widget.h" ConfigureGraphicsExtensions::ConfigureGraphicsExtensions( @@ -63,10 +60,6 @@ void ConfigureGraphicsExtensions::Setup(const ConfigurationShared::Builder& buil if (setting->Id() == Settings::values.dyna_state.Id()) { widget->slider->setTickInterval(1); widget->slider->setTickPosition(QSlider::TicksAbove); -#ifdef __APPLE__ - widget->setEnabled(false); - widget->setToolTip(tr("Extended Dynamic State is disabled on macOS due to MoltenVK compatibility issues that cause black screens.")); -#endif } } diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index a5c1ee009a..3f68de12d8 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2017 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -16,7 +13,7 @@ #include "ui_configure_hotkeys.h" #include "yuzu/configuration/configure_hotkeys.h" #include "yuzu/hotkeys.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #include "yuzu/util/sequence_dialog/sequence_dialog.h" constexpr int name_column = 0; diff --git a/src/yuzu/configuration/configure_input_per_game.h b/src/yuzu/configuration/configure_input_per_game.h index dcd6dd841b..4420e856cb 100644 --- a/src/yuzu/configuration/configure_input_per_game.h +++ b/src/yuzu/configuration/configure_input_per_game.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 @@ -12,7 +9,7 @@ #include "ui_configure_input_per_game.h" #include "yuzu/configuration/input_profiles.h" -#include "qt_common/qt_config.h" +#include "yuzu/configuration/qt_config.h" class QComboBox; diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 6afa8320a2..d0dc0ff44c 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -14,7 +14,7 @@ #include #include "common/assert.h" #include "common/param_package.h" -#include "qt_common/qt_config.h" +#include "configuration/qt_config.h" #include "hid_core/frontend/emulated_controller.h" #include "hid_core/hid_core.h" #include "hid_core/hid_types.h" diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index b51ede0de8..031a8d4c2d 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp @@ -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 @@ -41,7 +38,7 @@ #include "yuzu/configuration/configure_per_game.h" #include "yuzu/configuration/configure_per_game_addons.h" #include "yuzu/configuration/configure_system.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #include "yuzu/util/util.h" #include "yuzu/vk_device_info.h" diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index 83afc27f3d..e0f4e5cd67 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.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 @@ -18,8 +15,8 @@ #include "frontend_common/config.h" #include "vk_device_info.h" #include "yuzu/configuration/configuration_shared.h" -#include "qt_common/qt_config.h" -#include "qt_common/shared_translation.h" +#include "yuzu/configuration/qt_config.h" +#include "yuzu/configuration/shared_translation.h" namespace Core { class System; diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index ed4cbc1147..078f2e8288 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -24,7 +21,7 @@ #include "ui_configure_per_game_addons.h" #include "yuzu/configuration/configure_input.h" #include "yuzu/configuration/configure_per_game_addons.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* parent) : QWidget(parent), ui{std::make_unique()}, system{system_} { diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp index 795ad1a85e..f7249be97e 100644 --- a/src/yuzu/configuration/configure_ringcon.cpp +++ b/src/yuzu/configuration/configure_ringcon.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 @@ -11,7 +8,7 @@ #include #include -#include "qt_common/qt_config.h" +#include "configuration/qt_config.h" #include "hid_core/frontend/emulated_controller.h" #include "hid_core/hid_core.h" #include "input_common/drivers/keyboard.h" diff --git a/src/yuzu/configuration/configure_tas.cpp b/src/yuzu/configuration/configure_tas.cpp index 898a1a3e59..773658bf22 100644 --- a/src/yuzu/configuration/configure_tas.cpp +++ b/src/yuzu/configuration/configure_tas.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -11,7 +8,7 @@ #include "common/settings.h" #include "ui_configure_tas.h" #include "yuzu/configuration/configure_tas.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" ConfigureTasDialog::ConfigureTasDialog(QWidget* parent) : QDialog(parent), ui(std::make_unique()) { diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp index 2a4ae3bc89..a6237ab72f 100644 --- a/src/yuzu/configuration/configure_touch_from_button.cpp +++ b/src/yuzu/configuration/configure_touch_from_button.cpp @@ -484,8 +484,8 @@ void TouchScreenPreview::resizeEvent(QResizeEvent* event) { return; } - const int target_width = (std::min)(width(), height() * 4 / 3); - const int target_height = (std::min)(height(), width() * 3 / 4); + const int target_width = std::min(width(), height() * 4 / 3); + const int target_height = std::min(height(), width() * 3 / 4); if (target_width == width() && target_height == height()) { return; } diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index ac6d6e34aa..8dafee628b 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -27,7 +27,7 @@ #include "core/core.h" #include "core/frontend/framebuffer_layout.h" #include "ui_configure_ui.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" namespace { constexpr std::array default_game_icon_sizes{ diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp index 15a0029901..d62b5b0853 100644 --- a/src/yuzu/configuration/configure_web.cpp +++ b/src/yuzu/configuration/configure_web.cpp @@ -17,7 +17,7 @@ #include #include "common/settings.h" #include "ui_configure_web.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" ConfigureWeb::ConfigureWeb(QWidget* parent) : QWidget(parent) diff --git a/src/yuzu/configuration/input_profiles.h b/src/yuzu/configuration/input_profiles.h index dba5ce1318..023ec74a63 100644 --- a/src/yuzu/configuration/input_profiles.h +++ b/src/yuzu/configuration/input_profiles.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 @@ -9,7 +6,7 @@ #include #include -#include "qt_common/qt_config.h" +#include "configuration/qt_config.h" namespace Core { class System; diff --git a/src/qt_common/qt_config.cpp b/src/yuzu/configuration/qt_config.cpp similarity index 99% rename from src/qt_common/qt_config.cpp rename to src/yuzu/configuration/qt_config.cpp index f787873cf6..ae5b330e23 100644 --- a/src/qt_common/qt_config.cpp +++ b/src/yuzu/configuration/qt_config.cpp @@ -1,6 +1,3 @@ -// 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 diff --git a/src/qt_common/qt_config.h b/src/yuzu/configuration/qt_config.h similarity index 94% rename from src/qt_common/qt_config.h rename to src/yuzu/configuration/qt_config.h index a8c80dd273..dc2dceb4d7 100644 --- a/src/qt_common/qt_config.h +++ b/src/yuzu/configuration/qt_config.h @@ -1,6 +1,3 @@ -// 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 diff --git a/src/qt_common/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp similarity index 90% rename from src/qt_common/shared_translation.cpp rename to src/yuzu/configuration/shared_translation.cpp index cdc05e60e0..fca4c94893 100644 --- a/src/qt_common/shared_translation.cpp +++ b/src/yuzu/configuration/shared_translation.cpp @@ -7,21 +7,23 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "shared_translation.h" +#include "yuzu/configuration/shared_translation.h" #include +#include #include "common/settings.h" #include "common/settings_enums.h" #include "common/settings_setting.h" #include "common/time_zone.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #include #include +#include #include namespace ConfigurationShared { -std::unique_ptr InitializeTranslations(QObject* parent) +std::unique_ptr InitializeTranslations(QWidget* parent) { std::unique_ptr translations = std::make_unique(); const auto& tr = [parent](const char* text) -> QString { return parent->tr(text); }; @@ -288,14 +290,16 @@ std::unique_ptr InitializeTranslations(QObject* parent) "and safe to set at 16x on most GPUs.")); INSERT(Settings, gpu_accuracy, - tr("GPU Accuracy:"), + tr("GPU Level:"), tr("Controls the GPU emulation accuracy.\nMost games render fine with Normal, but High is still " "required for some.\nParticles tend to only render correctly with High " - "accuracy.\nExtreme should only be used as a last resort.")); + "accuracy.\nExtreme should only be used for debugging.\nThis option can " + "be changed while playing.\nSome games may require booting on high to render " + "properly.")); INSERT(Settings, dma_accuracy, - tr("DMA Accuracy:"), - 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.")); + tr("DMA Level:"), + tr("Controls the DMA precision accuracy. Higher precision can fix issues in some games, but it can also impact performance in some cases.\nIf unsure, leave it at Default.")); INSERT(Settings, use_asynchronous_shaders, tr("Use asynchronous shader building (Hack)"), @@ -463,7 +467,7 @@ std::unique_ptr InitializeTranslations(QObject* parent) return translations; } -std::unique_ptr ComboboxEnumeration(QObject* parent) +std::unique_ptr ComboboxEnumeration(QWidget* parent) { std::unique_ptr translations = std::make_unique(); const auto& tr = [&](const char* text, const char* context = "") { @@ -527,8 +531,9 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) translations->insert({Settings::EnumMetadata::Index(), { PAIR(DmaAccuracy, Default, tr("Default")), - PAIR(DmaAccuracy, Unsafe, tr("Unsafe (fast)")), - PAIR(DmaAccuracy, Safe, tr("Safe (stable)")), + PAIR(DmaAccuracy, Normal, tr("Normal")), + PAIR(DmaAccuracy, High, tr("High")), + PAIR(DmaAccuracy, Extreme, tr("Extreme")), }}); translations->insert( {Settings::EnumMetadata::Index(), @@ -639,58 +644,58 @@ std::unique_ptr ComboboxEnumeration(QObject* parent) translations->insert( {Settings::EnumMetadata::Index(), { - {static_cast(Settings::TimeZone::Auto), - tr("Auto (%1)", "Auto select time zone") - .arg(QString::fromStdString( - Settings::GetTimeZoneString(Settings::TimeZone::Auto)))}, - {static_cast(Settings::TimeZone::Default), - tr("Default (%1)", "Default time zone") - .arg(QString::fromStdString(Common::TimeZone::GetDefaultTimeZone()))}, - PAIR(TimeZone, Cet, tr("CET")), - PAIR(TimeZone, Cst6Cdt, tr("CST6CDT")), - PAIR(TimeZone, Cuba, tr("Cuba")), - PAIR(TimeZone, Eet, tr("EET")), - PAIR(TimeZone, Egypt, tr("Egypt")), - PAIR(TimeZone, Eire, tr("Eire")), - PAIR(TimeZone, Est, tr("EST")), - PAIR(TimeZone, Est5Edt, tr("EST5EDT")), - PAIR(TimeZone, Gb, tr("GB")), - PAIR(TimeZone, GbEire, tr("GB-Eire")), - PAIR(TimeZone, Gmt, tr("GMT")), - PAIR(TimeZone, GmtPlusZero, tr("GMT+0")), - PAIR(TimeZone, GmtMinusZero, tr("GMT-0")), - PAIR(TimeZone, GmtZero, tr("GMT0")), - PAIR(TimeZone, Greenwich, tr("Greenwich")), - PAIR(TimeZone, Hongkong, tr("Hongkong")), - PAIR(TimeZone, Hst, tr("HST")), - PAIR(TimeZone, Iceland, tr("Iceland")), - PAIR(TimeZone, Iran, tr("Iran")), - PAIR(TimeZone, Israel, tr("Israel")), - PAIR(TimeZone, Jamaica, tr("Jamaica")), - PAIR(TimeZone, Japan, tr("Japan")), - PAIR(TimeZone, Kwajalein, tr("Kwajalein")), - PAIR(TimeZone, Libya, tr("Libya")), - PAIR(TimeZone, Met, tr("MET")), - PAIR(TimeZone, Mst, tr("MST")), - PAIR(TimeZone, Mst7Mdt, tr("MST7MDT")), - PAIR(TimeZone, Navajo, tr("Navajo")), - PAIR(TimeZone, Nz, tr("NZ")), - PAIR(TimeZone, NzChat, tr("NZ-CHAT")), - PAIR(TimeZone, Poland, tr("Poland")), - PAIR(TimeZone, Portugal, tr("Portugal")), - PAIR(TimeZone, Prc, tr("PRC")), - PAIR(TimeZone, Pst8Pdt, tr("PST8PDT")), - PAIR(TimeZone, Roc, tr("ROC")), - PAIR(TimeZone, Rok, tr("ROK")), - PAIR(TimeZone, Singapore, tr("Singapore")), - PAIR(TimeZone, Turkey, tr("Turkey")), - PAIR(TimeZone, Uct, tr("UCT")), - PAIR(TimeZone, Universal, tr("Universal")), - PAIR(TimeZone, Utc, tr("UTC")), - PAIR(TimeZone, WSu, tr("W-SU")), - PAIR(TimeZone, Wet, tr("WET")), - PAIR(TimeZone, Zulu, tr("Zulu")), - }}); + {static_cast(Settings::TimeZone::Auto), + tr("Auto (%1)", "Auto select time zone") + .arg(QString::fromStdString( + Settings::GetTimeZoneString(Settings::TimeZone::Auto)))}, + {static_cast(Settings::TimeZone::Default), + tr("Default (%1)", "Default time zone") + .arg(QString::fromStdString(Common::TimeZone::GetDefaultTimeZone()))}, + PAIR(TimeZone, Cet, tr("CET")), + PAIR(TimeZone, Cst6Cdt, tr("CST6CDT")), + PAIR(TimeZone, Cuba, tr("Cuba")), + PAIR(TimeZone, Eet, tr("EET")), + PAIR(TimeZone, Egypt, tr("Egypt")), + PAIR(TimeZone, Eire, tr("Eire")), + PAIR(TimeZone, Est, tr("EST")), + PAIR(TimeZone, Est5Edt, tr("EST5EDT")), + PAIR(TimeZone, Gb, tr("GB")), + PAIR(TimeZone, GbEire, tr("GB-Eire")), + PAIR(TimeZone, Gmt, tr("GMT")), + PAIR(TimeZone, GmtPlusZero, tr("GMT+0")), + PAIR(TimeZone, GmtMinusZero, tr("GMT-0")), + PAIR(TimeZone, GmtZero, tr("GMT0")), + PAIR(TimeZone, Greenwich, tr("Greenwich")), + PAIR(TimeZone, Hongkong, tr("Hongkong")), + PAIR(TimeZone, Hst, tr("HST")), + PAIR(TimeZone, Iceland, tr("Iceland")), + PAIR(TimeZone, Iran, tr("Iran")), + PAIR(TimeZone, Israel, tr("Israel")), + PAIR(TimeZone, Jamaica, tr("Jamaica")), + PAIR(TimeZone, Japan, tr("Japan")), + PAIR(TimeZone, Kwajalein, tr("Kwajalein")), + PAIR(TimeZone, Libya, tr("Libya")), + PAIR(TimeZone, Met, tr("MET")), + PAIR(TimeZone, Mst, tr("MST")), + PAIR(TimeZone, Mst7Mdt, tr("MST7MDT")), + PAIR(TimeZone, Navajo, tr("Navajo")), + PAIR(TimeZone, Nz, tr("NZ")), + PAIR(TimeZone, NzChat, tr("NZ-CHAT")), + PAIR(TimeZone, Poland, tr("Poland")), + PAIR(TimeZone, Portugal, tr("Portugal")), + PAIR(TimeZone, Prc, tr("PRC")), + PAIR(TimeZone, Pst8Pdt, tr("PST8PDT")), + PAIR(TimeZone, Roc, tr("ROC")), + PAIR(TimeZone, Rok, tr("ROK")), + PAIR(TimeZone, Singapore, tr("Singapore")), + PAIR(TimeZone, Turkey, tr("Turkey")), + PAIR(TimeZone, Uct, tr("UCT")), + PAIR(TimeZone, Universal, tr("Universal")), + PAIR(TimeZone, Utc, tr("UTC")), + PAIR(TimeZone, WSu, tr("W-SU")), + PAIR(TimeZone, Wet, tr("WET")), + PAIR(TimeZone, Zulu, tr("Zulu")), + }}); translations->insert({Settings::EnumMetadata::Index(), { PAIR(AudioMode, Mono, tr("Mono")), diff --git a/src/qt_common/shared_translation.h b/src/yuzu/configuration/shared_translation.h similarity index 94% rename from src/qt_common/shared_translation.h rename to src/yuzu/configuration/shared_translation.h index 48a2cb5205..574b1e2c78 100644 --- a/src/qt_common/shared_translation.h +++ b/src/yuzu/configuration/shared_translation.h @@ -11,20 +11,23 @@ #include #include +#include #include #include #include #include "common/common_types.h" -#include "common/settings_enums.h" +#include "common/settings.h" + +class QWidget; namespace ConfigurationShared { using TranslationMap = std::map>; using ComboboxTranslations = std::vector>; using ComboboxTranslationMap = std::map; -std::unique_ptr InitializeTranslations(QObject *parent); +std::unique_ptr InitializeTranslations(QWidget* parent); -std::unique_ptr ComboboxEnumeration(QObject* parent); +std::unique_ptr ComboboxEnumeration(QWidget* parent); static const std::map anti_aliasing_texts_map = { {Settings::AntiAliasing::None, QStringLiteral(QT_TRANSLATE_NOOP("GMainWindow", "None"))}, diff --git a/src/yuzu/configuration/shared_widget.cpp b/src/yuzu/configuration/shared_widget.cpp index e30ecc4848..e23d86dc69 100644 --- a/src/yuzu/configuration/shared_widget.cpp +++ b/src/yuzu/configuration/shared_widget.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 @@ -45,7 +42,7 @@ #include "common/logging/log.h" #include "common/settings.h" #include "common/settings_common.h" -#include "qt_common/shared_translation.h" +#include "yuzu/configuration/shared_translation.h" namespace ConfigurationShared { diff --git a/src/yuzu/configuration/shared_widget.h b/src/yuzu/configuration/shared_widget.h index 9e718098a3..5c67d83542 100644 --- a/src/yuzu/configuration/shared_widget.h +++ b/src/yuzu/configuration/shared_widget.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 @@ -14,7 +11,7 @@ #include #include #include -#include "qt_common/shared_translation.h" +#include "yuzu/configuration/shared_translation.h" class QCheckBox; class QComboBox; diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp index 8fb22db192..1c1342ff18 100644 --- a/src/yuzu/debugger/console.cpp +++ b/src/yuzu/debugger/console.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -12,7 +9,7 @@ #include "common/logging/backend.h" #include "yuzu/debugger/console.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" namespace Debugger { void ToggleConsole() { diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index feb814b25e..9f9e21bc28 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -8,7 +5,7 @@ #include #include "yuzu/debugger/wait_tree.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #include "core/arm/debug.h" #include "core/core.h" diff --git a/src/qt_common/externals/CMakeLists.txt b/src/yuzu/externals/CMakeLists.txt similarity index 73% rename from src/qt_common/externals/CMakeLists.txt rename to src/yuzu/externals/CMakeLists.txt index 189a52c0a6..7de41f6dfd 100644 --- a/src/qt_common/externals/CMakeLists.txt +++ b/src/yuzu/externals/CMakeLists.txt @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later +# Explicitly include CPMUtil here since we have a separate cpmfile for Qt externals +set(CPMUTIL_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cpmfile.json) include(CPMUtil) # Disable tests/tools in all externals supporting the standard option name @@ -14,7 +16,3 @@ set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON) # QuaZip AddJsonPackage(quazip) - -# frozen -# TODO(crueter): Qt String Lookup -AddJsonPackage(frozen) diff --git a/src/qt_common/externals/cpmfile.json b/src/yuzu/externals/cpmfile.json similarity index 55% rename from src/qt_common/externals/cpmfile.json rename to src/yuzu/externals/cpmfile.json index 0b464b95b2..e3590d0f7f 100644 --- a/src/qt_common/externals/cpmfile.json +++ b/src/yuzu/externals/cpmfile.json @@ -8,12 +8,5 @@ "options": [ "QUAZIP_INSTALL OFF" ] - }, - "frozen": { - "package": "frozen", - "repo": "serge-sans-paille/frozen", - "sha": "61dce5ae18", - "hash": "1ae3d073e659c1f24b2cdd76379c90d6af9e06bc707d285a4fafce05f7a4c9e592ff208c94a9ae0f0d07620b3c6cec191f126b03d70ad4dfa496a86ed5658a6d", - "bundled": true } } diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index fa61cdfb1f..80dd90d876 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include "yuzu/game_list.h" +#include #include #include #include @@ -13,20 +13,19 @@ #include #include #include +#include #include "common/common_types.h" #include "common/logging/log.h" #include "core/core.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/registered_cache.h" -#include "qt_common/qt_game_util.h" -#include "qt_common/uisettings.h" #include "yuzu/compatibility_list.h" +#include "yuzu/game_list.h" #include "yuzu/game_list_p.h" #include "yuzu/game_list_worker.h" #include "yuzu/main.h" +#include "yuzu/uisettings.h" #include "yuzu/util/controller_navigation.h" -#include -#include GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist_, QObject* parent) : QObject(parent), gamelist{gamelist_} {} @@ -491,7 +490,7 @@ void GameList::DonePopulating(const QStringList& watch_list) { // Also artificially caps the watcher to a certain number of directories constexpr int LIMIT_WATCH_DIRECTORIES = 5000; constexpr int SLICE_SIZE = 25; - int len = (std::min)(static_cast(watch_list.size()), LIMIT_WATCH_DIRECTORIES); + int len = std::min(static_cast(watch_list.size()), LIMIT_WATCH_DIRECTORIES); for (int i = 0; i < len; i += SLICE_SIZE) { watcher->addPaths(watch_list.mid(i, i + SLICE_SIZE)); QCoreApplication::processEvents(); @@ -609,30 +608,30 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri connect(open_transferable_shader_cache, &QAction::triggered, [this, program_id]() { emit OpenTransferableShaderCacheRequested(program_id); }); connect(remove_all_content, &QAction::triggered, [this, program_id]() { - emit RemoveInstalledEntryRequested(program_id, QtCommon::Game::InstalledEntryType::Game); + emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::Game); }); connect(remove_update, &QAction::triggered, [this, program_id]() { - emit RemoveInstalledEntryRequested(program_id, QtCommon::Game::InstalledEntryType::Update); + emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::Update); }); connect(remove_dlc, &QAction::triggered, [this, program_id]() { - emit RemoveInstalledEntryRequested(program_id, QtCommon::Game::InstalledEntryType::AddOnContent); + emit RemoveInstalledEntryRequested(program_id, InstalledEntryType::AddOnContent); }); connect(remove_gl_shader_cache, &QAction::triggered, [this, program_id, path]() { - emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::GlShaderCache, path); + emit RemoveFileRequested(program_id, GameListRemoveTarget::GlShaderCache, path); }); connect(remove_vk_shader_cache, &QAction::triggered, [this, program_id, path]() { - emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::VkShaderCache, path); + emit RemoveFileRequested(program_id, GameListRemoveTarget::VkShaderCache, path); }); connect(remove_shader_cache, &QAction::triggered, [this, program_id, path]() { - emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::AllShaderCache, path); + emit RemoveFileRequested(program_id, GameListRemoveTarget::AllShaderCache, path); }); connect(remove_custom_config, &QAction::triggered, [this, program_id, path]() { - emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::CustomConfiguration, path); + emit RemoveFileRequested(program_id, GameListRemoveTarget::CustomConfiguration, path); }); connect(remove_play_time_data, &QAction::triggered, [this, program_id]() { emit RemovePlayTimeRequested(program_id); }); connect(remove_cache_storage, &QAction::triggered, [this, program_id, path] { - emit RemoveFileRequested(program_id, QtCommon::Game::GameListRemoveTarget::CacheStorage, path); + emit RemoveFileRequested(program_id, GameListRemoveTarget::CacheStorage, path); }); connect(dump_romfs, &QAction::triggered, [this, program_id, path]() { emit DumpRomFSRequested(program_id, path, DumpRomFSTarget::Normal); @@ -650,10 +649,10 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri // TODO: Implement shortcut creation for macOS #if !defined(__APPLE__) connect(create_desktop_shortcut, &QAction::triggered, [this, program_id, path]() { - emit CreateShortcut(program_id, path, QtCommon::Game::ShortcutTarget::Desktop); + emit CreateShortcut(program_id, path, GameListShortcutTarget::Desktop); }); connect(create_applications_menu_shortcut, &QAction::triggered, [this, program_id, path]() { - emit CreateShortcut(program_id, path, QtCommon::Game::ShortcutTarget::Applications); + emit CreateShortcut(program_id, path, GameListShortcutTarget::Applications); }); #endif connect(properties, &QAction::triggered, @@ -821,7 +820,7 @@ QStandardItemModel* GameList::GetModel() const { return item_model; } -void GameList::PopulateAsync(QVector& game_dirs) +void GameList::PopulateAsync(QVector& game_dirs, const bool cached) { tree_view->setEnabled(false); @@ -844,7 +843,8 @@ void GameList::PopulateAsync(QVector& game_dirs) game_dirs, compatibility_list, play_time_manager, - system); + system, + cached); // Get events from the worker as data becomes available connect(current_worker.get(), &GameListWorker::DataAvailable, this, &GameList::WorkerEvent, @@ -873,6 +873,14 @@ const QStringList GameList::supported_file_extensions = { QStringLiteral("nso"), QStringLiteral("nro"), QStringLiteral("nca"), QStringLiteral("xci"), QStringLiteral("nsp"), QStringLiteral("kip")}; +void GameList::ForceRefreshGameDirectory() +{ + if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) { + LOG_INFO(Frontend, "Force-reloading game list per user request."); + PopulateAsync(UISettings::values.game_dirs, false); + } +} + void GameList::RefreshGameDirectory() { if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) { diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index 94e7b2dc42..7c492bc19f 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -20,8 +20,7 @@ #include "common/common_types.h" #include "core/core.h" -#include "qt_common/uisettings.h" -#include "qt_common/qt_game_util.h" +#include "uisettings.h" #include "yuzu/compatibility_list.h" #include "yuzu/play_time_manager.h" @@ -47,11 +46,30 @@ enum class GameListOpenTarget { ModData, }; +enum class GameListRemoveTarget { + GlShaderCache, + VkShaderCache, + AllShaderCache, + CustomConfiguration, + CacheStorage, +}; + enum class DumpRomFSTarget { Normal, SDMC, }; +enum class GameListShortcutTarget { + Desktop, + Applications, +}; + +enum class InstalledEntryType { + Game, + Update, + AddOnContent, +}; + class GameList : public QWidget { Q_OBJECT @@ -79,7 +97,7 @@ public: bool IsEmpty() const; void LoadCompatibilityList(); - void PopulateAsync(QVector& game_dirs); + void PopulateAsync(QVector& game_dirs, const bool cached = true); void SaveInterfaceLayout(); void LoadInterfaceLayout(); @@ -92,6 +110,7 @@ public: static const QStringList supported_file_extensions; public slots: + void ForceRefreshGameDirectory(); void RefreshGameDirectory(); signals: @@ -100,15 +119,15 @@ signals: void OpenFolderRequested(u64 program_id, GameListOpenTarget target, const std::string& game_path); void OpenTransferableShaderCacheRequested(u64 program_id); - void RemoveInstalledEntryRequested(u64 program_id, QtCommon::Game::InstalledEntryType type); - void RemoveFileRequested(u64 program_id, QtCommon::Game::GameListRemoveTarget target, + void RemoveInstalledEntryRequested(u64 program_id, InstalledEntryType type); + void RemoveFileRequested(u64 program_id, GameListRemoveTarget target, const std::string& game_path); void RemovePlayTimeRequested(u64 program_id); void DumpRomFSRequested(u64 program_id, const std::string& game_path, DumpRomFSTarget target); void VerifyIntegrityRequested(const std::string& game_path); void CopyTIDRequested(u64 program_id); void CreateShortcut(u64 program_id, const std::string& game_path, - const QtCommon::Game::ShortcutTarget target); + GameListShortcutTarget target); void NavigateToGamedbEntryRequested(u64 program_id, const CompatibilityList& compatibility_list); void OpenPerGameGeneralRequested(const std::string& file); diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index 5a3b5829f5..c330b574f9 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: 2015 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,7 +19,7 @@ #include "common/logging/log.h" #include "common/string_util.h" #include "yuzu/play_time_manager.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #include "yuzu/util/util.h" enum class GameListItemType { diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 538c7ab822..60109769bf 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,7 +27,7 @@ #include "yuzu/game_list.h" #include "yuzu/game_list_p.h" #include "yuzu/game_list_worker.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" namespace { @@ -202,7 +199,8 @@ QList MakeGameListEntry(const std::string& path, u64 program_id, const CompatibilityList& compatibility_list, const PlayTime::PlayTimeManager& play_time_manager, - const FileSys::PatchManager& patch) + const FileSys::PatchManager& patch, + const bool cached) { const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id); @@ -226,10 +224,14 @@ QList MakeGameListEntry(const std::string& path, QString patch_versions; - patch_versions = GetGameListCachedObject( - fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] { - return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()); - }); + if (cached) { + patch_versions = GetGameListCachedObject( + fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] { + return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()); + }); + } else { + patch_versions = FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable()); + } list.insert(2, new GameListItem(patch_versions)); @@ -242,13 +244,15 @@ GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs_, QVector& game_dirs_, const CompatibilityList& compatibility_list_, const PlayTime::PlayTimeManager& play_time_manager_, - Core::System& system_) + Core::System& system_, + const bool cached_) : vfs{std::move(vfs_)} , provider{provider_} , game_dirs{game_dirs_} , compatibility_list{compatibility_list_} , play_time_manager{play_time_manager_} , system{system_} + , cached{cached_} { // We want the game list to manage our lifetime. setAutoDelete(false); @@ -351,7 +355,8 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { program_id, compatibility_list, play_time_manager, - patch); + patch, + cached); RecordEvent([=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); }); } } @@ -434,7 +439,8 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa id, compatibility_list, play_time_manager, - patch); + patch, + cached); RecordEvent( [=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); }); @@ -457,7 +463,8 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa program_id, compatibility_list, play_time_manager, - patch); + patch, + cached); RecordEvent( [=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); }); diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h index f5d5f6341b..0afd7c7849 100644 --- a/src/yuzu/game_list_worker.h +++ b/src/yuzu/game_list_worker.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -18,7 +15,7 @@ #include "common/thread.h" #include "core/file_sys/registered_cache.h" -#include "qt_common/uisettings.h" +#include "uisettings.h" #include "yuzu/compatibility_list.h" #include "yuzu/play_time_manager.h" @@ -48,7 +45,8 @@ public: QVector& game_dirs_, const CompatibilityList& compatibility_list_, const PlayTime::PlayTimeManager& play_time_manager_, - Core::System& system_); + Core::System& system_, + const bool cached = true); ~GameListWorker() override; /// Starts the processing of directory tree information. @@ -97,4 +95,6 @@ private: Common::Event processing_completed; Core::System& system; + + const bool cached; }; diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp index 31932e6f43..1931dcd1f6 100644 --- a/src/yuzu/hotkeys.cpp +++ b/src/yuzu/hotkeys.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 @@ -11,7 +8,7 @@ #include "hid_core/frontend/emulated_controller.h" #include "yuzu/hotkeys.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" HotkeyRegistry::HotkeyRegistry() = default; HotkeyRegistry::~HotkeyRegistry() = default; diff --git a/src/yuzu/install_dialog.cpp b/src/yuzu/install_dialog.cpp index e6f1392ce0..673bbaa836 100644 --- a/src/yuzu/install_dialog.cpp +++ b/src/yuzu/install_dialog.cpp @@ -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 @@ -11,7 +8,7 @@ #include #include #include "yuzu/install_dialog.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" InstallDialog::InstallDialog(QWidget* parent, const QStringList& files) : QDialog(parent) { file_list = new QListWidget(this); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d7d4e94ab7..4c6b176c56 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1,19 +1,18 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include +#include +#include +#include +#include +#include #include "core/hle/service/am/applet_manager.h" #include "core/loader/nca.h" #include "core/tools/renderdoc.h" #include "frontend_common/firmware_manager.h" -#include "qt_common/qt_common.h" -#include "qt_common/qt_content_util.h" -#include "qt_common/qt_game_util.h" -#include "qt_common/qt_meta.h" -#include "qt_common/qt_path_util.h" -#include -#include -#include -#include + +#include #ifdef __APPLE__ #include // for chdir @@ -40,16 +39,21 @@ #include "configuration/configure_input.h" #include "configuration/configure_per_game.h" #include "configuration/configure_tas.h" +#include "core/core_timing.h" #include "core/file_sys/romfs_factory.h" +#include "core/file_sys/vfs/vfs.h" +#include "core/file_sys/vfs/vfs_real.h" #include "core/frontend/applets/cabinet.h" #include "core/frontend/applets/controller.h" #include "core/frontend/applets/general.h" #include "core/frontend/applets/mii_edit.h" #include "core/frontend/applets/software_keyboard.h" +#include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/set/system_settings_server.h" #include "frontend_common/content_manager.h" -#include "hid_core/hid_core.h" #include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" #include "yuzu/multiplayer/state.h" #include "yuzu/util/controller_navigation.h" @@ -63,8 +67,9 @@ // These are wrappers to avoid the calls to CreateDirectory and CreateFile because of the Windows // defines. -static FileSys::VirtualDir VfsFilesystemCreateDirectoryWrapper(const std::string& path, FileSys::OpenMode mode) { - return QtCommon::vfs->CreateDirectory(path, mode); +static FileSys::VirtualDir VfsFilesystemCreateDirectoryWrapper( + const FileSys::VirtualFilesystem& vfs, const std::string& path, FileSys::OpenMode mode) { + return vfs->CreateDirectory(path, mode); } static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::VirtualDir& dir, @@ -113,7 +118,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "common/scm_rev.h" #include "common/scope_exit.h" #ifdef _WIN32 -#include "core/core_timing.h" +#include #include "common/windows/timer_resolution.h" #endif #ifdef ARCHITECTURE_x86_64 @@ -132,7 +137,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "core/file_sys/savedata_factory.h" #include "core/file_sys/submission_package.h" #include "core/hle/kernel/k_process.h" -#include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/am.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/sm/sm.h" @@ -152,7 +156,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "yuzu/compatibility_list.h" #include "yuzu/configuration/configure_dialog.h" #include "yuzu/configuration/configure_input_per_game.h" -#include "qt_common/qt_config.h" +#include "yuzu/configuration/qt_config.h" #include "yuzu/debugger/console.h" #include "yuzu/debugger/controller.h" #include "yuzu/debugger/wait_tree.h" @@ -160,12 +164,13 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "yuzu/discord.h" #include "yuzu/game_list.h" #include "yuzu/game_list_p.h" +#include "yuzu/hotkeys.h" #include "yuzu/install_dialog.h" #include "yuzu/loading_screen.h" #include "yuzu/main.h" #include "yuzu/play_time_manager.h" #include "yuzu/startup_checks.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #include "yuzu/util/clickable_label.h" #include "yuzu/vk_device_info.h" @@ -173,9 +178,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include #include #include -#ifdef _MSC_VER #pragma comment(lib, "Dwmapi.lib") -#endif static inline void ApplyWindowsTitleBarDarkMode(HWND hwnd, bool enabled) { if (!hwnd) @@ -294,6 +297,14 @@ enum class CalloutFlag : uint32_t { DRDDeprecation = 0x2, }; +/** + * Some games perform worse or straight-up don't work with updates, + * so this tracks which games are bad in this regard. + */ +constexpr std::array bad_update_games{ + 0x0100F2C0115B6000 // Tears of the Kingdom +}; + const int GMainWindow::max_recent_files_item; static void RemoveCachedContents() { @@ -375,8 +386,6 @@ static void OverrideWindowsFont() { } #endif -#ifndef _WIN32 -// TODO(crueter): carboxyl does this, is it needed in qml? inline static bool isDarkMode() { #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) const auto scheme = QGuiApplication::styleHints()->colorScheme(); @@ -388,13 +397,12 @@ inline static bool isDarkMode() { return text.lightness() > window.lightness(); #endif // QT_VERSION } -#endif // _WIN32 GMainWindow::GMainWindow(bool has_broken_vulkan) - : ui{std::make_unique()}, - input_subsystem{std::make_shared()}, user_data_migrator{this} { - QtCommon::Init(this); - + : ui{std::make_unique()}, system{std::make_unique()}, + input_subsystem{std::make_shared()}, user_data_migrator{this}, + vfs{std::make_shared()}, + provider{std::make_unique()} { Common::FS::CreateEdenPaths(); this->config = std::make_unique(); @@ -425,7 +433,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) UISettings::RestoreWindowState(config); - QtCommon::system->Initialize(); + system->Initialize(); Common::Log::Initialize(); Common::Log::Start(); @@ -447,11 +455,11 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); discord_rpc->Update(); - play_time_manager = std::make_unique(QtCommon::system->GetProfileManager()); + play_time_manager = std::make_unique(system->GetProfileManager()); Network::Init(); - QtCommon::Meta::RegisterMetaTypes(); + RegisterMetaTypes(); InitializeWidgets(); InitializeDebugWidgets(); @@ -464,7 +472,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) ConnectMenuEvents(); ConnectWidgetEvents(); - QtCommon::system->HIDCore().ReloadInputDevices(); + system->HIDCore().ReloadInputDevices(); controller_dialog->refreshConfiguration(); const auto branch_name = std::string(Common::g_scm_branch); @@ -508,7 +516,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) std::chrono::duration_cast>( Common::Windows::SetCurrentTimerResolutionToMaximum()) .count()); - QtCommon::system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution()); + system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution()); #endif UpdateWindowTitle(); @@ -534,10 +542,10 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) } #endif - QtCommon::system->SetContentProvider(std::make_unique()); - QtCommon::system->RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual, - QtCommon::provider.get()); - QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs); + system->SetContentProvider(std::make_unique()); + system->RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual, + provider.get()); + system->GetFileSystemController().CreateFactories(*vfs); // Remove cached contents generated during the previous session RemoveCachedContents(); @@ -547,7 +555,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) game_list->LoadCompatibilityList(); // force reload on first load to ensure add-ons get updated - game_list->PopulateAsync(UISettings::values.game_dirs); + game_list->PopulateAsync(UISettings::values.game_dirs, false); // make sure menubar has the arrow cursor instead of inheriting from this ui->menubar->setCursor(QCursor()); @@ -651,7 +659,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) if (!argument_ok) { // try to look it up by username, only finds the first username that matches. const std::string user_arg_str = args[user_arg_idx].toStdString(); - const auto user_idx = QtCommon::system->GetProfileManager().GetUserIndex(user_arg_str); + const auto user_idx = system->GetProfileManager().GetUserIndex(user_arg_str); if (user_idx == std::nullopt) { LOG_ERROR(Frontend, "Invalid user argument"); @@ -661,7 +669,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) selected_user = user_idx.value(); } - if (!QtCommon::system->GetProfileManager().UserExistsIndex(selected_user)) { + if (!system->GetProfileManager().UserExistsIndex(selected_user)) { LOG_ERROR(Frontend, "Selected user doesn't exist"); continue; } @@ -722,6 +730,65 @@ GMainWindow::~GMainWindow() { #endif } +void GMainWindow::RegisterMetaTypes() { + // Register integral and floating point types + qRegisterMetaType("u8"); + qRegisterMetaType("u16"); + qRegisterMetaType("u32"); + qRegisterMetaType("u64"); + qRegisterMetaType("u128"); + qRegisterMetaType("s8"); + qRegisterMetaType("s16"); + qRegisterMetaType("s32"); + qRegisterMetaType("s64"); + qRegisterMetaType("f32"); + qRegisterMetaType("f64"); + + // Register string types + qRegisterMetaType("std::string"); + qRegisterMetaType("std::wstring"); + qRegisterMetaType("std::u8string"); + qRegisterMetaType("std::u16string"); + qRegisterMetaType("std::u32string"); + qRegisterMetaType("std::string_view"); + qRegisterMetaType("std::wstring_view"); + qRegisterMetaType("std::u8string_view"); + qRegisterMetaType("std::u16string_view"); + qRegisterMetaType("std::u32string_view"); + + // Register applet types + + // Cabinet Applet + qRegisterMetaType("Core::Frontend::CabinetParameters"); + qRegisterMetaType>( + "std::shared_ptr"); + + // Controller Applet + qRegisterMetaType("Core::Frontend::ControllerParameters"); + + // Profile Select Applet + qRegisterMetaType( + "Core::Frontend::ProfileSelectParameters"); + + // Software Keyboard Applet + qRegisterMetaType( + "Core::Frontend::KeyboardInitializeParameters"); + qRegisterMetaType( + "Core::Frontend::InlineAppearParameters"); + qRegisterMetaType("Core::Frontend::InlineTextParameters"); + qRegisterMetaType("Service::AM::Frontend::SwkbdResult"); + qRegisterMetaType( + "Service::AM::Frontend::SwkbdTextCheckResult"); + qRegisterMetaType( + "Service::AM::Frontend::SwkbdReplyType"); + + // Web Browser Applet + qRegisterMetaType("Service::AM::Frontend::WebExitReason"); + + // Register loader types + qRegisterMetaType("Core::SystemResultStatus"); +} + void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, std::shared_ptr nfp_device) { cabinet_applet = @@ -752,7 +819,7 @@ void GMainWindow::AmiiboSettingsRequestExit() { void GMainWindow::ControllerSelectorReconfigureControllers( const Core::Frontend::ControllerParameters& parameters) { controller_applet = - new QtControllerSelectorDialog(this, parameters, input_subsystem.get(), *QtCommon::system); + new QtControllerSelectorDialog(this, parameters, input_subsystem.get(), *system); SCOPE_EXIT { controller_applet->deleteLater(); controller_applet = nullptr; @@ -765,8 +832,8 @@ void GMainWindow::ControllerSelectorReconfigureControllers( bool is_success = controller_applet->exec() != QDialog::Rejected; // Don't forget to apply settings. - QtCommon::system->HIDCore().DisableAllControllerConfiguration(); - QtCommon::system->ApplySettings(); + system->HIDCore().DisableAllControllerConfiguration(); + system->ApplySettings(); config->SaveAllValues(); UpdateStatusButtons(); @@ -782,7 +849,7 @@ void GMainWindow::ControllerSelectorRequestExit() { void GMainWindow::ProfileSelectorSelectProfile( const Core::Frontend::ProfileSelectParameters& parameters) { - profile_select_applet = new QtProfileSelectionDialog(*QtCommon::system, this, parameters); + profile_select_applet = new QtProfileSelectionDialog(*system, this, parameters); SCOPE_EXIT { profile_select_applet->deleteLater(); profile_select_applet = nullptr; @@ -797,7 +864,7 @@ void GMainWindow::ProfileSelectorSelectProfile( return; } - const auto uuid = QtCommon::system->GetProfileManager().GetUser( + const auto uuid = system->GetProfileManager().GetUser( static_cast(profile_select_applet->GetIndex())); if (!uuid.has_value()) { emit ProfileSelectorFinishedSelection(std::nullopt); @@ -820,7 +887,7 @@ void GMainWindow::SoftwareKeyboardInitialize( return; } - software_keyboard = new QtSoftwareKeyboardDialog(render_window, *QtCommon::system, is_inline, + software_keyboard = new QtSoftwareKeyboardDialog(render_window, *system, is_inline, std::move(initialize_parameters)); if (is_inline) { @@ -937,7 +1004,7 @@ void GMainWindow::WebBrowserOpenWebPage(const std::string& main_url, return; } - web_applet = new QtNXWebEngineView(this, *QtCommon::system, input_subsystem.get()); + web_applet = new QtNXWebEngineView(this, *system, input_subsystem.get()); ui->action_Pause->setEnabled(false); ui->action_Restart->setEnabled(false); @@ -1081,10 +1148,10 @@ void GMainWindow::InitializeWidgets() { #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING ui->action_Report_Compatibility->setVisible(true); #endif - render_window = new GRenderWindow(this, emu_thread.get(), input_subsystem, *QtCommon::system); + render_window = new GRenderWindow(this, emu_thread.get(), input_subsystem, *system); render_window->hide(); - game_list = new GameList(QtCommon::vfs, QtCommon::provider.get(), *play_time_manager, *QtCommon::system, this); + game_list = new GameList(vfs, provider.get(), *play_time_manager, *system, this); ui->horizontalLayout->addWidget(game_list); game_list_placeholder = new GameListPlaceholder(this); @@ -1094,7 +1161,7 @@ void GMainWindow::InitializeWidgets() { loading_screen = new LoadingScreen(this); loading_screen->hide(); ui->horizontalLayout->addWidget(loading_screen); - connect(loading_screen, &LoadingScreen::Hidden, this, [&] { + connect(loading_screen, &LoadingScreen::Hidden, [&] { loading_screen->Clear(); if (emulation_running) { render_window->show(); @@ -1103,7 +1170,7 @@ void GMainWindow::InitializeWidgets() { }); multiplayer_state = new MultiplayerState(this, game_list->GetModel(), ui->action_Leave_Room, - ui->action_Show_Room, *QtCommon::system); + ui->action_Show_Room, *system); multiplayer_state->setVisible(false); // Create status bar @@ -1357,12 +1424,12 @@ void GMainWindow::InitializeWidgets() { void GMainWindow::InitializeDebugWidgets() { QMenu* debug_menu = ui->menu_View_Debugging; - waitTreeWidget = new WaitTreeWidget(*QtCommon::system, this); + waitTreeWidget = new WaitTreeWidget(*system, this); addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget); waitTreeWidget->hide(); debug_menu->addAction(waitTreeWidget->toggleViewAction()); - controller_dialog = new ControllerDialog(QtCommon::system->HIDCore(), input_subsystem, this); + controller_dialog = new ControllerDialog(system->HIDCore(), input_subsystem, this); controller_dialog->hide(); debug_menu->addAction(controller_dialog->toggleViewAction()); @@ -1402,7 +1469,7 @@ void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name this->addAction(action); - auto* controller = QtCommon::system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); const auto* controller_hotkey = hotkey_registry.GetControllerHotkey(main_window, action_name.toStdString(), controller); connect( @@ -1447,7 +1514,7 @@ void GMainWindow::InitializeHotkeys() { const auto connect_shortcut = [&](const QString& action_name, const Fn& function) { const auto* hotkey = hotkey_registry.GetHotkey(main_window.toStdString(), action_name.toStdString(), this); - auto* controller = QtCommon::system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); const auto* controller_hotkey = hotkey_registry.GetControllerHotkey( main_window.toStdString(), action_name.toStdString(), controller); connect(hotkey, &QShortcut::activated, this, function); @@ -1471,9 +1538,9 @@ void GMainWindow::InitializeHotkeys() { connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] { Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue()); }); - connect_shortcut(QStringLiteral("Toggle Renderdoc Capture"), [] { + connect_shortcut(QStringLiteral("Toggle Renderdoc Capture"), [this] { if (Settings::values.enable_renderdoc_hotkey) { - QtCommon::system->GetRenderdocAPI().ToggleCapture(); + system->GetRenderdocAPI().ToggleCapture(); } }); connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] { @@ -1563,9 +1630,8 @@ void GMainWindow::ConnectWidgetEvents() { connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile); connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory); connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); - connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this, [this](u64 program_id) { - QtCommon::Path::OpenShaderCache(program_id, this); - }); + connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this, + &GMainWindow::OnTransferableShaderCacheOpenFile); connect(game_list, &GameList::RemoveInstalledEntryRequested, this, &GMainWindow::OnGameListRemoveInstalledEntry); connect(game_list, &GameList::RemoveFileRequested, this, &GMainWindow::OnGameListRemoveFile); @@ -1879,13 +1945,13 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa return false; } - QtCommon::system->SetFilesystem(QtCommon::vfs); + system->SetFilesystem(vfs); if (params.launch_type == Service::AM::LaunchType::FrontendInitiated) { - QtCommon::system->GetUserChannel().clear(); + system->GetUserChannel().clear(); } - QtCommon::system->SetFrontendAppletSet({ + system->SetFrontendAppletSet({ std::make_unique(*this), // Amiibo Settings (UISettings::values.controller_applet_disabled.GetValue() == true) ? nullptr @@ -1900,21 +1966,85 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa nullptr, // Net Connect }); - /** firmware check */ + /** Game Updates check */ - if (!QtCommon::Content::CheckGameFirmware(params.program_id, this)) { - return false; + // yuzu's configuration doesn't actually support lists so this is a bit hacky + QSettings settings; + QStringList currentIgnored = settings.value("ignoredBadUpdates", {}).toStringList(); + + if (std::find(bad_update_games.begin(), bad_update_games.end(), params.program_id) != + bad_update_games.end() && + !currentIgnored.contains(QString::number(params.program_id))) { + QMessageBox* msg = new QMessageBox(this); + msg->setWindowTitle(tr("Game Updates Warning")); + msg->setIcon(QMessageBox::Warning); + msg->setText( + tr("The game you are trying to launch is known to have performance or booting " + "issues when updates are applied. Please try increasing the memory layout to " + "6GB or 8GB if any issues occur.

Press \"OK\" to continue launching, or " + "\"Cancel\" to cancel the launch.")); + + msg->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + + QCheckBox* dontShowAgain = new QCheckBox(msg); + dontShowAgain->setText(tr("Don't show again for this game")); + msg->setCheckBox(dontShowAgain); + + int result = msg->exec(); + + // wtf + QMessageBox::ButtonRole role = + msg->buttonRole(msg->button((QMessageBox::StandardButton)result)); + + switch (role) { + case QMessageBox::RejectRole: + return false; + case QMessageBox::AcceptRole: + default: + if (dontShowAgain->isChecked()) { + currentIgnored << QString::number(params.program_id); + settings.setValue("ignoredBadUpdates", currentIgnored); + settings.sync(); + } + break; + } + } + + if (FirmwareManager::GameRequiresFirmware(params.program_id) && + !FirmwareManager::CheckFirmwarePresence(*system)) { + QMessageBox* msg = new QMessageBox(this); + msg->setWindowTitle(tr("Game Requires Firmware")); + msg->setIcon(QMessageBox::Warning); + msg->setText( + tr("The game you are trying to launch requires firmware to boot or to get past the " + "opening menu. Please " + "dump and install firmware, or press \"OK\" to launch anyways.")); + + msg->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + + int exec_result = msg->exec(); + + QMessageBox::ButtonRole role = + msg->buttonRole(msg->button((QMessageBox::StandardButton)exec_result)); + + switch (role) { + case QMessageBox::RejectRole: + return false; + case QMessageBox::AcceptRole: + default: + break; + } } /** Exec */ const Core::SystemResultStatus result{ - QtCommon::system->Load(*render_window, filename.toStdString(), params)}; + system->Load(*render_window, filename.toStdString(), params)}; const auto drd_callout = (UISettings::values.callout_flags.GetValue() & static_cast(CalloutFlag::DRDDeprecation)) == 0; if (result == Core::SystemResultStatus::Success && - QtCommon::system->GetAppLoader().GetFileType() == Loader::FileType::DeconstructedRomDirectory && + system->GetAppLoader().GetFileType() == Loader::FileType::DeconstructedRomDirectory && drd_callout) { UISettings::values.callout_flags = UISettings::values.callout_flags.GetValue() | static_cast(CalloutFlag::DRDDeprecation); @@ -1979,7 +2109,7 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa bool GMainWindow::SelectAndSetCurrentUser( const Core::Frontend::ProfileSelectParameters& parameters) { - QtProfileSelectionDialog dialog(*QtCommon::system, this, parameters); + QtProfileSelectionDialog dialog(*system, this, parameters); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); @@ -1994,12 +2124,12 @@ bool GMainWindow::SelectAndSetCurrentUser( void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) { // Ensure all NCAs are registered before launching the game - const auto file = QtCommon::vfs->OpenFile(filepath, FileSys::OpenMode::Read); + const auto file = vfs->OpenFile(filepath, FileSys::OpenMode::Read); if (!file) { return; } - auto loader = Loader::GetLoader(*QtCommon::system, file); + auto loader = Loader::GetLoader(*system, file); if (!loader) { return; } @@ -2012,7 +2142,7 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) { u64 program_id = 0; const auto res2 = loader->ReadProgramId(program_id); if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) { - QtCommon::provider->AddEntry(FileSys::TitleType::Application, + provider->AddEntry(FileSys::TitleType::Application, FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()), program_id, file); } else if (res2 == Loader::ResultStatus::Success && @@ -2022,7 +2152,7 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) { : FileSys::XCI{file}.GetSecurePartitionNSP(); for (const auto& title : nsp->GetNCAs()) { for (const auto& entry : title.second) { - QtCommon::provider->AddEntry(entry.first.first, entry.first.second, title.first, + provider->AddEntry(entry.first.first, entry.first.second, title.first, entry.second->GetBaseFile()); } } @@ -2048,8 +2178,8 @@ void GMainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletP last_filename_booted = filename; ConfigureFilesystemProvider(filename.toStdString()); - const auto v_file = Core::GetGameFileFromPath(QtCommon::vfs, filename.toUtf8().constData()); - const auto loader = Loader::GetLoader(*QtCommon::system, v_file, params.program_id, params.program_index); + const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); + const auto loader = Loader::GetLoader(*system, v_file, params.program_id, params.program_index); if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success && type == StartGameType::Normal) { @@ -2060,8 +2190,8 @@ void GMainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletP ? Common::FS::PathToUTF8String(file_path.filename()) : fmt::format("{:016X}", title_id); QtConfig per_game_config(config_file_name, Config::ConfigType::PerGameConfig); - QtCommon::system->HIDCore().ReloadInputDevices(); - QtCommon::system->ApplySettings(); + system->HIDCore().ReloadInputDevices(); + system->ApplySettings(); } Settings::LogSettings(); @@ -2087,19 +2217,19 @@ void GMainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletP return; } - QtCommon::system->SetShuttingDown(false); + system->SetShuttingDown(false); game_list->setDisabled(true); // Create and start the emulation thread - emu_thread = std::make_unique(*QtCommon::system); + emu_thread = std::make_unique(*system); emit EmulationStarting(emu_thread.get()); emu_thread->start(); // Register an ExecuteProgram callback such that Core can execute a sub-program - QtCommon::system->RegisterExecuteProgramCallback( + system->RegisterExecuteProgramCallback( [this](std::size_t program_index_) { render_window->ExecuteProgram(program_index_); }); - QtCommon::system->RegisterExitCallback([this] { + system->RegisterExitCallback([this] { emu_thread->ForceStop(); render_window->Exit(); }); @@ -2139,11 +2269,11 @@ void GMainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletP std::string title_name; std::string title_version; - const auto res = QtCommon::system->GetGameName(title_name); + const auto res = system->GetGameName(title_name); - const auto metadata = [title_id] { - const FileSys::PatchManager pm(title_id, QtCommon::system->GetFileSystemController(), - QtCommon::system->GetContentProvider()); + const auto metadata = [this, title_id] { + const FileSys::PatchManager pm(title_id, system->GetFileSystemController(), + system->GetContentProvider()); return pm.GetControlMetadata(); }(); if (metadata.first != nullptr) { @@ -2155,16 +2285,16 @@ void GMainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletP std::filesystem::path{Common::U16StringFromBuffer(filename.utf16(), filename.size())} .filename()); } - const bool is_64bit = QtCommon::system->Kernel().ApplicationProcess()->Is64Bit(); + const bool is_64bit = system->Kernel().ApplicationProcess()->Is64Bit(); const auto instruction_set_suffix = is_64bit ? tr("(64-bit)") : tr("(32-bit)"); title_name = tr("%1 %2", "%1 is the title name. %2 indicates if the title is 64-bit or 32-bit") .arg(QString::fromStdString(title_name), instruction_set_suffix) .toStdString(); LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); - const auto gpu_vendor = QtCommon::system->GPU().Renderer().GetDeviceVendor(); + const auto gpu_vendor = system->GPU().Renderer().GetDeviceVendor(); UpdateWindowTitle(title_name, title_version, gpu_vendor); - loading_screen->Prepare(QtCommon::system->GetAppLoader()); + loading_screen->Prepare(system->GetAppLoader()); loading_screen->show(); emulation_running = true; @@ -2192,11 +2322,11 @@ bool GMainWindow::OnShutdownBegin() { // Disable unlimited frame rate Settings::values.use_speed_limit.SetValue(true); - if (QtCommon::system->IsShuttingDown()) { + if (system->IsShuttingDown()) { return false; } - QtCommon::system->SetShuttingDown(true); + system->SetShuttingDown(true); discord_rpc->Pause(); RequestGameExit(); @@ -2207,9 +2337,9 @@ bool GMainWindow::OnShutdownBegin() { int shutdown_time = 1000; - if (QtCommon::system->DebuggerEnabled()) { + if (system->DebuggerEnabled()) { shutdown_time = 0; - } else if (QtCommon::system->GetExitLocked()) { + } else if (system->GetExitLocked()) { shutdown_time = 5000; } @@ -2227,7 +2357,7 @@ bool GMainWindow::OnShutdownBegin() { } void GMainWindow::OnShutdownBeginDialog() { - shutdown_dialog = new OverlayDialog(this, *QtCommon::system, QString{}, tr("Closing software..."), + shutdown_dialog = new OverlayDialog(this, *system, QString{}, tr("Closing software..."), QString{}, QString{}, Qt::AlignHCenter | Qt::AlignVCenter); shutdown_dialog->open(); } @@ -2279,10 +2409,10 @@ void GMainWindow::OnEmulationStopped() { OnTasStateChanged(); render_window->FinalizeCamera(); - QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::None); + system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::None); // Enable all controllers - QtCommon::system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); + system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); render_window->removeEventFilter(render_window); render_window->setAttribute(Qt::WA_Hover, false); @@ -2311,8 +2441,8 @@ void GMainWindow::OnEmulationStopped() { // Enable game list game_list->setEnabled(true); - Settings::RestoreGlobalState(QtCommon::system->IsPoweredOn()); - QtCommon::system->HIDCore().ReloadInputDevices(); + Settings::RestoreGlobalState(system->IsPoweredOn()); + system->HIDCore().ReloadInputDevices(); UpdateStatusButtons(); } @@ -2321,7 +2451,6 @@ void GMainWindow::ShutdownGame() { return; } - // TODO(crueter): make this common as well (frontend_common?) play_time_manager->Stop(); OnShutdownBegin(); OnEmulationStopTimeExpired(); @@ -2340,7 +2469,7 @@ void GMainWindow::StoreRecentFile(const QString& filename) { void GMainWindow::UpdateRecentFiles() { const int num_recent_files = - (std::min)(static_cast(UISettings::values.recent_files.size()), max_recent_files_item); + std::min(static_cast(UISettings::values.recent_files.size()), max_recent_files_item); for (int i = 0; i < num_recent_files; i++) { const QString text = QStringLiteral("&%1. %2").arg(i + 1).arg( @@ -2366,22 +2495,21 @@ void GMainWindow::OnGameListLoadFile(QString game_path, u64 program_id) { BootGame(game_path, params); } -// TODO(crueter): Common profile selector void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, const std::string& game_path) { std::filesystem::path path; QString open_target; - const auto [user_save_size, device_save_size] = [&game_path, &program_id] { - const FileSys::PatchManager pm{program_id, QtCommon::system->GetFileSystemController(), - QtCommon::system->GetContentProvider()}; + const auto [user_save_size, device_save_size] = [this, &game_path, &program_id] { + const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), + system->GetContentProvider()}; const auto control = pm.GetControlMetadata().first; if (control != nullptr) { return std::make_pair(control->GetDefaultNormalSaveSize(), control->GetDeviceSaveDataSize()); } else { - const auto file = Core::GetGameFileFromPath(QtCommon::vfs, game_path); - const auto loader = Loader::GetLoader(*QtCommon::system, file); + const auto file = Core::GetGameFileFromPath(vfs, game_path); + const auto loader = Loader::GetLoader(*system, file); FileSys::NACP nacp{}; loader->ReadControlData(nacp); @@ -2400,7 +2528,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target open_target = tr("Save Data"); const auto nand_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir); auto vfs_nand_dir = - QtCommon::vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read); + vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read); if (has_user_save) { // User save data @@ -2411,7 +2539,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target .display_options = {}, .purpose = Service::AM::Frontend::UserSelectionPurpose::General, }; - QtProfileSelectionDialog dialog(*QtCommon::system, this, parameters); + QtProfileSelectionDialog dialog(*system, this, parameters); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); @@ -2429,7 +2557,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target } const auto user_id = - QtCommon::system->GetProfileManager().GetUser(static_cast(index)); + system->GetProfileManager().GetUser(static_cast(index)); ASSERT(user_id); const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( @@ -2475,6 +2603,19 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target QDesktopServices::openUrl(QUrl::fromLocalFile(qpath)); } +void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { + const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir); + const auto shader_cache_folder_path{shader_cache_dir / fmt::format("{:016x}", program_id)}; + if (!Common::FS::CreateDirs(shader_cache_folder_path)) { + QMessageBox::warning(this, tr("Error Opening Transferable Shader Cache"), + tr("Failed to create the shader cache directory for this title.")); + return; + } + const auto shader_path_string{Common::FS::PathToUTF8String(shader_cache_folder_path)}; + const auto qt_shader_cache_path = QString::fromStdString(shader_path_string); + QDesktopServices::openUrl(QUrl::fromLocalFile(qt_shader_cache_path)); +} + static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog& dialog, const FileSys::VirtualDir& src, const FileSys::VirtualDir& dest, bool full) { @@ -2507,7 +2648,7 @@ static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog& if ((new_timestamp - last_timestamp) > 33ms) { last_timestamp = new_timestamp; dialog.setValue( - static_cast((std::min)(read_size, total_size) * 100 / total_size)); + static_cast(std::min(read_size, total_size) * 100 / total_size)); QCoreApplication::processEvents(); } @@ -2537,17 +2678,26 @@ static bool RomFSRawCopy(size_t total_size, size_t& read_size, QProgressDialog& return true; } -// TODO(crueter): All this can be transfered to qt_common -// Aldoe I need to decide re: message boxes for QML -// translations_common? strings_common? qt_strings? who knows -void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, QtCommon::Game::InstalledEntryType type) { +QString GMainWindow::GetGameListErrorRemoving(InstalledEntryType type) const { + switch (type) { + case InstalledEntryType::Game: + return tr("Error Removing Contents"); + case InstalledEntryType::Update: + return tr("Error Removing Update"); + case InstalledEntryType::AddOnContent: + return tr("Error Removing DLC"); + default: + return QStringLiteral("Error Removing "); + } +} +void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type) { const QString entry_question = [type] { switch (type) { - case QtCommon::Game::InstalledEntryType::Game: + case InstalledEntryType::Game: return tr("Remove Installed Game Contents?"); - case QtCommon::Game::InstalledEntryType::Update: + case InstalledEntryType::Update: return tr("Remove Installed Game Update?"); - case QtCommon::Game::InstalledEntryType::AddOnContent: + case InstalledEntryType::AddOnContent: return tr("Remove Installed Game DLC?"); default: return QStringLiteral("Remove Installed Game ?"); @@ -2559,19 +2709,18 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, QtCommon::Game: return; } - // TODO(crueter): move this to QtCommon (populate async?) switch (type) { - case QtCommon::Game::InstalledEntryType::Game: - QtCommon::Game::RemoveBaseContent(program_id, type); + case InstalledEntryType::Game: + RemoveBaseContent(program_id, type); [[fallthrough]]; - case QtCommon::Game::InstalledEntryType::Update: - QtCommon::Game::RemoveUpdateContent(program_id, type); - if (type != QtCommon::Game::InstalledEntryType::Game) { + case InstalledEntryType::Update: + RemoveUpdateContent(program_id, type); + if (type != InstalledEntryType::Game) { break; } [[fallthrough]]; - case QtCommon::Game::InstalledEntryType::AddOnContent: - QtCommon::Game::RemoveAddOnContent(program_id, type); + case InstalledEntryType::AddOnContent: + RemoveAddOnContent(program_id, type); break; } Common::FS::RemoveDirRecursively(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / @@ -2579,19 +2728,55 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, QtCommon::Game: game_list->PopulateAsync(UISettings::values.game_dirs); } -void GMainWindow::OnGameListRemoveFile(u64 program_id, QtCommon::Game::GameListRemoveTarget target, +void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { + const auto res = + ContentManager::RemoveBaseContent(system->GetFileSystemController(), program_id); + if (res) { + QMessageBox::information(this, tr("Successfully Removed"), + tr("Successfully removed the installed base game.")); + } else { + QMessageBox::warning( + this, GetGameListErrorRemoving(type), + tr("The base game is not installed in the NAND and cannot be removed.")); + } +} + +void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { + const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id); + if (res) { + QMessageBox::information(this, tr("Successfully Removed"), + tr("Successfully removed the installed update.")); + } else { + QMessageBox::warning(this, GetGameListErrorRemoving(type), + tr("There is no update installed for this title.")); + } +} + +void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) { + const size_t count = ContentManager::RemoveAllDLC(*system, program_id); + if (count == 0) { + QMessageBox::warning(this, GetGameListErrorRemoving(type), + tr("There are no DLC installed for this title.")); + return; + } + + QMessageBox::information(this, tr("Successfully Removed"), + tr("Successfully removed %1 installed DLC.").arg(count)); +} + +void GMainWindow::OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target, const std::string& game_path) { const QString question = [target] { switch (target) { - case QtCommon::Game::GameListRemoveTarget::GlShaderCache: + case GameListRemoveTarget::GlShaderCache: return tr("Delete OpenGL Transferable Shader Cache?"); - case QtCommon::Game::GameListRemoveTarget::VkShaderCache: + case GameListRemoveTarget::VkShaderCache: return tr("Delete Vulkan Transferable Shader Cache?"); - case QtCommon::Game::GameListRemoveTarget::AllShaderCache: + case GameListRemoveTarget::AllShaderCache: return tr("Delete All Transferable Shader Caches?"); - case QtCommon::Game::GameListRemoveTarget::CustomConfiguration: + case GameListRemoveTarget::CustomConfiguration: return tr("Remove Custom Game Configuration?"); - case QtCommon::Game::GameListRemoveTarget::CacheStorage: + case GameListRemoveTarget::CacheStorage: return tr("Remove Cache Storage?"); default: return QString{}; @@ -2604,20 +2789,20 @@ void GMainWindow::OnGameListRemoveFile(u64 program_id, QtCommon::Game::GameListR } switch (target) { - case QtCommon::Game::GameListRemoveTarget::VkShaderCache: - QtCommon::Game::RemoveVulkanDriverPipelineCache(program_id); + case GameListRemoveTarget::VkShaderCache: + RemoveVulkanDriverPipelineCache(program_id); [[fallthrough]]; - case QtCommon::Game::GameListRemoveTarget::GlShaderCache: - QtCommon::Game::RemoveTransferableShaderCache(program_id, target); + case GameListRemoveTarget::GlShaderCache: + RemoveTransferableShaderCache(program_id, target); break; - case QtCommon::Game::GameListRemoveTarget::AllShaderCache: - QtCommon::Game::RemoveAllTransferableShaderCaches(program_id); + case GameListRemoveTarget::AllShaderCache: + RemoveAllTransferableShaderCaches(program_id); break; - case QtCommon::Game::GameListRemoveTarget::CustomConfiguration: - QtCommon::Game::RemoveCustomConfiguration(program_id, game_path); + case GameListRemoveTarget::CustomConfiguration: + RemoveCustomConfiguration(program_id, game_path); break; - case QtCommon::Game::GameListRemoveTarget::CacheStorage: - QtCommon::Game::RemoveCacheStorage(program_id); + case GameListRemoveTarget::CacheStorage: + RemoveCacheStorage(program_id); break; } } @@ -2633,6 +2818,107 @@ void GMainWindow::OnGameListRemovePlayTimeData(u64 program_id) { game_list->PopulateAsync(UISettings::values.game_dirs); } +void GMainWindow::RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target) { + const auto target_file_name = [target] { + switch (target) { + case GameListRemoveTarget::GlShaderCache: + return "opengl.bin"; + case GameListRemoveTarget::VkShaderCache: + return "vulkan.bin"; + default: + return ""; + } + }(); + const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir); + const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id); + const auto target_file = shader_cache_folder_path / target_file_name; + + if (!Common::FS::Exists(target_file)) { + QMessageBox::warning(this, tr("Error Removing Transferable Shader Cache"), + tr("A shader cache for this title does not exist.")); + return; + } + if (Common::FS::RemoveFile(target_file)) { + QMessageBox::information(this, tr("Successfully Removed"), + tr("Successfully removed the transferable shader cache.")); + } else { + QMessageBox::warning(this, tr("Error Removing Transferable Shader Cache"), + tr("Failed to remove the transferable shader cache.")); + } +} + +void GMainWindow::RemoveVulkanDriverPipelineCache(u64 program_id) { + static constexpr std::string_view target_file_name = "vulkan_pipelines.bin"; + + const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir); + const auto shader_cache_folder_path = shader_cache_dir / fmt::format("{:016x}", program_id); + const auto target_file = shader_cache_folder_path / target_file_name; + + if (!Common::FS::Exists(target_file)) { + return; + } + if (!Common::FS::RemoveFile(target_file)) { + QMessageBox::warning(this, tr("Error Removing Vulkan Driver Pipeline Cache"), + tr("Failed to remove the driver pipeline cache.")); + } +} + +void GMainWindow::RemoveAllTransferableShaderCaches(u64 program_id) { + const auto shader_cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir); + const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id); + + if (!Common::FS::Exists(program_shader_cache_dir)) { + QMessageBox::warning(this, tr("Error Removing Transferable Shader Caches"), + tr("A shader cache for this title does not exist.")); + return; + } + if (Common::FS::RemoveDirRecursively(program_shader_cache_dir)) { + QMessageBox::information(this, tr("Successfully Removed"), + tr("Successfully removed the transferable shader caches.")); + } else { + QMessageBox::warning(this, tr("Error Removing Transferable Shader Caches"), + tr("Failed to remove the transferable shader cache directory.")); + } +} + +void GMainWindow::RemoveCustomConfiguration(u64 program_id, const std::string& game_path) { + const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path)); + const auto config_file_name = + program_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()).append(".ini") + : fmt::format("{:016X}.ini", program_id); + const auto custom_config_file_path = + Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir) / "custom" / config_file_name; + + if (!Common::FS::Exists(custom_config_file_path)) { + QMessageBox::warning(this, tr("Error Removing Custom Configuration"), + tr("A custom configuration for this title does not exist.")); + return; + } + + if (Common::FS::RemoveFile(custom_config_file_path)) { + QMessageBox::information(this, tr("Successfully Removed"), + tr("Successfully removed the custom game configuration.")); + } else { + QMessageBox::warning(this, tr("Error Removing Custom Configuration"), + tr("Failed to remove the custom game configuration.")); + } +} + +void GMainWindow::RemoveCacheStorage(u64 program_id) { + const auto nand_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir); + auto vfs_nand_dir = + vfs->OpenDirectory(Common::FS::PathToUTF8String(nand_dir), FileSys::OpenMode::Read); + + const auto cache_storage_path = FileSys::SaveDataFactory::GetFullPath( + {}, vfs_nand_dir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Cache, + 0 /* program_id */, {}, 0); + + const auto path = Common::FS::ConcatPathSafe(nand_dir, cache_storage_path); + + // Not an error if it wasn't cleared. + Common::FS::RemoveDirRecursively(path); +} + void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_path, DumpRomFSTarget target) { const auto failed = [this] { @@ -2642,7 +2928,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa }; const auto loader = - Loader::GetLoader(*QtCommon::system, QtCommon::vfs->OpenFile(game_path, FileSys::OpenMode::Read)); + Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::OpenMode::Read)); if (loader == nullptr) { failed(); return; @@ -2651,7 +2937,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa FileSys::VirtualFile packed_update_raw{}; loader->ReadUpdateRaw(packed_update_raw); - const auto& installed = QtCommon::system->GetContentProvider(); + const auto& installed = system->GetContentProvider(); u64 title_id{}; u8 raw_type{}; @@ -2683,14 +2969,14 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa const auto path = Common::FS::PathToUTF8String(dump_dir / romfs_dir); - const FileSys::PatchManager pm{title_id, QtCommon::system->GetFileSystemController(), installed}; + const FileSys::PatchManager pm{title_id, system->GetFileSystemController(), installed}; auto romfs = pm.PatchRomFS(base_nca.get(), base_romfs, type, packed_update_raw, false); - const auto out = VfsFilesystemCreateDirectoryWrapper(path, FileSys::OpenMode::ReadWrite); + const auto out = VfsFilesystemCreateDirectoryWrapper(vfs, path, FileSys::OpenMode::ReadWrite); if (out == nullptr) { failed(); - QtCommon::vfs->DeleteDirectory(path); + vfs->DeleteDirectory(path); return; } @@ -2704,7 +2990,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa selections, 0, false, &ok); if (!ok) { failed(); - QtCommon::vfs->DeleteDirectory(path); + vfs->DeleteDirectory(path); return; } @@ -2744,13 +3030,41 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa } else { progress.close(); failed(); - QtCommon::vfs->DeleteDirectory(path); + vfs->DeleteDirectory(path); } } -// END void GMainWindow::OnGameListVerifyIntegrity(const std::string& game_path) { - QtCommon::Content::VerifyGameContents(game_path); + const auto NotImplemented = [this] { + QMessageBox::warning(this, tr("Integrity verification couldn't be performed!"), + tr("File contents were not checked for validity.")); + }; + + QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); + progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(100); + progress.setAutoClose(false); + progress.setAutoReset(false); + + const auto QtProgressCallback = [&](size_t total_size, size_t processed_size) { + progress.setValue(static_cast((processed_size * 100) / total_size)); + return progress.wasCanceled(); + }; + + const auto result = ContentManager::VerifyGameContents(*system, game_path, QtProgressCallback); + progress.close(); + switch (result) { + case ContentManager::GameVerificationResult::Success: + QMessageBox::information(this, tr("Integrity verification succeeded!"), + tr("The operation completed successfully.")); + break; + case ContentManager::GameVerificationResult::Failed: + QMessageBox::critical(this, tr("Integrity verification failed!"), + tr("File contents may be corrupt.")); + break; + case ContentManager::GameVerificationResult::NotImplemented: + NotImplemented(); + } } void GMainWindow::OnGameListCopyTID(u64 program_id) { @@ -2771,12 +3085,172 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id, QUrl(QStringLiteral("https://eden-emulator.github.io/game/") + directory)); } +bool GMainWindow::CreateShortcutLink(const std::filesystem::path& shortcut_path, + const std::string& comment, + const std::filesystem::path& icon_path, + const std::filesystem::path& command, + const std::string& arguments, const std::string& categories, + const std::string& keywords, const std::string& name) try { +#ifdef _WIN32 // Windows + HRESULT hr = CoInitialize(nullptr); + if (FAILED(hr)) { + LOG_ERROR(Frontend, "CoInitialize failed"); + return false; + } + SCOPE_EXIT { + CoUninitialize(); + }; + IShellLinkW* ps1 = nullptr; + IPersistFile* persist_file = nullptr; + SCOPE_EXIT { + if (persist_file != nullptr) { + persist_file->Release(); + } + if (ps1 != nullptr) { + ps1->Release(); + } + }; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLinkW, + reinterpret_cast(&ps1)); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to create IShellLinkW instance"); + return false; + } + hres = ps1->SetPath(command.c_str()); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to set path"); + return false; + } + if (!arguments.empty()) { + hres = ps1->SetArguments(Common::UTF8ToUTF16W(arguments).data()); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to set arguments"); + return false; + } + } + if (!comment.empty()) { + hres = ps1->SetDescription(Common::UTF8ToUTF16W(comment).data()); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to set description"); + return false; + } + } + if (std::filesystem::is_regular_file(icon_path)) { + hres = ps1->SetIconLocation(icon_path.c_str(), 0); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to set icon location"); + return false; + } + } + hres = ps1->QueryInterface(IID_IPersistFile, reinterpret_cast(&persist_file)); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to get IPersistFile interface"); + return false; + } + hres = persist_file->Save(std::filesystem::path{shortcut_path / (name + ".lnk")}.c_str(), TRUE); + if (FAILED(hres)) { + LOG_ERROR(Frontend, "Failed to save shortcut"); + return false; + } + return true; +#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) // Any desktop NIX + std::filesystem::path shortcut_path_full = shortcut_path / (name + ".desktop"); + std::ofstream shortcut_stream(shortcut_path_full, std::ios::binary | std::ios::trunc); + if (!shortcut_stream.is_open()) { + LOG_ERROR(Frontend, "Failed to create shortcut"); + return false; + } + // TODO: Migrate fmt::print to std::print in futures STD C++ 23. + fmt::print(shortcut_stream, "[Desktop Entry]\n"); + fmt::print(shortcut_stream, "Type=Application\n"); + fmt::print(shortcut_stream, "Version=1.0\n"); + fmt::print(shortcut_stream, "Name={}\n", name); + if (!comment.empty()) { + fmt::print(shortcut_stream, "Comment={}\n", comment); + } + if (std::filesystem::is_regular_file(icon_path)) { + fmt::print(shortcut_stream, "Icon={}\n", icon_path.string()); + } + fmt::print(shortcut_stream, "TryExec={}\n", command.string()); + fmt::print(shortcut_stream, "Exec={} {}\n", command.string(), arguments); + if (!categories.empty()) { + fmt::print(shortcut_stream, "Categories={}\n", categories); + } + if (!keywords.empty()) { + fmt::print(shortcut_stream, "Keywords={}\n", keywords); + } + return true; +#else // Unsupported platform + return false; +#endif +} catch (const std::exception& e) { + LOG_ERROR(Frontend, "Failed to create shortcut: {}", e.what()); + return false; +} +// Messages in pre-defined message boxes for less code spaghetti +bool GMainWindow::CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title) { + int result = 0; + QMessageBox::StandardButtons buttons; + switch (imsg) { + case GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES: + buttons = QMessageBox::Yes | QMessageBox::No; + result = + QMessageBox::information(parent, tr("Create Shortcut"), + tr("Do you want to launch the game in fullscreen?"), buttons); + return result == QMessageBox::Yes; + case GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS: + QMessageBox::information(parent, tr("Create Shortcut"), + tr("Successfully created a shortcut to %1").arg(game_title)); + return false; + case GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING: + buttons = QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel; + result = + QMessageBox::warning(this, tr("Create Shortcut"), + tr("This will create a shortcut to the current AppImage. This may " + "not work well if you update. Continue?"), + buttons); + return result == QMessageBox::Ok; + default: + buttons = QMessageBox::Ok; + QMessageBox::critical(parent, tr("Create Shortcut"), + tr("Failed to create a shortcut to %1").arg(game_title), buttons); + return false; + } +} + +bool GMainWindow::MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, + std::filesystem::path& out_icon_path) { + // Get path to Yuzu icons directory & icon extension + std::string ico_extension = "png"; +#if defined(_WIN32) + out_icon_path = Common::FS::GetEdenPath(Common::FS::EdenPath::IconsDir); + ico_extension = "ico"; +#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) + out_icon_path = Common::FS::GetDataDirectory("XDG_DATA_HOME") / "icons/hicolor/256x256"; +#endif + // Create icons directory if it doesn't exist + if (!Common::FS::CreateDirs(out_icon_path)) { + QMessageBox::critical( + this, tr("Create Icon"), + tr("Cannot create icon file. Path \"%1\" does not exist and cannot be created.") + .arg(QString::fromStdString(out_icon_path.string())), + QMessageBox::StandardButton::Ok); + out_icon_path.clear(); + return false; + } + + // Create icon file path + out_icon_path /= (program_id == 0 ? fmt::format("eden-{}.{}", game_file_name, ico_extension) + : fmt::format("eden-{:016X}.{}", program_id, ico_extension)); + return true; +} + void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& game_path, - const QtCommon::Game::ShortcutTarget target) { + GameListShortcutTarget target) { // Create shortcut std::string arguments = fmt::format("-g \"{:s}\"", game_path); - QtCommon::Game::CreateShortcut(game_path, program_id, "", target, arguments, true); + CreateShortcut(game_path, program_id, "", target, arguments, true); } void GMainWindow::OnGameListOpenDirectory(const QString& directory) { @@ -2831,8 +3305,8 @@ void GMainWindow::OnGameListShowList(bool show) { void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { u64 title_id{}; - const auto v_file = Core::GetGameFileFromPath(QtCommon::vfs, file); - const auto loader = Loader::GetLoader(*QtCommon::system, v_file); + const auto v_file = Core::GetGameFileFromPath(vfs, file); + const auto loader = Loader::GetLoader(*system, v_file); if (loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { QMessageBox::information(this, tr("Properties"), @@ -2959,8 +3433,8 @@ void GMainWindow::OnMenuInstallToNAND() { } return false; }; - future = QtConcurrent::run([&file, progress_callback] { - return ContentManager::InstallNSP(*QtCommon::system, *QtCommon::vfs, file.toStdString(), + future = QtConcurrent::run([this, &file, progress_callback] { + return ContentManager::InstallNSP(*system, *vfs, file.toStdString(), progress_callback); }); @@ -3052,7 +3526,7 @@ ContentManager::InstallResult GMainWindow::InstallNCA(const QString& filename) { } const bool is_application = index >= static_cast(FileSys::TitleType::Application); - const auto& fs_controller = QtCommon::system->GetFileSystemController(); + const auto& fs_controller = system->GetFileSystemController(); auto* registered_cache = is_application ? fs_controller.GetUserNANDContents() : fs_controller.GetSystemNANDContents(); @@ -3063,7 +3537,7 @@ ContentManager::InstallResult GMainWindow::InstallNCA(const QString& filename) { } return false; }; - return ContentManager::InstallNCA(*QtCommon::vfs, filename.toStdString(), *registered_cache, + return ContentManager::InstallNCA(*vfs, filename.toStdString(), *registered_cache, static_cast(index), progress_callback); } @@ -3092,7 +3566,7 @@ void GMainWindow::OnStartGame() { UpdateMenuState(); OnTasStateChanged(); - play_time_manager->SetProgramId(QtCommon::system->GetApplicationProcessProgramID()); + play_time_manager->SetProgramId(system->GetApplicationProcessProgramID()); play_time_manager->Start(); discord_rpc->Update(); @@ -3103,7 +3577,7 @@ void GMainWindow::OnStartGame() { } void GMainWindow::OnRestartGame() { - if (!QtCommon::system->IsPoweredOn()) { + if (!system->IsPoweredOn()) { return; } @@ -3151,7 +3625,7 @@ void GMainWindow::OnStopGame() { bool GMainWindow::ConfirmShutdownGame() { if (UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Always) { - if (QtCommon::system->GetExitLocked()) { + if (system->GetExitLocked()) { if (!ConfirmForceLockedExit()) { return false; } @@ -3163,7 +3637,7 @@ bool GMainWindow::ConfirmShutdownGame() { } else { if (UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Based_On_Game && - QtCommon::system->GetExitLocked()) { + system->GetExitLocked()) { if (!ConfirmForceLockedExit()) { return false; } @@ -3190,12 +3664,12 @@ void GMainWindow::OnExit() { } void GMainWindow::OnSaveConfig() { - QtCommon::system->ApplySettings(); + system->ApplySettings(); config->SaveAllValues(); } void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_text) { - error_applet = new OverlayDialog(render_window, *QtCommon::system, error_code, error_text, QString{}, + error_applet = new OverlayDialog(render_window, *system, error_code, error_text, QString{}, tr("OK"), Qt::AlignLeft | Qt::AlignVCenter); SCOPE_EXIT { error_applet->deleteLater(); @@ -3424,7 +3898,7 @@ void GMainWindow::OnConfigure() { Settings::SetConfiguringGlobal(true); ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(), - vk_device_records, *QtCommon::system, + vk_device_records, *system, !multiplayer_state->IsHostingPublicRoom()); connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, &GMainWindow::OnLanguageChanged); @@ -3525,7 +3999,7 @@ void GMainWindow::OnConfigure() { UpdateStatusButtons(); controller_dialog->refreshConfiguration(); - QtCommon::system->ApplySettings(); + system->ApplySettings(); } void GMainWindow::OnConfigureTas() { @@ -3533,7 +4007,7 @@ void GMainWindow::OnConfigureTas() { const auto result = dialog.exec(); if (result != QDialog::Accepted && !UISettings::values.configuration_applied) { - Settings::RestoreGlobalState(QtCommon::system->IsPoweredOn()); + Settings::RestoreGlobalState(system->IsPoweredOn()); return; } else if (result == QDialog::Accepted) { dialog.ApplyConfiguration(); @@ -3547,7 +4021,7 @@ void GMainWindow::OnTasStartStop() { } // Disable system buttons to prevent TAS from executing a hotkey - auto* controller = QtCommon::system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); controller->ResetSystemButtons(); input_subsystem->GetTas()->StartStop(); @@ -3563,7 +4037,7 @@ void GMainWindow::OnTasRecord() { } // Disable system buttons to prevent TAS from recording a hotkey - auto* controller = QtCommon::system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* controller = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); controller->ResetSystemButtons(); const bool is_recording = input_subsystem->GetTas()->Record(); @@ -3585,8 +4059,8 @@ void GMainWindow::OnTasReset() { void GMainWindow::OnToggleDockedMode() { const bool is_docked = Settings::IsDockedMode(); - auto* player_1 = QtCommon::system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* handheld = QtCommon::system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); if (!is_docked && handheld->IsConnected()) { QMessageBox::warning(this, tr("Invalid config detected"), @@ -3601,7 +4075,7 @@ void GMainWindow::OnToggleDockedMode() { Settings::values.use_docked_mode.SetValue(is_docked ? Settings::ConsoleMode::Handheld : Settings::ConsoleMode::Docked); UpdateDockedButton(); - OnDockedModeChanged(is_docked, !is_docked, *QtCommon::system); + OnDockedModeChanged(is_docked, !is_docked, *system); } void GMainWindow::OnToggleGpuAccuracy() { @@ -3618,7 +4092,7 @@ void GMainWindow::OnToggleGpuAccuracy() { } } - QtCommon::system->ApplySettings(); + system->ApplySettings(); UpdateGPUAccuracyButton(); } @@ -3637,7 +4111,7 @@ void GMainWindow::OnDecreaseVolume() { if (current_volume <= 6) { step = 1; } - Settings::values.volume.SetValue((std::max)(current_volume - step, 0)); + Settings::values.volume.SetValue(std::max(current_volume - step, 0)); UpdateVolumeUI(); } @@ -3683,20 +4157,20 @@ void GMainWindow::OnToggleGraphicsAPI() { } void GMainWindow::OnConfigurePerGame() { - const u64 title_id = QtCommon::system->GetApplicationProcessProgramID(); + const u64 title_id = system->GetApplicationProcessProgramID(); OpenPerGameConfiguration(title_id, current_game_path.toStdString()); } void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) { - const auto v_file = Core::GetGameFileFromPath(QtCommon::vfs, file_name); + const auto v_file = Core::GetGameFileFromPath(vfs, file_name); Settings::SetConfiguringGlobal(false); - ConfigurePerGame dialog(this, title_id, file_name, vk_device_records, *QtCommon::system); + ConfigurePerGame dialog(this, title_id, file_name, vk_device_records, *system); dialog.LoadFromFile(v_file); const auto result = dialog.exec(); if (result != QDialog::Accepted && !UISettings::values.configuration_applied) { - Settings::RestoreGlobalState(QtCommon::system->IsPoweredOn()); + Settings::RestoreGlobalState(system->IsPoweredOn()); return; } else if (result == QDialog::Accepted) { dialog.ApplyConfiguration(); @@ -3708,9 +4182,9 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file } // Do not cause the global config to write local settings into the config file - const bool is_powered_on = QtCommon::system->IsPoweredOn(); + const bool is_powered_on = system->IsPoweredOn(); Settings::RestoreGlobalState(is_powered_on); - QtCommon::system->HIDCore().ReloadInputDevices(); + system->HIDCore().ReloadInputDevices(); UISettings::values.configuration_applied = false; @@ -3754,7 +4228,6 @@ void GMainWindow::OnLoadAmiibo() { LoadAmiibo(filename); } -// TODO(crueter): does this need to be ported to QML? bool GMainWindow::question(QWidget* parent, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { @@ -3765,7 +4238,7 @@ bool GMainWindow::question(QWidget* parent, const QString& title, const QString& box_dialog->setDefaultButton(defaultButton); ControllerNavigation* controller_navigation = - new ControllerNavigation(QtCommon::system->HIDCore(), box_dialog); + new ControllerNavigation(system->HIDCore(), box_dialog); connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent, [box_dialog](Qt::Key key) { QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); @@ -3806,35 +4279,182 @@ void GMainWindow::LoadAmiibo(const QString& filename) { } void GMainWindow::OnOpenRootDataFolder() { - QtCommon::Game::OpenRootDataFolder(); + QDesktopServices::openUrl( + QUrl(QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::EdenDir)))); } -void GMainWindow::OnOpenNANDFolder() -{ - QtCommon::Game::OpenNANDFolder(); +void GMainWindow::OnOpenNANDFolder() { + QDesktopServices::openUrl(QUrl::fromLocalFile( + QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::NANDDir)))); } -void GMainWindow::OnOpenSDMCFolder() -{ - QtCommon::Game::OpenSDMCFolder(); +void GMainWindow::OnOpenSDMCFolder() { + QDesktopServices::openUrl(QUrl::fromLocalFile( + QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::SDMCDir)))); } -void GMainWindow::OnOpenModFolder() -{ - QtCommon::Game::OpenModFolder(); +void GMainWindow::OnOpenModFolder() { + QDesktopServices::openUrl(QUrl::fromLocalFile( + QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::LoadDir)))); } -void GMainWindow::OnOpenLogFolder() -{ - QtCommon::Game::OpenLogFolder(); +void GMainWindow::OnOpenLogFolder() { + QDesktopServices::openUrl(QUrl::fromLocalFile( + QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::LogDir)))); } void GMainWindow::OnVerifyInstalledContents() { - QtCommon::Content::VerifyInstalledContents(); + // Initialize a progress dialog. + QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); + progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(100); + progress.setAutoClose(false); + progress.setAutoReset(false); + + // Declare progress callback. + auto QtProgressCallback = [&](size_t total_size, size_t processed_size) { + progress.setValue(static_cast((processed_size * 100) / total_size)); + return progress.wasCanceled(); + }; + + const std::vector result = + ContentManager::VerifyInstalledContents(*system, *provider, QtProgressCallback); + progress.close(); + + if (result.empty()) { + QMessageBox::information(this, tr("Integrity verification succeeded!"), + tr("The operation completed successfully.")); + } else { + const auto failed_names = + QString::fromStdString(fmt::format("{}", fmt::join(result, "\n"))); + QMessageBox::critical( + this, tr("Integrity verification failed!"), + tr("Verification failed for the following files:\n\n%1").arg(failed_names)); + } } void GMainWindow::InstallFirmware(const QString& location, bool recursive) { - QtCommon::Content::InstallFirmware(location, recursive); + QProgressDialog progress(tr("Installing Firmware..."), tr("Cancel"), 0, 100, this); + progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(100); + progress.setAutoClose(false); + progress.setAutoReset(false); + progress.show(); + + // Declare progress callback. + auto QtProgressCallback = [&](size_t total_size, size_t processed_size) { + progress.setValue(static_cast((processed_size * 100) / total_size)); + return progress.wasCanceled(); + }; + + LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString()); + + // Check for a reasonable number of .nca files (don't hardcode them, just see if there's some in + // there.) + std::filesystem::path firmware_source_path = location.toStdString(); + if (!Common::FS::IsDir(firmware_source_path)) { + progress.close(); + return; + } + + std::vector out; + const Common::FS::DirEntryCallable callback = + [&out](const std::filesystem::directory_entry& entry) { + if (entry.path().has_extension() && entry.path().extension() == ".nca") { + out.emplace_back(entry.path()); + } + + return true; + }; + + QtProgressCallback(100, 10); + + if (recursive) { + Common::FS::IterateDirEntriesRecursively(firmware_source_path, callback, + Common::FS::DirEntryFilter::File); + } else { + Common::FS::IterateDirEntries(firmware_source_path, callback, + Common::FS::DirEntryFilter::File); + } + + if (out.size() <= 0) { + progress.close(); + QMessageBox::warning(this, tr("Firmware install failed"), + tr("Unable to locate potential firmware NCA files")); + return; + } + + // Locate and erase the content of nand/system/Content/registered/*.nca, if any. + auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory(); + if (!sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) { + progress.close(); + QMessageBox::critical(this, tr("Firmware install failed"), + tr("Failed to delete one or more firmware file.")); + return; + } + + LOG_INFO(Frontend, + "Cleaned nand/system/Content/registered folder in preparation for new firmware."); + + QtProgressCallback(100, 20); + + auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered"); + + bool success = true; + int i = 0; + for (const auto& firmware_src_path : out) { + i++; + auto firmware_src_vfile = + vfs->OpenFile(firmware_src_path.generic_string(), FileSys::OpenMode::Read); + auto firmware_dst_vfile = + firmware_vdir->CreateFileRelative(firmware_src_path.filename().string()); + + if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) { + LOG_ERROR(Frontend, "Failed to copy firmware file {} to {} in registered folder!", + firmware_src_path.generic_string(), firmware_src_path.filename().string()); + success = false; + } + + if (QtProgressCallback( + 100, 20 + static_cast(((i) / static_cast(out.size())) * 70.0))) { + progress.close(); + QMessageBox::warning( + this, tr("Firmware install failed"), + tr("Firmware installation cancelled, firmware may be in a bad state or corrupted. " + "Restart Eden or re-install firmware.")); + return; + } + } + + if (!success) { + progress.close(); + QMessageBox::critical(this, tr("Firmware install failed"), + tr("One or more firmware files failed to copy into NAND.")); + return; + } + + // Re-scan VFS for the newly placed firmware files. + system->GetFileSystemController().CreateFactories(*vfs); + + auto VerifyFirmwareCallback = [&](size_t total_size, size_t processed_size) { + progress.setValue(90 + static_cast((processed_size * 10) / total_size)); + return progress.wasCanceled(); + }; + + auto result = + ContentManager::VerifyInstalledContents(*system, *provider, VerifyFirmwareCallback, true); + + if (result.size() > 0) { + const auto failed_names = + QString::fromStdString(fmt::format("{}", fmt::join(result, "\n"))); + progress.close(); + QMessageBox::critical( + this, tr("Firmware integrity verification failed!"), + tr("Verification failed for the following files:\n\n%1").arg(failed_names)); + return; + } + + progress.close(); OnCheckFirmwareDecryption(); } @@ -3881,14 +4501,32 @@ void GMainWindow::OnInstallFirmwareFromZIP() { return; } - const QString qCacheDir = QtCommon::Content::UnzipFirmwareToTmp(firmware_zip_location); + namespace fs = std::filesystem; + fs::path tmp{std::filesystem::temp_directory_path()}; - // In this case, it has to be done recursively, since sometimes people - // will pack it into a subdirectory after dumping - if (!qCacheDir.isEmpty()) { + if (!std::filesystem::create_directories(tmp / "eden" / "firmware")) { + goto unzipFailed; + } + + { + tmp /= "eden"; + tmp /= "firmware"; + + QString qCacheDir = QString::fromStdString(tmp.string()); + + QFile zip(firmware_zip_location); + + QStringList result = JlCompress::extractDir(&zip, qCacheDir); + if (result.isEmpty()) { + goto unzipFailed; + } + + // In this case, it has to be done recursively, since sometimes people + // will pack it into a subdirectory after dumping InstallFirmware(qCacheDir, true); + std::error_code ec; - std::filesystem::remove_all(std::filesystem::temp_directory_path() / "eden" / "firmware", ec); + std::filesystem::remove_all(tmp, ec); if (ec) { QMessageBox::warning(this, tr("Firmware cleanup failed"), @@ -3897,7 +4535,14 @@ void GMainWindow::OnInstallFirmwareFromZIP() { "again.\nOS reported error: %1") .arg(QString::fromStdString(ec.message()))); } + + return; } +unzipFailed: + QMessageBox::critical( + this, tr("Firmware unzip failed"), + tr("Check write permissions in the system temp directory and try again.")); + return; } void GMainWindow::OnInstallDecryptionKeys() { @@ -3906,9 +4551,30 @@ void GMainWindow::OnInstallDecryptionKeys() { return; } - QtCommon::Content::InstallKeys(); + const QString key_source_location = QFileDialog::getOpenFileName( + this, tr("Select Dumped Keys Location"), {}, QStringLiteral("Decryption Keys (*.keys)"), {}, + QFileDialog::ReadOnly); + if (key_source_location.isEmpty()) { + return; + } + FirmwareManager::KeyInstallResult result = + FirmwareManager::InstallKeys(key_source_location.toStdString(), "keys"); + + system->GetFileSystemController().CreateFactories(*vfs); game_list->PopulateAsync(UISettings::values.game_dirs); + + switch (result) { + case FirmwareManager::KeyInstallResult::Success: + QMessageBox::information(this, tr("Decryption Keys install succeeded"), + tr("Decryption Keys were successfully installed")); + break; + default: + QMessageBox::critical(this, tr("Decryption Keys install failed"), + tr(FirmwareManager::GetKeyInstallResultString(result))); + break; + } + OnCheckFirmwareDecryption(); } @@ -3935,20 +4601,18 @@ void GMainWindow::OnToggleStatusBar() { statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); } -void GMainWindow::OnGameListRefresh() -{ - // Resets metadata cache and reloads - QtCommon::Game::ResetMetadata(); - game_list->RefreshGameDirectory(); +void GMainWindow::OnGameListRefresh() { + // force reload add-ons etc + game_list->ForceRefreshGameDirectory(); SetFirmwareVersion(); } void GMainWindow::OnAlbum() { constexpr u64 AlbumId = static_cast(Service::AM::AppletProgramId::PhotoViewer); - auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents(); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { QMessageBox::warning(this, tr("No firmware available"), - tr("Please install firmware to use the Album applet.")); + tr("Please install the firmware to use the Album applet.")); return; } @@ -3959,7 +4623,7 @@ void GMainWindow::OnAlbum() { return; } - QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::PhotoViewer); + system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::PhotoViewer); const auto filename = QString::fromStdString(album_nca->GetFullPath()); UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); @@ -3968,10 +4632,10 @@ void GMainWindow::OnAlbum() { void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { constexpr u64 CabinetId = static_cast(Service::AM::AppletProgramId::Cabinet); - auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents(); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { QMessageBox::warning(this, tr("No firmware available"), - tr("Please install firmware to use the Cabinet applet.")); + tr("Please install the firmware to use the Cabinet applet.")); return; } @@ -3982,8 +4646,8 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { return; } - QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Cabinet); - QtCommon::system->GetFrontendAppletHolder().SetCabinetMode(mode); + system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Cabinet); + system->GetFrontendAppletHolder().SetCabinetMode(mode); const auto filename = QString::fromStdString(cabinet_nca->GetFullPath()); UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); @@ -3992,10 +4656,10 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { void GMainWindow::OnMiiEdit() { constexpr u64 MiiEditId = static_cast(Service::AM::AppletProgramId::MiiEdit); - auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents(); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { QMessageBox::warning(this, tr("No firmware available"), - tr("Please install firmware to use the Mii editor.")); + tr("Please install the firmware to use the Mii editor.")); return; } @@ -4006,7 +4670,7 @@ void GMainWindow::OnMiiEdit() { return; } - QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::MiiEdit); + system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::MiiEdit); const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); @@ -4015,10 +4679,10 @@ void GMainWindow::OnMiiEdit() { void GMainWindow::OnOpenControllerMenu() { constexpr u64 ControllerAppletId = static_cast(Service::AM::AppletProgramId::Controller); - auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents(); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { QMessageBox::warning(this, tr("No firmware available"), - tr("Please install firmware to use the Controller Menu.")); + tr("Please install the firmware to use the Controller Menu.")); return; } @@ -4030,7 +4694,7 @@ void GMainWindow::OnOpenControllerMenu() { return; } - QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Controller); + system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Controller); const auto filename = QString::fromStdString((controller_applet_nca->GetFullPath())); UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); @@ -4039,7 +4703,7 @@ void GMainWindow::OnOpenControllerMenu() { } void GMainWindow::OnHomeMenu() { - auto result = FirmwareManager::VerifyFirmware(*QtCommon::system.get()); + auto result = FirmwareManager::VerifyFirmware(*system.get()); switch (result) { case FirmwareManager::ErrorFirmwareMissing: @@ -4074,7 +4738,7 @@ void GMainWindow::OnHomeMenu() { } constexpr u64 QLaunchId = static_cast(Service::AM::AppletProgramId::QLaunch); - auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents(); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); if (!qlaunch_applet_nca) { @@ -4083,7 +4747,7 @@ void GMainWindow::OnHomeMenu() { return; } - QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::QLaunch); + system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::QLaunch); const auto filename = QString::fromStdString((qlaunch_applet_nca->GetFullPath())); UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); @@ -4092,10 +4756,10 @@ void GMainWindow::OnHomeMenu() { void GMainWindow::OnInitialSetup() { constexpr u64 Starter = static_cast(Service::AM::AppletProgramId::Starter); - auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents(); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { QMessageBox::warning(this, tr("No firmware available"), - tr("Please install firmware to use Starter.")); + tr("Please install the firmware to use Starter.")); return; } @@ -4106,7 +4770,7 @@ void GMainWindow::OnInitialSetup() { return; } - QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Starter); + system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::Starter); const auto filename = QString::fromStdString((qlaunch_nca->GetFullPath())); UISettings::values.roms_path = QFileInfo(filename).path().toStdString(); @@ -4114,11 +4778,158 @@ void GMainWindow::OnInitialSetup() { } void GMainWindow::OnCreateHomeMenuDesktopShortcut() { - QtCommon::Game::CreateHomeMenuShortcut(QtCommon::Game::ShortcutTarget::Desktop); + OnCreateHomeMenuShortcut(GameListShortcutTarget::Desktop); } void GMainWindow::OnCreateHomeMenuApplicationMenuShortcut() { - QtCommon::Game::CreateHomeMenuShortcut(QtCommon::Game::ShortcutTarget::Applications); + OnCreateHomeMenuShortcut(GameListShortcutTarget::Applications); +} + +std::filesystem::path GMainWindow::GetEdenCommand() { + std::filesystem::path command; + + QString appimage = QString::fromLocal8Bit(getenv("APPIMAGE")); + if (!appimage.isEmpty()) { + command = std::filesystem::path{appimage.toStdString()}; + } else { + const QStringList args = QApplication::arguments(); + command = args[0].toStdString(); + } + + // If relative path, make it an absolute path + if (command.c_str()[0] == '.') { + command = Common::FS::GetCurrentDir() / command; + } + + return command; +} + +std::filesystem::path GMainWindow::GetShortcutPath(GameListShortcutTarget target) { + std::filesystem::path shortcut_path{}; + if (target == GameListShortcutTarget::Desktop) { + shortcut_path = + QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString(); + } else if (target == GameListShortcutTarget::Applications) { + shortcut_path = + QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString(); + } + + return shortcut_path; +} + +void GMainWindow::CreateShortcut(const std::string& game_path, const u64 program_id, + const std::string& game_title_, GameListShortcutTarget target, + std::string arguments_, const bool needs_title) { + // Get path to yuzu executable + std::filesystem::path command = GetEdenCommand(); + + // Shortcut path + std::filesystem::path shortcut_path = GetShortcutPath(target); + + if (!std::filesystem::exists(shortcut_path)) { + GMainWindow::CreateShortcutMessagesGUI( + this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, + QString::fromStdString(shortcut_path.generic_string())); + LOG_ERROR(Frontend, "Invalid shortcut target {}", shortcut_path.generic_string()); + return; + } + + const FileSys::PatchManager pm{program_id, system->GetFileSystemController(), + system->GetContentProvider()}; + const auto control = pm.GetControlMetadata(); + const auto loader = + Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::OpenMode::Read)); + + std::string game_title{game_title_}; + + // Delete illegal characters from title + if (needs_title) { + game_title = fmt::format("{:016X}", program_id); + if (control.first != nullptr) { + game_title = control.first->GetApplicationName(); + } else { + loader->ReadTitle(game_title); + } + } + + const std::string illegal_chars = "<>:\"/\\|?*."; + for (auto it = game_title.rbegin(); it != game_title.rend(); ++it) { + if (illegal_chars.find(*it) != std::string::npos) { + game_title.erase(it.base() - 1); + } + } + + const QString qgame_title = QString::fromStdString(game_title); + + // Get icon from game file + std::vector icon_image_file{}; + if (control.second != nullptr) { + icon_image_file = control.second->ReadAllBytes(); + } else if (loader->ReadIcon(icon_image_file) != Loader::ResultStatus::Success) { + LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path); + } + + QImage icon_data = + QImage::fromData(icon_image_file.data(), static_cast(icon_image_file.size())); + std::filesystem::path out_icon_path; + if (GMainWindow::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) { + if (!SaveIconToFile(out_icon_path, icon_data)) { + LOG_ERROR(Frontend, "Could not write icon to file"); + } + } + +#if defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) + // Special case for AppImages + // Warn once if we are making a shortcut to a volatile AppImage + if (command.string().ends_with(".AppImage") && !UISettings::values.shortcut_already_warned) { + if (!GMainWindow::CreateShortcutMessagesGUI( + this, GMainWindow::CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, qgame_title)) { + return; + } + UISettings::values.shortcut_already_warned = true; + } +#endif + + // Create shortcut + std::string arguments{arguments_}; + if (GMainWindow::CreateShortcutMessagesGUI( + this, GMainWindow::CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, qgame_title)) { + arguments = "-f " + arguments; + } + const std::string comment = fmt::format("Start {:s} with the eden Emulator", game_title); + const std::string categories = "Game;Emulator;Qt;"; + const std::string keywords = "Switch;Nintendo;"; + + if (GMainWindow::CreateShortcutLink(shortcut_path, comment, out_icon_path, command, arguments, + categories, keywords, game_title)) { + GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_SUCCESS, + qgame_title); + return; + } + GMainWindow::CreateShortcutMessagesGUI(this, GMainWindow::CREATE_SHORTCUT_MSGBOX_ERROR, + qgame_title); +} + +void GMainWindow::OnCreateHomeMenuShortcut(GameListShortcutTarget target) { + constexpr u64 QLaunchId = static_cast(Service::AM::AppletProgramId::QLaunch); + auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); + if (!bis_system) { + QMessageBox::warning(this, tr("No firmware available"), + tr("Please install firmware to use the home menu.")); + return; + } + + auto qlaunch_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); + if (!qlaunch_nca) { + QMessageBox::warning(this, tr("Home Menu Applet"), + tr("Home Menu is not available. Please reinstall firmware.")); + return; + } + + auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); + const auto game_path = qlaunch_applet_nca->GetFullPath(); + + CreateShortcut(game_path, QLaunchId, "Switch Home Menu", target, "-qlaunch", false); } void GMainWindow::OnCaptureScreenshot() { @@ -4126,7 +4937,7 @@ void GMainWindow::OnCaptureScreenshot() { return; } - const u64 title_id = QtCommon::system->GetApplicationProcessProgramID(); + const u64 title_id = system->GetApplicationProcessProgramID(); const auto screenshot_path = QString::fromStdString(Common::FS::GetEdenPathString(Common::FS::EdenPath::ScreenshotsDir)); const auto date = @@ -4205,15 +5016,14 @@ void GMainWindow::OnEmulatorUpdateAvailable() { 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 compiler = std::string(Common::g_compiler_id); + const auto description = std::string(Common::g_build_version); + const auto build_id = std::string(Common::g_build_id); std::string yuzu_title; if (Common::g_is_dev_build) { - yuzu_title = fmt::format("Eden Nightly | {}-{} | {}", description, build_id, compiler); + yuzu_title = fmt::format("Eden Nightly | {}-{}", description, build_id); } else { - yuzu_title = fmt::format("Eden | {} | {}", description, compiler); + yuzu_title = fmt::format("Eden | {}", description); } const auto override_title = @@ -4288,7 +5098,7 @@ void GMainWindow::OnTasStateChanged() { } void GMainWindow::UpdateStatusBar() { - if (emu_thread == nullptr || !QtCommon::system->IsPoweredOn()) { + if (emu_thread == nullptr || !system->IsPoweredOn()) { status_bar_update_timer.stop(); return; } @@ -4299,8 +5109,8 @@ void GMainWindow::UpdateStatusBar() { tas_label->clear(); } - auto results = QtCommon::system->GetAndResetPerfStats(); - auto& shader_notify = QtCommon::system->GPU().ShaderNotify(); + auto results = system->GetAndResetPerfStats(); + auto& shader_notify = system->GPU().ShaderNotify(); const int shaders_building = shader_notify.ShadersBuilding(); if (shaders_building > 0) { @@ -4446,6 +5256,7 @@ void GMainWindow::OnMouseActivity() { } void GMainWindow::OnCheckFirmwareDecryption() { + system->GetFileSystemController().CreateFactories(*vfs); if (!ContentManager::AreKeysPresent()) { QMessageBox::warning(this, tr("Derivation Components Missing"), tr("Encryption keys are missing.")); @@ -4455,11 +5266,11 @@ void GMainWindow::OnCheckFirmwareDecryption() { } bool GMainWindow::CheckFirmwarePresence() { - return FirmwareManager::CheckFirmwarePresence(*QtCommon::system.get()); + return FirmwareManager::CheckFirmwarePresence(*system.get()); } void GMainWindow::SetFirmwareVersion() { - const auto pair = FirmwareManager::GetFirmwareVersion(*QtCommon::system.get()); + const auto pair = FirmwareManager::GetFirmwareVersion(*system.get()); const auto firmware_data = pair.first; const auto result = pair.second; @@ -4474,7 +5285,7 @@ void GMainWindow::SetFirmwareVersion() { const std::string display_version(firmware_data.display_version.data()); const std::string display_title(firmware_data.display_title.data()); - LOG_INFO(Frontend, "Installed firmware: {}", display_version); + LOG_INFO(Frontend, "Installed firmware: {}", display_title); firmware_label->setText(QString::fromStdString(display_version)); firmware_label->setToolTip(QString::fromStdString(display_title)); @@ -4545,7 +5356,7 @@ bool GMainWindow::ConfirmClose() { UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Never) { return true; } - if (!QtCommon::system->GetExitLocked() && + if (!system->GetExitLocked() && UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Based_On_Game) { return true; } @@ -4575,7 +5386,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { render_window->close(); multiplayer_state->Close(); - QtCommon::system->HIDCore().UnloadInputDevices(); + system->HIDCore().UnloadInputDevices(); Network::Shutdown(); QWidget::closeEvent(event); @@ -4646,12 +5457,12 @@ bool GMainWindow::ConfirmForceLockedExit() { } void GMainWindow::RequestGameExit() { - if (!QtCommon::system->IsPoweredOn()) { + if (!system->IsPoweredOn()) { return; } - QtCommon::system->SetExitRequested(true); - QtCommon::system->GetAppletManager().RequestExit(); + system->SetExitRequested(true); + system->GetAppletManager().RequestExit(); } void GMainWindow::filterBarSetChecked(bool state) { @@ -4761,7 +5572,7 @@ void GMainWindow::OnLanguageChanged(const QString& locale) { void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) { #ifdef USE_DISCORD_PRESENCE if (state) { - discord_rpc = std::make_unique(*QtCommon::system); + discord_rpc = std::make_unique(*system); } else { discord_rpc = std::make_unique(); } @@ -4824,13 +5635,13 @@ void VolumeButton::wheelEvent(QWheelEvent* event) { if (num_steps > 0) { Settings::values.volume.SetValue( - (std::min)(200, Settings::values.volume.GetValue() + num_steps)); + std::min(200, Settings::values.volume.GetValue() + num_steps)); } else { Settings::values.volume.SetValue( - (std::max)(0, Settings::values.volume.GetValue() + num_steps)); + std::max(0, Settings::values.volume.GetValue() + num_steps)); } - scroll_multiplier = (std::min)(MaxMultiplier, scroll_multiplier * 2); + scroll_multiplier = std::min(MaxMultiplier, scroll_multiplier * 2); scroll_timer.start(100); // reset the multiplier if no scroll event occurs within 100 ms emit VolumeChanged(); @@ -4871,11 +5682,11 @@ static void SetHighDPIAttributes() { constexpr float minimum_width = 1350.0f; constexpr float minimum_height = 900.0f; - const float width_ratio = (std::max)(1.0f, real_width / minimum_width); - const float height_ratio = (std::max)(1.0f, real_height / minimum_height); + const float width_ratio = std::max(1.0f, real_width / minimum_width); + const float height_ratio = std::max(1.0f, real_height / minimum_height); // Get the lower of the 2 ratios and truncate, this is the maximum integer scale. - const float max_ratio = std::trunc((std::min)(width_ratio, height_ratio)); + const float max_ratio = std::trunc(std::min(width_ratio, height_ratio)); if (max_ratio > real_ratio) { QApplication::setHighDpiScaleFactorRoundingPolicy( diff --git a/src/yuzu/main.h b/src/yuzu/main.h index e3922759b0..b1c5669a41 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -17,10 +17,9 @@ #include #include "common/common_types.h" +#include "configuration/qt_config.h" #include "frontend_common/content_manager.h" #include "input_common/drivers/tas_input.h" -#include "qt_common/qt_config.h" -#include "qt_common/qt_game_util.h" #include "user_data_migration.h" #include "yuzu/compatibility_list.h" #include "yuzu/hotkeys.h" @@ -54,7 +53,10 @@ class QSlider; class QHBoxLayout; class WaitTreeWidget; enum class GameListOpenTarget; +enum class GameListRemoveTarget; +enum class GameListShortcutTarget; enum class DumpRomFSTarget; +enum class InstalledEntryType; class GameListPlaceholder; class QtAmiiboSettingsDialog; @@ -70,6 +72,7 @@ enum class StartGameType { namespace Core { enum class SystemResultStatus : u32; +class System; } // namespace Core namespace Core::Frontend { @@ -160,6 +163,13 @@ class GMainWindow : public QMainWindow { /// Max number of recently loaded items to keep track of static const int max_recent_files_item = 10; + enum { + CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, + CREATE_SHORTCUT_MSGBOX_SUCCESS, + CREATE_SHORTCUT_MSGBOX_ERROR, + CREATE_SHORTCUT_MSGBOX_APPVOLATILE_WARNING, + }; + public: void filterBarSetChecked(bool state); void UpdateUITheme(); @@ -169,7 +179,7 @@ public: bool DropAction(QDropEvent* event); void AcceptDropEvent(QDropEvent* event); - std::filesystem::path GetShortcutPath(QtCommon::Game::ShortcutTarget target); + std::filesystem::path GetShortcutPath(GameListShortcutTarget target); signals: @@ -248,6 +258,8 @@ private: void LinkActionShortcut(QAction* action, const QString& action_name, const bool tas_allowed = false); + void RegisterMetaTypes(); + void InitializeWidgets(); void InitializeDebugWidgets(); void InitializeRecentFileMenuActions(); @@ -341,8 +353,9 @@ private slots: void OnGameListLoadFile(QString game_path, u64 program_id); void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target, const std::string& game_path); - void OnGameListRemoveInstalledEntry(u64 program_id, QtCommon::Game::InstalledEntryType type); - void OnGameListRemoveFile(u64 program_id, QtCommon::Game::GameListRemoveTarget target, + void OnTransferableShaderCacheOpenFile(u64 program_id); + void OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type); + void OnGameListRemoveFile(u64 program_id, GameListRemoveTarget target, const std::string& game_path); void OnGameListRemovePlayTimeData(u64 program_id); void OnGameListDumpRomFS(u64 program_id, const std::string& game_path, DumpRomFSTarget target); @@ -350,9 +363,8 @@ private slots: void OnGameListCopyTID(u64 program_id); void OnGameListNavigateToGamedbEntry(u64 program_id, const CompatibilityList& compatibility_list); - void OnGameListCreateShortcut(u64 program_id, - const std::string& game_path, - const QtCommon::Game::ShortcutTarget target); + void OnGameListCreateShortcut(u64 program_id, const std::string& game_path, + GameListShortcutTarget target); void OnGameListOpenDirectory(const QString& directory); void OnGameListAddDirectory(); void OnGameListShowList(bool show); @@ -409,6 +421,7 @@ private slots: void OnInitialSetup(); void OnCreateHomeMenuDesktopShortcut(); void OnCreateHomeMenuApplicationMenuShortcut(); + void OnCreateHomeMenuShortcut(GameListShortcutTarget target); void OnCaptureScreenshot(); void OnCheckFirmwareDecryption(); void OnLanguageChanged(const QString& locale); @@ -423,7 +436,16 @@ private slots: #endif private: + QString GetGameListErrorRemoving(InstalledEntryType type) const; + void RemoveBaseContent(u64 program_id, InstalledEntryType type); + void RemoveUpdateContent(u64 program_id, InstalledEntryType type); + void RemoveAddOnContent(u64 program_id, InstalledEntryType type); + void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target); + void RemoveVulkanDriverPipelineCache(u64 program_id); + void RemoveAllTransferableShaderCaches(u64 program_id); + void RemoveCustomConfiguration(u64 program_id, const std::string& game_path); void RemovePlayTimeData(u64 program_id); + void RemoveCacheStorage(u64 program_id); bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, u64* selected_title_id, u8* selected_content_record_type); ContentManager::InstallResult InstallNCA(const QString& filename); @@ -456,7 +478,13 @@ private: QString GetTasStateDescription() const; bool CreateShortcutMessagesGUI(QWidget* parent, int imsg, const QString& game_title); - + bool MakeShortcutIcoPath(const u64 program_id, const std::string_view game_file_name, + std::filesystem::path& out_icon_path); + bool CreateShortcutLink(const std::filesystem::path& shortcut_path, const std::string& comment, + const std::filesystem::path& icon_path, + const std::filesystem::path& command, const std::string& arguments, + const std::string& categories, const std::string& keywords, + const std::string& name); /** * Mimic the behavior of QMessageBox::question but link controller navigation to the dialog * The only difference is that it returns a boolean. @@ -470,6 +498,7 @@ private: std::unique_ptr ui; + std::unique_ptr system; std::unique_ptr discord_rpc; std::unique_ptr play_time_manager; std::shared_ptr input_subsystem; @@ -529,6 +558,10 @@ private: QString startup_icon_theme; + // FS + std::shared_ptr vfs; + std::unique_ptr provider; + // Debugger panes WaitTreeWidget* waitTreeWidget; ControllerDialog* controller_dialog; @@ -575,7 +608,7 @@ private: void CreateShortcut(const std::string& game_path, const u64 program_id, const std::string& game_title, - QtCommon::Game::ShortcutTarget target, + GameListShortcutTarget target, std::string arguments, const bool needs_title); diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp index deac3b9e59..30f37c2b4a 100644 --- a/src/yuzu/multiplayer/direct_connect.cpp +++ b/src/yuzu/multiplayer/direct_connect.cpp @@ -21,7 +21,7 @@ #include "yuzu/multiplayer/message.h" #include "yuzu/multiplayer/state.h" #include "yuzu/multiplayer/validation.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" enum class ConnectionType : u8 { TraversalServer, IP }; diff --git a/src/yuzu/multiplayer/host_room.cpp b/src/yuzu/multiplayer/host_room.cpp index 4dd3958550..d8e63da600 100644 --- a/src/yuzu/multiplayer/host_room.cpp +++ b/src/yuzu/multiplayer/host_room.cpp @@ -25,7 +25,7 @@ #include "yuzu/multiplayer/message.h" #include "yuzu/multiplayer/state.h" #include "yuzu/multiplayer/validation.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #ifdef ENABLE_WEB_SERVICE #include "web_service/verify_user_jwt.h" #endif diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp index 84723041df..ed6ba6a15c 100644 --- a/src/yuzu/multiplayer/lobby.cpp +++ b/src/yuzu/multiplayer/lobby.cpp @@ -22,7 +22,7 @@ #include "yuzu/multiplayer/message.h" #include "yuzu/multiplayer/state.h" #include "yuzu/multiplayer/validation.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #ifdef ENABLE_WEB_SERVICE #include "web_service/web_backend.h" #endif diff --git a/src/yuzu/multiplayer/state.cpp b/src/yuzu/multiplayer/state.cpp index 8ff1d991ec..d5529712b0 100644 --- a/src/yuzu/multiplayer/state.cpp +++ b/src/yuzu/multiplayer/state.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2018 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -22,7 +19,7 @@ #include "yuzu/multiplayer/lobby.h" #include "yuzu/multiplayer/message.h" #include "yuzu/multiplayer/state.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #include "yuzu/util/clickable_label.h" MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model_, diff --git a/src/yuzu/play_time_manager.cpp b/src/yuzu/play_time_manager.cpp index 6d06bc7614..2669e3a7ab 100644 --- a/src/yuzu/play_time_manager.cpp +++ b/src/yuzu/play_time_manager.cpp @@ -1,9 +1,7 @@ -// 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 "common/alignment.h" #include "common/fs/file.h" #include "common/fs/fs.h" #include "common/fs/path_util.h" @@ -170,7 +168,7 @@ QString ReadablePlayTime(qulonglong time_seconds) { if (time_seconds == 0) { return {}; } - const auto time_minutes = (std::max)(static_cast(time_seconds) / 60, 1.0); + const auto time_minutes = std::max(static_cast(time_seconds) / 60, 1.0); const auto time_hours = static_cast(time_seconds) / 3600; const bool is_minutes = time_minutes < 60; const char* unit = is_minutes ? "m" : "h"; diff --git a/src/yuzu/play_time_manager.h b/src/yuzu/play_time_manager.h index cd81bdb061..1714b91313 100644 --- a/src/yuzu/play_time_manager.h +++ b/src/yuzu/play_time_manager.h @@ -1,6 +1,3 @@ -// 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 @@ -12,9 +9,8 @@ #include "common/common_funcs.h" #include "common/common_types.h" -#include +#include "common/polyfill_thread.h" -// TODO(crueter): Extract this into frontend_common namespace Service::Account { class ProfileManager; } diff --git a/src/qt_common/qt_common.cpp b/src/yuzu/qt_common.cpp similarity index 55% rename from src/qt_common/qt_common.cpp rename to src/yuzu/qt_common.cpp index 6be241c740..413402165c 100644 --- a/src/qt_common/qt_common.cpp +++ b/src/yuzu/qt_common.cpp @@ -1,19 +1,12 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "qt_common.h" -#include "common/fs/fs.h" +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include #include +#include #include "common/logging/log.h" #include "core/frontend/emu_window.h" - -#include - -#include - -#include +#include "yuzu/qt_common.h" #if !defined(WIN32) && !defined(__APPLE__) #include @@ -22,19 +15,7 @@ #endif namespace QtCommon { - -#ifdef YUZU_QT_WIDGETS -QWidget* rootObject = nullptr; -#else -QObject* rootObject = nullptr; -#endif - -std::unique_ptr system = nullptr; -std::shared_ptr vfs = nullptr; -std::unique_ptr provider = nullptr; - -Core::Frontend::WindowSystemType GetWindowSystemType() -{ +Core::Frontend::WindowSystemType GetWindowSystemType() { // Determine WSI type based on Qt platform. QString platform_name = QGuiApplication::platformName(); if (platform_name == QStringLiteral("windows")) @@ -54,8 +35,7 @@ Core::Frontend::WindowSystemType GetWindowSystemType() return Core::Frontend::WindowSystemType::Windows; } // namespace Core::Frontend::WindowSystemType -Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) -{ +Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) { Core::Frontend::EmuWindow::WindowSystemInfo wsi; wsi.type = GetWindowSystemType(); @@ -63,8 +43,8 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) // Our Win32 Qt external doesn't have the private API. wsi.render_surface = reinterpret_cast(window->winId()); #elif defined(__APPLE__) - wsi.render_surface = reinterpret_cast( - objc_msgSend)(reinterpret_cast(window->winId()), sel_registerName("layer")); + wsi.render_surface = reinterpret_cast(objc_msgSend)( + reinterpret_cast(window->winId()), sel_registerName("layer")); #else QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); wsi.display_connection = pni->nativeResourceForWindow("display", window); @@ -77,46 +57,4 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) return wsi; } - -const QString tr(const char* str) -{ - return QGuiApplication::tr(str); -} - -const QString tr(const std::string& str) -{ - return QGuiApplication::tr(str.c_str()); -} - -#ifdef YUZU_QT_WIDGETS -void Init(QWidget* root) -#else -void Init(QObject* root) -#endif -{ - system = std::make_unique(); - rootObject = root; - vfs = std::make_unique(); - provider = std::make_unique(); -} - -std::filesystem::path GetEdenCommand() { - std::filesystem::path command; - - QString appimage = QString::fromLocal8Bit(getenv("APPIMAGE")); - if (!appimage.isEmpty()) { - command = std::filesystem::path{appimage.toStdString()}; - } else { - const QStringList args = QGuiApplication::arguments(); - command = args[0].toStdString(); - } - - // If relative path, make it an absolute path - if (command.c_str()[0] == '.') { - command = Common::FS::GetCurrentDir() / command; - } - - return command; -} - } // namespace QtCommon diff --git a/src/yuzu/qt_common.h b/src/yuzu/qt_common.h new file mode 100644 index 0000000000..9c63f08f34 --- /dev/null +++ b/src/yuzu/qt_common.h @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "core/frontend/emu_window.h" + +namespace QtCommon { + +Core::Frontend::WindowSystemType GetWindowSystemType(); + +Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window); + +} // namespace QtCommon diff --git a/src/qt_common/uisettings.cpp b/src/yuzu/uisettings.cpp similarity index 99% rename from src/qt_common/uisettings.cpp rename to src/yuzu/uisettings.cpp index a17f3c0a4a..6da5424775 100644 --- a/src/qt_common/uisettings.cpp +++ b/src/yuzu/uisettings.cpp @@ -7,7 +7,7 @@ #include #include "common/fs/fs.h" #include "common/fs/path_util.h" -#include "qt_common/uisettings.h" +#include "yuzu/uisettings.h" #ifndef CANNOT_EXPLICITLY_INSTANTIATE namespace Settings { diff --git a/src/qt_common/uisettings.h b/src/yuzu/uisettings.h similarity index 99% rename from src/qt_common/uisettings.h rename to src/yuzu/uisettings.h index 4981d98dbf..3322b31ca3 100644 --- a/src/qt_common/uisettings.h +++ b/src/yuzu/uisettings.h @@ -17,7 +17,7 @@ #include "common/common_types.h" #include "common/settings.h" #include "common/settings_enums.h" -#include "qt_common/qt_config.h" +#include "configuration/qt_config.h" using Settings::Category; using Settings::ConfirmStop; diff --git a/src/yuzu/user_data_migration.h b/src/yuzu/user_data_migration.h index a3ac2c15d3..3684d14916 100644 --- a/src/yuzu/user_data_migration.h +++ b/src/yuzu/user_data_migration.h @@ -10,7 +10,6 @@ #include #include "migration_worker.h" -// TODO(crueter): Quick implementation class UserDataMigrator { public: UserDataMigrator(QMainWindow* main_window); diff --git a/src/yuzu/util/util.cpp b/src/yuzu/util/util.cpp index 844da5c401..551df7b4cd 100644 --- a/src/yuzu/util/util.cpp +++ b/src/yuzu/util/util.cpp @@ -30,7 +30,7 @@ QString ReadableByteSize(qulonglong size) { return QStringLiteral("0"); } - const int digit_groups = (std::min)(static_cast(std::log10(size) / std::log10(1024)), + const int digit_groups = std::min(static_cast(std::log10(size) / std::log10(1024)), static_cast(units.size())); return QStringLiteral("%L1 %2") .arg(size / std::pow(1024, digit_groups), 0, 'f', 1) diff --git a/src/yuzu/vk_device_info.cpp b/src/yuzu/vk_device_info.cpp index d961d550a1..ab0d39c256 100644 --- a/src/yuzu/vk_device_info.cpp +++ b/src/yuzu/vk_device_info.cpp @@ -1,13 +1,10 @@ -// 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 -#include "qt_common/qt_common.h" +#include "yuzu/qt_common.h" #include "common/dynamic_library.h" #include "common/logging/log.h" diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index a60650bc19..ebd8fd7387 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -1,6 +1,3 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -# SPDX-License-Identifier: GPL-3.0-or-later - # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later @@ -31,7 +28,7 @@ add_executable(yuzu-cmd yuzu.rc ) -target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common video_core) +target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common) target_link_libraries(yuzu-cmd PRIVATE glad) if (MSVC) target_link_libraries(yuzu-cmd PRIVATE getopt) @@ -41,7 +38,7 @@ target_link_libraries(yuzu-cmd PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) create_resource("../../dist/yuzu.bmp" "yuzu_cmd/yuzu_icon.h" "yuzu_icon") target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR}) -target_link_libraries(yuzu-cmd PRIVATE SDL2::SDL2) +target_link_libraries(yuzu-cmd PRIVATE SDL2::SDL2 Vulkan::Headers) if(UNIX AND NOT APPLE) install(TARGETS yuzu-cmd) diff --git a/tools/cpm-fetch-all.sh b/tools/cpm-fetch-all.sh index 66f55df94d..38f7b1f941 100755 --- a/tools/cpm-fetch-all.sh +++ b/tools/cpm-fetch-all.sh @@ -6,6 +6,5 @@ # SPDX-FileCopyrightText: 2025 crueter # SPDX-License-Identifier: GPL-3.0-or-later -LIBS=$(find . externals src/qt_common src/dynarmic -maxdepth 2 -name cpmfile.json -exec jq -j 'keys_unsorted | join(" ")' {} \; -printf " ") - +LIBS=$(find . externals externals/nx_tzdb src/yuzu/externals externals/ffmpeg src/dynarmic/externals -maxdepth 1 -name cpmfile.json -exec jq -j 'keys_unsorted | join(" ")' {} \; -printf " ") tools/cpm-fetch.sh $LIBS \ No newline at end of file diff --git a/tools/cpm-fetch.sh b/tools/cpm-fetch.sh index 996cf76a97..1c2ce007d2 100755 --- a/tools/cpm-fetch.sh +++ b/tools/cpm-fetch.sh @@ -59,7 +59,7 @@ download_package() { if grep -e "patches" <<< "$JSON" > /dev/null; then PATCHES=$(jq -r '.patches | join(" ")' <<< "$JSON") for patch in $PATCHES; do - patch --binary -p1 < "$ROOTDIR"/.patch/$package/$patch + patch -p1 < "$ROOTDIR"/.patch/$package/$patch done fi @@ -84,7 +84,7 @@ ci_package() { for platform in windows-amd64 windows-arm64 android solaris freebsd linux linux-aarch64; do FILENAME="${NAME}-${platform}-${VERSION}.${EXT}" - DOWNLOAD="https://$GIT_HOST/${REPO}/releases/download/v${VERSION}/${FILENAME}" + DOWNLOAD="https://github.com/${REPO}/releases/download/v${VERSION}/${FILENAME}" PACKAGE_NAME="$PACKAGE" KEY=$platform @@ -105,8 +105,7 @@ ci_package() { for package in $@ do # prepare for cancer - # TODO(crueter): Fetch json once? - JSON=$(find . externals src/qt_common src/dynarmic -maxdepth 1 -name cpmfile.json -exec jq -r ".\"$package\" | select( . != null )" {} \;) + JSON=$(find . externals src/yuzu/externals externals/ffmpeg src/dynarmic/externals externals/nx_tzdb -maxdepth 1 -name cpmfile.json -exec jq -r ".\"$package\" | select( . != null )" {} \;) [ -z "$JSON" ] && echo "No cpmfile definition for $package" && continue @@ -119,44 +118,18 @@ do continue fi - VERSION=$(jq -r ".version" <<< "$JSON") - GIT_VERSION=$(jq -r ".git_version" <<< "$JSON") - TAG=$(jq -r ".tag" <<< "$JSON") - SHA=$(jq -r ".sha" <<< "$JSON") - - [ "$GIT_VERSION" == null ] && GIT_VERSION="$VERSION" - [ "$GIT_VERSION" == null ] && GIT_VERSION="$TAG" - # url parsing WOOOHOOHOHOOHOHOH URL=$(jq -r ".url" <<< "$JSON") REPO=$(jq -r ".repo" <<< "$JSON") SHA=$(jq -r ".sha" <<< "$JSON") - GIT_HOST=$(jq -r ".git_host" <<< "$JSON") - - [ "$GIT_HOST" == null ] && GIT_HOST=github.com - - VERSION=$(jq -r ".version" <<< "$JSON") - GIT_VERSION=$(jq -r ".git_version" <<< "$JSON") - - if [ "$GIT_VERSION" != null ]; then - VERSION_REPLACE="$GIT_VERSION" - else - VERSION_REPLACE="$VERSION" - fi - - TAG=$(jq -r ".tag" <<< "$JSON") - - TAG=$(sed "s/%VERSION%/$VERSION_REPLACE/" <<< $TAG) - - ARTIFACT=$(jq -r ".artifact" <<< "$JSON") - ARTIFACT=$(sed "s/%VERSION%/$VERSION_REPLACE/" <<< $ARTIFACT) - ARTIFACT=$(sed "s/%TAG%/$TAG/" <<< $ARTIFACT) if [ "$URL" != "null" ]; then DOWNLOAD="$URL" elif [ "$REPO" != "null" ]; then - GIT_URL="https://$GIT_HOST/$REPO" + GIT_URL="https://github.com/$REPO" + TAG=$(jq -r ".tag" <<< "$JSON") + ARTIFACT=$(jq -r ".artifact" <<< "$JSON") BRANCH=$(jq -r ".branch" <<< "$JSON") if [ "$TAG" != "null" ]; then @@ -183,20 +156,23 @@ do KEY=$(jq -r ".key" <<< "$JSON") if [ "$KEY" == null ]; then + VERSION=$(jq -r ".version" <<< "$JSON") + GIT_VERSION=$(jq -r ".git_version" <<< "$JSON") + if [ "$SHA" != null ]; then KEY=$(cut -c1-4 - <<< "$SHA") elif [ "$GIT_VERSION" != null ]; then KEY="$GIT_VERSION" - elif [ "$TAG" != null ]; then - KEY="$TAG" elif [ "$VERSION" != null ]; then KEY="$VERSION" else - echo "No valid key could be determined for $package. Must define one of: key, sha, tag, version, git_version" + echo "No valid key could be determined for $package. Must define one of: key, sha, version, git_version" continue fi fi + echo $KEY + echo "Downloading regular package $package, with key $KEY, from $DOWNLOAD" # hash parsing