diff --git a/.ci/macos/build.sh b/.ci/macos/build.sh index b6c5873e1..5ce79183d 100755 --- a/.ci/macos/build.sh +++ b/.ci/macos/build.sh @@ -2,7 +2,6 @@ set -o pipefail -export Qt5_DIR=$(brew --prefix)/opt/qt5 export PATH="/usr/local/opt/ccache/libexec:$PATH" # ccache configurations export CCACHE_CPP2=yes @@ -16,13 +15,16 @@ export ASM="clang" ccache -s mkdir build && cd build +# TODO: LibreSSL ASM disabled due to platform detection issues in build. cmake .. -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" \ -DENABLE_QT_TRANSLATION=ON \ -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \ -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \ -DUSE_DISCORD_PRESENCE=ON \ -DENABLE_FFMPEG_AUDIO_DECODER=ON \ -DENABLE_FFMPEG_VIDEO_DUMPER=ON \ + -DENABLE_ASM=OFF \ -GNinja ninja diff --git a/.ci/macos/deps.sh b/.ci/macos/deps.sh index 16b9cc8a0..302c5dcc4 100755 --- a/.ci/macos/deps.sh +++ b/.ci/macos/deps.sh @@ -1,28 +1,25 @@ #!/bin/sh -ex -brew update -brew unlink python@2 || true -rm '/usr/local/bin/2to3' || true -brew install qt5 p7zip ccache ninja wget || true +brew install ccache ninja || true pip3 install macpack -export SDL_VER=2.0.16 -export FFMPEG_VER=4.4 +export FFMPEG_VER=5.1 +export QT_VER=5.15.8 export VULKAN_SDK_VER=1.3.236.0 mkdir tmp cd tmp/ -# install SDL -wget https://github.com/SachinVin/ext-macos-bin/raw/main/sdl2/sdl-${SDL_VER}.7z -7z x sdl-${SDL_VER}.7z -cp -rv $(pwd)/sdl-${SDL_VER}/* / - # install FFMPEG wget https://github.com/SachinVin/ext-macos-bin/raw/main/ffmpeg/ffmpeg-${FFMPEG_VER}.7z 7z x ffmpeg-${FFMPEG_VER}.7z cp -rv $(pwd)/ffmpeg-${FFMPEG_VER}/* / +# install Qt +wget https://github.com/SachinVin/ext-macos-bin/raw/main/qt/qt-${QT_VER}.7z +7z x qt-${QT_VER}.7z +sudo cp -rv $(pwd)/qt-${QT_VER}/* /usr/local/ + # install Vulkan SDK wget https://sdk.lunarg.com/sdk/download/1.3.236.0/mac/vulkansdk-macos-${VULKAN_SDK_VER}.dmg hdiutil attach vulkansdk-macos-${VULKAN_SDK_VER}.dmg diff --git a/.ci/macos/upload.sh b/.ci/macos/upload.sh index 17317dda6..cac573a82 100755 --- a/.ci/macos/upload.sh +++ b/.ci/macos/upload.sh @@ -23,7 +23,7 @@ CITRA_STANDALONE_PATH="$REV_NAME/citra" # move libs into folder for deployment macpack $BUNDLE_EXECUTABLE_PATH -d "../Frameworks" # move qt frameworks into app bundle for deployment -$(brew --prefix)/opt/qt5/bin/macdeployqt $BUNDLE_PATH -executable=$BUNDLE_EXECUTABLE_PATH +macdeployqt $BUNDLE_PATH -executable=$BUNDLE_EXECUTABLE_PATH # move libs into folder for deployment macpack $CITRA_STANDALONE_PATH -d "libs" diff --git a/.gitmodules b/.gitmodules index 3aa3cd60c..6674f1ab1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,13 +12,10 @@ url = https://github.com/catchorg/Catch2 [submodule "dynarmic"] path = externals/dynarmic - url = https://github.com/citra-emu/dynarmic.git + url = https://github.com/merryhime/dynarmic.git [submodule "xbyak"] path = externals/xbyak url = https://github.com/herumi/xbyak.git -[submodule "cryptopp"] - path = externals/cryptopp/cryptopp - url = https://github.com/weidai11/cryptopp.git [submodule "fmt"] path = externals/fmt url = https://github.com/fmtlib/fmt.git @@ -58,6 +55,9 @@ [submodule "sdl2"] path = externals/sdl2/SDL url = https://github.com/libsdl-org/SDL +[submodule "cryptopp-cmake"] + path = externals/cryptopp-cmake + url = https://github.com/abdes/cryptopp-cmake.git [submodule "vulkan-headers"] path = externals/vulkan-headers url = https://github.com/KhronosGroup/Vulkan-Headers diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bb572d7b..7d84f74f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,14 +147,14 @@ function(detect_architecture symbol arch) # 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) + if (CMAKE_OSX_ARCHITECTURES) + set(ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}") + elseif (MSVC) detect_architecture("_M_AMD64" x86_64) detect_architecture("_M_IX86" x86) detect_architecture("_M_ARM" arm) @@ -168,8 +168,6 @@ if (NOT ENABLE_GENERIC) endif() if (NOT DEFINED ARCHITECTURE) set(ARCHITECTURE "GENERIC") - set(ARCHITECTURE_GENERIC 1) - add_definitions(-DARCHITECTURE_GENERIC=1) endif() message(STATUS "Target architecture: ${ARCHITECTURE}") @@ -195,7 +193,7 @@ find_package(Threads REQUIRED) if (ENABLE_QT) if (CITRA_USE_BUNDLED_QT) - if (MSVC_VERSION GREATER_EQUAL 1920 AND ARCHITECTURE_x86_64) + if (MSVC_VERSION GREATER_EQUAL 1920 AND "x86_64" IN_LIST ARCHITECTURE) set(QT_VER qt-5.15.7-msvc2019_64) else() message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable CITRA_USE_BUNDLED_QT and provide your own.") @@ -232,7 +230,7 @@ endif() if (ENABLE_FFMPEG) if (CITRA_USE_BUNDLED_FFMPEG) - if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64) + if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND "x86_64" IN_LIST ARCHITECTURE) set(FFmpeg_VER "ffmpeg-4.1-win64") else() message(FATAL_ERROR "No bundled FFmpeg binaries for your toolchain. Disable CITRA_USE_BUNDLED_FFMPEG and provide your own.") diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index d5114ceeb..712630633 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -29,25 +29,38 @@ set(CATCH_INSTALL_EXTRAS OFF) add_subdirectory(catch2) # Crypto++ -add_subdirectory(cryptopp) +set(CRYPTOPP_BUILD_DOCUMENTATION OFF) +set(CRYPTOPP_BUILD_TESTING OFF) +set(CRYPTOPP_INSTALL OFF) +add_subdirectory(cryptopp-cmake) + +# HACK: The logic to set up the base include directory for CryptoPP does not work with Android SDK CMake 3.22.1. +# Until there is a fixed version available, this code will detect and add in the proper include if it does not exist. +if(ANDROID) + message(STATUS "Applying CryptoPP include fix.") + get_target_property(CRYPTOPP_INCLUDES cryptopp INTERFACE_INCLUDE_DIRECTORIES) + foreach(CRYPTOPP_INCLUDE ${CRYPTOPP_INCLUDES}) + if("${CRYPTOPP_INCLUDE}" MATCHES "\\$") + message(STATUS "Fixed include path: ${CMAKE_MATCH_1}") + target_include_directories(cryptopp PUBLIC $) + break() + endif() + endforeach() +endif() # fmt and Xbyak need to be added before dynarmic # libfmt +option(FMT_INSTALL "" ON) add_subdirectory(fmt) # Xbyak -if (ARCHITECTURE_x86_64) - add_library(xbyak INTERFACE) - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include) - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/xbyak/xbyak DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include) - target_include_directories(xbyak SYSTEM INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include) - target_compile_definitions(xbyak INTERFACE XBYAK_NO_OP_NAMES) +if ("x86_64" IN_LIST ARCHITECTURE) + add_subdirectory(xbyak) endif() # Dynarmic -if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) +if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE) set(DYNARMIC_TESTS OFF) - set(DYNARMIC_NO_BUNDLED_FMT ON) set(DYNARMIC_FRONTENDS "A32") add_subdirectory(dynarmic) endif() diff --git a/externals/cryptopp-cmake b/externals/cryptopp-cmake new file mode 160000 index 000000000..15798ac9c --- /dev/null +++ b/externals/cryptopp-cmake @@ -0,0 +1 @@ +Subproject commit 15798ac9c2611d5c7f9ba832e2c9159bdd8945f2 diff --git a/externals/cryptopp/CMakeLists.txt b/externals/cryptopp/CMakeLists.txt deleted file mode 100644 index d927ca079..000000000 --- a/externals/cryptopp/CMakeLists.txt +++ /dev/null @@ -1,449 +0,0 @@ -# A trimmed down version of the CMakeLists.txt from noloader/cryptopp-cmake -# The differences are: -# - removed support for legacy CMake versions -# - removed support for 32-bit -# - added prefix "CRYPTOPP_OPT_" to all option names -# - disabled testing -# - disabled installation -# - disabled documentation -# - configured to build a static library only -# - adds include directories to the library target - -cmake_minimum_required(VERSION 3.1) -if (POLICY CMP0048) - cmake_policy(SET CMP0048 NEW) -endif () -project(cryptopp VERSION 8.5.0) -if (POLICY CMP0054) - cmake_policy(SET CMP0054 NEW) -endif () - -set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp) - -include(TestBigEndian) -include(GNUInstallDirs) -include(CheckCXXCompilerFlag) - -set(TEST_PROG_DIR ${SRC_DIR}/TestPrograms) -set(TEST_CXX_FILE ${TEST_PROG_DIR}/test_cxx.cxx) - -#============================================================================ -# Settable options -#============================================================================ - -option(CRYPTOPP_OPT_DISABLE_ASM "Disable ASM" OFF) -option(CRYPTOPP_OPT_DISABLE_SSSE3 "Disable SSSE3" OFF) -option(CRYPTOPP_OPT_DISABLE_SSE4 "Disable SSE4" OFF) -option(CRYPTOPP_OPT_DISABLE_AESNI "Disable AES-NI" OFF) -option(CRYPTOPP_OPT_DISABLE_SHA "Disable SHA" OFF) -option(CRYPTOPP_OPT_DISABLE_AVX "Disable AVX" OFF) -option(CRYPTOPP_OPT_DISABLE_AVX2 "Disable AVX2" OFF) - -#============================================================================ -# Compiler options -#============================================================================ - -# Only set when cross-compiling, http://www.vtk.org/Wiki/CMake_Cross_Compiling -if (NOT (CMAKE_SYSTEM_VERSION AND CMAKE_SYSTEM_PROCESSOR)) - set(CRYPTOPP_CROSS_COMPILE 1) -else() - set(CRYPTOPP_CROSS_COMPILE 0) -endif() - -set(CRYPTOPP_COMPILE_DEFINITIONS) -set(CRYPTOPP_COMPILE_OPTIONS) - -# Don't use RPATH's. The resulting binary could fail a security audit. -set(CMAKE_MACOSX_RPATH 0) - -if(CMAKE_CXX_COMPILER_ID MATCHES "Intel") - list(APPEND CRYPTOPP_COMPILE_OPTIONS -wd68 -wd186 -wd279 -wd327 -wd161 -wd3180) -endif() - -if(MSVC) - # Disable C4390: empty controlled statement found: is this the intent? - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4390") -endif() - -# Endianness -TEST_BIG_ENDIAN(IS_BIG_ENDIAN) -if(IS_BIG_ENDIAN) - add_definitions(-DIS_BIG_ENDIAN) -endif() - -if (CRYPTOPP_OPT_DISABLE_ASM) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_ASM) -endif () -if (CRYPTOPP_OPT_DISABLE_SSSE3) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_SSSE3) -endif () -if (CRYPTOPP_OPT_DISABLE_SSE4) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_SSSE4) -endif () -if (CRYPTOPP_OPT_DISABLE_CLMUL) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_CLMUL) -endif () -if (CRYPTOPP_OPT_DISABLE_AESNI) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_AESNI) -endif () -if (CRYPTOPP_OPT_DISABLE_RDRAND) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_RDRAND) -endif () -if (CRYPTOPP_OPT_DISABLE_RDSEED) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_RDSEED) -endif () -if (CRYPTOPP_OPT_DISABLE_AVX) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_AVX) -endif () -if (CRYPTOPP_OPT_DISABLE_AVX2) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_AVX2) -endif () -if (CRYPTOPP_OPT_DISABLE_SHA) - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS CRYPTOPP_DISABLE_SHA) -endif () - -# We need the output 'uname -s' for Unix and Linux system detection -if (NOT CRYPTOPP_CROSS_COMPILE) - set (UNAME_CMD "uname") - set (UNAME_ARG "-s") - execute_process(COMMAND ${UNAME_CMD} ${UNAME_ARG} - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - RESULT_VARIABLE UNAME_RESULT - OUTPUT_VARIABLE UNAME_SYSTEM) - string(REGEX REPLACE "\n$" "" UNAME_SYSTEM "${UNAME_SYSTEM}") -endif() - -# We need the output 'uname -m' for Unix and Linux platform detection -if (NOT CRYPTOPP_CROSS_COMPILE) - set (UNAME_CMD "uname") - set (UNAME_ARG "-m") - execute_process(COMMAND ${UNAME_CMD} ${UNAME_ARG} - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - RESULT_VARIABLE UNAME_RESULT - OUTPUT_VARIABLE UNAME_MACHINE) - string(REGEX REPLACE "\n$" "" UNAME_MACHINE "${UNAME_MACHINE}") -endif() - -############################################################################### - -# Try to find a Posix compatible grep and sed. Solaris, Digital Unix, -# Tru64, HP-UX and a few others need tweaking - -if (EXISTS /usr/xpg4/bin/grep) - set(GREP_CMD /usr/xpg4/bin/grep) -elseif (EXISTS /usr/gnu/bin/grep) - set(GREP_CMD /usr/gnu/bin/grep) -elseif (EXISTS /usr/linux/bin/grep) - set(GREP_CMD /usr/linux/bin/grep) -else () - set(GREP_CMD grep) -endif () - -if (EXISTS /usr/xpg4/bin/sed) - set(SED_CMD /usr/xpg4/bin/sed) -elseif (EXISTS /usr/gnu/bin/sed) - set(SED_CMD /usr/gnu/bin/sed) -elseif (EXISTS /usr/linux/bin/sed) - set(SED_CMD /usr/linux/bin/sed) -else () - set(SED_CMD sed) -endif () - -############################################################################### - -function(CheckCompileOption opt var) - CHECK_CXX_COMPILER_FLAG(${opt} ${var}) -endfunction(CheckCompileOption) - -function(CheckCompileLinkOption opt var prog) - - if (MSVC) - - # TODO: improve this... - CHECK_CXX_COMPILER_FLAG(${opt} ${var}) - - elseif (APPLE) - - message(STATUS "Performing Test ${var}") - try_compile(COMMAND_SUCCESS ${CMAKE_BINARY_DIR} ${prog} COMPILE_DEFINITIONS ${opt}) - if (COMMAND_SUCCESS) - set(${var} 1 PARENT_SCOPE) - message(STATUS "Performing Test ${var} - Success") - else () - set(${var} 0 PARENT_SCOPE) - message(STATUS "Performing Test ${var} - Failed") - endif () - - else () - - message(STATUS "Performing Test ${var}") - try_compile(COMMAND_SUCCESS ${CMAKE_BINARY_DIR} ${prog} COMPILE_DEFINITIONS ${opt}) - if (COMMAND_SUCCESS) - set(${var} 1 PARENT_SCOPE) - message(STATUS "Performing Test ${var} - Success") - else () - set(${var} 0 PARENT_SCOPE) - message(STATUS "Performing Test ${var} - Failed") - endif () - - endif () - -endfunction(CheckCompileLinkOption) - -function(AddCompileOption opt) - - if ("${COMMAND_OUTPUT}" NOT STREQUAL "") - list(APPEND CRYPTOPP_COMPILE_OPTIONS "${opt}") - endif () - -endfunction(AddCompileOption) - -############################################################################### - -function(DumpMachine output pattern) - - if (MSVC) - - # CMake does not provide a generic shell/terminal mechanism - # and Microsoft environments don't know what 'sh' is. - set(${output} 0 PARENT_SCOPE) - - else () - if(CMAKE_SYSTEM_PROCESSOR MATCHES ${pattern}) - set(${output} TRUE PARENT_SCOPE) - endif() - endif() - -endfunction(DumpMachine) - -# Thansk to Anonimal for MinGW; see http://github.com/weidai11/cryptopp/issues/466 -DumpMachine(CRYPTOPP_AMD64 "(x86_64|AMD64|amd64)") -DumpMachine(CRYPTOPP_I386 "(i.86)") -DumpMachine(CRYPTOPP_MINGW64 "(w64-mingw32)|(mingw64)") -DumpMachine(CRYPTOPP_ARMV8 "(armv8|aarch64)") - -############################################################################### - -if(MSVC) - if(CMAKE_SYSTEM_VERSION MATCHES "10\\.0.*") - list(APPEND CRYPTOPP_COMPILE_DEFINITIONS "_WIN32_WINNT=0x0A00") - endif() - list(APPEND CRYPTOPP_COMPILE_OPTIONS /FI winapifamily.h) -endif() - -# Enable PIC for all targets except Windows and 32-bit x86. -# Avoid on 32-bit x86 due to register pressures. -if ((NOT CRYPTOPP_CROSS_COMPILE) AND (NOT (WINDOWS OR WINDOWS_STORE OR WINDOWS_PHONE))) - # Use Regex; match i386, i486, i586 and i686 - if (NOT (${UNAME_MACHINE} MATCHES "i.86")) - SET(CMAKE_POSITION_INDEPENDENT_CODE 1) - endif() -endif() - -# Link is driven through the compiler, but CXXFLAGS are not used. Also see -# http://public.kitware.com/pipermail/cmake/2003-June/003967.html -if (NOT (WINDOWS OR WINDOWS_STORE OR WINDOWS_PHONE)) - SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_FLAGS}") -endif() - -#============================================================================ -# Sources & headers -#============================================================================ - -# Library headers -file(GLOB cryptopp_HEADERS ${SRC_DIR}/*.h) - -# Remove headers used to build test suite -list(REMOVE_ITEM cryptopp_HEADERS - ${SRC_DIR}/bench.h - ${SRC_DIR}/validate.h - ) - -# Library sources. -# These have been trimmed to include only things Citra uses. This speeds up -# compiles and reduces the amount of compilation breakage. -set(cryptopp_SOURCES - # The Crypto++ readme says you should put these 3 object files first, - # to avoid "problems associated with C++ static initialization order", - # but doesn't actually tell what could go wrong. Better safe than sorry - # I guess... - ${SRC_DIR}/cryptlib.cpp - ${SRC_DIR}/cpu.cpp - ${SRC_DIR}/integer.cpp - - ${SRC_DIR}/algparam.cpp - ${SRC_DIR}/allocate.cpp - ${SRC_DIR}/asn.cpp - ${SRC_DIR}/authenc.cpp - ${SRC_DIR}/base64.cpp - ${SRC_DIR}/basecode.cpp - ${SRC_DIR}/ccm.cpp - ${SRC_DIR}/crc_simd.cpp - ${SRC_DIR}/des.cpp - ${SRC_DIR}/dessp.cpp - ${SRC_DIR}/dll.cpp - ${SRC_DIR}/ec2n.cpp - ${SRC_DIR}/ecp.cpp - ${SRC_DIR}/filters.cpp - ${SRC_DIR}/fips140.cpp - ${SRC_DIR}/gcm_simd.cpp - ${SRC_DIR}/gf2n_simd.cpp - ${SRC_DIR}/gf2n.cpp - ${SRC_DIR}/gfpcrypt.cpp - ${SRC_DIR}/hex.cpp - ${SRC_DIR}/hmac.cpp - ${SRC_DIR}/hrtimer.cpp - ${SRC_DIR}/iterhash.cpp - ${SRC_DIR}/md5.cpp - ${SRC_DIR}/misc.cpp - ${SRC_DIR}/modes.cpp - ${SRC_DIR}/mqueue.cpp - ${SRC_DIR}/nbtheory.cpp - ${SRC_DIR}/neon_simd.cpp - ${SRC_DIR}/oaep.cpp - ${SRC_DIR}/osrng.cpp - ${SRC_DIR}/ppc_power7.cpp - ${SRC_DIR}/ppc_power8.cpp - ${SRC_DIR}/ppc_power9.cpp - ${SRC_DIR}/ppc_simd.cpp - ${SRC_DIR}/pubkey.cpp - ${SRC_DIR}/queue.cpp - ${SRC_DIR}/randpool.cpp - ${SRC_DIR}/rdtables.cpp - ${SRC_DIR}/rijndael_simd.cpp - ${SRC_DIR}/rijndael.cpp - ${SRC_DIR}/rng.cpp - ${SRC_DIR}/sha_simd.cpp - ${SRC_DIR}/sha.cpp - ${SRC_DIR}/sse_simd.cpp - ) - -if(ANDROID) - include_directories(${ANDROID_NDK}/sources/android/cpufeatures) - list(APPEND cryptopp_SOURCES ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c) -endif() - -set(cryptopp_SOURCES_ASM) - -if (MSVC AND NOT DISABLE_ASM) - if (${CMAKE_GENERATOR} MATCHES ".*ARM") - message(STATUS "Disabling ASM because ARM is specified as target platform.") - else () - enable_language(ASM_MASM) - list(APPEND cryptopp_SOURCES_ASM - ${SRC_DIR}/rdrand.asm - ${SRC_DIR}/rdseed.asm - ) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - list(APPEND cryptopp_SOURCES_ASM - ${SRC_DIR}/x64dll.asm - ${SRC_DIR}/x64masm.asm - ) - set_source_files_properties(${cryptopp_SOURCES_ASM} PROPERTIES COMPILE_DEFINITIONS "_M_X64") - else () - set_source_files_properties(${cryptopp_SOURCES_ASM} PROPERTIES COMPILE_DEFINITIONS "_M_X86" COMPILE_FLAGS "/safeseh") - endif () - set_source_files_properties(${cryptopp_SOURCES_ASM} PROPERTIES LANGUAGE ASM_MASM) - endif () -endif () - -#============================================================================ -# Architecture flags -#============================================================================ - -if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Intel" OR CMAKE_CXX_COMPILER MATCHES "xlC") - - if (CRYPTOPP_AMD64 OR CRYPTOPP_I386) - CheckCompileLinkOption("-msse2" CRYPTOPP_IA32_SSE2 - "${TEST_PROG_DIR}/test_x86_sse2.cxx") - CheckCompileLinkOption("-mssse3" CRYPTOPP_IA32_SSSE3 - "${TEST_PROG_DIR}/test_x86_ssse3.cxx") - CheckCompileLinkOption("-msse4.1" CRYPTOPP_IA32_SSE41 - "${TEST_PROG_DIR}/test_x86_sse41.cxx") - CheckCompileLinkOption("-msse4.2" CRYPTOPP_IA32_SSE42 - "${TEST_PROG_DIR}/test_x86_sse42.cxx") - CheckCompileLinkOption("-mssse3 -mpclmul" CRYPTOPP_IA32_CLMUL - "${TEST_PROG_DIR}/test_x86_clmul.cxx") - CheckCompileLinkOption("-msse4.1 -maes" CRYPTOPP_IA32_AES - "${TEST_PROG_DIR}/test_x86_aes.cxx") - CheckCompileLinkOption("-mavx" CRYPTOPP_IA32_AVX - "${TEST_PROG_DIR}/test_x86_avx.cxx") - CheckCompileLinkOption("-mavx2" CRYPTOPP_IA32_AVX2 - "${TEST_PROG_DIR}/test_x86_avx2.cxx") - CheckCompileLinkOption("-msse4.2 -msha" CRYPTOPP_IA32_SHA - "${TEST_PROG_DIR}/test_x86_sha.cxx") - if (EXISTS "${TEST_PROG_DIR}/test_asm_mixed.cxx") - CheckCompileLinkOption("" CRYPTOPP_MIXED_ASM - "${TEST_PROG_DIR}/test_asm_mixed.cxx") - else () - CheckCompileLinkOption("" CRYPTOPP_MIXED_ASM - "${TEST_PROG_DIR}/test_mixed_asm.cxx") - endif () - - if (NOT CRYPTOPP_MIXED_ASM) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_MIXED_ASM") - endif () - - if (NOT CRYPTOPP_IA32_SSE2 AND NOT CRYPTOPP_DISABLE_ASM) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_ASM") - elseif (CRYPTOPP_IA32_SSE2 AND NOT CRYPTOPP_DISABLE_ASM) - set_source_files_properties(${SRC_DIR}/sse_simd.cpp PROPERTIES COMPILE_FLAGS "-msse2") - endif () - if (NOT CRYPTOPP_IA32_SSSE3 AND NOT CRYPTOPP_DISABLE_SSSE3) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_SSSE3") - elseif (CRYPTOPP_IA32_SSSE3 AND NOT CRYPTOPP_DISABLE_SSSE3) - if (NOT CRYPTOPP_IA32_SSE41 AND NOT CRYPTOPP_DISABLE_SSE4) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_SSE4") - endif () - if (NOT CRYPTOPP_IA32_SSE42 AND NOT CRYPTOPP_DISABLE_SSE4) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_SSE4") - elseif (CRYPTOPP_IA32_SSE42 AND NOT CRYPTOPP_DISABLE_SSE4) - set_source_files_properties(${SRC_DIR}/crc_simd.cpp PROPERTIES COMPILE_FLAGS "-msse4.2") - if (NOT CRYPTOPP_IA32_CLMUL AND NOT CRYPTOPP_DISABLE_CLMUL) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_CLMUL") - elseif (CRYPTOPP_IA32_CLMUL AND NOT CRYPTOPP_DISABLE_CLMUL) - set_source_files_properties(${SRC_DIR}/gcm_simd.cpp PROPERTIES COMPILE_FLAGS "-mssse3 -mpclmul") - set_source_files_properties(${SRC_DIR}/gf2n_simd.cpp PROPERTIES COMPILE_FLAGS "-mpclmul") - endif () - if (NOT CRYPTOPP_IA32_AES AND NOT CRYPTOPP_DISABLE_AES) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_AESNI") - elseif (CRYPTOPP_IA32_AES AND NOT CRYPTOPP_DISABLE_AES) - set_source_files_properties(${SRC_DIR}/rijndael_simd.cpp PROPERTIES COMPILE_FLAGS "-msse4.1 -maes") - endif () - if (NOT CRYPTOPP_IA32_AVX2 AND NOT CRYPTOPP_DISABLE_AVX2) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_AVX2") - endif () - if (NOT CRYPTOPP_IA32_SHA AND NOT CRYPTOPP_DISABLE_SHA) - list(APPEND CRYPTOPP_COMPILE_OPTIONS "-DCRYPTOPP_DISABLE_SHANI") - elseif (CRYPTOPP_IA32_SHA AND NOT CRYPTOPP_DISABLE_SHA) - set_source_files_properties(${SRC_DIR}/sha_simd.cpp PROPERTIES COMPILE_FLAGS "-msse4.2 -msha") - endif () - endif () - endif () - endif () -endif () - -#============================================================================ -# Compile targets -#============================================================================ - -set(cryptopp_LIBRARY_SOURCES ${cryptopp_SOURCES_ASM}) -list(APPEND cryptopp_LIBRARY_SOURCES ${cryptopp_SOURCES}) - -add_library(cryptopp STATIC ${cryptopp_LIBRARY_SOURCES}) -target_compile_definitions(cryptopp PUBLIC ${CRYPTOPP_COMPILE_DEFINITIONS}) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}") -target_include_directories(cryptopp INTERFACE .) - -#============================================================================ -# Third-party libraries -#============================================================================ - -find_package(Threads) -target_link_libraries(cryptopp PRIVATE ${CMAKE_THREAD_LIBS_INIT}) - -if(ANDROID) - include(AndroidNdkModules) - android_ndk_import_module_cpufeatures() - target_link_libraries(cryptopp PRIVATE cpufeatures) -endif() diff --git a/externals/cryptopp/cryptopp b/externals/cryptopp/cryptopp deleted file mode 160000 index f2102243e..000000000 --- a/externals/cryptopp/cryptopp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f2102243e6fdd48c0b2a393a0993cca228f20573 diff --git a/externals/dynarmic b/externals/dynarmic index 7a926d689..9af4b970d 160000 --- a/externals/dynarmic +++ b/externals/dynarmic @@ -1 +1 @@ -Subproject commit 7a926d689bcc1cc39dd26d5bba379dffcc6815a3 +Subproject commit 9af4b970d302389829448a30608c7cb4fce9b662 diff --git a/externals/xbyak b/externals/xbyak index 48457bfa0..a1ac3750f 160000 --- a/externals/xbyak +++ b/externals/xbyak @@ -1 +1 @@ -Subproject commit 48457bfa0ded67bb4ae2d4c141c36b35469257ee +Subproject commit a1ac3750f9a639b5a6c6d6c7da4259b8d6790989 diff --git a/src/android/app/build.gradle b/src/android/app/build.gradle index 844167454..59bd66a62 100644 --- a/src/android/app/build.gradle +++ b/src/android/app/build.gradle @@ -96,7 +96,7 @@ android { externalNativeBuild { cmake { - version "3.18.1" + version "3.22.1" path "../../../CMakeLists.txt" } } diff --git a/src/android/gradle.properties b/src/android/gradle.properties index 8de505811..cbb503141 100644 --- a/src/android/gradle.properties +++ b/src/android/gradle.properties @@ -13,3 +13,4 @@ org.gradle.jvmargs=-Xmx1536m # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true +android.native.buildOutput=verbose diff --git a/src/citra_qt/Info.plist b/src/citra_qt/Info.plist index 87fc9c246..73db548c6 100644 --- a/src/citra_qt/Info.plist +++ b/src/citra_qt/Info.plist @@ -40,5 +40,7 @@ This app requires camera access to emulate the 3DS's cameras. NSMicrophoneUsageDescription This app requires microphone access to emulate the 3DS's microphone. + LSApplicationCategoryType + public.app-category.games diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 43b6e0f05..d16d40de3 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -54,6 +54,7 @@ #include "citra_qt/uisettings.h" #include "citra_qt/updater/updater.h" #include "citra_qt/util/clickable_label.h" +#include "common/arch.h" #include "common/common_paths.h" #include "common/detached_tasks.h" #include "common/file_util.h" @@ -65,7 +66,7 @@ #include "common/scm_rev.h" #include "common/scope_exit.h" #include "common/string_util.h" -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) #include "common/x64/cpu_detect.h" #endif #include "common/settings.h" @@ -200,7 +201,7 @@ GMainWindow::GMainWindow() LOG_INFO(Frontend, "Citra Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc); -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) const auto& caps = Common::GetCPUCaps(); std::string cpu_string = caps.cpu_string; if (caps.avx || caps.avx2 || caps.avx512) { @@ -2288,6 +2289,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det QString status_message; QString title, message; + QMessageBox::Icon error_severity_icon; if (result == Core::System::ResultStatus::ErrorSystemFiles) { const QString common_message = tr("%1 is missing. Please for details." "
Continuing emulation may result in crashes and bugs."); status_message = tr("Fatal Error encountered"); + error_severity_icon = QMessageBox::Icon::Critical; } QMessageBox message_box; message_box.setWindowTitle(title); message_box.setText(message); - message_box.setIcon(QMessageBox::Icon::Critical); - message_box.addButton(tr("Continue"), QMessageBox::RejectRole); - QPushButton* abort_button = message_box.addButton(tr("Abort"), QMessageBox::AcceptRole); - if (result != Core::System::ResultStatus::ShutdownRequested) - message_box.exec(); + message_box.setIcon(error_severity_icon); + if (error_severity_icon == QMessageBox::Icon::Critical) { + message_box.addButton(tr("Continue"), QMessageBox::RejectRole); + QPushButton* abort_button = message_box.addButton(tr("Quit Game"), QMessageBox::AcceptRole); + if (result != Core::System::ResultStatus::ShutdownRequested) + message_box.exec(); - if (result == Core::System::ResultStatus::ShutdownRequested || - message_box.clickedButton() == abort_button) { - if (emu_thread) { - ShutdownGame(); + if (result == Core::System::ResultStatus::ShutdownRequested || + message_box.clickedButton() == abort_button) { + if (emu_thread) { + ShutdownGame(); + return; + } } } else { - // Only show the message if the game is still running. - if (emu_thread) { - emu_thread->SetRunning(true); - message_label->setText(status_message); - message_label->setVisible(true); - message_label_used_for_movie = false; - } + // This block should run when the error isn't too big of a deal + // e.g. when a save state can't be saved or loaded + message_box.addButton(tr("OK"), QMessageBox::RejectRole); + message_box.exec(); + } + + // Only show the message if the game is still running. + if (emu_thread) { + emu_thread->SetRunning(true); + message_label->setText(status_message); + message_label->setVisible(true); + message_label_used_for_movie = false; } } diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 1f2ab936b..468363cc9 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -54,6 +54,8 @@ add_custom_command(OUTPUT scm_rev.cpp ) add_library(common STATIC + aarch64/cpu_detect.cpp + aarch64/cpu_detect.h alignment.h announce_multiplayer_room.h archives.h @@ -129,34 +131,21 @@ add_library(common STATIC unique_function.h vector_math.h web_result.h + x64/cpu_detect.cpp + x64/cpu_detect.h + x64/xbyak_abi.h + x64/xbyak_util.h zstd_compression.cpp zstd_compression.h ) -if(ARCHITECTURE_x86_64) - target_sources(common - PRIVATE - x64/cpu_detect.cpp - - x64/cpu_detect.h - x64/xbyak_abi.h - x64/xbyak_util.h - ) -elseif(ARCHITECTURE_arm64) - target_sources(common - PRIVATE - aarch64/cpu_detect.cpp - aarch64/cpu_detect.h - ) -endif() - create_target_directory_groups(common) target_link_libraries(common PUBLIC fmt::fmt microprofile Boost::boost Boost::serialization) target_link_libraries(common PRIVATE libzstd_static) set_target_properties(common PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) -if (ARCHITECTURE_x86_64) +if ("x86_64" IN_LIST ARCHITECTURE) target_link_libraries(common PRIVATE xbyak) endif() diff --git a/src/common/aarch64/cpu_detect.cpp b/src/common/aarch64/cpu_detect.cpp index 84eb8608e..52373bdef 100644 --- a/src/common/aarch64/cpu_detect.cpp +++ b/src/common/aarch64/cpu_detect.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "common/arch.h" +#if CITRA_ARCH(arm64) + #include #include #include @@ -110,3 +113,5 @@ const CPUCaps& GetCPUCaps() { } } // namespace Common + +#endif // CITRA_ARCH(arm64) diff --git a/src/common/aarch64/cpu_detect.h b/src/common/aarch64/cpu_detect.h index 79c54c2f1..8c037a528 100644 --- a/src/common/aarch64/cpu_detect.h +++ b/src/common/aarch64/cpu_detect.h @@ -4,6 +4,9 @@ #pragma once +#include "common/arch.h" +#if CITRA_ARCH(arm64) + #include namespace Common { @@ -29,3 +32,5 @@ struct CPUCaps { const CPUCaps& GetCPUCaps(); } // namespace Common + +#endif // CITRA_ARCH(arm64) diff --git a/src/common/arch.h b/src/common/arch.h new file mode 100644 index 000000000..5c70b8dca --- /dev/null +++ b/src/common/arch.h @@ -0,0 +1,13 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#define CITRA_ARCH(NAME) (CITRA_ARCH_##NAME) + +#define CITRA_ARCH_x86_64 BOOST_ARCH_X86_64 +#define CITRA_ARCH_arm64 \ + (BOOST_ARCH_ARM >= BOOST_VERSION_NUMBER(8, 0, 0) && BOOST_ARCH_WORD_BITS == 64) diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index a8dfdf10e..f8d3438ab 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -5,8 +5,9 @@ #pragma once #include +#include "common/arch.h" -#if !defined(ARCHITECTURE_x86_64) +#if !CITRA_ARCH(x86_64) #include // for exit #endif #include "common/common_types.h" @@ -36,7 +37,7 @@ #ifndef _MSC_VER -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) #define Crash() __asm__ __volatile__("int $3") #else #define Crash() exit(1) diff --git a/src/common/telemetry.cpp b/src/common/telemetry.cpp index 6241d08b3..e5fd193ef 100644 --- a/src/common/telemetry.cpp +++ b/src/common/telemetry.cpp @@ -4,11 +4,12 @@ #include #include +#include "common/arch.h" #include "common/assert.h" #include "common/scm_rev.h" #include "common/telemetry.h" -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) #include "common/x64/cpu_detect.h" #endif @@ -54,7 +55,7 @@ void AppendBuildInfo(FieldCollection& fc) { } void AppendCPUInfo(FieldCollection& fc) { -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) fc.AddField(FieldType::UserSystem, "CPU_Model", Common::GetCPUCaps().cpu_string); fc.AddField(FieldType::UserSystem, "CPU_BrandString", Common::GetCPUCaps().brand_string); fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AES", Common::GetCPUCaps().aes); diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp index f6677d5a0..2e301d377 100644 --- a/src/common/x64/cpu_detect.cpp +++ b/src/common/x64/cpu_detect.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + #include #include "common/common_types.h" #include "common/x64/cpu_detect.h" @@ -144,3 +147,5 @@ const CPUCaps& GetCPUCaps() { } } // namespace Common + +#endif // CITRA_ARCH(x86_64) diff --git a/src/common/x64/cpu_detect.h b/src/common/x64/cpu_detect.h index 92c85c2ec..31ed1c584 100644 --- a/src/common/x64/cpu_detect.h +++ b/src/common/x64/cpu_detect.h @@ -4,6 +4,9 @@ #pragma once +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + namespace Common { /// x86/x64 CPU capabilities that may be detected by this module @@ -33,3 +36,5 @@ struct CPUCaps { const CPUCaps& GetCPUCaps(); } // namespace Common + +#endif // CITRA_ARCH(x86_64) diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h index 2326c87c0..9c3615346 100644 --- a/src/common/x64/xbyak_abi.h +++ b/src/common/x64/xbyak_abi.h @@ -4,6 +4,9 @@ #pragma once +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + #include #include #include @@ -228,3 +231,5 @@ inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bits } } // namespace Common::X64 + +#endif // CITRA_ARCH(x86_64) diff --git a/src/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h index 461ca0516..32621b59d 100644 --- a/src/common/x64/xbyak_util.h +++ b/src/common/x64/xbyak_util.h @@ -4,6 +4,9 @@ #pragma once +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + #include #include #include "common/x64/xbyak_abi.h" @@ -45,3 +48,5 @@ inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) { } } // namespace Common::X64 + +#endif // CITRA_ARCH(x86_64) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9789c39d5..60d2559ad 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -486,7 +486,7 @@ if (ENABLE_WEB_SERVICE) endif() endif() -if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) +if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE) target_sources(core PRIVATE arm/dynarmic/arm_dynarmic.cpp arm/dynarmic/arm_dynarmic.h diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp index 53906eff9..5ba6dc9a8 100644 --- a/src/core/arm/exclusive_monitor.cpp +++ b/src/core/arm/exclusive_monitor.cpp @@ -1,7 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) +#include "common/arch.h" +#if CITRA_ARCH(x86_64) || CITRA_ARCH(arm64) #include "core/arm/dynarmic/arm_exclusive_monitor.h" #endif #include "common/settings.h" @@ -14,7 +15,7 @@ ExclusiveMonitor::~ExclusiveMonitor() = default; std::unique_ptr MakeExclusiveMonitor(Memory::MemorySystem& memory, std::size_t num_cores) { -#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) +#if CITRA_ARCH(x86_64) || CITRA_ARCH(arm64) if (Settings::values.use_cpu_jit) { return std::make_unique(memory, num_cores); } diff --git a/src/core/core.cpp b/src/core/core.cpp index a29cc8382..11cbc1282 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -10,11 +10,12 @@ #include "audio_core/dsp_interface.h" #include "audio_core/hle/hle.h" #include "audio_core/lle/lle.h" +#include "common/arch.h" #include "common/logging/log.h" #include "common/texture.h" #include "core/arm/arm_interface.h" #include "core/arm/exclusive_monitor.h" -#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) +#if CITRA_ARCH(x86_64) || CITRA_ARCH(arm64) #include "core/arm/dynarmic/arm_dynarmic.h" #endif #include "core/arm/dyncom/arm_dyncom.h" @@ -372,7 +373,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, exclusive_monitor = MakeExclusiveMonitor(*memory, num_cores); if (Settings::values.use_cpu_jit) { -#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) +#if CITRA_ARCH(x86_64) || CITRA_ARCH(arm64) for (u32 i = 0; i < num_cores; ++i) { cpu_cores.push_back(std::make_shared( this, *memory, i, timing->GetTimer(i), *exclusive_monitor)); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index d37363795..ca47d591f 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -224,6 +224,10 @@ public: /// Retrieves a process from the current list of processes. std::shared_ptr GetProcessById(u32 process_id) const; + const std::vector>& GetProcessList() const { + return process_list; + } + std::shared_ptr GetCurrentProcess() const; void SetCurrentProcess(std::shared_ptr process); void SetCurrentProcessForCPU(std::shared_ptr process, u32 core_id); diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index e2b905e8a..e3cfe37bd 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -44,6 +44,7 @@ void Process::serialize(Archive& ar, const unsigned int file_version) { ar& ideal_processor; ar& status; ar& process_id; + ar& creation_time_ticks; ar& vm_manager; ar& memory_used; ar& memory_region; @@ -72,6 +73,7 @@ std::shared_ptr KernelSystem::CreateProcess(std::shared_ptr co process->flags.memory_region.Assign(MemoryRegion::APPLICATION); process->status = ProcessStatus::Created; process->process_id = ++next_process_id; + process->creation_time_ticks = timing.GetTicks(); process_list.push_back(process); return process; diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index bb4fe6c12..e41eac309 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -185,6 +185,9 @@ public: /// The id of this process u32 process_id; + // Creation time in ticks of the process. + u64 creation_time_ticks; + /** * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them * to this process. diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 608d95fea..6af90edbd 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -80,6 +80,22 @@ struct PageInfo { u32 flags; }; +// Values accepted by svcGetHandleInfo. +enum class HandleInfoType { + /** + * Returns the time in ticks the KProcess referenced by the handle was created. + */ + KPROCESS_ELAPSED_TICKS = 0, + + /** + * Get internal refcount for kernel object. + */ + REFERENCE_COUNT = 1, + + STUBBED_1 = 2, + STUBBED_2 = 0x32107, +}; + /// Values accepted by svcGetSystemInfo's type parameter. enum class SystemInfoType { /** @@ -358,6 +374,8 @@ private: ResultCode UnmapMemoryBlock(Handle handle, u32 addr); ResultCode ConnectToPort(Handle* out_handle, VAddr port_name_address); ResultCode SendSyncRequest(Handle handle); + ResultCode OpenProcess(Handle* out_handle, u32 process_id); + ResultCode OpenThread(Handle* out_handle, Handle process_handle, u32 thread_id); ResultCode CloseHandle(Handle handle); ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds); ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle_count, @@ -399,6 +417,7 @@ private: ResultCode CancelTimer(Handle handle); void SleepThread(s64 nanoseconds); s64 GetSystemTick(); + ResultCode GetHandleInfo(s64* out, Handle handle, u32 type); ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, u32 other_permission); ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr name_address, @@ -409,6 +428,8 @@ private: ResultCode GetSystemInfo(s64* out, u32 type, s32 param); ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type); ResultCode GetThreadInfo(s64* out, Handle thread_handle, u32 type); + ResultCode GetProcessList(s32* process_count, VAddr out_process_array, + s32 out_process_array_count); ResultCode InvalidateInstructionCacheRange(u32 addr, u32 size); ResultCode InvalidateEntireInstructionCache(); u32 ConvertVaToPa(u32 addr); @@ -594,14 +615,16 @@ ResultCode SVC::UnmapMemoryBlock(Handle handle, u32 addr) { /// Connect to an OS service given the port name, returns the handle to the port to out ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) { - if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address)) + if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address)) { return ERR_NOT_FOUND; + } static constexpr std::size_t PortNameMaxLength = 11; // Read 1 char beyond the max allowed port name to detect names that are too long. std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1); - if (port_name.size() > PortNameMaxLength) + if (port_name.size() > PortNameMaxLength) { return ERR_PORT_NAME_TOO_LONG; + } LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); @@ -642,6 +665,50 @@ ResultCode SVC::SendSyncRequest(Handle handle) { return session->SendSyncRequest(thread); } +ResultCode SVC::OpenProcess(Handle* out_handle, u32 process_id) { + std::shared_ptr process = kernel.GetProcessById(process_id); + if (!process) { + // Result 0xd9001818 (process not found?) + return ResultCode(24, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); + } + auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(process); + if (result_handle.empty()) { + return result_handle.Code(); + } + *out_handle = result_handle.Unwrap(); + return RESULT_SUCCESS; +} + +ResultCode SVC::OpenThread(Handle* out_handle, Handle process_handle, u32 thread_id) { + if (process_handle == 0) { + LOG_ERROR(Kernel_SVC, "Uninplemented svcOpenThread process_handle=0"); + // Result 0xd9001819 (thread not found?) + return ResultCode(25, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); + } + + std::shared_ptr process = + kernel.GetCurrentProcess()->handle_table.Get(process_handle); + if (!process) { + return ERR_INVALID_HANDLE; + } + + for (u32 core_id = 0; core_id < system.GetNumCores(); core_id++) { + auto& thread_list = kernel.GetThreadManager(core_id).GetThreadList(); + for (auto& thread : thread_list) { + if (thread->owner_process.lock() == process && thread.get()->thread_id == thread_id) { + auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(thread); + if (result_handle.empty()) { + return result_handle.Code(); + } + *out_handle = result_handle.Unwrap(); + return RESULT_SUCCESS; + } + } + } + // Result 0xd9001819 (thread not found?) + return ResultCode(25, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); +} + /// Close a handle ResultCode SVC::CloseHandle(Handle handle) { LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); @@ -761,16 +828,18 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle bool wait_all, s64 nano_seconds) { Thread* thread = kernel.GetCurrentThreadManager().GetCurrentThread(); - if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) + if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) { return ERR_INVALID_POINTER; + } // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If // this happens, the running application will crash. ASSERT_MSG(out != nullptr, "invalid output pointer specified!"); // Check if 'handle_count' is invalid - if (handle_count < 0) + if (handle_count < 0) { return ERR_OUT_OF_RANGE; + } using ObjectPtr = std::shared_ptr; std::vector objects(handle_count); @@ -907,12 +976,14 @@ static ResultCode ReceiveIPCRequest(Kernel::KernelSystem& kernel, Memory::Memory /// In a single operation, sends a IPC reply and waits for a new request. ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, Handle reply_target) { - if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) + if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) { return ERR_INVALID_POINTER; + } // Check if 'handle_count' is invalid - if (handle_count < 0) + if (handle_count < 0) { return ERR_OUT_OF_RANGE; + } using ObjectPtr = std::shared_ptr; std::vector objects(handle_count); @@ -1522,6 +1593,40 @@ s64 SVC::GetSystemTick() { return result; } +// Returns information of the specified handle +ResultCode SVC::GetHandleInfo(s64* out, Handle handle, u32 type) { + std::shared_ptr KObject = kernel.GetCurrentProcess()->handle_table.GetGeneric(handle); + if (!KObject) { + return ERR_INVALID_HANDLE; + } + + // Not initialized in real kernel, but we don't want to leak memory. + s64 value = 0; + std::shared_ptr process; + + switch (static_cast(type)) { + case HandleInfoType::KPROCESS_ELAPSED_TICKS: + process = DynamicObjectCast(KObject); + if (process) { + value = process->creation_time_ticks; + } + break; + case HandleInfoType::REFERENCE_COUNT: + // This is the closest approximation we can get without a full KObject impl. + value = KObject.use_count() - 1; + break; + + // These values are stubbed in real kernel, they do nothing. + case HandleInfoType::STUBBED_1: + case HandleInfoType::STUBBED_2: + break; + default: + return ERR_INVALID_ENUM_VALUE; + } + *out = value; + return RESULT_SUCCESS; +} + /// Creates a memory block at the specified address with the specified permissions and size ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, u32 other_permission) { @@ -1833,6 +1938,25 @@ ResultCode SVC::GetThreadInfo(s64* out, Handle thread_handle, u32 type) { return RESULT_SUCCESS; } +ResultCode SVC::GetProcessList(s32* process_count, VAddr out_process_array, + s32 out_process_array_count) { + if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), out_process_array)) { + return ERR_INVALID_POINTER; + } + + s32 written = 0; + for (const auto process : kernel.GetProcessList()) { + if (written >= out_process_array_count) { + break; + } + if (process) { + memory.Write32(out_process_array + written++ * sizeof(u32), process->process_id); + } + } + *process_count = written; + return RESULT_SUCCESS; +} + ResultCode SVC::InvalidateInstructionCacheRange(u32 addr, u32 size) { Core::GetRunningCore().InvalidateCacheRange(addr, size); return RESULT_SUCCESS; @@ -1952,8 +2076,8 @@ ResultCode SVC::ControlProcess(Handle process_handle, u32 process_OP, u32 varg2, return RESULT_SUCCESS; } case ControlProcessOP::PROCESSOP_SCHEDULE_THREADS_WITHOUT_TLS_MAGIC: { - for (u32 i = 0; i < system.GetNumCores(); i++) { - auto& thread_list = kernel.GetThreadManager(i).GetThreadList(); + for (u32 core_id = 0; core_id < system.GetNumCores(); core_id++) { + auto& thread_list = kernel.GetThreadManager(core_id).GetThreadList(); for (auto& thread : thread_list) { if (thread->owner_process.lock() != process) { continue; @@ -2026,7 +2150,7 @@ const std::array SVC::SVC_Table{{ {0x26, nullptr, "SignalAndWait"}, {0x27, &SVC::Wrap<&SVC::DuplicateHandle>, "DuplicateHandle"}, {0x28, &SVC::Wrap<&SVC::GetSystemTick>, "GetSystemTick"}, - {0x29, nullptr, "GetHandleInfo"}, + {0x29, &SVC::Wrap<&SVC::GetHandleInfo>, "GetHandleInfo"}, {0x2A, &SVC::Wrap<&SVC::GetSystemInfo>, "GetSystemInfo"}, {0x2B, &SVC::Wrap<&SVC::GetProcessInfo>, "GetProcessInfo"}, {0x2C, &SVC::Wrap<&SVC::GetThreadInfo>, "GetThreadInfo"}, @@ -2036,8 +2160,8 @@ const std::array SVC::SVC_Table{{ {0x30, nullptr, "SendSyncRequest3"}, {0x31, nullptr, "SendSyncRequest4"}, {0x32, &SVC::Wrap<&SVC::SendSyncRequest>, "SendSyncRequest"}, - {0x33, nullptr, "OpenProcess"}, - {0x34, nullptr, "OpenThread"}, + {0x33, &SVC::Wrap<&SVC::OpenProcess>, "OpenProcess"}, + {0x34, &SVC::Wrap<&SVC::OpenThread>, "OpenThread"}, {0x35, &SVC::Wrap<&SVC::GetProcessId>, "GetProcessId"}, {0x36, &SVC::Wrap<&SVC::GetProcessIdOfThread>, "GetProcessIdOfThread"}, {0x37, &SVC::Wrap<&SVC::GetThreadId>, "GetThreadId"}, @@ -2086,7 +2210,7 @@ const std::array SVC::SVC_Table{{ {0x62, nullptr, "TerminateDebugProcess"}, {0x63, nullptr, "GetProcessDebugEvent"}, {0x64, nullptr, "ContinueDebugEvent"}, - {0x65, nullptr, "GetProcessList"}, + {0x65, &SVC::Wrap<&SVC::GetProcessList>, "GetProcessList"}, {0x66, nullptr, "GetThreadList"}, {0x67, nullptr, "GetDebugThreadContext"}, {0x68, nullptr, "SetDebugThreadContext"}, diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 118e2c9cf..5158d1348 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -12,15 +12,9 @@ add_executable(tests precompiled_headers.h audio_core/audio_fixures.h audio_core/decoder_tests.cpp + video_core/shader/shader_jit_x64_compiler.cpp ) -if (ARCHITECTURE_x86_64) - target_sources(tests - PRIVATE - video_core/shader/shader_jit_x64_compiler.cpp - ) -endif() - create_target_directory_groups(tests) target_link_libraries(tests PRIVATE common core video_core audio_core) diff --git a/src/tests/video_core/shader/shader_jit_x64_compiler.cpp b/src/tests/video_core/shader/shader_jit_x64_compiler.cpp index 464b2c276..79daca422 100644 --- a/src/tests/video_core/shader/shader_jit_x64_compiler.cpp +++ b/src/tests/video_core/shader/shader_jit_x64_compiler.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + #include #include #include @@ -158,3 +161,5 @@ TEST_CASE("Nested Loop", "[video_core][shader][shader_jit]") { REQUIRE(shader_unit_jit.registers.output[0].x.ToFloat32() == Catch::Approx(expected_out)); } } + +#endif // CITRA_ARCH(x86_64) diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 2570a42f0..1b4ef49ed 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -129,6 +129,10 @@ add_library(video_core STATIC shader/shader_cache.h shader/shader_interpreter.cpp shader/shader_interpreter.h + shader/shader_jit_x64.cpp + shader/shader_jit_x64_compiler.cpp + shader/shader_jit_x64.h + shader/shader_jit_x64_compiler.h shader/shader_uniforms.cpp shader/shader_uniforms.h swrasterizer/clipper.cpp @@ -158,17 +162,6 @@ add_library(video_core STATIC target_include_directories(video_core PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -if(ARCHITECTURE_x86_64) - target_sources(video_core - PRIVATE - shader/shader_jit_x64.cpp - shader/shader_jit_x64_compiler.cpp - - shader/shader_jit_x64.h - shader/shader_jit_x64_compiler.h - ) -endif() - create_target_directory_groups(video_core) # Ignore nullability warnings generated from VMA @@ -184,7 +177,7 @@ target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) target_link_libraries(video_core PRIVATE vulkan-headers vma sirit SPIRV glslang glad) target_link_libraries(video_core PRIVATE nihstro-headers Boost::serialization glm::glm) -if (ARCHITECTURE_x86_64) +if ("x86_64" IN_LIST ARCHITECTURE) target_link_libraries(video_core PUBLIC xbyak) endif() diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp index e757d2185..2e6f5d436 100644 --- a/src/video_core/shader/shader.cpp +++ b/src/video_core/shader/shader.cpp @@ -4,6 +4,7 @@ #include #include +#include "common/arch.h" #include "common/bit_set.h" #include "common/logging/log.h" #include "common/microprofile.h" @@ -12,9 +13,9 @@ #include "video_core/regs_shader.h" #include "video_core/shader/shader.h" #include "video_core/shader/shader_interpreter.h" -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) #include "video_core/shader/shader_jit_x64.h" -#endif // ARCHITECTURE_x86_64 +#endif // CITRA_ARCH(x86_64) #include "video_core/video_core.h" namespace Pica::Shader { @@ -134,13 +135,13 @@ void GSUnitState::ConfigOutput(const ShaderRegs& config) { MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240)); -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) static std::unique_ptr jit_engine; -#endif // ARCHITECTURE_x86_64 +#endif // CITRA_ARCH(x86_64) static InterpreterEngine interpreter_engine; ShaderEngine* GetEngine() { -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) // TODO(yuriks): Re-initialize on each change rather than being persistent if (VideoCore::g_shader_jit_enabled) { if (jit_engine == nullptr) { @@ -148,15 +149,15 @@ ShaderEngine* GetEngine() { } return jit_engine.get(); } -#endif // ARCHITECTURE_x86_64 +#endif // CITRA_ARCH(x86_64) return &interpreter_engine; } void Shutdown() { -#ifdef ARCHITECTURE_x86_64 +#if CITRA_ARCH(x86_64) jit_engine = nullptr; -#endif // ARCHITECTURE_x86_64 +#endif // CITRA_ARCH(x86_64) } } // namespace Pica::Shader diff --git a/src/video_core/shader/shader_jit_x64.cpp b/src/video_core/shader/shader_jit_x64.cpp index e70d6fdad..513e128cb 100644 --- a/src/video_core/shader/shader_jit_x64.cpp +++ b/src/video_core/shader/shader_jit_x64.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + #include "common/microprofile.h" #include "video_core/shader/shader.h" #include "video_core/shader/shader_jit_x64.h" @@ -43,3 +46,5 @@ void JitX64Engine::Run(const ShaderSetup& setup, UnitState& state) const { } } // namespace Pica::Shader + +#endif // CITRA_ARCH(x86_64) diff --git a/src/video_core/shader/shader_jit_x64.h b/src/video_core/shader/shader_jit_x64.h index 3f6b52cd6..b6bbdf317 100644 --- a/src/video_core/shader/shader_jit_x64.h +++ b/src/video_core/shader/shader_jit_x64.h @@ -4,6 +4,9 @@ #pragma once +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + #include #include #include "common/common_types.h" @@ -26,3 +29,5 @@ private: }; } // namespace Pica::Shader + +#endif // CITRA_ARCH(x86_64) diff --git a/src/video_core/shader/shader_jit_x64_compiler.cpp b/src/video_core/shader/shader_jit_x64_compiler.cpp index bcf3d21ec..126596357 100644 --- a/src/video_core/shader/shader_jit_x64_compiler.cpp +++ b/src/video_core/shader/shader_jit_x64_compiler.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + #include #include #include @@ -1131,3 +1134,5 @@ Xbyak::Label JitShader::CompilePrelude_Exp2() { } } // namespace Pica::Shader + +#endif // CITRA_ARCH(x86_64) diff --git a/src/video_core/shader/shader_jit_x64_compiler.h b/src/video_core/shader/shader_jit_x64_compiler.h index b6e62f01e..96dbfe82a 100644 --- a/src/video_core/shader/shader_jit_x64_compiler.h +++ b/src/video_core/shader/shader_jit_x64_compiler.h @@ -4,6 +4,9 @@ #pragma once +#include "common/arch.h" +#if CITRA_ARCH(x86_64) + #include #include #include @@ -138,3 +141,5 @@ private: }; } // namespace Pica::Shader + +#endif