28 Commits

Author SHA1 Message Date
spectranator
945de31fb9 Removed unusued and duplicate YUZU_NO_PRECOMPILED_HEADERS 2025-04-16 21:51:17 +02:00
spectranator
634acab40b Update some Android dependencies and fix build by making boost-process optional (#120)
Based on #119

Co-authored-by: Ramiro <ramiro.depaoli@gmail.com>
Co-authored-by: spectranator <spectranator@y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion>
Reviewed-on: http://vub63vv26q6v27xzv2dtcd25xumubshogm67yrpaz2rculqxs7jlfqad.onion/torzu-emu/torzu/pulls/120
2025-04-16 19:47:40 +00:00
spectranator
8561b75518 Replaced shasum with perl in Arch Linux package dependency list as shasum doesn't exist anymore 2025-04-13 22:49:56 +00:00
spectranator
15d00322a0 In containerized AppImage build script, actually install all required boost components 2025-04-13 19:53:19 +02:00
spectranator
7bd0bfbb0c Do not attempt to find boost in dynarmic if its target already exists 2025-04-13 17:45:01 +02:00
spectranator
829fad8b66 Updated vcpkg baseline for updated Boost library 2025-04-13 14:59:01 +00:00
spectranator
b539eef054 Updated revert list with previous commit 2025-04-13 16:11:38 +02:00
spectranator
f7849077e1 Removed Git SCM string anonymization as it's proven quite useless and hindering in understanding bug report 2025-04-13 16:10:03 +02:00
spectranator
35f4aa964f Fixed about dialog window being too small for content 2025-04-13 16:01:45 +02:00
spectranator
5b478bdb9c Link against all required Boost components 2025-04-13 13:05:27 +02:00
spectranator
b10bcac0cf Added loose snippets for Windows build on Linux guide 2025-04-13 00:21:17 +00:00
spectranator
cfbaa32d66 Updated minimum Boost version in Linux build guide 2025-04-13 00:14:42 +00:00
spectranator
125f4e2372 Updated vcpkg for updated Boost 2025-04-12 23:27:30 +02:00
spectranator
4e6bf7e82e In containerized AppImage build script allow CPM to be used with Clang 2025-04-12 22:48:09 +02:00
spectranator
76516783d3 Optionally use Clang for containerized AppImage build 2025-04-12 22:33:53 +02:00
spectranator
a426de1c51 Optionally use CPM in containerized AppImage build 2025-04-12 22:12:47 +02:00
spectranator
335570dfd3 In containerized AppImage build use Clang and allow thin/fat LTO for smaller and more optimized AppImages 2025-04-12 21:18:30 +02:00
spectranator
1319089702 Also mention Citron in README 2025-04-12 18:48:29 +02:00
spectranator
a640bbee41 Allow Yuzu to be built using Clang-CL for better compiler optimizations for Windows
Also updates Boost to 1.88.0
2025-04-12 18:46:13 +02:00
spectranator
709f70a3b2 Fix shader compile error if source directory path contains spaces 2025-04-12 12:28:22 +00:00
spectranator
977ed0063a Implemented dependency collection via CPM.cmake 2025-04-12 04:10:29 +02:00
spectranator
7c17d72b1a Restored accidentally removed IRC section in README 2025-04-11 19:10:12 +00:00
spectranator
ff2e94b286 Updated SDL to fix pipewire related compile error 2025-04-11 15:32:53 +02:00
spectranator
5de4fd6c76 Minor fixes around cleanup code in containerized AppImage build script 2025-04-06 22:48:56 +00:00
Zephyron
8f1b45003b service/vi: Improve OpenDisplay validation
Updates the OpenDisplay function in IApplicationDisplayService to properly
validate display names. Instead of only accepting "Default", now validates
against all known valid display names: "Default", "External", "Edid",
"Internal", and "Null".

- Changes log level from WARNING to DEBUG since this is no longer stubbed
- Adds proper validation for all valid display names
- Returns ResultOperationFailed for invalid display names
- Improves logging by including the requested display name
2025-04-06 23:41:57 +02:00
Zephyron
f78b30dbc4 cmake: Optimize Android VVL download logic
Improve the Vulkan Validation Layer (VVL) download logic for Android by checking
for the final library file instead of just the zip archive. This prevents
unnecessary re-downloads and extractions when the library is already in place.

The check now looks for libVkLayer_khronos_validation.so in the final
destination path before attempting to download and extract the archive.
2025-04-06 23:14:29 +02:00
Zephyron
e7e5906892 vulkan: Improve memory allocation robustness
Enhances the Vulkan memory allocator with better OOM handling and memory
alignment:

* Add memory recovery by cleaning up empty allocations before failing
* Implement proper fallback to non-device-local memory
* Simplify memory alignment handling for different vendors
* Add better error logging for allocation failures
* Add IsEmpty() helper to track unused allocations
* Fix alignment requirements for Adreno (4KB) vs other vendors

These changes improve the robustness of memory allocation, particularly
in low-memory situations, and streamline vendor-specific alignment
requirements.
2025-04-06 23:08:13 +02:00
spectranator
1526678a53 Removed "limited development" section from readme
It's not like I want the project to become "super public" again, I just dislike the way that section is written. It mostly still applies.
2025-04-06 22:47:41 +02:00
82 changed files with 2238 additions and 469 deletions

6
.gitmodules vendored
View File

@@ -16,9 +16,6 @@
[submodule "opus"]
path = externals/opus
url = https://github.com/xiph/opus.git
[submodule "SDL"]
path = externals/SDL
url = https://github.com/libsdl-org/SDL.git
[submodule "cpp-httplib"]
path = externals/cpp-httplib
url = https://github.com/yhirose/cpp-httplib.git
@@ -61,3 +58,6 @@
[submodule "externals/Vulkan-Headers"]
path = externals/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
[submodule "externals/SDL"]
path = externals/SDL
url = https://github.com/libsdl-org/SDL.git

View File

@@ -2,28 +2,78 @@
set -e
# Make sure script is called from inside our container
test -e /tmp/torzu-src || (echo "Script MUST NOT be called directly!" ; exit 1)
test -e /tmp/torzu-src-ro || (echo "Script MUST NOT be called directly!" ; exit 1)
# Set up environment
export LANG=C.UTF-8
export LC_ALL=C.UTF-8
unset LC_ADDRESS LC_NAME LC_MONETARY LC_PAPER LC_TELEPHONE LC_MEASUREMENT LC_TIME
# Raise max open files count
ulimit -n 50000
# Install dependencies
apt -y install cmake ninja-build build-essential pkg-config locales wget git file
apt -y install libfmt-dev libenet-dev liblz4-dev nlohmann-json3-dev zlib1g-dev libopus-dev libsimpleini-dev libstb-dev libzstd-dev libusb-1.0-0-dev libcubeb-dev libcpp-jwt-dev libvulkan-dev gamemode-dev libasound2-dev libglu1-mesa-dev libxext-dev mesa-common-dev qtbase5-dev qtmultimedia5-dev qtbase5-private-dev libva-dev glslang-tools libavcodec-dev libavfilter-dev libavutil-dev libswscale-dev
apt -y install cmake ninja-build build-essential autoconf pkg-config locales wget git file mold libtool lsb-release wget software-properties-common gnupg \
qtbase5-dev qtmultimedia5-dev qtbase5-private-dev glslang-tools libssl-dev libavcodec-dev libavfilter-dev libavutil-dev libswscale-dev libpulse-dev libasound2-dev
if [ ! "$BUILD_USE_CPM" = 1 ]; then
apt -y install libfmt-dev libenet-dev liblz4-dev nlohmann-json3-dev zlib1g-dev libopus-dev libsimpleini-dev libstb-dev libzstd-dev libusb-1.0-0-dev libcubeb-dev libcpp-jwt-dev libvulkan-dev gamemode-dev libasound2-dev libglu1-mesa-dev libxext-dev mesa-common-dev libva-dev
# Install correct version of boost
if [ ! -f /usr/local/lib/cmake/Boost-1.88.0/BoostConfigVersion.cmake ]; then
# Install Boost
wget https://archives.boost.io/release/1.88.0/source/boost_1_88_0.tar.bz2
echo "Extracting Boost sources..."
tar xf boost_1_88_0.tar.bz2
cd boost_1_88_0
./bootstrap.sh
./b2 install --with-{headers,context,system,fiber,atomic,filesystem} link=static
cd ..
rm -rf boost_1_88_0 boost_1_88_0.tar.bz2
fi
fi
# Install Clang
if ([ "$BUILD_USE_CLANG" = 1 ] && ! clang-19 --version); then
cd /tmp
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 19
rm llvm.sh
fi
# Mount Torzu sources with temporary overlay
cd /tmp
wget https://web.archive.org/web/20241120101759id_/https://boostorg.jfrog.io/artifactory/main/release/1.84.0/source/boost_1_84_0.tar.bz2
tar xf boost_1_84_0.tar.bz2
cd boost_1_84_0
./bootstrap.sh
./b2 install --with-{headers,context} link=static
cd ..
rm -rf boost_1_84_0
mkdir torzu-src-upper torzu-src-work torzu-src
mount -t overlay overlay -olowerdir=torzu-src-ro,upperdir=torzu-src-upper,workdir=torzu-src-work torzu-src
# Get extra configuration/compilation options
EXTRA_COMPILE_FLAGS=""
EXTRA_CMAKE_FLAGS=""
if [ "$BUILD_USE_CLANG" = 1 ]; then
EXTRA_CMAKE_FLAGS="-DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19"
FATLTO_FLAG="-flto=full"
else
FATLTO_FLAG="-flto"
fi
if [ "$BUILD_USE_THIN_LTO" = 1 ]; then
EXTRA_COMPILE_FLAGS="-flto=thin"
fi
if [ "$BUILD_USE_FAT_LTO" = 1 ]; then
EXTRA_COMPILE_FLAGS="$FATLTO_FLAG"
fi
if [ "$BUILD_USE_CPM" = 1 ]; then
EXTRA_CMAKE_FLAGS="$EXTRA_CMAKE_FLAGS -DYUZU_USE_CPM=ON"
fi
# Build Torzu
cd /tmp
mkdir torzu-build
cd torzu-build
cmake /tmp/torzu-src -GNinja -DCMAKE_BUILD_TYPE=Release -DYUZU_TESTS=OFF -DENABLE_QT_TRANSLATION=OFF -DSPIRV_WERROR=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_FIND_LIBRARY_SUFFIXES=".a;.so" -DSPIRV-Headers_SOURCE_DIR=/tmp/torzu-src/externals/SPIRV-Headers
ninja
cmake /tmp/torzu-src -GNinja -DCMAKE_BUILD_TYPE=Release -DYUZU_TESTS=OFF -DENABLE_QT_TRANSLATION=OFF -DSPIRV_WERROR=OFF -DCMAKE_FIND_LIBRARY_SUFFIXES=".a;.so" -DSPIRV-Headers_SOURCE_DIR=/tmp/torzu-src/externals/SPIRV-Headers -DCMAKE_{C,CXX}_FLAGS="$EXTRA_COMPILE_FLAGS -fdata-sections -ffunction-sections" -DCMAKE_{EXE,SHARED}_LINKER_FLAGS="-Wl,--gc-sections" $EXTRA_CMAKE_FLAGS
ninja || (
echo "Compilation has failed. Dropping you into a shell so you can inspect the situation. Run 'ninja' to retry and exit shell once compilation has finished successfully."
echo "Note that any changes made here will not be reflected to the host environment, but changes made from the host environment will be reflected here."
bash
)
# Generate AppImage
cp -rv /tmp/torzu-src/AppImageBuilder /tmp/AppImageBuilder

View File

@@ -1,27 +1,73 @@
#! /bin/bash
set -e
# Parse options
for i in "$@"
do
case $i in
-l|--clang)
export BUILD_USE_CLANG=1
echo "-> Using Clang for compilation."
;;
-o|--thin-lto)
export BUILD_USE_THIN_LTO=1
echo "-> Thin link time optimization enabled."
;;
-O|--fat-lto)
export BUILD_USE_FAT_LTO=1
echo "-> Fat link time optimization enabled."
;;
-p|--use-cpm)
export BUILD_USE_CPM=1
echo "-> Using CPM to download most dependencies."
;;
-k|--keep-rootfs)
BUILD_KEEP_ROOTFS=1
echo "-> Not deleting rootfs after successful build."
;;
*)
echo "Usage: $0 [--clang/-l] [--thin-lto/-o] [--fat-lto/-O] [--use-cpm/-p] [--keep-rootfs/-k]"
exit 1
;;
esac
done
# Make sure options are valid
if [ "$BUILD_USE_THIN_LTO" = 1 ] && [ "$BUILD_USE_CLANG" != 1 ]; then
echo "Thin LTO can't be used without Clang!"
exit 2
fi
if [ "$BUILD_USE_THIN_LTO" = 1 ] && [ "$BUILD_USE_FAT_LTO" = 1 ]; then
echo "Only either thin or fat LTO can be used!"
exit 2
fi
# Get torzu source dir
TORZU_SOURCE_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
echo "Source dir is $TORZU_SOURCE_DIR"
echo "-> Source dir is $TORZU_SOURCE_DIR"
rm -rf "$TORZU_SOURCE_DIR/AppImageBuilder/build"
# Generate debian rootfs
cd /tmp
rm -rf rootfs-torzu-appimage-build
debootstrap stable rootfs-torzu-appimage-build http://deb.debian.org/debian/
echo "Cleaning up before build..."
rm -rf torzu-debian-appimage-rootfs
[ -d rootfs-torzu-appimage-build ] ||
debootstrap stable rootfs-torzu-appimage-build http://deb.debian.org/debian/
bwrap --bind rootfs-torzu-appimage-build / \
--unshare-pid \
--dev-bind /dev /dev --proc /proc --tmpfs /tmp --ro-bind /sys /sys --dev-bind /run /run \
--tmpfs /var/tmp \
--chmod 1777 /tmp \
--ro-bind /etc/resolv.conf /etc/resolv.conf \
--ro-bind "$TORZU_SOURCE_DIR" /tmp/torzu-src \
--chdir / \
--tmpfs /home \
--setenv HOME /home \
--bind /tmp /tmp/hosttmp \
/tmp/torzu-src/AppImage-build-debian-inner.sh
appimagetool /tmp/torzu-debian-appimage-rootfs /tmp/torzu.AppImage
--unshare-pid \
--dev-bind /dev /dev --proc /proc --tmpfs /tmp --ro-bind /sys /sys --dev-bind /run /run \
--tmpfs /var/tmp \
--chmod 1777 /tmp \
--ro-bind /etc/resolv.conf /etc/resolv.conf \
--ro-bind "$TORZU_SOURCE_DIR" /tmp/torzu-src-ro \
--chdir / \
--tmpfs /home \
--setenv HOME /home \
--bind /tmp /tmp/hosttmp \
/tmp/torzu-src-ro/AppImage-build-debian-inner.sh
appimagetool torzu-debian-appimage-rootfs torzu.AppImage
echo "AppImage generated at /tmp/torzu.AppImage! Cleaning up..."
exec rm -rf /tmp/torzu-debian-appimage-rootfs /tmp/rootfs-torzu-appimage-build
rm -rf torzu-debian-appimage-rootfs
if [ ! "$BUILD_KEEP_ROOTFS" = 1 ]; then
rm -rf rootfs-torzu-appimage-build
fi

