Compare commits

..

24 commits

Author SHA1 Message Date
2b067c2160 [network] fix android build of jthread
All checks were successful
eden-license / license-header (pull_request) Successful in 27s
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-09-06 10:00:32 +02:00
a2084c4b94 [network] use jthread and use std::vector for packet list instead of std::list
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-09-06 10:00:32 +02:00
718891d11f
[fs] temporarely disable nca verification (#298)
Some checks failed
eden-license / license-header (pull_request) Failing after 25s
This adds a passthrough to basically disable nca verification for newer NCAs, this fixes (tested) Pokemon 4.0.0 update and other newer SDK games and updates (as reported on the discord)

This is implemented as toggle that is default enabled, this needs proper implementation in the future.

Co-authored-by: crueter <crueter@eden-emu.dev>
Reviewed-on: #298
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: Maufeat <sahyno1996@gmail.com>
Co-committed-by: Maufeat <sahyno1996@gmail.com>
2025-09-05 00:04:37 +02:00
bbcd8aded6
Revert "[heap_tracker] Use ankerl map instead of rb tree (#249)" (#382)
This reverts commit c9a3baab5d.

this commit caused issues in ender magnolia or something, need to make
sure I didn't mess up the revert

Reviewed-on: #382
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@outlook.com>
2025-09-04 16:04:42 +02:00
2bc792e211
[cmake] fix yuzu_cmd, bundled overrides (#381)
Fixes yuzu_cmd not linking to vma (just link to vma for now, but should
be linked to video_core maybe?)

also fixes the weird precedence of bundled packages esp w.r.t json where
an effectively garbage value was passed into the BUNDLED_PACKAGE
argument (was forced to on)

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

Reviewed-on: #381
2025-09-03 04:36:21 +02:00
e7560183fa
[android] minor ui tweaks + translations (#326)
CHANGES:
fix drawer pause/unpause sync (upon leaving/returning to app)
add quick toggle controller overlay to drawer (for players with multiple gear style)
added translation for emulation_hide_overlay
changed Show overlay to Show controller in all langs
added missing translations for values-de

WHAT TO TEST:
sync of pause/resume when you leave eden (screenshot, home, alt tab, etc).
show controller toggle: if it works it works.

Co-authored-by: Allison Cunha <allisonbzk@gmail.com>
Reviewed-on: #326
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
2025-09-03 03:55:19 +02:00
84fadd1506
[cmake] fix unordered-dense deps (#380)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Co-authored-by: crueter <crueter@eden-emu.dev>
Reviewed-on: #380
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-09-02 03:25:27 +02:00
Bix
be7a3e1e86
[Hotfix] Update recommended driver from T21 to T22 (#379)
Help crueters workload.
Signed-off-by: Bix <bix@bixed.xyz>

Reviewed-on: #379
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: Bix <bix@bixed.xyz>
Co-committed-by: Bix <bix@bixed.xyz>
2025-09-01 22:25:26 +02:00
6aa8be1da8
[cmake] fix gh dependencies (#377)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: #377
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-09-01 21:14:54 +02:00
innix
e28b0d2590
[android]: Force app to use the displays max set refresh rate (#373)
Since Android 15, google automatically forces "games" to be 60 hrz. This ensures the display's max refresh rate is actually used. Tested on a Google Pixel 7 Pro with Android 16

Co-authored-by: innix <dev@innix.space>
Reviewed-on: #373
Co-committed-by: innix <dev@innix.space>
2025-09-01 14:18:30 +02:00
innix
6fcfe7f4f3
[macOS, compat] Allow games to boot in MacOS (#372)
This fixes the crashes on game launch caused by MacOS not being present in host_manager.cpp and enables primitiveRestart for MoltenVK to suppress a bunch of errors given in the log about  MoltenVK requiring primitiveRestart. Fixes an crash when switching kingdoms in Mario Odyssey as well

EDS is forced to 0, otherwise games do not show graphics

Note: For now only dynarmicc is working, performance will be slow
Reviewed-on: #372
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@outlook.com>
Co-authored-by: innix <dev@innix.space>
Co-committed-by: innix <dev@innix.space>
2025-09-01 09:23:03 +02:00
e60fd4b68b
[VMA] Phase 3:- Hand all allocation & binding to VMA (#362)
This patch completely removes the Custom Sub allocator with VMA and delegates everything to the VMA.
Overall, the patch integrates VMA and simplifies memory management.
Once these changes pass the testing, it will be used as a base for further improvement.
Note to testers, test for stability and performance.

Co-authored-by: crueter <crueter@eden-emu.dev>
Reviewed-on: #362
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@outlook.com>
Co-authored-by: wildcard <wildcard@eden-emu.dev>
Co-committed-by: wildcard <wildcard@eden-emu.dev>
2025-09-01 00:20:03 +02:00
10c76568b8
[common, fs] include missing header introduced on #330 (#370)
Signed-off-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-on: #370
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Co-committed-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
2025-08-31 08:40:46 +02:00
8dba6a2cb4
[gpu/NVDRV] Finalize, improve AllocObjCtx (#333)
Improves object allocation per channel, only allowing max amount of 6 objects contexts per channel.
Previously objects were stored in a heap allocated vector which is sub-optimal for performance reasons.
The new implementation instead uses a stack based array with a O(1) approach.
This should boost performance in games which heavily rely on object context creation.

Co-authored-by: MaranBr <maranbr@outlook.com>
Reviewed-on: #333
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: SDK-Chan <sdkchan@eden-emu.dev>
Co-committed-by: SDK-Chan <sdkchan@eden-emu.dev>
2025-08-31 07:32:54 +02:00
4b5a8e0621
[cmake] changed app id from org.eden_emu.eden to dev.eden_emu.eden (#237)
it is better to match app id with website domain

Reviewed-on: #237
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: Guo Yunhe <i@guoyunhe.me>
Co-committed-by: Guo Yunhe <i@guoyunhe.me>
2025-08-31 04:56:23 +02:00
39e27bc954
[android] fix intent-auto-driver-install (#369)
Resolving drivers based on the artifact name was too buggy and inconsistent, this PR improves it. Well, I like to think it does

Reviewed-on: #369
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: Producdevity <y.gherbi.dev@gmail.com>
Co-committed-by: Producdevity <y.gherbi.dev@gmail.com>
2025-08-31 03:33:54 +02:00
21c77bdcac
[cmake] fix ffmpeg libdrm on macos (#367)
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: #367
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2025-08-31 03:10:34 +02:00
1c3ca17cfb
[dynarmic] fix annoying gcc/clang error (#365)
caused qt creator to crash somehow geg

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

Reviewed-on: #365
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@outlook.com>
2025-08-31 00:12:06 +02:00
7ca197d900
[qt, compat] fix freedesktop stuffs on Solaris/OpenBSD (#360)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: #360
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-08-30 23:08:04 +02:00
3b4c1beb0c
[desktop] only warn on firmware for qlaunch/games (#363)
- only warns about too new/missing for home menu
- only warns about missing for games that need it (mk8dx)

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

Reviewed-on: #363
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@outlook.com>
2025-08-30 20:32:28 +02:00
76de9d6c8c
[cmake, compat] fix solaris boost build once and for all (#364)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: #364
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-08-30 20:32:21 +02:00
ab015bc730
[VK] Fix asserts with incorrect memory allocations (#357)
This fixes many assertions with incorrect memory allocations. Regression introduced in PR 334.

Co-authored-by: JPikachu <jpikachu.eden@gmail.com>
Co-authored-by: MaranBr <maranbr@outlook.com>
Reviewed-on: #357
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: JPikachu <jpikachu@eden-emu.dev>
Co-committed-by: JPikachu <jpikachu@eden-emu.dev>
2025-08-30 19:35:53 +02:00
f005f6a3ab
[compat] fix freebsd mmap virtual base (#354)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: #354
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-08-30 17:03:56 +02:00
47b703067e
[settings] fix unreachable code warning in fastmem bool (#347)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: #347
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-08-30 15:17:30 +02:00
112 changed files with 1821 additions and 919 deletions

View file

@ -1,6 +1,6 @@
AppRun AppRun
eden.desktop eden.desktop
org.eden_emu.eden.desktop dev.eden_emu.eden.desktop
shared/bin/eden shared/bin/eden
shared/lib/lib.path shared/lib/lib.path
shared/lib/ld-linux-x86-64.so.2 shared/lib/ld-linux-x86-64.so.2

View file

@ -59,15 +59,15 @@ VERSION="$(echo "$EDEN_TAG")"
mkdir -p ./AppDir mkdir -p ./AppDir
cd ./AppDir cd ./AppDir
cp ../dist/org.eden_emu.eden.desktop . cp ../dist/dev.eden_emu.eden.desktop .
cp ../dist/org.eden_emu.eden.svg . cp ../dist/dev.eden_emu.eden.svg .
ln -sf ./org.eden_emu.eden.svg ./.DirIcon ln -sf ./dev.eden_emu.eden.svg ./.DirIcon
UPINFO='gh-releases-zsync|eden-emulator|Releases|latest|*.AppImage.zsync' UPINFO='gh-releases-zsync|eden-emulator|Releases|latest|*.AppImage.zsync'
if [ "$DEVEL" = 'true' ]; then if [ "$DEVEL" = 'true' ]; then
sed -i 's|Name=Eden|Name=Eden Nightly|' ./org.eden_emu.eden.desktop sed -i 's|Name=Eden|Name=Eden Nightly|' ./dev.eden_emu.eden.desktop
UPINFO="$(echo "$UPINFO" | sed 's|Releases|nightly|')" UPINFO="$(echo "$UPINFO" | sed 's|Releases|nightly|')"
fi fi

View file

@ -6,7 +6,7 @@
which png2icns || [ which yay && yay libicns ] || exit which png2icns || [ which yay && yay libicns ] || exit
which magick || exit which magick || exit
export EDEN_SVG_ICO="dist/org.eden_emu.eden.svg" export EDEN_SVG_ICO="dist/dev.eden_emu.eden.svg"
svgo --multipass $EDEN_SVG_ICO svgo --multipass $EDEN_SVG_ICO
magick -density 256x256 -background transparent $EDEN_SVG_ICO \ magick -density 256x256 -background transparent $EDEN_SVG_ICO \

View file

@ -0,0 +1,22 @@
From e59d30b7b12e1d04cc2fc9c6219e35bda447c17e Mon Sep 17 00:00:00 2001
From: Lizzie <159065448+Lizzie841@users.noreply.github.com>
Date: Fri, 16 May 2025 04:12:13 +0100
Subject: [PATCH] Update CMakeLists.txt
---
CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b5f4c4f..c5c6f31 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,7 +24,7 @@ target_include_directories(
target_compile_features(unordered_dense INTERFACE cxx_std_17)
-if(_unordered_dense_is_toplevel_project)
+if(_unordered_dense_is_toplevel_project OR UNORDERED_DENSE_INSTALL)
# locations are provided by GNUInstallDirs
install(
TARGETS unordered_dense

View file

@ -406,8 +406,10 @@ if (YUZU_USE_CPM)
if (NOT MSVC) if (NOT MSVC)
# boost sucks # boost sucks
if (NOT PLATFORM_LINUX AND NOT ANDROID) # Solaris (and probably other NIXes) need explicit pthread definition
target_compile_definitions(boost_container INTERFACE BOOST_HAS_PTHREADS) if (PLATFORM_SUN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthreads")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthreads")
endif() endif()
target_compile_options(boost_heap INTERFACE -Wno-shadow) target_compile_options(boost_heap INTERFACE -Wno-shadow)
@ -856,14 +858,14 @@ endif()
# https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html # https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
# https://www.freedesktop.org/software/appstream/docs/ # https://www.freedesktop.org/software/appstream/docs/
if(ENABLE_QT AND UNIX AND NOT APPLE) if(ENABLE_QT AND UNIX AND NOT APPLE)
install(FILES "dist/org.eden_emu.eden.desktop" install(FILES "dist/dev.eden_emu.eden.desktop"
DESTINATION "share/applications") DESTINATION "share/applications")
install(FILES "dist/org.eden_emu.eden.svg" install(FILES "dist/dev.eden_emu.eden.svg"
DESTINATION "share/icons/hicolor/scalable/apps") DESTINATION "share/icons/hicolor/scalable/apps")
# TODO: these files need to be updated. # TODO: these files need to be updated.
install(FILES "dist/org.eden_emu.eden.xml" install(FILES "dist/dev.eden_emu.eden.xml"
DESTINATION "share/mime/packages") DESTINATION "share/mime/packages")
install(FILES "dist/org.eden_emu.eden.metainfo.xml" install(FILES "dist/dev.eden_emu.eden.metainfo.xml"
DESTINATION "share/metainfo") DESTINATION "share/metainfo")
endif() endif()

View file

@ -184,8 +184,6 @@ function(AddJsonPackage)
# system/bundled # system/bundled
if (bundled STREQUAL "unset" AND DEFINED JSON_BUNDLED_PACKAGE) if (bundled STREQUAL "unset" AND DEFINED JSON_BUNDLED_PACKAGE)
set(bundled ${JSON_BUNDLED_PACKAGE}) set(bundled ${JSON_BUNDLED_PACKAGE})
else()
set(bundled ON)
endif() endif()
AddPackage( AddPackage(
@ -259,6 +257,7 @@ function(AddPackage)
KEY KEY
BUNDLED_PACKAGE BUNDLED_PACKAGE
FIND_PACKAGE_ARGUMENTS
) )
set(multiValueArgs OPTIONS PATCHES) set(multiValueArgs OPTIONS PATCHES)
@ -409,9 +408,9 @@ function(AddPackage)
set_precedence(OFF OFF) set_precedence(OFF OFF)
elseif (CPMUTIL_FORCE_SYSTEM) elseif (CPMUTIL_FORCE_SYSTEM)
set_precedence(ON ON) set_precedence(ON ON)
elseif(NOT CPMUTIL_FORCE_BUNDLED) elseif(CPMUTIL_FORCE_BUNDLED)
set_precedence(OFF OFF) set_precedence(OFF OFF)
elseif (DEFINED PKG_ARGS_BUNDLED_PACKAGE) elseif (DEFINED PKG_ARGS_BUNDLED_PACKAGE AND NOT PKG_ARGS_BUNDLED_PACKAGE STREQUAL "unset")
if (PKG_ARGS_BUNDLED_PACKAGE) if (PKG_ARGS_BUNDLED_PACKAGE)
set(local OFF) set(local OFF)
else() else()

View file

@ -10,7 +10,7 @@ Type=Application
Name=Eden Name=Eden
GenericName=Switch Emulator GenericName=Switch Emulator
Comment=Nintendo Switch video game console emulator Comment=Nintendo Switch video game console emulator
Icon=org.eden_emu.eden Icon=dev.eden_emu.eden
TryExec=eden TryExec=eden
Exec=eden %f Exec=eden %f
Categories=Game;Emulator;Qt; Categories=Game;Emulator;Qt;

View file

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Before After
Before After

View file

@ -96,15 +96,7 @@ if (ENABLE_WEB_SERVICE)
endif() endif()
# unordered_dense # unordered_dense
AddPackage( AddJsonPackage(unordered-dense)
NAME unordered_dense
REPO "Lizzie841/unordered_dense"
SHA e59d30b7b1
HASH 71eff7bd9ba4b9226967bacd56a8ff000946f8813167cb5664bb01e96fb79e4e220684d824fe9c59c4d1cc98c606f13aff05b7940a1ed8ab3c95d6974ee34fa0
FIND_PACKAGE_ARGUMENTS "CONFIG"
OPTIONS
"UNORDERED_DENSE_INSTALL OFF"
)
# FFMpeg # FFMpeg
if (YUZU_USE_BUNDLED_FFMPEG) if (YUZU_USE_BUNDLED_FFMPEG)
@ -147,6 +139,10 @@ add_subdirectory(nx_tzdb)
# VMA # VMA
AddJsonPackage(vulkan-memory-allocator) AddJsonPackage(vulkan-memory-allocator)
if (VulkanMemoryAllocator_ADDED AND MSVC)
target_compile_options(VulkanMemoryAllocator INTERFACE /wd4189)
endif()
if (NOT TARGET LLVM::Demangle) if (NOT TARGET LLVM::Demangle)
add_library(demangle demangle/ItaniumDemangle.cpp) add_library(demangle demangle/ItaniumDemangle.cpp)
target_include_directories(demangle PUBLIC ./demangle) target_include_directories(demangle PUBLIC ./demangle)

View file

@ -74,14 +74,14 @@
}, },
"xbyak_sun": { "xbyak_sun": {
"package": "xbyak", "package": "xbyak",
"repo": "Lizzie841/xbyak", "repo": "herumi/xbyak",
"sha": "51f507b0b3", "sha": "9bb219333a",
"hash": "4a29a3c2f97f7d5adf667a21a008be03c951fb6696b0d7ba27e7e4afa037bc76eb5e059bb84860e01baf741d4d3ac851b840cd54c99d038812fbe0f1fa6d38a4", "hash": "303165d45c8c19387ec49d9fda7d7a4e0d86d4c0153898c23f25ce2d58ece567f44c0bbbfe348239b933edb6e1a1e34f4bc1c0ab3a285bee5da0e548879387b0",
"bundled": true "bundled": true
}, },
"xbyak": { "xbyak": {
"package": "xbyak", "package": "xbyak",
"repo": "Lizzie841/xbyak", "repo": "herumi/xbyak",
"sha": "4e44f4614d", "sha": "4e44f4614d",
"hash": "5824e92159e07fa36a774aedd3b3ef3541d0241371d522cffa4ab3e1f215fa5097b1b77865b47b2481376c704fa079875557ea463ca63d0a7fd6a8a20a589e70", "hash": "5824e92159e07fa36a774aedd3b3ef3541d0241371d522cffa4ab3e1f215fa5097b1b77865b47b2481376c704fa079875557ea463ca63d0a7fd6a8a20a589e70",
"bundled": true "bundled": true
@ -105,5 +105,18 @@
"sha": "2bc873e53c", "sha": "2bc873e53c",
"hash": "02329058a7f9cf7d5039afaae5ab170d9f42f60f4c01e21eaf4f46073886922b057a9ae30eeac040b3ac182f51b9c1bfe9fe1050a2c9f6ce567a1a9a0ec2c768", "hash": "02329058a7f9cf7d5039afaae5ab170d9f42f60f4c01e21eaf4f46073886922b057a9ae30eeac040b3ac182f51b9c1bfe9fe1050a2c9f6ce567a1a9a0ec2c768",
"bundled": true "bundled": true
},
"unordered-dense": {
"package": "unordered_dense",
"repo": "martinus/unordered_dense",
"sha": "73f3cbb237",
"hash": "c08c03063938339d61392b687562909c1a92615b6ef39ec8df19ea472aa6b6478e70d7d5e33d4a27b5d23f7806daf57fe1bacb8124c8a945c918c7663a9e8532",
"find_args": "CONFIG",
"options": [
"UNORDERED_DENSE_INSTALL OFF"
],
"patches": [
"0001-cmake.patch"
]
} }
} }

View file

@ -63,20 +63,22 @@ if (NOT WIN32 AND NOT ANDROID)
set(FFmpeg_HWACCEL_INCLUDE_DIRS) set(FFmpeg_HWACCEL_INCLUDE_DIRS)
set(FFmpeg_HWACCEL_LDFLAGS) set(FFmpeg_HWACCEL_LDFLAGS)
# In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so if (NOT APPLE)
if(PLATFORM_SUN) # In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so
list(APPEND FFmpeg_HWACCEL_LIBRARIES if(PLATFORM_SUN)
X11 list(APPEND FFmpeg_HWACCEL_LIBRARIES
"/usr/lib/xorg/amd64/libdrm.so") X11
else() "/usr/lib/xorg/amd64/libdrm.so")
pkg_check_modules(LIBDRM libdrm REQUIRED) else()
list(APPEND FFmpeg_HWACCEL_LIBRARIES pkg_check_modules(LIBDRM libdrm REQUIRED)
${LIBDRM_LIBRARIES}) list(APPEND FFmpeg_HWACCEL_LIBRARIES
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${LIBDRM_LIBRARIES})
${LIBDRM_INCLUDE_DIRS}) list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS})
endif()
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-libdrm)
endif() endif()
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-libdrm)
if(LIBVA_FOUND) if(LIBVA_FOUND)
find_package(X11 REQUIRED) find_package(X11 REQUIRED)

View file

@ -30,8 +30,8 @@ val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toIn
android { android {
namespace = "org.yuzu.yuzu_emu" namespace = "org.yuzu.yuzu_emu"
compileSdkVersion = "android-35" compileSdkVersion = "android-36"
ndkVersion = "26.1.10909125" ndkVersion = "28.2.13676358"
buildFeatures { buildFeatures {
viewBinding = true viewBinding = true
@ -173,6 +173,7 @@ android {
"-DENABLE_OPENSSL=ON", "-DENABLE_OPENSSL=ON",
"-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
"-DYUZU_USE_CPM=ON", "-DYUZU_USE_CPM=ON",
"-DCPMUTIL_FORCE_BUNDLED=ON",
"-DYUZU_USE_BUNDLED_FFMPEG=ON", "-DYUZU_USE_BUNDLED_FFMPEG=ON",
"-DYUZU_ENABLE_LTO=ON", "-DYUZU_ENABLE_LTO=ON",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",

View file

@ -36,6 +36,9 @@ import androidx.core.net.toUri
import androidx.core.content.edit import androidx.core.content.edit
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.utils.NativeConfig
class GameAdapter(private val activity: AppCompatActivity) : class GameAdapter(private val activity: AppCompatActivity) :
AbstractDiffAdapter<Game, GameAdapter.GameViewHolder>(exact = false) { AbstractDiffAdapter<Game, GameAdapter.GameViewHolder>(exact = false) {
@ -229,6 +232,8 @@ class GameAdapter(private val activity: AppCompatActivity) :
binding.root.findNavController().navigate(action) binding.root.findNavController().navigate(action)
} }
val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
if (NativeLibrary.gameRequiresFirmware(game.programId) && !NativeLibrary.isFirmwareAvailable()) { if (NativeLibrary.gameRequiresFirmware(game.programId) && !NativeLibrary.isFirmwareAvailable()) {
MaterialAlertDialogBuilder(activity) MaterialAlertDialogBuilder(activity)
.setTitle(R.string.loader_requires_firmware) .setTitle(R.string.loader_requires_firmware)
@ -243,6 +248,23 @@ class GameAdapter(private val activity: AppCompatActivity) :
} }
.setNegativeButton(android.R.string.cancel) { _, _ -> } .setNegativeButton(android.R.string.cancel) { _, _ -> }
.show() .show()
} else if (BooleanSetting.DISABLE_NCA_VERIFICATION.getBoolean(false) && !preferences.getBoolean(
Settings.PREF_HIDE_NCA_POPUP, false)) {
MaterialAlertDialogBuilder(activity)
.setTitle(R.string.nca_verification_disabled)
.setMessage(activity.getString(R.string.nca_verification_disabled_description))
.setPositiveButton(android.R.string.ok) { _, _ ->
launch()
}
.setNeutralButton(R.string.dont_show_again) { _, _ ->
preferences.edit {
putBoolean(Settings.PREF_HIDE_NCA_POPUP, true)
}
launch()
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
} else { } else {
launch() launch()
} }

View file

@ -35,6 +35,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_SAMPLE_SHADING("sample_shading"), RENDERER_SAMPLE_SHADING("sample_shading"),
PICTURE_IN_PICTURE("picture_in_picture"), PICTURE_IN_PICTURE("picture_in_picture"),
USE_CUSTOM_RTC("custom_rtc_enabled"), USE_CUSTOM_RTC("custom_rtc_enabled"),
DISABLE_NCA_VERIFICATION("disable_nca_verification"),
BLACK_BACKGROUNDS("black_backgrounds"), BLACK_BACKGROUNDS("black_backgrounds"),
JOYSTICK_REL_CENTER("joystick_rel_center"), JOYSTICK_REL_CENTER("joystick_rel_center"),
DPAD_SLIDE("dpad_slide"), DPAD_SLIDE("dpad_slide"),

View file

@ -37,6 +37,7 @@ object Settings {
const val PREF_SHOULD_SHOW_PRE_ALPHA_WARNING = "ShouldShowPreAlphaWarning" const val PREF_SHOULD_SHOW_PRE_ALPHA_WARNING = "ShouldShowPreAlphaWarning"
const val PREF_SHOULD_SHOW_EDENS_VEIL_DIALOG = "ShouldShowEdensVeilDialog" const val PREF_SHOULD_SHOW_EDENS_VEIL_DIALOG = "ShouldShowEdensVeilDialog"
const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown" const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown"
const val PREF_HIDE_NCA_POPUP = "HideNCAVerificationPopup"
const val SECTION_STATS_OVERLAY = "Stats Overlay" const val SECTION_STATS_OVERLAY = "Stats Overlay"
// Deprecated input overlay preference keys // Deprecated input overlay preference keys

View file

@ -297,7 +297,13 @@ abstract class SettingsItem(
descriptionId = R.string.use_custom_rtc_description descriptionId = R.string.use_custom_rtc_description
) )
) )
put(
SwitchSetting(
BooleanSetting.DISABLE_NCA_VERIFICATION,
titleId = R.string.disable_nca_verification,
descriptionId = R.string.disable_nca_verification_description
)
)
put( put(
StringInputSetting( StringInputSetting(
StringSetting.WEB_TOKEN, StringSetting.WEB_TOKEN,

View file

@ -210,6 +210,7 @@ class SettingsFragmentPresenter(
add(IntSetting.LANGUAGE_INDEX.key) add(IntSetting.LANGUAGE_INDEX.key)
add(BooleanSetting.USE_CUSTOM_RTC.key) add(BooleanSetting.USE_CUSTOM_RTC.key)
add(LongSetting.CUSTOM_RTC.key) add(LongSetting.CUSTOM_RTC.key)
add(BooleanSetting.DISABLE_NCA_VERIFICATION.key)
add(HeaderSetting(R.string.network)) add(HeaderSetting(R.string.network))
add(StringSetting.WEB_TOKEN.key) add(StringSetting.WEB_TOKEN.key)

View file

@ -79,7 +79,7 @@ class DriverFetcherFragment : Fragment() {
IntRange(600, 639) to "Mr. Purple EOL-24.3.4", IntRange(600, 639) to "Mr. Purple EOL-24.3.4",
IntRange(640, 699) to "Mr. Purple T19", IntRange(640, 699) to "Mr. Purple T19",
IntRange(700, 710) to "KIMCHI 25.2.0_r5", IntRange(700, 710) to "KIMCHI 25.2.0_r5",
IntRange(711, 799) to "Mr. Purple T21", IntRange(711, 799) to "Mr. Purple T22",
IntRange(800, 899) to "GameHub Adreno 8xx", IntRange(800, 899) to "GameHub Adreno 8xx",
IntRange(900, Int.MAX_VALUE) to "Unsupported" IntRange(900, Int.MAX_VALUE) to "Unsupported"
) )

View file

@ -509,6 +509,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
gpuModel = GpuDriverHelper.getGpuModel().toString() gpuModel = GpuDriverHelper.getGpuModel().toString()
fwVersion = NativeLibrary.firmwareVersion() fwVersion = NativeLibrary.firmwareVersion()
updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean())
binding.surfaceEmulation.holder.addCallback(this) binding.surfaceEmulation.holder.addCallback(this)
binding.doneControlConfig.setOnClickListener { stopConfiguringControls() } binding.doneControlConfig.setOnClickListener { stopConfiguringControls() }
@ -530,6 +532,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
binding.inGameMenu.requestFocus() binding.inGameMenu.requestFocus()
emulationViewModel.setDrawerOpen(true) emulationViewModel.setDrawerOpen(true)
updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean())
} }
override fun onDrawerClosed(drawerView: View) { override fun onDrawerClosed(drawerView: View) {
@ -571,25 +574,24 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
R.id.menu_pause_emulation -> { R.id.menu_pause_emulation -> {
if (emulationState.isPaused) { if (emulationState.isPaused) {
emulationState.run(false) emulationState.run(false)
it.title = resources.getString(R.string.emulation_pause) updatePauseMenuEntry(false)
it.icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_pause,
requireContext().theme
)
} else { } else {
emulationState.pause() emulationState.pause()
it.title = resources.getString(R.string.emulation_unpause) updatePauseMenuEntry(true)
it.icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_play,
requireContext().theme
)
} }
binding.inGameMenu.requestFocus() binding.inGameMenu.requestFocus()
true true
} }
R.id.menu_quick_overlay -> {
val newState = !BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()
BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(newState)
updateQuickOverlayMenuEntry(newState)
binding.surfaceInputOverlay.refreshControls()
NativeConfig.saveGlobalConfig()
true
}
R.id.menu_settings -> { R.id.menu_settings -> {
val action = HomeNavigationDirections.actionGlobalSettingsActivity( val action = HomeNavigationDirections.actionGlobalSettingsActivity(
null, null,
@ -844,9 +846,50 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
} }
private fun updateQuickOverlayMenuEntry(isVisible: Boolean) {
val menu = binding.inGameMenu.menu
val item = menu.findItem(R.id.menu_quick_overlay)
if (isVisible) {
item.title = getString(R.string.emulation_hide_overlay)
item.icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_controller_disconnected,
requireContext().theme
)
} else {
item.title = getString(R.string.emulation_show_overlay)
item.icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_controller,
requireContext().theme
)
}
}
private fun updatePauseMenuEntry(isPaused: Boolean) {
val menu = binding.inGameMenu.menu
val pauseItem = menu.findItem(R.id.menu_pause_emulation)
if (isPaused) {
pauseItem.title = getString(R.string.emulation_unpause)
pauseItem.icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_play,
requireContext().theme
)
} else {
pauseItem.title = getString(R.string.emulation_pause)
pauseItem.icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_pause,
requireContext().theme
)
}
}
override fun onPause() { override fun onPause() {
if (emulationState.isRunning && emulationActivity?.isInPictureInPictureMode != true) { if (emulationState.isRunning && emulationActivity?.isInPictureInPictureMode != true) {
emulationState.pause() emulationState.pause()
updatePauseMenuEntry(true)
} }
super.onPause() super.onPause()
} }
@ -869,6 +912,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
val socPosition = IntSetting.SOC_OVERLAY_POSITION.getInt() val socPosition = IntSetting.SOC_OVERLAY_POSITION.getInt()
updateSocPosition(socPosition) updateSocPosition(socPosition)
binding.inGameMenu.post {
emulationState?.isPaused?.let { updatePauseMenuEntry(it) }
}
} }
private fun resetInputOverlay() { private fun resetInputOverlay() {
@ -1391,6 +1438,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
R.id.menu_show_overlay -> { R.id.menu_show_overlay -> {
it.isChecked = !it.isChecked it.isChecked = !it.isChecked
BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(it.isChecked) BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(it.isChecked)
updateQuickOverlayMenuEntry(it.isChecked)
binding.surfaceInputOverlay.refreshControls() binding.surfaceInputOverlay.refreshControls()
true true
} }

View file

@ -31,9 +31,6 @@ class HomeViewModel : ViewModel() {
private val _checkKeys = MutableStateFlow(false) private val _checkKeys = MutableStateFlow(false)
val checkKeys = _checkKeys.asStateFlow() val checkKeys = _checkKeys.asStateFlow()
private val _checkFirmware = MutableStateFlow(false)
val checkFirmware = _checkFirmware.asStateFlow()
var navigatedToSetup = false var navigatedToSetup = false
fun setStatusBarShadeVisibility(visible: Boolean) { fun setStatusBarShadeVisibility(visible: Boolean) {
@ -66,8 +63,4 @@ class HomeViewModel : ViewModel() {
fun setCheckKeys(value: Boolean) { fun setCheckKeys(value: Boolean) {
_checkKeys.value = value _checkKeys.value = value
} }
fun setCheckFirmware(value: Boolean) {
_checkFirmware.value = value
}
} }

View file

@ -38,6 +38,7 @@ import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.model.GamesViewModel import org.yuzu.yuzu_emu.model.GamesViewModel
import org.yuzu.yuzu_emu.model.HomeViewModel import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.model.InstallResult import org.yuzu.yuzu_emu.model.InstallResult
import android.os.Build
import org.yuzu.yuzu_emu.model.TaskState import org.yuzu.yuzu_emu.model.TaskState
import org.yuzu.yuzu_emu.model.TaskViewModel import org.yuzu.yuzu_emu.model.TaskViewModel
import org.yuzu.yuzu_emu.utils.* import org.yuzu.yuzu_emu.utils.*
@ -47,6 +48,7 @@ import java.io.BufferedOutputStream
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
import androidx.core.content.edit import androidx.core.content.edit
import kotlin.text.compareTo
class MainActivity : AppCompatActivity(), ThemeProvider { class MainActivity : AppCompatActivity(), ThemeProvider {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
@ -110,6 +112,19 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
// Since Android 15, google automatically forces "games" to be 60 hrz
// This ensures the display's max refresh rate is actually used
display?.let {
val supportedModes = it.supportedModes
val maxRefreshRate = supportedModes.maxByOrNull { mode -> mode.refreshRate }
if (maxRefreshRate != null) {
val layoutParams = window.attributes
layoutParams.preferredDisplayModeId = maxRefreshRate.modeId
window.attributes = layoutParams
}
}
setContentView(binding.root) setContentView(binding.root)
checkAndRequestBluetoothPermissions() checkAndRequestBluetoothPermissions()
@ -127,16 +142,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
checkedDecryption = true checkedDecryption = true
} }
if (!checkedFirmware) {
val firstTimeSetup = PreferenceManager.getDefaultSharedPreferences(applicationContext)
.getBoolean(Settings.PREF_FIRST_APP_LAUNCH, true)
if (!firstTimeSetup) {
checkFirmware()
showPreAlphaWarningDialog()
}
checkedFirmware = true
}
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
@ -183,13 +188,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
if (it) checkKeys() if (it) checkKeys()
} }
homeViewModel.checkFirmware.collect(
this,
resetState = { homeViewModel.setCheckFirmware(false) }
) {
if (it) checkFirmware()
}
setInsets() setInsets()
} }
@ -228,21 +226,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
).show(supportFragmentManager, MessageDialogFragment.TAG) ).show(supportFragmentManager, MessageDialogFragment.TAG)
} }
} }
private fun checkFirmware() {
val resultCode: Int = NativeLibrary.verifyFirmware()
if (resultCode == 0) return
val resultString: String =
resources.getStringArray(R.array.verifyFirmwareResults)[resultCode]
MessageDialogFragment.newInstance(
titleId = R.string.firmware_invalid,
descriptionString = resultString,
helpLinkId = R.string.firmware_missing_help
).show(supportFragmentManager, MessageDialogFragment.TAG)
}
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putBoolean(CHECKED_DECRYPTION, checkedDecryption) outState.putBoolean(CHECKED_DECRYPTION, checkedDecryption)
@ -419,7 +402,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
cacheFirmwareDir.copyRecursively(firmwarePath, true) cacheFirmwareDir.copyRecursively(firmwarePath, true)
NativeLibrary.initializeSystem(true) NativeLibrary.initializeSystem(true)
homeViewModel.setCheckKeys(true) homeViewModel.setCheckKeys(true)
homeViewModel.setCheckFirmware(true)
getString(R.string.save_file_imported_success) getString(R.string.save_file_imported_success)
} }
} catch (e: Exception) { } catch (e: Exception) {
@ -449,7 +431,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
// Optionally reinitialize the system or perform other necessary steps // Optionally reinitialize the system or perform other necessary steps
NativeLibrary.initializeSystem(true) NativeLibrary.initializeSystem(true)
homeViewModel.setCheckKeys(true) homeViewModel.setCheckKeys(true)
homeViewModel.setCheckFirmware(true)
messageToShow = getString(R.string.firmware_uninstalled_success) messageToShow = getString(R.string.firmware_uninstalled_success)
} else { } else {
messageToShow = getString(R.string.firmware_uninstalled_failure) messageToShow = getString(R.string.firmware_uninstalled_failure)

View file

@ -124,11 +124,16 @@ object CustomSettingsHandler {
// Check for driver requirements if activity and driverViewModel are provided // Check for driver requirements if activity and driverViewModel are provided
if (activity != null && driverViewModel != null) { if (activity != null && driverViewModel != null) {
val driverPath = extractDriverPath(customSettings) val rawDriverPath = extractDriverPath(customSettings)
if (driverPath != null) { if (rawDriverPath != null) {
Log.info("[CustomSettingsHandler] Custom settings specify driver: $driverPath") // Normalize to local storage path (we only store drivers under driverStoragePath)
val driverFilename = rawDriverPath.substringAfterLast('/')
.substringAfterLast('\\')
val localDriverPath = "${GpuDriverHelper.driverStoragePath}$driverFilename"
Log.info("[CustomSettingsHandler] Custom settings specify driver: $rawDriverPath (normalized: $localDriverPath)")
// Check if driver exists in the driver storage // Check if driver exists in the driver storage
val driverFile = File(driverPath) val driverFile = File(localDriverPath)
if (!driverFile.exists()) { if (!driverFile.exists()) {
Log.info("[CustomSettingsHandler] Driver not found locally: ${driverFile.name}") Log.info("[CustomSettingsHandler] Driver not found locally: ${driverFile.name}")
@ -182,7 +187,7 @@ object CustomSettingsHandler {
} }
// Attempt to download and install the driver // Attempt to download and install the driver
val driverUri = DriverResolver.ensureDriverAvailable(driverPath, activity) { progress -> val driverUri = DriverResolver.ensureDriverAvailable(driverFilename, activity) { progress ->
progressChannel.trySend(progress.toInt()) progressChannel.trySend(progress.toInt())
} }
@ -209,12 +214,12 @@ object CustomSettingsHandler {
return null return null
} }
// Verify the downloaded driver // Verify the downloaded driver (from normalized local path)
val installedFile = File(driverPath) val installedFile = File(localDriverPath)
val metadata = GpuDriverHelper.getMetadataFromZip(installedFile) val metadata = GpuDriverHelper.getMetadataFromZip(installedFile)
if (metadata.name == null) { if (metadata.name == null) {
Log.error( Log.error(
"[CustomSettingsHandler] Downloaded driver is invalid: $driverPath" "[CustomSettingsHandler] Downloaded driver is invalid: $localDriverPath"
) )
Toast.makeText( Toast.makeText(
activity, activity,
@ -232,7 +237,7 @@ object CustomSettingsHandler {
} }
// Add to driver list // Add to driver list
driverViewModel.onDriverAdded(Pair(driverPath, metadata)) driverViewModel.onDriverAdded(Pair(localDriverPath, metadata))
Log.info( Log.info(
"[CustomSettingsHandler] Successfully downloaded and installed driver: ${metadata.name}" "[CustomSettingsHandler] Successfully downloaded and installed driver: ${metadata.name}"
) )
@ -268,7 +273,7 @@ object CustomSettingsHandler {
// Driver exists, verify it's valid // Driver exists, verify it's valid
val metadata = GpuDriverHelper.getMetadataFromZip(driverFile) val metadata = GpuDriverHelper.getMetadataFromZip(driverFile)
if (metadata.name == null) { if (metadata.name == null) {
Log.error("[CustomSettingsHandler] Invalid driver file: $driverPath") Log.error("[CustomSettingsHandler] Invalid driver file: $localDriverPath")
Toast.makeText( Toast.makeText(
activity, activity,
activity.getString( activity.getString(
@ -459,6 +464,8 @@ object CustomSettingsHandler {
if (inGpuDriverSection && trimmed.startsWith("driver_path=")) { if (inGpuDriverSection && trimmed.startsWith("driver_path=")) {
return trimmed.substringAfter("driver_path=") return trimmed.substringAfter("driver_path=")
.trim()
.removeSurrounding("\"", "\"")
} }
} }

View file

@ -68,6 +68,48 @@ object DriverResolver {
val filename: String val filename: String
) )
// Matching helpers
private val KNOWN_SUFFIXES = listOf(
".adpkg.zip",
".zip",
".7z",
".tar.gz",
".tar.xz",
".rar"
)
private fun stripKnownSuffixes(name: String): String {
var result = name
var changed: Boolean
do {
changed = false
for (s in KNOWN_SUFFIXES) {
if (result.endsWith(s, ignoreCase = true)) {
result = result.dropLast(s.length)
changed = true
}
}
} while (changed)
return result
}
private fun normalizeName(name: String): String {
val base = stripKnownSuffixes(name.lowercase())
// Remove non-alphanumerics to make substring checks resilient
return base.replace(Regex("[^a-z0-9]+"), " ").trim()
}
private fun tokenize(name: String): Set<String> =
normalizeName(name).split(Regex("\\s+")).filter { it.isNotBlank() }.toSet()
// Jaccard similarity between two sets
private fun jaccard(a: Set<String>, b: Set<String>): Double {
if (a.isEmpty() || b.isEmpty()) return 0.0
val inter = a.intersect(b).size.toDouble()
val uni = a.union(b).size.toDouble()
return if (uni == 0.0) 0.0 else inter / uni
}
/** /**
* Resolve a driver download URL from its filename * Resolve a driver download URL from its filename
* @param filename The driver filename (e.g., "turnip_mrpurple-T19-toasted.adpkg.zip") * @param filename The driver filename (e.g., "turnip_mrpurple-T19-toasted.adpkg.zip")
@ -98,7 +140,7 @@ object DriverResolver {
async { async {
searchRepository(repoPath, filename) searchRepository(repoPath, filename)
} }
}.mapNotNull { it.await() }.firstOrNull().also { resolved -> }.firstNotNullOfOrNull { it.await() }.also { resolved ->
// Cache the result if found // Cache the result if found
resolved?.let { resolved?.let {
urlCache[filename] = it urlCache[filename] = it
@ -119,22 +161,56 @@ object DriverResolver {
releaseCache[repoPath] = it releaseCache[repoPath] = it
} }
// Search through all releases and artifacts // First pass: exact name (case-insensitive) against asset filenames
val target = filename.lowercase()
for (release in releases) { for (release in releases) {
for (artifact in release.artifacts) { for (artifact in release.artifacts) {
if (artifact.name == filename) { if (artifact.name.equals(filename, ignoreCase = true) || artifact.name.lowercase() == target) {
Log.info( Log.info("[DriverResolver] Found $filename in $repoPath/${release.tagName}")
"[DriverResolver] Found $filename in $repoPath/${release.tagName}"
)
return@withContext ResolvedDriver( return@withContext ResolvedDriver(
downloadUrl = artifact.url.toString(), downloadUrl = artifact.url.toString(),
repoPath = repoPath, repoPath = repoPath,
releaseTag = release.tagName, releaseTag = release.tagName,
filename = filename filename = artifact.name
) )
} }
} }
} }
// Second pass: fuzzy match by asset filenames only
val reqNorm = normalizeName(filename)
val reqTokens = tokenize(filename)
var best: ResolvedDriver? = null
var bestScore = 0.0
for (release in releases) {
for (artifact in release.artifacts) {
val artNorm = normalizeName(artifact.name)
val artTokens = tokenize(artifact.name)
var score = jaccard(reqTokens, artTokens)
// Boost if one normalized name contains the other
if (artNorm.contains(reqNorm) || reqNorm.contains(artNorm)) {
score = maxOf(score, 0.92)
}
if (score > bestScore) {
bestScore = score
best = ResolvedDriver(
downloadUrl = artifact.url.toString(),
repoPath = repoPath,
releaseTag = release.tagName,
filename = artifact.name
)
}
}
}
// Threshold to avoid bad guesses, this worked fine in testing but might need tuning
if (best != null && bestScore >= 0.6) {
Log.info("[DriverResolver] Fuzzy matched $filename -> ${best.filename} in ${best.repoPath} (score=%.2f)".format(bestScore))
return@withContext best
}
null null
} catch (e: Exception) { } catch (e: Exception) {
Log.error("[DriverResolver] Failed to search $repoPath: ${e.message}") Log.error("[DriverResolver] Failed to search $repoPath: ${e.message}")
@ -296,8 +372,8 @@ object DriverResolver {
context: Context, context: Context,
onProgress: ((Float) -> Unit)? = null onProgress: ((Float) -> Unit)? = null
): Uri? { ): Uri? {
// Extract filename from path // Extract filename from path (support both separators)
val filename = driverPath.substringAfterLast('/') val filename = driverPath.substringAfterLast('/').substringAfterLast('\\')
// Check if driver already exists locally // Check if driver already exists locally
val localPath = "${GpuDriverHelper.driverStoragePath}$filename" val localPath = "${GpuDriverHelper.driverStoragePath}$filename"

View file

@ -17,7 +17,7 @@ add_library(yuzu-android SHARED
set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers) target_link_libraries(yuzu-android PRIVATE audio_core common core input_common frontend_common Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log) target_link_libraries(yuzu-android PRIVATE android camera2ndk EGL glad jnigraphics log)
if (ARCHITECTURE_arm64) if (ARCHITECTURE_arm64)
target_link_libraries(yuzu-android PRIVATE adrenotools) target_link_libraries(yuzu-android PRIVATE adrenotools)

View file

@ -596,6 +596,8 @@ jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv *env, j
const std::string model_name{device.GetModelName()}; const std::string model_name{device.GetModelName()};
window.release();
return Common::Android::ToJString(env, model_name); return Common::Android::ToJString(env, model_name);
} }

View file

@ -8,6 +8,11 @@
android:icon="@drawable/ic_pause" android:icon="@drawable/ic_pause"
android:title="@string/emulation_pause" /> android:title="@string/emulation_pause" />
<item
android:id="@+id/menu_quick_overlay"
android:icon="@drawable/ic_controller"
android:title="@string/emulation_show_overlay"/>
<item <item
android:id="@+id/menu_settings" android:id="@+id/menu_settings"
android:icon="@drawable/ic_settings" android:icon="@drawable/ic_settings"

View file

@ -498,6 +498,8 @@
<string name="use_custom_rtc">ساعة مخصصة في الوقت الحقيقي</string> <string name="use_custom_rtc">ساعة مخصصة في الوقت الحقيقي</string>
<string name="use_custom_rtc_description">يسمح لك بتعيين ساعة مخصصة في الوقت الفعلي منفصلة عن وقت النظام الحالي لديك</string> <string name="use_custom_rtc_description">يسمح لك بتعيين ساعة مخصصة في الوقت الفعلي منفصلة عن وقت النظام الحالي لديك</string>
<string name="set_custom_rtc">تعيين ساعة مخصصة في الوقت الحقيقي</string> <string name="set_custom_rtc">تعيين ساعة مخصصة في الوقت الحقيقي</string>
<string name="disable_nca_verification">تعطيل التحقق من NCA</string>
<string name="disable_nca_verification_description">يعطل التحقق من سلامة أرشيفات محتوى NCA. قد يحسن هذا من سرعة التحميل لكنه يخاطر بتلف البيانات أو تمرير ملفات غير صالحة دون اكتشاف. ضروري لجعل الألعاب والتحديثات التي تتطلب نظامًا أساسيًا 20+ تعمل.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">توليد</string> <string name="generate">توليد</string>
@ -733,7 +735,8 @@
<string name="emulation_rel_stick_center">مركز العصا النسبي</string> <string name="emulation_rel_stick_center">مركز العصا النسبي</string>
<string name="emulation_dpad_slide">مزلاق الأسهم</string> <string name="emulation_dpad_slide">مزلاق الأسهم</string>
<string name="emulation_haptics">الاهتزازات الديناميكية</string> <string name="emulation_haptics">الاهتزازات الديناميكية</string>
<string name="emulation_show_overlay">عرض التراكب</string> <string name="emulation_show_overlay">إظهار وحدة التحكم</string>
<string name="emulation_hide_overlay">إخفاء وحدة التحكم</string>
<string name="emulation_toggle_all">الكل</string> <string name="emulation_toggle_all">الكل</string>
<string name="emulation_control_adjust">ضبط التراكب</string> <string name="emulation_control_adjust">ضبط التراكب</string>
<string name="emulation_control_scale">الحجم</string> <string name="emulation_control_scale">الحجم</string>

View file

@ -482,6 +482,8 @@
<string name="use_custom_rtc">RTCی تایبەتمەند</string> <string name="use_custom_rtc">RTCی تایبەتمەند</string>
<string name="use_custom_rtc_description">ڕێگەت پێدەدات کاتژمێرێکی کاتی ڕاستەقینەی تایبەتمەند دابنێیت کە جیاوازە لە کاتی ئێستای سیستەمەکەت.</string> <string name="use_custom_rtc_description">ڕێگەت پێدەدات کاتژمێرێکی کاتی ڕاستەقینەی تایبەتمەند دابنێیت کە جیاوازە لە کاتی ئێستای سیستەمەکەت.</string>
<string name="set_custom_rtc">دانانی RTCی تایبەتمەند</string> <string name="set_custom_rtc">دانانی RTCی تایبەتمەند</string>
<string name="disable_nca_verification">ناچالاککردنی پشکنینی NCA</string>
<string name="disable_nca_verification_description">پشکنینی پێکهاتەی ئارشیڤەکانی ناوەڕۆکی NCA ناچالاک دەکات. ئەمە لەوانەیە خێرایی بارکردن به‌ره‌وپێش ببات، بەڵام مەترسی لەناوچوونی داتا یان ئەوەی فایلە نادروستەکان بەبێ ئەوەی دۆزرایەوە تێپەڕبن زیاتر دەکات. بۆ ئەوەی یاری و نوێکردنەوەکان کار بکەن کە پێویستی بە فریموێری 20+ هەیە زۆر پێویستە.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">بەرهەم هێنان</string> <string name="generate">بەرهەم هێنان</string>
@ -710,7 +712,8 @@
<string name="emulation_rel_stick_center">ناوەندی گێڕ بەنزیکەیی</string> <string name="emulation_rel_stick_center">ناوەندی گێڕ بەنزیکەیی</string>
<string name="emulation_dpad_slide">خلیسکانی 4 دوگمەکە</string> <string name="emulation_dpad_slide">خلیسکانی 4 دوگمەکە</string>
<string name="emulation_haptics">لەرینەوەی پەنجەلێدان</string> <string name="emulation_haptics">لەرینەوەی پەنجەلێدان</string>
<string name="emulation_show_overlay">نیشاندانی داپۆشەر</string> <string name="emulation_show_overlay">نیشاندانی کۆنتڕۆڵەر</string>
<string name="emulation_hide_overlay">پیشاندانی کۆنتڕۆڵەر</string>
<string name="emulation_toggle_all">گۆڕینی سەرجەم</string> <string name="emulation_toggle_all">گۆڕینی سەرجەم</string>
<string name="emulation_control_adjust">ڕێکخستنی داپۆشەر</string> <string name="emulation_control_adjust">ڕێکخستنی داپۆشەر</string>
<string name="emulation_control_scale">پێوەر</string> <string name="emulation_control_scale">پێوەر</string>

View file

@ -458,6 +458,8 @@
<string name="use_custom_rtc">Vlastní RTC</string> <string name="use_custom_rtc">Vlastní RTC</string>
<string name="use_custom_rtc_description">Vlastní nastavení času</string> <string name="use_custom_rtc_description">Vlastní nastavení času</string>
<string name="set_custom_rtc">Nastavit vlastní RTC</string> <string name="set_custom_rtc">Nastavit vlastní RTC</string>
<string name="disable_nca_verification">Zakázat ověřování NCA</string>
<string name="disable_nca_verification_description">Zakáže ověřování integrity archivů obsahu NCA. To může zlepšit rychlost načítání, ale hrozí poškození dat nebo neodhalení neplatných souborů. Je nutné, aby fungovaly hry a aktualizace vyžadující firmware 20+.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Generovat</string> <string name="generate">Generovat</string>
@ -691,7 +693,8 @@
<string name="emulation_rel_stick_center">Relativní střed joysticku</string> <string name="emulation_rel_stick_center">Relativní střed joysticku</string>
<string name="emulation_dpad_slide">D-pad slide</string> <string name="emulation_dpad_slide">D-pad slide</string>
<string name="emulation_haptics">Haptická odezva</string> <string name="emulation_haptics">Haptická odezva</string>
<string name="emulation_show_overlay">Zobrazit překryv</string> <string name="emulation_show_overlay">Zobrazit ovladač</string>
<string name="emulation_hide_overlay">Skrýt ovladač</string>
<string name="emulation_toggle_all">Přepnout vše</string> <string name="emulation_toggle_all">Přepnout vše</string>
<string name="emulation_control_adjust">Upravit překryv</string> <string name="emulation_control_adjust">Upravit překryv</string>
<string name="emulation_control_scale">Měřítko</string> <string name="emulation_control_scale">Měřítko</string>

View file

@ -486,6 +486,8 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
<string name="select_rtc_date">RTC-Datum auswählen</string> <string name="select_rtc_date">RTC-Datum auswählen</string>
<string name="select_rtc_time">RTC-Zeit auswählen</string> <string name="select_rtc_time">RTC-Zeit auswählen</string>
<string name="use_custom_rtc">Benutzerdefinierte Echtzeituhr</string> <string name="use_custom_rtc">Benutzerdefinierte Echtzeituhr</string>
<string name="disable_nca_verification">NCA-Verifizierung deaktivieren</string>
<string name="disable_nca_verification_description">Deaktiviert die Integritätsprüfung von NCA-Inhaltsarchiven. Dies kann die Ladegeschwindigkeit verbessern, riskiert jedoch Datenbeschädigung oder dass ungültige Dateien unentdeckt bleiben. Ist notwendig, um Spiele und Updates, die Firmware 20+ benötigen, zum Laufen zu bringen.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Generieren</string> <string name="generate">Generieren</string>
@ -762,6 +764,13 @@ Wirklich fortfahren?</string>
<string name="emulation_exit">Emulation beenden</string> <string name="emulation_exit">Emulation beenden</string>
<string name="emulation_done">Fertig</string> <string name="emulation_done">Fertig</string>
<string name="emulation_fps_counter">FPS Zähler</string> <string name="emulation_fps_counter">FPS Zähler</string>
<string name="emulation_thermal_indicator"></string>
<string name="emulation_toggle_controls">Steuerung umschalten</string>
<string name="emulation_rel_stick_center">Relativer Stick-Zentrum</string>
<string name="emulation_dpad_slide">D-Pad-Scrollen</string>
<string name="emulation_haptics">Haptisches Feedback</string>
<string name="emulation_show_overlay">Controller anzeigen</string>
<string name="emulation_hide_overlay">Controller ausblenden</string>
<string name="emulation_toggle_all">Alle umschalten</string> <string name="emulation_toggle_all">Alle umschalten</string>
<string name="emulation_control_adjust">Overlay anpassen</string> <string name="emulation_control_adjust">Overlay anpassen</string>
<string name="emulation_control_scale">Größe</string> <string name="emulation_control_scale">Größe</string>

View file

@ -506,6 +506,8 @@
<string name="use_custom_rtc">RTC personalizado</string> <string name="use_custom_rtc">RTC personalizado</string>
<string name="use_custom_rtc_description">Te permite tener un reloj personalizado en tiempo real diferente del tiempo del propio sistema.</string> <string name="use_custom_rtc_description">Te permite tener un reloj personalizado en tiempo real diferente del tiempo del propio sistema.</string>
<string name="set_custom_rtc">Configurar RTC personalizado</string> <string name="set_custom_rtc">Configurar RTC personalizado</string>
<string name="disable_nca_verification">Desactivar verificación NCA</string>
<string name="disable_nca_verification_description">Desactiva la verificación de integridad de los archivos de contenido NCA. Esto puede mejorar la velocidad de carga, pero arriesga corrupción de datos o que archivos inválidos pasen desapercibidos. Es necesario para que funcionen juegos y actualizaciones que requieren firmware 20+.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Generar</string> <string name="generate">Generar</string>
@ -806,7 +808,8 @@
<string name="emulation_rel_stick_center">Centro relativo del stick</string> <string name="emulation_rel_stick_center">Centro relativo del stick</string>
<string name="emulation_dpad_slide">Deslizamiento de la cruceta</string> <string name="emulation_dpad_slide">Deslizamiento de la cruceta</string>
<string name="emulation_haptics">Toques hápticos</string> <string name="emulation_haptics">Toques hápticos</string>
<string name="emulation_show_overlay">Mostrar overlay</string> <string name="emulation_show_overlay">Mostrar controlador</string>
<string name="emulation_hide_overlay">Ocultar controlador</string>
<string name="emulation_toggle_all">Alternar todo</string> <string name="emulation_toggle_all">Alternar todo</string>
<string name="emulation_control_adjust">Ajustar overlay</string> <string name="emulation_control_adjust">Ajustar overlay</string>
<string name="emulation_control_scale">Escala</string> <string name="emulation_control_scale">Escala</string>

View file

@ -504,6 +504,8 @@
<string name="use_custom_rtc">زمان سفارشی</string> <string name="use_custom_rtc">زمان سفارشی</string>
<string name="use_custom_rtc_description">به شما امکان می‌دهد یک ساعت سفارشی جدا از زمان فعلی سیستم خود تنظیم کنید.</string> <string name="use_custom_rtc_description">به شما امکان می‌دهد یک ساعت سفارشی جدا از زمان فعلی سیستم خود تنظیم کنید.</string>
<string name="set_custom_rtc">تنظیم زمان سفارشی</string> <string name="set_custom_rtc">تنظیم زمان سفارشی</string>
<string name="disable_nca_verification">غیرفعال کردن تأیید اعتبار NCA</string>
<string name="disable_nca_verification_description">بررسی صحت آرشیوهای محتوای NCA را غیرفعال می‌کند. این ممکن است سرعت بارگذاری را بهبود بخشد اما خطر خرابی داده یا تشخیص داده نشدن فایل‌های نامعتبر را به همراه دارد. برای کار کردن بازی‌ها و به‌روزرسانی‌هایی که به فرمور ۲۰+ نیاز دارند، ضروری است.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">تولید</string> <string name="generate">تولید</string>
@ -805,7 +807,8 @@
<string name="emulation_rel_stick_center">مرکز نسبی استیک</string> <string name="emulation_rel_stick_center">مرکز نسبی استیک</string>
<string name="emulation_dpad_slide">لغزش دکمه‌های جهتی</string> <string name="emulation_dpad_slide">لغزش دکمه‌های جهتی</string>
<string name="emulation_haptics">لرزش لمسی</string> <string name="emulation_haptics">لرزش لمسی</string>
<string name="emulation_show_overlay">نشان دادن نمایش روی صفحه</string> <string name="emulation_show_overlay">نمایش کنترلر</string>
<string name="emulation_hide_overlay">پنهان کردن کنترلر</string>
<string name="emulation_toggle_all">تغییر همه</string> <string name="emulation_toggle_all">تغییر همه</string>
<string name="emulation_control_adjust">تنظیم نمایش روی صفحه</string> <string name="emulation_control_adjust">تنظیم نمایش روی صفحه</string>
<string name="emulation_control_scale">مقیاس</string> <string name="emulation_control_scale">مقیاس</string>

View file

@ -506,6 +506,8 @@
<string name="use_custom_rtc">RTC personnalisé</string> <string name="use_custom_rtc">RTC personnalisé</string>
<string name="use_custom_rtc_description">Vous permet de définir une horloge en temps réel personnalisée distincte de l\'heure actuelle de votre système.</string> <string name="use_custom_rtc_description">Vous permet de définir une horloge en temps réel personnalisée distincte de l\'heure actuelle de votre système.</string>
<string name="set_custom_rtc">Définir l\'horloge RTC personnalisée</string> <string name="set_custom_rtc">Définir l\'horloge RTC personnalisée</string>
<string name="disable_nca_verification">Désactiver la vérification NCA</string>
<string name="disable_nca_verification_description">Désactive la vérification d\'intégrité des archives de contenu NCA. Cela peut améliorer la vitesse de chargement mais risque une corruption des données ou que des fichiers invalides ne soient pas détectés. Est nécessaire pour faire fonctionner les jeux et mises à jour nécessitant un firmware 20+.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Générer</string> <string name="generate">Générer</string>
@ -854,7 +856,8 @@
<string name="emulation_rel_stick_center">Centre du stick relatif</string> <string name="emulation_rel_stick_center">Centre du stick relatif</string>
<string name="emulation_dpad_slide">Glissement du D-pad</string> <string name="emulation_dpad_slide">Glissement du D-pad</string>
<string name="emulation_haptics">Toucher haptique</string> <string name="emulation_haptics">Toucher haptique</string>
<string name="emulation_show_overlay">Afficher l\'overlay</string> <string name="emulation_show_overlay">Afficher la manette</string>
<string name="emulation_hide_overlay">Masquer la manette</string>
<string name="emulation_toggle_all">Tout basculer</string> <string name="emulation_toggle_all">Tout basculer</string>
<string name="emulation_control_adjust">Ajuster l\'overlay</string> <string name="emulation_control_adjust">Ajuster l\'overlay</string>
<string name="emulation_control_scale">Échelle</string> <string name="emulation_control_scale">Échelle</string>

View file

@ -505,6 +505,8 @@
<string name="use_custom_rtc">RTC מותאם אישית</string> <string name="use_custom_rtc">RTC מותאם אישית</string>
<string name="use_custom_rtc_description">מאפשר לך לקבוע שעון זמן אמת נפרד משעון המערכת שלך.</string> <string name="use_custom_rtc_description">מאפשר לך לקבוע שעון זמן אמת נפרד משעון המערכת שלך.</string>
<string name="set_custom_rtc">קבע RTC מותאם אישית</string> <string name="set_custom_rtc">קבע RTC מותאם אישית</string>
<string name="disable_nca_verification">השבת אימות NCA</string>
<string name="disable_nca_verification_description">משבית את אימות השלמות של ארכיוני התוכן של NCA. זה עשוי לשפר את מהירות הטעינה אך מסתכן בשחיקת נתונים או שמא קבצים לא חוקיים יעברו ללא זיהוי. זה הכרחי כדי לגרום למשחקים ועדכונים הדורשים firmware 20+ לעבוד.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">יצירה</string> <string name="generate">יצירה</string>
@ -739,7 +741,8 @@
<string name="emulation_rel_stick_center">מרכז ג׳ויסטיק יחסי</string> <string name="emulation_rel_stick_center">מרכז ג׳ויסטיק יחסי</string>
<string name="emulation_dpad_slide">החלקת D-pad</string> <string name="emulation_dpad_slide">החלקת D-pad</string>
<string name="emulation_haptics">רטט מגע</string> <string name="emulation_haptics">רטט מגע</string>
<string name="emulation_show_overlay">הצג את שכבת-העל</string> <string name="emulation_show_overlay">הצג בקר</string>
<string name="emulation_hide_overlay">הסתר בקר</string>
<string name="emulation_toggle_all">החלף הכל</string> <string name="emulation_toggle_all">החלף הכל</string>
<string name="emulation_control_adjust">התאם את שכבת-העל</string> <string name="emulation_control_adjust">התאם את שכבת-העל</string>
<string name="emulation_control_scale">קנה מידה</string> <string name="emulation_control_scale">קנה מידה</string>

View file

@ -501,6 +501,8 @@
<string name="use_custom_rtc">Egyéni RTC</string> <string name="use_custom_rtc">Egyéni RTC</string>
<string name="use_custom_rtc_description">Megadhatsz egy valós idejű órát, amely eltér a rendszer által használt órától.</string> <string name="use_custom_rtc_description">Megadhatsz egy valós idejű órát, amely eltér a rendszer által használt órától.</string>
<string name="set_custom_rtc">Egyéni RTC beállítása</string> <string name="set_custom_rtc">Egyéni RTC beállítása</string>
<string name="disable_nca_verification">NCA ellenőrzés letiltása</string>
<string name="disable_nca_verification_description">Letiltja az NCA tartalomarchívumok integritás-ellenőrzését. Ez javíthatja a betöltési sebességet, de az adatsérülés vagy az érvénytelen fájlok észrevétlen maradásának kockázatával jár. Elengedhetetlen a 20+ firmware-et igénylő játékok és frissítések működtetéséhez.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Generálás</string> <string name="generate">Generálás</string>
@ -843,7 +845,8 @@
<string name="emulation_toggle_controls">Irányítás átkapcsolása</string> <string name="emulation_toggle_controls">Irányítás átkapcsolása</string>
<string name="emulation_dpad_slide">D-pad csúsztatása</string> <string name="emulation_dpad_slide">D-pad csúsztatása</string>
<string name="emulation_haptics">Érintés haptikája</string> <string name="emulation_haptics">Érintés haptikája</string>
<string name="emulation_show_overlay">Átfedés mutatása</string> <string name="emulation_show_overlay">Vezérlő megjelenítése</string>
<string name="emulation_hide_overlay">Vezérlő elrejtése</string>
<string name="emulation_toggle_all">Összes átkapcsolása</string> <string name="emulation_toggle_all">Összes átkapcsolása</string>
<string name="emulation_control_adjust">Átfedés testreszabása</string> <string name="emulation_control_adjust">Átfedés testreszabása</string>
<string name="emulation_control_scale">Skálázás</string> <string name="emulation_control_scale">Skálázás</string>

View file

@ -502,6 +502,8 @@
<string name="use_custom_rtc">RTC Kustom</string> <string name="use_custom_rtc">RTC Kustom</string>
<string name="use_custom_rtc_description">Memungkinkan Anda untuk mengatur jam waktu nyata kustom yang terpisah dari waktu sistem saat ini Anda.</string> <string name="use_custom_rtc_description">Memungkinkan Anda untuk mengatur jam waktu nyata kustom yang terpisah dari waktu sistem saat ini Anda.</string>
<string name="set_custom_rtc">Setel RTC Kustom</string> <string name="set_custom_rtc">Setel RTC Kustom</string>
<string name="disable_nca_verification">Nonaktifkan Verifikasi NCA</string>
<string name="disable_nca_verification_description">Menonaktifkan verifikasi integritas arsip konten NCA. Ini dapat meningkatkan kecepatan pemuatan tetapi berisiko kerusakan data atau file yang tidak valid tidak terdeteksi. Diperlukan untuk membuat game dan pembaruan yang membutuhkan firmware 20+ bekerja.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Hasilkan</string> <string name="generate">Hasilkan</string>
@ -798,7 +800,8 @@
<string name="emulation_rel_stick_center">Pusat stick relatif</string> <string name="emulation_rel_stick_center">Pusat stick relatif</string>
<string name="emulation_dpad_slide">Geser Dpad</string> <string name="emulation_dpad_slide">Geser Dpad</string>
<string name="emulation_haptics">Haptik</string> <string name="emulation_haptics">Haptik</string>
<string name="emulation_show_overlay">Tampilkan Hamparan</string> <string name="emulation_show_overlay">Tampilkan Kontroler</string>
<string name="emulation_hide_overlay">Sembunyikan Kontroler</string>
<string name="emulation_toggle_all">Alihkan Semua</string> <string name="emulation_toggle_all">Alihkan Semua</string>
<string name="emulation_control_adjust">Menyesuaikan</string> <string name="emulation_control_adjust">Menyesuaikan</string>
<string name="emulation_control_scale">Skala</string> <string name="emulation_control_scale">Skala</string>

View file

@ -505,6 +505,8 @@
<string name="use_custom_rtc">RTC Personalizzato</string> <string name="use_custom_rtc">RTC Personalizzato</string>
<string name="use_custom_rtc_description">Ti permette di impostare un orologio in tempo reale personalizzato, completamente separato da quello di sistema.</string> <string name="use_custom_rtc_description">Ti permette di impostare un orologio in tempo reale personalizzato, completamente separato da quello di sistema.</string>
<string name="set_custom_rtc">Imposta un orologio in tempo reale personalizzato</string> <string name="set_custom_rtc">Imposta un orologio in tempo reale personalizzato</string>
<string name="disable_nca_verification">Disabilita verifica NCA</string>
<string name="disable_nca_verification_description">Disabilita la verifica dell\'integrità degli archivi di contenuto NCA. Può migliorare la velocità di caricamento ma rischia il danneggiamento dei dati o che file non validi passino inosservati. Necessario per far funzionare giochi e aggiornamenti che richiedono il firmware 20+.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Genera</string> <string name="generate">Genera</string>
@ -770,7 +772,8 @@
<string name="emulation_rel_stick_center">Centro relativo degli Stick</string> <string name="emulation_rel_stick_center">Centro relativo degli Stick</string>
<string name="emulation_dpad_slide">DPad A Scorrimento</string> <string name="emulation_dpad_slide">DPad A Scorrimento</string>
<string name="emulation_haptics">Feedback Aptico</string> <string name="emulation_haptics">Feedback Aptico</string>
<string name="emulation_show_overlay">Mostra l\'overlay</string> <string name="emulation_show_overlay">Mostra l\'controller</string>
<string name="emulation_hide_overlay">Nascondi l\'controller</string>
<string name="emulation_toggle_all">Attiva/Disattiva tutto</string> <string name="emulation_toggle_all">Attiva/Disattiva tutto</string>
<string name="emulation_control_adjust">Regola l\'overlay</string> <string name="emulation_control_adjust">Regola l\'overlay</string>
<string name="emulation_control_scale">Scala</string> <string name="emulation_control_scale">Scala</string>

View file

@ -491,6 +491,8 @@
<string name="use_custom_rtc">カスタム RTC</string> <string name="use_custom_rtc">カスタム RTC</string>
<string name="use_custom_rtc_description">現在のシステム時間とは別に、任意のリアルタイムクロックを設定できます。</string> <string name="use_custom_rtc_description">現在のシステム時間とは別に、任意のリアルタイムクロックを設定できます。</string>
<string name="set_custom_rtc">カスタムRTCを設定</string> <string name="set_custom_rtc">カスタムRTCを設定</string>
<string name="disable_nca_verification">NCA検証を無効化</string>
<string name="disable_nca_verification_description">NCAコンテンツアーカイブの整合性検証を無効にします。読み込み速度が向上する可能性がありますが、データ破損や不正なファイルが検出されないリスクがあります。ファームウェア20以上が必要なゲームや更新を動作させるために必要です。</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">生成</string> <string name="generate">生成</string>
@ -729,7 +731,8 @@
<string name="emulation_rel_stick_center">スティックを固定しない</string> <string name="emulation_rel_stick_center">スティックを固定しない</string>
<string name="emulation_dpad_slide">十字キーをスライド操作</string> <string name="emulation_dpad_slide">十字キーをスライド操作</string>
<string name="emulation_haptics">タッチ振動</string> <string name="emulation_haptics">タッチ振動</string>
<string name="emulation_show_overlay">ボタンを表示</string> <string name="emulation_show_overlay">コントローラーを表示</string>
<string name="emulation_hide_overlay">コントローラーを非表示</string>
<string name="emulation_toggle_all">すべて切替</string> <string name="emulation_toggle_all">すべて切替</string>
<string name="emulation_control_adjust">見た目を調整</string> <string name="emulation_control_adjust">見た目を調整</string>
<string name="emulation_control_scale">大きさ</string> <string name="emulation_control_scale">大きさ</string>

View file

@ -501,6 +501,8 @@
<string name="use_custom_rtc">사용자 지정 RTC</string> <string name="use_custom_rtc">사용자 지정 RTC</string>
<string name="use_custom_rtc_description">현재 시스템 시간과 별도로 사용자 지정 RTC를 설정할 수 있습니다.</string> <string name="use_custom_rtc_description">현재 시스템 시간과 별도로 사용자 지정 RTC를 설정할 수 있습니다.</string>
<string name="set_custom_rtc">사용자 지정 RTC 설정</string> <string name="set_custom_rtc">사용자 지정 RTC 설정</string>
<string name="disable_nca_verification">NCA 검증 비활성화</string>
<string name="disable_nca_verification_description">NCA 콘텐츠 아카이브의 무결성 검증을 비활성화합니다. 로딩 속도를 향상시킬 수 있지만 데이터 손상이나 유효하지 않은 파일이 미검증될 위험이 있습니다. 펌웨어 20+가 필요한 게임 및 업데이트를 실행하려면 필요합니다.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">생성</string> <string name="generate">생성</string>
@ -798,6 +800,7 @@
<string name="emulation_dpad_slide">십자키 슬라이드</string> <string name="emulation_dpad_slide">십자키 슬라이드</string>
<string name="emulation_haptics">터치 햅틱</string> <string name="emulation_haptics">터치 햅틱</string>
<string name="emulation_show_overlay">컨트롤러 표시</string> <string name="emulation_show_overlay">컨트롤러 표시</string>
<string name="emulation_hide_overlay">컨트롤러 숨기기</string>
<string name="emulation_toggle_all">모두 선택</string> <string name="emulation_toggle_all">모두 선택</string>
<string name="emulation_control_adjust">컨트롤러 조정</string> <string name="emulation_control_adjust">컨트롤러 조정</string>
<string name="emulation_control_scale">크기</string> <string name="emulation_control_scale">크기</string>

View file

@ -482,6 +482,8 @@
<string name="use_custom_rtc">Tilpasset Sannhetstidsklokke</string> <string name="use_custom_rtc">Tilpasset Sannhetstidsklokke</string>
<string name="use_custom_rtc_description">Gjør det mulig å stille inn en egendefinert sanntidsklokke separat fra den gjeldende systemtiden.</string> <string name="use_custom_rtc_description">Gjør det mulig å stille inn en egendefinert sanntidsklokke separat fra den gjeldende systemtiden.</string>
<string name="set_custom_rtc">Angi tilpasset RTC</string> <string name="set_custom_rtc">Angi tilpasset RTC</string>
<string name="disable_nca_verification">Deaktiver NCA-verifisering</string>
<string name="disable_nca_verification_description">Deaktiverer integritetsverifisering av NCA-innholdsarkiv. Dette kan forbedre lastehastigheten, men medfører risiko for datakorrupsjon eller at ugyldige filer ikke oppdages. Er nødvendig for å få spill og oppdateringer som trenger firmware 20+ til å fungere.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Generer</string> <string name="generate">Generer</string>
@ -720,7 +722,8 @@
<string name="emulation_rel_stick_center">Relativt pinnesenter</string> <string name="emulation_rel_stick_center">Relativt pinnesenter</string>
<string name="emulation_dpad_slide">D-pad-skyving</string> <string name="emulation_dpad_slide">D-pad-skyving</string>
<string name="emulation_haptics">Berøringshaptikk</string> <string name="emulation_haptics">Berøringshaptikk</string>
<string name="emulation_show_overlay">Vis overlegg</string> <string name="emulation_show_overlay">Vis kontroller</string>
<string name="emulation_hide_overlay">Skjul kontroller</string>
<string name="emulation_toggle_all">Veksle mellom alle</string> <string name="emulation_toggle_all">Veksle mellom alle</string>
<string name="emulation_control_adjust">Juster overlegg</string> <string name="emulation_control_adjust">Juster overlegg</string>
<string name="emulation_control_scale">Skaler</string> <string name="emulation_control_scale">Skaler</string>

View file

@ -482,6 +482,8 @@
<string name="use_custom_rtc">Niestandardowy RTC</string> <string name="use_custom_rtc">Niestandardowy RTC</string>
<string name="use_custom_rtc_description">Ta opcja pozwala na wybranie własnych ustawień czasu używanych w czasie emulacji, innych niż czas systemu Android.</string> <string name="use_custom_rtc_description">Ta opcja pozwala na wybranie własnych ustawień czasu używanych w czasie emulacji, innych niż czas systemu Android.</string>
<string name="set_custom_rtc">Ustaw niestandardowy czas RTC</string> <string name="set_custom_rtc">Ustaw niestandardowy czas RTC</string>
<string name="disable_nca_verification">Wyłącz weryfikację NCA</string>
<string name="disable_nca_verification_description">Wyłącza weryfikację integralności archiwów zawartości NCA. Może to poprawić szybkość ładowania, ale niesie ryzyko uszkodzenia danych lub niezauważenia nieprawidłowych plików. Konieczne, aby działały gry i aktualizacje wymagające firmware\'u 20+.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Generuj</string> <string name="generate">Generuj</string>
@ -718,7 +720,8 @@
<string name="emulation_rel_stick_center">Wycentruj gałki</string> <string name="emulation_rel_stick_center">Wycentruj gałki</string>
<string name="emulation_dpad_slide">Ruchomy D-pad</string> <string name="emulation_dpad_slide">Ruchomy D-pad</string>
<string name="emulation_haptics">Wibracje haptyczne</string> <string name="emulation_haptics">Wibracje haptyczne</string>
<string name="emulation_show_overlay">Pokaż przyciski</string> <string name="emulation_show_overlay">Pokaż kontroler</string>
<string name="emulation_hide_overlay">Ukryj kontroler</string>
<string name="emulation_toggle_all">Włącz wszystkie</string> <string name="emulation_toggle_all">Włącz wszystkie</string>
<string name="emulation_control_adjust">Dostosuj nakładkę</string> <string name="emulation_control_adjust">Dostosuj nakładkę</string>
<string name="emulation_control_scale">Skala</string> <string name="emulation_control_scale">Skala</string>

View file

@ -506,6 +506,8 @@
<string name="use_custom_rtc">Data e hora personalizadas</string> <string name="use_custom_rtc">Data e hora personalizadas</string>
<string name="use_custom_rtc_description">Permite a você configurar um relógio em tempo real separado do relógio do seu dispositivo.</string> <string name="use_custom_rtc_description">Permite a você configurar um relógio em tempo real separado do relógio do seu dispositivo.</string>
<string name="set_custom_rtc">Definir um relógio em tempo real personalizado</string> <string name="set_custom_rtc">Definir um relógio em tempo real personalizado</string>
<string name="disable_nca_verification">Desativar verificação NCA</string>
<string name="disable_nca_verification_description">Desativa a verificação de integridade de arquivos de conteúdo NCA. Pode melhorar a velocidade de carregamento, mas arrisica corromper dados ou que arquivos inválidos passem despercebidos. É necessário para fazer jogos e atualizações que exigem firmware 20+ funcionarem.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Gerar</string> <string name="generate">Gerar</string>
@ -855,7 +857,8 @@ uma tentativa de mapeamento automático</string>
<string name="emulation_rel_stick_center">Centro Relativo do Analógico</string> <string name="emulation_rel_stick_center">Centro Relativo do Analógico</string>
<string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string> <string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string>
<string name="emulation_haptics">Vibração ao tocar</string> <string name="emulation_haptics">Vibração ao tocar</string>
<string name="emulation_show_overlay">Mostrar overlay</string> <string name="emulation_show_overlay">Mostrar controle</string>
<string name="emulation_hide_overlay">Ocultar controle</string>
<string name="emulation_toggle_all">Marcar/Desmarcar tudo</string> <string name="emulation_toggle_all">Marcar/Desmarcar tudo</string>
<string name="emulation_control_adjust">Ajustar overlay</string> <string name="emulation_control_adjust">Ajustar overlay</string>
<string name="emulation_control_scale">Escala</string> <string name="emulation_control_scale">Escala</string>

View file

@ -506,6 +506,8 @@
<string name="use_custom_rtc">RTC personalizado</string> <string name="use_custom_rtc">RTC personalizado</string>
<string name="use_custom_rtc_description">Permite a você configurar um relógio em tempo real separado do relógio do seu dispositivo.</string> <string name="use_custom_rtc_description">Permite a você configurar um relógio em tempo real separado do relógio do seu dispositivo.</string>
<string name="set_custom_rtc">Defina um relógio em tempo real personalizado</string> <string name="set_custom_rtc">Defina um relógio em tempo real personalizado</string>
<string name="disable_nca_verification">Desativar verificação NCA</string>
<string name="disable_nca_verification_description">Desativa a verificação de integridade dos arquivos de conteúdo NCA. Pode melhorar a velocidade de carregamento, mas arrisca a corrupção de dados ou que ficheiros inválidos passem despercebidos. É necessário para que jogos e atualizações que necessitam de firmware 20+ funcionem.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Gerar</string> <string name="generate">Gerar</string>
@ -855,7 +857,8 @@ uma tentativa de mapeamento automático</string>
<string name="emulation_rel_stick_center">Centro Relativo de Analógico</string> <string name="emulation_rel_stick_center">Centro Relativo de Analógico</string>
<string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string> <string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string>
<string name="emulation_haptics">Vibração ao tocar</string> <string name="emulation_haptics">Vibração ao tocar</string>
<string name="emulation_show_overlay">Mostrar overlay</string> <string name="emulation_show_overlay">Mostrar comando</string>
<string name="emulation_hide_overlay">Ocultar comando</string>
<string name="emulation_toggle_all">Marcar/Desmarcar tudo</string> <string name="emulation_toggle_all">Marcar/Desmarcar tudo</string>
<string name="emulation_control_adjust">Ajustar overlay</string> <string name="emulation_control_adjust">Ajustar overlay</string>
<string name="emulation_control_scale">Escala</string> <string name="emulation_control_scale">Escala</string>

View file

@ -508,6 +508,8 @@
<string name="use_custom_rtc">Пользовательский RTC</string> <string name="use_custom_rtc">Пользовательский RTC</string>
<string name="use_custom_rtc_description">Позволяет установить пользовательские часы реального времени отдельно от текущего системного времени.</string> <string name="use_custom_rtc_description">Позволяет установить пользовательские часы реального времени отдельно от текущего системного времени.</string>
<string name="set_custom_rtc">Установить пользовательский RTC</string> <string name="set_custom_rtc">Установить пользовательский RTC</string>
<string name="disable_nca_verification">Отключить проверку NCA</string>
<string name="disable_nca_verification_description">Отключает проверку целостности архивов содержимого NCA. Может улучшить скорость загрузки, но есть риск повреждения данных или того, что недействительные файлы останутся незамеченными. Необходимо для работы игр и обновлений, требующих прошивку 20+.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Создать</string> <string name="generate">Создать</string>
@ -856,7 +858,8 @@
<string name="emulation_rel_stick_center">Относительный центр стика</string> <string name="emulation_rel_stick_center">Относительный центр стика</string>
<string name="emulation_dpad_slide">Слайд крестовиной</string> <string name="emulation_dpad_slide">Слайд крестовиной</string>
<string name="emulation_haptics">Обратная связь от нажатий</string> <string name="emulation_haptics">Обратная связь от нажатий</string>
<string name="emulation_show_overlay">Показать оверлей</string> <string name="emulation_show_overlay">Показать контроллер</string>
<string name="emulation_hide_overlay">Скрыть контроллер</string>
<string name="emulation_toggle_all">Переключить всё</string> <string name="emulation_toggle_all">Переключить всё</string>
<string name="emulation_control_adjust">Регулировка оверлея</string> <string name="emulation_control_adjust">Регулировка оверлея</string>
<string name="emulation_control_scale">Масштаб</string> <string name="emulation_control_scale">Масштаб</string>

View file

@ -457,6 +457,8 @@
<string name="use_custom_rtc">Цустом РТЦ</string> <string name="use_custom_rtc">Цустом РТЦ</string>
<string name="use_custom_rtc_description">Омогућава вам да поставите прилагођени сат у реалном времену одвојено од тренутног времена система.</string> <string name="use_custom_rtc_description">Омогућава вам да поставите прилагођени сат у реалном времену одвојено од тренутног времена система.</string>
<string name="set_custom_rtc">Подесите прилагођени РТЦ</string> <string name="set_custom_rtc">Подесите прилагођени РТЦ</string>
<string name="disable_nca_verification">Искључи верификацију НЦА</string>
<string name="disable_nca_verification_description">Искључује верификацију интегритета НЦА архива садржаја. Ово може побољшати брзину учитавања, али ризикује оштећење података или да неважећи фајлови прођу незапажено. Неопходно је да би игре и ажурирања која захтевају firmware 20+ радили.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Генериши</string> <string name="generate">Генериши</string>
@ -812,7 +814,8 @@
<string name="emulation_rel_stick_center">Релативни центар за штапић</string> <string name="emulation_rel_stick_center">Релативни центар за штапић</string>
<string name="emulation_dpad_slide">Д-Пад Слиде</string> <string name="emulation_dpad_slide">Д-Пад Слиде</string>
<string name="emulation_haptics">Додирните ХАптицс</string> <string name="emulation_haptics">Додирните ХАптицс</string>
<string name="emulation_show_overlay">Приказати прекривање</string> <string name="emulation_show_overlay">Приказати контролер</string>
<string name="emulation_hide_overlay">Сакрити контролер</string>
<string name="emulation_toggle_all">Пребацивати све</string> <string name="emulation_toggle_all">Пребацивати све</string>
<string name="emulation_control_adjust">Подесити прекривање</string> <string name="emulation_control_adjust">Подесити прекривање</string>
<string name="emulation_control_scale">Скала</string> <string name="emulation_control_scale">Скала</string>

View file

@ -495,6 +495,8 @@
<string name="use_custom_rtc">Свій RTC</string> <string name="use_custom_rtc">Свій RTC</string>
<string name="use_custom_rtc_description">Дозволяє встановити власний час (Real-time clock, або RTC), відмінний від системного.</string> <string name="use_custom_rtc_description">Дозволяє встановити власний час (Real-time clock, або RTC), відмінний від системного.</string>
<string name="set_custom_rtc">Встановити RTC</string> <string name="set_custom_rtc">Встановити RTC</string>
<string name="disable_nca_verification">Вимкнути перевірку NCA</string>
<string name="disable_nca_verification_description">Вимкає перевірку цілісності архівів вмісту NCA. Може покращити швидкість завантаження, але ризикує пошкодженням даних або тим, що недійсні файли залишаться непоміченими. Необхідно для роботи ігор та оновлень, які вимагають прошивки 20+.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Створити</string> <string name="generate">Створити</string>
@ -749,7 +751,8 @@
<string name="emulation_rel_stick_center">Відносний центр джойстика</string> <string name="emulation_rel_stick_center">Відносний центр джойстика</string>
<string name="emulation_dpad_slide">Ковзання D-pad</string> <string name="emulation_dpad_slide">Ковзання D-pad</string>
<string name="emulation_haptics">Тактильний відгук</string> <string name="emulation_haptics">Тактильний відгук</string>
<string name="emulation_show_overlay">Показати накладання</string> <string name="emulation_show_overlay">Показати контролер</string>
<string name="emulation_hide_overlay">Сховати контролер</string>
<string name="emulation_toggle_all">Перемкнути все</string> <string name="emulation_toggle_all">Перемкнути все</string>
<string name="emulation_control_adjust">Налаштувати накладання</string> <string name="emulation_control_adjust">Налаштувати накладання</string>
<string name="emulation_control_scale">Масштаб</string> <string name="emulation_control_scale">Масштаб</string>

View file

@ -482,6 +482,8 @@
<string name="use_custom_rtc">RTC tuỳ chỉnh</string> <string name="use_custom_rtc">RTC tuỳ chỉnh</string>
<string name="use_custom_rtc_description">Cho phép bạn thiết lập một đồng hồ thời gian thực tùy chỉnh riêng biệt so với thời gian hệ thống hiện tại.</string> <string name="use_custom_rtc_description">Cho phép bạn thiết lập một đồng hồ thời gian thực tùy chỉnh riêng biệt so với thời gian hệ thống hiện tại.</string>
<string name="set_custom_rtc">Thiết lập RTC tùy chỉnh</string> <string name="set_custom_rtc">Thiết lập RTC tùy chỉnh</string>
<string name="disable_nca_verification">Tắt xác minh NCA</string>
<string name="disable_nca_verification_description">Tắt xác minh tính toàn vẹn của kho lưu trữ nội dung NCA. Có thể cải thiện tốc độ tải nhưng có nguy cơ hỏng dữ liệu hoặc các tệp không hợp lệ không bị phát hiện. Cần thiết để các trò chơi và bản cập nhật yêu cầu firmware 20+ hoạt động.</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">Tạo</string> <string name="generate">Tạo</string>
@ -723,7 +725,8 @@
<string name="emulation_rel_stick_center">Trung tâm nút cần xoay tương đối</string> <string name="emulation_rel_stick_center">Trung tâm nút cần xoay tương đối</string>
<string name="emulation_dpad_slide">Trượt D-pad</string> <string name="emulation_dpad_slide">Trượt D-pad</string>
<string name="emulation_haptics">Chạm haptics</string> <string name="emulation_haptics">Chạm haptics</string>
<string name="emulation_show_overlay">Hiện lớp phủ</string> <string name="emulation_show_overlay">Hiện bộ điều khiển</string>
<string name="emulation_hide_overlay">Ẩn bộ điều khiển</string>
<string name="emulation_toggle_all">Chuyển đổi tất cả</string> <string name="emulation_toggle_all">Chuyển đổi tất cả</string>
<string name="emulation_control_adjust">Điều chỉnh lớp phủ</string> <string name="emulation_control_adjust">Điều chỉnh lớp phủ</string>
<string name="emulation_control_scale">Tỉ lệ thu phóng</string> <string name="emulation_control_scale">Tỉ lệ thu phóng</string>

View file

@ -500,6 +500,8 @@
<string name="use_custom_rtc">自定义系统时间</string> <string name="use_custom_rtc">自定义系统时间</string>
<string name="use_custom_rtc_description">此选项允许您设置与目前系统时间相独立的自定义系统时钟。</string> <string name="use_custom_rtc_description">此选项允许您设置与目前系统时间相独立的自定义系统时钟。</string>
<string name="set_custom_rtc">设置自定义系统时间</string> <string name="set_custom_rtc">设置自定义系统时间</string>
<string name="disable_nca_verification">禁用NCA验证</string>
<string name="disable_nca_verification_description">禁用NCA内容存档的完整性验证。可能会提高加载速度但存在数据损坏或无效文件未被检测到的风险。对于需要固件20+的游戏和更新是必需的。</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">生成</string> <string name="generate">生成</string>
@ -848,7 +850,8 @@
<string name="emulation_rel_stick_center">相对摇杆中心</string> <string name="emulation_rel_stick_center">相对摇杆中心</string>
<string name="emulation_dpad_slide">十字方向键滑动</string> <string name="emulation_dpad_slide">十字方向键滑动</string>
<string name="emulation_haptics">触觉反馈</string> <string name="emulation_haptics">触觉反馈</string>
<string name="emulation_show_overlay">显示虚拟按键</string> <string name="emulation_show_overlay">显示控制器</string>
<string name="emulation_hide_overlay">隐藏控制器</string>
<string name="emulation_toggle_all">全部切换</string> <string name="emulation_toggle_all">全部切换</string>
<string name="emulation_control_adjust">调整虚拟按键</string> <string name="emulation_control_adjust">调整虚拟按键</string>
<string name="emulation_control_scale">缩放</string> <string name="emulation_control_scale">缩放</string>

View file

@ -505,6 +505,8 @@
<string name="use_custom_rtc">自訂 RTC</string> <string name="use_custom_rtc">自訂 RTC</string>
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂即時時鐘。</string> <string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂即時時鐘。</string>
<string name="set_custom_rtc">設定自訂 RTC</string> <string name="set_custom_rtc">設定自訂 RTC</string>
<string name="disable_nca_verification">停用NCA驗證</string>
<string name="disable_nca_verification_description">停用NCA內容存檔的完整性驗證。可能會提高載入速度但存在資料損毀或無效檔案未被偵測到的風險。對於需要韌體20+的遊戲和更新是必需的。</string>
<!-- Network settings strings --> <!-- Network settings strings -->
<string name="generate">生成</string> <string name="generate">生成</string>
@ -853,7 +855,8 @@
<string name="emulation_rel_stick_center">相對搖桿中心</string> <string name="emulation_rel_stick_center">相對搖桿中心</string>
<string name="emulation_dpad_slide">方向鍵滑動</string> <string name="emulation_dpad_slide">方向鍵滑動</string>
<string name="emulation_haptics">觸覺回饋技術</string> <string name="emulation_haptics">觸覺回饋技術</string>
<string name="emulation_show_overlay">顯示覆疊</string> <string name="emulation_show_overlay">顯示控制器</string>
<string name="emulation_hide_overlay">隱藏控制器</string>
<string name="emulation_toggle_all">全部切換</string> <string name="emulation_toggle_all">全部切換</string>
<string name="emulation_control_adjust">調整覆疊</string> <string name="emulation_control_adjust">調整覆疊</string>
<string name="emulation_control_scale">縮放</string> <string name="emulation_control_scale">縮放</string>

View file

@ -474,6 +474,8 @@
<string name="use_custom_rtc">Custom RTC</string> <string name="use_custom_rtc">Custom RTC</string>
<string name="use_custom_rtc_description">Allows you to set a custom real-time clock separate from your current system time.</string> <string name="use_custom_rtc_description">Allows you to set a custom real-time clock separate from your current system time.</string>
<string name="set_custom_rtc">Set custom RTC</string> <string name="set_custom_rtc">Set custom RTC</string>
<string name="disable_nca_verification">Disable NCA Verification</string>
<string name="disable_nca_verification_description">Disables integrity verification of NCA content archives. This may improve loading speed but risks data corruption or invalid files going undetected. Some games that require firmware versions 20+ may need this as well.</string>
<string name="generate">Generate</string> <string name="generate">Generate</string>
@ -782,6 +784,9 @@
<string name="loader_requires_firmware">Game Requires Firmware</string> <string name="loader_requires_firmware">Game Requires Firmware</string>
<string name="loader_requires_firmware_description"><![CDATA[The game you are trying to launch requires firmware to boot or to get past the opening menu. Please <a href="https://yuzu-mirror.github.io/help/quickstart"> dump and install firmware</a>, or press "OK" to launch anyways.]]></string> <string name="loader_requires_firmware_description"><![CDATA[The game you are trying to launch requires firmware to boot or to get past the opening menu. Please <a href="https://yuzu-mirror.github.io/help/quickstart"> dump and install firmware</a>, or press "OK" to launch anyways.]]></string>
<string name="nca_verification_disabled">NCA Verification Disabled</string>
<string name="nca_verification_disabled_description">This is required to run new games and updates, but may cause instability or crashes if NCA files are corrupt, modified, or tampered with. If unsure, re-enable verification in Advanced Settings -> System, and use firmware versions of 19.0.1 or below.</string>
<!-- Intent Launch strings --> <!-- Intent Launch strings -->
<string name="searching_for_game">Searching for game...</string> <string name="searching_for_game">Searching for game...</string>
<string name="game_not_found_for_title_id">Game not found for Title ID: %1$s</string> <string name="game_not_found_for_title_id">Game not found for Title ID: %1$s</string>
@ -835,7 +840,8 @@
<string name="emulation_rel_stick_center">Relative stick center</string> <string name="emulation_rel_stick_center">Relative stick center</string>
<string name="emulation_dpad_slide">D-pad slide</string> <string name="emulation_dpad_slide">D-pad slide</string>
<string name="emulation_haptics">Touch haptics</string> <string name="emulation_haptics">Touch haptics</string>
<string name="emulation_show_overlay">Show overlay</string> <string name="emulation_show_overlay">Show controller</string>
<string name="emulation_hide_overlay">Hide controller</string>
<string name="emulation_toggle_all">Toggle all</string> <string name="emulation_toggle_all">Toggle all</string>
<string name="emulation_control_adjust">Adjust overlay</string> <string name="emulation_control_adjust">Adjust overlay</string>
<string name="emulation_control_scale">Scale</string> <string name="emulation_control_scale">Scale</string>

View file

@ -13,7 +13,7 @@
#include "common/polyfill_ranges.h" #include "common/polyfill_ranges.h"
namespace AudioCore { namespace AudioCore {
constexpr u32 CurrentRevision = 13; constexpr u32 CurrentRevision = 15;
enum class SupportTags { enum class SupportTags {
CommandProcessingTimeEstimatorVersion4, CommandProcessingTimeEstimatorVersion4,

View file

@ -262,23 +262,18 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
endif() endif()
if (BOOST_NO_HEADERS) if (BOOST_NO_HEADERS)
target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool) target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool)
else() else()
target_link_libraries(common PUBLIC Boost::headers) target_link_libraries(common PUBLIC Boost::headers)
endif() endif()
if (lz4_ADDED) if (lz4_ADDED)
target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib) target_include_directories(common PRIVATE ${lz4_SOURCE_DIR}/lib)
endif() endif()
target_link_libraries(common PUBLIC fmt::fmt stb::headers Threads::Threads) target_link_libraries(common PUBLIC fmt::fmt stb::headers Threads::Threads)
target_link_libraries(common PRIVATE lz4::lz4 LLVM::Demangle zstd::zstd) target_link_libraries(common PRIVATE lz4::lz4 LLVM::Demangle zstd::zstd)
if (TARGET unordered_dense::unordered_dense)
# weird quirk of system installs
target_link_libraries(common PUBLIC unordered_dense::unordered_dense)
endif()
if(ANDROID) if(ANDROID)
# For ASharedMemory_create # For ASharedMemory_create
target_link_libraries(common PRIVATE android) target_link_libraries(common PRIVATE android)

View file

@ -1,5 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -35,60 +33,68 @@ HeapTracker::~HeapTracker() = default;
void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length,
MemoryPermission perm, bool is_separate_heap) { MemoryPermission perm, bool is_separate_heap) {
bool rebuild_required = false;
// When mapping other memory, map pages immediately. // When mapping other memory, map pages immediately.
if (!is_separate_heap) { if (!is_separate_heap) {
m_buffer.Map(virtual_offset, host_offset, length, perm, false); m_buffer.Map(virtual_offset, host_offset, length, perm, false);
return; return;
} }
{ {
// We are mapping part of a separate heap and insert into mappings. // We are mapping part of a separate heap.
std::scoped_lock lk{m_lock}; std::scoped_lock lk{m_lock};
m_map_count++;
const auto it = m_mappings.insert_or_assign(virtual_offset, SeparateHeapMap{ auto* const map = new SeparateHeapMap{
.vaddr = virtual_offset,
.paddr = host_offset, .paddr = host_offset,
.size = length, .size = length,
.tick = m_tick++, .tick = m_tick++,
.perm = perm, .perm = perm,
.is_resident = false, .is_resident = false,
}); };
// Update tick before possible rebuild.
it.first->second.tick = m_tick++; // Insert into mappings.
// Check if we need to rebuild. m_map_count++;
if (m_resident_map_count >= m_max_resident_map_count) m_mappings.insert(*map);
rebuild_required = true;
// Map the area.
m_buffer.Map(it.first->first, it.first->second.paddr, it.first->second.size, it.first->second.perm, false);
// This map is now resident.
it.first->second.is_resident = true;
m_resident_map_count++;
m_resident_mappings.insert(*it.first);
} }
// A rebuild was required, so perform it now.
if (rebuild_required) // Finally, map.
this->RebuildSeparateHeapAddressSpace(); this->DeferredMapSeparateHeap(virtual_offset);
} }
void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) { void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) {
// If this is a separate heap... // If this is a separate heap...
if (is_separate_heap) { if (is_separate_heap) {
std::scoped_lock lk{m_lock}; std::scoped_lock lk{m_lock};
const SeparateHeapMap key{
.vaddr = virtual_offset,
};
// Split at the boundaries of the region we are removing. // Split at the boundaries of the region we are removing.
this->SplitHeapMapLocked(virtual_offset); this->SplitHeapMapLocked(virtual_offset);
this->SplitHeapMapLocked(virtual_offset + size); this->SplitHeapMapLocked(virtual_offset + size);
// Erase all mappings in range. // Erase all mappings in range.
auto it = m_mappings.find(virtual_offset); auto it = m_mappings.find(key);
while (it != m_mappings.end() && it->first < virtual_offset + size) { while (it != m_mappings.end() && it->vaddr < virtual_offset + size) {
// Get underlying item.
auto* const item = std::addressof(*it);
// If resident, erase from resident map. // If resident, erase from resident map.
if (it->second.is_resident) { if (item->is_resident) {
ASSERT(--m_resident_map_count >= 0); ASSERT(--m_resident_map_count >= 0);
m_resident_mappings.erase(m_resident_mappings.find(it->first)); m_resident_mappings.erase(m_resident_mappings.iterator_to(*item));
} }
// Erase from map. // Erase from map.
ASSERT(--m_map_count >= 0); ASSERT(--m_map_count >= 0);
it = m_mappings.erase(it); it = m_mappings.erase(it);
// Free the item.
delete item;
} }
} }
// Unmap pages. // Unmap pages.
m_buffer.Unmap(virtual_offset, size, false); m_buffer.Unmap(virtual_offset, size, false);
} }
@ -110,51 +116,110 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p
{ {
std::scoped_lock lk2{m_lock}; std::scoped_lock lk2{m_lock};
const SeparateHeapMap key{
.vaddr = next,
};
// Try to get the next mapping corresponding to this address. // Try to get the next mapping corresponding to this address.
const auto it = m_mappings.find(next); const auto it = m_mappings.nfind(key);
if (it == m_mappings.end()) { if (it == m_mappings.end()) {
// There are no separate heap mappings remaining. // There are no separate heap mappings remaining.
next = end; next = end;
should_protect = true; should_protect = true;
} else if (it->first == cur) { } else if (it->vaddr == cur) {
// We are in range. // We are in range.
// Update permission bits. // Update permission bits.
it->second.perm = perm; it->perm = perm;
// Determine next address and whether we should protect. // Determine next address and whether we should protect.
next = cur + it->second.size; next = cur + it->size;
should_protect = it->second.is_resident; should_protect = it->is_resident;
} else /* if (it->vaddr > cur) */ { } else /* if (it->vaddr > cur) */ {
// We weren't in range, but there is a block coming up that will be. // We weren't in range, but there is a block coming up that will be.
next = it->first; next = it->vaddr;
should_protect = true; should_protect = true;
} }
} }
// Clamp to end. // Clamp to end.
next = std::min(next, end); next = std::min(next, end);
// Reprotect, if we need to. // Reprotect, if we need to.
if (should_protect) if (should_protect) {
m_buffer.Protect(cur, next - cur, perm); m_buffer.Protect(cur, next - cur, perm);
}
// Advance. // Advance.
cur = next; cur = next;
} }
} }
bool HeapTracker::DeferredMapSeparateHeap(u8* fault_address) {
if (m_buffer.IsInVirtualRange(fault_address)) {
return this->DeferredMapSeparateHeap(fault_address - m_buffer.VirtualBasePointer());
}
return false;
}
bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) {
bool rebuild_required = false;
{
std::scoped_lock lk{m_lock};
// Check to ensure this was a non-resident separate heap mapping.
const auto it = this->GetNearestHeapMapLocked(virtual_offset);
if (it == m_mappings.end() || it->is_resident) {
return false;
}
// Update tick before possible rebuild.
it->tick = m_tick++;
// Check if we need to rebuild.
if (m_resident_map_count > m_max_resident_map_count) {
rebuild_required = true;
}
// Map the area.
m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false);
// This map is now resident.
it->is_resident = true;
m_resident_map_count++;
m_resident_mappings.insert(*it);
}
if (rebuild_required) {
// A rebuild was required, so perform it now.
this->RebuildSeparateHeapAddressSpace();
}
return true;
}
void HeapTracker::RebuildSeparateHeapAddressSpace() { void HeapTracker::RebuildSeparateHeapAddressSpace() {
std::scoped_lock lk{m_rebuild_lock, m_lock}; std::scoped_lock lk{m_rebuild_lock, m_lock};
ASSERT(!m_resident_mappings.empty()); ASSERT(!m_resident_mappings.empty());
// Dump half of the mappings. // Dump half of the mappings.
//
// Despite being worse in theory, this has proven to be better in practice than more // 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 // regularly dumping a smaller amount, because it significantly reduces average case
// lock contention. // lock contention.
std::size_t const desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2; const size_t 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 evict_count = m_resident_map_count - desired_count;
auto it = m_resident_mappings.begin(); auto it = m_resident_mappings.begin();
for (std::size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) {
for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) {
// Unmark and unmap. // Unmark and unmap.
it->second.is_resident = false; it->is_resident = false;
m_buffer.Unmap(it->first, it->second.size, false); m_buffer.Unmap(it->vaddr, it->size, false);
// Advance. // Advance.
ASSERT(--m_resident_map_count >= 0); ASSERT(--m_resident_map_count >= 0);
it = m_resident_mappings.erase(it); it = m_resident_mappings.erase(it);
@ -163,32 +228,53 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() {
void HeapTracker::SplitHeapMap(VAddr offset, size_t size) { void HeapTracker::SplitHeapMap(VAddr offset, size_t size) {
std::scoped_lock lk{m_lock}; std::scoped_lock lk{m_lock};
this->SplitHeapMapLocked(offset); this->SplitHeapMapLocked(offset);
this->SplitHeapMapLocked(offset + size); this->SplitHeapMapLocked(offset + size);
} }
void HeapTracker::SplitHeapMapLocked(VAddr offset) { void HeapTracker::SplitHeapMapLocked(VAddr offset) {
auto it = this->GetNearestHeapMapLocked(offset); const auto it = this->GetNearestHeapMapLocked(offset);
if (it != m_mappings.end() && it->first != offset) { if (it == m_mappings.end() || it->vaddr == offset) {
// Adjust left iterator // Not contained or no split required.
auto const orig_size = it->second.size; return;
auto const left_size = offset - it->first; }
it->second.size = left_size;
// Insert the new right map. // Cache the original values.
auto const right = SeparateHeapMap{ auto* const left = std::addressof(*it);
.paddr = it->second.paddr + left_size, const size_t orig_size = left->size;
.size = orig_size - left_size,
.tick = it->second.tick, // Adjust the left map.
.perm = it->second.perm, const size_t left_size = offset - left->vaddr;
.is_resident = it->second.is_resident, left->size = left_size;
};
m_map_count++; // Create the new right map.
auto rit = m_mappings.insert_or_assign(it->first + left_size, right); auto* const right = new SeparateHeapMap{
if (rit.first->second.is_resident) { .vaddr = left->vaddr + left_size,
m_resident_map_count++; .paddr = left->paddr + left_size,
m_resident_mappings.insert(*rit.first); .size = orig_size - left_size,
} .tick = left->tick,
.perm = left->perm,
.is_resident = left->is_resident,
};
// Insert the new right map.
m_map_count++;
m_mappings.insert(*right);
// If resident, also insert into resident map.
if (right->is_resident) {
m_resident_map_count++;
m_resident_mappings.insert(*right);
} }
} }
HeapTracker::AddrTree::iterator HeapTracker::GetNearestHeapMapLocked(VAddr offset) {
const SeparateHeapMap key{
.vaddr = offset,
};
return m_mappings.find(key);
}
} // namespace Common } // namespace Common

View file

@ -1,55 +1,93 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include <atomic>
#include <mutex> #include <mutex>
#include <set>
#include <shared_mutex> #include <shared_mutex>
#include <ankerl/unordered_dense.h>
#include "common/host_memory.h" #include "common/host_memory.h"
#include "common/intrusive_red_black_tree.h"
namespace Common { namespace Common {
struct SeparateHeapMap { struct SeparateHeapMap {
PAddr paddr{}; //8 Common::IntrusiveRedBlackTreeNode addr_node{};
std::size_t size{}; //8 (16) Common::IntrusiveRedBlackTreeNode tick_node{};
std::size_t tick{}; //8 (24) VAddr vaddr{};
// 4 bits needed, sync with host_memory.h if needed PAddr paddr{};
MemoryPermission perm : 4 = MemoryPermission::Read; size_t size{};
bool is_resident : 1 = false; size_t tick{};
MemoryPermission perm{};
bool is_resident{};
};
struct SeparateHeapMapAddrComparator {
static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) {
if (lhs.vaddr < rhs.vaddr) {
return -1;
} else if (lhs.vaddr <= (rhs.vaddr + rhs.size - 1)) {
return 0;
} else {
return 1;
}
}
};
struct SeparateHeapMapTickComparator {
static constexpr int Compare(const SeparateHeapMap& lhs, const SeparateHeapMap& rhs) {
if (lhs.tick < rhs.tick) {
return -1;
} else if (lhs.tick > rhs.tick) {
return 1;
} else {
return SeparateHeapMapAddrComparator::Compare(lhs, rhs);
}
}
}; };
static_assert(sizeof(SeparateHeapMap) == 32); //half a cache line! good for coherency
class HeapTracker { class HeapTracker {
public: public:
explicit HeapTracker(Common::HostMemory& buffer); explicit HeapTracker(Common::HostMemory& buffer);
~HeapTracker(); ~HeapTracker();
void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, bool is_separate_heap);
void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm,
bool is_separate_heap);
void Unmap(size_t virtual_offset, size_t size, bool is_separate_heap); void Unmap(size_t virtual_offset, size_t size, bool is_separate_heap);
void Protect(size_t virtual_offset, size_t length, MemoryPermission perm); void Protect(size_t virtual_offset, size_t length, MemoryPermission perm);
inline u8* VirtualBasePointer() noexcept { u8* VirtualBasePointer() {
return m_buffer.VirtualBasePointer(); return m_buffer.VirtualBasePointer();
} }
bool DeferredMapSeparateHeap(u8* fault_address);
bool DeferredMapSeparateHeap(size_t virtual_offset);
private: private:
// TODO: You may want to "fake-map" the first 2GB of 64-bit address space using AddrTreeTraits =
// and dedicate it entirely to a recursive PTE mapping :) Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::addr_node>;
// However Ankerl is way better than using an RB tree, in all senses using AddrTree = AddrTreeTraits::TreeType<SeparateHeapMapAddrComparator>;
using AddrTree = ankerl::unordered_dense::map<VAddr, SeparateHeapMap>;
AddrTree m_mappings; using TickTreeTraits =
using TicksTree = ankerl::unordered_dense::map<VAddr, SeparateHeapMap>; Common::IntrusiveRedBlackTreeMemberTraitsDeferredAssert<&SeparateHeapMap::tick_node>;
TicksTree m_resident_mappings; using TickTree = TickTreeTraits::TreeType<SeparateHeapMapTickComparator>;
AddrTree m_mappings{};
TickTree m_resident_mappings{};
private: private:
void SplitHeapMap(VAddr offset, size_t size); void SplitHeapMap(VAddr offset, size_t size);
void SplitHeapMapLocked(VAddr offset); void SplitHeapMapLocked(VAddr offset);
AddrTree::iterator GetNearestHeapMapLocked(VAddr offset);
void RebuildSeparateHeapAddressSpace(); void RebuildSeparateHeapAddressSpace();
inline HeapTracker::AddrTree::iterator GetNearestHeapMapLocked(VAddr offset) noexcept {
return m_mappings.find(offset);
}
private: private:
Common::HostMemory& m_buffer; Common::HostMemory& m_buffer;
const s64 m_max_resident_map_count; const s64 m_max_resident_map_count;
std::shared_mutex m_rebuild_lock{}; std::shared_mutex m_rebuild_lock{};
std::mutex m_lock{}; std::mutex m_lock{};
s64 m_map_count{}; s64 m_map_count{};

View file

@ -12,7 +12,7 @@
#include <windows.h> #include <windows.h>
#include "common/dynamic_library.h" #include "common/dynamic_library.h"
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) // ^^^ Windows ^^^ vvv Linux vvv #elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__) // ^^^ Windows ^^^ vvv POSIX vvv
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
@ -20,10 +20,18 @@
#include <boost/icl/interval_set.hpp> #include <boost/icl/interval_set.hpp>
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/random.h>
#include <unistd.h> #include <unistd.h>
#include "common/scope_exit.h" #include "common/scope_exit.h"
#if defined(__linux__)
#include <sys/random.h>
#elif defined(__APPLE__)
#include <sys/types.h>
#include <sys/random.h>
#include <mach/vm_map.h>
#include <mach/mach.h>
#endif
// FreeBSD // FreeBSD
#ifndef MAP_NORESERVE #ifndef MAP_NORESERVE
#define MAP_NORESERVE 0 #define MAP_NORESERVE 0
@ -32,8 +40,12 @@
#ifndef MAP_ALIGNED_SUPER #ifndef MAP_ALIGNED_SUPER
#define MAP_ALIGNED_SUPER 0 #define MAP_ALIGNED_SUPER 0
#endif #endif
// macOS
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
#endif // ^^^ Linux ^^^ #endif // ^^^ POSIX ^^^
#include <mutex> #include <mutex>
#include <random> #include <random>
@ -372,7 +384,7 @@ private:
std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset
}; };
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) // ^^^ Windows ^^^ vvv Linux vvv #elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__) // ^^^ Windows ^^^ vvv POSIX vvv
#ifdef ARCHITECTURE_arm64 #ifdef ARCHITECTURE_arm64
@ -417,14 +429,11 @@ static void* ChooseVirtualBase(size_t virtual_size) {
#else #else
static void* ChooseVirtualBase(size_t virtual_size) { static void* ChooseVirtualBase(size_t virtual_size) {
#if defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__managarm__) #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__managarm__) || defined(__AIX__)
void* virtual_base = mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER, -1, 0); void* virtual_base = mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER, -1, 0);
if (virtual_base != MAP_FAILED)
if (virtual_base != MAP_FAILED) {
return virtual_base; return virtual_base;
}
#endif #endif
return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
} }
@ -492,6 +501,13 @@ public:
#elif defined(__FreeBSD__) && __FreeBSD__ < 13 #elif defined(__FreeBSD__) && __FreeBSD__ < 13
// XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
fd = shm_open(SHM_ANON, O_RDWR, 0600); fd = shm_open(SHM_ANON, O_RDWR, 0600);
#elif defined(__APPLE__)
// macOS doesn't have memfd_create, use anonymous temporary file
char template_path[] = "/tmp/eden_mem_XXXXXX";
fd = mkstemp(template_path);
if (fd >= 0) {
unlink(template_path);
}
#else #else
fd = memfd_create("HostMemory", 0); fd = memfd_create("HostMemory", 0);
#endif #endif
@ -648,7 +664,7 @@ private:
FreeRegionManager free_manager{}; FreeRegionManager free_manager{};
}; };
#else // ^^^ Linux ^^^ vvv Generic vvv #else // ^^^ POSIX ^^^ vvv Generic vvv
class HostMemory::Impl { class HostMemory::Impl {
public: public:

View file

@ -163,8 +163,9 @@ bool IsFastmemEnabled() {
} }
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__)
return false; return false;
#endif #else
return true; return true;
#endif
} }
static bool is_nce_enabled = false; static bool is_nce_enabled = false;

View file

@ -217,7 +217,8 @@ struct Values {
true, true,
true, true,
&use_speed_limit}; &use_speed_limit};
SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core, Specialization::Default}; SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core,
Specialization::Default};
// Memory // Memory
#ifdef HAS_NCE #ifdef HAS_NCE
@ -551,6 +552,8 @@ struct Values {
3, 3,
#elif defined (ANDROID) #elif defined (ANDROID)
0, 0,
#elif defined (__APPLE__)
0,
#else #else
2, 2,
#endif #endif
@ -622,7 +625,11 @@ struct Values {
linkage, 0, "rng_seed", Category::System, Specialization::Hex, linkage, 0, "rng_seed", Category::System, Specialization::Hex,
true, true, &rng_seed_enabled}; true, true, &rng_seed_enabled};
Setting<std::string> device_name{ Setting<std::string> device_name{
linkage, "Eden", "device_name", Category::System, Specialization::Default, true, true}; linkage, "Eden", "device_name", Category::System, Specialization::Default, true, true};
SwitchableSetting<bool> disable_nca_verification{linkage, true, "disable_nca_verification",
Category::System, Specialization::Default};
Setting<bool> hide_nca_verification_popup{
linkage, false, "hide_nca_verification_popup", Category::System, Specialization::Default};
Setting<s32> current_user{linkage, 0, "current_user", Category::System}; Setting<s32> current_user{linkage, 0, "current_user", Category::System};

