diff --git a/.ci/ios/build.sh b/.ci/ios/build.sh new file mode 100755 index 0000000000..cd3a57ec32 --- /dev/null +++ b/.ci/ios/build.sh @@ -0,0 +1,21 @@ +#!/bin/sh -ex + +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +WORK_DIR="$PWD" +xcrun --sdk iphoneos --show-sdk-path + +# TODO: support iphonesimulator sdk + +cmake -G Xcode -B build/ios \ + -DCMAKE_TOOLCHAIN_FILE="$WORK_DIR/.ci/ios/ios-toolchain.cmake" \ + -DPLATFORM=OS64 \ + -DARCHS="arm64" \ + -DDEPLOYMENT_TARGET=16.0 \ + -DCMAKE_C_COMPILER="$(xcrun --sdk iphoneos --find clang)" \ + -DCMAKE_CXX_COMPILER="$(xcrun --sdk iphoneos --find clang++)" \ + -DCMAKE_BUILD_TYPE=Release \ + "$@" + +cmake --build build/ios -t eden-ios --config Release diff --git a/.ci/ios/ios-toolchain.cmake b/.ci/ios/ios-toolchain.cmake new file mode 100644 index 0000000000..5eed07b32f --- /dev/null +++ b/.ci/ios/ios-toolchain.cmake @@ -0,0 +1,1180 @@ +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +# This file is part of the ios-cmake project. It was retrieved from +# https://github.com/leetal/ios-cmake.git, which is a fork of +# https://github.com/gerstrong/ios-cmake.git, which is a fork of +# https://github.com/cristeab/ios-cmake.git, which is a fork of +# https://code.google.com/p/ios-cmake/. Which in turn is based off of +# the Platform/Darwin.cmake and Platform/UnixPaths.cmake files which +# are included with CMake 2.8.4 +# +# The ios-cmake project is licensed under the new BSD license. +# +# Copyright (c) 2014, Bogdan Cristea and LTE Engineering Software, +# Kitware, Inc., Insight Software Consortium. All rights reserved. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# This file is based on the Platform/Darwin.cmake and +# Platform/UnixPaths.cmake files which are included with CMake 2.8.4 +# It has been altered for iOS development. +# +# Updated by Alex Stewart (alexs.mac@gmail.com) +# +# ***************************************************************************** +# Now maintained by Alexander Widerberg (widerbergaren [at] gmail.com) +# under the BSD-3-Clause license +# https://github.com/leetal/ios-cmake +# ***************************************************************************** +# +# INFORMATION / HELP +# +############################################################################### +# OPTIONS # +############################################################################### +# +# PLATFORM: (default "OS64") +# OS = Build for iPhoneOS. +# OS64 = Build for arm64 iphoneOS. +# OS64COMBINED = Build for arm64 x86_64 iphoneOS + iphoneOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR = Build for x86 i386 iphoneOS Simulator. +# SIMULATOR64 = Build for x86_64 iphoneOS Simulator. +# SIMULATORARM64 = Build for arm64 iphoneOS Simulator. +# SIMULATOR64COMBINED = Build for arm64 x86_64 iphoneOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) +# TVOS = Build for arm64 tvOS. +# TVOSCOMBINED = Build for arm64 x86_64 tvOS + tvOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR_TVOS = Build for x86_64 tvOS Simulator. +# SIMULATORARM64_TVOS = Build for arm64 tvOS Simulator. +# VISIONOSCOMBINED = Build for arm64 visionOS + visionOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# VISIONOS = Build for arm64 visionOS. +# SIMULATOR_VISIONOS = Build for arm64 visionOS Simulator. +# WATCHOS = Build for armv7k arm64_32 for watchOS. +# WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS + watchOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# SIMULATOR_WATCHOS = Build for x86_64 for watchOS Simulator. +# SIMULATORARM64_WATCHOS = Build for arm64 for watchOS Simulator. +# SIMULATOR_WATCHOSCOMBINED = Build for arm64 x86_64 for watchOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) +# MAC = Build for x86_64 macOS. +# MAC_ARM64 = Build for Apple Silicon macOS. +# MAC_UNIVERSAL = Combined build for x86_64 and Apple Silicon on macOS. +# MAC_CATALYST = Build for x86_64 macOS with Catalyst support (iOS toolchain on macOS). +# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# MAC_CATALYST_ARM64 = Build for Apple Silicon macOS with Catalyst support (iOS toolchain on macOS). +# Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# MAC_CATALYST_UNIVERSAL = Combined build for x86_64 and Apple Silicon on Catalyst. +# +# CMAKE_OSX_SYSROOT: Path to the SDK to use. By default this is +# automatically determined from PLATFORM and xcodebuild, but +# can also be manually specified (although this should not be required). +# +# CMAKE_DEVELOPER_ROOT: Path to the Developer directory for the platform +# being compiled for. By default, this is automatically determined from +# CMAKE_OSX_SYSROOT, but can also be manually specified (although this should +# not be required). +# +# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 6.0 on watchOS, 13.0 on tvOS+iOS/iPadOS, 11.0 on macOS, 1.0 on visionOS +# +# NAMED_LANGUAGE_SUPPORT: +# ON (default) = Will require "enable_language(OBJC) and/or enable_language(OBJCXX)" for full OBJC|OBJCXX support +# OFF = Will embed the OBJC and OBJCXX flags into the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (legacy behavior, CMake version < 3.16) +# +# ENABLE_BITCODE: (ON|OFF) Enables or disables bitcode support. Default OFF +# +# ENABLE_ARC: (ON|OFF) Enables or disables ARC support. Default ON (ARC enabled by default) +# +# ENABLE_VISIBILITY: (ON|OFF) Enables or disables symbol visibility support. Default OFF (visibility hidden by default) +# +# ENABLE_STRICT_TRY_COMPILE: (ON|OFF) Enables or disables strict try_compile() on all Check* directives (will run linker +# to actually check if linking is possible). Default OFF (will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY) +# +# ARCHS: (armv7 armv7s armv7k arm64 arm64_32 i386 x86_64) If specified, will override the default architectures for the given PLATFORM +# OS = armv7 armv7s arm64 (if applicable) +# OS64 = arm64 (if applicable) +# SIMULATOR = i386 +# SIMULATOR64 = x86_64 +# SIMULATORARM64 = arm64 +# TVOS = arm64 +# SIMULATOR_TVOS = x86_64 (i386 has since long been deprecated) +# SIMULATORARM64_TVOS = arm64 +# WATCHOS = armv7k arm64_32 (if applicable) +# SIMULATOR_WATCHOS = x86_64 (i386 has since long been deprecated) +# SIMULATORARM64_WATCHOS = arm64 +# MAC = x86_64 +# MAC_ARM64 = arm64 +# MAC_UNIVERSAL = x86_64 arm64 +# MAC_CATALYST = x86_64 +# MAC_CATALYST_ARM64 = arm64 +# MAC_CATALYST_UNIVERSAL = x86_64 arm64 +# +# NOTE: When manually specifying ARCHS, put a semi-colon between the entries. E.g., -DARCHS="armv7;arm64" +# +############################################################################### +# END OPTIONS # +############################################################################### +# +# This toolchain defines the following properties (available via get_property()) for use externally: +# +# PLATFORM: The currently targeted platform. +# XCODE_VERSION: Version number (not including Build version) of Xcode detected. +# SDK_VERSION: Version of SDK being used. +# OSX_ARCHITECTURES: Architectures being compiled for (generated from PLATFORM). +# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If "ARCHS" is overridden, this will *NOT* be set! +# +# This toolchain defines the following macros for use externally: +# +# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE XCODE_VARIANT) +# A convenience macro for setting xcode specific properties on targets. +# Available variants are: All, Release, RelWithDebInfo, Debug, MinSizeRel +# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1" "all"). +# +# find_host_package (PROGRAM ARGS) +# A macro used to find executable programs on the host system, not within the +# environment. Thanks to the android-cmake project for providing the +# command. +# + +cmake_minimum_required(VERSION 3.10) + +# CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds. +# NOTE: To improve single-library build-times, provide the flag "OS_SINGLE_BUILD" as a build argument. +if(DEFINED OS_SINGLE_BUILD AND DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN}) + return() +endif() +set(ENV{_IOS_TOOLCHAIN_HAS_RUN} true) + +# List of supported platform values +list(APPEND _supported_platforms + "OS" "OS64" "OS64COMBINED" "SIMULATOR" "SIMULATOR64" "SIMULATORARM64" "SIMULATOR64COMBINED" + "TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS" "SIMULATORARM64_TVOS" + "WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS" "SIMULATORARM64_WATCHOS" "SIMULATOR_WATCHOSCOMBINED" + "MAC" "MAC_ARM64" "MAC_UNIVERSAL" + "VISIONOS" "SIMULATOR_VISIONOS" "VISIONOSCOMBINED" + "MAC_CATALYST" "MAC_CATALYST_ARM64" "MAC_CATALYST_UNIVERSAL") + +# Cache what generator is used +set(USED_CMAKE_GENERATOR "${CMAKE_GENERATOR}") + +# Check if using a CMake version capable of building combined FAT builds (simulator and target slices combined in one static lib) +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14") + set(MODERN_CMAKE YES) +endif() + +# Get the Xcode version being used. +# Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs. +# Workaround: On the first run (in which cache variables are always accessible), set an intermediary environment variable. +# +# NOTE: This pattern is used in many places in this toolchain to speed up checks of all sorts +if(DEFINED XCODE_VERSION_INT) + # Environment variables are always preserved. + set(ENV{_XCODE_VERSION_INT} "${XCODE_VERSION_INT}") +elseif(DEFINED ENV{_XCODE_VERSION_INT}) + set(XCODE_VERSION_INT "$ENV{_XCODE_VERSION_INT}") +elseif(NOT DEFINED XCODE_VERSION_INT) + find_program(XCODEBUILD_EXECUTABLE xcodebuild) + if(NOT XCODEBUILD_EXECUTABLE) + message(FATAL_ERROR "xcodebuild not found. Please install either the standalone commandline tools or Xcode.") + endif() + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version + OUTPUT_VARIABLE XCODE_VERSION_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX MATCH "Xcode [0-9\\.]+" XCODE_VERSION_INT "${XCODE_VERSION_INT}") + string(REGEX REPLACE "Xcode ([0-9\\.]+)" "\\1" XCODE_VERSION_INT "${XCODE_VERSION_INT}") + set(XCODE_VERSION_INT "${XCODE_VERSION_INT}" CACHE INTERNAL "") +endif() + +# Assuming that xcode 12.0 is installed you most probably have ios sdk 14.0 or later installed (tested on Big Sur) +# if you don't set a deployment target it will be set the way you only get 64-bit builds +#if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0) +# Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...) +# set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] "arm64") +#endif() + +# Check if the platform variable is set +if(DEFINED PLATFORM) + # Environment variables are always preserved. + set(ENV{_PLATFORM} "${PLATFORM}") +elseif(DEFINED ENV{_PLATFORM}) + set(PLATFORM "$ENV{_PLATFORM}") +elseif(NOT DEFINED PLATFORM) + message(FATAL_ERROR "PLATFORM argument not set. Bailing configure since I don't know what target you want to build for!") +endif () + +if(PLATFORM MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") + message(FATAL_ERROR "The combined builds support requires Xcode to be used as a generator via '-G Xcode' command-line argument in CMake") +endif() + +# Safeguard that the platform value is set and is one of the supported values +list(FIND _supported_platforms ${PLATFORM} contains_PLATFORM) +if("${contains_PLATFORM}" EQUAL "-1") + string(REPLACE ";" "\n * " _supported_platforms_formatted "${_supported_platforms}") + message(FATAL_ERROR " Invalid PLATFORM specified! Current value: ${PLATFORM}.\n" + " Supported PLATFORM values: \n * ${_supported_platforms_formatted}") +endif() + +# Check if Apple Silicon is supported +if(PLATFORM MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$|^(MAC_UNIVERSAL)$|^(MAC_CATALYST_UNIVERSAL)$" AND ${CMAKE_VERSION} VERSION_LESS "3.19.5") + message(FATAL_ERROR "Apple Silicon builds requires a minimum of CMake 3.19.5") +endif() + +# Touch the toolchain variable to suppress the "unused variable" warning. +# This happens if CMake is invoked with the same command line the second time. +if(CMAKE_TOOLCHAIN_FILE) +endif() + +# Fix for PThread library not in path +set(CMAKE_THREAD_LIBS_INIT "-lpthread") +set(CMAKE_HAVE_THREADS_LIBRARY 1) +set(CMAKE_USE_WIN32_THREADS_INIT 0) +set(CMAKE_USE_PTHREADS_INIT 1) + +# Specify named language support defaults. +if(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16") + set(NAMED_LANGUAGE_SUPPORT ON) + message(STATUS "[DEFAULTS] Using explicit named language support! E.g., enable_language(CXX) is needed in the project files.") +elseif(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") + set(NAMED_LANGUAGE_SUPPORT OFF) + message(STATUS "[DEFAULTS] Disabling explicit named language support. Falling back to legacy behavior.") +elseif(DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") + message(FATAL_ERROR "CMake named language support for OBJC and OBJCXX was added in CMake 3.16.") +endif() +set(NAMED_LANGUAGE_SUPPORT_INT ${NAMED_LANGUAGE_SUPPORT} CACHE BOOL + "Whether or not to enable explicit named language support" FORCE) + +# Specify the minimum version of the deployment target. +if(NOT DEFINED DEPLOYMENT_TARGET) + if (PLATFORM MATCHES "WATCHOS") + # Unless specified, SDK version 6.0 is used by default as minimum target version (watchOS). + set(DEPLOYMENT_TARGET "6.0") + elseif(PLATFORM STREQUAL "MAC") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on x86). + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") + # Unless specified, SDK version 1.0 is used by default as minimum target version (visionOS). + set(DEPLOYMENT_TARGET "1.0") + elseif(PLATFORM STREQUAL "MAC_ARM64") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on arm). + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "MAC_UNIVERSAL") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version for universal builds. + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") + # Unless specified, SDK version 13.1 is used by default as the minimum target version (mac catalyst minimum requirement). + set(DEPLOYMENT_TARGET "13.1") + else() + # Unless specified, SDK version 13.0 is used by default as the minimum target version (iOS, tvOS). + set(DEPLOYMENT_TARGET "13.0") + endif() + message(STATUS "[DEFAULTS] Using the default min-version since DEPLOYMENT_TARGET not provided!") +elseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM MATCHES "^MAC_CATALYST" AND ${DEPLOYMENT_TARGET} VERSION_LESS "13.1") + message(FATAL_ERROR "Mac Catalyst builds requires a minimum deployment target of 13.1!") +endif() + +# Store the DEPLOYMENT_TARGET in the cache +set(DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}" CACHE INTERNAL "") + +# Handle the case where we are targeting iOS and a version above 10.3.4 (32-bit support dropped officially) +if(PLATFORM STREQUAL "OS" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) + set(PLATFORM "OS64") + message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") +elseif(PLATFORM STREQUAL "SIMULATOR" AND DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.3.4) + set(PLATFORM "SIMULATOR64") + message(STATUS "Targeting minimum SDK version ${DEPLOYMENT_TARGET}. Dropping 32-bit support.") +endif() + +set(PLATFORM_INT "${PLATFORM}") + +if(DEFINED ARCHS) + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") +endif() + +# Determine the platform name and architectures for use in xcodebuild commands +# from the specified PLATFORM_INT name. +if(PLATFORM_INT STREQUAL "OS") + set(SDK_NAME iphoneos) + if(NOT ARCHS) + set(ARCHS armv7 armv7s arm64) + set(APPLE_TARGET_TRIPLE_INT arm-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "OS64") + set(SDK_NAME iphoneos) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS arm64) # FIXME: Add arm64e when Apple has fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example + else() + set(ARCHS arm64) + endif() + set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "OS64COMBINED") + set(SDK_NAME iphoneos) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + else() + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + endif() + set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-ios${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the OS64COMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR64COMBINED") + set(SDK_NAME iphonesimulator) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) # FIXME: Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + else() + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + endif() + set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the SIMULATOR64COMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS i386) + set(APPLE_TARGET_TRIPLE_INT i386-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() + message(DEPRECATION "SIMULATOR IS DEPRECATED. Consider using SIMULATOR64 instead.") +elseif(PLATFORM_INT STREQUAL "SIMULATOR64") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64") + set(SDK_NAME iphonesimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "TVOS") + set(SDK_NAME appletvos) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) + endif() +elseif (PLATFORM_INT STREQUAL "TVOSCOMBINED") + set(SDK_NAME appletvos) + if(MODERN_CMAKE) + if(NOT ARCHS) + set(ARCHS arm64 x86_64) + set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-tvos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvos*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the TVOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") + set(SDK_NAME appletvsimulator) + if(NOT ARCHS) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-tvos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") + set(SDK_NAME appletvsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "WATCHOS") + set(SDK_NAME watchos) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS armv7k arm64_32) + set(APPLE_TARGET_TRIPLE_INT arm64_32-apple-watchos${DEPLOYMENT_TARGET}) + else() + set(ARCHS armv7k) + set(APPLE_TARGET_TRIPLE_INT arm-apple-watchos${DEPLOYMENT_TARGET}) + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "WATCHOSCOMBINED") + set(SDK_NAME watchos) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS armv7k arm64_32 x86_64) + set(APPLE_TARGET_TRIPLE_INT arm64_32-x86_64-apple-watchos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k arm64_32") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k arm64_32") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "x86_64") + else() + set(ARCHS armv7k i386) + set(APPLE_TARGET_TRIPLE_INT arm-i386-apple-watchos${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the WATCHOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") + set(SDK_NAME watchsimulator) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 10.0) + set(ARCHS x86_64) + set(APPLE_TARGET_TRIPLE_INT x86_64-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(ARCHS i386) + set(APPLE_TARGET_TRIPLE_INT i386-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") + set(SDK_NAME watchsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOSCOMBINED") + set(SDK_NAME watchsimulator) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "arm64 x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "arm64 x86_64") + set(APPLE_TARGET_TRIPLE_INT arm64_x86_64-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(ARCHS arm64 i386) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchsimulator*] "i386") + set(APPLE_TARGET_TRIPLE_INT arm64_i386-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the SIMULATOR_WATCHOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_VISIONOS") + set(SDK_NAME xrsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "VISIONOS") + set(SDK_NAME xros) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "VISIONOSCOMBINED") + set(SDK_NAME xros) + if(MODERN_CMAKE) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xros*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xrsimulator*] "arm64") + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the VISIONOSCOMBINED setting work") + endif() +elseif(PLATFORM_INT STREQUAL "MAC" OR PLATFORM_INT STREQUAL "MAC_CATALYST") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS x86_64) + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + if(PLATFORM_INT STREQUAL "MAC") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) + elseif(PLATFORM_INT STREQUAL "MAC_CATALYST") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) + endif() +elseif(PLATFORM_INT MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS arm64) + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + if(PLATFORM_INT STREQUAL "MAC_ARM64") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) + elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_ARM64") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) + endif() +elseif(PLATFORM_INT STREQUAL "MAC_UNIVERSAL") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS "x86_64;arm64") + endif() + # For universal builds, don't set target triple - let CMake handle it + # string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + # set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) +elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_UNIVERSAL") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS "x86_64;arm64") + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + set(APPLE_TARGET_TRIPLE_INT apple-ios${DEPLOYMENT_TARGET}-macabi) +else() + message(FATAL_ERROR "Invalid PLATFORM: ${PLATFORM_INT}") +endif() + +string(REPLACE ";" " " ARCHS_SPACED "${ARCHS}") + +if(MODERN_CMAKE AND PLATFORM_INT MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") + message(FATAL_ERROR "The COMBINED options only work with Xcode generator, -G Xcode") +endif() + +if(CMAKE_GENERATOR MATCHES "Xcode" AND PLATFORM_INT MATCHES "^MAC_CATALYST") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "macosx") + set(CMAKE_XCODE_ATTRIBUTE_SUPPORTS_MACCATALYST "YES") + if(NOT DEFINED MACOSX_DEPLOYMENT_TARGET) + set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "10.15") + else() + set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "${MACOSX_DEPLOYMENT_TARGET}") + endif() +elseif(CMAKE_GENERATOR MATCHES "Xcode") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}") + if(NOT PLATFORM_INT MATCHES ".*COMBINED") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") + endif() +endif() + +# If the user did not specify the SDK root to use, then query xcodebuild for it. +if(DEFINED CMAKE_OSX_SYSROOT_INT) + # Environment variables are always preserved. + set(ENV{_CMAKE_OSX_SYSROOT_INT} "${CMAKE_OSX_SYSROOT_INT}") +elseif(DEFINED ENV{_CMAKE_OSX_SYSROOT_INT}) + set(CMAKE_OSX_SYSROOT_INT "$ENV{_CMAKE_OSX_SYSROOT_INT}") +elseif(NOT DEFINED CMAKE_OSX_SYSROOT_INT) + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -version -sdk ${SDK_NAME} Path + OUTPUT_VARIABLE CMAKE_OSX_SYSROOT_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +if (NOT DEFINED CMAKE_OSX_SYSROOT_INT AND NOT DEFINED CMAKE_OSX_SYSROOT) + message(SEND_ERROR "Please make sure that Xcode is installed and that the toolchain" + "is pointing to the correct path. Please run:" + "sudo xcode-select -s /Applications/Xcode.app/Contents/Developer" + "and see if that fixes the problem for you.") + message(FATAL_ERROR "Invalid CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT} " + "does not exist.") +elseif(DEFINED CMAKE_OSX_SYSROOT_INT) + set(CMAKE_OSX_SYSROOT_INT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + # Specify the location or name of the platform SDK to be used in CMAKE_OSX_SYSROOT. + set(CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") +endif() + +# Use bitcode or not +if(NOT DEFINED ENABLE_BITCODE) + message(STATUS "[DEFAULTS] Disabling bitcode support by default. ENABLE_BITCODE not provided for override!") + set(ENABLE_BITCODE OFF) +endif() +set(ENABLE_BITCODE_INT ${ENABLE_BITCODE} CACHE BOOL + "Whether or not to enable bitcode" FORCE) +# Use ARC or not +if(NOT DEFINED ENABLE_ARC) + # Unless specified, enable ARC support by default + set(ENABLE_ARC ON) + message(STATUS "[DEFAULTS] Enabling ARC support by default. ENABLE_ARC not provided!") +endif() +set(ENABLE_ARC_INT ${ENABLE_ARC} CACHE BOOL "Whether or not to enable ARC" FORCE) +# Use hidden visibility or not +if(NOT DEFINED ENABLE_VISIBILITY) + # Unless specified, disable symbols visibility by default + set(ENABLE_VISIBILITY OFF) + message(STATUS "[DEFAULTS] Hiding symbols visibility by default. ENABLE_VISIBILITY not provided!") +endif() +set(ENABLE_VISIBILITY_INT ${ENABLE_VISIBILITY} CACHE BOOL "Whether or not to hide symbols from the dynamic linker (-fvisibility=hidden)" FORCE) +# Set strict compiler checks or not +if(NOT DEFINED ENABLE_STRICT_TRY_COMPILE) + # Unless specified, disable strict try_compile() + set(ENABLE_STRICT_TRY_COMPILE OFF) + message(STATUS "[DEFAULTS] Using NON-strict compiler checks by default. ENABLE_STRICT_TRY_COMPILE not provided!") +endif() +set(ENABLE_STRICT_TRY_COMPILE_INT ${ENABLE_STRICT_TRY_COMPILE} CACHE BOOL + "Whether or not to use strict compiler checks" FORCE) + +# Get the SDK version information. +if(DEFINED SDK_VERSION) + # Environment variables are always preserved. + set(ENV{_SDK_VERSION} "${SDK_VERSION}") +elseif(DEFINED ENV{_SDK_VERSION}) + set(SDK_VERSION "$ENV{_SDK_VERSION}") +elseif(NOT DEFINED SDK_VERSION) + execute_process(COMMAND ${XCODEBUILD_EXECUTABLE} -sdk ${CMAKE_OSX_SYSROOT_INT} -version SDKVersion + OUTPUT_VARIABLE SDK_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +# Find the Developer root for the specific iOS platform being compiled for +# from CMAKE_OSX_SYSROOT. Should be ../../ from SDK specified in +# CMAKE_OSX_SYSROOT. There does not appear to be a direct way to obtain +# this information from xcrun or xcodebuild. +if (NOT DEFINED CMAKE_DEVELOPER_ROOT AND NOT CMAKE_GENERATOR MATCHES "Xcode") + get_filename_component(PLATFORM_SDK_DIR ${CMAKE_OSX_SYSROOT_INT} PATH) + get_filename_component(CMAKE_DEVELOPER_ROOT ${PLATFORM_SDK_DIR} PATH) + if (NOT EXISTS "${CMAKE_DEVELOPER_ROOT}") + message(FATAL_ERROR "Invalid CMAKE_DEVELOPER_ROOT: ${CMAKE_DEVELOPER_ROOT} does not exist.") + endif() +endif() + +# Find the C & C++ compilers for the specified SDK. +if(DEFINED CMAKE_C_COMPILER) + # Environment variables are always preserved. + set(ENV{_CMAKE_C_COMPILER} "${CMAKE_C_COMPILER}") +elseif(DEFINED ENV{_CMAKE_C_COMPILER}) + set(CMAKE_C_COMPILER "$ENV{_CMAKE_C_COMPILER}") + set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +elseif(NOT DEFINED CMAKE_C_COMPILER) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang + OUTPUT_VARIABLE CMAKE_C_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER}) +endif() +if(DEFINED CMAKE_CXX_COMPILER) + # Environment variables are always preserved. + set(ENV{_CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER}") +elseif(DEFINED ENV{_CMAKE_CXX_COMPILER}) + set(CMAKE_CXX_COMPILER "$ENV{_CMAKE_CXX_COMPILER}") +elseif(NOT DEFINED CMAKE_CXX_COMPILER) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find clang++ + OUTPUT_VARIABLE CMAKE_CXX_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +# Find (Apple's) libtool. +if(DEFINED BUILD_LIBTOOL) + # Environment variables are always preserved. + set(ENV{_BUILD_LIBTOOL} "${BUILD_LIBTOOL}") +elseif(DEFINED ENV{_BUILD_LIBTOOL}) + set(BUILD_LIBTOOL "$ENV{_BUILD_LIBTOOL}") +elseif(NOT DEFINED BUILD_LIBTOOL) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find libtool + OUTPUT_VARIABLE BUILD_LIBTOOL + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() +# Find the toolchain's provided install_name_tool if none is found on the host +if(DEFINED CMAKE_INSTALL_NAME_TOOL) + # Environment variables are always preserved. + set(ENV{_CMAKE_INSTALL_NAME_TOOL} "${CMAKE_INSTALL_NAME_TOOL}") +elseif(DEFINED ENV{_CMAKE_INSTALL_NAME_TOOL}) + set(CMAKE_INSTALL_NAME_TOOL "$ENV{_CMAKE_INSTALL_NAME_TOOL}") +elseif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + execute_process(COMMAND xcrun -sdk ${CMAKE_OSX_SYSROOT_INT} -find install_name_tool + OUTPUT_VARIABLE CMAKE_INSTALL_NAME_TOOL_INT + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_INSTALL_NAME_TOOL ${CMAKE_INSTALL_NAME_TOOL_INT} CACHE INTERNAL "") +endif() + +# Configure libtool to be used instead of ar + ranlib to build static libraries. +# This is required on Xcode 7+, but should also work on previous versions of +# Xcode. +get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(lang ${languages}) + set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "${BUILD_LIBTOOL} -static -o " CACHE INTERNAL "") +endforeach() + +# CMake 3.14+ support building for iOS, watchOS, and tvOS out of the box. +if(MODERN_CMAKE) + if(SDK_NAME MATCHES "iphone") + set(CMAKE_SYSTEM_NAME iOS) + elseif(SDK_NAME MATCHES "xros") + set(CMAKE_SYSTEM_NAME visionOS) + elseif(SDK_NAME MATCHES "xrsimulator") + set(CMAKE_SYSTEM_NAME visionOS) + elseif(SDK_NAME MATCHES "macosx") + set(CMAKE_SYSTEM_NAME Darwin) + elseif(SDK_NAME MATCHES "appletv") + set(CMAKE_SYSTEM_NAME tvOS) + elseif(SDK_NAME MATCHES "watch") + set(CMAKE_SYSTEM_NAME watchOS) + endif() + # Provide flags for a combined FAT library build on newer CMake versions + if(PLATFORM_INT MATCHES ".*COMBINED") + set(CMAKE_IOS_INSTALL_COMBINED YES) + if(CMAKE_GENERATOR MATCHES "Xcode") + # Set the SDKROOT Xcode properties to a Xcode-friendly value (the SDK_NAME, E.g, iphoneos) + # This way, Xcode will automatically switch between the simulator and device SDK when building. + set(CMAKE_XCODE_ATTRIBUTE_SDKROOT "${SDK_NAME}") + # Force to not build just one ARCH, but all! + set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "NO") + endif() + endif() +elseif(NOT DEFINED CMAKE_SYSTEM_NAME AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.10") + # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + set(CMAKE_SYSTEM_NAME iOS) +elseif(NOT DEFINED CMAKE_SYSTEM_NAME) + # Legacy code path before CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + set(CMAKE_SYSTEM_NAME Darwin) +endif() +# Standard settings. +set(CMAKE_SYSTEM_VERSION ${SDK_VERSION} CACHE INTERNAL "") +set(UNIX ON CACHE BOOL "") +set(APPLE ON CACHE BOOL "") +if(PLATFORM STREQUAL "MAC" OR PLATFORM STREQUAL "MAC_ARM64" OR PLATFORM STREQUAL "MAC_UNIVERSAL") + set(IOS OFF CACHE BOOL "") + set(MACOS ON CACHE BOOL "") +elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") + set(IOS ON CACHE BOOL "") + set(MACOS ON CACHE BOOL "") +elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") + set(IOS OFF CACHE BOOL "") + set(VISIONOS ON CACHE BOOL "") +else() + set(IOS ON CACHE BOOL "") +endif() +# Set the architectures for which to build. +set(CMAKE_OSX_ARCHITECTURES ${ARCHS} CACHE INTERNAL "") +# Change the type of target generated for try_compile() so it'll work when cross-compiling, weak compiler checks +if(NOT ENABLE_STRICT_TRY_COMPILE_INT) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +endif() +# All iOS/Darwin specific settings - some may be redundant. +if (NOT DEFINED CMAKE_MACOSX_BUNDLE) + set(CMAKE_MACOSX_BUNDLE YES) +endif() +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") +set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES ".tbd" ".so") +set(CMAKE_SHARED_MODULE_PREFIX "lib") +set(CMAKE_SHARED_MODULE_SUFFIX ".so") +set(CMAKE_C_COMPILER_ABI ELF) +set(CMAKE_CXX_COMPILER_ABI ELF) +set(CMAKE_C_HAS_ISYSROOT 1) +set(CMAKE_CXX_HAS_ISYSROOT 1) +set(CMAKE_MODULE_EXISTS 1) +set(CMAKE_DL_LIBS "") +set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") +set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") +set(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") + +if(ARCHS MATCHES "((^|;|, )(arm64|arm64e|x86_64))+") + set(CMAKE_C_SIZEOF_DATA_PTR 8) + set(CMAKE_CXX_SIZEOF_DATA_PTR 8) + if(ARCHS MATCHES "((^|;|, )(arm64|arm64e))+") + set(CMAKE_SYSTEM_PROCESSOR "aarch64") + else() + set(CMAKE_SYSTEM_PROCESSOR "x86_64") + endif() +else() + set(CMAKE_C_SIZEOF_DATA_PTR 4) + set(CMAKE_CXX_SIZEOF_DATA_PTR 4) + set(CMAKE_SYSTEM_PROCESSOR "arm") +endif() + +# Note that only Xcode 7+ supports the newer more specific: +# -m${SDK_NAME}-version-min flags, older versions of Xcode use: +# -m(ios/ios-simulator)-version-min instead. +if(${CMAKE_VERSION} VERSION_LESS "3.11") + if(PLATFORM_INT STREQUAL "OS" OR PLATFORM_INT STREQUAL "OS64") + if(XCODE_VERSION_INT VERSION_LESS 7.0) + set(SDK_NAME_VERSION_FLAGS + "-mios-version-min=${DEPLOYMENT_TARGET}") + else() + # Xcode 7.0+ uses flags we can build directly from SDK_NAME. + set(SDK_NAME_VERSION_FLAGS + "-m${SDK_NAME}-version-min=${DEPLOYMENT_TARGET}") + endif() + elseif(PLATFORM_INT STREQUAL "TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "MAC") + set(SDK_NAME_VERSION_FLAGS + "-mmacosx-version-min=${DEPLOYMENT_TARGET}") + else() + # SIMULATOR or SIMULATOR64 both use -mios-simulator-version-min. + set(SDK_NAME_VERSION_FLAGS + "-mios-simulator-version-min=${DEPLOYMENT_TARGET}") + endif() +elseif(NOT PLATFORM_INT MATCHES "^MAC_CATALYST") + # Newer versions of CMake sets the version min flags correctly, skip this for Mac Catalyst targets + set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} CACHE INTERNAL "Minimum OS X deployment version") +endif() + +if(DEFINED APPLE_TARGET_TRIPLE_INT) + set(APPLE_TARGET_TRIPLE ${APPLE_TARGET_TRIPLE_INT} CACHE INTERNAL "") + set(CMAKE_C_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) + set(CMAKE_CXX_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) + set(CMAKE_ASM_COMPILER_TARGET ${APPLE_TARGET_TRIPLE}) +endif() + +if(PLATFORM_INT MATCHES "^MAC_CATALYST") + set(C_TARGET_FLAGS "-isystem ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/usr/include -iframework ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks") +endif() + +if(ENABLE_BITCODE_INT) + set(BITCODE "-fembed-bitcode") + set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE "bitcode") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") +else() + set(BITCODE "") + set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") +endif() + +if(ENABLE_ARC_INT) + set(FOBJC_ARC "-fobjc-arc") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES") +else() + set(FOBJC_ARC "-fno-objc-arc") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO") +endif() + +if(NAMED_LANGUAGE_SUPPORT_INT) + set(OBJC_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") + set(OBJC_LEGACY_VARS "") +else() + set(OBJC_VARS "") + set(OBJC_LEGACY_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") +endif() + +if(NOT ENABLE_VISIBILITY_INT) + foreach(lang ${languages}) + set(CMAKE_${lang}_VISIBILITY_PRESET "hidden" CACHE INTERNAL "") + endforeach() + set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES") + set(VISIBILITY "-fvisibility=hidden -fvisibility-inlines-hidden") +else() + foreach(lang ${languages}) + set(CMAKE_${lang}_VISIBILITY_PRESET "default" CACHE INTERNAL "") + endforeach() + set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "NO") + set(VISIBILITY "-fvisibility=default") +endif() + +if(DEFINED APPLE_TARGET_TRIPLE) + set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}") +endif() + +#Check if Xcode generator is used since that will handle these flags automagically +if(CMAKE_GENERATOR MATCHES "Xcode") + message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.") +else() + set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all C build types.") + set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}") + set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}") + set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all CXX build types.") + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}") + if(NAMED_LANGUAGE_SUPPORT_INT) + set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all OBJC build types.") + set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}") + set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}") + set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}") + set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all OBJCXX build types.") + set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}") + set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}") + set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}") + endif() + set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all C link types.") + set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all CXX link types.") + if(NAMED_LANGUAGE_SUPPORT_INT) + set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all OBJC link types.") + set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all OBJCXX link types.") + endif() + set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp" CACHE INTERNAL + "Flags used by the compiler for all ASM build types.") +endif() + +## Print status messages to inform of the current state +message(STATUS "Configuring ${SDK_NAME} build for platform: ${PLATFORM_INT}, architecture(s): ${ARCHS}") +message(STATUS "Using SDK: ${CMAKE_OSX_SYSROOT_INT}") +message(STATUS "Using C compiler: ${CMAKE_C_COMPILER}") +message(STATUS "Using CXX compiler: ${CMAKE_CXX_COMPILER}") +message(STATUS "Using libtool: ${BUILD_LIBTOOL}") +message(STATUS "Using install name tool: ${CMAKE_INSTALL_NAME_TOOL}") +if(DEFINED APPLE_TARGET_TRIPLE) + message(STATUS "Autoconf target triple: ${APPLE_TARGET_TRIPLE}") +endif() +message(STATUS "Using minimum deployment version: ${DEPLOYMENT_TARGET}" + " (SDK version: ${SDK_VERSION})") +if(MODERN_CMAKE) + message(STATUS "Merging integrated CMake 3.14+ iOS,tvOS,watchOS,macOS toolchain(s) with this toolchain!") + if(PLATFORM_INT MATCHES ".*COMBINED") + message(STATUS "Will combine built (static) artifacts into FAT lib...") + endif() +endif() +if(CMAKE_GENERATOR MATCHES "Xcode") + message(STATUS "Using Xcode version: ${XCODE_VERSION_INT}") +endif() +message(STATUS "CMake version: ${CMAKE_VERSION}") +if(DEFINED SDK_NAME_VERSION_FLAGS) + message(STATUS "Using version flags: ${SDK_NAME_VERSION_FLAGS}") +endif() +message(STATUS "Using a data_ptr size of: ${CMAKE_CXX_SIZEOF_DATA_PTR}") +if(ENABLE_BITCODE_INT) + message(STATUS "Bitcode: Enabled") +else() + message(STATUS "Bitcode: Disabled") +endif() + +if(ENABLE_ARC_INT) + message(STATUS "ARC: Enabled") +else() + message(STATUS "ARC: Disabled") +endif() + +if(ENABLE_VISIBILITY_INT) + message(STATUS "Hiding symbols: Disabled") +else() + message(STATUS "Hiding symbols: Enabled") +endif() + +# Set global properties +set_property(GLOBAL PROPERTY PLATFORM "${PLATFORM}") +set_property(GLOBAL PROPERTY APPLE_TARGET_TRIPLE "${APPLE_TARGET_TRIPLE_INT}") +set_property(GLOBAL PROPERTY SDK_VERSION "${SDK_VERSION}") +set_property(GLOBAL PROPERTY XCODE_VERSION "${XCODE_VERSION_INT}") +set_property(GLOBAL PROPERTY OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") + +# Export configurable variables for the try_compile() command. +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES + PLATFORM + XCODE_VERSION_INT + SDK_VERSION + NAMED_LANGUAGE_SUPPORT + DEPLOYMENT_TARGET + CMAKE_DEVELOPER_ROOT + CMAKE_OSX_SYSROOT_INT + ENABLE_BITCODE + ENABLE_ARC + CMAKE_ASM_COMPILER + CMAKE_C_COMPILER + CMAKE_C_COMPILER_TARGET + CMAKE_CXX_COMPILER + CMAKE_CXX_COMPILER_TARGET + BUILD_LIBTOOL + CMAKE_INSTALL_NAME_TOOL + CMAKE_C_FLAGS + CMAKE_C_DEBUG + CMAKE_C_MINSIZEREL + CMAKE_C_RELWITHDEBINFO + CMAKE_C_RELEASE + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_LINK_FLAGS + CMAKE_CXX_LINK_FLAGS + CMAKE_ASM_FLAGS +) + +if(NAMED_LANGUAGE_SUPPORT_INT) + list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES + CMAKE_OBJC_FLAGS + CMAKE_OBJC_DEBUG + CMAKE_OBJC_MINSIZEREL + CMAKE_OBJC_RELWITHDEBINFO + CMAKE_OBJC_RELEASE + CMAKE_OBJCXX_FLAGS + CMAKE_OBJCXX_DEBUG + CMAKE_OBJCXX_MINSIZEREL + CMAKE_OBJCXX_RELWITHDEBINFO + CMAKE_OBJCXX_RELEASE + CMAKE_OBJC_LINK_FLAGS + CMAKE_OBJCXX_LINK_FLAGS + ) +endif() + +set(CMAKE_PLATFORM_HAS_INSTALLNAME 1) +set(CMAKE_SHARED_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks") +set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -Wl,-headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -Wl,-headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") +set(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".tbd" ".dylib" ".so" ".a") +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") + +# Set the find root to the SDK developer roots. +# Note: CMAKE_FIND_ROOT_PATH is only useful when cross-compiling. Thus, do not set on macOS builds. +if(NOT PLATFORM_INT MATCHES "^MAC.*$") + list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + set(CMAKE_IGNORE_PATH "/System/Library/Frameworks;/usr/local/lib;/opt/homebrew" CACHE INTERNAL "") +endif() + +# Default to searching for frameworks first. +IF(NOT DEFINED CMAKE_FIND_FRAMEWORK) + set(CMAKE_FIND_FRAMEWORK FIRST) +ENDIF(NOT DEFINED CMAKE_FIND_FRAMEWORK) + +# Set up the default search directories for frameworks. +if(PLATFORM_INT MATCHES "^MAC_CATALYST") + set(CMAKE_FRAMEWORK_PATH + ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks + ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks + ${CMAKE_OSX_SYSROOT_INT}/System/iOSSupport/System/Library/Frameworks + ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") +else() + set(CMAKE_FRAMEWORK_PATH + ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks + ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks + ${CMAKE_FRAMEWORK_PATH} CACHE INTERNAL "") +endif() + +# By default, search both the specified iOS SDK and the remainder of the host filesystem. +if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH CACHE INTERNAL "") +endif() +if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH CACHE INTERNAL "") +endif() + +# +# Some helper-macros below to simplify and beautify the CMakeFile +# + +# This little macro lets you set any Xcode specific property. +macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE XCODE_RELVERSION) + set(XCODE_RELVERSION_I "${XCODE_RELVERSION}") + if(XCODE_RELVERSION_I STREQUAL "All") + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} "${XCODE_VALUE}") + else() + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY}[variant=${XCODE_RELVERSION_I}] "${XCODE_VALUE}") + endif() +endmacro(set_xcode_property) + +# This macro lets you find executable programs on the host system. +macro(find_host_package) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) + set(_TOOLCHAIN_IOS ${IOS}) + set(IOS OFF) + find_package(${ARGN}) + set(IOS ${_TOOLCHAIN_IOS}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) +endmacro(find_host_package) diff --git a/.ci/license-header.sh b/.ci/license-header.sh index 6b19f91185..b674234c7c 100755 --- a/.ci/license-header.sh +++ b/.ci/license-header.sh @@ -115,7 +115,7 @@ for file in $FILES; do *.cmake|*.sh|*CMakeLists.txt) begin="#" ;; - *.kt*|*.cpp|*.h|*.qml) + *.kt*|*.cpp|*.h|*.qml|*.swift|*.mm) begin="//" ;; *) diff --git a/.patch/boost/0002-ios-fix.patch b/.patch/boost/0002-ios-fix.patch new file mode 100644 index 0000000000..4f5d495154 --- /dev/null +++ b/.patch/boost/0002-ios-fix.patch @@ -0,0 +1,31 @@ +diff --git a/libs/process/src/shell.cpp b/libs/process/src/shell.cpp +index bf4bbfd8..bc4aae89 100644 +--- a/libs/process/src/shell.cpp ++++ b/libs/process/src/shell.cpp +@@ -19,7 +19,7 @@ + #if defined(BOOST_PROCESS_V2_WINDOWS) + #include + #include +-#elif !defined(__OpenBSD__) && !defined(__ANDROID__) ++#elif !defined(__OpenBSD__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IPHONE) + #include + #endif + +@@ -30,7 +30,7 @@ BOOST_PROCESS_V2_DECL const error_category& get_shell_category() + { + return system_category(); + } +-#elif !defined(__OpenBSD__) && !defined(__ANDROID__) ++#elif !defined(__OpenBSD__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IPHONE) + + struct shell_category_t final : public error_category + { +@@ -99,7 +99,7 @@ auto shell::args() const-> args_type + return input_.c_str(); + } + +-#elif !defined(__OpenBSD__) && !defined(__ANDROID__) ++#elif !defined(__OpenBSD__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IPHONE) + + void shell::parse_() + { diff --git a/.patch/mcl/0001-assert-macro.patch b/.patch/mcl/0001-assert-macro.patch deleted file mode 100644 index 2d7d0dd1b0..0000000000 --- a/.patch/mcl/0001-assert-macro.patch +++ /dev/null @@ -1,55 +0,0 @@ -diff --git a/include/mcl/assert.hpp b/include/mcl/assert.hpp -index f77dbe7..9ec0b9c 100644 ---- a/include/mcl/assert.hpp -+++ b/include/mcl/assert.hpp -@@ -23,8 +23,11 @@ template - - } // namespace mcl::detail - -+#ifndef UNREACHABLE - #define UNREACHABLE() ASSERT_FALSE("Unreachable code!") -+#endif - -+#ifndef ASSERT - #define ASSERT(expr) \ - [&] { \ - if (std::is_constant_evaluated()) { \ -@@ -37,7 +40,9 @@ template - } \ - } \ - }() -+#endif - -+#ifndef ASSERT_MSG - #define ASSERT_MSG(expr, ...) \ - [&] { \ - if (std::is_constant_evaluated()) { \ -@@ -50,13 +55,24 @@ template - } \ - } \ - }() -+#endif - -+#ifndef ASSERT_FALSE - #define ASSERT_FALSE(...) ::mcl::detail::assert_terminate("false", __VA_ARGS__) -+#endif - - #if defined(NDEBUG) || defined(MCL_IGNORE_ASSERTS) --# define DEBUG_ASSERT(expr) ASSUME(expr) --# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr) -+# ifndef DEBUG_ASSERT -+# define DEBUG_ASSERT(expr) ASSUME(expr) -+# endif -+# ifndef DEBUG_ASSERT_MSG -+# define DEBUG_ASSERT_MSG(expr, ...) ASSUME(expr) -+# endif - #else --# define DEBUG_ASSERT(expr) ASSERT(expr) --# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__) -+# ifndef DEBUG_ASSERT -+# define DEBUG_ASSERT(expr) ASSERT(expr) -+# endif -+# ifndef DEBUG_ASSERT_MSG -+# define DEBUG_ASSERT_MSG(expr, ...) ASSERT_MSG(expr, __VA_ARGS__) -+# endif - #endif diff --git a/.patch/spirv-tools/0003-ios-fix.patch b/.patch/spirv-tools/0003-ios-fix.patch new file mode 100644 index 0000000000..7d5710ef68 --- /dev/null +++ b/.patch/spirv-tools/0003-ios-fix.patch @@ -0,0 +1,33 @@ +diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt +index 7ab2319..333e325 100644 +--- a/source/CMakeLists.txt ++++ b/source/CMakeLists.txt +@@ -151,9 +151,11 @@ add_custom_command(OUTPUT ${SPIRV_TOOLS_BUILD_VERSION_INC} + COMMENT "Update build-version.inc in the SPIRV-Tools build directory (if necessary).") + # Convenience target for standalone generation of the build-version.inc file. + # This is not required for any dependence chain. +-add_custom_target(spirv-tools-build-version +- DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC}) +-set_property(TARGET spirv-tools-build-version PROPERTY FOLDER "SPIRV-Tools build") ++if (NOT IOS) ++ add_custom_target(spirv-tools-build-version ++ DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC}) ++ set_property(TARGET spirv-tools-build-version PROPERTY FOLDER "SPIRV-Tools build") ++endif() + + list(APPEND PCH_DEPENDS + ${CORE_TABLES_HEADER_INC_FILE} +@@ -338,8 +340,11 @@ function(spirv_tools_default_target_options target) + ) + set_property(TARGET ${target} PROPERTY FOLDER "SPIRV-Tools libraries") + spvtools_check_symbol_exports(${target}) +- add_dependencies(${target} +- spirv-tools-build-version core_tables extinst_tables) ++ if (IOS) ++ add_dependencies(${target} core_tables extinst_tables) ++ else () ++ add_dependencies(${target} spirv-tools-build-version core_tables extinst_tables) ++ endif() + endfunction() + + if (SPIRV_TOOLS_BUILD_SHARED) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2edd31d04..4afadff0a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,29 @@ include(CMakeDependentOption) include(CTest) include(CPMUtil) +# TODO(crueter): Make this more automatic. +if (IOS) + list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") + list(APPEND CMAKE_PROGRAM_PATH "/opt/homebrew/bin" CACHE INTERNAL "") + + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "") + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH CACHE INTERNAL "") + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH CACHE INTERNAL "") + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH CACHE INTERNAL "") + + list(LENGTH CMAKE_OSX_ARCHITECTURES _arch_len) + if (NOT _arch_len EQUAL 1) + message(FATAL_ERROR "CMAKE_OSX_ARCHITECTURES must contain exactly one architecture.") + endif() + + # TODO(crueter): Proper handling for this. + if (CMAKE_OSX_ARCHITECTURES STREQUAL arm64) + set(CMAKE_SYSTEM_PROCESSOR aarch64) + else() + set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_OSX_ARCHITECTURES}) + endif() +endif() + if (NOT DEFINED ARCHITECTURE) message(FATAL_ERROR "Architecture didn't make it out of scope, did you delete DetectArchitecture.cmake?") endif() @@ -42,7 +65,7 @@ if (PLATFORM_NETBSD) set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig") endif() -cmake_dependent_option(YUZU_STATIC_ROOM "Build a static room executable only (CI only)" OFF "PLATFORM_LINUX" OFF) +cmake_dependent_option(YUZU_STATIC_ROOM "Build a static room executable only (CI only)" OFF "PLATFORM_LINUX OR WIN32 OR (APPLE AND NOT IOS)" OFF) if (YUZU_STATIC_ROOM) set(YUZU_ROOM ON) set(YUZU_ROOM_STANDALONE ON) @@ -67,9 +90,15 @@ if (YUZU_STATIC_ROOM) endif() # qt stuff -option(ENABLE_QT "Enable the Qt frontend" ON) +if (IOS OR ANDROID) + set(_default_qt OFF) +else() + set(_default_qt ON) +endif() + +option(ENABLE_QT "Enable the Qt frontend" ${_default_qt}) option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) -option(ENABLE_UPDATE_CHECKER "Enable update checker (for Qt and Android)" OFF) +cmake_dependent_option(ENABLE_UPDATE_CHECKER "Enable update checker (for Qt and Android)" OFF "ENABLE_QT OR ANDROID" OFF) cmake_dependent_option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF "NOT YUZU_USE_BUNDLED_QT" OFF) cmake_dependent_option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF "NOT YUZU_USE_BUNDLED_QT" OFF) set(YUZU_QT_MIRROR "" CACHE STRING "What mirror to use for downloading the bundled Qt libraries") @@ -170,31 +199,32 @@ if (MSVC AND NOT CXX_CLANG) set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /W3 /WX-") endif() -# TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system -cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Build SDL2 from external source" OFF "NOT MSVC;NOT ANDROID" OFF) -cmake_dependent_option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}" "NOT ANDROID" OFF) - -option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) - set(EXT_DEFAULT OFF) -if (MSVC OR ANDROID) +if (MSVC OR ANDROID OR IOS) set(EXT_DEFAULT ON) endif() +# TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system +cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Build SDL2 from external source" OFF "NOT MSVC;NOT ANDROID" OFF) +cmake_dependent_option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${EXT_DEFAULT}" "NOT ANDROID" OFF) + +# TODO(crueter): did not find header 'AudioHardware.h' in framework 'CoreAudio' +cmake_dependent_option(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF) + # ffmpeg option(YUZU_USE_BUNDLED_FFMPEG "Download bundled FFmpeg" ${EXT_DEFAULT}) cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from external source" "${PLATFORM_SUN}" "NOT WIN32 AND NOT ANDROID" OFF) # sirit set(BUNDLED_SIRIT_DEFAULT OFF) -if (MSVC AND NOT (CMAKE_BUILD_TYPE MATCHES "Deb") OR ANDROID) +if ((MSVC AND NOT (CMAKE_BUILD_TYPE MATCHES "Deb")) OR ANDROID OR IOS) set(BUNDLED_SIRIT_DEFAULT ON) endif() option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${BUNDLED_SIRIT_DEFAULT}) # FreeBSD 15+ has libusb, versions below should disable it -cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR PLATFORM_LINUX OR PLATFORM_FREEBSD OR APPLE" OFF) +cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR PLATFORM_LINUX OR PLATFORM_FREEBSD OR (APPLE AND NOT IOS)" OFF) cmake_dependent_option(ENABLE_OPENGL "Enable OpenGL" ON "NOT (WIN32 AND ARCHITECTURE_arm64) AND NOT APPLE" OFF) mark_as_advanced(FORCE ENABLE_OPENGL) @@ -212,10 +242,10 @@ option(YUZU_LEGACY "Apply patches that improve compatibility with older GPUs (e. option(NIGHTLY_BUILD "Use Nightly qualifiers in the update checker and build metadata" OFF) -cmake_dependent_option(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) +cmake_dependent_option(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID AND NOT IOS" OFF) cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF) -cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "NOT ANDROID" OFF) +cmake_dependent_option(YUZU_CMD "Compile the eden-cli executable" ON "NOT ANDROID AND NOT IOS" OFF) cmake_dependent_option(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR PLATFORM_LINUX" OFF) @@ -283,7 +313,7 @@ if (YUZU_ROOM) add_compile_definitions(YUZU_ROOM) endif() -if ((ANDROID OR APPLE OR UNIX) AND (NOT PLATFORM_LINUX OR ANDROID) AND NOT WIN32) +if ((ANDROID OR APPLE OR UNIX OR IOS) AND (NOT PLATFORM_LINUX OR ANDROID) AND NOT WIN32) if(CXX_APPLE OR CXX_CLANG) # libc++ has stop_token and jthread as experimental set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") @@ -359,7 +389,10 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) -find_package(RenderDoc MODULE) +find_package(RenderDoc MODULE QUIET) +if (NOT RenderDoc_FOUND) + message(WARNING "RenderDoc not found. Some debugging features may be disabled.") +endif() # openssl funniness if (YUZU_USE_BUNDLED_OPENSSL) @@ -484,9 +517,15 @@ endfunction() # Platform-specific library requirements # Put these BEFORE EXTERNALS or Boost WILL die # ============================================= - if (APPLE) - foreach(fw Carbon Metal Cocoa IOKit CoreVideo CoreMedia) + set(_libs Metal IOKit CoreVideo CoreMedia) + if (IOS) + list(APPEND _libs objc) + else() + list(APPEND _libs Carbon Cocoa) + endif() + + foreach(fw ${_libs}) find_library(${fw}_LIBRARY ${fw} REQUIRED) list(APPEND PLATFORM_LIBRARIES ${${fw}_LIBRARY}) endforeach() @@ -526,7 +565,6 @@ if (NOT YUZU_STATIC_ROOM) find_package(SPIRV-Tools) find_package(sirit) find_package(gamemode) - find_package(mcl) find_package(frozen) if (ARCHITECTURE_riscv64) diff --git a/CMakeModules/CPMUtil.cmake b/CMakeModules/CPMUtil.cmake index b992f24083..ca39a50331 100644 --- a/CMakeModules/CPMUtil.cmake +++ b/CMakeModules/CPMUtil.cmake @@ -3,7 +3,7 @@ set(CPM_SOURCE_CACHE "${PROJECT_SOURCE_DIR}/.cache/cpm" CACHE STRING "" FORCE) -if(MSVC OR ANDROID) +if(MSVC OR ANDROID OR IOS) set(BUNDLED_DEFAULT ON) else() set(BUNDLED_DEFAULT OFF) @@ -690,8 +690,10 @@ function(AddCIPackage) set(pkgname linux-amd64) elseif(PLATFORM_LINUX AND ARCHITECTURE_arm64) set(pkgname linux-aarch64) - elseif(APPLE) + elseif(APPLE AND NOT IOS) set(pkgname macos-universal) + elseif(IOS AND ARCHITECTURE_arm64) + set(pkgname ios-aarch64) endif() if (DEFINED pkgname AND NOT "${pkgname}" IN_LIST DISABLED_PLATFORMS) diff --git a/cpmfile.json b/cpmfile.json index 1bb29afae4..8542fcddc7 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -17,7 +17,8 @@ "version": "1.57", "find_args": "CONFIG OPTIONAL_COMPONENTS headers context system fiber filesystem", "patches": [ - "0001-clang-cl.patch" + "0001-clang-cl.patch", + "0002-ios-fix.patch" ] }, "fmt": { diff --git a/docs/CPMUtil/AddCIPackage.md b/docs/CPMUtil/AddCIPackage.md index bc7c1ccfad..7319b514ff 100644 --- a/docs/CPMUtil/AddCIPackage.md +++ b/docs/CPMUtil/AddCIPackage.md @@ -18,3 +18,4 @@ - `linux-amd64` - `linux-aarch64` - `macos-universal` + - `ios-aarch64` diff --git a/docs/CPMUtil/AddJsonPackage.md b/docs/CPMUtil/AddJsonPackage.md index 464cd1731b..e655d794f5 100644 --- a/docs/CPMUtil/AddJsonPackage.md +++ b/docs/CPMUtil/AddJsonPackage.md @@ -61,7 +61,8 @@ In order: OpenSSL CI, Boost (tag + artifact), Opus (options + find_args), discor "version": "3.6.0", "min_version": "1.1.1", "disabled_platforms": [ - "macos-universal" + "macos-universal", + "ios-aarch64" ] }, "boost": { diff --git a/docs/Caveats.md b/docs/Caveats.md index d554f3ff77..ad3fde1876 100644 --- a/docs/Caveats.md +++ b/docs/Caveats.md @@ -4,6 +4,7 @@ - [Arch Linux](#arch-linux) - [Gentoo Linux](#gentoo-linux) - [macOS](#macos) +- [iOS](#ios) - [Solaris](#solaris) - [HaikuOS](#haikuos) - [OpenBSD](#openbsd) @@ -31,6 +32,16 @@ If you're having issues with building, always consult that ebuild. macOS is largely untested. Expect crashes, significant Vulkan issues, and other fun stuff. +## iOS + +iOS has a dedicated build script, we **highly** recommend using that instead of doing anything else, we don't support any other configuration than the one present in said build script. + +To build, it's simply as easy as doing +```sh +chmod +x .ci/ios/build.sh +.ci/ios/build.sh +``` + ## Solaris Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability. diff --git a/docs/Deps.md b/docs/Deps.md index fe1f7a14b2..a34e838534 100644 --- a/docs/Deps.md +++ b/docs/Deps.md @@ -76,7 +76,6 @@ Certain other dependencies will be fetched by CPM regardless. System packages *c * This package is known to be broken on the AUR. * [cpp-jwt](https://github.com/arun11299/cpp-jwt) 1.4+ - if `ENABLE_WEB_SERVICE` is on * [unordered-dense](https://github.com/martinus/unordered_dense) -* [mcl](https://github.com/azahar-emu/mcl) - subject to removal On amd64: diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 1ab537f44d..2ebc09113b 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -76,9 +76,6 @@ if (ARCHITECTURE_riscv64) AddJsonPackage(biscuit) endif() -# mcl -AddJsonPackage(mcl) - # Vulkan stuff AddDependentPackages(vulkan-headers vulkan-utility-libraries) @@ -231,6 +228,10 @@ if (VulkanMemoryAllocator_ADDED) endif() # httplib +if (IOS) + set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF) +endif() + AddJsonPackage(httplib) # cpp-jwt diff --git a/externals/cmake-modules/DetectArchitecture.cmake b/externals/cmake-modules/DetectArchitecture.cmake index 105963c8c2..a7e60eba30 100644 --- a/externals/cmake-modules/DetectArchitecture.cmake +++ b/externals/cmake-modules/DetectArchitecture.cmake @@ -35,16 +35,21 @@ This file is based off of Yuzu and Dynarmic. # Do note that situations where multiple architectures are defined # should NOT be too dependent on the architecture # otherwise, you may end up with duplicate code -if (CMAKE_OSX_ARCHITECTURES) +if (DEFINED CMAKE_OSX_ARCHITECTURES) set(MULTIARCH_BUILD 1) set(ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}") - - # hope and pray the architecture names match - foreach(ARCH IN ${CMAKE_OSX_ARCHITECTURES}) - set(ARCHITECTURE_${ARCH} 1 PARENT_SCOPE) - add_definitions(-DARCHITECTURE_${ARCH}=1) - endforeach() - + if (IOS) + # TODO: Right... the toolchain file won't properly accomodate OSX_ARCHITECTURE + # they aren't defining it as a list properly I assume? + set(ARCHITECTURE_arm64 1) + add_definitions(-DARCHITECTURE_arm64=1) + else () + # hope and pray the architecture names match + foreach(ARCH ${CMAKE_OSX_ARCHITECTURES}) + set(ARCHITECTURE_${ARCH} 1) + add_definitions(-DARCHITECTURE_${ARCH}=1) + endforeach() + endif() return() endif() @@ -218,4 +223,4 @@ if (NOT DEFINED ARCHITECTURE) add_definitions(-DARCHITECTURE_GENERIC=1) endif() -message(STATUS "[DetectArchitecture] Target architecture: ${ARCHITECTURE}") \ No newline at end of file +message(STATUS "[DetectArchitecture] Target architecture: ${ARCHITECTURE}") diff --git a/externals/cmake-modules/DetectPlatform.cmake b/externals/cmake-modules/DetectPlatform.cmake index 6475884f1f..eec94d839c 100644 --- a/externals/cmake-modules/DetectPlatform.cmake +++ b/externals/cmake-modules/DetectPlatform.cmake @@ -51,6 +51,12 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") set(CXX_APPLE ON) endif() +# This fixes some quirks with xcrun or weird iOS toolchain cmake files +if (IOS) + unset(CXX_CLANG) + set(CXX_APPLE ON) +endif() + # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/11112 # This works totally fine on MinGW64, but not CLANG{,ARM}64 if(MINGW AND CXX_CLANG) diff --git a/externals/cpmfile.json b/externals/cpmfile.json index d67348cd68..45400f0801 100644 --- a/externals/cpmfile.json +++ b/externals/cpmfile.json @@ -23,7 +23,7 @@ "package": "sirit", "name": "sirit", "repo": "eden-emulator/sirit", - "version": "1.0.4" + "version": "1.0.5" }, "httplib": { "repo": "yhirose/cpp-httplib", @@ -36,7 +36,8 @@ "0002-fix-zstd.patch" ], "options": [ - "HTTPLIB_REQUIRE_OPENSSL ON" + "HTTPLIB_REQUIRE_OPENSSL ON", + "HTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES ON" ] }, "cpp-jwt": { @@ -111,7 +112,8 @@ ], "patches": [ "0001-netbsd-fix.patch", - "0002-allow-static-only.patch" + "0002-allow-static-only.patch", + "0003-ios-fix.patch" ] }, "spirv-headers": { @@ -208,18 +210,6 @@ "version": "0.9.1", "git_version": "0.19.0" }, - "mcl": { - "version": "0.1.12", - "repo": "azahar-emu/mcl", - "sha": "7b08d83418", - "hash": "9c6ba624cb22ef622f78046a82abb99bf5026284ba17dfacaf46ac842cbd3b0f515f5ba45a1598c7671318a78a2e648db72ce8d10e7537f34e39800bdcb57694", - "options": [ - "MCL_INSTALL OFF" - ], - "patches": [ - "0001-assert-macro.patch" - ] - }, "libusb": { "repo": "libusb/libusb", "tag": "v%VERSION%", diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt index 3140f8e545..b8d7ae3a12 100644 --- a/externals/ffmpeg/CMakeLists.txt +++ b/externals/ffmpeg/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2021 yuzu Emulator Project @@ -11,9 +11,9 @@ set(FFmpeg_HWACCEL_FLAGS) set(FFmpeg_HWACCEL_INCLUDE_DIRS) set(FFmpeg_HWACCEL_LDFLAGS) -if (UNIX AND NOT ANDROID) +if (UNIX AND NOT ANDROID AND NOT IOS) find_package(PkgConfig REQUIRED) - if (NOT ANDROID) + if (NOT ANDROID AND NOT IOS) pkg_check_modules(LIBVA libva) pkg_check_modules(CUDA cuda) pkg_check_modules(FFNVCODEC ffnvcodec) @@ -182,6 +182,10 @@ else() find_program(BASH_PROGRAM bash REQUIRED) set(FFmpeg_CROSS_COMPILE_FLAGS "") + # `configure` parameters builds only exactly what yuzu needs from FFmpeg + # `--disable-vdpau` is needed to avoid linking issues + set(FFmpeg_CC ${CMAKE_C_COMPILER_LAUNCHER} ${CMAKE_C_COMPILER}) + set(FFmpeg_CXX ${CMAKE_CXX_COMPILER_LAUNCHER} ${CMAKE_CXX_COMPILER}) if (ANDROID) string(TOLOWER "${CMAKE_HOST_SYSTEM_NAME}" FFmpeg_HOST_SYSTEM_NAME) set(TOOLCHAIN "${ANDROID_NDK}/toolchains/llvm/prebuilt/${FFmpeg_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}") @@ -197,12 +201,22 @@ else() --extra-ldflags="--ld-path=${TOOLCHAIN}/bin/ld.lld" --extra-ldflags="-nostdlib" ) + elseif(IOS) + execute_process(COMMAND xcrun --sdk iphoneos --show-sdk-path OUTPUT_VARIABLE SYSROOT) + # Lovely extra newline apple adds that **we** must remove... thank you apple! + string(STRIP "${SYSROOT}" SYSROOT) + set(FFmpeg_CC xcrun --sdk iphoneos clang -arch arm64) + set(FFmpeg_CXX xcrun --sdk iphoneos clang++ -arch arm64) + list(APPEND FFmpeg_CROSS_COMPILE_FLAGS + --arch=arm64 + --enable-cross-compile + --sysroot="${SYSROOT}" + --extra-ldflags="-miphoneos-version-min=16.0" + --install-name-dir='@rpath' + --disable-audiotoolbox + ) endif() - # `configure` parameters builds only exactly what yuzu needs from FFmpeg - # `--disable-vdpau` is needed to avoid linking issues - set(FFmpeg_CC ${CMAKE_C_COMPILER_LAUNCHER} ${CMAKE_C_COMPILER}) - set(FFmpeg_CXX ${CMAKE_CXX_COMPILER_LAUNCHER} ${CMAKE_CXX_COMPILER}) add_custom_command( OUTPUT ${FFmpeg_MAKEFILE} diff --git a/externals/libusb/CMakeLists.txt b/externals/libusb/CMakeLists.txt index 47b54f43cc..361e43a832 100644 --- a/externals/libusb/CMakeLists.txt +++ b/externals/libusb/CMakeLists.txt @@ -24,7 +24,8 @@ if (MINGW OR PLATFORM_LINUX OR APPLE) message(FATAL_ERROR "Required program `autoconf` not found.") endif() - find_program(LIBTOOLIZE libtoolize) + find_program(LIBTOOLIZE + NAMES libtoolize glibtoolize) if ("${LIBTOOLIZE}" STREQUAL "LIBTOOLIZE-NOTFOUND") message(FATAL_ERROR "Required program `libtoolize` not found.") endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 600b985609..ad8adc7a04 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -127,13 +127,15 @@ else() add_compile_options( $<$:-Werror=all> $<$:-Werror=extra> - $<$:-Werror=missing-declarations> $<$:-Werror=shadow> $<$:-Werror=unused> $<$:-Wno-attributes> $<$:-Wno-invalid-offsetof> $<$:-Wno-unused-parameter> $<$:-Wno-missing-field-initializers>) + if (NOT IOS) + add_compile_options($<$:-Werror=missing-declarations>) + endif() if (CXX_CLANG OR CXX_ICC OR CXX_APPLE) # Clang, AppleClang, or Intel C++ if (NOT MSVC) @@ -249,4 +251,9 @@ if (ANDROID) target_include_directories(yuzu-android PRIVATE android/app/src/main) endif() +if (IOS) + add_subdirectory(ios) + add_compile_options($<$:-Wno-error>) +endif() + include(GenerateDepHashes) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt index 46b75197d5..faa35bc3eb 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt @@ -133,8 +133,11 @@ class GamePropertiesFragment : Fragment() { } override fun onDestroy() { + val isChangingConfigurations = activity?.isChangingConfigurations == true super.onDestroy() - gamesViewModel.reloadGames(true) + if (!isChangingConfigurations) { + gamesViewModel.reloadGames(true) + } } private fun getPlayTime() { diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 1ee4794272..00a25a5744 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -144,7 +144,8 @@ add_library( zstd_compression.cpp zstd_compression.h fs/ryujinx_compat.h fs/ryujinx_compat.cpp - fs/symlink.h fs/symlink.cpp) + fs/symlink.h fs/symlink.cpp + httplib.h) if(WIN32) target_sources(common PRIVATE windows/timer_resolution.cpp @@ -242,7 +243,7 @@ else() target_link_libraries(common PUBLIC Boost::headers) endif() -target_link_libraries(common PUBLIC Boost::filesystem Boost::context) +target_link_libraries(common PUBLIC Boost::filesystem Boost::context httplib::httplib) if (lz4_ADDED) target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib) diff --git a/src/common/device_power_state.cpp b/src/common/device_power_state.cpp index 2dfa7dc305..01bcedeba2 100644 --- a/src/common/device_power_state.cpp +++ b/src/common/device_power_state.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include "device_power_state.h" @@ -14,11 +14,14 @@ extern std::atomic g_has_battery; #elif defined(__APPLE__) #include -#if TARGET_OS_MAC +#if defined(TARGET_OS_MAC) && TARGET_OS_MAC +#if TARGET_OS_IPHONE +// ios doesnt have this +#else #include #include #endif - +#endif #elif defined(__linux__) #include #include @@ -48,7 +51,9 @@ namespace Common { info.percentage = g_battery_percentage.load(std::memory_order_relaxed); info.charging = g_is_charging.load(std::memory_order_relaxed); info.has_battery = g_has_battery.load(std::memory_order_relaxed); - +#elif defined(__APPLE__) && TARGET_OS_IPHONE + // Not implemented + info.has_battery = false; #elif defined(__APPLE__) && TARGET_OS_MAC CFTypeRef info_ref = IOPSCopyPowerSourcesInfo(); CFArrayRef sources = IOPSCopyPowerSourcesList(info_ref); @@ -96,7 +101,6 @@ namespace Common { #else info.has_battery = false; #endif - return info; } } diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index d4b1709377..11f03867d5 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -27,9 +27,15 @@ #include #elif defined(__APPLE__) #include +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +// Not available on iOS for some fucking stupid reason... +#else #include +#endif #include #include +#elif defined(__FreeBSD__) +#include #endif // FreeBSD @@ -503,8 +509,7 @@ public: fd = shm_open_anon(O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); #elif defined(__OpenBSD__) fd = shm_open_anon(O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); -#elif defined(__FreeBSD__) && __FreeBSD__ < 13 - // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 +#elif defined(__FreeBSD__) fd = shm_open(SHM_ANON, O_RDWR, 0600); #elif defined(__APPLE__) // macOS doesn't have memfd_create, use anonymous temporary file @@ -571,9 +576,9 @@ public: if (True(perms & MemoryPermission::Execute)) prot_flags |= PROT_EXEC; #endif - int flags = (fd > 0 ? MAP_SHARED : MAP_PRIVATE) | MAP_FIXED; + int flags = (fd >= 0 ? MAP_SHARED : MAP_PRIVATE) | MAP_FIXED; void* ret = mmap(virtual_base + virtual_offset, length, prot_flags, flags, fd, host_offset); - ASSERT_MSG(ret != MAP_FAILED, "mmap: {}", strerror(errno)); + ASSERT_MSG(ret != MAP_FAILED, "mmap: {} {}", strerror(errno), fd); } void Unmap(size_t virtual_offset, size_t length) { @@ -587,9 +592,8 @@ public: auto [merged_pointer, merged_size] = free_manager.FreeBlock(virtual_base + virtual_offset, length); - void* ret = mmap(merged_pointer, merged_size, PROT_NONE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); - ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno)); + void* ret = mmap(merged_pointer, merged_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + ASSERT_MSG(ret != MAP_FAILED, "mmap: {}", strerror(errno)); } void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) { diff --git a/src/common/httplib.h b/src/common/httplib.h new file mode 100644 index 0000000000..2f971bd5f3 --- /dev/null +++ b/src/common/httplib.h @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#define CPPHTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES +#define CPPHTTPLIB_OPENSSL_SUPPORT + +#include diff --git a/src/common/settings.cpp b/src/common/settings.cpp index f549169cd2..54848c4dd1 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -186,7 +186,7 @@ bool IsFastmemEnabled() { // Only 4kb systems support host MMU right now // TODO: Support this return getpagesize() == 4096; -#elif !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && !defined(__linux__) +#elif !defined(__APPLE__) && !defined(__ANDROID__) && !defined(_WIN32) && !defined(__linux__) && !defined(__FreeBSD__) return false; #else return true; diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 7bcbe737b6..a209ac3600 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2013 Dolphin Emulator Project @@ -116,18 +116,119 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st } std::string UTF16ToUTF8(std::u16string_view input) { - std::wstring_convert, char16_t> convert; - return convert.to_bytes(input.data(), input.data() + input.size()); + std::string result; + result.reserve(input.size()); + for (size_t i = 0; i < input.size(); ++i) { + uint32_t codepoint = input[i]; + // Handle surrogate pairs + if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { + if (i + 1 < input.size()) { + uint32_t low = input[i + 1]; + if (low >= 0xDC00 && low <= 0xDFFF) { + codepoint = ((codepoint - 0xD800) << 10) + (low - 0xDC00) + 0x10000; + ++i; + } + } + } + if (codepoint <= 0x7F) { + result.push_back(static_cast(codepoint)); + } else if (codepoint <= 0x7FF) { + result.push_back(static_cast(0xC0 | (codepoint >> 6))); + result.push_back(static_cast(0x80 | (codepoint & 0x3F))); + } else if (codepoint <= 0xFFFF) { + result.push_back(static_cast(0xE0 | (codepoint >> 12))); + result.push_back(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + result.push_back(static_cast(0x80 | (codepoint & 0x3F))); + } else { + result.push_back(static_cast(0xF0 | (codepoint >> 18))); + result.push_back(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + result.push_back(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + result.push_back(static_cast(0x80 | (codepoint & 0x3F))); + } + } + return result; } std::u16string UTF8ToUTF16(std::string_view input) { - std::wstring_convert, char16_t> convert; - return convert.from_bytes(input.data(), input.data() + input.size()); + std::u16string result; + size_t i = 0; + while (i < input.size()) { + uint32_t codepoint = 0; + unsigned char c = input[i]; + size_t extra = 0; + if ((c & 0x80) == 0) { + codepoint = c; + extra = 0; + } else if ((c & 0xE0) == 0xC0) { + codepoint = c & 0x1F; + extra = 1; + } else if ((c & 0xF0) == 0xE0) { + codepoint = c & 0x0F; + extra = 2; + } else if ((c & 0xF8) == 0xF0) { + codepoint = c & 0x07; + extra = 3; + } else { + // Invalid UTF-8 + ++i; + continue; + } + if (i + extra >= input.size()) break; + for (size_t j = 1; j <= extra; ++j) { + if ((input[i + j] & 0xC0) != 0x80) { + codepoint = 0xFFFD; + break; + } + codepoint = (codepoint << 6) | (input[i + j] & 0x3F); + } + if (codepoint <= 0xFFFF) { + result.push_back(static_cast(codepoint)); + } else { + codepoint -= 0x10000; + result.push_back(static_cast(0xD800 + (codepoint >> 10))); + result.push_back(static_cast(0xDC00 + (codepoint & 0x3FF))); + } + i += extra + 1; + } + return result; } std::u32string UTF8ToUTF32(std::string_view input) { - std::wstring_convert, char32_t> convert; - return convert.from_bytes(input.data(), input.data() + input.size()); + std::u32string result; + size_t i = 0; + while (i < input.size()) { + uint32_t codepoint = 0; + unsigned char c = input[i]; + size_t extra = 0; + if ((c & 0x80) == 0) { + codepoint = c; + extra = 0; + } else if ((c & 0xE0) == 0xC0) { + codepoint = c & 0x1F; + extra = 1; + } else if ((c & 0xF0) == 0xE0) { + codepoint = c & 0x0F; + extra = 2; + } else if ((c & 0xF8) == 0xF0) { + codepoint = c & 0x07; + extra = 3; + } else { + // Invalid UTF-8 + ++i; + continue; + } + if (i + extra >= input.size()) break; + for (size_t j = 1; j <= extra; ++j) { + if ((input[i + j] & 0xC0) != 0x80) { + codepoint = 0xFFFD; + break; + } + codepoint = (codepoint << 6) | (input[i + j] & 0x3F); + } + result.push_back(codepoint); + i += extra + 1; + } + return result; } #ifdef _WIN32 diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 08a2d0e2db..aad42b883b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1264,12 +1264,15 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) hle/service/jit/jit.cpp hle/service/jit/jit.h) target_link_libraries(core PRIVATE dynarmic::dynarmic) + # Quick hack for XCode generator... + if (IOS) + target_include_directories(core PRIVATE "${CMAKE_SOURCE_DIR}/dynarmic/src") + endif() endif() target_sources(core PRIVATE hle/service/ssl/ssl_backend_openssl.cpp) target_link_libraries(core PRIVATE OpenSSL::SSL OpenSSL::Crypto) -target_compile_definitions(core PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT) # TODO diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 46384f7e6d..abae046d3c 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -1,10 +1,10 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include +#include "dynarmic/src/dynarmic/interface/halt_reason.h" #include "core/arm/arm_interface.h" diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 912a15475b..1520f128cf 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -186,7 +186,7 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) { config.only_detect_misalignment_via_page_table_on_page_boundary = true; config.fastmem_pointer = page_table->fastmem_arena ? - std::optional{reinterpret_cast(page_table->fastmem_arena)} : + std::optional{uintptr_t(page_table->fastmem_arena)} : std::nullopt; config.fastmem_exclusive_access = config.fastmem_pointer != std::nullopt; @@ -286,10 +286,6 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) { // Curated optimizations case Settings::CpuAccuracy::Auto: config.unsafe_optimizations = true; -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__DragonFly__) || defined(__NetBSD__) - config.fastmem_pointer = std::nullopt; - config.fastmem_exclusive_access = false; -#endif config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; @@ -304,6 +300,10 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) { default: break; } + if (!Settings::IsFastmemEnabled()) { + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; + } m_jit.emplace(config); } diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index d93cc1cfc9..9e55d8c27a 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include "dynarmic/src/dynarmic/interface/A32/a32.h" +#include "dynarmic/src/dynarmic/interface/code_page.h" #include "core/arm/arm_interface.h" #include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 55584d0e38..fe7fb5983f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -338,10 +338,6 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s // Safe optimisations case Settings::CpuAccuracy::Auto: config.unsafe_optimizations = true; -#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32) - config.fastmem_pointer = std::nullopt; - config.fastmem_exclusive_access = false; -#endif config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; config.fastmem_address_space_bits = 64; config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor; @@ -355,6 +351,10 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s default: break; } + if (!Settings::IsFastmemEnabled()) { + config.fastmem_pointer = std::nullopt; + config.fastmem_exclusive_access = false; + } m_jit.emplace(config); } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 9eff17c5fe..14b28a237b 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -10,12 +10,12 @@ #include #include -#include -#include -#include "common/common_types.h" -#include "common/hash.h" -#include "core/arm/arm_interface.h" -#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" +#include "../../../dynarmic/src/dynarmic/interface/A64/a64.h" +#include "../../../dynarmic/src/dynarmic/interface/code_page.h" +#include "../../../common/common_types.h" +#include "../../../common/hash.h" +#include "../arm_interface.h" +#include "dynarmic_exclusive_monitor.h" namespace Core::Memory { class Memory; diff --git a/src/core/arm/dynarmic/dynarmic_cp15.h b/src/core/arm/dynarmic/dynarmic_cp15.h index f3d96b0d83..5cec5d0060 100644 --- a/src/core/arm/dynarmic/dynarmic_cp15.h +++ b/src/core/arm/dynarmic/dynarmic_cp15.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2017 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -5,7 +8,7 @@ #include -#include +#include "dynarmic/interface/A32/coprocessor.h" #include "common/common_types.h" namespace Core { diff --git a/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h index c4f22ec891..5beb40c325 100644 --- a/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h +++ b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include +#include "dynarmic/src/dynarmic/interface/exclusive_monitor.h" #include "common/common_types.h" #include "core/arm/exclusive_monitor.h" diff --git a/src/core/arm/nce/visitor_base.h b/src/core/arm/nce/visitor_base.h index 6a2be3d9bc..65741bedac 100644 --- a/src/core/arm/nce/visitor_base.h +++ b/src/core/arm/nce/visitor_base.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 merryhime // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,9 +10,9 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" -#include -#include -#include +#include "dynarmic/frontend/A64/a64_types.h" +#include "dynarmic/frontend/A64/decoder/a64.h" +#include "dynarmic/frontend/imm.h" #pragma GCC diagnostic pop diff --git a/src/core/hle/service/bcat/news/builtin_news.cpp b/src/core/hle/service/bcat/news/builtin_news.cpp index ed001b056b..ad7aafa4e3 100644 --- a/src/core/hle/service/bcat/news/builtin_news.cpp +++ b/src/core/hle/service/bcat/news/builtin_news.cpp @@ -15,9 +15,7 @@ #include #include -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -#include -#endif +#include "common/httplib.h" #include #include @@ -37,7 +35,7 @@ namespace Service::News { namespace { -constexpr const char* GitHubAPI_EdenReleases = "/repos/eden-emulator/Releases/releases"; +[[maybe_unused]] constexpr const char* GitHubAPI_EdenReleases = "/repos/eden-emulator/Releases/releases"; // Cached logo data std::vector default_logo_small; @@ -104,7 +102,6 @@ std::vector TryLoadFromDisk(const std::filesystem::path& path) { std::vector DownloadImage(const std::string& url_path, const std::filesystem::path& cache_path) { LOG_INFO(Service_BCAT, "Downloading image: https://eden-emu.dev{}", url_path); -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT try { httplib::Client cli("https://eden-emu.dev"); cli.set_follow_location(true); @@ -128,7 +125,6 @@ std::vector DownloadImage(const std::string& url_path, const std::filesystem } catch (...) { LOG_WARNING(Service_BCAT, "Failed to download: {}", url_path); } -#endif return {}; } @@ -233,7 +229,6 @@ void WriteCachedJson(std::string_view json) { std::optional DownloadReleasesJson() { -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT try { httplib::SSLClient cli{"api.github.com", 443}; cli.set_connection_timeout(10); @@ -255,7 +250,7 @@ std::optional DownloadReleasesJson() { } catch (...) { LOG_WARNING(Service_BCAT, " failed to download releases"); } -#endif + return std::nullopt; } diff --git a/src/core/hle/service/jit/jit_context.cpp b/src/core/hle/service/jit/jit_context.cpp index 522d849e6f..cd0252c6ec 100644 --- a/src/core/hle/service/jit/jit_context.cpp +++ b/src/core/hle/service/jit/jit_context.cpp @@ -8,9 +8,9 @@ #include #include #include -#include -#include -#include +#include "dynarmic/interface/A64/a64.h" +#include "dynarmic/interface/A64/config.h" +#include "dynarmic/interface/code_page.h" #include "common/alignment.h" #include "common/common_funcs.h" diff --git a/src/core/hle/service/vi/shared_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp index 1568344830..21e42e2094 100644 --- a/src/core/hle/service/vi/shared_buffer_manager.cpp +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -373,6 +373,8 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence, android::Status::NoError, VI::ResultOperationFailed); + (void)m_container.SetLayerZIndex(layer_id, 100000); + // We succeeded. R_SUCCEED(); } diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index e0d1f942f0..dd1def5273 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -78,7 +78,9 @@ if (MSVC) /Zc:throwingNew # Assumes new (without std::nothrow) never returns null. /volatile:iso # Use strict standard-abiding volatile semantics /bigobj # Increase number of sections in .obj files - /DNOMINMAX) + /DNOMINMAX + /GR- + ) if (CXX_CLANG) list(APPEND DYNARMIC_CXX_FLAGS @@ -91,8 +93,10 @@ else() -Wextra -Wcast-qual -pedantic - -Wno-missing-braces) - + -Wno-missing-braces + -fno-rtti + #-fno-exceptions + ) if (CXX_GCC) # GCC produces bogus -Warray-bounds warnings from xbyak headers for code paths that are not # actually reachable. Specifically, it happens in cases where some code casts an Operand& @@ -102,7 +106,6 @@ else() list(APPEND DYNARMIC_CXX_FLAGS -Wno-array-bounds) list(APPEND DYNARMIC_CXX_FLAGS -Wstack-usage=4096) endif() - if (CXX_CLANG) # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. # And this in turns limits the size of a std::array. @@ -117,7 +120,6 @@ if (NOT Boost_FOUND) endif() find_package(fmt 8 CONFIG) -find_package(mcl 0.1.12 REQUIRED) find_package(unordered_dense REQUIRED) if ("arm64" IN_LIST ARCHITECTURE OR DYNARMIC_TESTS) diff --git a/src/dynarmic/CMakeModules/impl/TargetArchitectureSpecificSourcesWrapFile.cmake b/src/dynarmic/CMakeModules/impl/TargetArchitectureSpecificSourcesWrapFile.cmake index 82b3078a11..82c6c3bae0 100644 --- a/src/dynarmic/CMakeModules/impl/TargetArchitectureSpecificSourcesWrapFile.cmake +++ b/src/dynarmic/CMakeModules/impl/TargetArchitectureSpecificSourcesWrapFile.cmake @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + string(TOUPPER "${arch}" arch) file(READ "${input_file}" f_contents) -file(WRITE "${output_file}" "#include \n#if defined(MCL_ARCHITECTURE_${arch})\n${f_contents}\n#endif\n") +file(WRITE "${output_file}" "#if defined(ARCHITECTURE_${arch})\n${f_contents}\n#endif\n") diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index 2f05d8a34b..f79d18c15a 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -3,6 +3,12 @@ include(TargetArchitectureSpecificSources) add_library(dynarmic STATIC + mcl/bit.hpp + mcl/function_info.hpp + mcl/integer_of_size.hpp + mcl/intrusive_list.hpp + mcl/is_instance_of_template.hpp + backend/block_range_information.cpp backend/block_range_information.h backend/exception_handler.h @@ -353,7 +359,7 @@ set_target_properties(dynarmic PROPERTIES target_compile_options(dynarmic PRIVATE ${DYNARMIC_CXX_FLAGS}) target_link_libraries(dynarmic PRIVATE unordered_dense::unordered_dense) -target_link_libraries(dynarmic PUBLIC fmt::fmt merry::mcl) +target_link_libraries(dynarmic PUBLIC fmt::fmt) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic PRIVATE Boost::variant Boost::icl Boost::pool) diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a32_interface.cpp index 91adc5783b..d16a34275b 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a32_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,6 @@ #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/arm64/a32_address_space.h" @@ -36,14 +35,9 @@ struct Jit::Impl final { PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(hr); - + jit_interface->is_executing = false; return hr; } @@ -52,14 +46,9 @@ struct Jit::Impl final { PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - HaltReason hr = core.Step(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(hr); - + jit_interface->is_executing = false; return hr; } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a32_jitstate.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a32_jitstate.cpp index 67390a311d..0ce51d0e17 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a32_jitstate.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a32_jitstate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #include "dynarmic/backend/arm64/a32_jitstate.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::Backend::Arm64 { diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a64_interface.cpp index 10324394a5..b230f455c5 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a64_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,6 @@ #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/arm64/a64_address_space.h" @@ -34,32 +33,20 @@ struct Jit::Impl final { HaltReason Run() { ASSERT(!is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); - is_executing = true; - SCOPE_EXIT { - is_executing = false; - }; - HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(hr); - + is_executing = false; return hr; } HaltReason Step() { ASSERT(!is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); - is_executing = true; - SCOPE_EXIT { - is_executing = false; - }; - HaltReason hr = core.Step(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(hr); - + is_executing = false; return hr; } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/abi.cpp b/src/dynarmic/src/dynarmic/backend/arm64/abi.cpp index 04d8ca2eaf..acff6a89f0 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/abi.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/abi.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include diff --git a/src/dynarmic/src/dynarmic/backend/arm64/abi.h b/src/dynarmic/src/dynarmic/backend/arm64/abi.h index f2b6b1dca1..b2e29d49e0 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/abi.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,6 @@ #include #include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/common/assert.h" #include @@ -37,7 +36,7 @@ constexpr auto Rscratch0() { } else if constexpr (bitsize == 64) { return Xscratch0; } else { - static_assert(Common::always_false_v>); + return Xscratch0; //UNREACHABLE(); } } @@ -48,7 +47,7 @@ constexpr auto Rscratch1() { } else if constexpr (bitsize == 64) { return Xscratch1; } else { - static_assert(Common::always_false_v>); + return Xscratch1; //UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h b/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h index 60ce823066..737a6572e3 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/function_info.hpp" namespace Dynarmic::Backend::Arm64 { diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a32.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a32.cpp index a65efb3c59..213403b4ba 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a32.cpp @@ -6,7 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include #include "dynarmic/backend/arm64/a32_jitstate.h" diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp index a8c3aa02bf..c773d5a339 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,7 +6,6 @@ * SPDX-License-Identifier: 0BSD */ -#include #include #include "dynarmic/backend/arm64/a32_jitstate.h" @@ -46,7 +45,7 @@ static void EmitTwoOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, IR: } else if constexpr (size == 64) { emit(Qresult->D2(), Qoperand->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -69,7 +68,7 @@ static void EmitTwoOpArrangedWiden(oaknut::CodeGenerator& code, EmitContext& ctx } else if constexpr (size == 32) { emit(Qresult->D2(), Qoperand->toD().S2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -84,7 +83,7 @@ static void EmitTwoOpArrangedNarrow(oaknut::CodeGenerator& code, EmitContext& ct } else if constexpr (size == 64) { emit(Qresult->toD().S2(), Qoperand->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -107,7 +106,7 @@ static void EmitTwoOpArrangedPairWiden(oaknut::CodeGenerator& code, EmitContext& } else if constexpr (size == 32) { emit(Qresult->D2(), Qoperand->S4()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -122,7 +121,7 @@ static void EmitTwoOpArrangedLower(oaknut::CodeGenerator& code, EmitContext& ctx } else if constexpr (size == 32) { emit(Qresult->toD().S2(), Qoperand->toD().S2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -150,7 +149,7 @@ static void EmitThreeOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, I } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -175,7 +174,7 @@ static void EmitThreeOpArrangedWiden(oaknut::CodeGenerator& code, EmitContext& c } else if constexpr (size == 64) { emit(Qresult->Q1(), Qa->toD().D1(), Qb->toD().D1()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -198,7 +197,7 @@ static void EmitThreeOpArrangedLower(oaknut::CodeGenerator& code, EmitContext& c } else if constexpr (size == 32) { emit(Qresult->toD().S2(), Qa->toD().S2(), Qb->toD().S2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -220,7 +219,7 @@ static void EmitSaturatedAccumulate(oaknut::CodeGenerator&, EmitContext& ctx, IR } else if constexpr (size == 64) { emit(Qaccumulator->D2(), Qoperand->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -241,7 +240,7 @@ static void EmitImmShift(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* ins } else if constexpr (size == 64) { emit(Qresult->D2(), Qoperand->D2(), shift_amount); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -269,7 +268,7 @@ static void EmitReduce(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst, } else if constexpr (size == 64) { emit(Vresult, Qoperand->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp index 431d51c081..557d6284ed 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp @@ -7,14 +7,8 @@ */ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "dynarmic/mcl/function_info.hpp" +#include "dynarmic/mcl/integer_of_size.hpp" #include #include "dynarmic/backend/arm64/a32_jitstate.h" @@ -38,8 +32,6 @@ namespace Dynarmic::Backend::Arm64 { using namespace oaknut::util; -namespace mp = mcl::mp; - using A64FullVectorWidth = std::integral_constant; // Array alias that always sizes itself according to the given type T @@ -83,7 +75,7 @@ static void EmitTwoOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, IR: } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -111,7 +103,7 @@ static void EmitThreeOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, I } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -134,7 +126,7 @@ static void EmitFMA(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* ins } else if constexpr (size == 64) { emit(Qresult->D2(), Qm->D2(), Qn->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -156,7 +148,7 @@ static void EmitFromFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Ins } else if constexpr (size == 64) { emit(Qto->D2(), Qfrom->D2(), fbits); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }); } @@ -178,7 +170,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) } else if constexpr (fsize == 64) { return Qto->D2(); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }(); auto Vfrom = [&] { @@ -187,7 +179,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) } else if constexpr (fsize == 64) { return Qfrom->D2(); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } }(); diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp index 722a09176b..d63c1d92d0 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp @@ -1,9 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD */ -#include #include #include "dynarmic/backend/arm64/a32_jitstate.h" @@ -39,7 +41,7 @@ static void Emit(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst, EmitF } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h b/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h index cae05bcf23..953fc3783e 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,11 +10,10 @@ #include #include - -#include -#include "dynarmic/common/common_types.h" #include +#include "dynarmic/mcl/bit.hpp" +#include "dynarmic/common/common_types.h" #include "dynarmic/backend/exception_handler.h" #include "dynarmic/ir/location_descriptor.h" @@ -22,9 +21,16 @@ namespace Dynarmic::Backend::Arm64 { using DoNotFastmemMarker = std::tuple; +constexpr size_t xmrx(size_t x) noexcept { + x ^= x >> 32; + x *= 0xff51afd7ed558ccd; + x ^= mcl::bit::rotate_right(x, 47) ^ mcl::bit::rotate_right(x, 23); + return x; +} + struct DoNotFastmemMarkerHash { - size_t operator()(const DoNotFastmemMarker& value) const { - return mcl::hash::xmrx(std::get<0>(value).Value() ^ static_cast(std::get<1>(value))); + [[nodiscard]] constexpr size_t operator()(const DoNotFastmemMarker& value) const noexcept { + return xmrx(std::get<0>(value).Value() ^ u64(std::get<1>(value))); } }; diff --git a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp index e98a2f6e71..47d83f2362 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp @@ -13,9 +13,8 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/arm64/abi.h" @@ -299,7 +298,7 @@ int RegAlloc::GenerateImmediate(const IR::Value& value) { return 0; } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -366,7 +365,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) { } else if constexpr (required_kind == HostLoc::Kind::Flags) { UNREACHABLE(); //A simple read from flags is likely a logic error } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -390,7 +389,7 @@ int RegAlloc::RealizeWriteImpl(const IR::Inst* value) { flags.SetupLocation(value); return 0; } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -410,7 +409,7 @@ int RegAlloc::RealizeReadWriteImpl(const IR::Value& read_value, const IR::Inst* } else if constexpr (kind == HostLoc::Kind::Flags) { ASSERT(false && "Incorrect function for ReadWrite of flags"); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.h index 87446a240b..22ab5af662 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.h @@ -16,7 +16,7 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/is_instance_of_template.hpp" #include #include diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler.h b/src/dynarmic/src/dynarmic/backend/exception_handler.h index cd274b111f..ff116c5775 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler.h +++ b/src/dynarmic/src/dynarmic/backend/exception_handler.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,6 @@ #include #include -#include #include "dynarmic/common/common_types.h" #if defined(ARCHITECTURE_x86_64) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp index 622f86816f..be44207f0a 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -16,11 +16,10 @@ #include #include #include +#include #include #include "dynarmic/common/assert.h" -#include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/exception_handler.h" diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c b/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c index 25678ab115..ebbe5a079f 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c @@ -3,8 +3,6 @@ * SPDX-License-Identifier: 0BSD */ -#include - #if defined(ARCHITECTURE_x86_64) # include "dynarmic/backend/x64/mig/mach_exc_server.c" #elif defined(ARCHITECTURE_arm64) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp index 58a3325e17..8b52437930 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,8 +6,6 @@ * SPDX-License-Identifier: 0BSD */ -#include - #if defined(ARCHITECTURE_x86_64) # include "dynarmic/backend/x64/exception_handler_windows.cpp" #elif defined(ARCHITECTURE_arm64) diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.cpp index 05f43774b6..edb24761f6 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.cpp @@ -99,7 +99,7 @@ void A32AddressSpace::SetCursorPtr(CodePtr ptr) { } size_t A32AddressSpace::GetRemainingSize() { - return conf.code_cache_size - (GetCursorPtr() - GetMemPtr()); + return conf.code_cache_size - (GetCursorPtr() - GetMemPtr()); } EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) { diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.h b/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.h index 24148b192c..e882a9e2e6 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.h +++ b/src/dynarmic/src/dynarmic/backend/riscv64/a32_address_space.h @@ -41,25 +41,25 @@ private: template T GetMemPtr() { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(as.GetBufferPointer(0)); } template T GetMemPtr() const { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(as.GetBufferPointer(0)); } template T GetCursorPtr() { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(as.GetCursorPointer()); } template T GetCursorPtr() const { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(as.GetCursorPointer()); } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/a32_interface.cpp index c0f65a49ed..3f395bfafb 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/a32_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,6 @@ #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/riscv64/a32_address_space.h" @@ -34,28 +33,18 @@ struct Jit::Impl final { HaltReason Run() { ASSERT(!jit_interface->is_executing); jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); - RequestCacheInvalidation(); - + jit_interface->is_executing = false; return hr; } HaltReason Step() { ASSERT(!jit_interface->is_executing); jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - UNIMPLEMENTED(); - RequestCacheInvalidation(); - + jit_interface->is_executing = false; return HaltReason{}; } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/a32_jitstate.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/a32_jitstate.cpp index 87eeab6b0f..70cd6bf0f1 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/a32_jitstate.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/a32_jitstate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #include "dynarmic/backend/riscv64/a32_jitstate.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::Backend::RV64 { diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/code_block.h b/src/dynarmic/src/dynarmic/backend/riscv64/code_block.h index 7d53486a48..02bfa44eec 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/code_block.h +++ b/src/dynarmic/src/dynarmic/backend/riscv64/code_block.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -30,7 +30,7 @@ public: template T ptr() const noexcept { - static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); return reinterpret_cast(mem); } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp index 50cbaf9526..5ce7dee1e1 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/backend/riscv64/a32_jitstate.h" #include "dynarmic/backend/riscv64/abi.h" diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp index 49489c40a4..4ab5d43db8 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -12,7 +12,6 @@ #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" #include "dynarmic/common/always_false.h" @@ -164,9 +163,8 @@ u32 RegAlloc::GenerateImmediate(const IR::Value& value) { } else if constexpr (kind == HostLoc::Kind::Fpr) { UNIMPLEMENTED(); } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } - return 0; } @@ -225,7 +223,7 @@ u32 RegAlloc::RealizeReadImpl(const IR::Value& value) { fprs[new_location_index].realized = true; return new_location_index; } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } @@ -252,7 +250,7 @@ u32 RegAlloc::RealizeWriteImpl(const IR::Inst* value) { setup_location(fprs[new_location_index]); return new_location_index; } else { - static_assert(Common::always_false_v>); + UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.h index e8fd471ae1..be826e63f6 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -18,7 +18,7 @@ #include #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/is_instance_of_template.hpp" #include #include "dynarmic/backend/riscv64/stack_layout.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp index f037919eb0..80f0f9cc2f 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp @@ -15,8 +15,7 @@ #include #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp index a6b99b545f..f138b5f137 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/a32_emit_x64.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp index e540839fd5..b48dcf9046 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp @@ -14,7 +14,6 @@ #include #include "dynarmic/common/assert.h" #include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/common/llvm_disassemble.h" @@ -77,12 +76,7 @@ struct Jit::Impl { HaltReason Run() { ASSERT(!jit_interface->is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&jit_state.halt_reason))); - jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - const CodePtr current_codeptr = [this] { // RSB optimization const u32 new_rsb_ptr = (jit_state.rsb_ptr - 1) & A32JitState::RSBPtrMask; @@ -93,27 +87,19 @@ struct Jit::Impl { return GetCurrentBlock(); }(); - const HaltReason hr = block_of_code.RunCode(&jit_state, current_codeptr); - PerformRequestedCacheInvalidation(hr); - + jit_interface->is_executing = false; return hr; } HaltReason Step() { ASSERT(!jit_interface->is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&jit_state.halt_reason))); - jit_interface->is_executing = true; - SCOPE_EXIT { - jit_interface->is_executing = false; - }; - const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); - PerformRequestedCacheInvalidation(hr); - + jit_interface->is_executing = false; return hr; } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp index ed5a8f9454..066b931350 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include "dynarmic/backend/x64/a32_jitstate.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/backend/x64/block_of_code.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp index ff82d8b05c..832cfdcce2 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp @@ -11,9 +11,8 @@ #include #include #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include #include "dynarmic/backend/x64/a64_jitstate.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp index 6b3d4d86a5..4b7054b4b2 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/a64_emit_x64.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp index 44c63bdfc5..96440d273e 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp @@ -15,7 +15,6 @@ #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/llvm_disassemble.h" #include -#include #include "dynarmic/backend/x64/a64_emit_x64.h" #include "dynarmic/backend/x64/a64_jitstate.h" @@ -75,14 +74,8 @@ public: HaltReason Run() { ASSERT(!is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&jit_state.halt_reason))); - is_executing = true; - SCOPE_EXIT { - this->is_executing = false; - }; - // TODO: Check code alignment - const CodePtr current_code_ptr = [this] { // RSB optimization const u32 new_rsb_ptr = (jit_state.rsb_ptr - 1) & A64JitState::RSBPtrMask; @@ -92,27 +85,19 @@ public: } return CodePtr((uintptr_t(GetCurrentBlock()) + 15) & ~uintptr_t(15)); }(); - const HaltReason hr = block_of_code.RunCode(&jit_state, current_code_ptr); - PerformRequestedCacheInvalidation(hr); - + is_executing = false; return hr; } HaltReason Step() { ASSERT(!is_executing); PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&jit_state.halt_reason))); - is_executing = true; - SCOPE_EXIT { - this->is_executing = false; - }; - const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); - PerformRequestedCacheInvalidation(hr); - + is_executing = false; return hr; } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp index 9f983f3955..3f04ed63f0 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #include "dynarmic/backend/x64/a64_jitstate.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A64/a64_location_descriptor.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp index 28c821ab59..3a161fca6b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp @@ -25,7 +25,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/a32_jitstate.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h index 5ccab7a3ed..f6c12edaaa 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h @@ -13,7 +13,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/abi.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/constants.h b/src/dynarmic/src/dynarmic/backend/x64/constants.h index 65c5a09a53..a0ae9f3c1e 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/constants.h +++ b/src/dynarmic/src/dynarmic/backend/x64/constants.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/rounding_mode.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h b/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h index 6f22646157..422d21169f 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h +++ b/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -13,7 +13,7 @@ #include #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/function_info.hpp" #include "dynarmic/backend/x64/callback.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp index 2b0540e4a7..4e515fef2f 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.cpp @@ -12,8 +12,7 @@ #include "dynarmic/common/assert.h" #include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h index 5de5f2dc7a..301f4ffc89 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64.h @@ -16,7 +16,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include #include "dynarmic/backend/x64/xbyak.h" #include diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp index abe04b53ff..d073991fbe 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp @@ -11,14 +11,8 @@ #include #include "dynarmic/common/assert.h" -#include -#include -#include -#include -#include -#include #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/abi.h" @@ -41,7 +35,6 @@ namespace Dynarmic::Backend::X64 { using namespace Xbyak::util; -namespace mp = mcl::mp; namespace { diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc index aaed8b43f2..54fc595214 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc @@ -3,7 +3,8 @@ * SPDX-License-Identifier: 0BSD */ -#include +#define CONCATENATE_TOKENS(x, y) CONCATENATE_TOKENS_IMPL(x, y) +#define CONCATENATE_TOKENS_IMPL(x, y) x##y #define AxxEmitX64 CONCATENATE_TOKENS(Axx, EmitX64) #define AxxEmitContext CONCATENATE_TOKENS(Axx, EmitContext) diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp index 85ee3584eb..63827979df 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp @@ -9,9 +9,9 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/block_of_code.h" #include "dynarmic/backend/x64/emit_x64.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp index 1f96939d88..d94f0329f8 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp @@ -13,11 +13,9 @@ #include #include "dynarmic/common/assert.h" -#include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" -#include +#include "dynarmic/mcl/function_info.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/abi.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp index ee9ec39f46..70edfbd0bc 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp @@ -13,14 +13,8 @@ #include #include "dynarmic/common/assert.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "dynarmic/mcl/function_info.hpp" +#include "dynarmic/mcl/integer_of_size.hpp" #include "dynarmic/backend/x64/xbyak.h" #include "dynarmic/backend/x64/abi.h" @@ -41,7 +35,6 @@ namespace Dynarmic::Backend::X64 { using namespace Xbyak::util; -namespace mp = mcl::mp; namespace { @@ -2000,6 +1993,7 @@ void EmitX64::EmitFPVectorToHalf32(EmitContext& ctx, IR::Inst* inst) { } } + // Assembly thunk; just remember not to specialise too much otherwise i-cache death! // template // static void EmitFPVectorToFixedThunk(VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { diff --git a/src/dynarmic/src/dynarmic/backend/x64/perf_map.cpp b/src/dynarmic/src/dynarmic/backend/x64/perf_map.cpp index a0b5c4fdde..095d6194f6 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/perf_map.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/perf_map.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,17 +6,16 @@ * SPDX-License-Identifier: 0BSD */ -#include "dynarmic/backend/x64/perf_map.h" - #include #include +#include +#include "dynarmic/backend/x64/perf_map.h" +#include "dynarmic/common/common_types.h" #if defined(__linux__) && !defined(__ANDROID__) # include # include # include -# include -# include # include # include diff --git a/src/dynarmic/src/dynarmic/common/cast_util.h b/src/dynarmic/src/dynarmic/common/cast_util.h index 92c9a259b3..aed9067977 100644 --- a/src/dynarmic/src/dynarmic/common/cast_util.h +++ b/src/dynarmic/src/dynarmic/common/cast_util.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/function_info.hpp" namespace Dynarmic::Common { diff --git a/src/dynarmic/src/dynarmic/common/fp/fpcr.h b/src/dynarmic/src/dynarmic/common/fp/fpcr.h index be963a2099..948917bc35 100644 --- a/src/dynarmic/src/dynarmic/common/fp/fpcr.h +++ b/src/dynarmic/src/dynarmic/common/fp/fpcr.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/rounding_mode.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/fpsr.h b/src/dynarmic/src/dynarmic/common/fp/fpsr.h index 9308132879..caa5cb92c7 100644 --- a/src/dynarmic/src/dynarmic/common/fp/fpsr.h +++ b/src/dynarmic/src/dynarmic/common/fp/fpsr.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::FP { diff --git a/src/dynarmic/src/dynarmic/common/fp/fused.cpp b/src/dynarmic/src/dynarmic/common/fp/fused.cpp index 5c32b05eb4..a965575a5a 100644 --- a/src/dynarmic/src/dynarmic/common/fp/fused.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/fused.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #include "dynarmic/common/fp/fused.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/unpacked.h" #include "dynarmic/common/u128.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/info.h b/src/dynarmic/src/dynarmic/common/fp/info.h index 3969843f0f..eebca0fc0c 100644 --- a/src/dynarmic/src/dynarmic/common/fp/info.h +++ b/src/dynarmic/src/dynarmic/common/fp/info.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::FP { diff --git a/src/dynarmic/src/dynarmic/common/fp/mantissa_util.h b/src/dynarmic/src/dynarmic/common/fp/mantissa_util.h index 3999f97c27..43bb5fe604 100644 --- a/src/dynarmic/src/dynarmic/common/fp/mantissa_util.h +++ b/src/dynarmic/src/dynarmic/common/fp/mantissa_util.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,8 +8,7 @@ #pragma once -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic::FP { diff --git a/src/dynarmic/src/dynarmic/common/fp/op/FPConvert.cpp b/src/dynarmic/src/dynarmic/common/fp/op/FPConvert.cpp index 906aa781a1..82803f715d 100644 --- a/src/dynarmic/src/dynarmic/common/fp/op/FPConvert.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/op/FPConvert.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,8 +8,7 @@ #include "dynarmic/common/fp/op/FPConvert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/op/FPRecipExponent.cpp b/src/dynarmic/src/dynarmic/common/fp/op/FPRecipExponent.cpp index e932e02803..332870eb8a 100644 --- a/src/dynarmic/src/dynarmic/common/fp/op/FPRecipExponent.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/op/FPRecipExponent.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #include "dynarmic/common/fp/op/FPRecipExponent.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/op/FPRoundInt.cpp b/src/dynarmic/src/dynarmic/common/fp/op/FPRoundInt.cpp index 198a71c807..4bcfcd7c8a 100644 --- a/src/dynarmic/src/dynarmic/common/fp/op/FPRoundInt.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/op/FPRoundInt.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include "dynarmic/common/fp/op/FPRoundInt.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/op/FPToFixed.cpp b/src/dynarmic/src/dynarmic/common/fp/op/FPToFixed.cpp index 8e3474952a..2f37797b70 100644 --- a/src/dynarmic/src/dynarmic/common/fp/op/FPToFixed.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/op/FPToFixed.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,8 +10,7 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/process_nan.cpp b/src/dynarmic/src/dynarmic/common/fp/process_nan.cpp index ff1b09f4ba..7f47852d98 100644 --- a/src/dynarmic/src/dynarmic/common/fp/process_nan.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/process_nan.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,7 +11,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/unpacked.cpp b/src/dynarmic/src/dynarmic/common/fp/unpacked.cpp index f853ab07e1..d6bb615cb4 100644 --- a/src/dynarmic/src/dynarmic/common/fp/unpacked.cpp +++ b/src/dynarmic/src/dynarmic/common/fp/unpacked.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -7,8 +10,7 @@ #include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/fp/info.h" diff --git a/src/dynarmic/src/dynarmic/common/fp/unpacked.h b/src/dynarmic/src/dynarmic/common/fp/unpacked.h index 49dca74304..effc604fb0 100644 --- a/src/dynarmic/src/dynarmic/common/fp/unpacked.h +++ b/src/dynarmic/src/dynarmic/common/fp/unpacked.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/common/safe_ops.h b/src/dynarmic/src/dynarmic/common/safe_ops.h index f494bdb24b..5cc8cb5049 100644 --- a/src/dynarmic/src/dynarmic/common/safe_ops.h +++ b/src/dynarmic/src/dynarmic/common/safe_ops.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/u128.h" diff --git a/src/dynarmic/src/dynarmic/common/u128.h b/src/dynarmic/src/dynarmic/common/u128.h index 9ab4aa0bd5..363c8dfec4 100644 --- a/src/dynarmic/src/dynarmic/common/u128.h +++ b/src/dynarmic/src/dynarmic/common/u128.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,8 +11,7 @@ #include #include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic { diff --git a/src/dynarmic/src/dynarmic/frontend/A32/FPSCR.h b/src/dynarmic/src/dynarmic/frontend/A32/FPSCR.h index 7a4c738e9e..7e0532ee93 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/FPSCR.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/FPSCR.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/rounding_mode.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/ITState.h b/src/dynarmic/src/dynarmic/frontend/A32/ITState.h index eeddaeb6b5..baabc1ca15 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/ITState.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/ITState.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/ir/cond.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/PSR.h b/src/dynarmic/src/dynarmic/frontend/A32/PSR.h index 328fdb17c0..16ca86aeac 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/PSR.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/PSR.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -8,7 +8,7 @@ #pragma once -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/A32/ITState.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp b/src/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp index a47ce0b78b..704179ecfb 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD @@ -8,7 +11,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" namespace Dynarmic::A32 { diff --git a/src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h b/src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h index c6f034ae21..bbf128d797 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/decoder/arm.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -15,7 +15,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/decoder/decoder_detail.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/decoder/asimd.h b/src/dynarmic/src/dynarmic/frontend/A32/decoder/asimd.h index 6bf52b87e6..a16caedd87 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/decoder/asimd.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/decoder/asimd.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -15,7 +15,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/decoder/decoder_detail.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp index 8c55588a28..82d25f1337 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp @@ -32,8 +32,7 @@ bool CondCanContinue(const ConditionalState cond_state, const A32::IREmitter& ir } bool IsConditionPassed(TranslatorVisitor& v, IR::Cond cond) { - ASSERT_MSG(v.cond_state != ConditionalState::Break, - "This should never happen. We requested a break but that wasn't honored."); + ASSERT(v.cond_state != ConditionalState::Break && "This should never happen. We requested a break but that wasn't honored."); if (cond == IR::Cond::NV) { // NV conditional is obsolete diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp index d87cfcfe82..63b40b8c31 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h index a03b2e666b..a8888c355f 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h @@ -9,8 +9,7 @@ #pragma once #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/a32_ir_emitter.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp index 68c0d983af..8d0f78396a 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_load_store_structures.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp index 9d73e7d4ae..9aa50c6b8c 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,8 +9,7 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp index 459cbfea06..c5bdb1b551 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -7,7 +7,7 @@ */ #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp index da8f43f2fb..8d5e694bca 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_three_regs.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2020 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp index ddae1f420b..45455aa444 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2020 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp index 4d6855f1ed..d9cc3b1e64 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_scalar.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp index 27e94628a8..e5a4eb537f 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_shift.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -7,8 +7,7 @@ */ #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp index 49c5d65b3a..d7c667aecf 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp @@ -6,8 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/misc.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/misc.cpp index ef54b66827..bb33c3c47c 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/misc.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/misc.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/status_register_access.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/status_register_access.cpp index 8dfc64d6d7..7a0640598c 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/status_register_access.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/status_register_access.cpp @@ -6,7 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp index 926c499222..a8c75e22b9 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -6,7 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/interface/A32/config.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp index 090e98d1aa..7ea31d40ee 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -7,7 +7,7 @@ */ #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp index eb574d773c..e76666ecc2 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_dual.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2021 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp index d446fbf3dd..b68a2cb7c5 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2021 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/frontend/A32/translate/impl/common.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp index e0333e487d..309dd080f9 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/translate_thumb.cpp @@ -9,8 +9,7 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A32/a32_ir_emitter.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h b/src/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h index 4bfc5f890e..a8be0232ca 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h +++ b/src/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -13,7 +13,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/fp/fpcr.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h b/src/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h index 68422ed40d..4ac04731ea 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h +++ b/src/dynarmic/src/dynarmic/frontend/A64/decoder/a64.h @@ -15,7 +15,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/decoder/decoder_detail.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp index de63f560bc..f3ecd7c604 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp @@ -8,9 +8,7 @@ #include "dynarmic/frontend/A64/translate/impl/impl.h" -#include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/ir/terminal.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp index b33bc8f5ad..9354b54fa5 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp index db8e83631a..2afece1c46 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_modified_immediate.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp index 5d60cb31c3..332eb35ebe 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_shift_by_immediate.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/rounding_mode.h" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp index d551605bda..ad5b89df3a 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_scalar_three_same.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -5,7 +8,7 @@ #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp index 559721a22a..33debd1062 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_shift_by_immediate.cpp @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD */ -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/fp/rounding_mode.h" #include "dynarmic/frontend/A64/translate/impl/impl.h" diff --git a/src/dynarmic/src/dynarmic/frontend/decoder/decoder_detail.h b/src/dynarmic/src/dynarmic/frontend/decoder/decoder_detail.h index 0d9da6169c..3ab360c287 100644 --- a/src/dynarmic/src/dynarmic/frontend/decoder/decoder_detail.h +++ b/src/dynarmic/src/dynarmic/frontend/decoder/decoder_detail.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -13,8 +13,8 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" +#include "dynarmic/mcl/function_info.hpp" namespace Dynarmic::Decoder { namespace detail { @@ -75,11 +75,11 @@ struct detail { /// An argument is specified by a continuous string of the same character. template static consteval auto GetArgInfo(std::array bitstring) { + //static_assert(N > 0, "unexpected field"); std::array masks = {}; std::array shifts = {}; size_t arg_index = 0; char ch = 0; - for (size_t i = 0; i < opcode_bitsize; i++) { if (bitstring[i] == '0' || bitstring[i] == '1' || bitstring[i] == '-') { if (ch != 0) { @@ -93,17 +93,10 @@ struct detail { ch = bitstring[i]; arg_index++; } - - if constexpr (N > 0) { - const size_t bit_position = opcode_bitsize - i - 1; - if (arg_index >= N) - throw std::out_of_range("Unexpected field"); - - masks[arg_index] |= static_cast(1) << bit_position; - shifts[arg_index] = bit_position; - } else { - throw std::out_of_range("Unexpected field"); - } + const size_t bit_position = opcode_bitsize - i - 1; + //static_assert(arg_index >= N, "unexpected field"); + masks[arg_index] |= opcode_type(1) << bit_position; + shifts[arg_index] = bit_position; } } #if !defined(DYNARMIC_IGNORE_ASSERTS) && !defined(__ANDROID__) diff --git a/src/dynarmic/src/dynarmic/frontend/imm.cpp b/src/dynarmic/src/dynarmic/frontend/imm.cpp index 95e24206d7..aeb7b5d3f6 100644 --- a/src/dynarmic/src/dynarmic/frontend/imm.cpp +++ b/src/dynarmic/src/dynarmic/frontend/imm.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include "dynarmic/frontend/imm.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" namespace Dynarmic { diff --git a/src/dynarmic/src/dynarmic/frontend/imm.h b/src/dynarmic/src/dynarmic/frontend/imm.h index 4e277ede3b..3a6c10316a 100644 --- a/src/dynarmic/src/dynarmic/frontend/imm.h +++ b/src/dynarmic/src/dynarmic/frontend/imm.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -11,8 +11,7 @@ #include #include "dynarmic/common/assert.h" -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/math_util.h" diff --git a/src/dynarmic/src/dynarmic/interface/A32/a32.h b/src/dynarmic/src/dynarmic/interface/A32/a32.h index bc30b59c1e..00e9e045ef 100644 --- a/src/dynarmic/src/dynarmic/interface/A32/a32.h +++ b/src/dynarmic/src/dynarmic/interface/A32/a32.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -14,8 +14,8 @@ #include #include -#include "dynarmic/interface/A32/config.h" -#include "dynarmic/interface/halt_reason.h" +#include "config.h" +#include "dynarmic/src/dynarmic/interface/halt_reason.h" namespace Dynarmic { namespace A32 { diff --git a/src/dynarmic/src/dynarmic/interface/A32/config.h b/src/dynarmic/src/dynarmic/interface/A32/config.h index 5a97fb69f3..9f1f5cc0cd 100644 --- a/src/dynarmic/src/dynarmic/interface/A32/config.h +++ b/src/dynarmic/src/dynarmic/interface/A32/config.h @@ -14,9 +14,9 @@ #include #include -#include "dynarmic/frontend/A32/translate/translate_callbacks.h" -#include "dynarmic/interface/A32/arch_version.h" -#include "dynarmic/interface/optimization_flags.h" +#include "../../frontend/A32/translate/translate_callbacks.h" +#include "arch_version.h" +#include "../optimization_flags.h" namespace Dynarmic { class ExclusiveMonitor; diff --git a/src/dynarmic/src/dynarmic/interface/A64/a64.h b/src/dynarmic/src/dynarmic/interface/A64/a64.h index e8d2352702..86c24b02a1 100644 --- a/src/dynarmic/src/dynarmic/interface/A64/a64.h +++ b/src/dynarmic/src/dynarmic/interface/A64/a64.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -15,8 +15,8 @@ #include #include -#include "dynarmic/interface/A64/config.h" -#include "dynarmic/interface/halt_reason.h" +#include "config.h" +#include "../halt_reason.h" namespace Dynarmic { namespace A64 { diff --git a/src/dynarmic/src/dynarmic/interface/A64/config.h b/src/dynarmic/src/dynarmic/interface/A64/config.h index 83c1593fd8..f6d340c47f 100644 --- a/src/dynarmic/src/dynarmic/interface/A64/config.h +++ b/src/dynarmic/src/dynarmic/interface/A64/config.h @@ -14,7 +14,7 @@ #include #include -#include "dynarmic/interface/optimization_flags.h" +#include "../optimization_flags.h" namespace Dynarmic { class ExclusiveMonitor; diff --git a/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h b/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h index 566743c767..9315563888 100644 --- a/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h +++ b/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -11,7 +14,7 @@ #include #include -#include +#include "dynarmic/src/dynarmic/common/spin_lock.h" namespace Dynarmic { diff --git a/src/dynarmic/src/dynarmic/ir/basic_block.h b/src/dynarmic/src/dynarmic/ir/basic_block.h index 4044005bd0..bbf1319957 100644 --- a/src/dynarmic/src/dynarmic/ir/basic_block.h +++ b/src/dynarmic/src/dynarmic/ir/basic_block.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include "dynarmic/mcl/intrusive_list.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/ir/location_descriptor.h" diff --git a/src/dynarmic/src/dynarmic/ir/ir_emitter.h b/src/dynarmic/src/dynarmic/ir/ir_emitter.h index 2b5c7d5cdd..37f7c18065 100644 --- a/src/dynarmic/src/dynarmic/ir/ir_emitter.h +++ b/src/dynarmic/src/dynarmic/ir/ir_emitter.h @@ -12,7 +12,7 @@ #include "dynarmic/common/common_types.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/ir/opcodes.h" #include "dynarmic/ir/acc_type.h" diff --git a/src/dynarmic/src/dynarmic/ir/microinstruction.h b/src/dynarmic/src/dynarmic/ir/microinstruction.h index 1700eb110b..fb3ac1f49a 100644 --- a/src/dynarmic/src/dynarmic/ir/microinstruction.h +++ b/src/dynarmic/src/dynarmic/ir/microinstruction.h @@ -10,7 +10,7 @@ #include -#include +#include "dynarmic/mcl/intrusive_list.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/ir/value.h" diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index f22e8aaa69..ee29081d4d 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -27,8 +27,8 @@ #include "dynarmic/ir/opcodes.h" #include "dynarmic/ir/opt_passes.h" #include "dynarmic/ir/type.h" -#include "mcl/bit/swap.hpp" -#include "mcl/bit/rotate.hpp" +#include "dynarmic/mcl/bit.hpp" +#include "dynarmic/mcl/bit.hpp" namespace Dynarmic::Optimization { diff --git a/src/dynarmic/src/dynarmic/ir/value.cpp b/src/dynarmic/src/dynarmic/ir/value.cpp index 59b17b5a7b..451036b1fd 100644 --- a/src/dynarmic/src/dynarmic/ir/value.cpp +++ b/src/dynarmic/src/dynarmic/ir/value.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later /* This file is part of the dynarmic project. @@ -9,7 +9,7 @@ #include "dynarmic/ir/value.h" #include "dynarmic/common/assert.h" -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" diff --git a/src/dynarmic/src/dynarmic/mcl/bit.hpp b/src/dynarmic/src/dynarmic/mcl/bit.hpp new file mode 100644 index 0000000000..1ef9880a5f --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/bit.hpp @@ -0,0 +1,311 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include + +#include "dynarmic/common/common_types.h" +#include "dynarmic/common/assert.h" + +namespace mcl { +namespace detail { +template +concept SameHelper = std::is_same_v; +} // namespace detail +template +concept SameAs = detail::SameHelper && detail::SameHelper; +template +concept IsAnyOf = (SameAs || ...); +/// Integral upon which bit operations can be safely performed. +template +concept BitIntegral = IsAnyOf; + +template +constexpr std::size_t bitsizeof = CHAR_BIT * sizeof(T); + +} // namespace mcl + +namespace mcl::bit { + +constexpr u16 swap_bytes_16(u16 value) { + return static_cast(u32{value} >> 8 | u32{value} << 8); +} + +constexpr u32 swap_bytes_32(u32 value) { + return ((value & 0xff000000u) >> 24) + | ((value & 0x00ff0000u) >> 8) + | ((value & 0x0000ff00u) << 8) + | ((value & 0x000000ffu) << 24); +} + +constexpr u64 swap_bytes_64(u64 value) { + return ((value & 0xff00000000000000ull) >> 56) + | ((value & 0x00ff000000000000ull) >> 40) + | ((value & 0x0000ff0000000000ull) >> 24) + | ((value & 0x000000ff00000000ull) >> 8) + | ((value & 0x00000000ff000000ull) << 8) + | ((value & 0x0000000000ff0000ull) << 24) + | ((value & 0x000000000000ff00ull) << 40) + | ((value & 0x00000000000000ffull) << 56); +} + +constexpr u32 swap_halves_32(u32 value) { + return ((value & 0xffff0000u) >> 16) + | ((value & 0x0000ffffu) << 16); +} + +constexpr u64 swap_halves_64(u64 value) { + return ((value & 0xffff000000000000ull) >> 48) + | ((value & 0x0000ffff00000000ull) >> 16) + | ((value & 0x00000000ffff0000ull) << 16) + | ((value & 0x000000000000ffffull) << 48); +} + +constexpr u64 swap_words_64(u64 value) { + return ((value & 0xffffffff00000000ull) >> 32) + | ((value & 0x00000000ffffffffull) << 32); +} + +template +constexpr T rotate_right(T x, size_t amount) { + amount %= bitsizeof; + if (amount == 0) { + return x; + } + return static_cast((x >> amount) | (x << (bitsizeof - amount))); +} + +template +constexpr T rotate_left(T x, size_t amount) { + amount %= bitsizeof; + if (amount == 0) { + return x; + } + return static_cast((x << amount) | (x >> (bitsizeof - amount))); +} + +/// Create a mask with `count` number of one bits. +template +constexpr T ones() { + static_assert(count <= bitsizeof, "count larger than bitsize of T"); + + if constexpr (count == 0) { + return 0; + } else { + return static_cast(~static_cast(0)) >> (bitsizeof - count); + } +} + +/// Create a mask with `count` number of one bits. +template +constexpr T ones(size_t count) { + ASSERT(count <= bitsizeof && "count larger than bitsize of T"); + if (count == 0) { + return 0; + } + return static_cast(~static_cast(0)) >> (bitsizeof - count); +} + +/// Create a mask of type T for bits [begin_bit, end_bit] inclusive. +template +constexpr T mask() { + static_assert(begin_bit <= end_bit, "invalid bit range (position of beginning bit cannot be greater than that of end bit)"); + static_assert(begin_bit < bitsizeof, "begin_bit must be smaller than size of T"); + static_assert(end_bit < bitsizeof, "end_bit must be smaller than size of T"); + + return ones() << begin_bit; +} + +/// Create a mask of type T for bits [begin_bit, end_bit] inclusive. +template +constexpr T mask(size_t begin_bit, size_t end_bit) { + ASSERT(begin_bit <= end_bit && "invalid bit range (position of beginning bit cannot be greater than that of end bit)"); + ASSERT(begin_bit < bitsizeof && "begin_bit must be smaller than size of T"); + ASSERT(end_bit < bitsizeof && "end_bit must be smaller than size of T"); + return ones(end_bit - begin_bit + 1) << begin_bit; +} + +/// Extract bits [begin_bit, end_bit] inclusive from value of type T. +template +constexpr T get_bits(T value) { + constexpr T m = mask(); + return (value & m) >> begin_bit; +} + +/// Extract bits [begin_bit, end_bit] inclusive from value of type T. +template +constexpr T get_bits(size_t begin_bit, size_t end_bit, T value) { + const T m = mask(begin_bit, end_bit); + return (value & m) >> begin_bit; +} + +/// Clears bits [begin_bit, end_bit] inclusive of value of type T. +template +constexpr T clear_bits(T value) { + constexpr T m = mask(); + return value & ~m; +} + +/// Clears bits [begin_bit, end_bit] inclusive of value of type T. +template +constexpr T clear_bits(size_t begin_bit, size_t end_bit, T value) { + const T m = mask(begin_bit, end_bit); + return value & ~m; +} + +/// Modifies bits [begin_bit, end_bit] inclusive of value of type T. +template +constexpr T set_bits(T value, T new_bits) { + constexpr T m = mask(); + return (value & ~m) | ((new_bits << begin_bit) & m); +} + +/// Modifies bits [begin_bit, end_bit] inclusive of value of type T. +template +constexpr T set_bits(size_t begin_bit, size_t end_bit, T value, T new_bits) { + const T m = mask(begin_bit, end_bit); + return (value & ~m) | ((new_bits << begin_bit) & m); +} + +/// Extract bit at bit_position from value of type T. +template +constexpr bool get_bit(T value) { + constexpr T m = mask(); + return (value & m) != 0; +} + +/// Extract bit at bit_position from value of type T. +template +constexpr bool get_bit(size_t bit_position, T value) { + const T m = mask(bit_position, bit_position); + return (value & m) != 0; +} + +/// Clears bit at bit_position of value of type T. +template +constexpr T clear_bit(T value) { + constexpr T m = mask(); + return value & ~m; +} + +/// Clears bit at bit_position of value of type T. +template +constexpr T clear_bit(size_t bit_position, T value) { + const T m = mask(bit_position, bit_position); + return value & ~m; +} + +/// Modifies bit at bit_position of value of type T. +template +constexpr T set_bit(T value, bool new_bit) { + constexpr T m = mask(); + return (value & ~m) | (new_bit ? m : static_cast(0)); +} + +/// Modifies bit at bit_position of value of type T. +template +constexpr T set_bit(size_t bit_position, T value, bool new_bit) { + const T m = mask(bit_position, bit_position); + return (value & ~m) | (new_bit ? m : static_cast(0)); +} + +/// Sign-extends a value that has bit_count bits to the full bitwidth of type T. +template +constexpr T sign_extend(T value) { + static_assert(bit_count != 0, "cannot sign-extend zero-sized value"); + + using S = std::make_signed_t; + constexpr size_t shift_amount = bitsizeof - bit_count; + return static_cast(static_cast(value << shift_amount) >> shift_amount); +} + +/// Sign-extends a value that has bit_count bits to the full bitwidth of type T. +template +constexpr T sign_extend(size_t bit_count, T value) { + ASSERT(bit_count != 0 && "cannot sign-extend zero-sized value"); + using S = std::make_signed_t; + const size_t shift_amount = bitsizeof - bit_count; + return T(S(value << shift_amount) >> shift_amount); +} + +/// Replicate an element across a value of type T. +template +constexpr T replicate_element(T value) { + static_assert(element_size <= bitsizeof, "element_size is too large"); + static_assert(bitsizeof % element_size == 0, "bitsize of T not divisible by element_size"); + + if constexpr (element_size == bitsizeof) { + return value; + } else { + return replicate_element(static_cast(value | (value << element_size))); + } +} + +/// Replicate an element of type U across a value of type T. +template +constexpr T replicate_element(T value) { + static_assert(bitsizeof <= bitsizeof, "element_size is too large"); + + return replicate_element, T>(value); +} + +/// Replicate an element across a value of type T. +template +constexpr T replicate_element(size_t element_size, T value) { + ASSERT(element_size <= bitsizeof && "element_size is too large"); + ASSERT(bitsizeof % element_size == 0 && "bitsize of T not divisible by element_size"); + if (element_size == bitsizeof) + return value; + return replicate_element(element_size * 2, static_cast(value | (value << element_size))); +} + +template +constexpr bool most_significant_bit(T value) { + return get_bit - 1, T>(value); +} + +template +inline size_t count_ones(T x) { + return std::bitset>(x).count(); +} + +template +constexpr size_t count_leading_zeros(T x) { + size_t result = bitsizeof; + while (x != 0) { + x >>= 1; + result--; + } + return result; +} + +template +constexpr int highest_set_bit(T x) { + int result = -1; + while (x != 0) { + x >>= 1; + result++; + } + return result; +} + +template +constexpr size_t lowest_set_bit(T x) { + if (x == 0) { + return bitsizeof; + } + + size_t result = 0; + while ((x & 1) == 0) { + x >>= 1; + result++; + } + return result; +} + +} // namespace mcl::bit diff --git a/src/dynarmic/src/dynarmic/mcl/function_info.hpp b/src/dynarmic/src/dynarmic/mcl/function_info.hpp new file mode 100644 index 0000000000..452bd88bfc --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/function_info.hpp @@ -0,0 +1,73 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +namespace mcl { + +/// Contains a list of types +template +struct type_list {}; + +template +struct function_info : function_info {}; + +template +struct function_info { + using return_type = R; + using parameter_list = type_list; + static constexpr std::size_t parameter_count = sizeof...(As); + + using equivalent_function_type = R(As...); + + template + struct parameter { + static_assert(I < parameter_count, "Non-existent parameter"); + using type = std::tuple_element_t>; + }; +}; + +template +struct function_info : function_info {}; + +template +struct function_info : function_info { + using class_type = C; + + using equivalent_function_type_with_class = R(C*, As...); +}; + +template +struct function_info : function_info { + using class_type = C; + + using equivalent_function_type_with_class = R(C*, As...); +}; + +template +constexpr size_t parameter_count_v = function_info::parameter_count; + +template +using parameter_list = typename function_info::parameter_list; + +template +using get_parameter = typename function_info::template parameter::type; + +template +using equivalent_function_type = typename function_info::equivalent_function_type; + +template +using equivalent_function_type_with_class = typename function_info::equivalent_function_type_with_class; + +template +using return_type = typename function_info::return_type; + +template +using class_type = typename function_info::class_type; + +} // namespace mcl diff --git a/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp b/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp new file mode 100644 index 0000000000..8bdecc955d --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include "dynarmic/common/common_types.h" + +namespace mcl { + +namespace detail { + +template +struct integer_of_size_impl {}; + +template<> +struct integer_of_size_impl<8> { + using unsigned_type = u8; + using signed_type = s8; +}; + +template<> +struct integer_of_size_impl<16> { + using unsigned_type = u16; + using signed_type = s16; +}; + +template<> +struct integer_of_size_impl<32> { + using unsigned_type = u32; + using signed_type = s32; +}; + +template<> +struct integer_of_size_impl<64> { + using unsigned_type = u64; + using signed_type = s64; +}; + +} // namespace detail + +template +using unsigned_integer_of_size = typename detail::integer_of_size_impl::unsigned_type; + +template +using signed_integer_of_size = typename detail::integer_of_size_impl::signed_type; + +} // namespace mcl diff --git a/src/dynarmic/src/dynarmic/mcl/intrusive_list.hpp b/src/dynarmic/src/dynarmic/mcl/intrusive_list.hpp new file mode 100644 index 0000000000..3b1c1d6699 --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/intrusive_list.hpp @@ -0,0 +1,408 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include +#include +#include "dynarmic/common/assert.h" + +namespace mcl { + +template +class intrusive_list; +template +class intrusive_list_iterator; + +template +class intrusive_list_node { +public: + bool is_sentinel() const + { + return is_sentinel_; + } + +protected: + intrusive_list_node* next = nullptr; + intrusive_list_node* prev = nullptr; + bool is_sentinel_ = false; + + friend class intrusive_list; + friend class intrusive_list_iterator; + friend class intrusive_list_iterator; +}; + +template +class intrusive_list_sentinel final : public intrusive_list_node { + using intrusive_list_node::next; + using intrusive_list_node::prev; + using intrusive_list_node::is_sentinel_; + +public: + intrusive_list_sentinel() + { + next = this; + prev = this; + is_sentinel_ = true; + } +}; + +template +class intrusive_list_iterator { +public: + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + + // If value_type is const, we want "const intrusive_list_node", not "intrusive_list_node" + using node_type = std::conditional_t::value, + const intrusive_list_node>, + intrusive_list_node>; + using node_pointer = node_type*; + using node_reference = node_type&; + + intrusive_list_iterator() = default; + intrusive_list_iterator(const intrusive_list_iterator& other) = default; + intrusive_list_iterator& operator=(const intrusive_list_iterator& other) = default; + + explicit intrusive_list_iterator(node_pointer list_node) + : node(list_node) {} + explicit intrusive_list_iterator(pointer data) + : node(data) {} + explicit intrusive_list_iterator(reference data) + : node(&data) {} + + intrusive_list_iterator& operator++() + { + node = node->next; + return *this; + } + intrusive_list_iterator& operator--() + { + node = node->prev; + return *this; + } + intrusive_list_iterator operator++(int) + { + intrusive_list_iterator it(*this); + ++*this; + return it; + } + intrusive_list_iterator operator--(int) + { + intrusive_list_iterator it(*this); + --*this; + return it; + } + + bool operator==(const intrusive_list_iterator& other) const + { + return node == other.node; + } + bool operator!=(const intrusive_list_iterator& other) const + { + return !operator==(other); + } + + reference operator*() const + { + DEBUG_ASSERT(!node->is_sentinel()); + return static_cast(*node); + } + pointer operator->() const + { + return std::addressof(operator*()); + } + + node_pointer AsNodePointer() const + { + return node; + } + +private: + friend class intrusive_list; + node_pointer node = nullptr; +}; + +template +class intrusive_list { +public: + using difference_type = std::ptrdiff_t; + using size_type = std::size_t; + using value_type = T; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using iterator = intrusive_list_iterator; + using const_iterator = intrusive_list_iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + /** + * Inserts a node at the given location indicated by an iterator. + * + * @param location The location to insert the node. + * @param new_node The node to add. + */ + iterator insert(iterator location, pointer new_node) + { + return insert_before(location, new_node); + } + + /** + * Inserts a node at the given location, moving the previous + * node occupant ahead of the one inserted. + * + * @param location The location to insert the new node. + * @param new_node The node to insert into the list. + */ + iterator insert_before(iterator location, pointer new_node) + { + auto existing_node = location.AsNodePointer(); + + new_node->next = existing_node; + new_node->prev = existing_node->prev; + existing_node->prev->next = new_node; + existing_node->prev = new_node; + + return iterator(new_node); + } + + /** + * Inserts a new node into the list ahead of the position indicated. + * + * @param position Location to insert the node in front of. + * @param new_node The node to be inserted into the list. + */ + iterator insert_after(iterator position, pointer new_node) + { + if (empty()) + return insert(begin(), new_node); + + return insert(++position, new_node); + } + + /** + * Add an entry to the start of the list. + * @param node Node to add to the list. + */ + void push_front(pointer node) + { + insert(begin(), node); + } + + /** + * Add an entry to the end of the list + * @param node Node to add to the list. + */ + void push_back(pointer node) + { + insert(end(), node); + } + + /** + * Erases the node at the front of the list. + * @note Must not be called on an empty list. + */ + void pop_front() + { + DEBUG_ASSERT(!empty()); + erase(begin()); + } + + /** + * Erases the node at the back of the list. + * @note Must not be called on an empty list. + */ + void pop_back() + { + DEBUG_ASSERT(!empty()); + erase(--end()); + } + + /** + * Removes a node from this list + * @param it An iterator that points to the node to remove from list. + */ + pointer remove(iterator& it) + { + DEBUG_ASSERT(it != end()); + + pointer node = &*it++; + + node->prev->next = node->next; + node->next->prev = node->prev; +#if !defined(NDEBUG) + node->next = nullptr; + node->prev = nullptr; +#endif + + return node; + } + + /** + * Removes a node from this list + * @param it A constant iterator that points to the node to remove from list. + */ + pointer remove(const iterator& it) + { + iterator copy = it; + return remove(copy); + } + + /** + * Removes a node from this list. + * @param node A pointer to the node to remove. + */ + pointer remove(pointer node) + { + return remove(iterator(node)); + } + + /** + * Removes a node from this list. + * @param node A reference to the node to remove. + */ + pointer remove(reference node) + { + return remove(iterator(node)); + } + + /** + * Is this list empty? + * @returns true if there are no nodes in this list. + */ + bool empty() const + { + return root->next == root.get(); + } + + /** + * Gets the total number of elements within this list. + * @return the number of elements in this list. + */ + size_type size() const + { + return static_cast(std::distance(begin(), end())); + } + + /** + * Retrieves a reference to the node at the front of the list. + * @note Must not be called on an empty list. + */ + reference front() + { + DEBUG_ASSERT(!empty()); + return *begin(); + } + + /** + * Retrieves a constant reference to the node at the front of the list. + * @note Must not be called on an empty list. + */ + const_reference front() const + { + DEBUG_ASSERT(!empty()); + return *begin(); + } + + /** + * Retrieves a reference to the node at the back of the list. + * @note Must not be called on an empty list. + */ + reference back() + { + DEBUG_ASSERT(!empty()); + return *--end(); + } + + /** + * Retrieves a constant reference to the node at the back of the list. + * @note Must not be called on an empty list. + */ + const_reference back() const + { + DEBUG_ASSERT(!empty()); + return *--end(); + } + + // Iterator interface + iterator begin() { return iterator(root->next); } + const_iterator begin() const { return const_iterator(root->next); } + const_iterator cbegin() const { return begin(); } + + iterator end() { return iterator(root.get()); } + const_iterator end() const { return const_iterator(root.get()); } + const_iterator cend() const { return end(); } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator crbegin() const { return rbegin(); } + + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator crend() const { return rend(); } + + /** + * Erases a node from the list, indicated by an iterator. + * @param it The iterator that points to the node to erase. + */ + iterator erase(iterator it) + { + remove(it); + return it; + } + + /** + * Erases a node from this list. + * @param node A pointer to the node to erase from this list. + */ + iterator erase(pointer node) + { + return erase(iterator(node)); + } + + /** + * Erases a node from this list. + * @param node A reference to the node to erase from this list. + */ + iterator erase(reference node) + { + return erase(iterator(node)); + } + + /** + * Exchanges contents of this list with another list instance. + * @param other The other list to swap with. + */ + void swap(intrusive_list& other) noexcept + { + root.swap(other.root); + } + +private: + std::shared_ptr> root = std::make_shared>(); +}; + +/** + * Exchanges contents of an intrusive list with another intrusive list. + * @tparam T The type of data being kept track of by the lists. + * @param lhs The first list. + * @param rhs The second list. + */ +template +void swap(intrusive_list& lhs, intrusive_list& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace mcl diff --git a/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp b/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp new file mode 100644 index 0000000000..0cb143430d --- /dev/null +++ b/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2022 merryhime +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +namespace mcl { + +/// A metavalue (of type VT and value v). +template using value = std::integral_constant; +/// A metavalue of type size_t (and value v). +template using size_value = value; +/// A metavalue of type bool (and value v). (Aliases to std::bool_constant.) +template using bool_value = value; +/// true metavalue (Aliases to std::true_type). +using true_type = bool_value; +/// false metavalue (Aliases to std::false_type). +using false_type = bool_value; + +/// Is type T an instance of template class C? +template class, class> +struct is_instance_of_template : false_type {}; + +template class C, class... As> +struct is_instance_of_template> : true_type {}; + +/// Is type T an instance of template class C? +template class C, class T> +constexpr bool is_instance_of_template_v = is_instance_of_template::value; + +} // namespace mcl diff --git a/src/dynarmic/tests/A32/fuzz_arm.cpp b/src/dynarmic/tests/A32/fuzz_arm.cpp index cd2eade884..e9834a6663 100644 --- a/src/dynarmic/tests/A32/fuzz_arm.cpp +++ b/src/dynarmic/tests/A32/fuzz_arm.cpp @@ -15,9 +15,7 @@ #include #include -#include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/tests/fuzz_util.h" @@ -356,67 +354,67 @@ static void RunTestInstance(Dynarmic::A32::Jit& jit, uni_env.ticks_left = instructions.size(); // Unicorn counts thumb instructions weirdly. uni.Run(); - SCOPE_FAIL { - fmt::print("Instruction Listing:\n"); - fmt::print("{}\n", Common::DisassembleAArch32(std::is_same_v, initial_pc, (const u8*)instructions.data(), instructions.size() * sizeof(instructions[0]))); + // SCOPE_FAIL { + // fmt::print("Instruction Listing:\n"); + // fmt::print("{}\n", Common::DisassembleAArch32(std::is_same_v, initial_pc, (const u8*)instructions.data(), instructions.size() * sizeof(instructions[0]))); - fmt::print("Initial register listing:\n"); - for (size_t i = 0; i < regs.size(); ++i) { - fmt::print("{:3s}: {:08x}\n", static_cast(i), regs[i]); - } - for (size_t i = 0; i < vecs.size(); ++i) { - fmt::print("{:3s}: {:08x}\n", static_cast(i), vecs[i]); - } - fmt::print("cpsr {:08x}\n", cpsr); - fmt::print("fpcr {:08x}\n", fpscr); - fmt::print("fpcr.AHP {}\n", FP::FPCR{fpscr}.AHP()); - fmt::print("fpcr.DN {}\n", FP::FPCR{fpscr}.DN()); - fmt::print("fpcr.FZ {}\n", FP::FPCR{fpscr}.FZ()); - fmt::print("fpcr.RMode {}\n", static_cast(FP::FPCR{fpscr}.RMode())); - fmt::print("fpcr.FZ16 {}\n", FP::FPCR{fpscr}.FZ16()); - fmt::print("\n"); + // fmt::print("Initial register listing:\n"); + // for (size_t i = 0; i < regs.size(); ++i) { + // fmt::print("{:3s}: {:08x}\n", static_cast(i), regs[i]); + // } + // for (size_t i = 0; i < vecs.size(); ++i) { + // fmt::print("{:3s}: {:08x}\n", static_cast(i), vecs[i]); + // } + // fmt::print("cpsr {:08x}\n", cpsr); + // fmt::print("fpcr {:08x}\n", fpscr); + // fmt::print("fpcr.AHP {}\n", FP::FPCR{fpscr}.AHP()); + // fmt::print("fpcr.DN {}\n", FP::FPCR{fpscr}.DN()); + // fmt::print("fpcr.FZ {}\n", FP::FPCR{fpscr}.FZ()); + // fmt::print("fpcr.RMode {}\n", static_cast(FP::FPCR{fpscr}.RMode())); + // fmt::print("fpcr.FZ16 {}\n", FP::FPCR{fpscr}.FZ16()); + // fmt::print("\n"); - fmt::print("Final register listing:\n"); - fmt::print(" unicorn dynarmic\n"); - const auto uni_regs = uni.GetRegisters(); - for (size_t i = 0; i < regs.size(); ++i) { - fmt::print("{:3s}: {:08x} {:08x} {}\n", static_cast(i), uni_regs[i], jit.Regs()[i], uni_regs[i] != jit.Regs()[i] ? "*" : ""); - } - const auto uni_ext_regs = uni.GetExtRegs(); - for (size_t i = 0; i < vecs.size(); ++i) { - fmt::print("s{:2d}: {:08x} {:08x} {}\n", static_cast(i), uni_ext_regs[i], jit.ExtRegs()[i], uni_ext_regs[i] != jit.ExtRegs()[i] ? "*" : ""); - } - fmt::print("cpsr {:08x} {:08x} {}\n", uni.GetCpsr(), jit.Cpsr(), uni.GetCpsr() != jit.Cpsr() ? "*" : ""); - fmt::print("fpsr {:08x} {:08x} {}\n", uni.GetFpscr(), jit.Fpscr(), (uni.GetFpscr() & 0xF0000000) != (jit.Fpscr() & 0xF0000000) ? "*" : ""); - fmt::print("\n"); + // fmt::print("Final register listing:\n"); + // fmt::print(" unicorn dynarmic\n"); + // const auto uni_regs = uni.GetRegisters(); + // for (size_t i = 0; i < regs.size(); ++i) { + // fmt::print("{:3s}: {:08x} {:08x} {}\n", static_cast(i), uni_regs[i], jit.Regs()[i], uni_regs[i] != jit.Regs()[i] ? "*" : ""); + // } + // const auto uni_ext_regs = uni.GetExtRegs(); + // for (size_t i = 0; i < vecs.size(); ++i) { + // fmt::print("s{:2d}: {:08x} {:08x} {}\n", static_cast(i), uni_ext_regs[i], jit.ExtRegs()[i], uni_ext_regs[i] != jit.ExtRegs()[i] ? "*" : ""); + // } + // fmt::print("cpsr {:08x} {:08x} {}\n", uni.GetCpsr(), jit.Cpsr(), uni.GetCpsr() != jit.Cpsr() ? "*" : ""); + // fmt::print("fpsr {:08x} {:08x} {}\n", uni.GetFpscr(), jit.Fpscr(), (uni.GetFpscr() & 0xF0000000) != (jit.Fpscr() & 0xF0000000) ? "*" : ""); + // fmt::print("\n"); - fmt::print("Modified memory:\n"); - fmt::print(" uni dyn\n"); - auto uni_iter = uni_env.modified_memory.begin(); - auto jit_iter = jit_env.modified_memory.begin(); - while (uni_iter != uni_env.modified_memory.end() || jit_iter != jit_env.modified_memory.end()) { - if (uni_iter == uni_env.modified_memory.end() || (jit_iter != jit_env.modified_memory.end() && uni_iter->first > jit_iter->first)) { - fmt::print("{:08x}: {:02x} *\n", jit_iter->first, jit_iter->second); - jit_iter++; - } else if (jit_iter == jit_env.modified_memory.end() || jit_iter->first > uni_iter->first) { - fmt::print("{:08x}: {:02x} *\n", uni_iter->first, uni_iter->second); - uni_iter++; - } else if (uni_iter->first == jit_iter->first) { - fmt::print("{:08x}: {:02x} {:02x} {}\n", uni_iter->first, uni_iter->second, jit_iter->second, uni_iter->second != jit_iter->second ? "*" : ""); - uni_iter++; - jit_iter++; - } - } - fmt::print("\n"); + // fmt::print("Modified memory:\n"); + // fmt::print(" uni dyn\n"); + // auto uni_iter = uni_env.modified_memory.begin(); + // auto jit_iter = jit_env.modified_memory.begin(); + // while (uni_iter != uni_env.modified_memory.end() || jit_iter != jit_env.modified_memory.end()) { + // if (uni_iter == uni_env.modified_memory.end() || (jit_iter != jit_env.modified_memory.end() && uni_iter->first > jit_iter->first)) { + // fmt::print("{:08x}: {:02x} *\n", jit_iter->first, jit_iter->second); + // jit_iter++; + // } else if (jit_iter == jit_env.modified_memory.end() || jit_iter->first > uni_iter->first) { + // fmt::print("{:08x}: {:02x} *\n", uni_iter->first, uni_iter->second); + // uni_iter++; + // } else if (uni_iter->first == jit_iter->first) { + // fmt::print("{:08x}: {:02x} {:02x} {}\n", uni_iter->first, uni_iter->second, jit_iter->second, uni_iter->second != jit_iter->second ? "*" : ""); + // uni_iter++; + // jit_iter++; + // } + // } + // fmt::print("\n"); - fmt::print("x86_64:\n"); - fmt::print("{}", jit.Disassemble()); + // fmt::print("x86_64:\n"); + // fmt::print("{}", jit.Disassemble()); - fmt::print("Interrupts:\n"); - for (const auto& i : uni_env.interrupts) { - std::puts(i.c_str()); - } - }; + // fmt::print("Interrupts:\n"); + // for (const auto& i : uni_env.interrupts) { + // std::puts(i.c_str()); + // } + // }; REQUIRE(uni_env.code_mem_modified_by_guest == jit_env.code_mem_modified_by_guest); if (uni_env.code_mem_modified_by_guest) { diff --git a/src/dynarmic/tests/A32/fuzz_thumb.cpp b/src/dynarmic/tests/A32/fuzz_thumb.cpp index f985e6f93d..7fef968b95 100644 --- a/src/dynarmic/tests/A32/fuzz_thumb.cpp +++ b/src/dynarmic/tests/A32/fuzz_thumb.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/tests/rand_int.h" diff --git a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp index 0c7a30a868..749cc77126 100644 --- a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp +++ b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp @@ -12,7 +12,6 @@ #include #include -#include #include "dynarmic/common/common_types.h" #include "dynarmic/tests/fuzz_util.h" @@ -205,82 +204,82 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv uni_env.ticks_left = instructions.size() * 4; uni.Run(); - SCOPE_FAIL { - fmt::print("Instruction Listing:\n"); - for (u32 instruction : instructions) { - fmt::print("{:08x} {}\n", instruction, Common::DisassembleAArch64(instruction)); - } - fmt::print("\n"); + // SCOPE_FAIL { + // fmt::print("Instruction Listing:\n"); + // for (u32 instruction : instructions) { + // fmt::print("{:08x} {}\n", instruction, Common::DisassembleAArch64(instruction)); + // } + // fmt::print("\n"); - fmt::print("Initial register listing:\n"); - for (size_t i = 0; i < regs.size(); ++i) { - fmt::print("{:3s}: {:016x}\n", A64::RegToString(static_cast(i)), regs[i]); - } - for (size_t i = 0; i < vecs.size(); ++i) { - fmt::print("{:3s}: {:016x}{:016x}\n", A64::VecToString(static_cast(i)), vecs[i][1], vecs[i][0]); - } - fmt::print("sp : {:016x}\n", initial_sp); - fmt::print("pc : {:016x}\n", instructions_start); - fmt::print("p : {:08x}\n", pstate); - fmt::print("fpcr {:08x}\n", fpcr); - fmt::print("fpcr.AHP {}\n", FP::FPCR{fpcr}.AHP()); - fmt::print("fpcr.DN {}\n", FP::FPCR{fpcr}.DN()); - fmt::print("fpcr.FZ {}\n", FP::FPCR{fpcr}.FZ()); - fmt::print("fpcr.RMode {}\n", static_cast(FP::FPCR{fpcr}.RMode())); - fmt::print("fpcr.FZ16 {}\n", FP::FPCR{fpcr}.FZ16()); - fmt::print("\n"); + // fmt::print("Initial register listing:\n"); + // for (size_t i = 0; i < regs.size(); ++i) { + // fmt::print("{:3s}: {:016x}\n", A64::RegToString(static_cast(i)), regs[i]); + // } + // for (size_t i = 0; i < vecs.size(); ++i) { + // fmt::print("{:3s}: {:016x}{:016x}\n", A64::VecToString(static_cast(i)), vecs[i][1], vecs[i][0]); + // } + // fmt::print("sp : {:016x}\n", initial_sp); + // fmt::print("pc : {:016x}\n", instructions_start); + // fmt::print("p : {:08x}\n", pstate); + // fmt::print("fpcr {:08x}\n", fpcr); + // fmt::print("fpcr.AHP {}\n", FP::FPCR{fpcr}.AHP()); + // fmt::print("fpcr.DN {}\n", FP::FPCR{fpcr}.DN()); + // fmt::print("fpcr.FZ {}\n", FP::FPCR{fpcr}.FZ()); + // fmt::print("fpcr.RMode {}\n", static_cast(FP::FPCR{fpcr}.RMode())); + // fmt::print("fpcr.FZ16 {}\n", FP::FPCR{fpcr}.FZ16()); + // fmt::print("\n"); - fmt::print("Final register listing:\n"); - fmt::print(" unicorn dynarmic\n"); - const auto uni_regs = uni.GetRegisters(); - for (size_t i = 0; i < regs.size(); ++i) { - fmt::print("{:3s}: {:016x} {:016x} {}\n", A64::RegToString(static_cast(i)), uni_regs[i], jit.GetRegisters()[i], uni_regs[i] != jit.GetRegisters()[i] ? "*" : ""); - } - const auto uni_vecs = uni.GetVectors(); - for (size_t i = 0; i < vecs.size(); ++i) { - fmt::print("{:3s}: {:016x}{:016x} {:016x}{:016x} {}\n", A64::VecToString(static_cast(i)), - uni_vecs[i][1], uni_vecs[i][0], - jit.GetVectors()[i][1], jit.GetVectors()[i][0], - uni_vecs[i] != jit.GetVectors()[i] ? "*" : ""); - } - fmt::print("sp : {:016x} {:016x} {}\n", uni.GetSP(), jit.GetSP(), uni.GetSP() != jit.GetSP() ? "*" : ""); - fmt::print("pc : {:016x} {:016x} {}\n", uni.GetPC(), jit.GetPC(), uni.GetPC() != jit.GetPC() ? "*" : ""); - fmt::print("p : {:08x} {:08x} {}\n", uni.GetPstate(), jit.GetPstate(), (uni.GetPstate() & 0xF0000000) != (jit.GetPstate() & 0xF0000000) ? "*" : ""); - fmt::print("qc : {:08x} {:08x} {}\n", uni.GetFpsr(), jit.GetFpsr(), FP::FPSR{uni.GetFpsr()}.QC() != FP::FPSR{jit.GetFpsr()}.QC() ? "*" : ""); - fmt::print("\n"); + // fmt::print("Final register listing:\n"); + // fmt::print(" unicorn dynarmic\n"); + // const auto uni_regs = uni.GetRegisters(); + // for (size_t i = 0; i < regs.size(); ++i) { + // fmt::print("{:3s}: {:016x} {:016x} {}\n", A64::RegToString(static_cast(i)), uni_regs[i], jit.GetRegisters()[i], uni_regs[i] != jit.GetRegisters()[i] ? "*" : ""); + // } + // const auto uni_vecs = uni.GetVectors(); + // for (size_t i = 0; i < vecs.size(); ++i) { + // fmt::print("{:3s}: {:016x}{:016x} {:016x}{:016x} {}\n", A64::VecToString(static_cast(i)), + // uni_vecs[i][1], uni_vecs[i][0], + // jit.GetVectors()[i][1], jit.GetVectors()[i][0], + // uni_vecs[i] != jit.GetVectors()[i] ? "*" : ""); + // } + // fmt::print("sp : {:016x} {:016x} {}\n", uni.GetSP(), jit.GetSP(), uni.GetSP() != jit.GetSP() ? "*" : ""); + // fmt::print("pc : {:016x} {:016x} {}\n", uni.GetPC(), jit.GetPC(), uni.GetPC() != jit.GetPC() ? "*" : ""); + // fmt::print("p : {:08x} {:08x} {}\n", uni.GetPstate(), jit.GetPstate(), (uni.GetPstate() & 0xF0000000) != (jit.GetPstate() & 0xF0000000) ? "*" : ""); + // fmt::print("qc : {:08x} {:08x} {}\n", uni.GetFpsr(), jit.GetFpsr(), FP::FPSR{uni.GetFpsr()}.QC() != FP::FPSR{jit.GetFpsr()}.QC() ? "*" : ""); + // fmt::print("\n"); - fmt::print("Modified memory:\n"); - fmt::print(" uni dyn\n"); - auto uni_iter = uni_env.modified_memory.begin(); - auto jit_iter = jit_env.modified_memory.begin(); - while (uni_iter != uni_env.modified_memory.end() || jit_iter != jit_env.modified_memory.end()) { - if (uni_iter == uni_env.modified_memory.end() || (jit_iter != jit_env.modified_memory.end() && uni_iter->first > jit_iter->first)) { - fmt::print("{:016x}: {:02x} *\n", jit_iter->first, jit_iter->second); - jit_iter++; - } else if (jit_iter == jit_env.modified_memory.end() || jit_iter->first > uni_iter->first) { - fmt::print("{:016x}: {:02x} *\n", uni_iter->first, uni_iter->second); - uni_iter++; - } else if (uni_iter->first == jit_iter->first) { - fmt::print("{:016x}: {:02x} {:02x} {}\n", uni_iter->first, uni_iter->second, jit_iter->second, uni_iter->second != jit_iter->second ? "*" : ""); - uni_iter++; - jit_iter++; - } - } - fmt::print("\n"); + // fmt::print("Modified memory:\n"); + // fmt::print(" uni dyn\n"); + // auto uni_iter = uni_env.modified_memory.begin(); + // auto jit_iter = jit_env.modified_memory.begin(); + // while (uni_iter != uni_env.modified_memory.end() || jit_iter != jit_env.modified_memory.end()) { + // if (uni_iter == uni_env.modified_memory.end() || (jit_iter != jit_env.modified_memory.end() && uni_iter->first > jit_iter->first)) { + // fmt::print("{:016x}: {:02x} *\n", jit_iter->first, jit_iter->second); + // jit_iter++; + // } else if (jit_iter == jit_env.modified_memory.end() || jit_iter->first > uni_iter->first) { + // fmt::print("{:016x}: {:02x} *\n", uni_iter->first, uni_iter->second); + // uni_iter++; + // } else if (uni_iter->first == jit_iter->first) { + // fmt::print("{:016x}: {:02x} {:02x} {}\n", uni_iter->first, uni_iter->second, jit_iter->second, uni_iter->second != jit_iter->second ? "*" : ""); + // uni_iter++; + // jit_iter++; + // } + // } + // fmt::print("\n"); - const auto get_code = [&jit_env](u64 vaddr) { return jit_env.MemoryReadCode(vaddr); }; - const A64::LocationDescriptor location{instructions_start, FP::FPCR{fpcr}}; - IR::Block ir_block{location}; - A64::Translate(ir_block, location, get_code, {}); - fmt::print("IR:\n{}\n", IR::DumpBlock(ir_block)); - Optimization::Optimize(ir_block, conf, {}); - fmt::print("Optimized IR:\n{}\n", IR::DumpBlock(ir_block)); - fmt::print("x86_64:\n{}", jit.Disassemble()); - fmt::print("Interrupts:\n"); - for (auto& i : uni_env.interrupts) { - puts(i.c_str()); - } - }; + // const auto get_code = [&jit_env](u64 vaddr) { return jit_env.MemoryReadCode(vaddr); }; + // const A64::LocationDescriptor location{instructions_start, FP::FPCR{fpcr}}; + // IR::Block ir_block{location}; + // A64::Translate(ir_block, location, get_code, {}); + // fmt::print("IR:\n{}\n", IR::DumpBlock(ir_block)); + // Optimization::Optimize(ir_block, conf, {}); + // fmt::print("Optimized IR:\n{}\n", IR::DumpBlock(ir_block)); + // fmt::print("x86_64:\n{}", jit.Disassemble()); + // fmt::print("Interrupts:\n"); + // for (auto& i : uni_env.interrupts) { + // puts(i.c_str()); + // } + // }; REQUIRE(uni_env.code_mem_modified_by_guest == jit_env.code_mem_modified_by_guest); if (uni_env.code_mem_modified_by_guest) { diff --git a/src/dynarmic/tests/CMakeLists.txt b/src/dynarmic/tests/CMakeLists.txt index 395181efe3..ca44dce593 100644 --- a/src/dynarmic/tests/CMakeLists.txt +++ b/src/dynarmic/tests/CMakeLists.txt @@ -72,7 +72,7 @@ add_executable(dynarmic_print_info print_info.cpp ) create_target_directory_groups(dynarmic_print_info) -target_link_libraries(dynarmic_print_info PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense) +target_link_libraries(dynarmic_print_info PRIVATE dynarmic fmt::fmt unordered_dense::unordered_dense) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic_print_info PRIVATE Boost::variant Boost::icl Boost::pool) else() @@ -93,7 +93,7 @@ add_executable(dynarmic_test_generator create_target_directory_groups(dynarmic_test_generator) -target_link_libraries(dynarmic_test_generator PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense) +target_link_libraries(dynarmic_test_generator PRIVATE dynarmic fmt::fmt unordered_dense::unordered_dense) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic_test_generator PRIVATE Boost::variant Boost::icl Boost::pool) else() @@ -110,7 +110,7 @@ add_executable(dynarmic_test_reader test_reader.cpp ) create_target_directory_groups(dynarmic_test_reader) -target_link_libraries(dynarmic_test_reader PRIVATE dynarmic fmt::fmt merry::mcl unordered_dense::unordered_dense) +target_link_libraries(dynarmic_test_reader PRIVATE dynarmic fmt::fmt unordered_dense::unordered_dense) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic_test_reader PRIVATE Boost::variant Boost::icl Boost::pool) else() @@ -123,7 +123,7 @@ target_compile_definitions(dynarmic_test_reader PRIVATE FMT_USE_USER_DEFINED_LIT # create_target_directory_groups(dynarmic_tests) -target_link_libraries(dynarmic_tests PRIVATE dynarmic Catch2::Catch2WithMain fmt::fmt merry::mcl unordered_dense::unordered_dense) +target_link_libraries(dynarmic_tests PRIVATE dynarmic Catch2::Catch2WithMain fmt::fmt unordered_dense::unordered_dense) if (BOOST_NO_HEADERS) target_link_libraries(dynarmic_tests PRIVATE Boost::variant Boost::icl Boost::pool) else() diff --git a/src/dynarmic/tests/print_info.cpp b/src/dynarmic/tests/print_info.cpp index 33d84ba8cd..19e2ca38b2 100644 --- a/src/dynarmic/tests/print_info.cpp +++ b/src/dynarmic/tests/print_info.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "dynarmic/common/llvm_disassemble.h" diff --git a/src/dynarmic/tests/test_generator.cpp b/src/dynarmic/tests/test_generator.cpp index 33e41099ff..43203c3e13 100644 --- a/src/dynarmic/tests/test_generator.cpp +++ b/src/dynarmic/tests/test_generator.cpp @@ -16,8 +16,7 @@ #include #include -#include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/common/common_types.h" #include "./A32/testenv.h" diff --git a/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp b/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp index 66c1e7fd24..9a17bc5582 100644 --- a/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp +++ b/src/dynarmic/tests/unicorn_emu/a32_unicorn.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include "dynarmic/mcl/bit.hpp" #include "dynarmic/tests/unicorn_emu/a32_unicorn.h" #include "dynarmic/common/assert.h" #include "dynarmic/tests/A32/testenv.h" diff --git a/src/frontend_common/CMakeLists.txt b/src/frontend_common/CMakeLists.txt index a6d580cb18..f9b3805939 100644 --- a/src/frontend_common/CMakeLists.txt +++ b/src/frontend_common/CMakeLists.txt @@ -22,8 +22,6 @@ if (ENABLE_UPDATE_CHECKER) target_sources(frontend_common PRIVATE update_checker.cpp update_checker.h) - - target_compile_definitions(frontend_common PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT) target_link_libraries(frontend_common PRIVATE OpenSSL::SSL OpenSSL::Crypto) endif() diff --git a/src/frontend_common/update_checker.cpp b/src/frontend_common/update_checker.cpp index 75b1dc00cc..3e5a832ba0 100644 --- a/src/frontend_common/update_checker.cpp +++ b/src/frontend_common/update_checker.cpp @@ -13,7 +13,7 @@ #include "common/scm_rev.h" #include "update_checker.h" -#include +#include "common/httplib.h" #ifdef YUZU_BUNDLED_OPENSSL #include diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 9355a88c4b..d625617bd5 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp @@ -800,6 +800,10 @@ Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { auto& controller = GetControllerFromNpadIdType(aruid, npad_id); auto* shared_memory = controller.shared_memory; + if (!shared_memory) { + LOG_WARNING(Service_HID, "DisconnectNpad: shared_memory is null for npad_id={}", npad_id); + return ResultSuccess; + } // Don't reset shared_memory->assignment_mode this value is persistent shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out shared_memory->device_type.raw = 0; diff --git a/src/ios/AppUI-Bridging-Header.h b/src/ios/AppUI-Bridging-Header.h new file mode 100644 index 0000000000..00fadaa6dc --- /dev/null +++ b/src/ios/AppUI-Bridging-Header.h @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef AppUI_Bridging_Header_h +#define AppUI_Bridging_Header_h + +#import "AppUIObjC.h" + +#endif /* AppUI_Bridging_Header_h */ diff --git a/src/ios/AppUI.swift b/src/ios/AppUI.swift new file mode 100644 index 0000000000..b1d95324cc --- /dev/null +++ b/src/ios/AppUI.swift @@ -0,0 +1,105 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +import UIKit +import Foundation +import QuartzCore.CAMetalLayer + +public struct AppUI { + + public static let shared = AppUI() + + fileprivate let appUIObjC = AppUIObjC.shared() + + public func configure(layer: CAMetalLayer, with size: CGSize) { + appUIObjC.configure(layer: layer, with: size) + } + + public func information(for url: URL) -> AppUIInformation { + appUIObjC.gameInformation.information(for: url) + } + + public func insert(game url: URL) { + appUIObjC.insert(game: url) + } + + public func insert(games urls: [URL]) { + appUIObjC.insert(games: urls) + } + + public func bootOS() { + appUIObjC.bootOS() + } + + public func pause() { + appUIObjC.pause() + } + + public func play() { + appUIObjC.play() + } + + public func ispaused() -> Bool { + return appUIObjC.ispaused() + } + + public func FirstFrameShowed() -> Bool { + return appUIObjC.hasfirstfame() + } + + public func canGetFullPath() -> Bool { + return appUIObjC.canGetFullPath() + } + + + public func exit() { + appUIObjC.quit() + } + + public func step() { + appUIObjC.step() + } + + public func orientationChanged(orientation: UIInterfaceOrientation, with layer: CAMetalLayer, size: CGSize) { + appUIObjC.orientationChanged(orientation: orientation, with: layer, size: size) + } + + public func touchBegan(at point: CGPoint, for index: UInt) { + appUIObjC.touchBegan(at: point, for: index) + } + + public func touchEnded(for index: UInt) { + appUIObjC.touchEnded(for: index) + } + + public func touchMoved(at point: CGPoint, for index: UInt) { + appUIObjC.touchMoved(at: point, for: index) + } + + public func gyroMoved(x: Float, y: Float, z: Float, accelX: Float, accelY: Float, accelZ: Float, controllerId: Int32, deltaTimestamp: Int32) { + // Calling the Objective-C function with both gyroscope and accelerometer data + appUIObjC.virtualControllerGyro(controllerId, + deltaTimestamp: deltaTimestamp, + gyroX: x, gyroY: y, gyroZ: z, + accelX: accelX, accelY: accelY, accelZ: accelZ) + } + + + public func thumbstickMoved(analog: VirtualControllerAnalogType, x: Float, y: Float, controllerid: Int) { + appUIObjC.thumbstickMoved(analog, x: CGFloat(x), y: CGFloat(y), controllerId: Int32(controllerid)) + } + + public func virtualControllerButtonDown(button: VirtualControllerButtonType, controllerid: Int) { + appUIObjC.virtualControllerButtonDown(button, controllerId: Int32(controllerid)) + } + + public func virtualControllerButtonUp(button: VirtualControllerButtonType, controllerid: Int) { + appUIObjC.virtualControllerButtonUp(button, controllerId: Int32(controllerid)) + } + + public func settingsSaved() { + appUIObjC.settingsChanged() + } +} diff --git a/src/ios/AppUIGameInformation.h b/src/ios/AppUIGameInformation.h new file mode 100644 index 0000000000..1a602956c3 --- /dev/null +++ b/src/ios/AppUIGameInformation.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface AppUIInformation : NSObject +@property (nonatomic, strong) NSString *developer; +@property (nonatomic, strong) NSData *iconData; +@property (nonatomic) BOOL isHomebrew; +@property (nonatomic) uint64_t programID; +@property (nonatomic, strong) NSString *title, *version; + +-(AppUIInformation *) initWithDeveloper:(NSString *)developer iconData:(NSData *)iconData isHomebrew:(BOOL)isHomebrew programID:(uint64_t)programID title:(NSString *)title version:(NSString *)version; +@end + +@interface AppUIGameInformation : NSObject ++(AppUIGameInformation *) sharedInstance NS_SWIFT_NAME(shared()); + +-(AppUIInformation *) informationForGame:(NSURL *)url NS_SWIFT_NAME(information(for:)); +@end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/AppUIGameInformation.mm b/src/ios/AppUIGameInformation.mm new file mode 100644 index 0000000000..5c0e603348 --- /dev/null +++ b/src/ios/AppUIGameInformation.mm @@ -0,0 +1,436 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#import +#import "AppUIGameInformation.h" +#import "EmulationSession.h" + +#include "common/fs/fs.h" +#include "common/fs/path_util.h" +#include "core/core.h" +#include "core/file_sys/fs_filesystem.h" +#include "core/file_sys/patch_manager.h" +#include "core/loader/loader.h" +#include "core/loader/nro.h" +#include "frontend_common/config.h" + +struct GameMetadata { + std::string title; + u64 programId; + std::string developer; + std::string version; + std::vector icon; + bool isHomebrew; +}; + + +class SdlConfig final : public Config { +public: + explicit SdlConfig(std::optional config_path); + ~SdlConfig() override; + + void ReloadAllValues() override; + void SaveAllValues() override; + +protected: + void ReadSdlValues(); + void ReadSdlPlayerValues(std::size_t player_index); + void ReadSdlControlValues(); + void ReadHidbusValues() override; + void ReadDebugControlValues() override; + void ReadPathValues() override {} + void ReadShortcutValues() override {} + void ReadUIValues() override {} + void ReadUIGamelistValues() override {} + void ReadUILayoutValues() override {} + void ReadMultiplayerValues() override {} + + void SaveSdlValues(); + void SaveSdlPlayerValues(std::size_t player_index); + void SaveSdlControlValues(); + void SaveHidbusValues() override; + void SaveDebugControlValues() override; + void SavePathValues() override {} + void SaveShortcutValues() override {} + void SaveUIValues() override {} + void SaveUIGamelistValues() override {} + void SaveUILayoutValues() override {} + void SaveMultiplayerValues() override {} + + std::vector& FindRelevantList(Settings::Category category) override; + +public: + static const std::array default_buttons; + static const std::array default_motions; + static const std::array, Settings::NativeAnalog::NumAnalogs> default_analogs; + static const std::array default_stick_mod; + static const std::array default_ringcon_analogs; +}; + + +#define SDL_MAIN_HANDLED +#include + +#include "common/logging.h" +#include "input_common/main.h" + +const std::array SdlConfig::default_buttons = { + SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T, + SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W, + SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B, +}; + +const std::array SdlConfig::default_motions = { + SDL_SCANCODE_7, + SDL_SCANCODE_8, +}; + +const std::array, Settings::NativeAnalog::NumAnalogs> SdlConfig::default_analogs{ + { + { + SDL_SCANCODE_UP, + SDL_SCANCODE_DOWN, + SDL_SCANCODE_LEFT, + SDL_SCANCODE_RIGHT, + }, + { + SDL_SCANCODE_I, + SDL_SCANCODE_K, + SDL_SCANCODE_J, + SDL_SCANCODE_L, + }, + }}; + +const std::array SdlConfig::default_stick_mod = { + SDL_SCANCODE_D, + 0, +}; + +const std::array SdlConfig::default_ringcon_analogs{{ + 0, + 0, +}}; + +SdlConfig::SdlConfig(const std::optional config_path) { + Initialize(config_path); + ReadSdlValues(); + SaveSdlValues(); +} + +SdlConfig::~SdlConfig() { + if (global) { + SdlConfig::SaveAllValues(); + } +} + +void SdlConfig::ReloadAllValues() { + Reload(); + ReadSdlValues(); + SaveSdlValues(); +} + +void SdlConfig::SaveAllValues() { + SaveValues(); + SaveSdlValues(); +} + +void SdlConfig::ReadSdlValues() { + ReadSdlControlValues(); +} + +void SdlConfig::ReadSdlControlValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); + + Settings::values.players.SetGlobal(!IsCustomConfig()); + for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { + ReadSdlPlayerValues(p); + } + if (IsCustomConfig()) { + EndGroup(); + return; + } + ReadDebugControlValues(); + ReadHidbusValues(); + + EndGroup(); +} + +void SdlConfig::ReadSdlPlayerValues(const std::size_t player_index) { + std::string player_prefix; + if (type != ConfigType::InputProfile) { + player_prefix.append("player_").append(ToString(player_index)).append("_"); + } + + auto& player = Settings::values.players.GetValue()[player_index]; + if (IsCustomConfig()) { + const auto profile_name = + ReadStringSetting(std::string(player_prefix).append("profile_name")); + if (profile_name.empty()) { + // Use the global input config + player = Settings::values.players.GetValue(true)[player_index]; + player.profile_name = ""; + return; + } + } + + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + auto& player_buttons = player.buttons[i]; + + player_buttons = ReadStringSetting( + std::string(player_prefix).append(Settings::NativeButton::mapping[i]), default_param); + if (player_buttons.empty()) { + player_buttons = default_param; + } + } + + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_stick_mod[i], 0.5f); + auto& player_analogs = player.analogs[i]; + + player_analogs = ReadStringSetting( + std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), default_param); + if (player_analogs.empty()) { + player_analogs = default_param; + } + } + + for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); + auto& player_motions = player.motions[i]; + + player_motions = ReadStringSetting( + std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), default_param); + if (player_motions.empty()) { + player_motions = default_param; + } + } +} + +void SdlConfig::ReadDebugControlValues() { + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; + debug_pad_buttons = ReadStringSetting( + std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), default_param); + if (debug_pad_buttons.empty()) { + debug_pad_buttons = default_param; + } + } + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_stick_mod[i], 0.5f); + auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; + debug_pad_analogs = ReadStringSetting( + std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), default_param); + if (debug_pad_analogs.empty()) { + debug_pad_analogs = default_param; + } + } +} + +void SdlConfig::ReadHidbusValues() { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); + auto& ringcon_analogs = Settings::values.ringcon_analogs; + + ringcon_analogs = ReadStringSetting(std::string("ring_controller"), default_param); + if (ringcon_analogs.empty()) { + ringcon_analogs = default_param; + } +} + +void SdlConfig::SaveSdlValues() { + LOG_DEBUG(Config, "Saving SDL configuration values"); + SaveSdlControlValues(); + + WriteToIni(); +} + +void SdlConfig::SaveSdlControlValues() { + BeginGroup(Settings::TranslateCategory(Settings::Category::Controls)); + + Settings::values.players.SetGlobal(!IsCustomConfig()); + for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { + SaveSdlPlayerValues(p); + } + if (IsCustomConfig()) { + EndGroup(); + return; + } + SaveDebugControlValues(); + SaveHidbusValues(); + + EndGroup(); +} + +void SdlConfig::SaveSdlPlayerValues(const std::size_t player_index) { + std::string player_prefix; + if (type != ConfigType::InputProfile) { + player_prefix = std::string("player_").append(ToString(player_index)).append("_"); + } + + const auto& player = Settings::values.players.GetValue()[player_index]; + if (IsCustomConfig() && player.profile_name.empty()) { + // No custom profile selected + return; + } + + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + WriteStringSetting(std::string(player_prefix).append(Settings::NativeButton::mapping[i]), + player.buttons[i], std::make_optional(default_param)); + } + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_stick_mod[i], 0.5f); + WriteStringSetting(std::string(player_prefix).append(Settings::NativeAnalog::mapping[i]), + player.analogs[i], std::make_optional(default_param)); + } + for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); + WriteStringSetting(std::string(player_prefix).append(Settings::NativeMotion::mapping[i]), + player.motions[i], std::make_optional(default_param)); + } +} + +void SdlConfig::SaveDebugControlValues() { + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + WriteStringSetting(std::string("debug_pad_").append(Settings::NativeButton::mapping[i]), + Settings::values.debug_pad_buttons[i], + std::make_optional(default_param)); + } + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_stick_mod[i], 0.5f); + WriteStringSetting(std::string("debug_pad_").append(Settings::NativeAnalog::mapping[i]), + Settings::values.debug_pad_analogs[i], + std::make_optional(default_param)); + } +} + +void SdlConfig::SaveHidbusValues() { + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f); + WriteStringSetting(std::string("ring_controller"), Settings::values.ringcon_analogs, + std::make_optional(default_param)); +} + +std::vector& SdlConfig::FindRelevantList(Settings::Category category) { + return Settings::values.linkage.by_category[category]; +} + + + + + + + +std::unordered_map m_game_metadata_cache; + +GameMetadata CacheGameMetadata(const std::string& path) { + const auto file = + Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path); + auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0); + + GameMetadata entry; + loader->ReadTitle(entry.title); + loader->ReadProgramId(entry.programId); + loader->ReadIcon(entry.icon); + + const FileSys::PatchManager pm{ + entry.programId, EmulationSession::GetInstance().System().GetFileSystemController(), + EmulationSession::GetInstance().System().GetContentProvider()}; + const auto control = pm.GetControlMetadata(); + + if (control.first != nullptr) { + entry.developer = control.first->GetDeveloperName(); + entry.version = control.first->GetVersionString(); + } else { + FileSys::NACP nacp; + if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success) { + entry.developer = nacp.GetDeveloperName(); + } else { + entry.developer = ""; + } + + entry.version = "1.0.0"; + } + + if (loader->GetFileType() == Loader::FileType::NRO) { + auto loader_nro = reinterpret_cast(loader.get()); + entry.isHomebrew = loader_nro->IsHomebrew(); + } else { + entry.isHomebrew = false; + } + + m_game_metadata_cache[path] = entry; + + return entry; +} + +GameMetadata GameMetadata(const std::string& path, bool reload = false) { + if (!EmulationSession::GetInstance().IsInitialized()) { + NSURL *dir_url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject]; + const char *directory_cstr = [[dir_url path] UTF8String]; + Common::FS::SetAppDirectory(directory_cstr); + + EmulationSession::GetInstance().System().Initialize(); + EmulationSession::GetInstance().InitializeSystem(false); + } + + if (reload) { + return CacheGameMetadata(path); + } + + if (auto search = m_game_metadata_cache.find(path); search != m_game_metadata_cache.end()) { + return search->second; + } + + return CacheGameMetadata(path); +} + + +@implementation AppUIInformation +-(AppUIInformation *) initWithDeveloper:(NSString *)developer iconData:(NSData *)iconData isHomebrew:(BOOL)isHomebrew programID:(uint64_t)programID + title:(NSString *)title version:(NSString *)version { + if (self = [super init]) { + self.developer = developer; + self.iconData = iconData; + self.isHomebrew = isHomebrew; + self.programID = programID; + self.title = title; + self.version = version; + } return self; +} +@end + +@implementation AppUIGameInformation ++(AppUIGameInformation *) sharedInstance { + static AppUIGameInformation *sharedInstance = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + + +-(AppUIInformation *) informationForGame:(NSURL *)url { + auto gameMetadata = GameMetadata([url.path UTF8String]); + + return [[AppUIInformation alloc] initWithDeveloper:[NSString stringWithCString:gameMetadata.developer.c_str() encoding:NSUTF8StringEncoding] + iconData:[NSData dataWithBytes:gameMetadata.icon.data() length:gameMetadata.icon.size()] + isHomebrew:gameMetadata.isHomebrew programID:gameMetadata.programId + title:[NSString stringWithCString:gameMetadata.title.c_str() encoding:NSUTF8StringEncoding] + version:[NSString stringWithCString:gameMetadata.version.c_str() encoding:NSUTF8StringEncoding]]; +} +@end diff --git a/src/ios/AppUIObjC.h b/src/ios/AppUIObjC.h new file mode 100644 index 0000000000..942cd111a7 --- /dev/null +++ b/src/ios/AppUIObjC.h @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#import +#import +#import + +#import "AppUIGameInformation.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, VirtualControllerAnalogType) { + VirtualControllerAnalogTypeLeft = 0, + VirtualControllerAnalogTypeRight = 1 +}; + +typedef NS_ENUM(NSUInteger, VirtualControllerButtonType) { + VirtualControllerButtonTypeA = 0, + VirtualControllerButtonTypeB = 1, + VirtualControllerButtonTypeX = 2, + VirtualControllerButtonTypeY = 3, + VirtualControllerButtonTypeL = 4, + VirtualControllerButtonTypeR = 5, + VirtualControllerButtonTypeTriggerL = 6, + VirtualControllerButtonTypeTriggerR = 7, + VirtualControllerButtonTypeTriggerZL = 8, + VirtualControllerButtonTypeTriggerZR = 9, + VirtualControllerButtonTypePlus = 10, + VirtualControllerButtonTypeMinus = 11, + VirtualControllerButtonTypeDirectionalPadLeft = 12, + VirtualControllerButtonTypeDirectionalPadUp = 13, + VirtualControllerButtonTypeDirectionalPadRight = 14, + VirtualControllerButtonTypeDirectionalPadDown = 15, + VirtualControllerButtonTypeSL = 16, + VirtualControllerButtonTypeSR = 17, + VirtualControllerButtonTypeHome = 18, + VirtualControllerButtonTypeCapture = 19 +}; + +@interface AppUIObjC : NSObject { + CAMetalLayer *_layer; + CGSize _size; +} + +@property (nonatomic, strong) AppUIGameInformation *gameInformation; + ++(AppUIObjC *) sharedInstance NS_SWIFT_NAME(shared()); +-(void) configureLayer:(CAMetalLayer *)layer withSize:(CGSize)size NS_SWIFT_NAME(configure(layer:with:)); +-(void) bootOS; +-(void) pause; +-(void) play; +-(BOOL) ispaused; +-(BOOL) canGetFullPath; +-(void) quit; +-(void) insertGame:(NSURL *)url NS_SWIFT_NAME(insert(game:)); +-(void) insertGames:(NSArray *)games NS_SWIFT_NAME(insert(games:)); +-(void) step; +-(BOOL) hasfirstfame; + +-(void) touchBeganAtPoint:(CGPoint)point index:(NSUInteger)index NS_SWIFT_NAME(touchBegan(at:for:)); +-(void) touchEndedForIndex:(NSUInteger)index; +-(void) touchMovedAtPoint:(CGPoint)point index:(NSUInteger)index NS_SWIFT_NAME(touchMoved(at:for:)); + +-(void) thumbstickMoved:(VirtualControllerAnalogType)analog + x:(CGFloat)x + y:(CGFloat)y + controllerId:(int)controllerId; + +-(void) virtualControllerGyro:(int)controllerId + deltaTimestamp:(int)delta_timestamp + gyroX:(float)gyro_x + gyroY:(float)gyro_y + gyroZ:(float)gyro_z + accelX:(float)accel_x + accelY:(float)accel_y + accelZ:(float)accel_z; + +-(void) virtualControllerButtonDown:(VirtualControllerButtonType)button + controllerId:(int)controllerId; + +-(void) virtualControllerButtonUp:(VirtualControllerButtonType)button + controllerId:(int)controllerId; + + +-(void) orientationChanged:(UIInterfaceOrientation)orientation with:(CAMetalLayer *)layer size:(CGSize)size NS_SWIFT_NAME(orientationChanged(orientation:with:size:)); + +-(void) settingsChanged; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/AppUIObjC.mm b/src/ios/AppUIObjC.mm new file mode 100644 index 0000000000..32bffd43ca --- /dev/null +++ b/src/ios/AppUIObjC.mm @@ -0,0 +1,251 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#import "AppUIObjC.h" + +#import "Config.h" +#import "EmulationSession.h" + +#include "common/fs/fs.h" +#include "common/fs/path_util.h" +#include "common/settings.h" +#include "common/fs/fs.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/savedata_factory.h" +#include "core/loader/nro.h" +#include "frontend_common/content_manager.h" +#include "common/settings_enums.h" +#include "network/announce_multiplayer_session.h" +#include "common/announce_multiplayer_room.h" +#include "network/network.h" + +#include "common/detached_tasks.h" +#include "common/dynamic_library.h" +#include "common/fs/path_util.h" +#include "common/logging.h" +#include "common/scope_exit.h" +#include "common/settings.h" +#include "common/string_util.h" +#include "core/core.h" +#include "core/cpu_manager.h" +#include "core/crypto/key_manager.h" +#include "core/file_sys/card_image.h" +#include "core/file_sys/content_archive.h" +#include "core/file_sys/fs_filesystem.h" +#include "core/file_sys/submission_package.h" +#include "core/file_sys/vfs/vfs.h" +#include "core/file_sys/vfs/vfs_real.h" +#include "core/frontend/applets/cabinet.h" +#include "core/frontend/applets/controller.h" +#include "core/frontend/applets/error.h" +#include "core/frontend/applets/general.h" +#include "core/frontend/applets/mii_edit.h" +#include "core/frontend/applets/profile_select.h" +#include "core/frontend/applets/software_keyboard.h" +#include "core/frontend/applets/web_browser.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/loader/loader.h" +#include "hid_core/hid_core.h" +#include "hid_core/hid_types.h" +#include "video_core/renderer_base.h" +#include "video_core/renderer_vulkan/renderer_vulkan.h" +#include "video_core/vulkan_common/vulkan_instance.h" +#include "video_core/vulkan_common/vulkan_surface.h" + + +#import + +@implementation AppUIObjC +-(AppUIObjC *) init { + if (self = [super init]) { + _gameInformation = [AppUIGameInformation sharedInstance]; + + NSURL *dir_url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject]; + const char *directory_cstr = [[dir_url path] UTF8String]; + + Common::FS::SetAppDirectory(directory_cstr); + // Config{"config", Config::ConfigType::GlobalConfig}; + + EmulationSession::GetInstance().System().Initialize(); + EmulationSession::GetInstance().InitializeSystem(false); + EmulationSession::GetInstance().InitializeGpuDriver(); + + + Settings::values.dump_shaders.SetValue(true); + Settings::values.use_asynchronous_shaders.SetValue(true); + // Settings::values.astc_recompression.SetValue(Settings::AstcRecompression::Bc3); + // Settings::values.resolution_setup.SetValue(Settings::ResolutionSetup::Res1X); + // Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::Bilinear); + } return self; +} + + ++(AppUIObjC *) sharedInstance { + static AppUIObjC *sharedInstance = NULL; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + +- (BOOL)ispaused { + return EmulationSession::GetInstance().IsPaused(); +} + +-(void) pause { + EmulationSession::GetInstance().System().Pause(); + EmulationSession::GetInstance().HaltEmulation(); + EmulationSession::GetInstance().PauseEmulation(); +} + +-(void) play { + + EmulationSession::GetInstance().System().Run(); + EmulationSession::GetInstance().RunEmulation(); + EmulationSession::GetInstance().UnPauseEmulation(); +} + +-(BOOL)hasfirstfame { + @try { + auto* window = &EmulationSession::GetInstance().Window(); + if (window && window->HasFirstFrame()) { + return YES; + } + } + @catch (NSException *exception) { + NSLog(@"Exception occurred: %@", exception); + // Handle the exception, maybe return a default value + return NO; + } + return NO; +} + +- (BOOL)canGetFullPath { + @try { + Core::System& system = EmulationSession::GetInstance().System(); + auto bis_system = system.GetFileSystemController().GetSystemNANDContents(); + + if (bis_system == nullptr) { + return NO; + } + + constexpr u64 QLaunchId = static_cast(Service::AM::AppletProgramId::QLaunch); + auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); + + if (qlaunch_applet_nca == nullptr) { + return NO; + } + + const auto filename = qlaunch_applet_nca->GetFullPath(); + + // If GetFullPath() is successful + return YES; + } @catch (NSException *exception) { + // Handle the exception if needed + return NO; + } +} + +-(void) quit { + EmulationSession::GetInstance().ShutdownEmulation(); +} + +-(void) configureLayer:(CAMetalLayer *)layer withSize:(CGSize)size { + _layer = layer; + _size = size; + EmulationSession::GetInstance().SetNativeWindow(layer, size); +} + +-(void) bootOS { + EmulationSession::GetInstance().BootOS(); +} + +-(void) insertGame:(NSURL *)url { + EmulationSession::GetInstance().InitializeEmulation([url.path UTF8String], [_gameInformation informationForGame:url].programID, true); +} + +-(void) insertGames:(NSArray *)games { + for (NSURL *url in games) { + EmulationSession::GetInstance().ConfigureFilesystemProvider([url.path UTF8String]); + } +} + +-(void) step { + void(EmulationSession::GetInstance().System().Run()); +} + +-(void) touchBeganAtPoint:(CGPoint)point index:(NSUInteger)index { + float h_ratio, w_ratio; + h_ratio = EmulationSession::GetInstance().Window().GetFramebufferLayout().height / (_size.height * [[UIScreen mainScreen] nativeScale]); + w_ratio = EmulationSession::GetInstance().Window().GetFramebufferLayout().width / (_size.width * [[UIScreen mainScreen] nativeScale]); + + EmulationSession::GetInstance().Window().OnTouchPressed([[NSNumber numberWithUnsignedInteger:index] intValue], + (point.x) * [[UIScreen mainScreen] nativeScale] * w_ratio, + ((point.y) * [[UIScreen mainScreen] nativeScale] * h_ratio)); +} + +-(void) touchEndedForIndex:(NSUInteger)index { + EmulationSession::GetInstance().Window().OnTouchReleased([[NSNumber numberWithUnsignedInteger:index] intValue]); +} + +-(void) touchMovedAtPoint:(CGPoint)point index:(NSUInteger)index { + float h_ratio, w_ratio; + h_ratio = EmulationSession::GetInstance().Window().GetFramebufferLayout().height / (_size.height * [[UIScreen mainScreen] nativeScale]); + w_ratio = EmulationSession::GetInstance().Window().GetFramebufferLayout().width / (_size.width * [[UIScreen mainScreen] nativeScale]); + + EmulationSession::GetInstance().Window().OnTouchMoved([[NSNumber numberWithUnsignedInteger:index] intValue], + (point.x) * [[UIScreen mainScreen] nativeScale] * w_ratio, + ((point.y) * [[UIScreen mainScreen] nativeScale] * h_ratio)); +} + +-(void) thumbstickMoved:(VirtualControllerAnalogType)analog + x:(CGFloat)x + y:(CGFloat)y + controllerId:(int)controllerId { + EmulationSession::GetInstance().OnGamepadConnectEvent(controllerId); + EmulationSession::GetInstance().Window().OnGamepadJoystickEvent(controllerId, [[NSNumber numberWithUnsignedInteger:analog] intValue], CGFloat(x), CGFloat(y)); +} + +-(void) virtualControllerButtonDown:(VirtualControllerButtonType)button + controllerId:(int)controllerId { + EmulationSession::GetInstance().OnGamepadConnectEvent(controllerId); + EmulationSession::GetInstance().Window().OnGamepadButtonEvent(controllerId, [[NSNumber numberWithUnsignedInteger:button] intValue], true); +} + +-(void) virtualControllerGyro:(int)controllerId + deltaTimestamp:(int)delta_timestamp + gyroX:(float)gyro_x + gyroY:(float)gyro_y + gyroZ:(float)gyro_z + accelX:(float)accel_x + accelY:(float)accel_y + accelZ:(float)accel_z +{ + EmulationSession::GetInstance().OnGamepadConnectEvent(controllerId); + EmulationSession::GetInstance().Window().OnGamepadMotionEvent(controllerId, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); +} + + +-(void) virtualControllerButtonUp:(VirtualControllerButtonType)button + controllerId:(int)controllerId { + EmulationSession::GetInstance().OnGamepadConnectEvent(controllerId); + EmulationSession::GetInstance().Window().OnGamepadButtonEvent(controllerId, [[NSNumber numberWithUnsignedInteger:button] intValue], false); +} + + +-(void) orientationChanged:(UIInterfaceOrientation)orientation with:(CAMetalLayer *)layer size:(CGSize)size { + _layer = layer; + _size = size; + EmulationSession::GetInstance().Window().OnSurfaceChanged(layer, size); +} + +-(void) settingsChanged { + // +} + +@end diff --git a/src/ios/CMakeLists.txt b/src/ios/CMakeLists.txt new file mode 100644 index 0000000000..98b2585a5b --- /dev/null +++ b/src/ios/CMakeLists.txt @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +enable_language(Swift OBJCXX) +add_executable(eden-ios + AppUI-Bridging-Header.h + AppUI.swift + AppUIGameInformation.h + AppUIGameInformation.mm + AppUIObjC.h + AppUIObjC.mm + Config.h + Config.mm + EmulationSession.h + EmulationSession.mm + EmulationWindow.h + EmulationWindow.mm + VMA.cpp + + PomeloApp.swift + ContentView.swift +) + +set(MACOSX_BUNDLE_GUI_IDENTIFIER "dev.eden-emu.eden") +set(MACOSX_BUNDLE_BUNDLE_NAME "Eden") +set(MACOSX_BUNDLE_INFO_STRING "Eden: A high-performance Nintendo Switch emulator") + +# TODO(crueter): Copyright, and versioning + +# Keep bundle identifier as-is, for compatibility sake +set_target_properties(eden-ios PROPERTIES + XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/AppUI-Bridging-Header.h" + XCODE_ATTRIBUTE_SWIFT_OBJC_INTERFACE_HEADER_NAME "eden-ios-Swift.h" + XCODE_ATTRIBUTE_DERIVED_FILE_DIR "${CMAKE_CURRENT_BINARY_DIR}") + +target_link_libraries(eden-ios PRIVATE common core input_common frontend_common video_core sirit::sirit) +target_link_libraries(eden-ios PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) +target_link_libraries(eden-ios PRIVATE SDL2::SDL2 glad stb::headers) +create_target_directory_groups(eden-ios) + +# FIXME(crueter): This should /all/ be in a module of some kind! + +# Xcode will automatically generate the Assets.car and icns file for us. +set(_dist "${CMAKE_SOURCE_DIR}/dist") +if (CMAKE_GENERATOR MATCHES "Xcode") + set(_icons "${_dist}/eden.icon") + + set_target_properties(eden-ios PROPERTIES + XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME eden + MACOSX_BUNDLE_ICON_FILE eden + # Also force xcode to manage signing for us. + XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED ON + XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED ON + XCODE_ATTRIBUTE_CODE_SIGN_STYLE Automatic) +# Otherwise, we'll use our own. +else() + set(_icons "${_dist}/eden.icns" "${_dist}/Assets.car") +endif() + +set_source_files_properties(${_icons} PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) +target_sources(eden-ios PRIVATE ${_icons}) + +set_target_properties(eden-ios PROPERTIES MACOSX_BUNDLE TRUE) + +set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib") +find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) +message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.") + +set_source_files_properties(${MOLTENVK_LIBRARY} PROPERTIES + MACOSX_PACKAGE_LOCATION Frameworks + XCODE_FILE_ATTRIBUTES "CodeSignOnCopy") +target_sources(eden-ios PRIVATE ${MOLTENVK_LIBRARY}) diff --git a/src/ios/Config.h b/src/ios/Config.h new file mode 100644 index 0000000000..4adc23fe44 --- /dev/null +++ b/src/ios/Config.h @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include "common/common_types.h" +#include "common/settings_setting.h" +#include "common/settings_enums.h" + +namespace IOSSettings { + struct Values { + Settings::Linkage linkage; + Settings::Setting touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay}; + }; + + extern Values values; + +} // namespace IOSSettings diff --git a/src/ios/Config.mm b/src/ios/Config.mm new file mode 100644 index 0000000000..5b063d79f9 --- /dev/null +++ b/src/ios/Config.mm @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + + +#include "Config.h" + +namespace IOSSettings { + +Values values; + +} // namespace IOSSettings diff --git a/src/ios/ContentView.swift b/src/ios/ContentView.swift new file mode 100644 index 0000000000..877af33fcb --- /dev/null +++ b/src/ios/ContentView.swift @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Pomelo, Stossy11 +// SPDX-License-Identifier: GPL-3.0-or-later + +import SwiftUI +//import AppUI + +struct ContentView: View { +// @State var core = Core(games: [], root: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]) + var body: some View { +// HomeView(core: core).onAppear() { +// Air.play(AnyView( +// Text("Select Game").font(.system(size: 100)) +// )) +// // rest of death +// } + } +} diff --git a/src/ios/EmulationSession.h b/src/ios/EmulationSession.h new file mode 100644 index 0000000000..c6bce5e4dd --- /dev/null +++ b/src/ios/EmulationSession.h @@ -0,0 +1,103 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#import +#import + +#if __has_include() +#import +#else +#import +#endif +#import "EmulationWindow.h" + +#include "common/detached_tasks.h" +#include "core/core.h" +#include "core/file_sys/registered_cache.h" +#include "core/hle/service/acc/profile_manager.h" +#include "core/perf_stats.h" +#include "frontend_common/content_manager.h" +#include "video_core/rasterizer_interface.h" + +class EmulationSession final { +public: + explicit EmulationSession(); + ~EmulationSession() = default; + + static EmulationSession& GetInstance(); + const Core::System& System() const; + Core::System& System(); + FileSys::ManualContentProvider* GetContentProvider(); + InputCommon::InputSubsystem& GetInputSubsystem(); + + const EmulationWindow& Window() const; + EmulationWindow& Window(); + CAMetalLayer* NativeWindow() const; + void SetNativeWindow(CAMetalLayer* native_window, CGSize size); + void SurfaceChanged(); + + void InitializeGpuDriver(); + + bool IsRunning() const; + bool IsPaused() const; + void PauseEmulation(); + void UnPauseEmulation(); + void HaltEmulation(); + void RunEmulation(); + void ShutdownEmulation(); + + const Core::PerfStatsResults& PerfStats(); + void ConfigureFilesystemProvider(const std::string& filepath); + void InitializeSystem(bool reload); + void SetAppletId(int applet_id); + Core::SystemResultStatus InitializeEmulation(const std::string& filepath, + const std::size_t program_index, + const bool frontend_initiated); + Core::SystemResultStatus BootOS(); + + static void OnEmulationStarted(); + static u64 GetProgramId(std::string programId); + bool IsInitialized() { return is_initialized; }; + + bool IsHandheldOnly(); + void SetDeviceType([[maybe_unused]] int index, int type); + void OnGamepadConnectEvent([[maybe_unused]] int index); + void OnGamepadDisconnectEvent([[maybe_unused]] int index); +private: + static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max); + static void OnEmulationStopped(Core::SystemResultStatus result); + static void ChangeProgram(std::size_t program_index); + +private: + // Window management + std::unique_ptr m_window; + CAMetalLayer* m_native_window{}; + + // Core emulation + Core::System m_system; + InputCommon::InputSubsystem m_input_subsystem; + Common::DetachedTasks m_detached_tasks; + Core::PerfStatsResults m_perf_stats{}; + std::shared_ptr m_vfs; + Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized}; + std::atomic m_is_running = false; + std::atomic m_is_paused = false; + std::unique_ptr m_manual_provider; + int m_applet_id{1}; + + // GPU driver parameters + std::shared_ptr m_vulkan_library; + + // Synchronization + std::condition_variable_any m_cv; + mutable std::mutex m_mutex; + bool is_initialized = false; + CGSize m_size; + + // Program index for next boot + std::atomic m_next_program_index = -1; +}; diff --git a/src/ios/EmulationSession.mm b/src/ios/EmulationSession.mm new file mode 100644 index 0000000000..9861e0a544 --- /dev/null +++ b/src/ios/EmulationSession.mm @@ -0,0 +1,474 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#import "EmulationSession.h" + +#include + +#include +#include +#include +#include +#include + +#include "common/fs/fs.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/savedata_factory.h" +#include "core/loader/nro.h" +#include "frontend_common/content_manager.h" + +#include "common/detached_tasks.h" +#include "common/dynamic_library.h" +#include "common/fs/path_util.h" +#include "common/logging.h" +#include "common/scm_rev.h" +#include "common/scope_exit.h" +#include "common/settings.h" +#include "common/string_util.h" +#include "core/core.h" +#include "core/cpu_manager.h" +#include "core/crypto/key_manager.h" +#include "core/file_sys/card_image.h" +#include "core/file_sys/content_archive.h" +#include "core/file_sys/fs_filesystem.h" +#include "core/file_sys/submission_package.h" +#include "core/file_sys/vfs/vfs.h" +#include "core/file_sys/vfs/vfs_real.h" +#include "core/frontend/applets/cabinet.h" +#include "core/frontend/applets/controller.h" +#include "core/frontend/applets/error.h" +#include "core/frontend/applets/general.h" +#include "core/frontend/applets/mii_edit.h" +#include "core/frontend/applets/profile_select.h" +#include "core/frontend/applets/software_keyboard.h" +#include "core/frontend/applets/web_browser.h" +#include "core/hle/service/am/applet_manager.h" +#include "core/hle/service/am/frontend/applets.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/loader/loader.h" +#include "frontend_common/config.h" +#include "hid_core/frontend/emulated_controller.h" +#include "hid_core/hid_core.h" +#include "hid_core/hid_types.h" +#include "video_core/renderer_base.h" +#include "video_core/renderer_vulkan/renderer_vulkan.h" +#include "video_core/vulkan_common/vulkan_instance.h" +#include "video_core/vulkan_common/vulkan_surface.h" + +#define jconst [[maybe_unused]] const auto +#define jauto [[maybe_unused]] auto + +static EmulationSession s_instance; + +EmulationSession::EmulationSession() { + m_vfs = std::make_shared(); +} + +EmulationSession& EmulationSession::GetInstance() { + return s_instance; +} + +const Core::System& EmulationSession::System() const { + return m_system; +} + +Core::System& EmulationSession::System() { + return m_system; +} + +FileSys::ManualContentProvider* EmulationSession::GetContentProvider() { + return m_manual_provider.get(); +} + +InputCommon::InputSubsystem& EmulationSession::GetInputSubsystem() { + return m_input_subsystem; +} + +const EmulationWindow& EmulationSession::Window() const { + return *m_window; +} + +EmulationWindow& EmulationSession::Window() { + return *m_window; +} + +CAMetalLayer* EmulationSession::NativeWindow() const { + return m_native_window; +} + +void EmulationSession::SetNativeWindow(CAMetalLayer* native_window, CGSize size) { + m_native_window = native_window; + m_size = size; +} + +void EmulationSession::InitializeGpuDriver() { + m_vulkan_library = std::make_shared(dlopen("@executable_path/Frameworks/MoltenVK", RTLD_NOW)); +} + +bool EmulationSession::IsRunning() const { + return m_is_running; +} + +bool EmulationSession::IsPaused() const { + return m_is_running && m_is_paused; +} + +const Core::PerfStatsResults& EmulationSession::PerfStats() { + m_perf_stats = m_system.GetAndResetPerfStats(); + return m_perf_stats; +} + +void EmulationSession::SurfaceChanged() { + if (!IsRunning()) { + return; + } + m_window->OnSurfaceChanged(m_native_window, m_size); +} + +void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath) { + const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::OpenMode::Read); + if (!file) { + return; + } + + auto loader = Loader::GetLoader(m_system, file); + if (!loader) { + return; + } + + const auto file_type = loader->GetFileType(); + if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) { + return; + } + + u64 program_id = 0; + const auto res2 = loader->ReadProgramId(program_id); + if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) { + m_manual_provider->AddEntry(FileSys::TitleType::Application, + FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()), + program_id, file); + } else if (res2 == Loader::ResultStatus::Success && + (file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) { + const auto nsp = file_type == Loader::FileType::NSP + ? std::make_shared(file) + : FileSys::XCI{file}.GetSecurePartitionNSP(); + for (const auto& title : nsp->GetNCAs()) { + for (const auto& entry : title.second) { + m_manual_provider->AddEntry(entry.first.first, entry.first.second, title.first, + entry.second->GetBaseFile()); + } + } + } +} + +void EmulationSession::InitializeSystem(bool reload) { + if (!reload) { + SDL_SetMainReady(); + + // Initialize logging system + Common::Log::Initialize(); + Common::Log::SetColorConsoleBackendEnabled(true); + Common::Log::Start(); + } + + // Initialize filesystem. + m_system.SetFilesystem(m_vfs); + m_system.GetUserChannel().clear(); + m_manual_provider = std::make_unique(); + m_system.SetContentProvider(std::make_unique()); + m_system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual, + m_manual_provider.get()); + m_system.GetFileSystemController().CreateFactories(*m_vfs); + + is_initialized = true; +} + +void EmulationSession::SetAppletId(int applet_id) { + m_applet_id = applet_id; + m_system.GetFrontendAppletHolder().SetCurrentAppletId( + static_cast(m_applet_id)); +} + +Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath, + const std::size_t program_index, + const bool frontend_initiated) { + std::scoped_lock lock(m_mutex); + + // Create the render window. + m_window = std::make_unique(&m_input_subsystem, m_native_window, m_size, m_vulkan_library); + + // Initialize system. + m_system.SetShuttingDown(false); + m_system.ApplySettings(); + Settings::LogSettings(); + m_system.HIDCore().ReloadInputDevices(); + m_system.SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet{}); + + // Initialize filesystem. + ConfigureFilesystemProvider(filepath); + + // Load the ROM. + Service::AM::FrontendAppletParameters params{ + .applet_id = static_cast(m_applet_id), + .launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated + : Service::AM::LaunchType::ApplicationInitiated, + .program_index = static_cast(program_index), + }; + m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params); + if (m_load_result != Core::SystemResultStatus::Success) { + return m_load_result; + } + + // Complete initialization. + m_system.GPU().Start(); + m_system.GetCpuManager().OnGpuReady(); + m_system.RegisterExitCallback([&] { HaltEmulation(); }); + + if (Settings::values.use_disk_shader_cache.GetValue()) { + m_system.Renderer().ReadRasterizer()->LoadDiskResources( + m_system.GetApplicationProcessProgramID(), std::stop_token{}, + [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); + } + + // Register an ExecuteProgram callback such that Core can execute a sub-program + m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) { + m_next_program_index = program_index_; + EmulationSession::GetInstance().HaltEmulation(); + ChangeProgram(m_next_program_index); + }); + + OnEmulationStarted(); + return Core::SystemResultStatus::Success; +} + + +Core::SystemResultStatus EmulationSession::BootOS() { + std::scoped_lock lock(m_mutex); + + // Create the render window. + m_window = std::make_unique(&m_input_subsystem, m_native_window, m_size, m_vulkan_library); + + // Initialize system. + m_system.SetShuttingDown(false); + m_system.ApplySettings(); + Settings::LogSettings(); + m_system.HIDCore().ReloadInputDevices(); + m_system.SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet{}); + + constexpr u64 QLaunchId = static_cast(Service::AM::AppletProgramId::QLaunch); + auto bis_system = m_system.GetFileSystemController().GetSystemNANDContents(); + + auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program); + + m_system.GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::QLaunch); + + const auto filename = qlaunch_applet_nca->GetFullPath(); + + auto params = Service::AM::FrontendAppletParameters { + .program_id = QLaunchId, + .applet_id = Service::AM::AppletId::QLaunch, + .applet_type = Service::AM::AppletType::LibraryApplet + }; + + m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filename, params); + + if (m_load_result != Core::SystemResultStatus::Success) { + return m_load_result; + } + + // Complete initialization. + m_system.GPU().Start(); + m_system.GetCpuManager().OnGpuReady(); + m_system.RegisterExitCallback([&] { HaltEmulation(); }); + + if (Settings::values.use_disk_shader_cache.GetValue()) { + m_system.Renderer().ReadRasterizer()->LoadDiskResources( + m_system.GetApplicationProcessProgramID(), std::stop_token{}, + [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); + } + + // Register an ExecuteProgram callback such that Core can execute a sub-program + m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) { + m_next_program_index = program_index_; + EmulationSession::GetInstance().HaltEmulation(); + }); + + OnEmulationStarted(); + return Core::SystemResultStatus::Success; +} + +void EmulationSession::ShutdownEmulation() { + std::scoped_lock lock(m_mutex); + + if (m_next_program_index != -1) { + ChangeProgram(m_next_program_index); + m_next_program_index = -1; + } + + m_is_running = false; + + // Unload user input. + m_system.HIDCore().UnloadInputDevices(); + + // Enable all controllers + m_system.HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); + + // Shutdown the main emulated process + if (m_load_result == Core::SystemResultStatus::Success) { + m_system.DetachDebugger(); + m_system.ShutdownMainProcess(); + m_detached_tasks.WaitForAllTasks(); + m_load_result = Core::SystemResultStatus::ErrorNotInitialized; + m_window.reset(); + OnEmulationStopped(Core::SystemResultStatus::Success); + return; + } + + // Tear down the render window. + m_window.reset(); +} + +void EmulationSession::PauseEmulation() { + std::scoped_lock lock(m_mutex); + m_system.Pause(); + m_is_paused = true; +} + +void EmulationSession::UnPauseEmulation() { + std::scoped_lock lock(m_mutex); + m_system.Run(); + m_is_paused = false; +} + +void EmulationSession::HaltEmulation() { + std::scoped_lock lock(m_mutex); + m_is_running = false; + m_cv.notify_one(); +} + +void EmulationSession::RunEmulation() { + { + std::scoped_lock lock(m_mutex); + m_is_running = true; + } + + // Load the disk shader cache. + if (Settings::values.use_disk_shader_cache.GetValue()) { + LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); + m_system.Renderer().ReadRasterizer()->LoadDiskResources( + m_system.GetApplicationProcessProgramID(), std::stop_token{}, LoadDiskCacheProgress); + LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0); + } + + void(m_system.Run()); + + if (m_system.DebuggerEnabled()) { + m_system.InitializeDebugger(); + } + + while (true) { + { + [[maybe_unused]] std::unique_lock lock(m_mutex); + if (m_cv.wait_for(lock, std::chrono::milliseconds(800), + [&]() { return !m_is_running; })) { + // Emulation halted. + break; + } + } + } + + // Reset current applet ID. + m_applet_id = static_cast(Service::AM::AppletId::Application); +} + +void EmulationSession::LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, + int max) { + +} + +void EmulationSession::OnEmulationStarted() { + +} + +void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) { + +} + +void EmulationSession::ChangeProgram(std::size_t program_index) { + LOG_INFO(Frontend, "Trying To Switch Program"); + // Halt current emulation session + EmulationSession::GetInstance().HaltEmulation(); + // Save the current state if necessary + + // Shutdown the current emulation session cleanly + // Update the program index + EmulationSession::GetInstance().m_next_program_index = program_index; + + // Initialize the new program + // Start the new emulation session + EmulationSession::GetInstance().RunEmulation(); +} + +u64 EmulationSession::GetProgramId(std::string programId) { + try { + return std::stoull(programId); + } catch (...) { + return 0; + } +} + +bool EmulationSession::IsHandheldOnly() { + jconst npad_style_set = m_system.HIDCore().GetSupportedStyleTag(); + + if (npad_style_set.fullkey == 1) { + return false; + } + + if (npad_style_set.handheld == 0) { + return false; + } + + return !Settings::IsDockedMode(); +} + +void EmulationSession::SetDeviceType([[maybe_unused]] int index, int type) { + jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); + controller->SetNpadStyleIndex(static_cast(type)); +} + +void EmulationSession::OnGamepadConnectEvent([[maybe_unused]] int index) { + jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); + + // Ensure that player1 is configured correctly and handheld disconnected + if (controller->GetNpadIdType() == Core::HID::NpadIdType::Player1) { + jauto handheld = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + + if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) { + handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey); + controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Fullkey); + handheld->Disconnect(); + } + } + + // Ensure that handheld is configured correctly and player 1 disconnected + if (controller->GetNpadIdType() == Core::HID::NpadIdType::Handheld) { + jauto player1 = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + + if (controller->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::Handheld) { + player1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld); + controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld); + player1->Disconnect(); + } + } + + if (!controller->IsConnected()) { + controller->Connect(); + } +} + +void EmulationSession::OnGamepadDisconnectEvent([[maybe_unused]] int index) { + jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); + controller->Disconnect(); +} diff --git a/src/ios/EmulationWindow.h b/src/ios/EmulationWindow.h new file mode 100644 index 0000000000..8d285ab33e --- /dev/null +++ b/src/ios/EmulationWindow.h @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#if __has_include() +#import +#else +#import +#endif +#import +#import +#import +#import + +#include +#include + +#include "core/frontend/emu_window.h" +#include "core/frontend/graphics_context.h" +#include "input_common/main.h" + +class GraphicsContext_Apple final : public Core::Frontend::GraphicsContext { +public: + explicit GraphicsContext_Apple(std::shared_ptr driver_library) + : m_driver_library{driver_library} {} + + ~GraphicsContext_Apple() = default; + + std::shared_ptr GetDriverLibrary() override { + return m_driver_library; + } + +private: + std::shared_ptr m_driver_library; +}; + +NS_ASSUME_NONNULL_BEGIN + +class EmulationWindow final : public Core::Frontend::EmuWindow { +public: + EmulationWindow(InputCommon::InputSubsystem* input_subsystem, CAMetalLayer* surface, CGSize size, + std::shared_ptr driver_library); + + ~EmulationWindow() = default; + + void OnSurfaceChanged(CAMetalLayer* surface, CGSize size); + void OrientationChanged(UIInterfaceOrientation orientation); + void OnFrameDisplayed() override; + + void OnTouchPressed(int id, float x, float y); + void OnTouchMoved(int id, float x, float y); + void OnTouchReleased(int id); + + void OnGamepadButtonEvent(int player_index, int button_id, bool pressed); + void OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y); + void OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z); + + std::unique_ptr CreateSharedContext() const override { + return {std::make_unique(m_driver_library)}; + } + + + bool HasFirstFrame() const { + return m_first_frame; + } + + bool IsShown() const override { + return true; + }; + +private: + float m_window_width{}; + float m_window_height{}; + CGSize m_size; + bool is_portrait = true; + + InputCommon::InputSubsystem* m_input_subsystem{}; + std::shared_ptr m_driver_library; + + bool m_first_frame = false; +}; + +NS_ASSUME_NONNULL_END diff --git a/src/ios/EmulationWindow.mm b/src/ios/EmulationWindow.mm new file mode 100644 index 0000000000..b917929c2c --- /dev/null +++ b/src/ios/EmulationWindow.mm @@ -0,0 +1,82 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Jarrod Norwell +// SPDX-License-Identifier: GPL-2.0-or-later + +#import "EmulationWindow.h" +#import "EmulationSession.h" + +#include + +#include "common/logging.h" +#include "input_common/drivers/touch_screen.h" +#include "input_common/drivers/virtual_amiibo.h" +#include "input_common/drivers/virtual_gamepad.h" +#include "input_common/main.h" + +void EmulationWindow::OnSurfaceChanged(CAMetalLayer* surface, CGSize size) { + m_size = size; + + m_window_width = size.width; + m_window_height = size.height; + + // Ensures that we emulate with the correct aspect ratio. + // UpdateCurrentFramebufferLayout(m_window_width, m_window_height); + + window_info.render_surface = (__bridge void *)surface; + window_info.render_surface_scale = [[UIScreen mainScreen] nativeScale]; +} + +void EmulationWindow::OrientationChanged(UIInterfaceOrientation orientation) { + is_portrait = orientation == UIInterfaceOrientationPortrait; +} + +void EmulationWindow::OnTouchPressed(int id, float x, float y) { + const auto [touch_x, touch_y] = MapToTouchScreen(x, y); + EmulationSession::GetInstance().GetInputSubsystem().GetTouchScreen()->TouchPressed(touch_x, + touch_y, id); +} + +void EmulationWindow::OnTouchMoved(int id, float x, float y) { + const auto [touch_x, touch_y] = MapToTouchScreen(x, y); + EmulationSession::GetInstance().GetInputSubsystem().GetTouchScreen()->TouchMoved(touch_x, + touch_y, id); +} + +void EmulationWindow::OnTouchReleased(int id) { + EmulationSession::GetInstance().GetInputSubsystem().GetTouchScreen()->TouchReleased(id); +} + +void EmulationWindow::OnGamepadButtonEvent(int player_index, int button_id, bool pressed) { + m_input_subsystem->GetVirtualGamepad()->SetButtonState(player_index, button_id, pressed); +} + +void EmulationWindow::OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y) { + m_input_subsystem->GetVirtualGamepad()->SetStickPosition(player_index, stick_id, x, y); +} + +void EmulationWindow::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z) { + m_input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z); +} + +void EmulationWindow::OnFrameDisplayed() { + if (!m_first_frame) { + m_first_frame = true; + } +} + +EmulationWindow::EmulationWindow(InputCommon::InputSubsystem* input_subsystem, CAMetalLayer* surface, CGSize size, std::shared_ptr driver_library) + : m_window_width{}, m_window_height{}, m_size{size}, is_portrait{true}, m_input_subsystem{input_subsystem}, m_driver_library{driver_library}, m_first_frame{false} { + LOG_INFO(Frontend, "initializing"); + + if (!surface) { + LOG_CRITICAL(Frontend, "surface is nullptr"); + return; + } + + OnSurfaceChanged(surface, m_size); + window_info.render_surface_scale = [[UIScreen mainScreen] nativeScale]; + window_info.type = Core::Frontend::WindowSystemType::Cocoa; + + m_input_subsystem->Initialize(); +} diff --git a/src/ios/PomeloApp.swift b/src/ios/PomeloApp.swift new file mode 100644 index 0000000000..4a48939f54 --- /dev/null +++ b/src/ios/PomeloApp.swift @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: Copyright 2024 Pomelo, Stossy11 +// SPDX-License-Identifier: GPL-3.0-or-later + +import SwiftUI + +infix operator --: LogicalDisjunctionPrecedence + +func --(lhs: Bool, rhs: Bool) -> Bool { + return lhs || rhs +} + +@main +struct PomeloApp: App { + var body: some Scene { + WindowGroup { ContentView() } + } +} diff --git a/src/ios/VMA.cpp b/src/ios/VMA.cpp new file mode 100644 index 0000000000..7e2ea49c28 --- /dev/null +++ b/src/ios/VMA.cpp @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#define VMA_IMPLEMENTATION +#include "video_core/vulkan_common/vma.h" diff --git a/src/qt_common/CMakeLists.txt b/src/qt_common/CMakeLists.txt index 904b03d288..399fbe67a0 100644 --- a/src/qt_common/CMakeLists.txt +++ b/src/qt_common/CMakeLists.txt @@ -50,7 +50,6 @@ if (USE_DISCORD_PRESENCE) if (YUZU_USE_BUNDLED_OPENSSL) target_link_libraries(qt_common PUBLIC OpenSSL::SSL OpenSSL::Crypto) - target_compile_definitions(qt_common PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT) endif() target_compile_definitions(qt_common PUBLIC USE_DISCORD_PRESENCE) diff --git a/src/qt_common/discord/discord_impl.cpp b/src/qt_common/discord/discord_impl.cpp index 37b24cdd57..c1cb5319dc 100644 --- a/src/qt_common/discord/discord_impl.cpp +++ b/src/qt_common/discord/discord_impl.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include "common/httplib.h" #include #include diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 362b068656..3a572eb875 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -369,7 +369,6 @@ else() else() target_compile_options(video_core PRIVATE $<$:-Werror=conversion>) endif() - target_compile_options(video_core PRIVATE $<$:-Wno-sign-conversion>) # xbyak diff --git a/src/video_core/vulkan_common/vma.h b/src/video_core/vulkan_common/vma.h index e022b2bf7d..514ff4501c 100644 --- a/src/video_core/vulkan_common/vma.h +++ b/src/video_core/vulkan_common/vma.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -13,9 +13,14 @@ #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4189 ) +#elif defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" #endif #include "vk_mem_alloc.h" #ifdef _MSC_VER #pragma warning( pop ) +#elif defined(__clang__) +#pragma clang diagnostic pop #endif diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt index 0dedad16f7..a3acdfcf0f 100644 --- a/src/web_service/CMakeLists.txt +++ b/src/web_service/CMakeLists.txt @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp index 60b11fff5a..1e71406989 100644 --- a/src/web_service/web_backend.cpp +++ b/src/web_service/web_backend.cpp @@ -16,7 +16,7 @@ #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #endif -#include +#include "common/httplib.h" #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 1ed1fdff2a..d94487ec79 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -369,7 +369,7 @@ if (APPLE) if (CMAKE_GENERATOR MATCHES "Xcode") set(_icons "${_dist}/eden.icon") - set_target_properties(eden PROPERTIES + set_target_properties(yuzu PROPERTIES XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME eden MACOSX_BUNDLE_ICON_FILE eden # Also force xcode to manage signing for us. diff --git a/tools/cpm/package/fetch.sh b/tools/cpm/package/fetch.sh index b03a824146..54ea8c64c4 100755 --- a/tools/cpm/package/fetch.sh +++ b/tools/cpm/package/fetch.sh @@ -83,7 +83,7 @@ ci_package() { android-aarch64 android-x86_64 \ solaris-amd64 freebsd-amd64 openbsd-amd64 \ linux-amd64 linux-aarch64 \ - macos-universal; do + macos-universal ios-aarch64; do echo "-- * platform $platform" case $DISABLED in diff --git a/tools/cpm/package/util/interactive.sh b/tools/cpm/package/util/interactive.sh index 99db77e20d..07087e5d10 100755 --- a/tools/cpm/package/util/interactive.sh +++ b/tools/cpm/package/util/interactive.sh @@ -151,7 +151,7 @@ mingw-amd64 mingw-arm64 android-aarch64 android-x86_64 solaris-amd64 freebsd-amd64 openbsd-amd64 linux-amd64 linux-aarch64 -macos-universal" +macos-universal ios-aarch64" DISABLED_PLATFORMS="$reply" fi