Compare commits

..

25 Commits

Author SHA1 Message Date
lizzie
8e80396ee0 fix 2025-11-06 22:49:49 +00:00
CamilleLaVey
672011f302 Added Maintenance5 to 9 headers 2025-11-06 18:03:30 -04:00
CamilleLaVey
bb1d1e484d Added Maintenance EXT's for better driver compatibility 2025-11-06 17:47:05 -04:00
CamilleLaVey
5a03ef7fba Disabling BGR5 emulation format on 8 Elite stock drivers 2025-11-06 17:37:16 -04:00
CamilleLaVey
88555a17be Forcing hardware handling for decode formats on Android 2025-11-06 15:55:10 -04:00
CamilleLaVey
9600f99b1a Maintance for older driver statements and new handling on QCOM drivers 2025-11-06 14:39:39 -04:00
CamilleLaVey
7bed3bb947 Disabling VK_KHR_shader_float_controls on QCOM and ARM 2025-11-06 12:10:33 -04:00
CamilleLaVey
380112bcb4 Added QCOM helper for driver detections 2025-11-06 09:59:01 -04:00
CamilleLaVey
2685f832e5 Profilling FP16 to FTZ usage in QCOM drivers 2025-11-06 09:22:57 -04:00
CamilleLaVey
d65afcda81 revert Added FTZ optimizations and adjust pipeline float control handling for Qualcomm drivers
revert Added FTZ optimizations and adjust pipeline float control handling for Qualcomm drivers
2025-11-06 13:34:05 +01:00
CamilleLaVey
1cb88492a8 revert [vk] Add back VIDS but disable on EDS0 (#2957)
revert [vk] Add back VIDS but disable on EDS0 (#2957)

Should fix regressions from removing it while also fixing black screen with it enabled

Co-authored-by: JPikachu <jpikachu.eden@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2957
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: JPikachu <jpikachu@eden-emu.dev>
Co-committed-by: JPikachu <jpikachu@eden-emu.dev>
2025-11-06 03:12:38 +01:00
CamilleLaVey
1b06fa6658 revert [vk] disable VK_EXT_vertex_input_dynamic_state again (#2954)
revert [vk] disable VK_EXT_vertex_input_dynamic_state again (#2954)

DO NOT REMOVE THIS! EVER! EVEN IF MESA CLAIMS TO FIX IT!

A few months ago, Aleksandr and I did extensive testing on a 6600 and
6950XT and were able to confirm that VK_EXT_vertex_input_dynamic_state
is indeed broken beyond repair on RADV. MESA has claimed multiple times
to fix this, yet it's never budged once (average GitLab users)

Most games literally do not work without this. DO. NOT. REMOVE.
EVER!

Signed-off-by: crueter <crueter@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2954
Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
2025-11-06 03:12:11 +01:00
CamilleLaVey
af1b610fbb revert [vk] Clean up Extended Dynamic State code (#2947)
revert [vk] Clean up Extended Dynamic State code (#2947)

- Removed forced dynamic state 0 logic
- Restore and update the removal of broken states on certain drivers
- Inside 'vk_rasterizer.cpp' make 'UpdateDynamicStates' only check device
   capabilities directly instead of relying on user settings.
- Add a 'Force Unsupported Extensions' toggle that:
   "Bypasses all driver workarounds and safety checks.
     May cause crashes, graphical glitches, or instability.
     Only enable for testing purposes."

Cleans up EDS logic and adds new 'Force Unsupported Extensions' toggle,
Fixes vertex explosions in 'Pokemon: Legends ZA' when EDS is set to 0.

Co-authored-by: JPikachu <jpikachu.eden@gmail.com>
Co-authored-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2947
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: JPikachu <jpikachu@eden-emu.dev>
Co-committed-by: JPikachu <jpikachu@eden-emu.dev>
2025-11-06 03:11:31 +01:00
CamilleLaVey
9a266e60b6 Merge branch 'floatopsfixes1' of https://git.eden-emu.dev/eden-emu/eden into floatopsfixes1 2025-11-05 22:10:11 -04:00
CamilleLaVey
1fc9c3f6ff Added FTZ optimizations and adjust pipeline float control handling for Qualcomm drivers 2025-11-05 22:10:02 -04:00
CamilleLaVey
a0f08704f1 revert 612da00d1b
revert [vk] Clean up Extended Dynamic State code (#2947)

- Removed forced dynamic state 0 logic
- Restore and update the removal of broken states on certain drivers
- Inside 'vk_rasterizer.cpp' make 'UpdateDynamicStates' only check device
   capabilities directly instead of relying on user settings.
- Add a 'Force Unsupported Extensions' toggle that:
   "Bypasses all driver workarounds and safety checks.
     May cause crashes, graphical glitches, or instability.
     Only enable for testing purposes."

Cleans up EDS logic and adds new 'Force Unsupported Extensions' toggle,
Fixes vertex explosions in 'Pokemon: Legends ZA' when EDS is set to 0.

Co-authored-by: JPikachu <jpikachu.eden@gmail.com>
Co-authored-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2947
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: JPikachu <jpikachu@eden-emu.dev>
Co-committed-by: JPikachu <jpikachu@eden-emu.dev>
2025-11-06 02:58:21 +01:00
CamilleLaVey
c6c3edc95c revert 1c4dae066b
revert [vk] Add back VIDS but disable on EDS0 (#2957)

Should fix regressions from removing it while also fixing black screen with it enabled

Co-authored-by: JPikachu <jpikachu.eden@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2957
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: JPikachu <jpikachu@eden-emu.dev>
Co-committed-by: JPikachu <jpikachu@eden-emu.dev>
2025-11-06 02:57:49 +01:00
CamilleLaVey
76c5de0443 revert 9406438d51
revert [vk] disable VK_EXT_vertex_input_dynamic_state again (#2954)

DO NOT REMOVE THIS! EVER! EVEN IF MESA CLAIMS TO FIX IT!

A few months ago, Aleksandr and I did extensive testing on a 6600 and
6950XT and were able to confirm that VK_EXT_vertex_input_dynamic_state
is indeed broken beyond repair on RADV. MESA has claimed multiple times
to fix this, yet it's never budged once (average GitLab users)

Most games literally do not work without this. DO. NOT. REMOVE.
EVER!

Signed-off-by: crueter <crueter@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2954
Reviewed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
2025-11-06 02:57:19 +01:00
CamilleLaVey
9ffead7e7a Re-enabling VK_KHR_shader_float_controls for further testing 2025-11-05 19:23:37 -04:00
CamilleLaVey
22bb942947 Merge branch 'floatopsfixes1' of https://git.eden-emu.dev/eden-emu/eden into floatopsfixes1 2025-11-05 16:50:26 -04:00
CamilleLaVey
3af7aafc25 Add suitability for Robustness2 2025-11-05 16:50:18 -04:00
CamilleLaVey
3a8677597f Fix parenthesis/ build error 2025-11-05 21:25:42 +01:00
CamilleLaVey
16ae756da3 Improve float operations for ARM and Qualcomm drivers and other extensions workarounds 2025-11-05 21:25:42 +01:00
CamilleLaVey
004264d2a6 Fix parenthesis/ build error 2025-11-05 14:33:15 -04:00
CamilleLaVey
4bbde3e5ec Improve float operations for ARM and Qualcomm drivers and other extensions workarounds 2025-11-05 13:59:47 -04:00
217 changed files with 11547 additions and 9451 deletions

View File

@@ -1,19 +0,0 @@
name: tx-src
on:
push:
branches: [ master ]
jobs:
sources:
runs-on: source
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Push New Sources
run: |
export PATH=/usr/lib/qt6/bin:$PATH
./tools/translations/qt-source.sh
tx-cli push -s

View File

@@ -1,61 +0,0 @@
name: tx-pull
on:
# monday, wednesday, saturday at 2pm
schedule:
cron:
- '0 14 * * 1,3,6'
jobs:
tx-update:
runs-on: source
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get New Translations
run: tx-cli pull -t -f
- name: Push branch
run: |
git config --local user.name "Eden CI"
git config --local user.email "ci@eden-emu.dev"
git config --local user.signingkey "D57652791BB25D2A"
git config --local push.autoSetupRemote true
git remote set-url origin ci:eden-emu/eden.git
TIMESTAMP=$(date +"%s")
echo "TIMESTAMP=$TIMESTAMP" >> "$GITHUB_ENV"
git switch -c update-translations-$TIMESTAMP
git add dist src/android/app/src/main/res
git commit -sS -m "[dist, android] Update translations from Transifex"
git push
- name: Create PR
run: |
DATE=$(date +"%b %d")
TITLE="[dist, android] Update translations from Transifex for $DATE"
BODY="Automatic translation update for $DATE"
BASE=master
HEAD=update-translations-$TIMESTAMP
cat << EOF > data.json
{
"base": "$BASE",
"body": "$BODY",
"head": "$HEAD",
"title": "$TITLE"
}
EOF
curl -X 'POST' \
'https://git.eden-emu.dev/api/v1/repos/eden-emu/eden/pulls' \
-H 'accept: application/json' \
-H 'Authorization: Bearer ${{ secrets.CI_FJ_TOKEN }}' \
-H 'Content-Type: application/json' \
-d "@data.json" --fail

View File

@@ -13,19 +13,12 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
set(PLATFORM_OPENBSD ON)
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "NetBSD")
set(PLATFORM_NETBSD ON)
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "DragonFly")
set(PLATFORM_DRAGONFLYBSD ON)
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Haiku")
set(PLATFORM_HAIKU ON)
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(PLATFORM_LINUX ON)
endif()
# dumb heuristic to detect msys2
if (CMAKE_COMMAND MATCHES "msys64")
set(PLATFORM_MSYS ON)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CXX_CLANG ON)
if (MSVC)
@@ -90,89 +83,6 @@ if (PLATFORM_NETBSD)
set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/pkg/lib/ffmpeg7/pkgconfig")
endif()
# MSYS2 utilities
if (PLATFORM_MSYS)
include(FixMsysPaths)
# really, really dumb heuristic to detect what environment we are in
macro(system var)
if (CMAKE_COMMAND MATCHES ${var})
set(MSYSTEM ${var})
endif()
endmacro()
system(mingw64)
system(clang64)
system(clangarm64)
system(ucrt64)
if (NOT DEFINED MSYSTEM)
set(MSYSTEM msys2)
endif()
# we (generally) want to prioritize environment-specific binaries if possible
# some, like autoconf, are not present on environments besides msys2 though
set(CMAKE_PROGRAM_PATH C:/msys64/${MSYSTEM}/bin C:/msys64/usr/bin)
set(ENV{PKG_CONFIG_PATH} C:/msys64/${MSYSTEM}/lib/pkgconfig)
endif()
# static stuff
option(YUZU_STATIC_BUILD "Use static libraries and executables if available" OFF)
if (YUZU_STATIC_BUILD)
# lol
set(Boost_USE_STATIC_LIBS ON)
set(BUILD_SHARED_LIBS OFF)
## find .a libs first (static, usually)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
## some libraries define a Library::Name_static alternative ##
set(YUZU_STATIC_SUFFIX _static)
## some libraries use CMAKE_IMPORT_LIBRARY_SUFFIX e.g. Harfbuzz ##
set(CMAKE_IMPORT_LIBRARY_SUFFIX ".a")
if (MINGW)
# simple hook to reject dynamic libs
function(find_library var)
# also skip previously-found libraries cuz... yaknow
if (${var})
return()
endif()
_find_library(${var} ${ARGN})
if (${var})
get_filename_component(lib_name "${${var}}" NAME)
if (lib_name MATCHES "dll\\.a$")
unset(${var} CACHE)
set(${var} "${var}-NOTFOUND" CACHE INTERNAL "" FORCE)
endif()
endif()
endfunction()
# msys2 quazip does not build a static lib
set(QuaZip-Qt6_FORCE_BUNDLED ON)
set(YUZU_USE_BUNDLED_FFMPEG ON)
set(YUZU_USE_BUNDLED_SDL2 ON)
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF)
elseif(APPLE)
# these libs do not properly provide static libs/let you do it with cmake
set(YUZU_USE_CPM ON)
# IMPORTED_IMPLIB not set for imported target
# TODO(crueter): wtf
set(YUZU_USE_BUNDLED_FFMPEG ON)
set(YUZU_USE_EXTERNAL_SDL2 ON)
set(fmt_FORCE_BUNDLED ON)
set(SPIRV-Tools_FORCE_BUNDLED ON)
set(SPIRV-Headers_FORCE_BUNDLED ON)
set(zstd_FORCE_BUNDLED ON)
endif()
endif()
# Detect current compilation architecture and create standard definitions
# =======================================================================
@@ -279,9 +189,9 @@ if (CXX_CLANG_CL)
$<$<COMPILE_LANGUAGE:C,CXX>:/EHsc> # thanks microsoft
)
# REQUIRED CPU features IN Windows-amd64
if (ARCHITECTURE_x86_64)
add_compile_options(
# Required CPU features for amd64
$<$<COMPILE_LANGUAGE:C,CXX>:-msse4.1>
$<$<COMPILE_LANGUAGE:C,CXX>:-mcx16>
)
@@ -299,17 +209,20 @@ if (MSVC AND NOT CXX_CLANG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /WX-")
endif()
if (PLATFORM_FREEBSD OR PLATFORM_DRAGONFLYBSD)
if (PLATFORM_FREEBSD)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/local/lib")
endif()
# Set bundled sdl2/qt as dependent options.
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
cmake_dependent_option(ENABLE_SDL2 "Enable the SDL2 frontend" ON "NOT ANDROID" OFF)
# 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 "ENABLE_SDL2;NOT MSVC" OFF)
cmake_dependent_option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}" "ENABLE_SDL2" OFF)
if (ENABLE_SDL2)
# TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system
cmake_dependent_option(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF)
option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}")
endif()
# qt stuff
option(ENABLE_QT "Enable the Qt frontend" ON)
@@ -330,14 +243,10 @@ option(YUZU_USE_CPM "Use CPM to fetch system dependencies (fmt, boost, etc) if n
# 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)
cmake_dependent_option(YUZU_USE_EXTERNAL_FFMPEG "Build FFmpeg from source" "${PLATFORM_SUN}" "NOT WIN32 AND NOT ANDROID" OFF)
# sirit
set(BUNDLED_SIRIT_DEFAULT OFF)
if ((MSVC AND NOT (CMAKE_BUILD_TYPE MATCHES "Debug|RelWithDebInfo") OR ANDROID))
set(BUNDLED_SIRIT_DEFAULT ON)
endif()
option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${BUNDLED_SIRIT_DEFAULT})
option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${EXT_DEFAULT})
# Re-allow on FreeBSD once its on mainline ports
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR PLATFORM_LINUX OR APPLE" OFF)
@@ -374,17 +283,6 @@ if(USE_CCACHE)
else()
message(FATAL_ERROR "USE_CCACHE enabled, but no executable found at: ${CCACHE_PATH}")
endif()
# Follow SCCache recommendations:
# <https://github.com/mozilla/sccache/blob/main/README.md?plain=1#L144>
if(WIN32)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
endif()
endif()
endif()
# TODO(crueter): CI this?
@@ -456,6 +354,13 @@ if (ANDROID)
set(CMAKE_POLICY_VERSION_MINIMUM 3.5) # Workaround for Oboe
endif()
# We need to downgrade debug info (/Zi -> /Z7) to use an older but more cacheable format
# See https://github.com/nanoant/CMakePCHCompiler/issues/21
if(WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
endif()
# Default to a Release build
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
@@ -676,12 +581,11 @@ else()
find_package(stb MODULE)
find_package(Opus 1.3 MODULE REQUIRED)
find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED MODULE)
# wow
find_package(Boost 1.57.0 CONFIG REQUIRED OPTIONAL_COMPONENTS headers context system fiber filesystem)
find_package(Boost 1.57.0 CONFIG REQUIRED OPTIONAL_COMPONENTS headers context system fiber)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR ANDROID)
find_package(gamemode 1.7 MODULE)
@@ -729,15 +633,15 @@ if (APPLE)
# Umbrella framework for everything GUI-related
find_library(COCOA_LIBRARY Cocoa)
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
# find_library(ICONV_LIBRARY iconv REQUIRED)
# list(APPEND PLATFORM_LIBRARIES ${ICONV_LIBRARY})
find_library(ICONV_LIBRARY iconv REQUIRED)
list(APPEND PLATFORM_LIBRARIES ${ICONV_LIBRARY})
elseif (WIN32)
# Target Windows 10
add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00)
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} winmm iphlpapi ws2_32 wlanapi)
set(PLATFORM_LIBRARIES winmm ws2_32 iphlpapi)
if (MINGW)
# PSAPI is the Process Status API
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version crypt32 rpcrt4 gdi32 wldap32 mswsock)
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)
endif()
elseif (PLATFORM_HAIKU)
# Haiku is so special :)
@@ -750,8 +654,6 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU|SunOS)$")
set(PLATFORM_LIBRARIES rt)
endif()
message(STATUS "Platform Libraries: ${PLATFORM_LIBRARIES}")
add_subdirectory(externals)
# pass targets from externals

View File

@@ -542,11 +542,10 @@ function(AddCIPackage)
PACKAGE
EXTENSION
MIN_VERSION
DISABLED_PLATFORMS
)
set(multiValueArgs DISABLED_PLATFORMS)
cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "" ${ARGN})
if(NOT DEFINED PKG_ARGS_VERSION)
message(FATAL_ERROR "[CPMUtil] VERSION is required")

View File

@@ -1,6 +1,3 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,10 +10,6 @@ find_package_handle_standard_args(Opus
VERSION_VAR OPUS_VERSION
)
if (PLATFORM_MSYS)
FixMsysPath(PkgConfig::OPUS)
endif()
if (Opus_FOUND AND NOT TARGET Opus::opus)
add_library(Opus::opus ALIAS PkgConfig::OPUS)
endif()

View File

@@ -1,6 +1,3 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,10 +10,6 @@ find_package_handle_standard_args(SPIRV-Tools
VERSION_VAR SPIRV-Tools_VERSION
)
if (PLATFORM_MSYS)
FixMsysPath(PkgConfig::SPIRV-Tools)
endif()
if (SPIRV-Tools_FOUND AND NOT TARGET SPIRV-Tools::SPIRV-Tools)
if (TARGET SPIRV-Tools)
add_library(SPIRV-Tools::SPIRV-Tools ALIAS SPIRV-Tools)

View File