View file

@ -7,6 +7,7 @@
#pragma once #pragma once
#include <algorithm>
#include <cstddef> #include <cstddef>
#include <span> #include <span>
#include <string> #include <string>

View file

@ -88,6 +88,8 @@ add_library(core STATIC
file_sys/fssystem/fssystem_crypto_configuration.h file_sys/fssystem/fssystem_crypto_configuration.h
file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.cpp file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.cpp
file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h
file_sys/fssystem/fssystem_hierarchical_sha3_storage.cpp
file_sys/fssystem/fssystem_hierarchical_sha3_storage.h
file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp file_sys/fssystem/fssystem_hierarchical_sha256_storage.cpp
file_sys/fssystem/fssystem_hierarchical_sha256_storage.h file_sys/fssystem/fssystem_hierarchical_sha256_storage.h
file_sys/fssystem/fssystem_indirect_storage.cpp file_sys/fssystem/fssystem_indirect_storage.cpp
@ -102,6 +104,7 @@ add_library(core STATIC
file_sys/fssystem/fssystem_nca_header.cpp file_sys/fssystem/fssystem_nca_header.cpp
file_sys/fssystem/fssystem_nca_header.h file_sys/fssystem/fssystem_nca_header.h
file_sys/fssystem/fssystem_nca_reader.cpp file_sys/fssystem/fssystem_nca_reader.cpp
file_sys/fssystem/fssystem_passthrough_storage.h
file_sys/fssystem/fssystem_pooled_buffer.cpp file_sys/fssystem/fssystem_pooled_buffer.cpp
file_sys/fssystem/fssystem_pooled_buffer.h file_sys/fssystem/fssystem_pooled_buffer.h
file_sys/fssystem/fssystem_sparse_storage.cpp file_sys/fssystem/fssystem_sparse_storage.cpp

View file

@ -3,9 +3,47 @@
#ifdef __linux__ #ifdef __linux__
//#include "common/signal_chain.h" #include "common/signal_chain.h"
#include "core/arm/dynarmic/arm_dynarmic.h" #include "core/arm/dynarmic/arm_dynarmic.h"
//#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
//#include "core/memory.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 #endif

View file

@ -26,4 +26,24 @@ constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) {
return static_cast<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 } // namespace Core

View file

@ -343,11 +343,15 @@ bool ArmDynarmic32::IsInThumbMode() const {
} }
HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) { HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState(); m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Run()); return TranslateHaltReason(m_jit->Run());
} }
HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) { HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState(); m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Step()); return TranslateHaltReason(m_jit->Step());
} }
@ -389,6 +393,7 @@ ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProc
m_cp15(std::make_shared<DynarmicCP15>(*this)), m_core_index{core_index} { m_cp15(std::make_shared<DynarmicCP15>(*this)), m_core_index{core_index} {
auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl(); auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl();
m_jit = MakeJit(&page_table_impl); m_jit = MakeJit(&page_table_impl);
ScopedJitExecution::RegisterHandler();
} }
ArmDynarmic32::~ArmDynarmic32() = default; ArmDynarmic32::~ArmDynarmic32() = default;