View File

@@ -12,6 +12,13 @@ include(DownloadExternals)
include(CMakeDependentOption)
include(CTest)
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
if (NOT YUZU_USE_BUNDLED_VCPKG)
option(YUZU_USE_CPM "Use CPM.cmake for yuzu dependencies" OFF)
else()
set(YUZU_USE_CPM OFF)
endif()
# Set bundled sdl2/qt as dependent options.
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
@@ -34,11 +41,19 @@ option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
if (NOT YUZU_USE_CPM)
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
option(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES "Use Vulkan-Utility-Libraries from externals" ON)
option(YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS "Use SPIRV-Tools from externals" ON)
option(YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS "Use SPIRV-Tools from externals" ON)
else()
set(YUZU_USE_EXTERNAL_VULKAN_HEADERS OFF)
set(YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES OFF)
set(YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS OFF)
endif()
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
@@ -48,6 +63,8 @@ option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
option(YUZU_NO_CPU_DEBUGGER "Do not build debugging code" OFF)
option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}")
option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
@@ -60,8 +77,6 @@ option(YUZU_CMD "Compile the -cmd executable (can disable if -cmd is unused)" ON
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF)
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
option(YUZU_CHECK_SUBMODULES "Check if submodules are present" ON)
option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF)
@@ -76,6 +91,66 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available
CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF)
# 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} (${YUZU_MARCH})")
if (MSVC AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(YUZU_MARCH "SSE4.2" CACHE STRING "Compile for specified x86 arch (AVX, AVX2, etc.)")
add_compile_options(/arch:${YUZU_MARCH})
else()
if (ARCHITECTURE STREQUAL "x86_64")
set(YUZU_MARCH "x86-64-v2" CACHE STRING "Compile for specified x86 microarchitecture level (x86-64-v3, native, etc.)")
add_compile_options(-march=${YUZU_MARCH})
elseif (ARCHITECTURE STREQUAL "arm64")
set(YUZU_MARCH "armv8-a" CACHE STRING "Compile for specified ARM architecture (armv8.1-a, native, etc.)")
add_compile_options(-march=${YUZU_MARCH})
else()
message(WARNING "Architecture ${ARCHITECTURE} unknown, EXPECT THINGS TO GO WRONG.")
endif()
endif()
if (MSVC)
add_definitions(-DWIN32)
endif()
set(DEFAULT_ENABLE_OPENSSL ON)
if (ANDROID OR WIN32 OR APPLE)
# - Windows defaults to the Schannel backend.
@@ -89,21 +164,26 @@ endif()
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
set(vvl_version "sdk-1.3.261.1")
set(vvl_version "1.4.304.1")
set(vvl_zip_file "${CMAKE_BINARY_DIR}/externals/vvl-android.zip")
if (NOT EXISTS "${vvl_zip_file}")
# Download and extract validation layer release to externals directory
set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download")
file(DOWNLOAD "${vvl_base_url}/${vvl_version}/android-binaries-${vvl_version}-android.zip"
"${vvl_zip_file}" SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
endif()
# Copy the arm64 binary to src/android/app/main/jniLibs
set(vvl_lib_path "${CMAKE_CURRENT_SOURCE_DIR}/src/android/app/src/main/jniLibs/arm64-v8a/")
file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/arm64-v8a/libVkLayer_khronos_validation.so"
DESTINATION "${vvl_lib_path}")
set(vvl_final_lib "${vvl_lib_path}/libVkLayer_khronos_validation.so")
if (NOT EXISTS "${vvl_final_lib}")
# Download and extract validation layer release to externals directory
if (NOT EXISTS "${vvl_zip_file}")
set(vvl_base_url "https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases/download")
file(DOWNLOAD "${vvl_base_url}/vulkan-sdk-${vvl_version}/android-binaries-${vvl_version}.zip"
"${vvl_zip_file}" SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${vvl_zip_file}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
endif()
# Copy the arm64 binary to src/android/app/main/jniLibs
file(COPY "${CMAKE_BINARY_DIR}/externals/android-binaries-${vvl_version}/arm64-v8a/libVkLayer_khronos_validation.so"
DESTINATION "${vvl_lib_path}")
endif()
endif()
if (ANDROID)
@@ -226,46 +306,6 @@ 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 (UNIX)
add_definitions(-DYUZU_UNIX=1)
@@ -298,33 +338,112 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
# =======================================================================
# Enforce the search mode of non-required packages for better and shorter failure messages
find_package(Boost 1.79.0 REQUIRED context)
find_package(enet 1.3 MODULE)
find_package(fmt REQUIRED)
if (YUZU_USE_LLVM_DEMANGLE)
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
if (NOT YUZU_USE_CPM)
find_package(Boost 1.86.0 REQUIRED headers context system fiber)
find_package(enet 1.3 MODULE)
find_package(fmt REQUIRED)
if (YUZU_USE_LLVM_DEMANGLE)
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
endif()
find_package(lz4 REQUIRED)
find_package(nlohmann_json 3.8 REQUIRED)
find_package(Opus 1.3 MODULE)
find_package(RenderDoc MODULE)
find_package(SimpleIni MODULE)
find_package(stb MODULE)
find_package(VulkanMemoryAllocator CONFIG)
find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED)
else()
include(CMakeModules/CPM.cmake)
# Disable tests in all externals supporting the standard option name
set(BUILD_TESTING OFF)
# Some externals take these options instead
set(BUILD_TESTS OFF)
set(BUILD_TOOLS OFF)
# Build only static externals
set(BUILD_SHARED_LIBS OFF)
# Do not attempt to use Brotli in httplib since we're not downloading it
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF)
# Configure Opus to not generate as much overhead
set(OPUS_BUILD_TESTING OFF)
set(OPUS_BUILD_PROGRAMS OFF)
set(OPUS_INSTALL_PKG_CONFIG_MODULE OFF)
set(OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF)
message(STATUS "Downloading and extracting boost library sources. This will take some time...")
CPMAddPackage(
NAME boost
URL "https://github.com/boostorg/boost/releases/download/boost-1.88.0/boost-1.88.0-cmake.7z"
PATCHES boost-1.88.0-fix.patch
VERSION 1.88.0
)
CPMAddPackage("gh:lsalzman/enet@1.3.18")
CPMAddPackage("gh:fmtlib/fmt#11.1.4")
CPMAddPackage(
NAME lz4
GIT_REPOSITORY https://github.com/lz4/lz4.git
VERSION 1.10.0
DOWNLOAD_ONLY YES
)
add_subdirectory(${lz4_SOURCE_DIR}/build/cmake lz4)
CPMAddPackage("gh:nlohmann/json@3.8.0")
CPMAddPackage("gh:xiph/opus@1.3.1")
CPMAddPackage("gh:brofield/simpleini@4.22")
CPMAddPackage("gh:GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@3.2.1")
CPMAddPackage("gh:madler/zlib@1.2.13")
CPMAddPackage(
NAME zstd
GIT_REPOSITORY https://github.com/facebook/zstd.git
VERSION 1.5.7
DOWNLOAD_ONLY YES
)
add_subdirectory(${zstd_SOURCE_DIR}/build/cmake zstd)
CPMAddPackage("gh:KhronosGroup/SPIRV-Headers#vulkan-sdk-1.3.280.0")
CPMAddPackage("gh:yhirose/cpp-httplib@0.20.0")
# Set up required aliases
add_library(Opus::opus ALIAS opus)
add_library(lz4::lz4 ALIAS lz4)
add_library(zstd::zstd ALIAS libzstd)
add_library(zstd::libzstd ALIAS libzstd)
add_library(nlohmann::json ALIAS nlohmann_json)
# Enet specific setup to add missing include dir
add_library(enet_fixed INTERFACE)
target_link_libraries(enet_fixed INTERFACE enet)
target_include_directories(enet_fixed INTERFACE ${enet_SOURCE_DIR}/include)
add_library(enet::enet ALIAS enet_fixed)
endif()
find_package(lz4 REQUIRED)
find_package(nlohmann_json 3.8 REQUIRED)
find_package(Opus 1.3 MODULE)
find_package(RenderDoc MODULE)
find_package(SimpleIni MODULE)
find_package(stb MODULE)
find_package(VulkanMemoryAllocator CONFIG)
find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED)
if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
find_package(VulkanHeaders 1.3.274 REQUIRED)
if (NOT YUZU_USE_CPM)
find_package(VulkanHeaders 1.3.274 REQUIRED)
else()
CPMAddPackage("gh:KhronosGroup/Vulkan-Headers@1.3.274")
endif()
endif()
if (NOT YUZU_USE_EXTERNAL_VULKAN_UTILITY_LIBRARIES)
find_package(VulkanUtilityLibraries REQUIRED)
if (NOT YUZU_USE_CPM)
find_package(VulkanUtilityLibraries REQUIRED)
else()
CPMAddPackage("gh:KhronosGroup/Vulkan-Utility-Libraries#fce11d52fee0344bb10a098b0a398dff42cb5d51")
endif()
endif()
if (NOT YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SPIRV-Tools REQUIRED SPIRV-Tools)
if (NOT YUZU_USE_CPM)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SPIRV-Tools REQUIRED SPIRV-Tools)
else()
CPMAddPackage("gh:KhronosGroup/SPIRV-Tools#dd4b663e13c07fea4fbb3f70c1c91c86731099f7") # This is tag v2024.2, but some weird but is preventing us from using it here
endif()
endif()
if (ENABLE_LIBUSB)
@@ -353,7 +472,6 @@ endif()
if (ENABLE_WEB_SERVICE)
find_package(cpp-jwt 1.4 CONFIG)
find_package(httplib 0.12 MODULE COMPONENTS OpenSSL)
endif()
if (YUZU_TESTS)
@@ -527,6 +645,10 @@ if(ENABLE_QT)
if (DEFINED QT_BUILD)
download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX)
execute_process(COMMAND chmod +x ${QT_PREFIX}/bin/moc.exe ERROR_QUIET)
execute_process(COMMAND chmod +x ${QT_PREFIX}/bin/uic.exe ERROR_QUIET)
execute_process(COMMAND chmod +x ${QT_PREFIX}/bin/rcc.exe ERROR_QUIET)
execute_process(COMMAND chmod +x ${QT_PREFIX}/bin/lrelease.exe ERROR_QUIET)
endif()
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
@@ -693,7 +815,10 @@ function(create_target_directory_groups target_name)
endfunction()
# Prevent boost from linking against libs when building
target_link_libraries(Boost::headers INTERFACE Boost::disable_autolinking)
if (NOT TARGET Boost::headers)
target_link_libraries(Boost::headers INTERFACE Boost::disable_autolinking)
endif()
# Adjustments for MSVC + Ninja
if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
add_compile_options(
@@ -703,6 +828,59 @@ if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
)
endif()
# Adjustments for Clang-cl
if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND ARCHITECTURE STREQUAL "x86_64")
set(LLVM_MINGW_VERSION 20250402)
# Set download URL and library path within the ZIP
set(ZIP_URL "https://github.com/mstorsjo/llvm-mingw/releases/download/${LLVM_MINGW_VERSION}/llvm-mingw-${LLVM_MINGW_VERSION}-ucrt-x86_64.zip")
set(LIB_PATH "llvm-mingw-${LLVM_MINGW_VERSION}-ucrt-x86_64/lib/clang/20/lib/windows/libclang_rt.builtins-x86_64.a")
# Set paths for download and extraction
set(DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/llvm-mingw-download")
set(ZIP_FILE "${DOWNLOAD_DIR}/llvm-mingw.zip")
set(EXTRACTED_LIB "${DOWNLOAD_DIR}/${LIB_PATH}")
# Create download directory if it doesn't exist
file(MAKE_DIRECTORY "${DOWNLOAD_DIR}")
# Download and extract if the library doesn't exist
if(NOT EXISTS "${EXTRACTED_LIB}")
message(STATUS "Downloading llvm-mingw runtime libraries...")
# Download the ZIP file
file(DOWNLOAD
${ZIP_URL}
${ZIP_FILE}
SHOW_PROGRESS
# Uncomment and add EXPECTED_HASH if you know the SHA256 checksum
EXPECTED_HASH SHA256=4edc13d878b4ec49c2f1a6e9161abb093bbaefc8b7d129f3b3f57a22a4a41d38
)
message(STATUS "Extracting compiler-rt builtins library...")
# Extract the specific file from the ZIP
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xvf "${ZIP_FILE}" "${LIB_PATH}"
WORKING_DIRECTORY "${DOWNLOAD_DIR}"
RESULT_VARIABLE extraction_result
)
if(NOT extraction_result EQUAL 0)
message(FATAL_ERROR "Failed to extract library: ${extraction_result}")
endif()
endif()
# Create imported target for the library
add_library(llvm-mingw-runtime STATIC IMPORTED)
set_target_properties(llvm-mingw-runtime PROPERTIES
IMPORTED_LOCATION "${EXTRACTED_LIB}"
)
# Link the library to all executables in the project
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.