@@ -1,6 +1,3 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
@@ -14,10 +11,6 @@ find_package_handle_standard_args(enet
VERSION_VAR ENET_VERSION
)
if (PLATFORM_MSYS)
FixMsysPath(PkgConfig::ENET)
endif()
if (enet_FOUND AND NOT TARGET enet::enet)
add_library(enet::enet ALIAS PkgConfig::ENET)
endif()

View File

@@ -1,6 +1,3 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
#
# SPDX-License-Identifier: GPL-3.0-or-later
@@ -14,10 +11,6 @@ find_package_handle_standard_args(libusb
VERSION_VAR LIBUSB_VERSION
)
if (PLATFORM_MSYS)
FixMsysPath(PkgConfig::LIBUSB)
endif()
if (libusb_FOUND AND NOT TARGET libusb::usb)
add_library(libusb::usb ALIAS PkgConfig::LIBUSB)
endif()

View File

@@ -1,6 +1,3 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,11 +9,6 @@ if (lz4_CONSIDERED_CONFIGS)
else()
find_package(PkgConfig QUIET)
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
if (PLATFORM_MSYS)
FixMsysPath(PkgConfig::LZ4)
endif()
find_package_handle_standard_args(lz4
REQUIRED_VARS LZ4_LINK_LIBRARIES
VERSION_VAR LZ4_VERSION

View File

@@ -6,34 +6,22 @@
include(FindPackageHandleStandardArgs)
find_package(zstd QUIET CONFIG)
if (zstd_CONSIDERED_CONFIGS)
find_package_handle_standard_args(zstd CONFIG_MODE)
else()
find_package(PkgConfig QUIET)
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
find_package_handle_standard_args(zstd
REQUIRED_VARS ZSTD_LINK_LIBRARIES
VERSION_VAR ZSTD_VERSION
)
endif()
find_package(PkgConfig QUIET)
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
find_package_handle_standard_args(zstd
REQUIRED_VARS ZSTD_LINK_LIBRARIES
VERSION_VAR ZSTD_VERSION
)
if (zstd_FOUND AND NOT TARGET zstd::zstd)
if (TARGET zstd::libzstd_shared AND NOT YUZU_STATIC_BUILD)
if (TARGET zstd::libzstd_shared)
add_library(zstd::zstd ALIAS zstd::libzstd_shared)
add_library(zstd::libzstd ALIAS zstd::libzstd_shared)
elseif (TARGET zstd::libzstd_static)
add_library(zstd::zstd ALIAS zstd::libzstd_static)
add_library(zstd::libzstd ALIAS zstd::libzstd_static)
else()
add_library(zstd::zstd ALIAS PkgConfig::ZSTD)
endif()
endif()
get_target_property(ZSTD_TARGET zstd::zstd ALIASED_TARGET)
if (NOT TARGET zstd::libzstd)
if (ZSTD_TARGET)
add_library(zstd::libzstd ALIAS ${ZSTD_TARGET})
else()
add_library(zstd::libzstd ALIAS zstd::zstd)
add_library(zstd::libzstd ALIAS PkgConfig::ZSTD)
endif()
endif()

View File

@@ -1,21 +0,0 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
function(FixMsysPath target)
get_target_property(include_dir ${target} INTERFACE_INCLUDE_DIRECTORIES)
if (NOT (include_dir MATCHES "^/"))
return()
endif()
set(root_default $ENV{MSYS2_LOCATION})
if (root_default STREQUAL "")
set(root_default "C:/msys64")
endif()
set(MSYS_ROOT_PATH ${root_default} CACHE STRING "Location of the MSYS2 root")
set(include_dir "C:/msys64${include_dir}")
set_target_properties(${target} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${include_dir})
endfunction()

View File

@@ -0,0 +1,58 @@
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
set(SDL2_PATH ${MINGW_PREFIX})
set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
# Specify the cross compiler
set(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}clang)
set(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}clang++)
set(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres)
set(CMAKE_C_COMPILER_AR ${MINGW_TOOL_PREFIX}ar)
set(CMAKE_CXX_COMPILER_AR ${MINGW_TOOL_PREFIX}ar)
set(CMAKE_C_COMPILER_RANLIB ${MINGW_TOOL_PREFIX}ranlib)
set(CMAKE_CXX_COMPILER_RANLIB ${MINGW_TOOL_PREFIX}ranlib)
# Mingw tools
set(STRIP ${MINGW_TOOL_PREFIX}strip)
set(WINDRES ${MINGW_TOOL_PREFIX}windres)
set(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config)
# ccache wrapper
option(USE_CCACHE "Use ccache for compilation" OFF)
if(USE_CCACHE)
find_program(CCACHE ccache)
if(CCACHE)
message(STATUS "Using ccache found in PATH")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
else(CCACHE)
message(WARNING "USE_CCACHE enabled, but no ccache found")
endif(CCACHE)
endif(USE_CCACHE)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Echo modified cmake vars to screen for debugging purposes
if(NOT DEFINED ENV{MINGW_DEBUG_INFO})
message("")
message("Custom cmake vars: (blank = system default)")
message("-----------------------------------------")
message("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
message("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
message("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
message("* WINDRES : ${WINDRES}")
message("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}")
message("* STRIP : ${STRIP}")
message("* USE_CCACHE : ${USE_CCACHE}")
message("")
# So that the debug info only appears once
set(ENV{MINGW_DEBUG_INFO} SHOWN)
endif()

View File

@@ -0,0 +1,57 @@
# SPDX-FileCopyrightText: 2018 tech4me <guiwanglong@gmail.com>
# SPDX-License-Identifier: GPL-2.0-or-later
set(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
# Actually a hack, w/o this will cause some strange errors
set(CMAKE_HOST_WIN32 TRUE)
set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
set(SDL2_PATH ${MINGW_PREFIX})
set(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
# Specify the cross compiler
set(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++)
set(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres)
# Mingw tools
set(STRIP ${MINGW_TOOL_PREFIX}strip)
set(WINDRES ${MINGW_TOOL_PREFIX}windres)
set(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config)
# ccache wrapper
option(USE_CCACHE "Use ccache for compilation" OFF)
if(USE_CCACHE)
find_program(CCACHE ccache)
if(CCACHE)
message(STATUS "Using ccache found in PATH")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
else(CCACHE)
message(WARNING "USE_CCACHE enabled, but no ccache found")
endif(CCACHE)
endif(USE_CCACHE)
# Search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Echo modified cmake vars to screen for debugging purposes
if(NOT DEFINED ENV{MINGW_DEBUG_INFO})
message("")
message("Custom cmake vars: (blank = system default)")
message("-----------------------------------------")
message("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
message("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
message("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
message("* WINDRES : ${WINDRES}")
message("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}")
message("* STRIP : ${STRIP}")
message("* USE_CCACHE : ${USE_CCACHE}")
message("")
# So that the debug info only appears once
set(ENV{MINGW_DEBUG_INFO} SHOWN)
endif()

View File

@@ -20,7 +20,7 @@
"hash": "4fb7f6fde92762305aad8754d7643cd918dd1f3f67e104e9ab385b18c73178d72a17321354eb203b790b6702f2cf6d725a5d6e2dfbc63b1e35f9eb59fb42ece9",
"git_version": "1.89.0",
"version": "1.57",
"find_args": "CONFIG OPTIONAL_COMPONENTS headers context system fiber filesystem",
"find_args": "CONFIG",
"patches": [
"0001-clang-cl.patch",
"0002-use-marmasm.patch",

0
dist/dev.eden_emu.eden.desktop vendored Executable file → Normal file
View File

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 13 KiB

BIN
dist/eden.icns vendored

Binary file not shown.

BIN
dist/eden.ico vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 403 KiB

83
dist/eden_named.svg vendored

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@@ -1,9 +0,0 @@
# Icon variations
These icons are licensed under GPLv3. Please see the [script for generating icons](../../tools/README.md) and appropriatedly redirect for seasonal icons.
- `base_named.svg` - Named variant.
- `base_small.svg`: Variant used for tiny icons (16x16, 64x64, etc).
- `base.svg`: Variant without branding/naming.
Try to keep the icons simple. And preferably automatically be able to be generated (to reduce maintanaince burden). Additionally keep the files small (use `svgo` and `optipng`) to not clutter the git.

View File

@@ -1,80 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="512"
height="512"
fill="none"
viewBox="0 0 512 512"
version="1.1"
id="svg7"
sodipodi:docname="base_small.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs7">
<linearGradient
id="linearGradient10"
inkscape:collect="always">
<stop
style="stop-color:#f977d9;stop-opacity:1;"
offset="0"
id="stop10" />
<stop
style="stop-color:#a655d5;stop-opacity:1;"
offset="0.54051435"
id="stop13" />
<stop
style="stop-color:#984fd5;stop-opacity:1;"
offset="0.5714342"
id="stop12" />
<stop
style="stop-color:#8c4ad4;stop-opacity:1;"
offset="0.59666741"
id="stop14" />
<stop
style="stop-color:#3928d2;stop-opacity:1;"
offset="1"
id="stop11" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10"
id="linearGradient11"
x1="264.17508"
y1="28.385544"
x2="264.17508"
y2="488.65109"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.97815818,0,0,0.97880258,4.570042,5.8799159)" />
</defs>
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.88388348"
inkscape:cx="153.30075"
inkscape:cy="243.24473"
inkscape:window-width="1600"
inkscape:window-height="849"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg7"
showguides="false" />
<path
id="path9"
style="fill:url(#linearGradient11);fill-opacity:1;stroke:none;stroke-width:13.3314;stroke-opacity:1;paint-order:stroke fill markers"
d="M 262.97461 33.6875 A 218.44267 225.23091 0 0 0 138.83789 73.589844 L 141.13867 72.265625 L 161.2207 65.195312 L 181.01953 61.517578 L 204.35352 64.205078 L 228.96094 76.650391 L 265.80078 115 L 283 99.400391 L 304.59961 85.800781 L 331 76.400391 L 360.59961 69.599609 L 379.95508 69.208984 A 218.44267 225.23091 0 0 0 262.97461 33.6875 z M 380.07617 69.291016 L 350.19922 77.800781 L 329.19922 89.199219 L 307.40039 108 L 288.80078 129.80078 L 287.40039 135 L 302.40039 129.59961 L 319 127.80078 L 348.80078 131.80078 L 370.19922 141.40039 L 393 161.40039 L 399.59961 171.59961 L 374.80078 160.80078 L 338.40039 150.80078 L 309.19922 150 L 288.80078 154.40039 L 293.19922 155.19922 L 319.19922 168.80078 L 338 187.19922 L 350.80078 224 L 349.19922 260 L 326 222.80078 L 302.80078 194 L 277.59961 172.40039 L 269.19922 187.59961 L 256.80078 281.59961 L 258 364 L 278.40039 452.80078 L 297.19531 481.36914 A 218.44267 225.23091 0 0 0 481.41797 258.91797 A 218.44267 225.23091 0 0 0 380.07617 69.291016 z M 133.07422 77.839844 A 218.44267 225.23091 0 0 0 44.533203 258.91797 A 218.44267 225.23091 0 0 0 257.04102 484.06641 L 247.3457 458.62891 L 237.87109 418.18359 L 233.0625 380.42383 L 230.375 354.9668 L 229.95117 321.30859 L 232.35547 291.32812 L 237.44727 254.98242 L 254.55859 191.9082 L 261.62891 172.5332 L 255.54883 174.08984 L 240.98242 180.87695 L 229.59961 190.19922 L 210.59961 208.19922 L 197.40039 229.40039 L 186.40039 252.59961 L 173.40039 269 L 171.40039 253.19922 L 173.59961 229.40039 L 183 202.40039 L 199.40039 178 L 221.04102 153.44141 L 209.02148 155.70508 L 177.05859 162.77539 L 148.06836 171.40234 L 119.92578 183 L 120.63281 180.16992 L 129.82422 165.88672 L 151.17969 147.50195 L 172.95898 135.48242 L 190.07031 129.54102 L 209.02148 127.98633 L 227.6875 128.69336 L 247.76953 128.41016 L 246.49805 125.1582 L 226.69922 105.92383 L 219.62695 97.439453 L 221.4668 90.085938 L 206.75781 94.044922 L 195.86914 95.458984 L 179.46289 88.671875 L 156.12891 81.458984 L 133.07422 77.839844 z " />
<path
style="fill:#1b1b1b;fill-opacity:0.12492698;stroke:none;stroke-width:13.374;stroke-opacity:0.415999;paint-order:stroke fill markers"
d="m 259.36665,490.16617 39.03323,-6.96642 -20,-30.4 -20.4,-88.8 -1.2,-82.4 12.4,-94 8.4,-15.2 25.2,21.6 23.2,28.8 23.2,37.2 1.6,-36 -12.8,-36.8 -18.8,-18.4 -26,-13.6 -4.4,-0.8 20.4,-4.4 29.2,0.8 36.4,10 24.8,10.8 -6.6,-10.2 -22.8,-20 -21.4,-9.6 -29.8,-4 -16.6,1.8 -15,5.4 1.4,-5.2 18.6,-21.8 21.8,-18.800003 21,-11.4 30.2,-8.6 -19.8,0.4 -29.6,6.8 -26.4,9.4 -21.6,13.6 -17.2,15.600003 -36.83882,-38.349628 -24.60732,-12.445079 -23.33452,-2.687006 -19.79899,3.676955 -20.08184,7.071068 -9.33381,5.374012 24.32448,3.818376 23.33452,7.212489 16.40488,6.788226 10.88944,-1.414214 14.70782,-3.959798 -1.83847,7.353911 7.07106,8.485288 19.79899,19.2333 1.2728,3.25269 -20.08184,0.28284 -18.66762,-0.7071 -18.95046,1.55563 -17.11198,5.9397 -21.77889,12.02081 -21.35462,18.38478 -9.19239,14.28356 -0.70711,2.82843 28.14285,-11.59656 28.99138,-8.6267 31.96122,-7.07107 12.02082,-2.26274 -21.64158,24.55783 -16.4,24.4 -9.4,27 -2.2,23.8 2,15.8 13,-16.4 11,-23.2 13.2,-21.2 19,-18 11.38199,-9.32209 14.5664,-6.78822 6.08112,-1.55564 -7.07107,19.37473 -17.11198,63.07393 -5.09117,36.34528 -2.40416,29.98133 0.42426,33.65828 2.68701,25.45585 4.80832,37.7595 9.47523,40.44651 z"
id="path8-4" />
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -821,6 +821,31 @@ QTabBar QToolButton::left-arrow:disabled {
image: url(:/qss_icons/rc/left_arrow_disabled.png);
}
QDockWidget {
background: #31363b;
border: 1px solid #403F3F;
titlebar-close-icon: url(:/qss_icons/rc/close.png);
titlebar-normal-icon: url(:/qss_icons/rc/undock.png);
}
QDockWidget::close-button,
QDockWidget::float-button {
border: 1px solid transparent;
border-radius: 2px;
background: transparent;
}
QDockWidget::close-button:hover,
QDockWidget::float-button:hover {
background: rgba(255, 255, 255, 10);
}
QDockWidget::close-button:pressed,
QDockWidget::float-button:pressed {
padding: 1px -1px -1px 1px;
background: rgba(255, 255, 255, 10);
}
QTreeView,
QListView {
border: 1px solid #54575B;

View File

@@ -1685,6 +1685,54 @@ QTabBar QToolButton::right-arrow:disabled {
image: url(":/qss_icons/rc/arrow_right_disabled.png");
}
/* QDockWiget -------------------------------------------------------------
--------------------------------------------------------------------------- */
QDockWidget {
outline: 1px solid #32414B;
background-color: #19232D;
border: 1px solid #32414B;
border-radius: 4px;
titlebar-close-icon: url(":/qss_icons/rc/window_close.png");
titlebar-normal-icon: url(":/qss_icons/rc/window_undock.png");
}
QDockWidget::title {
/* Better size for title bar */
padding: 6px;
spacing: 4px;
border: none;
background-color: #32414B;
}
QDockWidget::close-button {
background-color: #32414B;
border-radius: 4px;
border: none;
}
QDockWidget::close-button:hover {
image: url(":/qss_icons/rc/window_close_focus.png");
}
QDockWidget::close-button:pressed {
image: url(":/qss_icons/rc/window_close_pressed.png");
}
QDockWidget::float-button {
background-color: #32414B;
border-radius: 4px;
border: none;
}
QDockWidget::float-button:hover {
image: url(":/qss_icons/rc/window_undock_focus.png");
}
QDockWidget::float-button:pressed {
image: url(":/qss_icons/rc/window_undock_pressed.png");
}
/* QTreeView QListView QTableView -----------------------------------------
https://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qtreeview

BIN
dist/yuzu.bmp vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

BIN
dist/yuzu.icns vendored

Binary file not shown.

View File

@@ -30,13 +30,6 @@ macOS is largely untested. Expect crashes, significant Vulkan issues, and other
## Solaris
Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability.
Run the usual update + install of essential toolings: `sudo pkg update && sudo pkg install git cmake`.
- **gcc**: `sudo pkg install developer/gcc-14`.
- **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`.
Qt Widgets appears to be broken. For now, add `-DENABLE_QT=OFF` to your configure command. In the meantime, a Qt Quick frontend is in the works--check back later!
This is needed for some dependencies that call cc directly (tz):
@@ -81,7 +74,7 @@ Still will not run flawlessly until `mesa-24` is available. Modify CMakeCache.tx
After configuration, you may need to modify `externals/ffmpeg/CMakeFiles/ffmpeg-build/build.make` to use `-j$(nproc)` instead of just `-j`.
`-lc++-experimental` doesn't exist in OpenBSD but the LLVM driver still tries to link against it, to solve just symlink `ln -s /usr/lib/libc++.a /usr/lib/libc++experimental.a`. Builds are currently not working due to lack of `std::jthread` and such, either compile libc++ manually or wait for ports to catch up.
`-lc++-experimental` doesn't exist in OpenBSD but the LLVM driver still tries to link against it, to solve just symlink `ln -s /usr/lib/libc++.a /usr/lib/libc++experimental.a`.
If clang has errors, try using `g++-11`.
@@ -114,21 +107,6 @@ cmake --build build -- -j`nproc`
cmake --install build
```
# DragonFlyBSD
If `libstdc++.so.6` is not found (`GLIBCXX_3.4.30`) then attempt:
```sh
rm /usr/local/lib/gcc11/libstdc++.so.6
ln -s /usr/local/lib/gcc14/libstdc++.so /usr/local/lib/gcc11/libstdc++.so.6
```
This may have unforeseen consequences of which we don't need to worry about for now.
Default `g++` (and the libstdc++) is too outdated - so install `gcc14` and redirect CMake to the new compiler toolchain `-DCMAKE_CXX_COMPILER=gcc14 -DCMAKE_C_COMPILER=g++14`.
There is also `llvm18` and use `-DCMAKE_CXX_COMPILER=clang++18 -DCMAKE_C_COMPILER=clang18` (note the `18` suffix at the end). NOTE: It doesn't have an updated libcxx so `<span>` will be missing, either build it manually or use gcc.
If build hangs, use `hammer2 bulkfree`.
## MSYS2
`qt6-static` isn't supported yet.
@@ -191,9 +169,3 @@ find ./*/ -name "*.dll" | while read -r dll; do deps "$dll"; done
DirectX 12 is not available - simply copy and paste a random DLL and name it `d3d12.dll`.
Install [Qt6 compatibility libraries](github.com/ANightly/qt6windows7) specifically Qt 6.9.5.
## RedoxOS
The package install may randomly hang at times, in which case it has to be restarted. ALWAYS do a `sudo pkg update` or the chances of it hanging will be close to 90%. If "multiple" installs fail at once, try installing 1 by 1 the packages.
When CMake invokes certain file syscalls - it may sometimes cause crashes or corruptions on the (kernel?) address space - so reboot the system if there is a "hang" in CMake.

View File

@@ -8,8 +8,6 @@ But for new developers you may find that following these guidelines will make ev
Simply put, types/classes are named as `PascalCase`, same for methods and functions like `AddElement`. Variables are named `like_this_snake_case` and constants are `IN_SCREAMING_CASE`.
Except for Qt MOC where `functionName` is preferred.
Template typenames prefer short names like `T`, `I`, `U`, if a longer name is required either `Iterator` or `perform_action` are fine as well.
Macros must always be in `SCREAMING_CASE`. Do not use short letter macros as systems like Solaris will conflict with them; a good rule of thumb is >5 characters per macro - i.e `THIS_MACRO_IS_GOOD`, `AND_ALSO_THIS_ONE`.

View File

@@ -196,6 +196,7 @@ apk add g++ git cmake make mbedtls-dev mbedtls-static mesa-dev qt6-qtbase-dev qt
`mbedtls-static` has to be specified otherwise `libeverest.a` and `libp256m.a` will fail to be found.
</details>
<details>
<summary>Void Linux</summary>
@@ -235,7 +236,7 @@ brew install molten-vk vulkan-loader
<details>
<summary>FreeBSD</summary>
As root run: `pkg install devel/cmake devel/sdl20 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/jwt-cpp devel/unordered-dense mbedtls3 vulkan-headers quazip-qt6`
As root run: `pkg install devel/cmake devel/sdl20 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/jwt-cpp devel/unordered-dense`
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
@@ -260,23 +261,18 @@ pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gm
[Caveats](./Caveats.md#openbsd).
</details>
<details>
<summary>DragonFlyBSD</summary>
```sh
pkg install gcc14 git cmake unzip nasm autoconf bash pkgconf ffmpeg glslang gmake jq nlohmann-json enet spirv-tools sdl2 vulkan-utility-libraries vulkan-headers catch2 libfmt openssl liblz4 boost-libs cpp-httplib qt6-base quazip-qt6 unordered-dense libva-vdpau-driver libva-utils libva-intel-driver
```
[Caveats](./Caveats.md#dragonflybsd).
</details>
<details>
<summary>Solaris / OpenIndiana</summary>
```sh
sudo pkg install qt6 boost glslang libzip library/lz4 libusb-1 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt
```
Always consult [the OpenIndiana package list](https://pkg.openindiana.org/hipster/en/index.shtml) to cross-verify availability.
Run the usual update + install of essential toolings: `sudo pkg update && sudo pkg install git cmake`.
- **gcc**: `sudo pkg install developer/gcc-14`.
- **clang**: Version 20 is broken, use `sudo pkg install developer/clang-19`.
Then install the libraries: `sudo pkg install qt6 boost glslang libzip library/lz4 libusb-1 nlohmann-json openssl opus sdl2 zlib compress/zstd unzip pkg-config nasm autoconf mesa library/libdrm header-drm developer/fmt`.
[Caveats](./Caveats.md#solaris).
@@ -320,16 +316,16 @@ pkgman install git cmake patch libfmt_devel nlohmann_json lz4_devel opus_devel b
[Caveats](./Caveats.md#haikuos).
</details>
<details>
<summary>RedoxOS</summary>
TODO: Fix syscall crashes (heavy IO stalls and hangup due to net mutexes?)
```sh
sudo pkg update
sudo pkg install git cmake ffmpeg6 sdl2 zlib llvm18
sudo pkg update && sudo pkg install git cmake
sudo pkg install ffmpeg6 sdl2 zlib llvm18
```
[Caveats](./Caveats.md#redoxos).
</details>
## All Done

View File

@@ -160,6 +160,13 @@ if (YUZU_USE_BUNDLED_SIRIT)
AddJsonPackage(sirit-ci)
else()
AddJsonPackage(sirit)
# Change to old-but-more-cacheable debug info on Windows
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
get_target_property(sirit_opts sirit COMPILE_OPTIONS)
list(FILTER sirit_opts EXCLUDE REGEX "/Zi")
list(APPEND sirit_opts "/Z7")
set_target_properties(sirit PROPERTIES COMPILE_OPTIONS "${sirit_opts}")
endif()
if(MSVC AND CXX_CLANG)
target_compile_options(siritobj PRIVATE -Wno-error=unused-command-line-argument)
endif()

View File

@@ -25,26 +25,18 @@ if (UNIX AND NOT ANDROID)
if (NOT APPLE)
# In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so
if(PLATFORM_SUN)
find_library(LIBDRM_LIB libdrm PATHS /usr/lib/64 /usr/lib/amd64 /usr/lib)
if(LIBDRM_LIB)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
X11
"${LIBDRM_LIB}")
message(STATUS "Found libdrm at: ${LIBDRM_LIB}")
else()
message(WARNING "libdrm not found, disabling libdrm support")
list(APPEND FFmpeg_HWACCEL_FLAGS
--disable-libdrm)
endif()
list(APPEND FFmpeg_HWACCEL_LIBRARIES
X11
"/usr/lib/xorg/amd64/libdrm.so")
else()
pkg_check_modules(LIBDRM libdrm REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-libdrm)
endif()
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-libdrm)
endif()
if(LIBVA_FOUND)
@@ -97,7 +89,7 @@ if (UNIX AND NOT ANDROID)
endif(CUDA_FOUND)
endif()
if (VDPAU_FOUND AND NOT APPLE)
if (VDPAU_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-vdpau
--enable-hwaccel=h264_vdpau
@@ -255,19 +247,11 @@ else()
SYSTEM_THREADS)
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
# BSD make or Solaris make don't support ffmpeg make-j8
if (PLATFORM_LINUX OR ANDROID OR APPLE OR WIN32 OR PLATFORM_FREEBSD)
set(FFmpeg_MAKE_ARGS -j${SYSTEM_THREADS})
else()
set(FFmpeg_MAKE_ARGS "")
endif()
add_custom_command(
OUTPUT
${FFmpeg_BUILD_LIBRARIES}
COMMAND
make ${FFmpeg_MAKE_ARGS}
make -j${SYSTEM_THREADS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)

View File

@@ -15,7 +15,8 @@
"disabled_platforms": [
"freebsd-amd64",
"solaris-amd64",
"openbsd-amd64"
"openbsd-amd64",
"macos-universal"
]
}
}

View File

@@ -5,7 +5,7 @@
"git_host": "git.crueter.xyz",
"artifact": "%VERSION%.tar.gz",
"tag": "%VERSION%",
"hash": "dc37a189a44ce8b5c988ca550582431a6c7eadfd3c6e709bee6277116ee803e714333e85c9e6cbb5c69346a14d6f2cc7ed96e8aa09cc5fb8a89f945059651db6",
"version": "121125"
"hash": "87abb2aeca716d5d77b05317086dbc2f8acfc2f3f76ce4778345ee3df19973e6cd8ecbf16cfab5ad94c9636a6c44fd3588f9aadd3cba89403cfd56c8bec645c5",
"version": "091025"
}
}

View File

@@ -9,15 +9,11 @@ pkgs.mkShellNoCC {
# libraries
openssl boost fmt nlohmann_json lz4 zlib zstd
enet libopus vulkan-headers vulkan-utility-libraries
spirv-tools spirv-headers vulkan-loader unzip mbedtls
glslang python3 httplib cpp-jwt ffmpeg-headless
libusb1 cubeb
# eden
qt6.qtbase qt6.qtmultimedia qt6.qtwayland qt6.qttools
qt6.qtwebengine qt6.qt5compat
# eden-cli
SDL2
# optional components
discord-rpc gamemode
spirv-tools spirv-headers simpleini vulkan-memory-allocator
vulkan-loader unzip mbedtls glslang python3 httplib
cpp-jwt ffmpeg-headless libusb1 cubeb
qt6.full # eden
SDL2 # eden-cli
discord-rpc gamemode # optional components
];
}

View File

@@ -35,6 +35,7 @@ if (MSVC AND NOT CXX_CLANG)
# /W4 - Level 4 warnings
# /MP - Multi-threaded compilation
# /Zi - Output debugging information
# /Zm - Specifies the precompiled header memory allocation limit
# /Zo - Enhanced debug info for optimized builds
# /permissive- - Enables stricter C++ standards conformance checks
@@ -97,6 +98,11 @@ if (MSVC AND NOT CXX_CLANG)
)
endif()
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
endif()
if (ARCHITECTURE_x86_64)
add_compile_options(/QIntel-jcc-erratum)
endif()
@@ -121,7 +127,7 @@ else()
-Werror=unused
-Wno-attributes
$<$<COMPILE_LANGUAGE:CXX>:-Wno-invalid-offsetof>
-Wno-invalid-offsetof
-Wno-unused-parameter
-Wno-missing-field-initializers
)
@@ -170,27 +176,13 @@ else()
add_compile_definitions(_FILE_OFFSET_BITS=64)
endif()
if (YUZU_STATIC_BUILD)
add_compile_definitions(QT_STATICPLUGIN)
# macos doesn't even let you make static executables... wtf?
if (NOT APPLE)
add_compile_options(-static)
if (YUZU_STATIC_BUILD)
# yuzu-cmd requires us to explicitly link libpthread, libgcc, and libstdc++ as static
# At a guess, it's probably because Qt handles the Qt executable for us, whereas this does not
add_link_options(-static -lpthread)
add_link_options(-static-libgcc -static-libstdc++)
endif()
endif()
endif()
if (MINGW)
add_compile_definitions(MINGW_HAS_SECURE_API)
add_compile_options("-msse4.1")
# Only windows has this requirement, thanks windows
if (WIN32 AND ARCHITECTURE_x86_64)
add_compile_options("-msse4.1")
if (MINGW_STATIC_BUILD)
add_compile_definitions(QT_STATICPLUGIN)
add_compile_options("-static")
endif()
endif()

View File

@@ -16,15 +16,11 @@ import java.io.FileOutputStream
import java.security.KeyStore
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
import android.content.res.Configuration
import android.os.LocaleList
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.DocumentsTree
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
import org.yuzu.yuzu_emu.utils.Log
import org.yuzu.yuzu_emu.utils.PowerStateUpdater
import java.util.Locale
fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
@@ -77,38 +73,5 @@ class YuzuApplication : Application() {
val appContext: Context
get() = application.applicationContext
private val LANGUAGE_CODES = arrayOf(
"system", "en", "es", "fr", "de", "it", "pt", "pt-BR", "ru", "ja", "ko",
"zh-CN", "zh-TW", "pl", "cs", "nb", "hu", "uk", "vi", "id", "ar", "ckb", "fa", "he", "sr"
)
fun applyLanguage(context: Context): Context {
val languageIndex = IntSetting.APP_LANGUAGE.getInt()
val langCode = if (languageIndex in LANGUAGE_CODES.indices) {
LANGUAGE_CODES[languageIndex]
} else {
"system"
}
if (langCode == "system") {
return context
}
val locale = when {
langCode.contains("-") -> {
val parts = langCode.split("-")
Locale.Builder().setLanguage(parts[0]).setRegion(parts[1]).build()
}
else -> Locale.Builder().setLanguage(langCode).build()
}
Locale.setDefault(locale)
val config = Configuration(context.resources.configuration)
config.setLocales(LocaleList(locale))
return context.createConfigurationContext(config)
}
}
}

View File

@@ -86,10 +86,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
private var foregroundService: Intent? = null
override fun attachBaseContext(base: Context) {
super.attachBaseContext(YuzuApplication.applyLanguage(base))
}
override fun onCreate(savedInstanceState: Bundle?) {
Log.gameLaunched = true
ThemeHelper.setTheme(this)

View File

@@ -29,6 +29,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
SYNC_MEMORY_OPERATIONS("sync_memory_operations"),
BUFFER_REORDER_DISABLE("disable_buffer_reorder"),
RENDERER_DEBUG("debug"),
RENDERER_FORCE_UNSUPPORTED_EXTENSIONS("force_unsupported_extensions"),
RENDERER_PROVOKING_VERTEX("provoking_vertex"),
RENDERER_DESCRIPTOR_INDEXING("descriptor_indexing"),
RENDERER_SAMPLE_SHADING("sample_shading"),

View File

@@ -32,7 +32,6 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
MAX_ANISOTROPY("max_anisotropy"),
THEME("theme"),
THEME_MODE("theme_mode"),
APP_LANGUAGE("app_language"),
OVERLAY_SCALE("control_scale"),
OVERLAY_OPACITY("control_opacity"),
LOCK_DRAWER("lock_drawer"),

View File

@@ -139,6 +139,13 @@ abstract class SettingsItem(
valuesId = R.array.dynaStateValues
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_FORCE_UNSUPPORTED_EXTENSIONS,
titleId = R.string.force_unsupported_extensions,
descriptionId = R.string.force_unsupported_extensions_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_PROVOKING_VERTEX,
@@ -667,11 +674,10 @@ abstract class SettingsItem(
)
)
put(
SpinBoxSetting(
SliderSetting(
IntSetting.CPU_TICKS,
titleId = R.string.cpu_ticks,
descriptionId = 0,
valueHint = R.string.cpu_ticks,
min = 77,
max = 65535
)
@@ -757,15 +763,6 @@ abstract class SettingsItem(
titleId = R.string.enable_update_checks,
)
)
put(
SingleChoiceSetting(
IntSetting.APP_LANGUAGE,
titleId = R.string.app_language,
descriptionId = R.string.app_language_description,
choicesId = R.array.appLanguageNames,
valuesId = R.array.appLanguageValues
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_DEBUG,

View File

@@ -1,13 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.features.settings.ui
import android.content.Context
import org.yuzu.yuzu_emu.YuzuApplication
import android.os.Bundle
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
@@ -29,7 +24,6 @@ import org.yuzu.yuzu_emu.features.input.NativeInput
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
import org.yuzu.yuzu_emu.fragments.ResetSettingsDialogFragment
import org.yuzu.yuzu_emu.utils.*
import org.yuzu.yuzu_emu.utils.collect
class SettingsActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingsBinding
@@ -38,10 +32,6 @@ class SettingsActivity : AppCompatActivity() {
private val settingsViewModel: SettingsViewModel by viewModels()
override fun attachBaseContext(base: Context) {
super.attachBaseContext(YuzuApplication.applyLanguage(base))
}
override fun onCreate(savedInstanceState: Bundle?) {
ThemeHelper.setTheme(this)
@@ -135,16 +125,6 @@ class SettingsActivity : AppCompatActivity() {
NativeConfig.savePerGameConfig()
NativeConfig.unloadPerGameConfig()
}
if (settingsViewModel.shouldRecreateForLanguageChange.value) {
settingsViewModel.setShouldRecreateForLanguageChange(false)
val relaunchIntent = packageManager?.getLaunchIntentForPackage(packageName)
if (relaunchIntent != null) {
relaunchIntent.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK or android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(relaunchIntent)
android.os.Process.killProcess(android.os.Process.myPid())
}
}
}
}

View File

@@ -425,14 +425,6 @@ class SettingsAdapter(
position
).show(fragment.childFragmentManager, SettingsDialogFragment.TAG)
// reset language if detected
if (item.setting.key == "app_language") {
// recreate page apply language change instantly
fragment.requireActivity().recreate()
settingsViewModel.setShouldRecreateForLanguageChange(true)
}
return true
}

View File

@@ -14,9 +14,6 @@ import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.MotionEvent
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import androidx.fragment.app.DialogFragment
@@ -200,54 +197,6 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
updateValidity(newValue)
}
fun attachRepeat(button: View, delta: Int) {
val handler = Handler(Looper.getMainLooper())
var runnable: Runnable? = null
val initialDelay = 400L
val minDelay = 40L
val accelerationFactor = 0.75f
button.setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
val current = spinboxBinding.editValue.text.toString().toIntOrNull() ?: currentValue
val newValue = (current + delta)
spinboxBinding.editValue.setText(newValue.toString())
updateValidity(newValue)
var delay = initialDelay
runnable = object : Runnable {
override fun run() {
val curr = spinboxBinding.editValue.text.toString().toIntOrNull() ?: currentValue
val next = curr + delta
spinboxBinding.editValue.setText(next.toString())
updateValidity(next)
// accelerate
delay = (delay * accelerationFactor).toLong().coerceAtLeast(minDelay)
handler.postDelayed(this, delay)
}
}
handler.postDelayed(runnable!!, initialDelay)
true
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
if (runnable != null) {
handler.removeCallbacks(runnable!!)
runnable = null
}
v.performClick()
true
}
else -> false
}
}
}
attachRepeat(spinboxBinding.buttonDecrement, -1)
attachRepeat(spinboxBinding.buttonIncrement, 1)
spinboxBinding.editValue.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
@@ -387,12 +336,6 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
.show()
}
scSetting.setSelectedValue(value)
if (scSetting.setting.key == "app_language") {
settingsViewModel.setShouldRecreateForLanguageChange(true)
// recreate page apply language change instantly
requireActivity().recreate()
}
}
is StringSingleChoiceSetting -> {

View File

@@ -453,6 +453,7 @@ class SettingsFragmentPresenter(
sl.apply {
add(HeaderSetting(R.string.veil_extensions))
add(ByteSetting.RENDERER_DYNA_STATE.key)
add(BooleanSetting.RENDERER_FORCE_UNSUPPORTED_EXTENSIONS.key)
add(BooleanSetting.RENDERER_PROVOKING_VERTEX.key)
add(BooleanSetting.RENDERER_DESCRIPTOR_INDEXING.key)
add(BooleanSetting.RENDERER_SAMPLE_SHADING.key)
@@ -1030,10 +1031,8 @@ class SettingsFragmentPresenter(
override fun reset() = IntSetting.THEME.setInt(defaultValue)
}
add(HeaderSetting(R.string.app_settings))
add(IntSetting.APP_LANGUAGE.key)
if (NativeLibrary.isUpdateCheckerEnabled()) {
add(HeaderSetting(R.string.app_settings))
add(BooleanSetting.ENABLE_UPDATE_CHECKS.key)
}

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -57,8 +54,6 @@ class SettingsViewModel : ViewModel() {
private val _shouldShowResetInputDialog = MutableStateFlow(false)
val shouldShowResetInputDialog = _shouldShowResetInputDialog.asStateFlow()
private val _shouldRecreateForLanguageChange = MutableStateFlow(false)
val shouldRecreateForLanguageChange = _shouldRecreateForLanguageChange.asStateFlow()
fun setShouldRecreate(value: Boolean) {
_shouldRecreate.value = value
}
@@ -108,10 +103,6 @@ class SettingsViewModel : ViewModel() {
_shouldShowResetInputDialog.value = value
}
fun setShouldRecreateForLanguageChange(value: Boolean) {
_shouldRecreateForLanguageChange.value = value
}
fun getCurrentDeviceParams(defaultParams: ParamPackage): ParamPackage =
try {
InputHandler.registeredControllers[currentDevice]

View File

@@ -4,7 +4,6 @@
package org.yuzu.yuzu_emu.ui.main
import android.content.Intent
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.view.View
@@ -54,7 +53,6 @@ import org.yuzu.yuzu_emu.activities.EmulationActivity
import kotlin.text.compareTo
import androidx.core.net.toUri
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.YuzuApplication
class MainActivity : AppCompatActivity(), ThemeProvider {
private lateinit var binding: ActivityMainBinding
@@ -70,10 +68,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
private val CHECKED_DECRYPTION = "CheckedDecryption"
private var checkedDecryption = false
override fun attachBaseContext(base: Context) {
super.attachBaseContext(YuzuApplication.applyLanguage(base))
}
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }

View File

@@ -62,7 +62,6 @@ namespace AndroidSettings {
Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android};
Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds",
Settings::Category::Android};
Settings::Setting<s32> app_language{linkage, 0, "app_language", Settings::Category::Android};
Settings::Setting<bool> enable_update_checks{linkage, true, "enable_update_checks",
Settings::Category::Android};

View File

@@ -4,8 +4,6 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#define VMA_IMPLEMENTATION
#include "video_core/vulkan_common/vma.h"
#include <codecvt>
#include <locale>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -391,61 +391,6 @@
<item>2</item>
</integer-array>
<string-array name="appLanguageNames">
<item>@string/app_language_system</item>
<item>@string/app_language_english</item>
<item>@string/app_language_spanish</item>
<item>@string/app_language_french</item>
<item>@string/app_language_german</item>
<item>@string/app_language_italian</item>
<item>@string/app_language_portuguese</item>
<item>@string/app_language_brazilian_portuguese</item>
<item>@string/app_language_russian</item>
<item>@string/app_language_japanese</item>
<item>@string/app_language_korean</item>
<item>@string/app_language_simplified_chinese</item>
<item>@string/app_language_traditional_chinese</item>
<item>@string/app_language_polish</item>
<item>@string/app_language_czech</item>
<item>@string/app_language_norwegian</item>
<item>@string/app_language_hungarian</item>
<item>@string/app_language_ukrainian</item>
<item>@string/app_language_vietnamese</item>
<item>@string/app_language_indonesian</item>
<item>@string/app_language_arabic</item>
<item>@string/app_language_central_kurdish</item>
<item>@string/app_language_persian</item>
<item>@string/app_language_hebrew</item>
<item>@string/app_language_serbian</item>
</string-array>
<integer-array name="appLanguageValues">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<item>10</item>
<item>11</item>
<item>12</item>
<item>13</item>
<item>14</item>
<item>15</item>
<item>16</item>
<item>17</item>
<item>18</item>
<item>19</item>
<item>20</item>
<item>21</item>
<item>22</item>
<item>23</item>
<item>24</item>
</integer-array>
<string-array name="outputEngineEntries">
<item>@string/auto</item>
<item>@string/oboe</item>

View File

@@ -94,6 +94,8 @@
<string name="dyna_state">Extended Dynamic State</string>
<string name="dyna_state_description">Controls the number of features that can be used in Extended Dynamic State. Higher numbers allow for more features and can increase performance, but may cause issues with some drivers and vendors. The default value may vary depending on your system and hardware capabilities. This value can be changed until stability and a better visual quality are achieved.</string>
<string name="disabled">Disabled</string>
<string name="force_unsupported_extensions">Force Unsupported Extensions</string>
<string name="force_unsupported_extensions_description">Bypasses all driver workarounds and safety checks. May cause crashes, graphical glitches, or instability. Only enable for testing purposes.</string>
<string name="provoking_vertex">Provoking Vertex</string>
<string name="provoking_vertex_description">Improves lighting and vertex handling in certain games. Only supported on Vulkan 1.0+ GPUs.</string>
<string name="descriptor_indexing">Descriptor Indexing</string>
@@ -1028,35 +1030,6 @@
<string name="use_black_backgrounds">Black backgrounds</string>
<string name="use_black_backgrounds_description">When using the dark theme, apply black backgrounds.</string>
<!-- App Language -->
<string name="app_language">App Language</string>
<string name="app_language_description">Change the language of the app interface</string>
<string name="app_language_system">Follow System</string>
<string name="app_language_english">English</string>
<string name="app_language_spanish">Español</string>
<string name="app_language_french">Français</string>
<string name="app_language_german">Deutsch</string>
<string name="app_language_italian">Italiano</string>
<string name="app_language_portuguese">Português</string>
<string name="app_language_brazilian_portuguese">Português do Brasil</string>
<string name="app_language_russian">Русский</string>
<string name="app_language_japanese">日本語</string>
<string name="app_language_korean">한국어</string>
<string name="app_language_simplified_chinese">简体中文</string>
<string name="app_language_traditional_chinese">繁體中文</string>
<string name="app_language_polish">Polski</string>
<string name="app_language_czech">Čeština</string>
<string name="app_language_norwegian">Norsk bokmål</string>
<string name="app_language_hungarian">Magyar</string>
<string name="app_language_ukrainian">Українська</string>
<string name="app_language_vietnamese">Tiếng Việt</string>
<string name="app_language_indonesian">Bahasa Indonesia</string>
<string name="app_language_arabic">العربية</string>
<string name="app_language_central_kurdish">کوردیی ناوەندی</string>
<string name="app_language_persian">فارسی</string>
<string name="app_language_hebrew">עברית</string>
<string name="app_language_serbian">Српски</string>
<!-- Static Themes -->
<string name="static_theme_color">Theme Color</string>
<string name="eden_theme">Eden (Default)</string>

View File

@@ -84,7 +84,6 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
const auto pow_10 = [](f32 val) -> f32 {
return (val >= 0.0f) ? 1.0f : (val <= -5.3f) ? 0.0f : std::pow(10.0f, val);
};
const auto cos = [](f32 degrees) -> f32 {
return std::cos(degrees * std::numbers::pi_v<f32> / 180.0f);
};
@@ -92,39 +91,26 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
static bool unk_initialized{false};
static Common::FixedPoint<50, 14> unk_value{};
auto sample_rate = Common::FixedPoint<50, 14>::from_base(params.sample_rate);
if (sample_rate.to_float() < 1.0f) sample_rate = Common::FixedPoint<50, 14>(1.0f);
auto pre_delay_time = Common::FixedPoint<50, 14>::from_base(params.pre_delay);
if (pre_delay_time.to_float() < 0.0f) pre_delay_time = Common::FixedPoint<50, 14>(0.0f);
const auto sample_rate{Common::FixedPoint<50, 14>::from_base(params.sample_rate)};
const auto pre_delay_time{Common::FixedPoint<50, 14>::from_base(params.pre_delay)};
for (u32 i = 0; i < ReverbInfo::MaxDelayTaps; i++) {
int target_delay = ((pre_delay_time + EarlyDelayTimes[params.early_mode][i]) * sample_rate).to_int();
if (target_delay < 0) target_delay = 0;
if (target_delay > state.pre_delay_line.sample_count_max) target_delay = state.pre_delay_line.sample_count_max;
int old_delay = state.early_delay_times[i] - 1;
int smooth_delay = old_delay + (target_delay - old_delay) / 4;
state.early_delay_times[i] = smooth_delay + 1;
auto target_gain = Common::FixedPoint<50, 14>::from_base(params.early_gain) * EarlyDelayGains[params.early_mode][i];
if (target_gain.to_float() < 0.0f) target_gain = Common::FixedPoint<50, 14>(0.0f);
if (target_gain.to_float() > 1.0f) target_gain = Common::FixedPoint<50, 14>(1.0f);
state.early_gains[i] = state.early_gains[i] + (target_gain - state.early_gains[i]) / 4;
auto early_delay{
((pre_delay_time + EarlyDelayTimes[params.early_mode][i]) * sample_rate).to_int()};
early_delay = (std::min)(early_delay, state.pre_delay_line.sample_count_max);
state.early_delay_times[i] = early_delay + 1;
state.early_gains[i] = Common::FixedPoint<50, 14>::from_base(params.early_gain) *
EarlyDelayGains[params.early_mode][i];
}
if (params.channel_count == 2) {
state.early_gains[4] *= Common::FixedPoint<50, 14>(0.5f);
state.early_gains[5] *= Common::FixedPoint<50, 14>(0.5f);
state.early_gains[4] * 0.5f;
state.early_gains[5] * 0.5f;
}
int target_pre_time = ((pre_delay_time + EarlyDelayTimes[params.early_mode][10]) * sample_rate).to_int();
if (target_pre_time < 0) target_pre_time = 0;
if (target_pre_time > state.pre_delay_line.sample_count_max) target_pre_time = state.pre_delay_line.sample_count_max;
int old_pre_time = state.pre_delay_time;
state.pre_delay_time = old_pre_time + (target_pre_time - old_pre_time) / 4;
auto pre_time{
((pre_delay_time + EarlyDelayTimes[params.early_mode][10]) * sample_rate).to_int()};
state.pre_delay_time = (std::min)(pre_time, state.pre_delay_line.sample_count_max);
if (!unk_initialized) {
unk_value = cos((1280.0f / sample_rate).to_float());
@@ -132,64 +118,45 @@ static void UpdateReverbEffectParameter(const ReverbInfo::ParameterVersion2& par
}
for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) {
int target_fdn_delay = (FdnDelayTimes[params.late_mode][i] * sample_rate).to_int();
if (target_fdn_delay < 0) target_fdn_delay = 0;
if (target_fdn_delay > state.fdn_delay_lines[i].sample_count_max) target_fdn_delay = state.fdn_delay_lines[i].sample_count_max;
const auto fdn_delay{(FdnDelayTimes[params.late_mode][i] * sample_rate).to_int()};
state.fdn_delay_lines[i].sample_count =
(std::min)(fdn_delay, state.fdn_delay_lines[i].sample_count_max);
state.fdn_delay_lines[i].buffer_end =
&state.fdn_delay_lines[i].buffer[state.fdn_delay_lines[i].sample_count - 1];
int old_fdn = state.fdn_delay_lines[i].sample_count;
state.fdn_delay_lines[i].sample_count = old_fdn + (target_fdn_delay - old_fdn) / 4;
state.fdn_delay_lines[i].buffer_end = &state.fdn_delay_lines[i].buffer[state.fdn_delay_lines[i].sample_count - 1];
const auto decay_delay{(DecayDelayTimes[params.late_mode][i] * sample_rate).to_int()};
state.decay_delay_lines[i].sample_count =
(std::min)(decay_delay, state.decay_delay_lines[i].sample_count_max);
state.decay_delay_lines[i].buffer_end =
&state.decay_delay_lines[i].buffer[state.decay_delay_lines[i].sample_count - 1];
int target_decay_delay = (DecayDelayTimes[params.late_mode][i] * sample_rate).to_int();
if (target_decay_delay < 0) target_decay_delay = 0;
if (target_decay_delay > state.decay_delay_lines[i].sample_count_max) target_decay_delay = state.decay_delay_lines[i].sample_count_max;
state.decay_delay_lines[i].decay =
0.5999755859375f * (1.0f - Common::FixedPoint<50, 14>::from_base(params.colouration));
int old_decay = state.decay_delay_lines[i].sample_count;
state.decay_delay_lines[i].sample_count = old_decay + (target_decay_delay - old_decay) / 4;
state.decay_delay_lines[i].buffer_end = &state.decay_delay_lines[i].buffer[state.decay_delay_lines[i].sample_count - 1];
auto a{(Common::FixedPoint<50, 14>(state.fdn_delay_lines[i].sample_count_max) +
state.decay_delay_lines[i].sample_count_max) *
-3};
auto b{a / (Common::FixedPoint<50, 14>::from_base(params.decay_time) * sample_rate)};
Common::FixedPoint<50, 14> c{0.0f};
Common::FixedPoint<50, 14> d{0.0f};
auto hf_decay_ratio{Common::FixedPoint<50, 14>::from_base(params.high_freq_decay_ratio)};
auto colouration = Common::FixedPoint<50, 14>::from_base(params.colouration);
if (colouration.to_float() < 0.0f) colouration = Common::FixedPoint<50, 14>(0.0f);
if (colouration.to_float() > 1.0f) colouration = Common::FixedPoint<50, 14>(1.0f);
state.decay_delay_lines[i].decay = state.decay_delay_lines[i].decay + (0.5999755859375f * (1.0f - colouration) - state.decay_delay_lines[i].decay) / 4;
auto decay_time_fp = Common::FixedPoint<50, 14>::from_base(params.decay_time);
if (decay_time_fp.to_float() <= 0.0f) decay_time_fp = Common::FixedPoint<50, 14>(0.0001f);
auto a = (Common::FixedPoint<50, 14>(state.fdn_delay_lines[i].sample_count_max) + state.decay_delay_lines[i].sample_count_max) * -3;
auto b = a / (decay_time_fp * sample_rate);
auto hf_decay_ratio = Common::FixedPoint<50, 14>::from_base(params.high_freq_decay_ratio);
if (hf_decay_ratio.to_float() < 0.001f) hf_decay_ratio = Common::FixedPoint<50, 14>(0.001f);
if (hf_decay_ratio.to_float() > 0.999f) hf_decay_ratio = Common::FixedPoint<50, 14>(0.999f);
Common::FixedPoint<50, 14> c{0.0f}, d{0.0f};
if (hf_decay_ratio.to_float() > 0.9949f) {
if (hf_decay_ratio > 0.99493408203125f) {
c = 0.0f;
d = 1.0f;
} else {
auto e = pow_10(((((1.0f / hf_decay_ratio.to_float()) - 1.0f) * 2) / 100 * (b / 10)).to_float());
if (e < 0.0001f) e = 0.0001f;
if (e > 1.0f) e = 1.0f;
auto f = 1.0f - e;
if (f < 0.0001f) f = 0.0001f;
auto g = 2.0f - (unk_value.to_float() * e * 2);
auto h_sq = g * g - f * f * 4;
if (h_sq < 0.0f) h_sq = 0.0f;
auto h = std::sqrt(h_sq);
const auto e{
pow_10(((((1.0f / hf_decay_ratio) - 1.0f) * 2) / 100 * (b / 10)).to_float())};
const auto f{1.0f - e};
const auto g{2.0f - (unk_value * e * 2)};
const auto h{std::sqrt(std::pow(g.to_float(), 2.0f) - (std::pow(f, 2.0f) * 4))};
c = (g - h) / (f * 2.0f);
d = 1.0f - c;
}
state.hf_decay_prev_gain[i] = state.hf_decay_prev_gain[i] + (c - state.hf_decay_prev_gain[i]) / 4;
state.hf_decay_gain[i] = state.hf_decay_gain[i] + (pow_10((b / 1000).to_float()) * d * 0.70709228515625f - state.hf_decay_gain[i]) / 4;
state.hf_decay_prev_gain[i] = c;
state.hf_decay_gain[i] = pow_10((b / 1000).to_float()) * d * 0.70709228515625f;
state.prev_feedback_output[i] = 0;
}
}
@@ -224,8 +191,6 @@ static void InitializeReverbEffect(const ReverbInfo::ParameterVersion2& params,
const auto center_delay_time{(5 * delay).to_uint_floor()};
state.center_delay_line.Initialize(center_delay_time, 1.0f);
UpdateReverbEffectParameter(params, state);
for (u32 i = 0; i < ReverbInfo::MaxDelayLines; i++) {
std::ranges::fill(state.fdn_delay_lines[i].buffer, 0);
std::ranges::fill(state.decay_delay_lines[i].buffer, 0);

View File

@@ -257,8 +257,6 @@ else()
target_link_libraries(common PUBLIC Boost::headers)
endif()
target_link_libraries(common PUBLIC Boost::filesystem)
if (lz4_ADDED)
target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib)
endif()

View File

@@ -10,6 +10,8 @@
#include "video_core/rasterizer_interface.h"
#include "common/android/multiplayer/multiplayer.h"
#include <network/network.h>
#include "common/settings.h"
#include "common/logging/log.h"
static JavaVM *s_java_vm;
@@ -524,6 +526,13 @@ namespace Common::Android {
s_patch_title_id_field = env->GetFieldID(patch_class, "titleId", "Ljava/lang/String;");
env->DeleteLocalRef(patch_class);
// Prefer hardware decoding on Android by default, forcing this setting will
// make the native side attempt GPU decoding first. If the platform lacks a usable
// FFmpeg HW device, FFmpeg will fall back to CPU automatically.
Settings::values.nvdec_emulation.SetValue(Settings::NvdecEmulation::Gpu);
LOG_INFO(HW_GPU, "Android JNI_OnLoad: forced nvdec_emulation = GPU");
const jclass double_class = env->FindClass("java/lang/Double");
s_double_class = reinterpret_cast<jclass>(env->NewGlobalRef(double_class));
s_double_constructor = env->GetMethodID(double_class, "<init>", "(D)V");

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -106,60 +103,46 @@ template <>
#else
// Some architectures lack u128, there is no definitive way to check them all without even more macro magic
// so let's just... do this; add your favourite arches once they get u128 support :)
#if (defined(__clang__) || defined(__GNUC__)) && (defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64))
using RealU128 = unsigned __int128;
# define SYNC_VAL_COMPARE_AND_SWAP(p, e, v) __sync_val_compare_and_swap(p, e, v)
# define SYNC_BOOL_COMPARE_AND_SWAP(p, e, v) __sync_bool_compare_and_swap(p, e, v)
# define U128_ZERO_INIT 0
#else
using RealU128 = u128;
# define SYNC_VAL_COMPARE_AND_SWAP(p, e, v) ((*p == e) ? *p = v : *p)
# define SYNC_BOOL_COMPARE_AND_SWAP(p, e, v) ((*p == e) ? (void)(*p = v) : (void)0), true
# define U128_ZERO_INIT {}
#endif
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected) {
return SYNC_BOOL_COMPARE_AND_SWAP(pointer, expected, value);
return __sync_bool_compare_and_swap(pointer, expected, value);
}
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected) {
RealU128 value_a;
RealU128 expected_a;
unsigned __int128 value_a;
unsigned __int128 expected_a;
std::memcpy(&value_a, value.data(), sizeof(u128));
std::memcpy(&expected_a, expected.data(), sizeof(u128));
return SYNC_BOOL_COMPARE_AND_SWAP((RealU128*)pointer, expected_a, value_a);
return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
}
template <typename T>
[[nodiscard]] inline bool AtomicCompareAndSwap(T* pointer, T value, T expected, T& actual) {
actual = SYNC_VAL_COMPARE_AND_SWAP(pointer, expected, value);
actual = __sync_val_compare_and_swap(pointer, expected, value);
return actual == expected;
}
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected, u128& actual) {
RealU128 value_a;
RealU128 expected_a;
RealU128 actual_a;
[[nodiscard]] inline bool AtomicCompareAndSwap(u64* pointer, u128 value, u128 expected,
u128& actual) {
unsigned __int128 value_a;
unsigned __int128 expected_a;
unsigned __int128 actual_a;
std::memcpy(&value_a, value.data(), sizeof(u128));
std::memcpy(&expected_a, expected.data(), sizeof(u128));
actual_a = SYNC_VAL_COMPARE_AND_SWAP((RealU128*)pointer, expected_a, value_a);
actual_a = __sync_val_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
std::memcpy(actual.data(), &actual_a, sizeof(u128));
return actual_a == expected_a;
}
[[nodiscard]] inline u128 AtomicLoad128(u64* pointer) {
RealU128 zeros_a = U128_ZERO_INIT;
RealU128 result_a = SYNC_VAL_COMPARE_AND_SWAP((RealU128*)pointer, zeros_a, zeros_a);
unsigned __int128 zeros_a = 0;
unsigned __int128 result_a =
__sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a);
u128 result;
std::memcpy(result.data(), &result_a, sizeof(u128));
return result;
}
#undef U128_ZERO_INIT
#undef SYNC_VAL_COMPARE_AND_SWAP
#undef SYNC_BOOL_COMPARE_AND_SWAP
#endif

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -15,4 +12,24 @@ namespace Common {
template <typename T>
concept IsContiguousContainer = std::contiguous_iterator<typename T::iterator>;
// TODO: Replace with std::derived_from when the <concepts> header
// is available on all supported platforms.
template <typename Derived, typename Base>
concept DerivedFrom = requires {
std::is_base_of_v<Base, Derived>;
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
};
// TODO: Replace with std::convertible_to when libc++ implements it.
template <typename From, typename To>
concept ConvertibleTo = std::is_convertible_v<From, To>;
// No equivalents in the stdlib
template <typename T>
concept IsArithmetic = std::is_arithmetic_v<T>;
template <typename T>
concept IsIntegral = std::is_integral_v<T>;
} // namespace Common

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2015 Evan Teran
// SPDX-License-Identifier: MIT
@@ -19,10 +16,6 @@
namespace Common {
// No equivalent for "std::arithmetic" in the stdlib
template <typename T>
concept IsArithmetic = std::is_arithmetic_v<T>;
template <size_t I, size_t F>
class FixedPoint;
@@ -399,13 +392,13 @@ public: // binary math operators, effects underlying bit pattern since these
return *this;
}
template <std::integral Integer>
template <IsIntegral Integer>
constexpr FixedPoint& operator>>=(Integer n) {
data_ >>= n;
return *this;
}
template <std::integral Integer>
template <IsIntegral Integer>
constexpr FixedPoint& operator<<=(Integer n) {
data_ <<= n;
return *this;
@@ -594,12 +587,12 @@ constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) {
}
// shift operators
template <size_t I, size_t F, std::integral Integer>
template <size_t I, size_t F, IsIntegral Integer>
constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) {
lhs <<= rhs;
return lhs;
}
template <size_t I, size_t F, std::integral Integer>
template <size_t I, size_t F, IsIntegral Integer>
constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) {
lhs >>= rhs;
return lhs;

View File

@@ -14,29 +14,16 @@ namespace fs = std::filesystem;
fs::path GetKvdbPath()
{
return GetKvdbPath(GetLegacyPath(EmuPath::RyujinxDir));
}
fs::path GetKvdbPath(const fs::path& path) {
return path / "bis" / "system" / "save" / "8000000000000000" / "0"
return GetLegacyPath(EmuPath::RyujinxDir) / "bis" / "system" / "save" / "8000000000000000" / "0"
/ "imkvdb.arc";
}
fs::path GetRyuPathFromSavePath(const fs::path& path) {
// This is a horrible hack, but I cba to find something better
return path.parent_path().parent_path().parent_path().parent_path().parent_path();
}
fs::path GetRyuSavePath(const u64 &save_id)
{
return GetRyuSavePath(GetLegacyPath(EmuPath::RyujinxDir), save_id);
}
std::filesystem::path GetRyuSavePath(const std::filesystem::path& path, const u64& save_id) {
std::string hex = fmt::format("{:016x}", save_id);
// TODO: what's the difference between 0 and 1?
return path / "bis" / "user" / "save" / hex / "0";
// TODO: what's the difference between 0 and 1?
return GetLegacyPath(EmuPath::RyujinxDir) / "bis" / "user" / "save" / hex / "0";
}
IMENReadResult ReadKvdb(const fs::path &path, std::vector<IMEN> &imens)

View File

@@ -7,17 +7,16 @@
#include <filesystem>
#include <vector>
namespace fs = std::filesystem;
namespace Common::FS {
constexpr const char IMEN_MAGIC[4] = {0x49, 0x4d, 0x45, 0x4e};
constexpr const char IMKV_MAGIC[4] = {0x49, 0x4d, 0x4b, 0x56};
constexpr const u8 IMEN_SIZE = 0x8c;
std::filesystem::path GetKvdbPath();
std::filesystem::path GetKvdbPath(const std::filesystem::path &path);
std::filesystem::path GetRyuPathFromSavePath(const std::filesystem::path &path);
std::filesystem::path GetRyuSavePath(const u64 &save_id);
std::filesystem::path GetRyuSavePath(const std::filesystem::path &path, const u64 &save_id);
fs::path GetKvdbPath();
fs::path GetRyuSavePath(const u64 &program_id);
enum class IMENReadResult {
Nonexistent, // ryujinx not found
@@ -36,6 +35,6 @@ struct IMEN
static_assert(sizeof(IMEN) == 0x10, "IMEN has incorrect size.");
IMENReadResult ReadKvdb(const std::filesystem::path &path, std::vector<IMEN> &imens);
IMENReadResult ReadKvdb(const fs::path &path, std::vector<IMEN> &imens);
} // namespace Common::FS

View File

@@ -4,12 +4,10 @@
#include "symlink.h"
#ifdef _WIN32
#include <fmt/format.h>
#include <windows.h>
#include <fmt/format.h>
#endif
#include <boost/filesystem.hpp>
namespace fs = std::filesystem;
// The sole purpose of this file is to treat symlinks like symlinks on POSIX,
@@ -17,40 +15,29 @@ namespace fs = std::filesystem;
// This is because, for some inexplicable reason, Microsoft has locked symbolic
// links behind a "security policy", whereas directory junctions--functionally identical
// for directories, by the way--are not. Why? I don't know.
// And no, they do NOT provide a standard API for this (at least to my knowledge).
// CreateSymbolicLink, even when EXPLICITLY TOLD to create a junction, still fails
// because of their security policy.
// I don't know what kind of drugs the Windows developers have been on since NT started.
// Microsoft still has not implemented any of this in their std::filesystem implemenation,
// which ALSO means that it DOES NOT FOLLOW ANY DIRECTORY JUNCTIONS... AT ALL.
// Nor does any of their command line utilities or APIs. So you're quite literally
// on your own.
namespace Common::FS {
bool CreateSymlink(fs::path from, fs::path to)
bool CreateSymlink(const fs::path &from, const fs::path &to)
{
from.make_preferred();
to.make_preferred();
#ifdef _WIN32
const std::string command = fmt::format("mklink /J {} {}", to.string(), from.string());
return system(command.c_str()) == 0;
#else
std::error_code ec;
fs::create_directory_symlink(from, to, ec);
#ifdef _WIN32
if (ec) {
const std::string command = fmt::format("mklink /J \"{}\" \"{}\"",
to.string(),
from.string());
return system(command.c_str()) == 0;
}
#endif
return !ec;
#endif
}
bool IsSymlink(const fs::path &path)
{
return boost::filesystem::is_symlink(boost::filesystem::path{path});
#ifdef _WIN32
auto attributes = GetFileAttributesW(path.wstring().c_str());
return attributes & FILE_ATTRIBUTE_REPARSE_POINT;
#else
return fs::is_symlink(path);
#endif
}
} // namespace Common::FS

View File

@@ -6,7 +6,7 @@
#include <filesystem>
namespace Common::FS {
bool CreateSymlink(std::filesystem::path from, std::filesystem::path to);
bool CreateSymlink(const std::filesystem::path &from, const std::filesystem::path &to);
bool IsSymlink(const std::filesystem::path &path);
} // namespace Common::FS

View File

@@ -1,10 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fstream>
#include <vector>
#include "common/heap_tracker.h"
#include "common/logging/log.h"
#include "common/assert.h"
@@ -36,6 +37,8 @@ HeapTracker::~HeapTracker() = default;
void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
MemoryPermission perm, bool is_separate_heap) {
bool rebuild_required = false;
// When mapping other memory, map pages immediately.
if (!is_separate_heap) {
m_buffer.Map(virtual_offset, host_offset, length, perm, false);
@@ -57,11 +60,29 @@ void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
// Insert into mappings.
m_map_count++;
m_mappings.insert(*map);
const auto it = m_mappings.insert(*map);
// Update tick before possible rebuild.
it->tick = m_tick++;
// Check if we need to rebuild.
if (m_resident_map_count >= m_max_resident_map_count) {
rebuild_required = true;
}
// Map the area.
m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false);
// This map is now resident.
it->is_resident = true;
m_resident_map_count++;
m_resident_mappings.insert(*it);
}
// Finally, map.
this->DeferredMapSeparateHeap(virtual_offset);
if (rebuild_required) {
// A rebuild was required, so perform it now.
this->RebuildSeparateHeapAddressSpace();
}
}
void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) {
@@ -148,6 +169,7 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p
// Clamp to end.
next = (std::min)(next, end);
// Reprotect, if we need to.
if (should_protect) {
m_buffer.Protect(cur, next - cur, perm);
@@ -158,51 +180,6 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p
}
}
bool HeapTracker::DeferredMapSeparateHeap(u8* fault_address) {
if (m_buffer.IsInVirtualRange(fault_address)) {
return this->DeferredMapSeparateHeap(fault_address - m_buffer.VirtualBasePointer());
}
return false;
}
bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) {
bool rebuild_required = false;
{
std::scoped_lock lk{m_lock};
// Check to ensure this was a non-resident separate heap mapping.
const auto it = this->GetNearestHeapMapLocked(virtual_offset);
if (it == m_mappings.end() || it->is_resident) {
return false;
}
// Update tick before possible rebuild.
it->tick = m_tick++;
// Check if we need to rebuild.
if (m_resident_map_count > m_max_resident_map_count) {
rebuild_required = true;
}
// Map the area.
m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false);
// This map is now resident.
it->is_resident = true;
m_resident_map_count++;
m_resident_mappings.insert(*it);
}
if (rebuild_required) {
// A rebuild was required, so perform it now.
this->RebuildSeparateHeapAddressSpace();
}
return true;
}
void HeapTracker::RebuildSeparateHeapAddressSpace() {
std::scoped_lock lk{m_rebuild_lock, m_lock};
@@ -213,8 +190,8 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() {
// Despite being worse in theory, this has proven to be better in practice than more
// regularly dumping a smaller amount, because it significantly reduces average case
// lock contention.
std::size_t const desired_count = (std::min)(m_resident_map_count, m_max_resident_map_count) / 2;
std::size_t const evict_count = m_resident_map_count - desired_count;
const size_t desired_count = (std::min)(m_resident_map_count, m_max_resident_map_count) / 2;
const size_t evict_count = m_resident_map_count - desired_count;
auto it = m_resident_mappings.begin();
for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) {

View File

@@ -521,29 +521,14 @@ public:
#else
fd = memfd_create("HostMemory", 0);
#endif
bool use_anon = false;
if (fd <= 0) {
LOG_WARNING(Common_Memory, "memfd_create: {}", strerror(errno));
use_anon = true;
}
if (!use_anon) {
// Defined to extend the file with zeros
int ret = ftruncate(fd, backing_size);
if (ret != 0) {
LOG_WARNING(Common_Memory, "ftruncate: {} (likely out-of-emory)", strerror(errno));
use_anon = true;
}
}
if (use_anon) {
LOG_WARNING(Common_Memory, "Using private mappings instead of shared ones");
backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
if (fd > 0) {
fd = -1;
close(fd);
}
} else {
backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
}
ASSERT_MSG(fd >= 0, "memfd_create failed: {}", strerror(errno));
// Defined to extend the file with zeros
int ret = ftruncate(fd, backing_size);
ASSERT_MSG(ret == 0, "ftruncate failed with {}, are you out-of-memory?", strerror(errno));
backing_base = static_cast<u8*>(
mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
ASSERT_MSG(backing_base != MAP_FAILED, "mmap failed: {}", strerror(errno));
// Virtual memory initialization
@@ -567,18 +552,22 @@ public:
free_manager.AllocateBlock(virtual_base + virtual_offset, length);
// Deduce mapping protection flags.
int prot_flags = PROT_NONE;
if (True(perms & MemoryPermission::Read))
prot_flags |= PROT_READ;
if (True(perms & MemoryPermission::Write))
prot_flags |= PROT_WRITE;
int flags = PROT_NONE;
if (True(perms & MemoryPermission::Read)) {
flags |= PROT_READ;
}
if (True(perms & MemoryPermission::Write)) {
flags |= PROT_WRITE;
}
#ifdef ARCHITECTURE_arm64
if (True(perms & MemoryPermission::Execute))
prot_flags |= PROT_EXEC;
if (True(perms & MemoryPermission::Execute)) {
flags |= PROT_EXEC;
}
#endif
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));
void* ret = mmap(virtual_base + virtual_offset, length, flags, MAP_SHARED | MAP_FIXED, fd,
host_offset);
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
}
void Unmap(size_t virtual_offset, size_t length) {
@@ -730,9 +719,7 @@ void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length,
ASSERT(virtual_offset % PageAlignment == 0);
ASSERT(host_offset % PageAlignment == 0);
ASSERT(length % PageAlignment == 0);
if (impl && virtual_base) {
ASSERT(virtual_offset + length <= virtual_size);
}
ASSERT(virtual_offset + length <= virtual_size);
ASSERT(host_offset + length <= backing_size);
if (length == 0 || !virtual_base || !impl) {
return;
@@ -743,9 +730,7 @@ void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length,
void HostMemory::Unmap(size_t virtual_offset, size_t length, bool separate_heap) {
ASSERT(virtual_offset % PageAlignment == 0);
ASSERT(length % PageAlignment == 0);
if (impl && virtual_base) {
ASSERT(virtual_offset + length <= virtual_size);
}
ASSERT(virtual_offset + length <= virtual_size);
if (length == 0 || !virtual_base || !impl) {
return;
}
@@ -755,9 +740,7 @@ void HostMemory::Unmap(size_t virtual_offset, size_t length, bool separate_heap)
void HostMemory::Protect(size_t virtual_offset, size_t length, MemoryPermission perm) {
ASSERT(virtual_offset % PageAlignment == 0);
ASSERT(length % PageAlignment == 0);
if (impl && virtual_base) {
ASSERT(virtual_offset + length <= virtual_size);
}
ASSERT(virtual_offset + length <= virtual_size);
if (length == 0 || !virtual_base || !impl) {
return;
}

View File

@@ -1,14 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <type_traits>
#include <fmt/ranges.h>
#include "common/swap.h"
// adapted from https://github.com/fmtlib/fmt/issues/2704
// a generic formatter for enum classes
@@ -23,14 +20,3 @@ struct fmt::formatter<T, std::enable_if_t<std::is_enum_v<T>, char>>
}
};
#endif
template <typename T, typename U>
struct fmt::formatter<SwapStructT<T, U>> {
constexpr auto parse(format_parse_context& ctx) {
return ctx.begin();
}
template <typename FormatContext>
auto format(const SwapStructT<T, U>& reg, FormatContext& ctx) const {
return fmt::format_to(ctx.out(), "{}", T(reg));
}
};

View File

@@ -169,7 +169,7 @@ bool IsFastmemEnabled() {
if (values.cpu_accuracy.GetValue() == CpuAccuracy::Unsafe) {
return bool(values.cpuopt_unsafe_host_mmu);
}
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
return false;
#else
return true;
@@ -359,9 +359,6 @@ void RestoreGlobalState(bool is_powered_on) {
for (const auto& reset : values.linkage.restore_functions) {
reset();
}
// Reset per-game flags
values.use_squashed_iterated_blend = false;
}
static bool configuring_global = true;

View File

@@ -296,7 +296,7 @@ struct Values {
Category::CpuDebug};
SwitchableSetting<bool> cpuopt_unsafe_host_mmu{linkage,
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
false,
#else
true,
@@ -349,7 +349,9 @@ struct Values {
linkage, true, "use_asynchronous_gpu_emulation", Category::Renderer};
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
#ifdef ANDROID
AstcDecodeMode::Cpu,
// Most modern Android devices have native ASTC support
// and benefit from GPU decoding. Default to GPU there.
AstcDecodeMode::Gpu,
#else
AstcDecodeMode::Gpu,
#endif
@@ -546,6 +548,7 @@ struct Values {
Category::RendererExtensions,
Specialization::Scalar};
SwitchableSetting<bool> force_unsupported_extensions{linkage, false, "force_unsupported_extensions", Category::RendererExtensions};
SwitchableSetting<bool> provoking_vertex{linkage, false, "provoking_vertex", Category::RendererExtensions};
SwitchableSetting<bool> descriptor_indexing{linkage, false, "descriptor_indexing", Category::RendererExtensions};
SwitchableSetting<bool> sample_shading{linkage, false, "sample_shading", Category::RendererExtensions, Specialization::Paired};
@@ -560,60 +563,6 @@ struct Values {
false,
&sample_shading};
#ifdef ANDROID
// Shader Float Controls (Android only) - Eden Veil / Extensions
// Force enable VK_KHR_shader_float_controls even if driver has known issues
// Allows fine-tuning float behavior to match Switch/Maxwell or optimize performance
SwitchableSetting<bool> shader_float_controls_force_enable{linkage,
false,
"shader_float_controls_force_enable",
Category::RendererExtensions,
Specialization::Paired};
// Individual float behavior controls (visible only when force_enable is true)
// Multiple can be active simultaneously EXCEPT FTZ and DenormPreserve (mutually exclusive)
//
// Recommended configurations:
// Switch-native: FTZ=ON, RTE=ON, SignedZero=ON (matches Maxwell behavior)
// Performance: FTZ=ON only (fastest)
// Accuracy: DenormPreserve=ON, RTE=ON, SignedZero=ON (slowest, highest precision)
SwitchableSetting<bool> shader_float_ftz{linkage,
false,
"shader_float_ftz",
Category::RendererExtensions,
Specialization::Default,
true,
false,
&shader_float_controls_force_enable};
SwitchableSetting<bool> shader_float_denorm_preserve{linkage,
false,
"shader_float_denorm_preserve",
Category::RendererExtensions,
Specialization::Default,
true,
false,
&shader_float_controls_force_enable};
SwitchableSetting<bool> shader_float_rte{linkage,
false,
"shader_float_rte",
Category::RendererExtensions,
Specialization::Default,
true,
false,
&shader_float_controls_force_enable};
SwitchableSetting<bool> shader_float_signed_zero_inf_nan{linkage,
false,
"shader_float_signed_zero_inf_nan",
Category::RendererExtensions,
Specialization::Default,
true,
false,
&shader_float_controls_force_enable};
#endif
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback",
Category::RendererDebug};
@@ -813,9 +762,6 @@ struct Values {
// Add-Ons
std::map<u64, std::vector<std::string>> disabled_addons;
// Per-game overrides
bool use_squashed_iterated_blend;
};
extern Values values;

View File

@@ -152,16 +152,6 @@ ENUM(SpirvOptimizeMode, Never, OnLoad, Always);
ENUM(GpuOverclock, Low, Medium, High)
ENUM(TemperatureUnits, Celsius, Fahrenheit)
// Shader Float Controls behavior modes
// These control how floating-point denormals and special values are handled in shaders
ENUM(ShaderFloatBehavior,
DriverDefault, // Let driver choose (safest, may not match Switch behavior)
SwitchNative, // Emulate Switch/Maxwell behavior (FTZ + RTE + SignedZero)
FlushToZero, // FTZ only - flush denorms to zero (fastest, some precision loss)
PreserveDenorms, // Preserve denorms (slowest, highest precision)
RoundToEven, // RTE rounding mode (IEEE 754 compliant)
SignedZeroInfNan); // Preserve signed zero, inf, nan (accuracy for edge cases)
template <typename Type>
inline std::string_view CanonicalizeEnum(Type id) {
const auto group = EnumMetadata<Type>::Canonicalizations();

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2012 PPSSPP Project
// SPDX-FileCopyrightText: 2012 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -20,17 +17,7 @@
namespace Common {
#if defined(__Bitrig__) || defined(__OpenBSD__)
// We'll redefine swap16, swap32, swap64 as inline functions
// but OpenBSD is like "wow I bring my own stuff"
// It would be nice if we could use them without C++ namespace shenanigans
// But alas :)
#undef swap16
#undef swap32
#undef swap64
#endif
#if defined(_MSC_VER)
#ifdef _MSC_VER
[[nodiscard]] inline u16 swap16(u16 data) noexcept {
return _byteswap_ushort(data);
}
@@ -41,6 +28,12 @@ namespace Common {
return _byteswap_uint64(data);
}
#elif defined(__clang__) || defined(__GNUC__)
#if defined(__Bitrig__) || defined(__OpenBSD__)
// redefine swap16, swap32, swap64 as inline functions
#undef swap16
#undef swap32
#undef swap64
#endif
[[nodiscard]] inline u16 swap16(u16 data) noexcept {
return __builtin_bswap16(data);
}
@@ -51,9 +44,7 @@ namespace Common {
return __builtin_bswap64(data);
}
#else
// Generic implementation - compiler will optimise these into their respective
// __builtin_byteswapXX() and such; if not, the compiler is stupid and we probably
// have bigger problems to worry about :)
// Generic implementation.
[[nodiscard]] inline u16 swap16(u16 data) noexcept {
return (data >> 8) | (data << 8);
}
@@ -71,27 +62,33 @@ namespace Common {
[[nodiscard]] inline float swapf(float f) noexcept {
static_assert(sizeof(u32) == sizeof(float), "float must be the same size as uint32_t.");
u32 value;
std::memcpy(&value, &f, sizeof(u32));
value = swap32(value);
std::memcpy(&f, &value, sizeof(u32));
return f;
}
[[nodiscard]] inline double swapd(double f) noexcept {
static_assert(sizeof(u64) == sizeof(double), "double must be the same size as uint64_t.");
u64 value;
std::memcpy(&value, &f, sizeof(u64));
value = swap64(value);
std::memcpy(&f, &value, sizeof(u64));
return f;
}
} // Namespace Common
template <typename T, typename F>
struct SwapStructT {
using SwappedT = SwapStructT;
struct swap_struct_t {
using swapped_t = swap_struct_t;
protected:
T value;
@@ -104,137 +101,137 @@ public:
T swap() const {
return swap(value);
}
SwapStructT() = default;
SwapStructT(const T& v) : value(swap(v)) {}
swap_struct_t() = default;
swap_struct_t(const T& v) : value(swap(v)) {}
template <typename S>
SwappedT& operator=(const S& source) {
value = swap(T(source));
swapped_t& operator=(const S& source) {
value = swap(static_cast<T>(source));
return *this;
}
operator s8() const {
return s8(swap());
return static_cast<s8>(swap());
}
operator u8() const {
return u8(swap());
return static_cast<u8>(swap());
}
operator s16() const {
return s16(swap());
return static_cast<s16>(swap());
}
operator u16() const {
return u16(swap());
return static_cast<u16>(swap());
}
operator s32() const {
return s32(swap());
return static_cast<s32>(swap());
}
operator u32() const {
return u32(swap());
return static_cast<u32>(swap());
}
operator s64() const {
return s64(swap());
return static_cast<s64>(swap());
}
operator u64() const {
return u64(swap());
return static_cast<u64>(swap());
}
operator float() const {
return float(swap());
return static_cast<float>(swap());
}
operator double() const {
return double(swap());
return static_cast<double>(swap());
}
// +v
SwappedT operator+() const {
swapped_t operator+() const {
return +swap();
}
// -v
SwappedT operator-() const {
swapped_t operator-() const {
return -swap();
}
// v / 5
SwappedT operator/(const SwappedT& i) const {
swapped_t operator/(const swapped_t& i) const {
return swap() / i.swap();
}
template <typename S>
SwappedT operator/(const S& i) const {
swapped_t operator/(const S& i) const {
return swap() / i;
}
// v * 5
SwappedT operator*(const SwappedT& i) const {
swapped_t operator*(const swapped_t& i) const {
return swap() * i.swap();
}
template <typename S>
SwappedT operator*(const S& i) const {
swapped_t operator*(const S& i) const {
return swap() * i;
}
// v + 5
SwappedT operator+(const SwappedT& i) const {
swapped_t operator+(const swapped_t& i) const {
return swap() + i.swap();
}
template <typename S>
SwappedT operator+(const S& i) const {
return swap() + T(i);
swapped_t operator+(const S& i) const {
return swap() + static_cast<T>(i);
}
// v - 5
SwappedT operator-(const SwappedT& i) const {
swapped_t operator-(const swapped_t& i) const {
return swap() - i.swap();
}
template <typename S>
SwappedT operator-(const S& i) const {
return swap() - T(i);
swapped_t operator-(const S& i) const {
return swap() - static_cast<T>(i);
}
// v += 5
SwappedT& operator+=(const SwappedT& i) {
swapped_t& operator+=(const swapped_t& i) {
value = swap(swap() + i.swap());
return *this;
}
template <typename S>
SwappedT& operator+=(const S& i) {
value = swap(swap() + T(i));
swapped_t& operator+=(const S& i) {
value = swap(swap() + static_cast<T>(i));
return *this;
}
// v -= 5
SwappedT& operator-=(const SwappedT& i) {
swapped_t& operator-=(const swapped_t& i) {
value = swap(swap() - i.swap());
return *this;
}
template <typename S>
SwappedT& operator-=(const S& i) {
value = swap(swap() - T(i));
swapped_t& operator-=(const S& i) {
value = swap(swap() - static_cast<T>(i));
return *this;
}
// ++v
SwappedT& operator++() {
swapped_t& operator++() {
value = swap(swap() + 1);
return *this;
}
// --v
SwappedT& operator--() {
swapped_t& operator--() {
value = swap(swap() - 1);
return *this;
}
// v++
SwappedT operator++(int) {
SwappedT old = *this;
swapped_t operator++(int) {
swapped_t old = *this;
value = swap(swap() + 1);
return old;
}
// v--
SwappedT operator--(int) {
SwappedT old = *this;
swapped_t operator--(int) {
swapped_t old = *this;
value = swap(swap() - 1);
return old;
}
// Comparison
// v == i
bool operator==(const SwappedT& i) const {
bool operator==(const swapped_t& i) const {
return swap() == i.swap();
}
template <typename S>
@@ -243,7 +240,7 @@ public:
}
// v != i
bool operator!=(const SwappedT& i) const {
bool operator!=(const swapped_t& i) const {
return swap() != i.swap();
}
template <typename S>
@@ -252,7 +249,7 @@ public:
}
// v > i
bool operator>(const SwappedT& i) const {
bool operator>(const swapped_t& i) const {
return swap() > i.swap();
}
template <typename S>
@@ -261,7 +258,7 @@ public:
}
// v < i
bool operator<(const SwappedT& i) const {
bool operator<(const swapped_t& i) const {
return swap() < i.swap();
}
template <typename S>
@@ -270,7 +267,7 @@ public:
}
// v >= i
bool operator>=(const SwappedT& i) const {
bool operator>=(const swapped_t& i) const {
return swap() >= i.swap();
}
template <typename S>
@@ -279,7 +276,7 @@ public:
}
// v <= i
bool operator<=(const SwappedT& i) const {
bool operator<=(const swapped_t& i) const {
return swap() <= i.swap();
}
template <typename S>
@@ -288,82 +285,82 @@ public:
}
// logical
SwappedT operator!() const {
swapped_t operator!() const {
return !swap();
}
// bitmath
SwappedT operator~() const {
swapped_t operator~() const {
return ~swap();
}
SwappedT operator&(const SwappedT& b) const {
swapped_t operator&(const swapped_t& b) const {
return swap() & b.swap();
}
template <typename S>
SwappedT operator&(const S& b) const {
swapped_t operator&(const S& b) const {
return swap() & b;
}
SwappedT& operator&=(const SwappedT& b) {
swapped_t& operator&=(const swapped_t& b) {
value = swap(swap() & b.swap());
return *this;
}
template <typename S>
SwappedT& operator&=(const S b) {
swapped_t& operator&=(const S b) {
value = swap(swap() & b);
return *this;
}
SwappedT operator|(const SwappedT& b) const {
swapped_t operator|(const swapped_t& b) const {
return swap() | b.swap();
}
template <typename S>
SwappedT operator|(const S& b) const {
swapped_t operator|(const S& b) const {
return swap() | b;
}
SwappedT& operator|=(const SwappedT& b) {
swapped_t& operator|=(const swapped_t& b) {
value = swap(swap() | b.swap());
return *this;
}
template <typename S>
SwappedT& operator|=(const S& b) {
swapped_t& operator|=(const S& b) {
value = swap(swap() | b);
return *this;
}
SwappedT operator^(const SwappedT& b) const {
swapped_t operator^(const swapped_t& b) const {
return swap() ^ b.swap();
}
template <typename S>
SwappedT operator^(const S& b) const {
swapped_t operator^(const S& b) const {
return swap() ^ b;
}
SwappedT& operator^=(const SwappedT& b) {
swapped_t& operator^=(const swapped_t& b) {
value = swap(swap() ^ b.swap());
return *this;
}
template <typename S>
SwappedT& operator^=(const S& b) {
swapped_t& operator^=(const S& b) {
value = swap(swap() ^ b);
return *this;
}
template <typename S>
SwappedT operator<<(const S& b) const {
swapped_t operator<<(const S& b) const {
return swap() << b;
}
template <typename S>
SwappedT& operator<<=(const S& b) const {
swapped_t& operator<<=(const S& b) const {
value = swap(swap() << b);
return *this;
}
template <typename S>
SwappedT operator>>(const S& b) const {
swapped_t operator>>(const S& b) const {
return swap() >> b;
}
template <typename S>
SwappedT& operator>>=(const S& b) const {
swapped_t& operator>>=(const S& b) const {
value = swap(swap() >> b);
return *this;
}
@@ -373,167 +370,167 @@ public:
// Arithmetic
template <typename S, typename T2, typename F2>
friend S operator+(const S& p, const SwappedT v);
friend S operator+(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend S operator-(const S& p, const SwappedT v);
friend S operator-(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend S operator/(const S& p, const SwappedT v);
friend S operator/(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend S operator*(const S& p, const SwappedT v);
friend S operator*(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend S operator%(const S& p, const SwappedT v);
friend S operator%(const S& p, const swapped_t v);
// Arithmetic + assignments
template <typename S, typename T2, typename F2>
friend S operator+=(const S& p, const SwappedT v);
friend S operator+=(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend S operator-=(const S& p, const SwappedT v);
friend S operator-=(const S& p, const swapped_t v);
// Bitmath
template <typename S, typename T2, typename F2>
friend S operator&(const S& p, const SwappedT v);
friend S operator&(const S& p, const swapped_t v);
// Comparison
template <typename S, typename T2, typename F2>
friend bool operator<(const S& p, const SwappedT v);
friend bool operator<(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend bool operator>(const S& p, const SwappedT v);
friend bool operator>(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend bool operator<=(const S& p, const SwappedT v);
friend bool operator<=(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend bool operator>=(const S& p, const SwappedT v);
friend bool operator>=(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend bool operator!=(const S& p, const SwappedT v);
friend bool operator!=(const S& p, const swapped_t v);
template <typename S, typename T2, typename F2>
friend bool operator==(const S& p, const SwappedT v);
friend bool operator==(const S& p, const swapped_t v);
};
// Arithmetic
template <typename S, typename T, typename F>
S operator+(const S& i, const SwapStructT<T, F> v) {
S operator+(const S& i, const swap_struct_t<T, F> v) {
return i + v.swap();
}
template <typename S, typename T, typename F>
S operator-(const S& i, const SwapStructT<T, F> v) {
S operator-(const S& i, const swap_struct_t<T, F> v) {
return i - v.swap();
}
template <typename S, typename T, typename F>
S operator/(const S& i, const SwapStructT<T, F> v) {
S operator/(const S& i, const swap_struct_t<T, F> v) {
return i / v.swap();
}
template <typename S, typename T, typename F>
S operator*(const S& i, const SwapStructT<T, F> v) {
S operator*(const S& i, const swap_struct_t<T, F> v) {
return i * v.swap();
}
template <typename S, typename T, typename F>
S operator%(const S& i, const SwapStructT<T, F> v) {
S operator%(const S& i, const swap_struct_t<T, F> v) {
return i % v.swap();
}
// Arithmetic + assignments
template <typename S, typename T, typename F>
S& operator+=(S& i, const SwapStructT<T, F> v) {
S& operator+=(S& i, const swap_struct_t<T, F> v) {
i += v.swap();
return i;
}
template <typename S, typename T, typename F>
S& operator-=(S& i, const SwapStructT<T, F> v) {
S& operator-=(S& i, const swap_struct_t<T, F> v) {
i -= v.swap();
return i;
}
// Logical
template <typename S, typename T, typename F>
S operator&(const S& i, const SwapStructT<T, F> v) {
S operator&(const S& i, const swap_struct_t<T, F> v) {
return i & v.swap();
}
// Comparison
template <typename S, typename T, typename F>
bool operator<(const S& p, const SwapStructT<T, F> v) {
bool operator<(const S& p, const swap_struct_t<T, F> v) {
return p < v.swap();
}
template <typename S, typename T, typename F>
bool operator>(const S& p, const SwapStructT<T, F> v) {
bool operator>(const S& p, const swap_struct_t<T, F> v) {
return p > v.swap();
}
template <typename S, typename T, typename F>
bool operator<=(const S& p, const SwapStructT<T, F> v) {
bool operator<=(const S& p, const swap_struct_t<T, F> v) {
return p <= v.swap();
}
template <typename S, typename T, typename F>
bool operator>=(const S& p, const SwapStructT<T, F> v) {
bool operator>=(const S& p, const swap_struct_t<T, F> v) {
return p >= v.swap();
}
template <typename S, typename T, typename F>
bool operator!=(const S& p, const SwapStructT<T, F> v) {
bool operator!=(const S& p, const swap_struct_t<T, F> v) {
return p != v.swap();
}
template <typename S, typename T, typename F>
bool operator==(const S& p, const SwapStructT<T, F> v) {
bool operator==(const S& p, const swap_struct_t<T, F> v) {
return p == v.swap();
}
template <typename T>
struct Swap64T {
struct swap_64_t {
static T swap(T x) {
return T(Common::swap64(x));
return static_cast<T>(Common::swap64(x));
}
};
template <typename T>
struct Swap32T {
struct swap_32_t {
static T swap(T x) {
return T(Common::swap32(x));
return static_cast<T>(Common::swap32(x));
}
};
template <typename T>
struct Swap16T {
struct swap_16_t {
static T swap(T x) {
return T(Common::swap16(x));
return static_cast<T>(Common::swap16(x));
}
};
template <typename T>
struct SwapFloatT {
struct swap_float_t {
static T swap(T x) {
return T(Common::swapf(x));
return static_cast<T>(Common::swapf(x));
}
};
template <typename T>
struct SwapDoubleT {
struct swap_double_t {
static T swap(T x) {
return T(Common::swapd(x));
return static_cast<T>(Common::swapd(x));
}
};
template <typename T>
struct SwapEnumT {
struct swap_enum_t {
static_assert(std::is_enum_v<T>);
using base = std::underlying_type_t<T>;
public:
SwapEnumT() = default;
SwapEnumT(const T& v) : value(swap(v)) {}
swap_enum_t() = default;
swap_enum_t(const T& v) : value(swap(v)) {}
SwapEnumT& operator=(const T& v) {
swap_enum_t& operator=(const T& v) {
value = swap(v);
return *this;
}
@@ -543,20 +540,22 @@ public:
}
explicit operator base() const {
return base(swap(value));
return static_cast<base>(swap(value));
}
protected:
T value{};
// clang-format off
using swap_t = std::conditional_t<
std::is_same_v<base, u16>, Swap16T<u16>, std::conditional_t<
std::is_same_v<base, s16>, Swap16T<s16>, std::conditional_t<
std::is_same_v<base, u32>, Swap32T<u32>, std::conditional_t<
std::is_same_v<base, s32>, Swap32T<s32>, std::conditional_t<
std::is_same_v<base, u64>, Swap64T<u64>, std::conditional_t<
std::is_same_v<base, s64>, Swap64T<s64>, void>>>>>>;
std::is_same_v<base, u16>, swap_16_t<u16>, std::conditional_t<
std::is_same_v<base, s16>, swap_16_t<s16>, std::conditional_t<
std::is_same_v<base, u32>, swap_32_t<u32>, std::conditional_t<
std::is_same_v<base, s32>, swap_32_t<s32>, std::conditional_t<
std::is_same_v<base, u64>, swap_64_t<u64>, std::conditional_t<
std::is_same_v<base, s64>, swap_64_t<s64>, void>>>>>>;
// clang-format on
static T swap(T x) {
return T(swap_t::swap(base(x)));
return static_cast<T>(swap_t::swap(static_cast<base>(x)));
}
};
@@ -582,17 +581,17 @@ struct AddEndian<u8, SwapTag> {
template <>
struct AddEndian<u16, SwapTag> {
using type = SwapStructT<u16, Swap16T<u16>>;
using type = swap_struct_t<u16, swap_16_t<u16>>;
};
template <>
struct AddEndian<u32, SwapTag> {
using type = SwapStructT<u32, Swap32T<u32>>;
using type = swap_struct_t<u32, swap_32_t<u32>>;
};
template <>
struct AddEndian<u64, SwapTag> {
using type = SwapStructT<u64, Swap64T<u64>>;
using type = swap_struct_t<u64, swap_64_t<u64>>;
};
template <>
@@ -602,33 +601,33 @@ struct AddEndian<s8, SwapTag> {
template <>
struct AddEndian<s16, SwapTag> {
using type = SwapStructT<s16, Swap16T<s16>>;
using type = swap_struct_t<s16, swap_16_t<s16>>;
};
template <>
struct AddEndian<s32, SwapTag> {
using type = SwapStructT<s32, Swap32T<s32>>;
using type = swap_struct_t<s32, swap_32_t<s32>>;
};
template <>
struct AddEndian<s64, SwapTag> {
using type = SwapStructT<s64, Swap64T<s64>>;
using type = swap_struct_t<s64, swap_64_t<s64>>;
};
template <>
struct AddEndian<float, SwapTag> {
using type = SwapStructT<float, SwapFloatT<float>>;
using type = swap_struct_t<float, swap_float_t<float>>;
};
template <>
struct AddEndian<double, SwapTag> {
using type = SwapStructT<double, SwapDoubleT<double>>;
using type = swap_struct_t<double, swap_double_t<double>>;
};
template <typename T>
struct AddEndian<T, SwapTag> {
static_assert(std::is_enum_v<T>);
using type = SwapEnumT<T>;
using type = swap_enum_t<T>;
};
// Alias LETag/BETag as KeepTag/SwapTag depending on the system

View File

@@ -1199,10 +1199,10 @@ else()
target_link_libraries(core PUBLIC Boost::headers)
endif()
target_link_libraries(core PRIVATE fmt::fmt nlohmann_json::nlohmann_json RenderDoc::API MbedTLS::mbedcrypto${YUZU_STATIC_SUFFIX} MbedTLS::mbedtls${YUZU_STATIC_SUFFIX})
# if (MINGW)
# target_link_libraries(core PRIVATE ws2_32 mswsock wlanapi)
# endif()
target_link_libraries(core PRIVATE fmt::fmt nlohmann_json::nlohmann_json RenderDoc::API MbedTLS::mbedcrypto MbedTLS::mbedtls)
if (MINGW)
target_link_libraries(core PRIVATE ws2_32 mswsock wlanapi)
endif()
if (ENABLE_WEB_SERVICE)
target_compile_definitions(core PUBLIC ENABLE_WEB_SERVICE)
@@ -1231,7 +1231,6 @@ endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
target_sources(core PRIVATE
arm/dynarmic/arm_dynarmic.cpp
arm/dynarmic/arm_dynarmic.h
arm/dynarmic/arm_dynarmic_64.cpp
arm/dynarmic/arm_dynarmic_64.h

View File

@@ -1,52 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef __linux__
#include "common/signal_chain.h"
#include "core/arm/dynarmic/arm_dynarmic.h"
#include "core/hle/kernel/k_process.h"
#include "core/memory.h"
namespace Core {
namespace {
thread_local Core::Memory::Memory* g_current_memory{};
std::once_flag g_registered{};
struct sigaction g_old_segv {};
void HandleSigSegv(int sig, siginfo_t* info, void* ctx) {
if (g_current_memory && g_current_memory->InvalidateSeparateHeap(info->si_addr)) {
return;
}
return g_old_segv.sa_sigaction(sig, info, ctx);
}
} // namespace
ScopedJitExecution::ScopedJitExecution(Kernel::KProcess* process) {
g_current_memory = std::addressof(process->GetMemory());
}
ScopedJitExecution::~ScopedJitExecution() {
g_current_memory = nullptr;
}
void ScopedJitExecution::RegisterHandler() {
std::call_once(g_registered, [] {
struct sigaction sa {};
sa.sa_sigaction = &HandleSigSegv;
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
Common::SigAction(SIGSEGV, std::addressof(sa), std::addressof(g_old_segv));
});
}
} // namespace Core
#endif

View File

@@ -29,24 +29,4 @@ constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) {
return static_cast<HaltReason>(hr);
}
#ifdef __linux__
class ScopedJitExecution {
public:
explicit ScopedJitExecution(Kernel::KProcess* process);
~ScopedJitExecution();
static void RegisterHandler();
};
#else
class ScopedJitExecution {
public:
explicit ScopedJitExecution(Kernel::KProcess* process) {}
~ScopedJitExecution() {}
static void RegisterHandler() {}
};
#endif
} // namespace Core

View File

@@ -210,12 +210,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
config.wall_clock_cntpct = m_uses_wall_clock;
config.enable_cycle_counting = !m_uses_wall_clock;
// Code cache size
#if defined(ARCHITECTURE_arm64) || defined(__sun__)
// Code cache size - max in ARM is 128MiB, max in x86_64 is 2GiB
// Solaris doesn't support kPageSize >= 512MiB
config.code_cache_size = std::uint32_t(128_MiB);
#else
config.code_cache_size = std::uint32_t(512_MiB);
#endif
// Allow memory fault handling to work
if (m_system.DebuggerEnabled()) {
@@ -295,7 +292,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
// Curated optimizations
case Settings::CpuAccuracy::Auto:
config.unsafe_optimizations = true;
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__DragonFly__)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
config.fastmem_pointer = std::nullopt;
config.fastmem_exclusive_access = false;
#endif
@@ -344,15 +341,11 @@ bool ArmDynarmic32::IsInThumbMode() const {
}
HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Run());
}
HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Step());
}
@@ -394,7 +387,6 @@ ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProc
m_cp15(std::make_shared<DynarmicCP15>(*this)), m_core_index{core_index} {
auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl();
m_jit = MakeJit(&page_table_impl);
ScopedJitExecution::RegisterHandler();
}
ArmDynarmic32::~ArmDynarmic32() = default;

View File

@@ -269,12 +269,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
config.wall_clock_cntpct = m_uses_wall_clock;
config.enable_cycle_counting = !m_uses_wall_clock;
// Code cache size
#if defined(ARCHITECTURE_arm64) || defined(__sun__)
// Code cache size - max in ARM is 128MiB, max in x86_64 is 2GiB
// Solaris doesn't support kPageSize >= 512MiB
config.code_cache_size = std::uint32_t(128_MiB);
#else
config.code_cache_size = std::uint32_t(512_MiB);
#endif
// Allow memory fault handling to work
if (m_system.DebuggerEnabled()) {
@@ -354,7 +351,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
// Safe optimisations
case Settings::CpuAccuracy::Auto:
config.unsafe_optimizations = true;
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__ANDROID__) && !defined(_WIN32)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__)
config.fastmem_pointer = std::nullopt;
config.fastmem_exclusive_access = false;
#endif
@@ -375,15 +372,11 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
}
HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Run());
}
HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Step());
}
@@ -423,7 +416,6 @@ ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProc
auto& page_table = process->GetPageTable().GetBasePageTable();
auto& page_table_impl = page_table.GetImpl();
m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth());
ScopedJitExecution::RegisterHandler();
}
ArmDynarmic64::~ArmDynarmic64() = default;

View File

@@ -388,6 +388,14 @@ void ArmNce::SignalInterrupt(Kernel::KThread* thread) {
const std::size_t CACHE_PAGE_SIZE = 4096;
void ArmNce::ClearInstructionCache() {
#if defined(__GNUC__) || defined(__clang__)
void* start = (void*)((uintptr_t)__builtin_return_address(0) & ~(CACHE_PAGE_SIZE - 1));
void* end =
(void*)((uintptr_t)start + CACHE_PAGE_SIZE * 2); // Clear two pages for better coverage
// Prefetch next likely pages
__builtin_prefetch((void*)((uintptr_t)end), 1, 3);
__builtin___clear_cache(static_cast<char*>(start), static_cast<char*>(end));
#endif
#ifdef __aarch64__
// Ensure all previous memory operations complete
asm volatile("dmb ish" ::: "memory");
@@ -397,6 +405,20 @@ void ArmNce::ClearInstructionCache() {
}
void ArmNce::InvalidateCacheRange(u64 addr, std::size_t size) {
#if defined(__GNUC__) || defined(__clang__)
// Align the start address to cache line boundary for better performance
const size_t CACHE_LINE_SIZE = 64;
addr &= ~(CACHE_LINE_SIZE - 1);
// Round up size to nearest cache line
size = (size + CACHE_LINE_SIZE - 1) & ~(CACHE_LINE_SIZE - 1);
// Prefetch the range to be invalidated
for (size_t offset = 0; offset < size; offset += CACHE_LINE_SIZE) {
__builtin_prefetch((void*)(addr + offset), 1, 3);
}
#endif
this->ClearInstructionCache();
}

View File

@@ -181,6 +181,14 @@ bool InterpreterVisitor::Ordered(size_t size, bool L, bool o0, Reg Rn, Reg Rt) {
const size_t dbytes = datasize / 8;
u64 address = (Rn == Reg::SP) ? this->GetSp() : this->GetReg(Rn);
// Conservative prefetch for atomic ops
if (memop == MemOp::Load) {
__builtin_prefetch(reinterpret_cast<const void*>(address), 0, 1);
} else {
__builtin_prefetch(reinterpret_cast<const void*>(address), 1, 1);
}
switch (memop) {
case MemOp::Store: {
std::atomic_thread_fence(std::memory_order_seq_cst);
@@ -427,6 +435,21 @@ bool InterpreterVisitor::RegisterImmediate(bool wback, bool postindex, size_t sc
if (!postindex)
address += offset;
// Optimized prefetch for loads
if (memop == MemOp::Load) {
const size_t access_size = datasize / 8;
const bool is_aligned = (address % access_size) == 0;
if (is_aligned) {
__builtin_prefetch(reinterpret_cast<const void*>(address), 0, 3);
if (access_size >= 8 && access_size <= 32) {
__builtin_prefetch(reinterpret_cast<const void*>(address + PREFETCH_STRIDE), 0, 3);
}
} else {
__builtin_prefetch(reinterpret_cast<const void*>(address), 0, 1);
}
}
switch (memop) {
case MemOp::Store: {
u64 data = this->GetReg(Rt);
@@ -493,6 +516,15 @@ bool InterpreterVisitor::SIMDImmediate(bool wback, bool postindex, size_t scale,
if (!postindex)
address += offset;
// Aggressive prefetch for SIMD
if (memop == MemOp::Load) {
__builtin_prefetch(reinterpret_cast<const void*>(address), 0, 3);
__builtin_prefetch(reinterpret_cast<const void*>(address + CACHE_LINE_SIZE), 0, 3);
if (datasize >= SIMD_PREFETCH_THRESHOLD) {
__builtin_prefetch(reinterpret_cast<const void*>(address + PREFETCH_STRIDE), 0, 3);
}
}
switch (memop) {
case MemOp::Store: {
u128 data = VectorGetElement(this->GetVec(Vt), datasize);

View File

@@ -297,9 +297,6 @@ struct System::Impl {
std::string vendor = gpu_core->Renderer().GetDeviceVendor();
LOG_INFO(Core, "GPU Vendor: {}", vendor);
// Reset all per-game flags
Settings::values.use_squashed_iterated_blend = false;
// Insert PC overrides here
#ifdef ANDROID
@@ -325,13 +322,6 @@ struct System::Impl {
#endif
// Ninja Gaiden Ragebound
constexpr u64 ngr = 0x0100781020710000ULL;
if (programId == ngr) {
LOG_INFO(Core, "Enabling game specifc override: use_squashed_iterated_blend");
Settings::values.use_squashed_iterated_blend = true;
}
}
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
@@ -435,9 +425,6 @@ struct System::Impl {
void ShutdownMainProcess() {
SetShuttingDown(true);
// Reset per-game flags
Settings::values.use_squashed_iterated_blend = false;
is_powered_on = false;
exit_locked = false;
exit_requested = false;

View File

@@ -63,10 +63,12 @@ constexpr bool IsInvalidCharacter(char c) {
return impl::IsInvalidCharacterImpl<InvalidCharacters, std::size(InvalidCharacters)>(c);
}
constexpr bool IsInvalidCharacterForHostName(char c) {
return impl::IsInvalidCharacterImpl<InvalidCharactersForHostName, std::size(InvalidCharactersForHostName)>(c);
return impl::IsInvalidCharacterImpl<InvalidCharactersForHostName,
std::size(InvalidCharactersForHostName)>(c);
}
constexpr bool IsInvalidCharacterForMountName(char c) {
return impl::IsInvalidCharacterImpl<InvalidCharactersForMountName, std::size(InvalidCharactersForMountName)>(c);
return impl::IsInvalidCharacterImpl<InvalidCharactersForMountName,
std::size(InvalidCharactersForMountName)>(c);
}
} // namespace StringTraits

View File

@@ -15,6 +15,7 @@
#include "common/alignment.h"
#include "common/assert.h"
#include "common/common_types.h"
#include "common/concepts.h"
namespace Kernel {
@@ -23,7 +24,7 @@ class KThread;
template <typename T>
concept KPriorityQueueAffinityMask = !
std::is_reference_v<T>&& requires(T& t) {
{ t.GetAffinityMask() } -> std::convertible_to<u64>;
{ t.GetAffinityMask() } -> Common::ConvertibleTo<u64>;
{ t.SetAffinityMask(0) };
{ t.GetAffinity(0) } -> std::same_as<bool>;
@@ -49,9 +50,9 @@ std::is_reference_v<T>&& requires(T& t) {
std::remove_cvref_t<decltype(t.GetAffinityMask())>()
} -> KPriorityQueueAffinityMask;
{ t.GetActiveCore() } -> std::convertible_to<s32>;
{ t.GetPriority() } -> std::convertible_to<s32>;
{ t.IsDummyThread() } -> std::convertible_to<bool>;
{ t.GetActiveCore() } -> Common::ConvertibleTo<s32>;
{ t.GetPriority() } -> Common::ConvertibleTo<s32>;
{ t.IsDummyThread() } -> Common::ConvertibleTo<bool>;
};
template <typename Member, size_t NumCores_, int LowestPriority, int HighestPriority>

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-late
// SPDX-License-Identifier: GPL-2.0-or-later
// This file is automatically generated using svc_generator.py.
// DO NOT MODIFY IT MANUALLY
#pragma once
@@ -19,6 +16,8 @@ class System;
#include "core/hle/result.h"
namespace Kernel::Svc {
// clang-format off
Result SetHeapSize(Core::System& system, uint64_t* out_address, uint64_t size);
Result SetMemoryPermission(Core::System& system, uint64_t address, uint64_t size, MemoryPermission perm);
Result SetMemoryAttribute(Core::System& system, uint64_t address, uint64_t size, uint32_t mask, uint32_t attr);
@@ -507,6 +506,8 @@ enum class SvcId : u32 {
MapInsecureMemory = 0x90,
UnmapInsecureMemory = 0x91,
};
// clang-format on
// Custom ABI.
Result ReplyAndReceiveLight(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64From32(Core::System& system, Handle handle, uint32_t* args);

View File

@@ -1,6 +1,3 @@
#!/usr/bin/python3
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
@@ -381,7 +378,7 @@ def emit_gather(sources, name, type_name, reg_size):
if len(sources) == 1:
s, = sources
line = f"{type_name} {name} = Convert<{type_name}>({get_fn}(args, {s}));"
line = f"{name} = Convert<{type_name}>({get_fn}(args, {s}));"
return [line]
var_type = f"std::array<uint{reg_size*8}_t, {len(sources)}>"
@@ -389,9 +386,10 @@ def emit_gather(sources, name, type_name, reg_size):
f"{var_type} {name}_gather{{}};"
]
for i in range(0, len(sources)):
lines.append(f"{name}_gather[{i}] = {get_fn}(args, {sources[i]});")
lines.append(
f"{name}_gather[{i}] = {get_fn}(args, {sources[i]});")
lines.append(f"{type_name} {name} = Convert<{type_name}>({name}_gather);")
lines.append(f"{name} = Convert<{type_name}>({name}_gather);")
return lines
@@ -407,9 +405,14 @@ def emit_scatter(destinations, name, reg_size):
return [line]
var_type = f"std::array<{reg_type}, {len(destinations)}>"
lines = [f"auto {name}_scatter = Convert<{var_type}>({name});"]
lines = [
f"auto {name}_scatter = Convert<{var_type}>({name});"
]
for i in range(0, len(destinations)):
lines.append(f"{set_fn}(args, {destinations[i]}, {name}_scatter[{i}]);")
lines.append(
f"{set_fn}(args, {destinations[i]}, {name}_scatter[{i}]);")
return lines
@@ -433,8 +436,25 @@ def emit_wrapper(wrapped_fn, suffix, register_info, arguments, byte_size):
f"static void SvcWrap_{wrapped_fn}{suffix}(Core::System& system, std::span<uint64_t, 8> args) {{"
]
# Get everything ready.
for return_type, _ in return_write:
lines.append(f"{return_type} ret{{}};")
if return_write:
lines.append("")
for output_type, var_name, _, is_address in output_writes:
output_type = "uint64_t" if is_address else output_type
lines.append(f"{output_type} {var_name}{{}};")
for input_type, var_name, _ in input_reads:
lines.append(f"{input_type} {var_name}{{}};")
if output_writes or input_reads:
lines.append("")
for input_type, var_name, sources in input_reads:
lines += emit_gather(sources, var_name, input_type, byte_size)
if input_reads:
lines.append("")
# Build the call.
call_arguments = ["system"]
@@ -444,18 +464,16 @@ def emit_wrapper(wrapped_fn, suffix, register_info, arguments, byte_size):
else:
call_arguments.append(arg.var_name)
# Get everything ready.
for output_type, var_name, _, is_address in output_writes:
output_type = "uint64_t" if is_address else output_type
lines.append(f"{output_type} {var_name}{{}};")
line = ""
for return_type, _ in return_write:
line += f"{return_type} ret = "
if return_write:
line += "ret = "
line += f"{wrapped_fn}{suffix}({', '.join(call_arguments)});"
lines.append(line)
if return_write or output_writes:
lines.append("")
# Write back the return value and outputs.
for _, destinations in return_write:
lines += emit_scatter(destinations, "ret", byte_size)
@@ -467,13 +485,10 @@ def emit_wrapper(wrapped_fn, suffix, register_info, arguments, byte_size):
COPYRIGHT = """\
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-late
// SPDX-License-Identifier: GPL-2.0-or-later
// This file is automatically generated using svc_generator.py.
// DO NOT MODIFY IT MANUALLY
"""
PROLOGUE_H = """
@@ -490,9 +505,13 @@ class System;
#include "core/hle/result.h"
namespace Kernel::Svc {
// clang-format off
"""
EPILOGUE_H = """
// clang-format on
// Custom ABI.
Result ReplyAndReceiveLight(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64From32(Core::System& system, Handle handle, uint32_t* args);
@@ -534,7 +553,7 @@ PROLOGUE_CPP = """
namespace Kernel::Svc {
static uint32_t GetArg32(std::span<uint64_t, 8> args, int n) {
return uint32_t(args[n]);
return static_cast<uint32_t>(args[n]);
}
static void SetArg32(std::span<uint64_t, 8> args, int n, uint32_t result) {
@@ -555,27 +574,37 @@ template <typename To, typename From>
requires(std::is_trivial_v<To> && std::is_trivially_copyable_v<From>)
static To Convert(const From& from) {
To to{};
if constexpr (sizeof(To) >= sizeof(From))
if constexpr (sizeof(To) >= sizeof(From)) {
std::memcpy(std::addressof(to), std::addressof(from), sizeof(From));
else
} else {
std::memcpy(std::addressof(to), std::addressof(from), sizeof(To));
}
return to;
}
// clang-format off
"""
EPILOGUE_CPP = """
// clang-format on
void Call(Core::System& system, u32 imm) {
auto& kernel = system.Kernel();
auto& process = GetCurrentProcess(kernel);
std::array<uint64_t, 8> args;
kernel.CurrentPhysicalCore().SaveSvcArguments(process, args);
//kernel.EnterSVCProfile();
if (process.Is64Bit())
kernel.EnterSVCProfile();
if (process.Is64Bit()) {
Call64(system, imm, args);
else
} else {
Call32(system, imm, args);
//kernel.ExitSVCProfile();
}
kernel.ExitSVCProfile();
kernel.CurrentPhysicalCore().LoadSvcArguments(process, args);
}
@@ -588,11 +617,12 @@ def emit_call(bitness, names, suffix):
indent = " "
lines = [
f"static void Call{bit_size}(Core::System& system, u32 imm, std::span<uint64_t, 8> args) {{",
f"{indent}switch (SvcId(imm)) {{"
f"{indent}switch (static_cast<SvcId>(imm)) {{"
]
for _, name in names:
lines.append(f"{indent}case SvcId::{name}: return SvcWrap_{name}{suffix}(system, args);")
lines.append(f"{indent}case SvcId::{name}:")
lines.append(f"{indent*2}return SvcWrap_{name}{suffix}(system, args);")
lines.append(f"{indent}default:")
lines.append(
@@ -662,7 +692,7 @@ def main():
call_64 = emit_call(BIT_64, names, SUFFIX_NAMES[BIT_64])
enum_decls = build_enum_declarations()
with open("src/core/hle/kernel/svc.h", "w") as f:
with open("svc.h", "w") as f:
f.write(COPYRIGHT)
f.write(PROLOGUE_H)
f.write("\n".join(svc_fw_declarations))
@@ -674,7 +704,7 @@ def main():
f.write(enum_decls)
f.write(EPILOGUE_H)
with open("src/core/hle/kernel/svc.cpp", "w") as f:
with open("svc.cpp", "w") as f:
f.write(COPYRIGHT)
f.write(PROLOGUE_CPP)
f.write(emit_size_check())

View File

@@ -7,6 +7,8 @@
#include <algorithm>
#include <cstring>
#include <filesystem>
#include <iostream>
#include <random>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/find.hpp>
@@ -16,11 +18,11 @@
#include "common/fs/fs.h"
#include "common/fs/fs_types.h"
#include "common/fs/path_util.h"
#include "common/fs/symlink.h"
#include "common/settings.h"
#include "common/string_util.h"
#include "core/file_sys/savedata_factory.h"
#include "core/hle/service/acc/profile_manager.h"
#include <ranges>
namespace Service::Account {
@@ -490,32 +492,6 @@ void ProfileManager::ResetUserSaveFile()
ParseUserSaveFile();
}
std::vector<UUID> ProfileManager::FindExistingProfileUUIDs()
{
std::vector<UUID> uuids;
for (const ProfileInfo& p : profiles) {
auto uuid = p.user_uuid;
if (!uuid.IsInvalid()) {
uuids.emplace_back(uuid);
}
}
return uuids;
}
std::vector<std::string> ProfileManager::FindExistingProfileStrings()
{
std::vector<UUID> uuids = FindExistingProfileUUIDs();
std::vector<std::string> uuid_strings;
for (const UUID &uuid : uuids) {
auto user_id = uuid.AsU128();
uuid_strings.emplace_back(fmt::format("{:016X}{:016X}", user_id[1], user_id[0]));
}
return uuid_strings;
}
std::vector<std::string> ProfileManager::FindGoodProfiles()
{
namespace fs = std::filesystem;
@@ -525,17 +501,31 @@ std::vector<std::string> ProfileManager::FindGoodProfiles()
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir)
/ "user/save/0000000000000000";
// some exceptions, e.g. the "system" profile
static constexpr const std::array<const char* const, 1> EXCEPTION_UUIDS
= {"00000000000000000000000000000000"};
// some exceptions because certain games just LOVE TO CAUSE ISSUES
static constexpr const std::array<const char* const, 2> EXCEPTION_UUIDS
= {"5755CC2A545A87128500000000000000", "00000000000000000000000000000000"};
for (const char *const uuid : EXCEPTION_UUIDS) {
if (fs::exists(path / uuid))
good_uuids.emplace_back(uuid);
}
auto existing = FindExistingProfileStrings();
good_uuids.insert(good_uuids.end(), existing.begin(), existing.end());
for (const ProfileInfo& p : profiles) {
std::string uuid_string = [p]() -> std::string {
auto uuid = p.user_uuid;
// "ignore" invalid uuids
if (uuid.IsInvalid()) {
return "0";
}
auto user_id = uuid.AsU128();
return fmt::format("{:016X}{:016X}", user_id[1], user_id[0]);
}();
if (uuid_string != "0") good_uuids.emplace_back(uuid_string);
}
return good_uuids;
}
@@ -572,8 +562,7 @@ std::vector<std::string> ProfileManager::FindOrphanedProfiles()
override = true;
// if there are any regular files (NOT directories) there, do NOT delete it :p
// Also: check for symlinks
if (file.is_regular_file() || Common::FS::IsSymlink(file.path()))
if (file.is_regular_file())
return false;
}
} catch (const fs::filesystem_error& e) {

View File

@@ -105,8 +105,6 @@ public:
void ResetUserSaveFile();
std::vector<Common::UUID> FindExistingProfileUUIDs();
std::vector<std::string> FindExistingProfileStrings();
std::vector<std::string> FindGoodProfiles();
std::vector<std::string> FindOrphanedProfiles();

View File

@@ -237,6 +237,7 @@ WebBrowser::~WebBrowser() = default;
void WebBrowser::Initialize() {
if (Settings::values.disable_web_applet) {
LOG_INFO(Service_AM, "Web Browser Applet disabled, skipping.");
return;
}
@@ -304,7 +305,6 @@ void WebBrowser::ExecuteInteractive() {
void WebBrowser::Execute() {
if (Settings::values.disable_web_applet) {
LOG_WARNING(Service_AM, "(STUBBED) called, Web Browser Applet is disabled");
WebBrowserExit(WebExitReason::EndButtonPressed);
return;
}

View File

@@ -229,7 +229,8 @@ std::shared_ptr<FrontendApplet> FrontendAppletHolder::GetApplet(std::shared_ptr<
case AppletId::ProfileSelect:
return std::make_shared<ProfileSelect>(system, applet, mode, *frontend.profile_select);
case AppletId::SoftwareKeyboard:
return std::make_shared<SoftwareKeyboard>(system, applet, mode, *frontend.software_keyboard);
return std::make_shared<SoftwareKeyboard>(system, applet, mode,
*frontend.software_keyboard);
case AppletId::MiiEdit:
return std::make_shared<MiiEdit>(system, applet, mode, *frontend.mii_edit);
case AppletId::Web:
@@ -243,7 +244,9 @@ std::shared_ptr<FrontendApplet> FrontendAppletHolder::GetApplet(std::shared_ptr<
case AppletId::NetConnect:
return std::make_shared<NetConnect>(system, applet, mode, *frontend.net_connect);
default:
LOG_ERROR(Service_AM, "No backend implementation exists for applet_id={:02X}. Falling back to stub applet", static_cast<u8>(id));
UNIMPLEMENTED_MSG(
"No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
static_cast<u8>(id));
return std::make_shared<StubApplet>(system, applet, id, mode);
}
}

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -396,24 +393,6 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
const bool is_buffer_b{BufferDescriptorB().size() > buffer_index &&
BufferDescriptorB()[buffer_index].Size()};
const std::size_t buffer_size{GetWriteBufferSize(buffer_index)};
// Defensive check: if client didn't provide output buffer, log detailed error but don't crash
if (buffer_size == 0) {
LOG_ERROR(Core,
"WriteBuffer called but client provided NO output buffer! "
"Requested size: 0x{:X}, buffer_index: {}, is_buffer_b: {}, "
"BufferB count: {}, BufferC count: {}",
size, buffer_index, is_buffer_b, BufferDescriptorB().size(),
BufferDescriptorC().size());
// Log command context for debugging
LOG_ERROR(Core, "IPC Command: 0x{:X}, Type: {}", GetCommand(),
static_cast<u32>(GetCommandType()));
// Return 0 instead of crashing - let service handle error
return 0;
}
if (size > buffer_size) {
LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size,
buffer_size);

View File

@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -11,8 +8,8 @@
#include <mutex>
#include <string>
#include <unordered_map>
#include <concepts>
#include "common/concepts.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/result.h"
@@ -66,7 +63,7 @@ public:
Result UnregisterService(const std::string& name);
Result GetServicePort(Kernel::KClientPort** out_client_port, const std::string& name);
template <std::derived_from<SessionRequestHandler> T>
template <Common::DerivedFrom<SessionRequestHandler> T>
std::shared_ptr<T> GetService(const std::string& service_name, bool block = false) const {
auto service = registered_services.find(service_name);
if (service == registered_services.end() && !block) {

View File

@@ -8,7 +8,6 @@
#include <optional>
#include <ostream>
#include <string>
#include <concepts>
#include "common/concepts.h"
#include "common/fs/path_util.h"
#include "common/logging/log.h"
@@ -28,7 +27,7 @@ namespace Loader {
namespace {
template <std::derived_from<AppLoader> T>
template <Common::DerivedFrom<AppLoader> T>
std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) {
const auto file_type = T::IdentifyType(file);
if (file_type != FileType::Error) {

View File

@@ -1230,22 +1230,7 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
if (rasterizer) {
impl->InvalidateGPUMemory(ptr, size);
}
#ifdef __linux__
if (!rasterizer && mapped) {
impl->buffer->DeferredMapSeparateHeap(GetInteger(vaddr));
}
#endif
return mapped && ptr != nullptr;
}
bool Memory::InvalidateSeparateHeap(void* fault_address) {
#ifdef __linux__
return impl->buffer->DeferredMapSeparateHeap(static_cast<u8*>(fault_address));
#else
return false;
#endif
}
} // namespace Core::Memory

View File

@@ -495,8 +495,6 @@ public:
bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size);
bool InvalidateSeparateHeap(void* fault_address);
private:
Core::System& system;

View File

@@ -4,6 +4,9 @@
# SPDX-FileCopyrightText: 2017 Citra Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
add_library(yuzu-room STATIC EXCLUDE_FROM_ALL
yuzu_room.cpp
yuzu_room.h
@@ -16,7 +19,7 @@ if (ENABLE_WEB_SERVICE)
target_link_libraries(yuzu-room PRIVATE web_service)
endif()
target_link_libraries(yuzu-room PRIVATE MbedTLS::mbedcrypto${YUZU_STATIC_SUFFIX} MbedTLS::mbedtls${YUZU_STATIC_SUFFIX})
target_link_libraries(yuzu-room PRIVATE MbedTLS::mbedcrypto MbedTLS::mbedtls)
if (MSVC)
target_link_libraries(yuzu-room PRIVATE getopt)
endif()

View File

@@ -81,6 +81,11 @@ if (MSVC)
/bigobj # Increase number of sections in .obj files
/DNOMINMAX)
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
endif()
if (CXX_CLANG)
list(APPEND DYNARMIC_CXX_FLAGS
-Qunused-arguments

View File

@@ -125,10 +125,6 @@ struct Jit::Impl final {
current_state.exclusive_state = false;
}
std::string Disassemble() const {
return {};
}
private:
void PerformRequestedCacheInvalidation(HaltReason hr) {
if (Has(hr, HaltReason::CacheInvalidation)) {
@@ -235,8 +231,4 @@ void Jit::ClearExclusiveState() {
impl->ClearExclusiveState();
}
std::string Jit::Disassemble() const {
return impl->Disassemble();
}
} // namespace Dynarmic::A32

View File

@@ -152,7 +152,7 @@ struct Jit::Impl final {
}
std::string Disassemble() const {
return {};
UNREACHABLE();
}
private:

View File

@@ -468,9 +468,8 @@ void EmitIR<IR::Opcode::FPRoundInt32>(oaknut::CodeGenerator& code, EmitContext&
case FP::RoundingMode::ToNearest_TieAwayFromZero:
code.FRINTA(Sresult, Soperand);
break;
default:
UNREACHABLE();
}
UNREACHABLE();
}
}

View File

@@ -1668,9 +1668,8 @@ void EmitIR<IR::Opcode::VectorTableLookup64>(oaknut::CodeGenerator& code, EmitCo
code.TBX(Dresult->B8(), oaknut::List{V0.B16(), V1.B16()}, Dindices->B8());
}
break;
default:
UNREACHABLE();
}
UNREACHABLE();
}
template<>
@@ -1732,9 +1731,8 @@ void EmitIR<IR::Opcode::VectorTableLookup128>(oaknut::CodeGenerator& code, EmitC
code.TBX(Qresult->B16(), oaknut::List{V0.B16(), V1.B16(), V2.B16(), V3.B16()}, Qindices->B16());
}
break;
default:
UNREACHABLE();
}
UNREACHABLE();
}
template<>

View File

@@ -645,9 +645,8 @@ void EmitIR<IR::Opcode::FPVectorRoundInt32>(oaknut::CodeGenerator& code, EmitCon
case FP::RoundingMode::ToNearest_TieAwayFromZero:
code.FRINTA(Qresult->S4(), Qoperand->S4());
break;
default:
UNREACHABLE();
}
UNREACHABLE();
}
});
}
@@ -685,9 +684,8 @@ void EmitIR<IR::Opcode::FPVectorRoundInt64>(oaknut::CodeGenerator& code, EmitCon
case FP::RoundingMode::ToNearest_TieAwayFromZero:
code.FRINTA(Qresult->D2(), Qoperand->D2());
break;
default:
UNREACHABLE();
}
UNREACHABLE();
}
});
}

View File

@@ -371,9 +371,8 @@ void RAReg<T>::Realize() {
case RWType::ReadWrite:
reg = T{reg_alloc.RealizeReadWriteImpl<kind>(read_value, write_value)};
break;
default:
UNREACHABLE();
}
UNREACHABLE();
}
} // namespace Dynarmic::Backend::Arm64

View File

@@ -188,15 +188,15 @@ private:
ExceptionHandler::ExceptionHandler() = default;
ExceptionHandler::~ExceptionHandler() = default;
#if defined(ARCHITECTURE_x86_64)
#if defined(MCL_ARCHITECTURE_X86_64)
void ExceptionHandler::Register(X64::BlockOfCode& code) {
impl = std::make_unique<Impl>(std::bit_cast<u64>(code.getCode()), code.GetTotalCodeSize());
}
#elif defined(ARCHITECTURE_arm64)
#elif defined(MCL_ARCHITECTURE_ARM64)
void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) {
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr()), size);
}
#elif defined(ARCHITECTURE_riscv64)
#elif defined(MCL_ARCHITECTURE_RISCV)
void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) {
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr<u64>()), size);
}

Some files were not shown because too many files have changed in this diff Show More