View file

@ -374,11 +374,15 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
} }
HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) { HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState(); m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Run()); return TranslateHaltReason(m_jit->Run());
} }
HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) { HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) {
ScopedJitExecution sj(thread->GetOwnerProcess());
m_jit->ClearExclusiveState(); m_jit->ClearExclusiveState();
return TranslateHaltReason(m_jit->Step()); return TranslateHaltReason(m_jit->Step());
} }
@ -418,6 +422,7 @@ ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProc
auto& page_table = process->GetPageTable().GetBasePageTable(); auto& page_table = process->GetPageTable().GetBasePageTable();
auto& page_table_impl = page_table.GetImpl(); auto& page_table_impl = page_table.GetImpl();
m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth()); m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth());
ScopedJitExecution::RegisterHandler();
} }
ArmDynarmic64::~ArmDynarmic64() = default; ArmDynarmic64::~ArmDynarmic64() = default;

View file

@ -1,6 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree.h" #include "core/file_sys/fssystem/fssystem_bucket_tree.h"
#include "core/file_sys/fssystem/fssystem_bucket_tree_utils.h" #include "core/file_sys/fssystem/fssystem_bucket_tree_utils.h"
@ -233,7 +237,10 @@ Result BucketTree::Initialize(VirtualFile node_storage, VirtualFile entry_storag
void BucketTree::Initialize(size_t node_size, s64 end_offset) { void BucketTree::Initialize(size_t node_size, s64 end_offset) {
ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax); ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax);
ASSERT(Common::IsPowerOfTwo(node_size)); ASSERT(Common::IsPowerOfTwo(node_size));
ASSERT(end_offset > 0);
if (!Settings::values.disable_nca_verification.GetValue()) {
ASSERT(end_offset > 0);
}
ASSERT(!this->IsInitialized()); ASSERT(!this->IsInitialized());
m_node_size = node_size; m_node_size = node_size;

View file

@ -5,23 +5,10 @@
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h" #include "core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h"
#include <cmath>
namespace FileSys { namespace FileSys {
namespace {
s32 Log2(s32 value) {
ASSERT(value > 0);
ASSERT(Common::IsPowerOfTwo(value));
s32 log = 0;
while ((value >>= 1) > 0) {
++log;
}
return log;
}
} // namespace
Result HierarchicalSha256Storage::Initialize(VirtualFile* base_storages, s32 layer_count, Result HierarchicalSha256Storage::Initialize(VirtualFile* base_storages, s32 layer_count,
size_t htbs, void* hash_buf, size_t hash_buf_size) { size_t htbs, void* hash_buf, size_t hash_buf_size) {
// Validate preconditions. // Validate preconditions.
@ -31,7 +18,8 @@ Result HierarchicalSha256Storage::Initialize(VirtualFile* base_storages, s32 lay
// Set size tracking members. // Set size tracking members.
m_hash_target_block_size = static_cast<s32>(htbs); m_hash_target_block_size = static_cast<s32>(htbs);
m_log_size_ratio = Log2(m_hash_target_block_size / HashSize); m_log_size_ratio =
static_cast<s32>(std::log2(static_cast<double>(m_hash_target_block_size) / HashSize));
// Get the base storage size. // Get the base storage size.
m_base_storage_size = base_storages[2]->GetSize(); m_base_storage_size = base_storages[2]->GetSize();

View file

@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "common/alignment.h"
#include "common/scope_exit.h"
#include "core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.h"
#include <cmath>
namespace FileSys {
Result HierarchicalSha3Storage::Initialize(VirtualFile* base_storages, s32 layer_count, size_t htbs,
void* hash_buf, size_t hash_buf_size) {
ASSERT(layer_count == LayerCount);
ASSERT(Common::IsPowerOfTwo(htbs));
ASSERT(hash_buf != nullptr);
m_hash_target_block_size = static_cast<s32>(htbs);
m_log_size_ratio =
static_cast<s32>(std::log2(static_cast<double>(m_hash_target_block_size) / HashSize));
m_base_storage_size = base_storages[2]->GetSize();
{
auto size_guard = SCOPE_GUARD {
m_base_storage_size = 0;
};
R_UNLESS(m_base_storage_size <= static_cast<s64>(HashSize)
<< m_log_size_ratio << m_log_size_ratio,
ResultHierarchicalSha256BaseStorageTooLarge);
size_guard.Cancel();
}
m_base_storage = base_storages[2];
m_hash_buffer = static_cast<char*>(hash_buf);
m_hash_buffer_size = hash_buf_size;
std::array<u8, HashSize> master_hash{};
base_storages[0]->ReadObject(std::addressof(master_hash));
s64 hash_storage_size = base_storages[1]->GetSize();
ASSERT(Common::IsAligned(hash_storage_size, HashSize));
ASSERT(hash_storage_size <= m_hash_target_block_size);
ASSERT(hash_storage_size <= static_cast<s64>(m_hash_buffer_size));
base_storages[1]->Read(reinterpret_cast<u8*>(m_hash_buffer),
static_cast<size_t>(hash_storage_size), 0);
R_SUCCEED();
}
size_t HierarchicalSha3Storage::Read(u8* buffer, size_t size, size_t offset) const {
if (size == 0)
return size;
ASSERT(buffer != nullptr);
return m_base_storage->Read(buffer, size, offset);
}
} // namespace FileSys

View file

@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <mutex>
#include "core/file_sys/errors.h"
#include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {
class HierarchicalSha3Storage : public IReadOnlyStorage {
YUZU_NON_COPYABLE(HierarchicalSha3Storage);
YUZU_NON_MOVEABLE(HierarchicalSha3Storage);
public:
static constexpr s32 LayerCount = 3;
static constexpr size_t HashSize = 256 / 8; // SHA3-256
public:
HierarchicalSha3Storage() : m_mutex() {}
Result Initialize(VirtualFile* base_storages, s32 layer_count, size_t htbs, void* hash_buf,
size_t hash_buf_size);
virtual size_t GetSize() const override {
return m_base_storage->GetSize();
}
virtual size_t Read(u8* buffer, size_t length, size_t offset) const override;
private:
VirtualFile m_base_storage;
s64 m_base_storage_size{};
char* m_hash_buffer{};
size_t m_hash_buffer_size{};
s32 m_hash_target_block_size{};
s32 m_log_size_ratio{};
std::mutex m_mutex;
};
} // namespace FileSys

View file

@ -1,6 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h" #include "core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h"
#include "core/file_sys/fssystem/fssystem_aes_ctr_storage.h" #include "core/file_sys/fssystem/fssystem_aes_ctr_storage.h"
#include "core/file_sys/fssystem/fssystem_aes_xts_storage.h" #include "core/file_sys/fssystem/fssystem_aes_xts_storage.h"
@ -10,10 +14,12 @@
#include "core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h" #include "core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h"
#include "core/file_sys/fssystem/fssystem_indirect_storage.h" #include "core/file_sys/fssystem/fssystem_indirect_storage.h"
#include "core/file_sys/fssystem/fssystem_integrity_romfs_storage.h" #include "core/file_sys/fssystem/fssystem_integrity_romfs_storage.h"
#include "core/file_sys/fssystem/fssystem_passthrough_storage.h"
#include "core/file_sys/fssystem/fssystem_memory_resource_buffer_hold_storage.h" #include "core/file_sys/fssystem/fssystem_memory_resource_buffer_hold_storage.h"
#include "core/file_sys/fssystem/fssystem_nca_file_system_driver.h" #include "core/file_sys/fssystem/fssystem_nca_file_system_driver.h"
#include "core/file_sys/fssystem/fssystem_sparse_storage.h" #include "core/file_sys/fssystem/fssystem_sparse_storage.h"
#include "core/file_sys/fssystem/fssystem_switch_storage.h" #include "core/file_sys/fssystem/fssystem_switch_storage.h"
#include "core/file_sys/fssystem/fssystem_hierarchical_sha3_storage.h"
#include "core/file_sys/vfs/vfs_offset.h" #include "core/file_sys/vfs/vfs_offset.h"
#include "core/file_sys/vfs/vfs_vector.h" #include "core/file_sys/vfs/vfs_vector.h"
@ -299,18 +305,24 @@ Result NcaFileSystemDriver::CreateStorageByRawStorage(VirtualFile* out,
// Process hash/integrity layer. // Process hash/integrity layer.
switch (header_reader->GetHashType()) { switch (header_reader->GetHashType()) {
case NcaFsHeader::HashType::HierarchicalSha256Hash: case NcaFsHeader::HashType::HierarchicalSha256Hash:
R_TRY(this->CreateSha256Storage(std::addressof(storage), std::move(storage), R_TRY(CreateSha256Storage(&storage, std::move(storage),
header_reader->GetHashData().hierarchical_sha256_data)); header_reader->GetHashData().hierarchical_sha256_data));
break; break;
case NcaFsHeader::HashType::HierarchicalIntegrityHash: case NcaFsHeader::HashType::HierarchicalIntegrityHash:
R_TRY(this->CreateIntegrityVerificationStorage( R_TRY(CreateIntegrityVerificationStorage(&storage, std::move(storage),
std::addressof(storage), std::move(storage), header_reader->GetHashData().integrity_meta_info));
header_reader->GetHashData().integrity_meta_info)); break;
case NcaFsHeader::HashType::HierarchicalSha3256Hash:
R_TRY(CreateSha3Storage(&storage, std::move(storage),
header_reader->GetHashData().hierarchical_sha256_data));
break; break;
default: default:
LOG_ERROR(Loader, "Unhandled Fs HashType enum={}",
static_cast<int>(header_reader->GetHashType()));
R_THROW(ResultInvalidNcaFsHeaderHashType); R_THROW(ResultInvalidNcaFsHeaderHashType);
} }
// Process compression layer. // Process compression layer.
if (header_reader->ExistsCompressionLayer()) { if (header_reader->ExistsCompressionLayer()) {
R_TRY(this->CreateCompressedStorage( R_TRY(this->CreateCompressedStorage(
@ -679,6 +691,7 @@ Result NcaFileSystemDriver::CreateSparseStorageMetaStorageWithVerification(
// Create the verification storage. // Create the verification storage.
VirtualFile integrity_storage; VirtualFile integrity_storage;
Result rc = this->CreateIntegrityVerificationStorageForMeta( Result rc = this->CreateIntegrityVerificationStorageForMeta(
std::addressof(integrity_storage), out_layer_info_storage, std::move(decrypted_storage), std::addressof(integrity_storage), out_layer_info_storage, std::move(decrypted_storage),
meta_offset, meta_data_hash_data_info); meta_offset, meta_data_hash_data_info);
@ -734,8 +747,26 @@ Result NcaFileSystemDriver::CreateSparseStorageWithVerification(
NcaHeader::CtrBlockSize))); NcaHeader::CtrBlockSize)));
// Check the meta data hash type. // Check the meta data hash type.
R_UNLESS(meta_data_hash_type == NcaFsHeader::MetaDataHashType::HierarchicalIntegrity, if (meta_data_hash_type != NcaFsHeader::MetaDataHashType::HierarchicalIntegrity) {
ResultRomNcaInvalidSparseMetaDataHashType); LOG_ERROR(Loader, "Sparse meta hash type {} not supported for verification; mounting sparse data WITHOUT verification (temporary).", static_cast<int>(meta_data_hash_type));
R_TRY(this->CreateBodySubStorage(std::addressof(body_substorage),
sparse_info.physical_offset,
sparse_info.GetPhysicalSize()));
// Create sparse core directly (no meta verification)
std::shared_ptr<SparseStorage> sparse_storage_fallback;
R_TRY(this->CreateSparseStorageCore(std::addressof(sparse_storage_fallback),
body_substorage, sparse_info.GetPhysicalSize(),
/*meta_storage*/ body_substorage, // dummy; not used
sparse_info, false));
if (out_sparse_storage)
*out_sparse_storage = sparse_storage_fallback;
*out_fs_data_offset = fs_offset;
*out = std::move(sparse_storage_fallback);
R_SUCCEED();
}
// Create the meta storage. // Create the meta storage.
VirtualFile meta_storage; VirtualFile meta_storage;
@ -1093,6 +1124,56 @@ Result NcaFileSystemDriver::CreatePatchMetaStorage(
R_SUCCEED(); R_SUCCEED();
} }
Result NcaFileSystemDriver::CreateSha3Storage(
VirtualFile* out, VirtualFile base_storage,
const NcaFsHeader::HashData::HierarchicalSha256Data& hash_data) {
ASSERT(out != nullptr);
ASSERT(base_storage != nullptr);
using VerificationStorage = HierarchicalSha3Storage;
R_UNLESS(Common::IsPowerOfTwo(hash_data.hash_block_size),
ResultInvalidHierarchicalSha256BlockSize);
R_UNLESS(hash_data.hash_layer_count == VerificationStorage::LayerCount - 1,
ResultInvalidHierarchicalSha256LayerCount);
const auto& hash_region = hash_data.hash_layer_region[0];
const auto& data_region = hash_data.hash_layer_region[1];
constexpr s32 CacheBlockCount = 2;
const auto hash_buffer_size = static_cast<size_t>(hash_region.size);
const auto cache_buffer_size = CacheBlockCount * hash_data.hash_block_size;
const auto total_buffer_size = hash_buffer_size + cache_buffer_size;
auto buffer_hold_storage = std::make_shared<MemoryResourceBufferHoldStorage>(
std::move(base_storage), total_buffer_size);
R_UNLESS(buffer_hold_storage != nullptr, ResultAllocationMemoryFailedAllocateShared);
R_UNLESS(buffer_hold_storage->IsValid(), ResultAllocationMemoryFailedInNcaFileSystemDriverI);
s64 base_size = buffer_hold_storage->GetSize();
R_UNLESS(hash_region.offset + hash_region.size <= base_size, ResultNcaBaseStorageOutOfRangeC);
R_UNLESS(data_region.offset + data_region.size <= base_size, ResultNcaBaseStorageOutOfRangeC);
auto master_hash_storage =
std::make_shared<ArrayVfsFile<sizeof(Hash)>>(hash_data.fs_data_master_hash.value);
auto verification_storage = std::make_shared<VerificationStorage>();
R_UNLESS(verification_storage != nullptr, ResultAllocationMemoryFailedAllocateShared);
std::array<VirtualFile, VerificationStorage::LayerCount> layer_storages{
std::make_shared<OffsetVfsFile>(master_hash_storage, sizeof(Hash), 0),
std::make_shared<OffsetVfsFile>(buffer_hold_storage, hash_region.size, hash_region.offset),
std::make_shared<OffsetVfsFile>(buffer_hold_storage, data_region.size, data_region.offset),
};
R_TRY(verification_storage->Initialize(layer_storages.data(), VerificationStorage::LayerCount,
hash_data.hash_block_size,
buffer_hold_storage->GetBuffer(), hash_buffer_size));
*out = std::move(verification_storage);
R_SUCCEED();
}
Result NcaFileSystemDriver::CreateSha256Storage( Result NcaFileSystemDriver::CreateSha256Storage(
VirtualFile* out, VirtualFile base_storage, VirtualFile* out, VirtualFile base_storage,
const NcaFsHeader::HashData::HierarchicalSha256Data& hash_data) { const NcaFsHeader::HashData::HierarchicalSha256Data& hash_data) {
@ -1160,6 +1241,7 @@ Result NcaFileSystemDriver::CreateSha256Storage(
Result NcaFileSystemDriver::CreateIntegrityVerificationStorage( Result NcaFileSystemDriver::CreateIntegrityVerificationStorage(
VirtualFile* out, VirtualFile base_storage, VirtualFile* out, VirtualFile base_storage,
const NcaFsHeader::HashData::IntegrityMetaInfo& meta_info) { const NcaFsHeader::HashData::IntegrityMetaInfo& meta_info) {
R_RETURN(this->CreateIntegrityVerificationStorageImpl( R_RETURN(this->CreateIntegrityVerificationStorageImpl(
out, base_storage, meta_info, 0, IntegrityDataCacheCount, IntegrityHashCacheCount, out, base_storage, meta_info, 0, IntegrityDataCacheCount, IntegrityHashCacheCount,
HierarchicalIntegrityVerificationStorage::GetDefaultDataCacheBufferLevel( HierarchicalIntegrityVerificationStorage::GetDefaultDataCacheBufferLevel(
@ -1209,63 +1291,96 @@ Result NcaFileSystemDriver::CreateIntegrityVerificationStorageImpl(
VirtualFile* out, VirtualFile base_storage, VirtualFile* out, VirtualFile base_storage,
const NcaFsHeader::HashData::IntegrityMetaInfo& meta_info, s64 layer_info_offset, const NcaFsHeader::HashData::IntegrityMetaInfo& meta_info, s64 layer_info_offset,
int max_data_cache_entries, int max_hash_cache_entries, s8 buffer_level) { int max_data_cache_entries, int max_hash_cache_entries, s8 buffer_level) {
// Validate preconditions. // Preconditions
ASSERT(out != nullptr); ASSERT(out != nullptr);
ASSERT(base_storage != nullptr); ASSERT(base_storage != nullptr);
ASSERT(layer_info_offset >= 0); ASSERT(layer_info_offset >= 0);
// Define storage types. if (!Settings::values.disable_nca_verification.GetValue()) {
using VerificationStorage = HierarchicalIntegrityVerificationStorage; // Define storage types.
using StorageInfo = VerificationStorage::HierarchicalStorageInformation; using VerificationStorage = HierarchicalIntegrityVerificationStorage;
using StorageInfo = VerificationStorage::HierarchicalStorageInformation;
// Validate the meta info. // Validate the meta info.
HierarchicalIntegrityVerificationInformation level_hash_info; HierarchicalIntegrityVerificationInformation level_hash_info;
std::memcpy(std::addressof(level_hash_info), std::addressof(meta_info.level_hash_info), std::memcpy(std::addressof(level_hash_info), std::addressof(meta_info.level_hash_info),
sizeof(level_hash_info)); sizeof(level_hash_info));
R_UNLESS(IntegrityMinLayerCount <= level_hash_info.max_layers, R_UNLESS(IntegrityMinLayerCount <= level_hash_info.max_layers,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount); ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(level_hash_info.max_layers <= IntegrityMaxLayerCount, R_UNLESS(level_hash_info.max_layers <= IntegrityMaxLayerCount,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount); ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
// Get the base storage size. // Get the base storage size.
s64 base_storage_size = base_storage->GetSize(); s64 base_storage_size = base_storage->GetSize();
// Create storage info. // Create storage info.
StorageInfo storage_info; StorageInfo storage_info;
for (s32 i = 0; i < static_cast<s32>(level_hash_info.max_layers - 2); ++i) { for (s32 i = 0; i < static_cast<s32>(level_hash_info.max_layers - 2); ++i) {
const auto& layer_info = level_hash_info.info[i]; const auto& layer_info = level_hash_info.info[i];
R_UNLESS(layer_info_offset + layer_info.offset + layer_info.size <= base_storage_size, R_UNLESS(layer_info_offset + layer_info.offset + layer_info.size <= base_storage_size,
ResultNcaBaseStorageOutOfRangeD);
storage_info[i + 1] = std::make_shared<OffsetVfsFile>(
base_storage, layer_info.size, layer_info_offset + layer_info.offset);
}
// Set the last layer info.
const auto& layer_info = level_hash_info.info[level_hash_info.max_layers - 2];
const s64 last_layer_info_offset = layer_info_offset > 0 ? 0LL : layer_info.offset.Get();
R_UNLESS(last_layer_info_offset + layer_info.size <= base_storage_size,
ResultNcaBaseStorageOutOfRangeD); ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(last_layer_info_offset + layer_info.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
storage_info.SetDataStorage(std::make_shared<OffsetVfsFile>(
std::move(base_storage), layer_info.size, last_layer_info_offset));
storage_info[i + 1] = std::make_shared<OffsetVfsFile>( // Make the integrity romfs storage.
base_storage, layer_info.size, layer_info_offset + layer_info.offset); auto integrity_storage = std::make_shared<IntegrityRomFsStorage>();
R_UNLESS(integrity_storage != nullptr, ResultAllocationMemoryFailedAllocateShared);
// Initialize the integrity storage.
R_TRY(integrity_storage->Initialize(level_hash_info, meta_info.master_hash, storage_info,
max_data_cache_entries, max_hash_cache_entries,
buffer_level));
// Set the output.
*out = std::move(integrity_storage);
R_SUCCEED();
} else {
// Read IVFC layout
HierarchicalIntegrityVerificationInformation lhi{};
std::memcpy(std::addressof(lhi), std::addressof(meta_info.level_hash_info), sizeof(lhi));
R_UNLESS(IntegrityMinLayerCount <= lhi.max_layers,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
R_UNLESS(lhi.max_layers <= IntegrityMaxLayerCount,
ResultInvalidNcaHierarchicalIntegrityVerificationLayerCount);
const auto& data_li = lhi.info[lhi.max_layers - 2];
const s64 base_size = base_storage->GetSize();
// Compute the data layer window
const s64 data_off = (layer_info_offset > 0) ? 0LL : data_li.offset.Get();
R_UNLESS(data_off + data_li.size <= base_size, ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(data_off + data_li.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
// TODO: Passthrough (temporary compatibility: integrity disabled)
auto data_view = std::make_shared<OffsetVfsFile>(base_storage, data_li.size, data_off);
R_UNLESS(data_view != nullptr, ResultAllocationMemoryFailedAllocateShared);
auto passthrough = std::make_shared<PassthroughStorage>(std::move(data_view));
R_UNLESS(passthrough != nullptr, ResultAllocationMemoryFailedAllocateShared);
*out = std::move(passthrough);
R_SUCCEED();
} }
// Set the last layer info.
const auto& layer_info = level_hash_info.info[level_hash_info.max_layers - 2];
const s64 last_layer_info_offset = layer_info_offset > 0 ? 0LL : layer_info.offset.Get();
R_UNLESS(last_layer_info_offset + layer_info.size <= base_storage_size,
ResultNcaBaseStorageOutOfRangeD);
if (layer_info_offset > 0) {
R_UNLESS(last_layer_info_offset + layer_info.size <= layer_info_offset,
ResultRomNcaInvalidIntegrityLayerInfoOffset);
}
storage_info.SetDataStorage(std::make_shared<OffsetVfsFile>(
std::move(base_storage), layer_info.size, last_layer_info_offset));
// Make the integrity romfs storage.
auto integrity_storage = std::make_shared<IntegrityRomFsStorage>();
R_UNLESS(integrity_storage != nullptr, ResultAllocationMemoryFailedAllocateShared);
// Initialize the integrity storage.
R_TRY(integrity_storage->Initialize(level_hash_info, meta_info.master_hash, storage_info,
max_data_cache_entries, max_hash_cache_entries,
buffer_level));
// Set the output.
*out = std::move(integrity_storage);
R_SUCCEED();
} }
Result NcaFileSystemDriver::CreateRegionSwitchStorage(VirtualFile* out, Result NcaFileSystemDriver::CreateRegionSwitchStorage(VirtualFile* out,

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -329,6 +332,10 @@ private:
const NcaPatchInfo& patch_info, const NcaPatchInfo& patch_info,
const NcaMetaDataHashDataInfo& meta_data_hash_data_info); const NcaMetaDataHashDataInfo& meta_data_hash_data_info);
Result CreateSha3Storage(VirtualFile* out, VirtualFile base_storage,
const NcaFsHeader::HashData::HierarchicalSha256Data& hash_data);
Result CreateSha256Storage(VirtualFile* out, VirtualFile base_storage, Result CreateSha256Storage(VirtualFile* out, VirtualFile base_storage,
const NcaFsHeader::HashData::HierarchicalSha256Data& sha256_data); const NcaFsHeader::HashData::HierarchicalSha256Data& sha256_data);

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -10,11 +13,13 @@ u8 NcaHeader::GetProperKeyGeneration() const {
} }
bool NcaPatchInfo::HasIndirectTable() const { bool NcaPatchInfo::HasIndirectTable() const {
return this->indirect_size != 0; static constexpr unsigned char BKTR[4] = {'B', 'K', 'T', 'R'};
return std::memcmp(indirect_header.data(), BKTR, sizeof(BKTR)) == 0;
} }
bool NcaPatchInfo::HasAesCtrExTable() const { bool NcaPatchInfo::HasAesCtrExTable() const {
return this->aes_ctr_ex_size != 0; static constexpr unsigned char BKTR[4] = {'B', 'K', 'T', 'R'};
return std::memcmp(aes_ctr_ex_header.data(), BKTR, sizeof(BKTR)) == 0;
} }
} // namespace FileSys } // namespace FileSys

View file

@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "core/file_sys/fssystem/fs_i_storage.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys {
//TODO: No integrity verification.
class PassthroughStorage final : public IReadOnlyStorage {
YUZU_NON_COPYABLE(PassthroughStorage);
YUZU_NON_MOVEABLE(PassthroughStorage);
public:
explicit PassthroughStorage(VirtualFile base) : base_(std::move(base)) {}
~PassthroughStorage() override = default;
size_t Read(u8* buffer, size_t size, size_t offset) const override {
if (!base_ || size == 0)
return 0;
return base_->Read(buffer, size, offset);
}
size_t GetSize() const override {
return base_ ? base_->GetSize() : 0;
}
private:
VirtualFile base_{};
};
} // namespace FileSys

View file

@ -1266,6 +1266,10 @@ void KProcess::InitializeInterfaces() {
#ifdef HAS_NCE #ifdef HAS_NCE
if (this->IsApplication() && Settings::IsNceEnabled()) { if (this->IsApplication() && Settings::IsNceEnabled()) {
// Register the scoped JIT handler before creating any NCE instances
// so that its signal handler will appear first in the signal chain.
Core::ScopedJitExecution::RegisterHandler();
for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i); m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i);
} }

View file

@ -1,5 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator
// Project// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/am/applet.h" #include "core/hle/service/am/applet.h"
@ -12,7 +15,7 @@ Applet::Applet(Core::System& system, std::unique_ptr<Process> process_, bool is_
process(std::move(process_)), hid_registration(system, *process), process(std::move(process_)), hid_registration(system, *process),
gpu_error_detected_event(context), friend_invitation_storage_channel_event(context), gpu_error_detected_event(context), friend_invitation_storage_channel_event(context),
notification_storage_channel_event(context), health_warning_disappeared_system_event(context), notification_storage_channel_event(context), health_warning_disappeared_system_event(context),
acquired_sleep_lock_event(context), pop_from_general_channel_event(context), unknown_event(context), acquired_sleep_lock_event(context), pop_from_general_channel_event(context),
library_applet_launchable_event(context), accumulated_suspended_tick_changed_event(context), library_applet_launchable_event(context), accumulated_suspended_tick_changed_event(context),
sleep_lock_event(context), state_changed_event(context) { sleep_lock_event(context), state_changed_event(context) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -120,6 +123,7 @@ struct Applet {
Event friend_invitation_storage_channel_event; Event friend_invitation_storage_channel_event;
Event notification_storage_channel_event; Event notification_storage_channel_event;
Event health_warning_disappeared_system_event; Event health_warning_disappeared_system_event;
Event unknown_event;
Event acquired_sleep_lock_event; Event acquired_sleep_lock_event;
Event pop_from_general_channel_event; Event pop_from_general_channel_event;
Event library_applet_launchable_event; Event library_applet_launchable_event;

View file

@ -18,6 +18,7 @@ IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& sys
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
{110, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxyEx"},
{200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"}, {200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"},
{201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"}, {201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"},
{300, nullptr, "OpenOverlayAppletProxy"}, {300, nullptr, "OpenOverlayAppletProxy"},
@ -25,6 +26,7 @@ IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& sys
{400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"}, {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
{410, nullptr, "GetSystemAppletControllerForDebug"}, {410, nullptr, "GetSystemAppletControllerForDebug"},
{450, D<&IAllSystemAppletProxiesService::GetSystemProcessCommonFunctions>, "GetSystemProcessCommonFunctions"}, // 19.0.0+ {450, D<&IAllSystemAppletProxiesService::GetSystemProcessCommonFunctions>, "GetSystemProcessCommonFunctions"}, // 19.0.0+
{460, D<&IAllSystemAppletProxiesService::GetAppletAlternativeFunctions>, "GetAppletAlternativeFunctions"}, // 20.0.0+
{1000, nullptr, "GetDebugFunctions"}, {1000, nullptr, "GetDebugFunctions"},
}; };
// clang-format on // clang-format on
@ -99,6 +101,14 @@ Result IAllSystemAppletProxiesService::GetSystemProcessCommonFunctions() {
R_SUCCEED(); R_SUCCEED();
} }
Result IAllSystemAppletProxiesService::GetAppletAlternativeFunctions() {
LOG_DEBUG(Service_AM, "(STUBBED) called.");
// TODO (maufeat)
R_SUCCEED();
}
std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId( std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
ProcessId process_id) { ProcessId process_id) {
return m_window_system.GetByAppletResourceUserId(process_id.pid); return m_window_system.GetByAppletResourceUserId(process_id.pid);

View file

@ -39,6 +39,7 @@ private:
InCopyHandle<Kernel::KProcess> process_handle, InCopyHandle<Kernel::KProcess> process_handle,
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute); InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
Result GetSystemProcessCommonFunctions(); Result GetSystemProcessCommonFunctions();
Result GetAppletAlternativeFunctions();
private: private:
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);

View file

@ -35,6 +35,7 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
{310, nullptr, "IsSystemAppletHomeMenu"}, //19.0.0+ {310, nullptr, "IsSystemAppletHomeMenu"}, //19.0.0+
{320, nullptr, "SetGpuTimeSliceBoost"}, //19.0.0+ {320, nullptr, "SetGpuTimeSliceBoost"}, //19.0.0+
{321, nullptr, "SetGpuTimeSliceBoostDueToApplication"}, //19.0.0+ {321, nullptr, "SetGpuTimeSliceBoostDueToApplication"}, //19.0.0+
{350, D<&IAppletCommonFunctions::Unknown350>, "Unknown350"} //20.0.0+
}; };
// clang-format on // clang-format on
@ -70,4 +71,10 @@ Result IAppletCommonFunctions::GetCurrentApplicationId(Out<u64> out_application_
R_SUCCEED(); R_SUCCEED();
} }
Result IAppletCommonFunctions::Unknown350(Out<u16> out_unknown) {
LOG_WARNING(Service_AM, "(STUBBED) called");
*out_unknown = 0;
R_SUCCEED();
}
} // namespace Service::AM } // namespace Service::AM

View file

@ -20,6 +20,7 @@ private:
Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled); Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled);
Result SetCpuBoostRequestPriority(s32 priority); Result SetCpuBoostRequestPriority(s32 priority);
Result GetCurrentApplicationId(Out<u64> out_application_id); Result GetCurrentApplicationId(Out<u64> out_application_id);
Result Unknown350(Out<u16> out_unknown);
const std::shared_ptr<Applet> applet; const std::shared_ptr<Applet> applet;
}; };

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -85,6 +88,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_
{181, nullptr, "UpgradeLaunchRequiredVersion"}, {181, nullptr, "UpgradeLaunchRequiredVersion"},
{190, nullptr, "SendServerMaintenanceOverlayNotification"}, {190, nullptr, "SendServerMaintenanceOverlayNotification"},
{200, nullptr, "GetLastApplicationExitReason"}, {200, nullptr, "GetLastApplicationExitReason"},
{210, D<&IApplicationFunctions::GetUnknownEvent210>, "Unknown210"},
{500, nullptr, "StartContinuousRecordingFlushForDebug"}, {500, nullptr, "StartContinuousRecordingFlushForDebug"},
{1000, nullptr, "CreateMovieMaker"}, {1000, nullptr, "CreateMovieMaker"},
{1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"}, {1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"},
@ -487,6 +491,13 @@ Result IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(
R_SUCCEED(); R_SUCCEED();
} }
Result IApplicationFunctions::GetUnknownEvent210(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_AM, "called");
*out_event = m_applet->unknown_event.GetHandle();
R_SUCCEED();
}
Result IApplicationFunctions::PrepareForJit() { Result IApplicationFunctions::PrepareForJit() {
LOG_WARNING(Service_AM, "(STUBBED) called"); LOG_WARNING(Service_AM, "(STUBBED) called");

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -76,6 +79,7 @@ private:
Result TryPopFromFriendInvitationStorageChannel(Out<SharedPointer<IStorage>> out_storage); Result TryPopFromFriendInvitationStorageChannel(Out<SharedPointer<IStorage>> out_storage);
Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetNotificationStorageChannelEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetUnknownEvent210(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result PrepareForJit(); Result PrepareForJit();
const std::shared_ptr<Applet> m_applet; const std::shared_ptr<Applet> m_applet;

View file

@ -113,9 +113,11 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
Firmware1700 = 17, Firmware1700 = 17,
Firmware1800 = 18, Firmware1800 = 18,
Firmware1900 = 19, Firmware1900 = 19,
Firmware2000 = 20,
Firmware2100 = 21,
}; };
auto process = CreateProcess(system, program_id, Firmware1400, Firmware1900); auto process = CreateProcess(system, program_id, Firmware1400, Firmware2100);
if (!process) { if (!process) {
// Couldn't initialize the guest process // Couldn't initialize the guest process
return {}; return {};

View file

@ -306,6 +306,9 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
{3013, nullptr, "IsGameCardEnabled"}, {3013, nullptr, "IsGameCardEnabled"},
{3014, nullptr, "IsLocalContentShareEnabled"}, {3014, nullptr, "IsLocalContentShareEnabled"},
{3050, nullptr, "ListAssignELicenseTaskResult"}, {3050, nullptr, "ListAssignELicenseTaskResult"},
{4022, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4022"},
{4023, D<&IApplicationManagerInterface::Unknown4023>, "Unknown4023"},
{4088, D<&IApplicationManagerInterface::Unknown4022>, "Unknown4088"},
{9999, nullptr, "GetApplicationCertificate"}, {9999, nullptr, "GetApplicationCertificate"},
}; };
// clang-format on // clang-format on
@ -523,4 +526,17 @@ Result IApplicationManagerInterface::GetApplicationTerminateResult(Out<Result> o
R_SUCCEED(); R_SUCCEED();
} }
Result IApplicationManagerInterface::Unknown4022(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Service_NS, "(STUBBED) called");
*out_event = gamecard_update_detection_event.GetHandle();
R_SUCCEED();
}
Result IApplicationManagerInterface::Unknown4023(Out<u64> out_result) {
LOG_WARNING(Service_NS, "(STUBBED) called.");
*out_result = 0;
R_SUCCEED();
}
} // namespace Service::NS } // namespace Service::NS

View file

@ -53,6 +53,8 @@ public:
u64 application_id); u64 application_id);
Result CheckApplicationLaunchVersion(u64 application_id); Result CheckApplicationLaunchVersion(u64 application_id);
Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id); Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id);
Result Unknown4022(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result Unknown4023(Out<u64> out_result);
private: private:
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;

View file

@ -219,28 +219,55 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx& params, DeviceFD fd) {
return NvResult::Success; return NvResult::Success;
} }
NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) { s32_le nvhost_gpu::GetObjectContextClassNumberIndex(CtxClasses class_number) {
LOG_DEBUG(Service_NVDRV, "called, class_num={:X}, flags={:X}, obj_id={:X}", params.class_num, constexpr s32_le invalid_class_number_index = -1;
params.flags, params.obj_id); switch (class_number) {
case CtxClasses::Ctx2D: return 0;
case CtxClasses::Ctx3D: return 1;
case CtxClasses::CtxCompute: return 2;
case CtxClasses::CtxKepler: return 3;
case CtxClasses::CtxDMA: return 4;
case CtxClasses::CtxChannelGPFIFO: return 5;
default: return invalid_class_number_index;
}
}
if (!channel_state->initialized) { NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
LOG_DEBUG(Service_NVDRV, "called, class_num={:#X}, flags={:#X}, obj_id={:#X}", params.class_num,
params.flags, params.obj_id);
if (!channel_state || !channel_state->initialized) {
LOG_CRITICAL(Service_NVDRV, "No address space bound to allocate a object context!"); LOG_CRITICAL(Service_NVDRV, "No address space bound to allocate a object context!");
return NvResult::NotInitialized; return NvResult::NotInitialized;
} }
switch (static_cast<CtxClasses>(params.class_num)) { std::scoped_lock lk(channel_mutex);
case CtxClasses::Ctx2D:
case CtxClasses::Ctx3D: if (params.flags) {
case CtxClasses::CtxCompute: LOG_WARNING(Service_NVDRV, "non-zero flags={:#X} for class={:#X}", params.flags,
case CtxClasses::CtxKepler: params.class_num);
case CtxClasses::CtxDMA:
case CtxClasses::CtxChannelGPFIFO: constexpr u32 allowed_mask{};
ctxObj_params.push_back(params); params.flags = allowed_mask;
return NvResult::Success; }
default:
LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:X}", params.class_num); s32_le ctx_class_number_index =
GetObjectContextClassNumberIndex(static_cast<CtxClasses>(params.class_num));
if (ctx_class_number_index < 0) {
LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:#X}",
params.class_num);
return NvResult::BadParameter; return NvResult::BadParameter;
} }
if (ctxObjs[ctx_class_number_index].has_value()) {
LOG_ERROR(Service_NVDRV, "Object context for class {:#X} already allocated on this channel",
params.class_num);
return NvResult::AlreadyAllocated;
}
ctxObjs[ctx_class_number_index] = params;
return NvResult::Success;
} }
static boost::container::small_vector<Tegra::CommandHeader, 512> BuildWaitCommandList( static boost::container::small_vector<Tegra::CommandHeader, 512> BuildWaitCommandList(

View file

@ -172,7 +172,7 @@ private:
s32_le nvmap_fd{}; s32_le nvmap_fd{};
u64_le user_data{}; u64_le user_data{};
IoctlZCullBind zcull_params{}; IoctlZCullBind zcull_params{};
std::vector<IoctlAllocObjCtx> ctxObj_params{}; std::array<std::optional<IoctlAllocObjCtx>, 6> ctxObjs{};
u32_le channel_priority{}; u32_le channel_priority{};
u32_le channel_timeslice{}; u32_le channel_timeslice{};
@ -184,9 +184,12 @@ private:
NvResult SetChannelPriority(IoctlChannelSetPriority& params); NvResult SetChannelPriority(IoctlChannelSetPriority& params);
NvResult AllocGPFIFOEx(IoctlAllocGpfifoEx& params, DeviceFD fd); NvResult AllocGPFIFOEx(IoctlAllocGpfifoEx& params, DeviceFD fd);
NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx& params, DeviceFD fd); NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx& params, DeviceFD fd);
s32_le GetObjectContextClassNumberIndex(CtxClasses class_number);
NvResult AllocateObjectContext(IoctlAllocObjCtx& params); NvResult AllocateObjectContext(IoctlAllocObjCtx& params);
NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries); NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries);
NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params, NvResult SubmitGPFIFOBase1(IoctlSubmitGpfifo& params,
std::span<Tegra::CommandListHeader> commands, bool kickoff = false); std::span<Tegra::CommandListHeader> commands, bool kickoff = false);
NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params, NvResult SubmitGPFIFOBase2(IoctlSubmitGpfifo& params,

View file

@ -80,11 +80,12 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
{1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"}, {1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"},
{1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"}, {1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"},
{1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"}, {1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"},
{1454, nullptr, "GetPlayTimerRemainingTime"}, {1454, D<&IParentalControlService::GetPlayTimerRemainingTime>, "GetPlayTimerRemainingTime"},
{1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"}, {1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"},
{1456, D<&IParentalControlService::GetPlayTimerSettingsOld>, "GetPlayTimerSettingsOld"}, {1456, D<&IParentalControlService::GetPlayTimerSettingsOld>, "GetPlayTimerSettingsOld"},
{1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"}, {1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"},
{1458, D<&IParentalControlService::IsPlayTimerAlarmDisabled>, "IsPlayTimerAlarmDisabled"}, {1458, D<&IParentalControlService::IsPlayTimerAlarmDisabled>, "IsPlayTimerAlarmDisabled"},
{1459, D<&IParentalControlService::GetPlayTimerRemainingTimeDisplayInfo>, "GetPlayTimerRemainingTimeDisplayInfo"},
{1471, nullptr, "NotifyWrongPinCodeInputManyTimes"}, {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
{1472, nullptr, "CancelNetworkRequest"}, {1472, nullptr, "CancelNetworkRequest"},
{1473, D<&IParentalControlService::GetUnlinkedEvent>, "GetUnlinkedEvent"}, {1473, D<&IParentalControlService::GetUnlinkedEvent>, "GetUnlinkedEvent"},
@ -378,6 +379,12 @@ Result IParentalControlService::IsPlayTimerEnabled(Out<bool> out_is_play_timer_e
R_SUCCEED(); R_SUCCEED();
} }
Result IParentalControlService::GetPlayTimerRemainingTime(Out<s32> out_remaining_time) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
*out_remaining_time = std::numeric_limits<s32>::max();
R_SUCCEED();
}
Result IParentalControlService::IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer) { Result IParentalControlService::IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer) {
*out_is_restricted_by_play_timer = false; *out_is_restricted_by_play_timer = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, restricted={}", *out_is_restricted_by_play_timer); LOG_WARNING(Service_PCTL, "(STUBBED) called, restricted={}", *out_is_restricted_by_play_timer);
@ -412,6 +419,11 @@ Result IParentalControlService::IsPlayTimerAlarmDisabled(Out<bool> out_play_time
R_SUCCEED(); R_SUCCEED();
} }
Result IParentalControlService::GetPlayTimerRemainingTimeDisplayInfo(/* Out 0x18 */) {
LOG_INFO(Service_PCTL, "called");
R_SUCCEED();
}
Result IParentalControlService::GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) { Result IParentalControlService::GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_PCTL, "called"); LOG_INFO(Service_PCTL, "called");
*out_event = unlinked_event.GetHandle(); *out_event = unlinked_event.GetHandle();