1291
CMakeModules/CPM.cmake Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -98,22 +98,22 @@ function(copy_yuzu_Qt5_deps target_dir)
"${Qt5_XCBGLINTEGRATIONS_DIR}libqxcb-glx-integration.so"
)
foreach(LIB ${Qt5_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}/lib" FOLLOW_SYMLINK_CHAIN)
file(COPY "${LIB}" DESTINATION "${DLL_DEST}/lib" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_IMAGEFORMAT_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/imageformats/" FOLLOW_SYMLINK_CHAIN)
file(COPY "${LIB}" DESTINATION "${DLL_DEST}plugins/imageformats/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORMTHEME_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platformthemes/" FOLLOW_SYMLINK_CHAIN)
file(COPY "${LIB}" DESTINATION "${DLL_DEST}plugins/platformthemes/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORM_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platforms/" FOLLOW_SYMLINK_CHAIN)
file(COPY "${LIB}" DESTINATION "${DLL_DEST}plugins/platforms/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_PLATFORMINPUTCONTEXT_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/platforminputcontexts/" FOLLOW_SYMLINK_CHAIN)
file(COPY "${LIB}" DESTINATION "${DLL_DEST}plugins/platforminputcontexts/" FOLLOW_SYMLINK_CHAIN)
endforeach()
foreach(LIB ${Qt5_XCBGLINTEGRATION_DLLS})
file(COPY ${LIB} DESTINATION "${DLL_DEST}plugins/xcbglintegrations/" FOLLOW_SYMLINK_CHAIN)
file(COPY "${LIB}" DESTINATION "${DLL_DEST}plugins/xcbglintegrations/" FOLLOW_SYMLINK_CHAIN)
endforeach()
endif()

View File

@@ -12,16 +12,25 @@ 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.
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})
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})
# /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()
# /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()

View File