View file

@ -49,10 +49,12 @@ private:
Result StartPlayTimer(); Result StartPlayTimer();
Result StopPlayTimer(); Result StopPlayTimer();
Result IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled); Result IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled);
Result GetPlayTimerRemainingTime(Out<s32> out_remaining_time);
Result IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer); Result IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer);
Result GetPlayTimerSettingsOld(Out<PlayTimerSettings> out_play_timer_settings); Result GetPlayTimerSettingsOld(Out<PlayTimerSettings> out_play_timer_settings);
Result GetPlayTimerEventToRequestSuspension(OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetPlayTimerEventToRequestSuspension(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled); Result IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled);
Result GetPlayTimerRemainingTimeDisplayInfo();
Result GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); Result GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetStereoVisionRestriction(Out<bool> out_stereo_vision_restriction); Result GetStereoVisionRestriction(Out<bool> out_stereo_vision_restriction);
Result SetStereoVisionRestriction(bool stereo_vision_restriction); Result SetStereoVisionRestriction(bool stereo_vision_restriction);

View file

@ -61,7 +61,8 @@ struct Memory::Impl {
} }
#ifdef __linux__ #ifdef __linux__
buffer.emplace(system.DeviceMemory().buffer); heap_tracker.emplace(system.DeviceMemory().buffer);
buffer = std::addressof(*heap_tracker);
#else #else
buffer = std::addressof(system.DeviceMemory().buffer); buffer = std::addressof(system.DeviceMemory().buffer);
#endif #endif
@ -1023,8 +1024,9 @@ struct Memory::Impl {
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
std::mutex sys_core_guard; std::mutex sys_core_guard;
std::optional<Common::HeapTracker> heap_tracker;
#ifdef __linux__ #ifdef __linux__
std::optional<Common::HeapTracker> buffer; Common::HeapTracker* buffer{};
#else #else
Common::HostMemory* buffer{}; Common::HostMemory* buffer{};
#endif #endif
@ -1228,7 +1230,22 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
if (rasterizer) { if (rasterizer) {
impl->InvalidateGPUMemory(ptr, size); impl->InvalidateGPUMemory(ptr, size);
} }
#ifdef __linux__
if (!rasterizer && mapped) {
impl->buffer->DeferredMapSeparateHeap(GetInteger(vaddr));
}
#endif
return mapped && ptr != nullptr; 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 } // namespace Core::Memory