@@ -26,23 +26,10 @@ I highly advice against downloading anything from these websites, specially if t
There have been issues with the infrastructure running the main repository while I've been away from home. It should be all back and functional now!
Sorry for that!
## Limited public development
## IRC chat
I feel like working publicly on this has taken away the fun. You may not understand, but it's quite stressful to have the public eye on a project.
Keep in mind, this is just a hobby project. I feel like I always have to keep updating so I don't disappoint you. It's just not a good situation for a hobby project to be in.
Turns out: running an open source project takes a lot more time than I have.
And then stupid and unnecessary issues like Windows Defender flagging the emulator as malware ruin the rest. I am grateful for all your bug reports, help and support, but all that has distracted me from taking the project into the direction I would've liked.
It is not all over though. My plan is to:
- Continue the blog
- Keep this repository updated enough so it stays compilable on Linux and Windows
- Keep the externals updated
- NOT publish releases. If someone feels like publishing builds they should feel free to do that
- NOT offer support in any way
- Feel free to open issues on the main repository though if you feel like an issue REALLY needs my attention
- Accept pull requests as long as they are of reasonable quality
Again, thanks to everyone who has supported my efforts so far in any way (even by creating bug reports), I really appreciate it.
There's an IRC! Connect to `mao7u6s7jwxeof2fax2kwwqeabyevy5b2icbl24lhgnmkebbtmh37had.onion` port `6667` using your favorite client and join `#torzu`. Connecting via Tor might require a bit of setup but that shouldn't take much more than a quick web search to figure out.
Please **register your nicks**!
## Compatibility
@@ -80,7 +67,7 @@ git submodule update --init --recursive
Note that above repository may be taken down any time. Do not rely on its existence in production. In case the NotABug mirror goes down, another mirror will be most likely be set up on Bitbucket.
This project incorporates several commits from the [Suyu](https://suyu.dev) and [Sudachi](https://github.com/sudachi-emu/sudachi) forks, as well as changes listed in **Changes**.
This project incorporates several commits from the [Suyu](https://suyu.dev), [Sudachi](https://github.com/sudachi-emu/sudachi) and [Citron](https://github.com/ong19th/Citron) forks, as well as changes listed in **Changes**.
## Move away from Codeberg

24
boost-1.88.0-fix.patch Normal file
View File

@@ -0,0 +1,24 @@
diff -ruN boost-src/libs/cobalt/include/boost/cobalt/concepts.hpp boost-src-patched/libs/cobalt/include/boost/cobalt/concepts.hpp
--- boost-src/libs/cobalt/include/boost/cobalt/concepts.hpp 2025-04-12 18:25:53.791233755 +0200
+++ boost-src-patched/libs/cobalt/include/boost/cobalt/concepts.hpp 2025-04-12 18:29:50.304496166 +0200
@@ -62,7 +62,7 @@
template <typename T>
concept with_get_executor = requires (T& t)
{
- {t.get_executor()} -> asio::execution::executor;
+ t.get_executor();
};
diff -ruN boost-src/libs/context/CMakeLists.txt boost-src-patched/libs/context/CMakeLists.txt
--- boost-src/libs/context/CMakeLists.txt 2025-04-12 18:25:53.847233801 +0200
+++ boost-src-patched/libs/context/CMakeLists.txt 2025-04-12 18:29:33.436479899 +0200
@@ -189,7 +189,7 @@
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")
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT MSVC)
set_property(SOURCE ${ASM_SOURCES} APPEND PROPERTY COMPILE_OPTIONS "-Wno-unused-command-line-argument")
endif()

View File

@@ -44,9 +44,9 @@ https://developer.android.com/studio/intro
### Dependencies
```
sudo apt-get update
sudo apt-get install -y sdkmanager openjdk-17-jdk build-essential curl git pkg-config glslang-tools zip
sudo sdkmanager "ndk;26.3.11579264" "platforms;android-34" "build-tools;34.0.0" "cmake;3.22.1" "platform-tools;34.0.5"
sudo update-alternatives --config java # Select Java 17 here if possible
sudo apt-get install -y sdkmanager openjdk-21-jdk build-essential curl git pkg-config glslang-tools zip
sudo sdkmanager "ndk;26.3.11579264" "platforms;android-35" "build-tools;35.0.0" "cmake;3.22.1" "platform-tools;35.0.5"
sudo update-alternatives --config java # Select Java 21 here if possible
```
### Cloning Yuzu with Git

View File

@@ -89,7 +89,7 @@ If version 5.15.2 is not already installed, pre-compiled binaries for Qt 5.15.2
All other dependencies will be downloaded by [vcpkg](https://vcpkg.io/) if needed:
* [Boost](https://www.boost.org/users/download/) 1.79.0+
* [Boost](https://www.boost.org/users/download/) 1.86.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+
@@ -107,7 +107,7 @@ All other dependencies will be downloaded by [vcpkg](https://vcpkg.io/) if neede
- Arch / Manjaro:
```bash
sudo pacman -Syu --needed base-devel boost catch2 cmake ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt5 sdl2 shasum unzip zip zlib zstd
sudo pacman -Syu --needed base-devel boost catch2 cmake ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt5 sdl2 unzip zip zlib zstd perl
```
- Building with QT Web Engine needs to be specified when running CMake with the param `-DCMAKE_CXX_FLAGS="-I/usr/include/qt/QtWebEngineWidgets"` with qt5-webengine installed.
- GCC 11 or later is required.

View File

@@ -165,7 +165,28 @@ git submodule update --init --recursive
---
---
# Method II: MinGW-w64 Build with MSYS2
# Method II: Clang-CL on Linux
Yet to be written. These loose snippets may help you:
https://github.com/mstorsjo/msvc-wine
https://apt.llvm.org
```
exec bwrap --bind / / --ro-bind '/opt/msvc/Windows Kits/10/Include/10.0.22621.0/ucrt' /usr/include --dev /dev /bin/bash
```
```
CC=clang-cl-19 CXX=clang-cl-19 cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS:STRING="--target=x86_64-windows-msvc /EHa -Wno-unused-command-line-argument -Wno-unknown-argument" -DCMAKE_C_FLAGS:STRING="--target=x86_64-windows-msvc -Wno-unused-command-line-argument -Wno-unknown-argument" -DCMAKE_SYSTEM_NAME:STRING=Windows -DYUZU_USE_BUNDLED_VCPKG=OFF -DYUZU_USE_CPM=ON -DENABLE_OPENSSL=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF -DYUZU_TESTS=OFF -GNinja
```
---
---
---
---
---
# Method III: MinGW-w64 Build with MSYS2
## Prerequisites to install
@@ -255,7 +276,7 @@ Doesn't require the rather large Qt dependency, but you will lack a GUI frontend
---
---
# Method III: CLion Environment Setup
# Method IV: CLion Environment Setup
## Minimal Dependencies

View File

@@ -15,17 +15,21 @@ set(BUILD_SHARED_LIBS OFF)
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
# SPIRV Headers
find_package(SPIRV-Headers)
if (NOT TARGET SPIRV-Headers::SPIRV-Headers)
add_subdirectory(SPIRV-Headers)
find_package(SPIRV-Headers)
if (NOT TARGET SPIRV-Headers::SPIRV-Headers)
add_subdirectory(SPIRV-Headers)
endif()
endif()
# fmt (also used by Dynarmic, so needs to be added first)
find_package(fmt)
if (NOT TARGET fmt::fmt)
# fmtlib formatting library
set(FMT_INSTALL ON)
add_subdirectory(fmt)
find_package(fmt)
if (NOT TARGET fmt::fmt)
# fmtlib formatting library
set(FMT_INSTALL ON)
add_subdirectory(fmt)
endif()
endif()
# Xbyak (also used by Dynarmic, so needs to be added first)
@@ -142,7 +146,7 @@ endif()
if (ENABLE_WEB_SERVICE AND NOT TARGET cpp-jwt::cpp-jwt)
set(CPP_JWT_BUILD_EXAMPLES OFF)
set(CPP_JWT_BUILD_TESTS OFF)
set(CPP_JWT_USE_VENDORED_NLOHMANN_JSON OFF)
set(CPP_JWT_USE_VENDORED_NLOHMANN_JSON ${YUZU_USE_CPM})
add_subdirectory(cpp-jwt)
endif()
@@ -197,8 +201,10 @@ if (NOT TARGET LLVM::Demangle)
add_library(LLVM::Demangle ALIAS demangle)
endif()
add_library(stb stb/stb_dxt.cpp)
target_include_directories(stb PUBLIC ./stb)
if (NOT TARGET stb)
add_library(stb stb/stb_dxt.cpp)
target_include_directories(stb PUBLIC ./stb)
endif()
if (NOT TARGET stb::headers)
add_library(stb::headers ALIAS stb)

2
externals/SDL vendored

View File

@@ -140,7 +140,9 @@ if (DYNARMIC_USE_BUNDLED_EXTERNALS)
set(CMAKE_DISABLE_FIND_PACKAGE_Zydis ON)
endif()
find_package(Boost 1.57 REQUIRED)
if (NOT TARGET boost_headers)
find_package(Boost 1.57 REQUIRED)
endif()
find_package(fmt 9 CONFIG)
find_package(mcl 0.1.12 EXACT CONFIG)
find_package(tsl-robin-map CONFIG)
@@ -182,26 +184,29 @@ endif()
#
# Install
#
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
# Only try to install if boost wasn't included as submodule
if (NOT TARGET boost_headers)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
install(TARGETS dynarmic EXPORT dynarmicTargets)
install(EXPORT dynarmicTargets
NAMESPACE dynarmic::
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
install(TARGETS dynarmic EXPORT dynarmicTargets)
install(EXPORT dynarmicTargets
NAMESPACE dynarmic::
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
configure_package_config_file(CMakeModules/dynarmicConfig.cmake.in
dynarmicConfig.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
write_basic_package_version_file(dynarmicConfigVersion.cmake
COMPATIBILITY SameMajorVersion
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/dynarmicConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/dynarmicConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
configure_package_config_file(CMakeModules/dynarmicConfig.cmake.in
dynarmicConfig.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
write_basic_package_version_file(dynarmicConfigVersion.cmake
COMPATIBILITY SameMajorVersion
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/dynarmicConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/dynarmicConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
install(DIRECTORY src/dynarmic TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
install(DIRECTORY src/dynarmic TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
endif()

View File

@@ -503,11 +503,22 @@ set_target_properties(dynarmic PROPERTIES
target_compile_options(dynarmic PRIVATE ${DYNARMIC_CXX_FLAGS})
target_link_libraries(dynarmic
PRIVATE
Boost::boost
fmt::fmt
merry::mcl
tsl::robin_map
)
if (TARGET boost_headers)
target_link_libraries(dynarmic
PRIVATE
boost_headers boost_variant boost_icl
)
else()
target_link_libraries(dynarmic
PRIVATE
Boost::boost
)
endif()
if (DYNARMIC_USE_LLVM)
target_include_directories(dynarmic PRIVATE ${LLVM_INCLUDE_DIRS})
target_compile_definitions(dynarmic PRIVATE DYNARMIC_USE_LLVM=1 ${LLVM_DEFINITIONS})

View File

@@ -57,8 +57,7 @@ if (MSVC)
/EHsc
/Zc:throwingNew # Assumes new never returns null
/Zc:inline # Omits inline functions from object-file output
/DNOMINMAX
/WX)
/DNOMINMAX)
if (CMAKE_VS_PLATFORM_TOOLSET MATCHES "LLVM-vs[0-9]+")
list(APPEND SIRIT_CXX_FLAGS
@@ -76,8 +75,7 @@ else()
-Wno-missing-braces
-Wconversion
-Wsign-conversion
-Wshadow
-Werror)
-Wshadow)
endif()
# Enable unit-testing.

View File

@@ -5,4 +5,5 @@ c8997e4ab546f1ac29f54a2ef518821ba232b484
c92b9f9024404fbb68ac87370dd7589e1d5f237a
Anonymization (Disabled telemetry, anonymized scm strings)
3857ff1aa81c2e3a97f8b1e35c406853ad0618a5
3857ff1aa81c2e3a97f8b1e35c406853ad0618a5
f7849077e1f8f3d1006485523c48f26d1907763c

View File

@@ -110,11 +110,17 @@ else()
add_compile_options(
-fwrapv
-Werror=all
-Werror=extra
-Werror=missing-declarations
-Werror=shadow
-Werror=unused
# These cause issues with Boost, let's just set them to regular warnings instead (for now)
#-Werror=all
#-Werror=extra
#-Werror=missing-declarations
#-Werror=shadow
#-Werror=unused
-Wall
-Wextra
-Wmissing-declarations
-Wshadow
-Wunused
-Wno-attributes
-Wno-invalid-offsetof
@@ -128,9 +134,12 @@ else()
-Wno-braced-scalar-init
-Wno-unused-private-field
-Wno-nullability-completeness
-Werror=shadow-uncaptured-local
-Werror=implicit-fallthrough
-Werror=type-limits
# Boost...
#-Werror=shadow-uncaptured-local
#-Werror=implicit-fallthrough
-Wshadow-uncaptured-local
-Wimplicit-fallthrough
)
endif()

View File

@@ -27,7 +27,7 @@ val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toIn
android {
namespace = "org.yuzu.yuzu_emu"
compileSdkVersion = "android-34"
compileSdkVersion = "android-35"
ndkVersion = "26.3.11579264"
buildFeatures {
@@ -35,12 +35,12 @@ android {
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
kotlinOptions {
jvmTarget = "17"
jvmTarget = "21"
}
packaging {
@@ -118,7 +118,6 @@ android {
isDefault = true
resValue("string", "app_name_suffixed", "yuzu Debug Release")
signingConfig = signingConfigs.getByName("default")
isMinifyEnabled = true
isDebuggable = true
proguardFiles(
getDefaultProguardFile("proguard-android.txt"),
@@ -165,9 +164,10 @@ android {
"-DENABLE_WEB_SERVICE=0", // Don't use telemetry
"-DBUNDLE_SPEEX=ON",
"-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
"-DYUZU_NO_CPU_DEBUGGER=ON",
"-DYUZU_ENABLE_LTO=ON",
"-DYUZU_USE_BUNDLED_VCPKG=ON",
"-DYUZU_USE_BUNDLED_FFMPEG=ON",
"-DYUZU_ENABLE_LTO=ON",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
)

View File

@@ -297,7 +297,9 @@ void EmulationSession::ShutdownEmulation() {
// Shutdown the main emulated process
if (m_load_result == Core::SystemResultStatus::Success) {
#ifndef YUZU_NO_CPU_DEBUGGER
m_system.DetachDebugger();
#endif
m_system.ShutdownMainProcess();
m_detached_tasks.WaitForAllTasks();
m_load_result = Core::SystemResultStatus::ErrorNotInitialized;
@@ -344,9 +346,11 @@ void EmulationSession::RunEmulation() {
void(m_system.Run());
#ifndef YUZU_NO_CPU_DEBUGGER
if (m_system.DebuggerEnabled()) {
m_system.InitializeDebugger();
}
#endif
while (true) {
{

View File

@@ -17,4 +17,4 @@ kotlin.parallel.tasks.in.project=true
android.defaults.buildfeatures.buildconfig=true
# Android Gradle plugin 8.0.2
android.suppressUnsupportedCompileSdk=34
android.suppressUnsupportedCompileSdk=35

View File

@@ -53,7 +53,7 @@ add_library(audio_core STATIC
out/audio_out.h
out/audio_out_system.cpp
out/audio_out_system.h
precompiled_headers.h
precompiled_headers.hpp
renderer/audio_device.cpp
renderer/audio_device.h
renderer/audio_renderer.h
@@ -261,7 +261,7 @@ if (ANDROID)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
target_precompile_headers(audio_core PRIVATE precompiled_headers.hpp)
endif()
create_target_directory_groups(audio_core)

View File

@@ -3,4 +3,4 @@
#pragma once
#include "common/common_precompiled_headers.h"
#include "common/common_precompiled_headers.hpp"

View File

@@ -34,7 +34,7 @@ add_library(common STATIC
cityhash.cpp
cityhash.h
common_funcs.h
common_precompiled_headers.h
common_precompiled_headers.hpp
common_types.h
concepts.h
container_hash.h
@@ -103,7 +103,7 @@ add_library(common STATIC
param_package.h
parent_of_member.h
point.h
precompiled_headers.h
precompiled_headers.hpp
quaternion.h
range_map.h
range_mutex.h
@@ -259,7 +259,10 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
)
endif()
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
target_link_libraries(common PUBLIC Boost::headers Boost::context fmt::fmt microprofile stb::headers Threads::Threads)
if (YUZU_USE_CPM)
target_link_libraries(common PUBLIC Boost::icl)
endif()
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
if (ANDROID)
@@ -268,7 +271,7 @@ if (ANDROID)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(common PRIVATE precompiled_headers.h)
target_precompile_headers(common PRIVATE precompiled_headers.hpp)
endif()
create_target_directory_groups(common)

View File

@@ -3,4 +3,4 @@
#pragma once
#include "common/common_precompiled_headers.h"
#include "common/common_precompiled_headers.hpp"

View File

@@ -19,10 +19,9 @@
#define TITLE_BAR_FORMAT_RUNNING "@TITLE_BAR_FORMAT_RUNNING@"
namespace Common {
const char* g_scm_rev;
const char* g_scm_branch;
const char* g_scm_desc;
const char g_scm_rev[] = GIT_REV;
const char g_scm_branch[] = GIT_BRANCH;
const char g_scm_desc[] = GIT_DESC;
const char g_build_name[] = BUILD_NAME;
const char g_build_date[] = BUILD_DATE;
const char g_build_fullname[] = BUILD_FULLNAME;
@@ -30,50 +29,4 @@ 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;
/// 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

View File

@@ -5,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[];

View File

@@ -5,7 +5,11 @@
#include <utility>
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
#define MSV_BUT_NOT_CLANG
#endif
#ifdef MSV_BUT_NOT_CLANG
#include <intrin.h>
#pragma intrinsic(__umulh)
#pragma intrinsic(_umul128)
@@ -20,7 +24,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) {
#ifdef _MSC_VER
#ifdef MSV_BUT_NOT_CLANG
u128 r{};
r[0] = _umul128(a, b, &r[1]);
u64 remainder;
@@ -41,7 +45,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;
#ifdef _MSC_VER
#ifdef MSV_BUT_NOT_CLANG
result[0] = _umul128(a, b, &result[1]);
#else
unsigned __int128 tmp = a;

View File

@@ -24,7 +24,7 @@ constexpr auto PauseCycles = 100'000U;
} // Anonymous namespace
#ifdef _MSC_VER
#if defined(_MSC_VER) && !defined(__clang__)
__forceinline static void TPAUSE() {
static constexpr auto RequestC02State = 0U;
_tpause(RequestC02State, FencedRDTSC() + PauseCycles);

View File

@@ -30,13 +30,6 @@ add_library(core STATIC
crypto/partition_data_manager.h
crypto/xts_encryption_layer.cpp
crypto/xts_encryption_layer.h
debugger/debugger.cpp
debugger/debugger.h
debugger/debugger_interface.h
debugger/gdbstub.cpp
debugger/gdbstub.h
debugger/gdbstub_arch.cpp
debugger/gdbstub_arch.h
device_memory.cpp
device_memory.h
device_memory_manager.h
@@ -1133,7 +1126,7 @@ add_library(core STATIC
memory/dmnt_cheat_vm.h
perf_stats.cpp
perf_stats.h
precompiled_headers.h
precompiled_headers.hpp
reporter.cpp
reporter.h
tools/freezer.cpp
@@ -1142,6 +1135,20 @@ add_library(core STATIC
tools/renderdoc.h
)
if (YUZU_NO_CPU_DEBUGGER)
target_compile_definitions(core PUBLIC YUZU_NO_CPU_DEBUGGER)
else()
target_sources(core PRIVATE
debugger/debugger.cpp
debugger/debugger.h
debugger/debugger_interface.h
debugger/gdbstub.cpp
debugger/gdbstub.h
debugger/gdbstub_arch.cpp
debugger/gdbstub_arch.h
)
endif()
if (MSVC)
target_compile_options(core PRIVATE
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
@@ -1150,7 +1157,9 @@ if (MSVC)
)
else()
target_compile_options(core PRIVATE
-Werror=conversion
# Currently causes issues with Boost, degrading it to just a warning for now...
#-Werror=conversion
-Wconversion
-Wno-sign-conversion
-Wno-cast-function-type
@@ -1161,6 +1170,11 @@ endif()
target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz)
target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls RenderDoc::API)
if (YUZU_USE_CPM)
target_link_libraries(core PUBLIC Boost::heap Boost::asio Boost::process Boost::crc)
else()
target_link_libraries(core PUBLIC Boost::system Boost::fiber)
endif()
if (MINGW)
target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY})
endif()
@@ -1230,7 +1244,7 @@ else()
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(core PRIVATE precompiled_headers.h)
target_precompile_headers(core PRIVATE precompiled_headers.hpp)
endif()
if (YUZU_ENABLE_LTO)

View File

@@ -16,10 +16,15 @@ using namespace Common::Literals;
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
public:
explicit DynarmicCallbacks32(ArmDynarmic32& parent, Kernel::KProcess* process)
: m_parent{parent}, m_memory(process->GetMemory()),
m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()},
m_check_memory_access{m_debugger_enabled ||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
: m_parent{parent}
, m_memory(process->GetMemory())
, m_process(process)
#ifndef YUZU_NO_CPU_DEBUGGER
, m_debugger_enabled{parent.m_system.DebuggerEnabled()}
#endif
, m_check_memory_access{m_debugger_enabled
|| !Settings::values.cpuopt_ignore_memory_aborts.GetValue()}
{}
u8 MemoryRead8(u32 vaddr) override {
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
@@ -213,10 +218,12 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
config.code_cache_size = 512_MiB;
#endif
#ifndef YUZU_NO_CPU_DEBUGGER
// Allow memory fault handling to work
if (m_system.DebuggerEnabled()) {
config.check_halt_on_memory_access = true;
}
#endif
// null_jit
if (!page_table) {

View File

@@ -16,10 +16,18 @@ using namespace Common::Literals;
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
public:
explicit DynarmicCallbacks64(ArmDynarmic64& parent, Kernel::KProcess* process)
: m_parent{parent}, m_memory(process->GetMemory()),
m_process(process), m_debugger_enabled{parent.m_system.DebuggerEnabled()},
m_check_memory_access{m_debugger_enabled ||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
: m_parent{parent}
, m_memory(process->GetMemory())
, m_process(process)
#ifndef YUZU_NO_CPU_DEBUGGER
, m_debugger_enabled{parent.m_system.DebuggerEnabled()}
#endif
, m_check_memory_access{
#ifndef YUZU_NO_CPU_DEBUGGER
m_debugger_enabled ||
#endif
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()}
{}
u8 MemoryRead8(u64 vaddr) override {
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
@@ -139,10 +147,12 @@ public:
ReturnException(pc, PrefetchAbort);
return;
default:
#ifndef YUZU_NO_CPU_DEBUGGER
if (m_debugger_enabled) {
ReturnException(pc, InstructionBreakpoint);
return;
}
#endif
m_parent.LogBacktrace(m_process);
LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
@@ -192,6 +202,7 @@ public:
return false;
}
#ifndef YUZU_NO_CPU_DEBUGGER
if (!m_debugger_enabled) {
return true;
}
@@ -202,6 +213,7 @@ public:
m_parent.m_jit->HaltExecution(DataAbort);
return false;
}
#endif
return true;
}
@@ -217,7 +229,9 @@ public:
u64 m_tpidrro_el0{};
u64 m_tpidr_el0{};
Kernel::KProcess* m_process{};
#ifndef YUZU_NO_CPU_DEBUGGER
const bool m_debugger_enabled{};
#endif
const bool m_check_memory_access{};
static constexpr u64 MinimumRunCycles = 10000U;
};
@@ -272,10 +286,12 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
config.code_cache_size = 512_MiB;
#endif
#ifndef YUZU_NO_CPU_DEBUGGER
// Allow memory fault handling to work
if (m_system.DebuggerEnabled()) {
config.check_halt_on_memory_access = true;
}
#endif
// null_jit
if (!page_table) {

View File

@@ -256,9 +256,11 @@ struct System::Impl {
return nvdec_active;
}
#ifndef YUZU_NO_CPU_DEBUGGER
void InitializeDebugger(System& system, u16 port) {
debugger = std::make_unique<Debugger>(system, port);
}
#endif
void InitializeKernel(System& system) {
LOG_DEBUG(Core, "initialized OK");
@@ -421,7 +423,9 @@ struct System::Impl {
host1x_core.reset();
perf_stats.reset();
cpu_manager.Shutdown();
#ifndef YUZU_NO_CPU_DEBUGGER
debugger.reset();
#endif
kernel.Shutdown();
stop_event = {};
Network::RestartSocketOperations();
@@ -516,8 +520,10 @@ struct System::Impl {
/// Network instance
Network::NetworkInstance network_instance;
#ifndef YUZU_NO_CPU_DEBUGGER
/// Debugger
std::unique_ptr<Core::Debugger> debugger;
#endif
SystemResultStatus status = SystemResultStatus::Success;
std::string status_details = "";
@@ -582,11 +588,13 @@ void System::SetShuttingDown(bool shutting_down) {
impl->SetShuttingDown(shutting_down);
}
#ifndef YUZU_NO_CPU_DEBUGGER
void System::DetachDebugger() {
if (impl->debugger) {
impl->debugger->NotifyShutdown();
}
}
#endif
std::unique_lock<std::mutex> System::StallApplication() {
return impl->StallApplication();
@@ -604,9 +612,11 @@ bool System::GetNVDECActive() {
return impl->GetNVDECActive();
}
#ifndef YUZU_NO_CPU_DEBUGGER
void System::InitializeDebugger() {
impl->InitializeDebugger(*this, Settings::values.gdbstub_port.GetValue());
}
#endif
SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
Service::AM::FrontendAppletParameters& params) {
@@ -927,6 +937,7 @@ bool System::IsMulticore() const {
return impl->is_multicore;
}
#ifndef YUZU_NO_CPU_DEBUGGER
bool System::DebuggerEnabled() const {
return Settings::values.use_gdbstub.GetValue();
}
@@ -938,6 +949,7 @@ Core::Debugger& System::GetDebugger() {
const Core::Debugger& System::GetDebugger() const {
return *impl->debugger;
}
#endif
Network::RoomNetwork& System::GetRoomNetwork() {
return impl->room_network;

View File

@@ -184,8 +184,10 @@ public:
/// Set the shutting down state.
void SetShuttingDown(bool shutting_down);
#ifndef YUZU_NO_CPU_DEBUGGER
/// Forcibly detach the debugger if it is running.
void DetachDebugger();
#endif
std::unique_lock<std::mutex> StallApplication();
void UnstallApplication();
@@ -193,10 +195,12 @@ public:
void SetNVDECActive(bool is_nvdec_active);
[[nodiscard]] bool GetNVDECActive();
#ifndef YUZU_NO_CPU_DEBUGGER
/**
* Initialize the debugger.
*/
void InitializeDebugger();
#endif
/**
* Load an executable application.
@@ -377,8 +381,10 @@ public:
[[nodiscard]] Service::Account::ProfileManager& GetProfileManager();
[[nodiscard]] const Service::Account::ProfileManager& GetProfileManager() const;
#ifndef YUZU_NO_CPU_DEBUGGER
[[nodiscard]] Core::Debugger& GetDebugger();
[[nodiscard]] const Core::Debugger& GetDebugger() const;
#endif
/// Gets a mutable reference to the Room Network.
[[nodiscard]] Network::RoomNetwork& GetRoomNetwork();
@@ -412,8 +418,10 @@ public:
/// Tells if system is running on multicore.
[[nodiscard]] bool IsMulticore() const;
#ifndef YUZU_NO_CPU_DEBUGGER
/// Tells if the system debugger is enabled.
[[nodiscard]] bool DebuggerEnabled() const;
#endif
/// Runs a server instance until shutdown.
void RunServer(std::unique_ptr<Service::ServerManager>&& server_manager);

View File

@@ -1,41 +1,44 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/debugger/debugger.h"
#include <algorithm>
#include <mutex>
#include <thread>
#include <boost/asio.hpp>
#include <boost/process/async_pipe.hpp>
#include <boost/process/v1/async_pipe.hpp>
#include "common/logging/log.h"
#include "common/polyfill_thread.h"
#include "common/thread.h"
#include "core/core.h"
#include "core/debugger/debugger.h"
#include "core/debugger/debugger_interface.h"
#include "core/debugger/gdbstub.h"
#include "core/hle/kernel/global_scheduler_context.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scheduler.h"
template <typename Readable, typename Buffer, typename Callback>
static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) {
template<typename Readable, typename Buffer, typename Callback>
static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c)
{
static_assert(std::is_trivial_v<Buffer>);
auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))};
r.async_read_some(
boost_buffer, [&, c](const boost::system::error_code& error, size_t bytes_read) {
if (!error.failed()) {
const u8* buffer_start = reinterpret_cast<const u8*>(&buffer);
std::span<const u8> received_data{buffer_start, buffer_start + bytes_read};
c(received_data);
AsyncReceiveInto(r, buffer, c);
}
});
r.async_read_some(boost_buffer,
[&, c](const boost::system::error_code& error, size_t bytes_read) {
if (!error.failed()) {
const u8* buffer_start = reinterpret_cast<const u8*>(&buffer);
std::span<const u8> received_data{buffer_start,
buffer_start + bytes_read};
c(received_data);
AsyncReceiveInto(r, buffer, c);
}
});
}
template <typename Callback>
static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c) {
template<typename Callback>
static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c)
{
acceptor.async_accept([&, c](const boost::system::error_code& error, auto&& peer_socket) {
if (!error.failed()) {
c(peer_socket);
@@ -44,8 +47,9 @@ static void AsyncAccept(boost::asio::ip::tcp::acceptor& acceptor, Callback&& c)
});
}
template <typename Readable, typename Buffer>
static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer) {
template<typename Readable, typename Buffer>
static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer)
{
static_assert(std::is_trivial_v<Buffer>);
auto boost_buffer{boost::asio::buffer(&buffer, sizeof(Buffer))};
size_t bytes_read = r.read_some(boost_buffer);
@@ -60,7 +64,8 @@ enum class SignalType {
ShuttingDown,
};
struct SignalInfo {
struct SignalInfo
{
SignalType type;
Kernel::KThread* thread;
const Kernel::DebugWatchpoint* watchpoint;
@@ -68,17 +73,19 @@ struct SignalInfo {
namespace Core {
class DebuggerImpl : public DebuggerBackend {
class DebuggerImpl : public DebuggerBackend
{
public:
explicit DebuggerImpl(Core::System& system_, u16 port) : system{system_} {
explicit DebuggerImpl(Core::System& system_, u16 port)
: system{system_}
{
InitializeServer(port);
}
~DebuggerImpl() override {
ShutdownServer();
}
~DebuggerImpl() override { ShutdownServer(); }
bool SignalDebugger(SignalInfo signal_info) {
bool SignalDebugger(SignalInfo signal_info)
{
std::scoped_lock lk{connection_lock};
if (stopped || !state) {
@@ -100,25 +107,24 @@ public:
// These functions are callbacks from the frontend, and the lock will be held.
// There is no need to relock it.
std::span<const u8> ReadFromClient() override {
std::span<const u8> ReadFromClient() override
{
return ReceiveInto(state->client_socket, state->client_data);
}
void WriteToClient(std::span<const u8> data) override {
void WriteToClient(std::span<const u8> data) override
{
boost::asio::write(state->client_socket,
boost::asio::buffer(data.data(), data.size_bytes()));
}
void SetActiveThread(Kernel::KThread* thread) override {
state->active_thread = thread;
}
void SetActiveThread(Kernel::KThread* thread) override { state->active_thread = thread; }
Kernel::KThread* GetActiveThread() override {
return state->active_thread.GetPointerUnsafe();
}
Kernel::KThread* GetActiveThread() override { return state->active_thread.GetPointerUnsafe(); }
private:
void InitializeServer(u16 port) {
void InitializeServer(u16 port)
{
using boost::asio::ip::tcp;
LOG_INFO(Debug_GDBStub, "Starting server on port {}...", port);
@@ -142,7 +148,8 @@ private:
});
}
void AcceptConnection(boost::asio::ip::tcp::socket&& peer) {
void AcceptConnection(boost::asio::ip::tcp::socket&& peer)
{
LOG_INFO(Debug_GDBStub, "Accepting new peer connection");
std::scoped_lock lk{connection_lock};
@@ -177,13 +184,15 @@ private:
frontend->Connected();
}
void ShutdownServer() {
void ShutdownServer()
{
connection_thread.request_stop();
io_context.stop();
connection_thread.join();
}
void PipeData(std::span<const u8> data) {
void PipeData(std::span<const u8> data)
{
std::scoped_lock lk{connection_lock};
switch (state->info.type) {
@@ -197,8 +206,7 @@ private:
UpdateActiveThread();
if (state->info.type == SignalType::Watchpoint) {
frontend->Watchpoint(std::addressof(*state->active_thread),
*state->info.watchpoint);
frontend->Watchpoint(std::addressof(*state->active_thread), *state->info.watchpoint);
} else {
frontend->Stopped(std::addressof(*state->active_thread));
}
@@ -220,7 +228,8 @@ private:
}
}
void ClientData(std::span<const u8> data) {
void ClientData(std::span<const u8> data)
{
std::scoped_lock lk{connection_lock};
const auto actions{frontend->ClientData(data)};
@@ -262,7 +271,8 @@ private:
}
}
void PauseEmulation() {
void PauseEmulation()
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()};
@@ -272,7 +282,8 @@ private:
}
}
void ResumeEmulation(Kernel::KThread* except = nullptr) {
void ResumeEmulation(Kernel::KThread* except = nullptr)
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
Kernel::KScopedSchedulerLock sl{system.Kernel()};
@@ -287,13 +298,15 @@ private:
}
}
template <typename Callback>
void MarkResumed(Callback&& cb) {
template<typename Callback>
void MarkResumed(Callback&& cb)
{
stopped = false;
cb();
}
void UpdateActiveThread() {
void UpdateActiveThread()
{
Kernel::KScopedLightLock ll{debug_process->GetListLock()};
auto& threads{ThreadList()};
@@ -307,13 +320,9 @@ private:
}
private:
void SetDebugProcess() {
debug_process = std::move(system.Kernel().GetProcessList().back());
}
void SetDebugProcess() { debug_process = std::move(system.Kernel().GetProcessList().back()); }
Kernel::KProcess::ThreadList& ThreadList() {
return debug_process->GetThreadList();
}
Kernel::KProcess::ThreadList& ThreadList() { return debug_process->GetThreadList(); }
private:
System& system;
@@ -324,9 +333,10 @@ private:
std::jthread connection_thread;
std::mutex connection_lock;
struct ConnectionState {
struct ConnectionState
{
boost::asio::ip::tcp::socket client_socket;
boost::process::async_pipe signal_pipe;
boost::process::v1::async_pipe signal_pipe;
SignalInfo info;
Kernel::KScopedAutoObject<Kernel::KThread> active_thread;
@@ -338,7 +348,8 @@ private:
bool stopped{};
};
Debugger::Debugger(Core::System& system, u16 port) {
Debugger::Debugger(Core::System& system, u16 port)
{
try {
impl = std::make_unique<DebuggerImpl>(system, port);
} catch (const std::exception& ex) {
@@ -348,16 +359,18 @@ Debugger::Debugger(Core::System& system, u16 port) {
Debugger::~Debugger() = default;
bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) {
bool Debugger::NotifyThreadStopped(Kernel::KThread* thread)
{
return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread, nullptr});
}
bool Debugger::NotifyThreadWatchpoint(Kernel::KThread* thread,
const Kernel::DebugWatchpoint& watch) {
bool Debugger::NotifyThreadWatchpoint(Kernel::KThread* thread, const Kernel::DebugWatchpoint& watch)
{
return impl && impl->SignalDebugger(SignalInfo{SignalType::Watchpoint, thread, &watch});
}
void Debugger::NotifyShutdown() {
void Debugger::NotifyShutdown()
{
if (impl) {
impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr, nullptr});
}

View File

@@ -992,10 +992,12 @@ Result KProcess::Run(s32 priority, size_t stack_size) {
this->ChangeState(state);
};
#ifndef YUZU_NO_CPU_DEBUGGER
// Suspend for debug, if we should.
if (m_kernel.System().DebuggerEnabled()) {
main_thread->RequestSuspend(SuspendType::Debug);
}
#endif
// Run our thread.
R_TRY(main_thread->Run());

View File

@@ -71,7 +71,9 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) {
// Notify the debugger and go to sleep if a step was performed
// and this thread has been scheduled again.
if (thread->GetStepState() == StepState::StepPerformed) {
#ifndef YUZU_NO_CPU_DEBUGGER
system.GetDebugger().NotifyThreadStopped(thread);
#endif
thread->RequestSuspend(SuspendType::Debug);
return;
}
@@ -113,20 +115,23 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) {
if (breakpoint) {
interface->RewindBreakpointInstruction();
}
#ifndef YUZU_NO_CPU_DEBUGGER
if (system.DebuggerEnabled()) {
system.GetDebugger().NotifyThreadStopped(thread);
} else {
} else
#endif
interface->LogBacktrace(process);
}
thread->RequestSuspend(SuspendType::Debug);
return;
}
// Notify the debugger and go to sleep on data abort.
if (data_abort) {
#ifndef YUZU_NO_CPU_DEBUGGER
if (system.DebuggerEnabled()) {
system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint());
}
#endif
thread->RequestSuspend(SuspendType::Debug);
return;
}

View File

@@ -2,7 +2,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#ifndef YUZU_NO_CPU_DEBUGGER
#include "core/debugger/debugger.h"
#endif
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/svc.h"
@@ -106,6 +108,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
system.CurrentPhysicalCore().LogBacktrace();
}
#ifndef YUZU_NO_CPU_DEBUGGER
const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl();
const bool should_break = is_hbl || !notification_only;
@@ -114,6 +117,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
system.GetDebugger().NotifyThreadStopped(thread);
thread->RequestSuspend(Kernel::SuspendType::Debug);
}
#endif
}
void ReturnFromException(Core::System& system, Result result) {

View File

@@ -191,12 +191,12 @@ private:
struct VM {
static constexpr u32 YUZU_PAGESIZE{0x1000};
static constexpr u32 PAGE_SIZE_BITS{std::countr_zero(YUZU_PAGESIZE)};
static constexpr u32 PAGE_SIZE_BITS{static_cast<u32>(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{std::countr_zero(DEFAULT_BIG_PAGE_SIZE)};
u32 big_page_size_bits{static_cast<u32>(std::countr_zero(DEFAULT_BIG_PAGE_SIZE))};
static constexpr u32 VA_START_SHIFT{10};
static constexpr u64 DEFAULT_VA_SPLIT{1ULL << 34};

View File

@@ -85,11 +85,25 @@ Result IApplicationDisplayService::GetIndirectDisplayTransactionService(
}
Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) {
LOG_WARNING(Service_VI, "(STUBBED) called");
LOG_DEBUG(Service_VI, "called with display_name={}", display_name.data());
// Ensure the display name is null-terminated
display_name[display_name.size() - 1] = '\0';
ASSERT_MSG(strcmp(display_name.data(), "Default") == 0,
"Non-default displays aren't supported yet");
// According to switchbrew, only "Default", "External", "Edid", "Internal" and "Null" are valid
const std::array<std::string_view, 5> valid_names = {
"Default", "External", "Edid", "Internal", "Null"
};
bool valid_name = false;
for (const auto& name : valid_names) {
if (name == display_name.data()) {
valid_name = true;
break;
}
}
R_UNLESS(valid_name, ResultOperationFailed);
R_RETURN(m_container->OpenDisplay(out_display_id, display_name));
}

View File

@@ -6,6 +6,6 @@
#include <boost/container/flat_map.hpp> // used by service.h which is heavily included
#include <boost/intrusive/rbtree.hpp> // used by k_auto_object.h which is heavily included
#include "common/common_precompiled_headers.h"
#include "common/common_precompiled_headers.hpp"
#include "core/hle/kernel/k_process.h"

View File

@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
add_executable(yuzu-room
precompiled_headers.h
precompiled_headers.hpp
yuzu_room.cpp
yuzu_room.rc
)
@@ -24,7 +24,7 @@ if(UNIX AND NOT APPLE)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h)
target_precompile_headers(yuzu-room PRIVATE precompiled_headers.hpp)
endif()
create_target_directory_groups(yuzu-room)

View File

@@ -3,4 +3,4 @@
#pragma once
#include "common/common_precompiled_headers.h"
#include "common/common_precompiled_headers.hpp"

View File

@@ -134,7 +134,7 @@ add_library(hid_core STATIC
hid_result.h
hid_types.h
hid_util.h
precompiled_headers.h
precompiled_headers.hpp
resource_manager.cpp
resource_manager.h
)
@@ -160,5 +160,5 @@ create_target_directory_groups(hid_core)
target_link_libraries(hid_core PUBLIC core)
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(hid_core PRIVATE precompiled_headers.h)
target_precompile_headers(hid_core PRIVATE precompiled_headers.hpp)
endif()

View File

@@ -3,4 +3,4 @@
#pragma once
#include "common/common_precompiled_headers.h"
#include "common/common_precompiled_headers.hpp"

View File

@@ -32,7 +32,7 @@ add_library(input_common STATIC
input_poller.h
main.cpp
main.h
precompiled_headers.h
precompiled_headers.hpp
)
if (MSVC)
@@ -42,7 +42,9 @@ if (MSVC)
)
else()
target_compile_options(input_common PRIVATE
-Werror=conversion
# Causes Boost to fail to compile, let's just let it be a warning for now.
#-Werror=conversion
-Wconversion
)
endif()
@@ -89,7 +91,7 @@ create_target_directory_groups(input_common)
target_link_libraries(input_common PUBLIC hid_core PRIVATE common Boost::headers)
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(input_common PRIVATE precompiled_headers.h)
target_precompile_headers(input_common PRIVATE precompiled_headers.hpp)
endif()
if (ANDROID)

View File

@@ -26,8 +26,8 @@ public:
using clock = std::chrono::system_clock;
explicit Socket(const std::string& host, u16 port, SocketCallback callback_)
: callback(std::move(callback_)), timer(io_service),
socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) {
: callback(std::move(callback_)), timer(io_context),
socket(io_context, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) {
boost::system::error_code ec{};
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
if (ec.value() != boost::system::errc::success) {
@@ -39,11 +39,11 @@ public:
}
void Stop() {
io_service.stop();
io_context.stop();
}
void Loop() {
io_service.run();
io_context.run();
}
void StartSend(const clock::time_point& from) {
@@ -113,7 +113,7 @@ private:
}
SocketCallback callback;
boost::asio::io_service io_service;
boost::asio::io_context io_context;
boost::asio::basic_waitable_timer<clock> timer;
udp::socket socket;

View File

@@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.h"

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.hpp"

View File

@@ -8,7 +8,7 @@ add_library(network STATIC
network.h
packet.cpp
packet.h
precompiled_headers.h
precompiled_headers.hpp
room.cpp
room.h
room_member.cpp
@@ -26,5 +26,5 @@ if (ENABLE_WEB_SERVICE)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(network PRIVATE precompiled_headers.h)
target_precompile_headers(network PRIVATE precompiled_headers.hpp)
endif()

View File

@@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.h"

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.hpp"

View File

@@ -234,7 +234,7 @@ add_library(shader_recompiler STATIC
ir_opt/vendor_workaround_pass.cpp
ir_opt/verification_pass.cpp
object_pool.h
precompiled_headers.h
precompiled_headers.hpp
profile.h
program_header.h
runtime_info.h
@@ -269,5 +269,5 @@ endif()
create_target_directory_groups(shader_recompiler)
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(shader_recompiler PRIVATE precompiled_headers.h)
target_precompile_headers(shader_recompiler PRIVATE precompiled_headers.hpp)
endif()

View File

@@ -3,5 +3,5 @@
#pragma once
#include "common/common_precompiled_headers.h"
#include "common/common_precompiled_headers.hpp"
#include "frontend/maxwell/translate/impl/impl.h"

View File

@@ -14,7 +14,7 @@ add_executable(tests
common/unique_function.cpp
core/core_timing.cpp
core/internal_network/network.cpp
precompiled_headers.h
precompiled_headers.hpp
video_core/memory_tracker.cpp
input_common/calibration_configuration_job.cpp
)
@@ -27,5 +27,5 @@ target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} Catch2::Catch2WithMain
add_test(NAME tests COMMAND tests)
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(tests PRIVATE precompiled_headers.h)
target_precompile_headers(tests PRIVATE precompiled_headers.hpp)
endif()

View File

@@ -14,7 +14,7 @@
class FakeCemuhookServer {
public:
FakeCemuhookServer()
: socket(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)) {}
: socket(io_context, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)) {}
~FakeCemuhookServer() {
is_running = false;
@@ -82,7 +82,7 @@ public:
}
private:
boost::asio::io_service io_service;
boost::asio::io_context io_context;
boost::asio::ip::udp::socket socket;
std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> send_buffer;
std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> receive_buffer;

View File

@@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.h"

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.hpp"

View File

@@ -99,7 +99,7 @@ add_library(video_core STATIC
invalidation_accumulator.h
memory_manager.cpp
memory_manager.h
precompiled_headers.h
precompiled_headers.hpp
present.h
pte_kind.h
query_cache/bank_base.h
@@ -347,7 +347,11 @@ if (NOT MSVC)
# error: implicit conversion loses integer precision: 'int' to 'boost::icl::bound_type' (aka 'unsigned char')
target_compile_options(video_core PRIVATE -Wno-shadow -Wno-unused-local-typedef)
else()
target_compile_options(video_core PRIVATE -Werror=conversion)
target_compile_options(video_core PRIVATE
# Boost is breaking this so don't make it an error.
#-Werror=conversion
-Wconversion
)
endif()
target_compile_options(video_core PRIVATE
@@ -372,10 +376,6 @@ if (ARCHITECTURE_x86_64)
macro/macro_jit_x64.h
)
target_link_libraries(video_core PUBLIC xbyak::xbyak)
if (NOT MSVC)
target_compile_options(video_core PRIVATE -msse4.1)
endif()
endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
@@ -383,7 +383,7 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(video_core PRIVATE precompiled_headers.h)
target_precompile_headers(video_core PRIVATE precompiled_headers.hpp)
endif()
if (YUZU_ENABLE_LTO)

View File

@@ -131,7 +131,7 @@ foreach(FILENAME IN ITEMS ${SHADER_FILES})
OUTPUT
${SPIRV_HEADER_FILE}
COMMAND
${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION}
${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I${FIDELITYFX_INCLUDE_DIR} ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} --target-env ${SPIR_V_VERSION}
MAIN_DEPENDENCY
${SOURCE_FILE}
)

View File

@@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.h"

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.hpp"

View File

@@ -140,6 +140,10 @@ public:
return (flags & property_flags) == flags && (type_mask & shifted_memory_type) != 0;
}
[[nodiscard]] bool IsEmpty() const noexcept {
return commits.empty();
}
private:
[[nodiscard]] static constexpr u32 ShiftType(u32 type) {
return 1U << type;
@@ -284,39 +288,78 @@ MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements& requirements, M
const u32 type_mask = requirements.memoryTypeBits;
const VkMemoryPropertyFlags usage_flags = MemoryUsagePropertyFlags(usage);
const VkMemoryPropertyFlags flags = MemoryPropertyFlags(type_mask, usage_flags);
// First attempt
if (std::optional<MemoryCommit> commit = TryCommit(requirements, flags)) {
return std::move(*commit);
}
// Commit has failed, allocate more memory.
// 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);
if (TryAllocMemory(flags, type_mask, chunk_size)) {
return TryCommit(requirements, flags).value();
}
// 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();
// Memory allocation failed - try to recover by releasing empty allocations
for (auto it = allocations.begin(); it != allocations.end();) {
if ((*it)->IsEmpty()) {
it = allocations.erase(it);
} else {
++it;
}
}
// Try allocating again after cleanup
if (TryAllocMemory(flags, type_mask, chunk_size)) {
return TryCommit(requirements, flags).value();
}
// If still failing, try with non-device-local memory as a last resort
if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
const VkMemoryPropertyFlags fallback_flags = flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
if (TryAllocMemory(fallback_flags, type_mask, chunk_size)) {
if (auto commit = TryCommit(requirements, fallback_flags)) {
LOG_WARNING(Render_Vulkan, "Falling back to non-device-local memory due to OOM");
return std::move(*commit);
}
}
}
LOG_CRITICAL(Render_Vulkan, "Vulkan memory allocation failed - out of device memory");
throw vk::Exception(VK_ERROR_OUT_OF_DEVICE_MEMORY);
}
bool MemoryAllocator::TryAllocMemory(VkMemoryPropertyFlags flags, u32 type_mask, u64 size) {
const u32 type = FindType(flags, type_mask).value();
const auto type_opt = FindType(flags, type_mask);
if (!type_opt) {
if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) {
// Try to allocate non device local memory
return TryAllocMemory(flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, type_mask, size);
}
return false;
}
const u64 aligned_size = (device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) ?
Common::AlignUp(size, 4096) : // Adreno requires 4KB alignment
size; // Others (NVIDIA, AMD, Intel, etc)
vk::DeviceMemory memory = device.GetLogical().TryAllocateMemory({
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = nullptr,
.allocationSize = size,
.memoryTypeIndex = type,
.allocationSize = aligned_size,
.memoryTypeIndex = *type_opt,
});
if (!memory) {
if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) {
// Try to allocate non device local memory
return TryAllocMemory(flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, type_mask, size);
} else {
// RIP
return false;
}
return false;
}
allocations.push_back(
std::make_unique<MemoryAllocation>(this, std::move(memory), flags, size, type));
std::make_unique<MemoryAllocation>(this, std::move(memory), flags, aligned_size, *type_opt));
return true;
}

View File

@@ -4,7 +4,7 @@
add_library(web_service STATIC
announce_room_json.cpp
announce_room_json.h
precompiled_headers.h
precompiled_headers.hpp
verify_login.cpp
verify_login.h
verify_user_jwt.cpp
@@ -18,5 +18,5 @@ create_target_directory_groups(web_service)
target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json httplib::httplib cpp-jwt::cpp-jwt)
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(web_service PRIVATE precompiled_headers.h)
target_precompile_headers(web_service PRIVATE precompiled_headers.hpp)
endif()

View File

@@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.h"

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.hpp"

View File

@@ -203,7 +203,7 @@ add_executable(yuzu
multiplayer/validation.h
play_time_manager.cpp
play_time_manager.h
precompiled_headers.h
precompiled_headers.hpp
qt_common.cpp
qt_common.h
startup_checks.cpp
@@ -382,8 +382,14 @@ elseif(WIN32)
endif()
target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core)
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets httplib::httplib)
target_link_libraries(yuzu PRIVATE Boost::headers httplib::httplib glad Qt${QT_MAJOR_VERSION}::Widgets)
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
if (TARGET nlohmann::json)
target_link_libraries(yuzu PRIVATE nlohmann::json)
endif()
if (ENABLE_WEB_SERVICE)
target_link_libraries(yuzu PRIVATE httplib::httplib)
endif()
target_link_libraries(yuzu PRIVATE Vulkan::Headers)
if (NOT WIN32)
@@ -474,7 +480,7 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(yuzu PRIVATE precompiled_headers.h)
target_precompile_headers(yuzu PRIVATE precompiled_headers.hpp)
endif()
create_target_directory_groups(yuzu)

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>616</width>
<height>294</height>
<height>341</height>
</rect>
</property>
<property name="windowTitle">
@@ -46,7 +46,7 @@
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -106,7 +106,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
&lt;br&gt;&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:12pt;&quot;&gt;This software should not be used to play games you have not legally obtained.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -116,7 +116,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -156,10 +156,10 @@ li.checked::marker { content: &quot;\2612&quot;; }
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>

View File

@@ -100,9 +100,11 @@ void EmuThread::run() {
m_system.GetCpuManager().OnGpuReady();
#ifndef YUZU_NO_CPU_DEBUGGER
if (m_system.DebuggerEnabled()) {
m_system.InitializeDebugger();
}
#endif
while (!stop_token.stop_requested()) {
std::unique_lock lk{m_should_run_mutex};
@@ -122,7 +124,9 @@ void EmuThread::run() {
}
// Shutdown the main emulated process
#ifndef YUZU_NO_CPU_DEBUGGER
m_system.DetachDebugger();
#endif
m_system.ShutdownMainProcess();
#if MICROPROFILE_ENABLED

View File

@@ -19,9 +19,14 @@ ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent)
ui->setupUi(this);
SetConfiguration();
#ifdef YUZU_NO_CPU_DEBUGGER
ui->cpu_debug_box->setEnabled(false);
ui->toggle_gdbstub->setCheckState(Qt::Unchecked);
#endif
connect(ui->open_log_button, &QPushButton::clicked, []() {
const auto path =
QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::LogDir));
const auto path = QString::fromStdString(
Common::FS::GetYuzuPathString(Common::FS::YuzuPath::LogDir));
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
});

View File

@@ -18,8 +18,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>842</width>
<height>741</height>
<width>829</width>
<height>758</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_1">
@@ -29,7 +29,7 @@
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QGroupBox" name="cpu_debug_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -40,7 +40,7 @@
<string>Debugger</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="flat">
<bool>false</bool>
@@ -59,7 +59,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>0</number>
@@ -355,10 +355,10 @@
<item row="10" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
<enum>QSizePolicy::Policy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -452,10 +452,10 @@
<item row="7" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
<enum>QSizePolicy::Policy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -501,10 +501,10 @@
<item row="5" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
<enum>QSizePolicy::Policy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -522,7 +522,7 @@
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>

View File

@@ -2076,9 +2076,12 @@ bool GMainWindow::OnShutdownBegin() {
int shutdown_time = 1000;
#ifndef YUZU_NO_CPU_DEBUGGER
if (system->DebuggerEnabled()) {
shutdown_time = 0;
} else if (system->GetExitLocked()) {
} else
#endif
if (system->GetExitLocked()) {
shutdown_time = 5000;
}

View File

@@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.h"

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.hpp"

View File

@@ -22,7 +22,7 @@ if (YUZU_CMD)
emu_window/emu_window_sdl2_null.h
emu_window/emu_window_sdl2_vk.cpp
emu_window/emu_window_sdl2_vk.h
precompiled_headers.h
precompiled_headers.hpp
sdl_config.cpp
sdl_config.h
yuzu.cpp
@@ -60,7 +60,7 @@ if (YUZU_CMD)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(yuzu-cmd PRIVATE precompiled_headers.h)
target_precompile_headers(yuzu-cmd PRIVATE precompiled_headers.hpp)
endif()
create_target_directory_groups(yuzu-cmd)

View File

@@ -1,6 +0,0 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.h"

View File

@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_precompiled_headers.hpp"

View File

@@ -436,13 +436,17 @@ int main(int argc, char** argv) {
#endif
void(system.Run());
#ifndef YUZU_NO_CPU_DEBUGGER
if (system.DebuggerEnabled()) {
system.InitializeDebugger();
}
#endif
while (emu_window->IsOpen()) {
emu_window->WaitEvent();
}
#ifndef YUZU_NO_CPU_DEBUGGER
system.DetachDebugger();
#endif
void(system.Pause());
system.ShutdownMainProcess();

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
"name": "yuzu",
"builtin-baseline": "c82f74667287d3dc386bce81e44964370c91a289",
"builtin-baseline": "bc994510d2eb11aac7b43b03f67a7751d5bfe0e4",
"version": "1.0",
"dependencies": [
"boost-algorithm",
@@ -16,7 +16,10 @@
"boost-icl",
"boost-intrusive",
"boost-mpl",
"boost-process",
{
"name": "boost-process",
"platform": "!android"
},
"boost-range",
"boost-spirit",
"boost-test",
@@ -48,6 +51,10 @@
{
"name": "oboe",
"platform": "android"
},
{
"name": "boost-fiber",
"platform": "android"
}
]
}