View file

@ -487,8 +487,13 @@ public:
* marked as debug or non-debug. * marked as debug or non-debug.
*/ */
void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug); void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug);
void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers); void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers);
bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size); bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size);
bool InvalidateSeparateHeap(void* fault_address);
private: private:
Core::System& system; Core::System& system;

View file

@ -62,10 +62,10 @@ AddJsonPackage(
# unordered_dense # unordered_dense
AddJsonPackage( # AddJsonPackage(
NAME unordered-dense # NAME unordered-dense
BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS} # BUNDLED_PACKAGE ${DYNARMIC_USE_BUNDLED_EXTERNALS}
) # )
# xbyak # xbyak
# uncomment if in an independent repo # uncomment if in an independent repo

View file

@ -14,16 +14,6 @@
"MCL_INSTALL OFF" "MCL_INSTALL OFF"
] ]
}, },
"unordered-dense": {
"package": "unordered_dense",
"repo": "Lizzie841/unordered_dense",
"sha": "e59d30b7b1",
"hash": "71eff7bd9ba4b9226967bacd56a8ff000946f8813167cb5664bb01e96fb79e4e220684d824fe9c59c4d1cc98c606f13aff05b7940a1ed8ab3c95d6974ee34fa0",
"find_args": "CONFIG",
"options": [
"UNORDERED_DENSE_INSTALL OFF"
]
},
"zycore": { "zycore": {
"package": "Zycore", "package": "Zycore",
"repo": "zyantific/zycore-c", "repo": "zyantific/zycore-c",

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage * Copyright (c) 2018 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
@ -19,6 +22,16 @@
namespace Dynarmic::Common { namespace Dynarmic::Common {
// prevents this function from printing 56,000 character warning messages
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wno-stack-usage"
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wno-stack-usage"
#endif
template<typename Function, typename... Values> template<typename Function, typename... Values>
inline auto GenerateLookupTableFromList(Function f, mcl::mp::list<Values...>) { inline auto GenerateLookupTableFromList(Function f, mcl::mp::list<Values...>) {
#ifdef _MSC_VER #ifdef _MSC_VER
@ -34,4 +47,11 @@ inline auto GenerateLookupTableFromList(Function f, mcl::mp::list<Values...>) {
return MapT(pair_array.begin(), pair_array.end()); return MapT(pair_array.begin(), pair_array.end());
} }
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef __clang__
#pragma clang diagnostic pop
#endif
} // namespace Dynarmic::Common } // namespace Dynarmic::Common

View file

@ -332,7 +332,8 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS})
add_dependencies(video_core host_shaders) add_dependencies(video_core host_shaders)
target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE})
target_link_libraries(video_core PRIVATE sirit Vulkan::Headers Vulkan::UtilityHeaders GPUOpen::VulkanMemoryAllocator) target_link_libraries(video_core PRIVATE sirit Vulkan::Headers Vulkan::UtilityHeaders)
target_link_libraries(video_core PUBLIC GPUOpen::VulkanMemoryAllocator)
if (ENABLE_NSIGHT_AFTERMATH) if (ENABLE_NSIGHT_AFTERMATH)
if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})

View file

@ -102,13 +102,16 @@ constexpr VkPipelineVertexInputStateCreateInfo PIPELINE_VERTEX_INPUT_STATE_CREAT
.vertexAttributeDescriptionCount = 0, .vertexAttributeDescriptionCount = 0,
.pVertexAttributeDescriptions = nullptr, .pVertexAttributeDescriptions = nullptr,
}; };
constexpr VkPipelineInputAssemblyStateCreateInfo PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, VkPipelineInputAssemblyStateCreateInfo GetPipelineInputAssemblyStateCreateInfo(const Device& device) {
.pNext = nullptr, return VkPipelineInputAssemblyStateCreateInfo{
.flags = 0, .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .pNext = nullptr,
.primitiveRestartEnable = VK_FALSE, .flags = 0,
}; .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.primitiveRestartEnable = device.IsMoltenVK() ? VK_TRUE : VK_FALSE,
};
}
constexpr VkPipelineViewportStateCreateInfo PIPELINE_VIEWPORT_STATE_CREATE_INFO{ constexpr VkPipelineViewportStateCreateInfo PIPELINE_VIEWPORT_STATE_CREATE_INFO{
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -802,6 +805,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe
.pAttachments = &blend_attachment, .pAttachments = &blend_attachment,
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
}; };
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -809,7 +813,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr, .pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
@ -833,6 +837,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
} }
blit_depth_stencil_keys.push_back(key); blit_depth_stencil_keys.push_back(key);
const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag); const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -840,7 +845,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr, .pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
@ -885,6 +890,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel
.pAttachments = &color_blend_attachment_state, .pAttachments = &color_blend_attachment_state,
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
}; };
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -892,7 +898,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr, .pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
@ -940,6 +946,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
.minDepthBounds = 0.0f, .minDepthBounds = 0.0f,
.maxDepthBounds = 0.0f, .maxDepthBounds = 0.0f,
}; };
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -947,7 +954,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr, .pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
@ -970,6 +977,7 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
} }
VkShaderModule frag_shader = *convert_float_to_depth_frag; VkShaderModule frag_shader = *convert_float_to_depth_frag;
const std::array stages = MakeStages(*full_screen_vert, frag_shader); const std::array stages = MakeStages(*full_screen_vert, frag_shader);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline({ pipeline = device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -977,7 +985,7 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr, .pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
@ -999,6 +1007,7 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend
} }
VkShaderModule frag_shader = *convert_depth_to_float_frag; VkShaderModule frag_shader = *convert_depth_to_float_frag;
const std::array stages = MakeStages(*full_screen_vert, frag_shader); const std::array stages = MakeStages(*full_screen_vert, frag_shader);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline({ pipeline = device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -1006,7 +1015,7 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr, .pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
@ -1029,6 +1038,7 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
return; return;
} }
const std::array stages = MakeStages(*full_screen_vert, *module); const std::array stages = MakeStages(*full_screen_vert, *module);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline({ pipeline = device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -1036,7 +1046,7 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr, .pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
@ -1070,6 +1080,7 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende
VkShaderModule frag_shader = VkShaderModule frag_shader =
is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag; is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
const std::array stages = MakeStages(*full_screen_vert, frag_shader); const std::array stages = MakeStages(*full_screen_vert, frag_shader);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
pipeline = device.GetLogical().CreateGraphicsPipeline({ pipeline = device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -1077,7 +1088,7 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende
.stageCount = static_cast<u32>(stages.size()), .stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(), .pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr, .pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,

View file

@ -400,12 +400,12 @@ static vk::Pipeline CreateWrappedPipelineImpl(
.pVertexAttributeDescriptions = nullptr, .pVertexAttributeDescriptions = nullptr,
}; };
constexpr VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{ const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
.primitiveRestartEnable = VK_FALSE, .primitiveRestartEnable = device.IsMoltenVK() ? VK_TRUE : VK_FALSE,
}; };
constexpr VkPipelineViewportStateCreateInfo viewport_state_ci{ constexpr VkPipelineViewportStateCreateInfo viewport_state_ci{

View file

@ -635,14 +635,16 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
.flags = 0, .flags = 0,
.topology = input_assembly_topology, .topology = input_assembly_topology,
.primitiveRestartEnable = .primitiveRestartEnable =
dynamic.primitive_restart_enable != 0 && // MoltenVK/Metal always has primitive restart enabled and cannot disable it
device.IsMoltenVK() ? VK_TRUE :
(dynamic.primitive_restart_enable != 0 &&
((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
device.IsTopologyListPrimitiveRestartSupported()) || device.IsTopologyListPrimitiveRestartSupported()) ||
SupportsPrimitiveRestart(input_assembly_topology) || SupportsPrimitiveRestart(input_assembly_topology) ||
(input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && (input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
device.IsPatchListPrimitiveRestartSupported())) device.IsPatchListPrimitiveRestartSupported()))
? VK_TRUE ? VK_TRUE
: VK_FALSE, : VK_FALSE),
}; };
const VkPipelineTessellationStateCreateInfo tessellation_ci{ const VkPipelineTessellationStateCreateInfo tessellation_ci{
.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,

View file

@ -1,3 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -8,4 +10,4 @@
#define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#include <vk_mem_alloc.h> #include "vk_mem_alloc.h"

View file

@ -725,6 +725,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
dynamic_state3_enables = true; dynamic_state3_enables = true;
} }
if (is_mvk && Settings::values.dyna_state.GetValue() != 0) {
LOG_WARNING(Render_Vulkan, "MoltenVK detected: Forcing dynamic state to 0 to prevent black screen issues");
Settings::values.dyna_state.SetValue(0);
}
if (Settings::values.dyna_state.GetValue() == 0) { if (Settings::values.dyna_state.GetValue() == 0) {
must_emulate_scaled_formats = true; must_emulate_scaled_formats = true;
LOG_INFO(Render_Vulkan, "Dynamic state is disabled (dyna_state = 0), forcing scaled format emulation ON"); LOG_INFO(Render_Vulkan, "Dynamic state is disabled (dyna_state = 0), forcing scaled format emulation ON");
@ -753,18 +758,24 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
functions.vkGetInstanceProcAddr = dld.vkGetInstanceProcAddr; functions.vkGetInstanceProcAddr = dld.vkGetInstanceProcAddr;
functions.vkGetDeviceProcAddr = dld.vkGetDeviceProcAddr; functions.vkGetDeviceProcAddr = dld.vkGetDeviceProcAddr;
const VmaAllocatorCreateInfo allocator_info = { VmaAllocatorCreateFlags flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT, if (extensions.memory_budget) {
.physicalDevice = physical, flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
.device = *logical, }
.preferredLargeHeapBlockSize = 0, const VmaAllocatorCreateInfo allocator_info{
.pAllocationCallbacks = nullptr, .flags = flags,
.pDeviceMemoryCallbacks = nullptr, .physicalDevice = physical,
.pHeapSizeLimit = nullptr, .device = *logical,
.pVulkanFunctions = &functions, .preferredLargeHeapBlockSize = is_integrated
.instance = instance, ? (64u * 1024u * 1024u)
.vulkanApiVersion = VK_API_VERSION_1_1, : (256u * 1024u * 1024u),
.pTypeExternalMemoryHandleTypes = nullptr, .pAllocationCallbacks = nullptr,
.pDeviceMemoryCallbacks = nullptr,
.pHeapSizeLimit = nullptr,
.pVulkanFunctions = &functions,
.instance = instance,
.vulkanApiVersion = ApiVersion(),
.pTypeExternalMemoryHandleTypes = nullptr,
}; };
vk::Check(vmaCreateAllocator(&allocator_info, &allocator)); vk::Check(vmaCreateAllocator(&allocator_info, &allocator));
@ -1090,8 +1101,15 @@ bool Device::GetSuitability(bool requires_swapchain) {
// Some features are mandatory. Check those. // Some features are mandatory. Check those.
#define CHECK_FEATURE(feature, name) \ #define CHECK_FEATURE(feature, name) \
if (!features.feature.name) { \ if (!features.feature.name) { \
LOG_ERROR(Render_Vulkan, "Missing required feature {}", #name); \ if (IsMoltenVK() && (strcmp(#name, "geometryShader") == 0 || \
suitable = false; \ strcmp(#name, "logicOp") == 0 || \
strcmp(#name, "shaderCullDistance") == 0 || \
strcmp(#name, "wideLines") == 0)) { \
LOG_INFO(Render_Vulkan, "MoltenVK missing feature {} - using fallback", #name); \
} else { \
LOG_ERROR(Render_Vulkan, "Missing required feature {}", #name); \
suitable = false; \
} \
} }
#define LOG_FEATURE(feature, name) \ #define LOG_FEATURE(feature, name) \
@ -1378,13 +1396,13 @@ void Device::CollectPhysicalMemoryInfo() {
device_access_memory += mem_properties.memoryHeaps[element].size; device_access_memory += mem_properties.memoryHeaps[element].size;
} }
if (!is_integrated) { if (!is_integrated) {
const u64 reserve_memory = std::min<u64>(device_access_memory / 4, 2_GiB); const u64 reserve_memory = std::min<u64>(device_access_memory / 8, 1_GiB);
device_access_memory -= reserve_memory; device_access_memory -= reserve_memory;
if (Settings::values.vram_usage_mode.GetValue() != Settings::VramUsageMode::Aggressive) { if (Settings::values.vram_usage_mode.GetValue() != Settings::VramUsageMode::Aggressive) {
// Account for resolution scaling in memory limits // Account for resolution scaling in memory limits
const size_t normal_memory = 8_GiB; const size_t normal_memory = 6_GiB;
const size_t scaler_memory = 2_GiB * Settings::values.resolution_info.ScaleUp(1); const size_t scaler_memory = 1_GiB * Settings::values.resolution_info.ScaleUp(1);
device_access_memory = device_access_memory =
std::min<u64>(device_access_memory, normal_memory + scaler_memory); std::min<u64>(device_access_memory, normal_memory + scaler_memory);
} }
@ -1393,7 +1411,7 @@ void Device::CollectPhysicalMemoryInfo() {
} }
const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage); const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage);
device_access_memory = static_cast<u64>(std::max<s64>( device_access_memory = static_cast<u64>(std::max<s64>(
std::min<s64>(available_memory - 4_GiB, 6_GiB), std::min<s64>(local_memory, 6_GiB))); std::min<s64>(available_memory - 8_GiB, 6_GiB), std::min<s64>(local_memory, 6_GiB)));
} }
void Device::CollectToolingInfo() { void Device::CollectToolingInfo() {

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