Compare commits

...

102 commits

Author SHA1 Message Date
lizzie
2c5082b397 fix shit 2026-03-16 22:34:46 +00:00
lizzie
c79ca350c2 fix nproc 2026-03-16 21:39:17 +00:00
lizzie
7917880f03 disable openssl and register user 2026-03-16 21:38:52 +00:00
lizzie
c564f8be30 needs libscienternal 2026-03-16 21:35:03 +00:00
lizzie
fc5ac0bade try fix musl 2 2026-03-16 21:35:03 +00:00
lizzie
45dd3db6b5 native ps4 audio sink 2026-03-16 21:35:03 +00:00
lizzie
b303045891 init audio 2026-03-16 21:34:50 +00:00
lizzie
c653070510 fix virtual buffers 2026-03-16 21:34:50 +00:00
lizzie
1ad9184e25 fix openssl 2026-03-16 21:34:50 +00:00
lizzie
9c9c655c80 disable stdio buffering 2026-03-16 21:34:50 +00:00
lizzie
d3e8f03e97 FX 2026-03-16 21:34:50 +00:00
lizzie
7745d51001 let it rip 2026-03-16 21:34:50 +00:00
lizzie
caa2651163 leave pending param package stuff 2026-03-16 21:34:50 +00:00
lizzie
11772e7387 restore protection 2026-03-16 21:34:50 +00:00
lizzie
eac83f6711 immediately terminate in OO, use 2MB swap handler 2026-03-16 21:34:49 +00:00
lizzie
1572330c33 use btver2 2026-03-16 21:34:49 +00:00
lizzie
f5d21b6731 reduce fiber sizes 2026-03-16 21:34:49 +00:00
lizzie
cffa389461 fix yuzu cpp 2026-03-16 21:34:49 +00:00
lizzie
3f61c8be44 use dmem for swap buffers, restore full jit sizes 2026-03-16 21:34:49 +00:00
lizzie
7910f56263 force ankerl + fixup for OO with prelude commits 2026-03-16 21:34:49 +00:00
lizzie
10e084e854 add hash 2026-03-16 21:34:49 +00:00
lizzie
6e76c54864 fix 2026-03-16 21:34:49 +00:00
lizzie
73ec45523c fixup shit 2026-03-16 21:34:49 +00:00
lizzie
bedb2e07c7 SDL2 PS4 patch 2026-03-16 21:34:49 +00:00
lizzie
a9845aa570 use newer sdl2, make bigger stack 2026-03-16 21:34:49 +00:00
lizzie
30dd3fa1f3 mark codeblocks as noexcept 2026-03-16 21:34:49 +00:00
lizzie
0be3261b0b fix ps4/orbis 2026-03-16 21:34:48 +00:00
lizzie
1dd80ca391 fix2 2026-03-16 21:34:48 +00:00
lizzie
bf489567ed make a bit more mergeable 2026-03-16 21:34:48 +00:00
lizzie
57fe2c67c9 Use updated SDL2 2026-03-16 21:34:48 +00:00
lizzie
a0671fe6f9 revert input system to main 2026-03-16 21:34:48 +00:00
lizzie
2b541d0f05 stub add proper iostream init 2026-03-16 21:34:48 +00:00
lizzie
99365e445e ps4 icon 2026-03-16 21:34:48 +00:00
lizzie
f40648da3e update loicense 2026-03-16 21:34:48 +00:00
lizzie
4359353d9a restore stupid lock, make ps4sup library 2026-03-16 21:34:48 +00:00
lizzie
8192b57a36 bs fix 2026-03-16 21:34:46 +00:00
lizzie
49d4505e1c fix eboot 2026-03-16 21:34:32 +00:00
lizzie
bee5ce95cb temp fix for dpad 2026-03-16 21:34:32 +00:00
lizzie
e0824f4865 add emutls.c 2026-03-16 21:34:32 +00:00
lizzie
afad0f6a4e reduce arm codeisze, force 16x4 pages again 2026-03-16 21:34:32 +00:00
lizzie
640d3d2894 extra buffer precautions to not exhaust DMem, format better + perf history nerf 2026-03-16 21:34:32 +00:00
lizzie
b93d351e6b more inline pt2 2026-03-16 21:34:32 +00:00
lizzie
b6b8918f26 fix atexit impl 2026-03-16 21:34:32 +00:00
lizzie
6dff84150e fibers that don't immediately crash?!!?!?!!? 2026-03-16 21:34:32 +00:00
lizzie
38804535fc add fallback buffer back 2026-03-16 21:34:32 +00:00
lizzie
1be302ae7d force running services on host 2026-03-16 21:34:31 +00:00
lizzie
88aeddf321 fix alloc failures 2026-03-16 21:34:31 +00:00
lizzie
5222ecb412 fix sdl2 2026-03-16 21:34:31 +00:00
lizzie
d17ee07463 fix for crashes on TLS due to openorbis being W E I R D 2026-03-16 21:34:31 +00:00
lizzie
72df03302c opengl bullshit 2026-03-16 21:34:31 +00:00
lizzie
f80688c04c proper memswap mechanism 2026-03-16 21:34:31 +00:00
lizzie
d11f8864ff more stupid stuff 2026-03-16 21:34:31 +00:00
lizzie
26e4f59c16 fixes 4 stuff 2026-03-16 21:34:31 +00:00
lizzie
236b0a7c51 swap handling 2026-03-16 21:34:31 +00:00
lizzie
369e15776b license 2026-03-16 21:34:29 +00:00
lizzie
70967e0b2c add sce_module so it loads on real hw 2026-03-16 21:32:33 +00:00
lizzie
f61de8ab9f fixes for mbedtls 2026-03-16 21:32:33 +00:00
lizzie
e73f7d786a adapt to new master 2026-03-16 21:32:33 +00:00
lizzie
f907eb58b8 evil haxx 2026-03-16 21:32:33 +00:00
lizzie
a61fd63993 extra ps4 defs 2026-03-16 21:32:33 +00:00
lizzie
edb208f894 make virtual buffer become an optional 2026-03-16 21:32:33 +00:00
lizzie
877d42131c force NO fastmem 2026-03-16 21:32:33 +00:00
lizzie
762a42869a more memory shit 2026-03-16 21:32:33 +00:00
lizzie
4dcddffd8b MAP_SYSTEM 2026-03-16 21:32:32 +00:00
lizzie
c727f90b50 (likely) fixes for virtual dmem? 2026-03-16 21:32:32 +00:00
lizzie
60d5e32524 disable fastmem 2026-03-16 21:32:32 +00:00
lizzie
3c18308c22 try to fix the paths 2026-03-16 21:32:32 +00:00
lizzie
9cb8f0baa8 sysconf stub cuz crash(?) + some stderrp stuff 2026-03-16 21:32:32 +00:00
lizzie
41f91ece33 the orb 2026-03-16 21:32:31 +00:00
lizzie
d3c9866d22 fself + pkg stuffs 2026-03-16 21:32:31 +00:00
lizzie
a679230e8f make .pkg and .self 2026-03-16 21:32:31 +00:00
lizzie
3b9b120ab3 exclude more stuff from vulkan 2026-03-16 21:32:31 +00:00
lizzie
213df5d4ed exclude from vulkan surface selection 2026-03-16 21:32:31 +00:00
lizzie
946307cb04 buildable toolchain script + fixes for ffmpeg 2026-03-16 21:32:31 +00:00
lizzie
78321c9ecb merge 2026-03-16 21:32:31 +00:00
lizzie
973b701e5a merge 2026-03-16 21:32:30 +00:00
lizzie
7d9e804d69 fix 2026-03-16 21:32:30 +00:00
lizzie
88aa1f0717 toolchain-fix 2026-03-16 21:32:30 +00:00
lizzie
2701ae2ee0 fuck you 2026-03-16 21:32:30 +00:00
lizzie
43496e7ec7 no conversion fixs 2026-03-16 21:32:30 +00:00
crueter
f0a4ac7359
[frontend] only set https on Android (#3733)
Some checks failed
tx-src / sources (push) Has been cancelled
Check Strings / check-strings (push) Has been cancelled
Otherwise it breaks the shit out of every other platform.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3733
2026-03-15 02:57:32 +01:00
Eden CI
d604a9da7b
[dist, android] Update translations from Transifex for Mar 14 (#3732)
Automatic translation update for Mar 14

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3732
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: Eden CI <ci@eden-emu.dev>
Co-committed-by: Eden CI <ci@eden-emu.dev>
2026-03-15 02:52:34 +01:00
lizzie
0ec60f21ff
Revert "[updater] Explicit set https for api url (#3720)" (#3726)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
#3720 was merged without proper revision.
AAAA
It's fine, if there are issues just merge the revert of.

This reverts commit 8de1dd151f.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3726
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-03-15 02:06:29 +01:00
crueter
9cf1e19d98
[externals] Update SDL2 (#3731)
https://github.com/libsdl-org/SDL/pull/15207

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3731
2026-03-15 01:45:11 +01:00
John
98a93561de
Revert #3690 to fix regression. (#3728)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
- Fixes Ender Magnolia and Demon Slayer freezing on Android.

May be related to this PR or other fixes on the master but:
- Using Cure in Ender Magnolia no longer crashes the game.
- Fixes Demon Slayer vertex explosion on Android.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3728
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: John <john@eden-emu.dev>
Co-committed-by: John <john@eden-emu.dev>
2026-03-14 19:37:24 +01:00
xbzk
4a60085a76
[android,settings] fix for *_combined (fastmem, gpu unswizzle) kotlin side only settings being unnecesarily requested to native (#3724)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Fixes jni reporting error when these settings change.
Combined settings are the grouping reference for settings like gpu unswizzle.
As far as i recall, fastmen only uses it coz it has a sub setting in the past.

[ 445.450666] Frontend <Error> main/jni/native_config.cpp:33:getSetting: [Android Native] Could not find setting - gpu_unswizzle_combined
[ 450.054470] Frontend <Error> main/jni/native_config.cpp:33:getSetting: [Android Native] Could not find setting - fastmem_combined

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3724
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
2026-03-14 03:30:37 +01:00
PavelBARABANOV
47ed86d3e2
[vk] Partial return of the old buffer update logic (#3690)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Fixes shadows in Metroid Prime Remastered

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3690
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: PavelBARABANOV <pavelbarabanov94@gmail.com>
Co-committed-by: PavelBARABANOV <pavelbarabanov94@gmail.com>
2026-03-13 19:59:11 +01:00
xbzk
2aea7f9584
[android,settings] addons: fix crash when launching Install addons from per game addons menu (#3727)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
to fix navigation issues (PR3699), i've bounded all orphaned fragments to SettingsSubscreenActivity.
(IIRC that were tested, whatever) Somehow the launching from per-game settings (where addons fragment is bounded to MainActivity got broken).
This PR just made ContentTypeSelectionDialogFragment self-sufficient so it lives under both MainActivity and SettingsSubscreenActivity.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3727
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
2026-03-13 19:46:35 +01:00
lizzie
59b0e66722
Revert "[core/memory] remove indirection handling for unaligned access (#3584)" (#3725)
This reverts commit 2d27359074.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3725
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-03-13 19:09:53 +01:00
DraVee
8de1dd151f
[updater] Explicit set https for api url (#3720)
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3720
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: DraVee <chimera@dravee.dev>
Co-committed-by: DraVee <chimera@dravee.dev>
2026-03-13 17:55:38 +01:00
DraVee
98604d369a
[vulkan] Revert "[vulkan]fix vuid 02751 (#3573)" (#3721)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Attached backtrace on PR comments

This reverts commit cdf9b556b2.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3721
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: DraVee <chimera@dravee.dev>
Co-committed-by: DraVee <chimera@dravee.dev>
2026-03-13 02:47:47 +01:00
lizzie
4337135910
[common/logging] fix android stupid ctor() init order not initializing logging first (#3719)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3719
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-03-12 23:16:56 +01:00
lizzie
395613b01f
[common/logging] Simplify logging logic and fix issues when logging before system is created (#3688)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
- our logging code was bigger than spdlog itself, why???? just keep it simple
- fix issues when logging before logging system is even started
- removes the "initialized logging twice" issue
- removes uneeded indirection in file logging
- uses direct formatting instead of jumping hoopla-around the fmt::format() ressult
- code duplication and dead code removal as usual

I did explore dup2() but I think it's not worth the hassle
I did try `fwopen()` but it's better if things are just kept as-is.

there is a lot of noise because I removed a bunch of redundant files on logging and just put everything in one file

now normally this wouldn't be a good idea, however consider: the complexity of logging; it's less than 500 lines... does it really need a whole subsystem?!?!?! ITS JUST LOGGING

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3688
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-03-12 18:29:15 +01:00
xbzk
2896fa3835
[android,ui] chore: settings subscreens transition and other minor conformances (#3699)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
- Fix black screen in transition animations

- Adjustments to about fragment
made about text more label and less button like, header transparency, spacing adjustments, word Contributors replaced by People in Contributors field for de-duplication.

- installable actions code de-duplication
Extracted install/update/import firmware/user data flows into InstallableActions.kt and reused it from MainActivity and InstallableFragment, reducing duplicated logic, ensuring single source of truth.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3699
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
2026-03-11 22:47:16 +01:00
lizzie
0dad29698e
[frontend] allow to specify input profile name for first player on command line (#3684)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3684
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-03-11 16:50:00 +01:00
lizzie
5a0780b826
[video_core] Properly disable/avoid building OpenGL when it's disabled (#3692)
- OpenGL symbols would still be included in builds without OpenGL, this pr fixes that
- Same goes for Vulkan, but now with `ENABLE_VULKAN`
- Add support to have OpenGL-only builds (why would you do this?)
- Add support for headless runs (yes you could just select NULL backend, but why not compile it headless? :)

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3692
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-03-11 16:49:29 +01:00
lizzie
d35fc7b7ee
[docs] testing guidelines, unify controller guide, gamemode (#3709)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3709
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-03-11 16:49:03 +01:00
crueter
8678cb06eb
[meta] clang-format literally all of the Qt code (#3706)
Some checks failed
tx-src / sources (push) Has been cancelled
Check Strings / check-strings (push) Has been cancelled
I'm tired of dealing with this tbh

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3706
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-03-10 06:51:08 +01:00
crueter
769edbfea3
[video_core] Revert "Simplify TextureCache GC and remove redundant code" (#3652) (#3704)
regr. Steam Deck

Please, for the love of God, stop saying "YOLO good to merge" after
testers report performance regressions (and promptly get brushed to the
side). Seriously, what the hell?

This reverts commit f8ea09fa0f.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3704
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: DraVee <chimera@dravee.dev>
2026-03-10 05:44:51 +01:00
crueter
0ff1d215c8
[desktop] Port some QtCommon changes from QML branch (#3703)
- Linker now resolves implementation differences
- Remove unneeded ifdefs
- Better abstractions overall

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3703
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-03-10 05:37:45 +01:00
crueter
07e3a2aa46
[settings] Disable fastmem on Linux systems with non-4kb page sizes (#3669)
Asahi, etc

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3669
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-03-10 05:36:12 +01:00
xbzk
a1b50e9339
[android] patches bin button + version bug fixes (#3691)
Some checks failed
tx-src / sources (push) Has been cancelled
Check Strings / check-strings (push) Has been cancelled
This fixed the delete button enabled for external content (which is auto handled and the proper way to get rid of them is either by removing its folder from ext content list, or removing the file itself) by streaming patch source thru jni.

Along the way stumbled upon another bug: If you have an external content update installed (say latest version for example) and you NAND install a previous update (like in silksong's hard mode update), the newest update version string would leak to the previous one.

Did videos for both. Fixed both. Seems good to go.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3691
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: DraVee <chimera@dravee.dev>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
2026-03-09 00:30:10 +01:00
526 changed files with 55693 additions and 39194 deletions

View file

@ -115,7 +115,7 @@ for file in $FILES; do
*.cmake|*.sh|*CMakeLists.txt)
begin="#"
;;
*.kt*|*.cpp|*.h)
*.kt*|*.cpp|*.h|*.qml)
begin="//"
;;
*)
@ -193,7 +193,7 @@ if [ "$UPDATE" = "true" ]; then
begin="#"
shell=true
;;
*.kt*|*.cpp|*.h)
*)
begin="//"
shell="false"
;;

67
.ci/ps4/build.sh Executable file
View file

@ -0,0 +1,67 @@
#!/usr/local/bin/bash -ex
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
[ -z ${OO_PS4_TOOLCHAIN+x} ] && exit
[ -f "ps4-toolchain.cmake" ] || cat << EOF >"ps4-toolchain.cmake"
set(CMAKE_SYSROOT "$OO_PS4_TOOLCHAIN")
set(CMAKE_STAGING_PREFIX "$OO_PS4_TOOLCHAIN")
set(CMAKE_SYSTEM_NAME "OpenOrbis")
set(CMAKE_C_FLAGS " -D__OPENORBIS__ -D_LIBCPP_HAS_MUSL_LIBC=1 -D_GNU_SOURCE=1 --target=x86_64-pc-freebsd12-elf -mtune=btver2 -march=btver2 -fPIC -funwind-tables")
set(CMAKE_CXX_FLAGS " -D__OPENORBIS__ -D_LIBCPP_HAS_MUSL_LIBC=1 -D_GNU_SOURCE=1 --target=x86_64-pc-freebsd12-elf -mtune=btver2 -march=btver2 -fPIC -funwind-tables")
set(CMAKE_EXE_LINKER_FLAGS "-m elf_x86_64 -pie -T $OO_PS4_TOOLCHAIN/link.x --eh-frame-hdr -L$OO_PS4_TOOLCHAIN/lib")
set(CMAKE_C_LINK_FLAGS "-m elf_x86_64 -pie -T $OO_PS4_TOOLCHAIN/link.x --eh-frame-hdr -L$OO_PS4_TOOLCHAIN/lib")
set(CMAKE_CXX_LINK_FLAGS "-m elf_x86_64 -pie -T $OO_PS4_TOOLCHAIN/link.x --eh-frame-hdr -L$OO_PS4_TOOLCHAIN/lib")
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_LINKER ld.lld)
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_C_LINK_FLAGS> <OBJECTS> -o <TARGET> -lc -lkernel -lSceUserService -lSceSysmodule -lSceNet -lSceLibcInternal $OO_PS4_TOOLCHAIN/lib/crt1.o <LINK_LIBRARIES>")
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_CXX_LINK_FLAGS> <OBJECTS> -o <TARGET> -lc -lkernel -lc++ -lSceUserService -lSceSysmodule -lSceNet -lSceLibcInternal $OO_PS4_TOOLCHAIN/lib/crt1.o <LINK_LIBRARIES>")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# TODO: Why does cmake not set this?
set(CMAKE_SIZEOF_VOID_P 8)
EOF
[ -z ${NPROC+x} ] && NPROC=$(nproc || 1)
# Normally a platform has a package manager
# PS4 does not, atleast not in the normal sense
export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" $@)
cmake -S . -B build -G "Unix Makefiles" \
-DCMAKE_TOOLCHAIN_FILE="ps4-toolchain.cmake" \
-DENABLE_QT_TRANSLATION=OFF \
-DENABLE_CUBEB=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS" \
-DCMAKE_C_FLAGS="$ARCH_FLAGS" \
-DENABLE_SDL2=ON \
-DENABLE_LIBUSB=OFF \
-DENABLE_UPDATE_CHECKER=OFF \
-DENABLE_QT=OFF \
-DENABLE_OPENSSL=OFF \
-DENABLE_WEB_SERVICE=OFF \
-DUSE_DISCORD_PRESENCE=OFF \
-DCPMUTIL_FORCE_BUNDLED=ON \
-DOPENSSL_ROOT_DIR="$OO_PS4_TOOLCHAIN" \
-DOPENSSL_SSL_LIBRARY="$OO_PS4_TOOLCHAIN/lib/libssl.a" \
-DOPENSSL_CRYPTO_LIBRARY="$OO_PS4_TOOLCHAIN/lib/libcrypto.a" \
-DOPENSSL_INCLUDE_DIR="$OO_PS4_TOOLCHAIN/include/openssl" \
-DYUZU_USE_EXTERNAL_FFMPEG=ON \
-DYUZU_USE_CPM=ON \
-DDYNARMIC_ENABLE_NO_EXECUTE_SUPPORT=OFF \
-DDYNARMIC_TESTS=ON \
-DYUZU_USE_EXTERNAL_SDL2=ON \
"${EXTRA_CMAKE_FLAGS[@]}" || exit
cmake --build build -t yuzu-cmd_pkg -- -j$NPROC
#cmake --build build -t dynarmic_tests_pkg -- -j$NPROC
#cmake --build build -t testps4_pkg -- -j$NPROC

176
.ci/ps4/make-toolchain.sh Executable file
View file

@ -0,0 +1,176 @@
#!/usr/local/bin/bash -ex
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# Define global vars
# These flags are used everywhere, so let's reuse them.
export OO_PS4_TOOLCHAIN="$PWD/prefix"
export PREFIX="$OO_PS4_TOOLCHAIN"
export CC="clang"
export CXX="clang++"
export AR="llvm-ar"
export CFLAGS="-fPIC -DPS4 -D_LIBUNWIND_IS_BAREMETAL=1"
export CXXFLAGS="$CFLAGS -D__STDC_VERSION__=0"
export TARGET="x86_64-scei-ps4"
export LLVM_ROOT="$PWD/llvm-project"
export LLVM_PATH="$PWD/llvm-project/llvm"
export WORK_PATH="$PWD"
prepare_prefix() {
[ -d OpenOrbis-PS4-Toolchain ] || git clone --depth=1 https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain
[ -d musl ] || git clone --depth=1 https://github.com/OpenOrbis/musl
[ -d llvm-project ] || git clone --depth=1 --branch openorbis/20.x https://github.com/seuros/llvm-project
[ -d create-fself ] || git clone --depth=1 https://github.com/OpenOrbis/create-fself
[ -d create-gp4 ] || git clone --depth=1 https://github.com/OpenOrbis/create-gp4
[ -d readoelf ] || git clone --depth=1 https://github.com/OpenOrbis/readoelf
[ -d LibOrbisPkg ] || git clone --depth=1 https://github.com/maxton/LibOrbisPkg
mkdir -p $PREFIX "$PREFIX/bin" "$PREFIX/include"
[ -f "$PREFIX/include/orbis/libkernel.h" ] || cp -r OpenOrbis-PS4-Toolchain/include/* "$PREFIX/include/"
mkdir -p $PREFIX/usr
[ -L "$PREFIX/usr/include" ] || ln -s $PREFIX/include $PREFIX/usr/include || echo 1
[ -L "$PREFIX/usr/share" ] || ln -s $PREFIX/share $PREFIX/usr/share || echo 1
[ -L "$PREFIX/usr/lib" ] || ln -s $PREFIX/lib $PREFIX/usr/lib || echo 1
[ -L "$PREFIX/usr/bin" ] || ln -s $PREFIX/bin $PREFIX/usr/bin || echo 1
}
build_musl() {
mkdir -p musl-build
cd musl-build
../musl/configure --target=$TARGET --disable-shared CC="$CC" CFLAGS="$CFLAGS" --prefix=$PREFIX
gmake -j8 && gmake install
cd ..
}
build_llvm() {
# Build compiler-rt
cmake "$LLVM_ROOT/compiler-rt" -B "$WORK_PATH/llvm-build/compiler-rt" \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" \
-DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \
-DCMAKE_ASM_COMPILER="$CC" -DCMAKE_ASM_FLAGS="$CFLAGS -x assembler-with-cpp" \
-DLLVM_PATH="$LLVM_PATH" -DCOMPILER_RT_DEFAULT_TARGET_TRIPLE="$TARGET" \
-DCOMPILER_RT_BAREMETAL_BUILD=YES -DCOMPILER_RT_BUILD_BUILTINS=ON \
-DCOMPILER_RT_BUILD_CRT=OFF -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
-DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
-DCOMPILER_RT_BUILD_PROFILE=OFF -DCOMPILER_RT_STANDALONE_BUILD=ON
# Build libunwind
cmake "$LLVM_ROOT/libunwind" -B "$WORK_PATH/llvm-build/libunwind" \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" \
-DCMAKE_C_FLAGS="$CFLAGS -fcxx-exceptions" -DCMAKE_CXX_FLAGS="$CXXFLAGS -fcxx-exceptions" \
-DCMAKE_ASM_COMPILER="$CC" -DCMAKE_ASM_FLAGS="$CFLAGS -x assembler-with-cpp" \
-DLLVM_PATH="$LLVM_PATH" -DLIBUNWIND_USE_COMPILER_RT=YES \
-DLIBUNWIND_BUILD_32_BITS=NO -DLIBUNWIND_ENABLE_STATIC=ON \
-DLIBUNWIND_ENABLE_SHARED=OFF -DLIBUNWIND_IS_BAREMETAL=ON
# Build libcxxabi
cmake "$LLVM_ROOT/libcxxabi" -B "$WORK_PATH/llvm-build/libcxxabi" \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" \
-DCMAKE_C_FLAGS="$CFLAGS -D_GNU_SOURCE=1 -isysroot $PREFIX -isystem $LLVM_ROOT/libcxx/include -isystem $PREFIX/include -isystem $WORK_PATH/llvm-build/libcxx/include/c++/v1" \
-DCMAKE_CXX_FLAGS="$CXXFLAGS -D_GNU_SOURCE=1 -isysroot $PREFIX -isystem $LLVM_ROOT/libcxx/include -isystem $PREFIX/include -isystem $WORK_PATH/llvm-build/libcxx/include/c++/v1" \
-DCMAKE_ASM_COMPILER="$CC" -DCMAKE_ASM_FLAGS="$CFLAGS -x assembler-with-cpp" \
-DLLVM_PATH="$LLVM_PATH" -DLIBCXXABI_ENABLE_SHARED=NO \
-DLLVM_ENABLE_RUNTIMES="rt;libunwind" \
-DLIBCXXABI_ENABLE_STATIC=YES -DLIBCXXABI_ENABLE_EXCEPTIONS=YES \
-DLIBCXXABI_USE_COMPILER_RT=YES -DLIBCXXABI_USE_LLVM_UNWINDER=YES \
-DLIBCXXABI_LIBUNWIND_PATH="$LLVM_ROOT/libunwind" \
-DLIBCXXABI_LIBCXX_INCLUDES="$LLVM_ROOT/libcxx/include" \
-DLIBCXXABI_ENABLE_PIC=YES
# Build libcxx
cmake "$LLVM_ROOT/libcxx" -B "$WORK_PATH/llvm-build/libcxx" \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" \
-DCMAKE_C_FLAGS="$CFLAGS -D_LIBCPP_HAS_MUSL_LIBC=1 -D_GNU_SOURCE=1 -isysroot $PREFIX -isystem $PREFIX/include/c++/v1 -isystem $PREFIX/include" \
-DCMAKE_CXX_FLAGS="$CXXFLAGS -D_LIBCPP_HAS_MUSL_LIBC=1 -D_GNU_SOURCE=1 -isysroot $PREFIX -isystem $PREFIX/include/c++/v1 -isystem $PREFIX/include" \
-DCMAKE_ASM_COMPILER="$CC" -DCMAKE_ASM_FLAGS="$CFLAGS -x assembler-with-cpp" \
-DLLVM_PATH="$LLVM_PATH" -DLIBCXX_ENABLE_RTTI=YES \
-DLIBCXX_HAS_MUSL_LIBC=YES -DLIBCXX_ENABLE_SHARED=NO \
-DLIBCXX_CXX_ABI=libcxxabi -DLIBCXX_CXX_ABI_INCLUDE_PATHS="$LLVM_ROOT/libcxxabi/include" \
-DLIBCXX_CXX_ABI_LIBRARY_PATH="$LLVM_ROOT/libcxxabi/build/lib"
cmake --build "$WORK_PATH/llvm-build/compiler-rt" --parallel
cmake --install "$WORK_PATH/llvm-build/compiler-rt"
cmake --build "$WORK_PATH/llvm-build/libunwind" --parallel
cmake --install "$WORK_PATH/llvm-build/libunwind"
cmake --build "$WORK_PATH/llvm-build/libcxxabi" --parallel
cmake --install "$WORK_PATH/llvm-build/libcxxabi"
touch "$WORK_PATH/llvm-build/libcxx/include/c++/v1/libcxx.imp"
cmake --build "$WORK_PATH/llvm-build/libcxx" --parallel
cmake --install "$WORK_PATH/llvm-build/libcxx"
}
build_tools() {
# Build create-fself
cd create-fself/cmd/create-fself
cp go-linux.mod go.mod
go build -ldflags "-linkmode external -extldflags -static" -o create-fself
mv ./create-fself $PREFIX/bin/create-fself
cd ../../../
# Build create-gp4
cd create-gp4/cmd/create-gp4
go build -ldflags "-linkmode external -extldflags -static" -o create-gp4
mv ./create-gp4 $PREFIX/bin/create-gp4
cd ../../../
# Build readoelf
cd readoelf/cmd/readoelf
go build -ldflags "-linkmode external -extldflags -static" -o readoelf
mv ./readoelf $PREFIX/bin/readoelf
cd ../../../
# # Pull maxton's publishing tools (<3)
# # Sadly maxton has passed on, we have forked the repository and will continue to update it in the future. RIP <3
# cd $PREFIX/bin
# [ -f PkgTool.Core-linux-x64-0.2.231.zip ] || wget https://github.com/maxton/LibOrbisPkg/releases/download/v0.2/PkgTool.Core-linux-x64-0.2.231.zip
# [ -f PkgTool.Core ] || unzip PkgTool.Core-linux-x64-0.2.231.zip
# chmod +x PkgTool.Core
}
finish_prefix() {
as $WORK_PATH/OpenOrbis-PS4-Toolchain/src/crt/crtlib.S -o $PREFIX/lib/crtlib.o
cp -a $WORK_PATH/OpenOrbis-PS4-Toolchain/link.x $PREFIX/
cp -a ~/OpenOrbis/PS4Toolchain/lib/libkernel* $PREFIX/lib/
cp -a ~/OpenOrbis/PS4Toolchain/lib/libSce* $PREFIX/lib/
cp -a ~/OpenOrbis/PS4Toolchain/lib/libSDL* $PREFIX/lib/
cp -r ~/OpenOrbis/PS4Toolchain/include/SDL2 $PREFIX/include/SDL2
cp $WORK_PATH/llvm-build/compiler-rt/lib/freebsd/libclang_rt.builtins-x86_64.a $PREFIX/lib/
# Combine libc++, libc++abi and libunwind into a single archive
cat << EOF >"mri.txt"
CREATE $PREFIX/lib/libc++M.a
ADDLIB $PREFIX/lib/libunwind.a
ADDLIB $PREFIX/lib/libc++abi.a
ADDLIB $PREFIX/lib/libc++.a
SAVE
END
EOF
$AR -M < mri.txt
cp $PREFIX/lib/libc++M.a $PREFIX/lib/libc++.a
# Merge compiler-rt into libc
cat << EOF >"mri.txt"
CREATE $PREFIX/lib/libcM.a
ADDLIB $PREFIX/lib/libc.a
ADDLIB $PREFIX/lib/libclang_rt.builtins-x86_64.a
SAVE
END
EOF
$AR -M < mri.txt
cp $PREFIX/lib/libcM.a $PREFIX/lib/libc.a
rm mri.txt
}
prepare_prefix
build_musl
build_llvm
build_tools
finish_prefix

3
.gitignore vendored
View file

@ -64,3 +64,6 @@ artifacts
/install*
vulkansdk*.exe
*.tar.zst
# PS4 toolchain stuff
ps4-toolchain.cmake

View file

@ -0,0 +1,17 @@
diff --git a/libs/asio/include/boost/asio/detail/impl/socket_ops.ipp b/libs/asio/include/boost/asio/detail/impl/socket_ops.ipp
index 0129511c..10fc9b04 100644
--- a/libs/asio/include/boost/asio/detail/impl/socket_ops.ipp
+++ b/libs/asio/include/boost/asio/detail/impl/socket_ops.ipp
@@ -15,6 +15,12 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+// hacky fix for ps4
+#if defined(__OPENORBIS__)
+# define FIONBIO 0
+# define FIONREAD 1
+#endif
+
#include <boost/asio/detail/config.hpp>
#include <cctype>

View file

@ -0,0 +1,13 @@
diff --git a/unix.c b/unix.c
index 6669216..86a2faa 100644
--- a/unix.c
+++ b/unix.c
@@ -53,7 +53,7 @@
#include <poll.h>
#endif
-#if !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined)
+#if !defined(__OPENORBIS__) && !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined)
typedef int socklen_t;
#endif

View file

@ -0,0 +1,13 @@
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 611768c..8950ee4 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -118,7 +118,7 @@ static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
*
* Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7
*/
-#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM)
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM) && !defined(__OPENORBIS__)
#include <sys/param.h>
#include <sys/sysctl.h>
#if defined(KERN_ARND)

View file

@ -0,0 +1,359 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7c230473ac..b1275edb61 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -331,6 +331,13 @@ if(CYGWIN)
list(APPEND SDL_CFLAGS "-I/usr/include/mingw")
endif()
+######### *FIXME*
+if(PS4 OR ORBIS)
+ set(USE_GENERATED_CONFIG Off)
+else()
+ set(USE_GENERATED_CONFIG On)
+endif()
+
# General includes
target_compile_definitions(sdl-build-options INTERFACE "-DUSING_GENERATED_CONFIG_H")
target_include_directories(sdl-build-options BEFORE INTERFACE "${SDL2_BINARY_DIR}/include" "${SDL2_BINARY_DIR}/include-config-$<LOWER_CASE:$<CONFIG>>")
@@ -359,6 +366,15 @@ if(EMSCRIPTEN)
set(SDL_CPUINFO_ENABLED_BY_DEFAULT OFF)
endif()
+if(PS4 OR ORBIS)
+ set(SDL_ATOMIC_ENABLED_BY_DEFAULT ON)
+ set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
+ set(SDL_THREADS_ENABLED_BY_DEFAULT ON)
+ set(SDL_PTHREADS_ENABLED_BY_DEFAULT ON)
+ set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF)
+ set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF)
+endif()
+
if(VITA OR PSP OR PS2 OR N3DS)
set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF)
@@ -1478,7 +1494,42 @@ elseif(EMSCRIPTEN)
CheckPTHREAD()
CheckLibUnwind()
+elseif(PS4 OR ORBIS)
+ CheckPTHREAD()
+ if(SDL_AUDIO)
+ set(SDL_AUDIO_DRIVER_PS4 1)
+ file(GLOB PS4_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/ps4/*.c)
+ set(SOURCE_FILES ${SOURCE_FILES} ${PS4_AUDIO_SOURCES})
+ set(HAVE_SDL_AUDIO TRUE)
+ endif()
+# if(SDL_FILESYSTEM)
+# set(SDL_FILESYSTEM_PS4 1)
+# file(GLOB PS4_FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/ps4/*.c)
+# set(SOURCE_FILES ${SOURCE_FILES} ${PS4_FILESYSTEM_SOURCES})
+# set(HAVE_SDL_FILESYSTEM TRUE)
+# endif()
+ if(SDL_JOYSTICK)
+ set(SDL_JOYSTICK_PS4 1)
+ file(GLOB PS4_JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/ps4/*.c)
+ set(SOURCE_FILES ${SOURCE_FILES} ${PS4_JOYSTICK_SOURCES})
+ set(HAVE_SDL_JOYSTICK TRUE)
+ endif()
+ if(SDL_TIMERS)
+ set(SDL_TIMER_UNIX 1)
+ file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c)
+ set(SOURCE_FILES ${SOURCE_FILES} ${TIMER_SOURCES})
+ set(HAVE_SDL_TIMERS TRUE)
+ if(CLOCK_GETTIME)
+ set(HAVE_CLOCK_GETTIME 1)
+ endif()
+ endif()
+ if(SDL_VIDEO)
+ set(SDL_VIDEO_DRIVER_PS4 1)
+ file(GLOB PS4_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/ps4/*.c)
+ set(SOURCE_FILES ${SOURCE_FILES} ${PS4_VIDEO_SOURCES})
+ set(HAVE_SDL_VIDEO TRUE)
+ endif()
elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
if(SDL_AUDIO)
if(SYSV5 OR SOLARIS OR HPUX)
@@ -3039,7 +3090,7 @@ endif()
# We always need to have threads and timers around
if(NOT HAVE_SDL_THREADS)
# The emscripten platform has been carefully vetted to work without threads
- if (EMSCRIPTEN)
+ if (EMSCRIPTEN OR PS4 OR ORBIS)
set(SDL_THREADS_DISABLED 1)
file(GLOB THREADS_SOURCES ${SDL2_SOURCE_DIR}/src/thread/generic/*.c)
list(APPEND SOURCE_FILES ${THREADS_SOURCES})
diff --git a/README.md b/README.md
index fa7f7ba0b5..8d5a375694 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-# Simple DirectMedia Layer (SDL) Version 2.0
+# Simple DirectMedia Layer (SDL) Version 2.0 (For OpenOrbis PS4 SDK)
https://www.libsdl.org/
diff --git a/include/SDL_config.h b/include/SDL_config.h
index a628d86252..a101532d16 100644
--- a/include/SDL_config.h
+++ b/include/SDL_config.h
@@ -41,6 +41,10 @@
#include "SDL_config_iphoneos.h"
#elif defined(__ANDROID__)
#include "SDL_config_android.h"
+#elif defined(__PSP__)
+#include "SDL_config_psp.h"
+#elif defined(__OPENORBIS__)
+#include "SDL_config_ps4.h"
#elif defined(__OS2__)
#include "SDL_config_os2.h"
#elif defined(__EMSCRIPTEN__)
diff --git a/include/SDL_platform.h b/include/SDL_platform.h
index 36df782a4e..0cc20dc4e2 100644
--- a/include/SDL_platform.h
+++ b/include/SDL_platform.h
@@ -214,6 +214,10 @@
#if defined(PS2)
#define __PS2__ 1
#endif
+#if defined(__OPENORBIS__)
+#undef __PS4__
+#define __PS4__ 1
+#endif
/* The NACL compiler defines __native_client__ and __pnacl__
* Ref: http://www.chromium.org/nativeclient/pnacl/stability-of-the-pnacl-bitcode-abi
diff --git a/src/SDL.c b/src/SDL.c
index cfeea077e7..33fce965c0 100644
--- a/src/SDL.c
+++ b/src/SDL.c
@@ -642,6 +642,8 @@ const char *SDL_GetPlatform(void)
return "Nokia N-Gage";
#elif defined(__3DS__)
return "Nintendo 3DS";
+#elif defined(__PS4__)
+ return "PlayStation4";
#else
return "Unknown (see SDL_platform.h)";
#endif
diff --git a/src/SDL_error.c b/src/SDL_error.c
index 993f5bac55..083ebf3027 100644
--- a/src/SDL_error.c
+++ b/src/SDL_error.c
@@ -50,11 +50,14 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
va_end(ap);
}
}
-
+#ifndef __OPENORBIS__ // Yeah this is stupid but whatever
if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) {
+#endif
/* If we are in debug mode, print out the error message */
SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", error->str);
+#ifndef __OPENORBIS__ // Yeah this is stupid but whatever
}
+#endif
}
return -1;
diff --git a/src/SDL_log.c b/src/SDL_log.c
index 7a5f1dbc03..a7f3d85782 100644
--- a/src/SDL_log.c
+++ b/src/SDL_log.c
@@ -390,10 +390,12 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va
int len;
va_list aq;
+#ifndef __OPENORBIS__
/* Nothing to do if we don't have an output function */
if (!SDL_log_function) {
return;
}
+#endif
/* Make sure we don't exceed array bounds */
if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
@@ -442,7 +444,11 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va
}
SDL_LockMutex(log_function_mutex);
+#ifdef __OPENORBIS__
+ printf("%s\n", message); // just fucking do it
+#else
SDL_log_function(SDL_log_userdata, category, priority, message);
+#endif
SDL_UnlockMutex(log_function_mutex);
/* Free only if dynamically allocated */
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 421adbc76a..82d087a2f8 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -114,7 +114,10 @@ static const AudioBootStrap *const bootstrap[] = {
#ifdef SDL_AUDIO_DRIVER_N3DS
&N3DSAUDIO_bootstrap,
#endif
-#ifdef SDL_AUDIO_DRIVER_EMSCRIPTEN
+#if SDL_AUDIO_DRIVER_PS4
+ &PS4AUDIO_bootstrap,
+#endif
+#if SDL_AUDIO_DRIVER_EMSCRIPTEN
&EMSCRIPTENAUDIO_bootstrap,
#endif
#ifdef SDL_AUDIO_DRIVER_JACK
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
index 87387692ce..b1c00ba9dc 100644
--- a/src/audio/SDL_sysaudio.h
+++ b/src/audio/SDL_sysaudio.h
@@ -207,6 +207,7 @@ extern AudioBootStrap PS2AUDIO_bootstrap;
extern AudioBootStrap PSPAUDIO_bootstrap;
extern AudioBootStrap VITAAUD_bootstrap;
extern AudioBootStrap N3DSAUDIO_bootstrap;
+extern AudioBootStrap PS4AUDIO_bootstrap;
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
extern AudioBootStrap OS2AUDIO_bootstrap;
diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h
index 178218c053..a6e298a9fe 100644
--- a/src/dynapi/SDL_dynapi.h
+++ b/src/dynapi/SDL_dynapi.h
@@ -69,6 +69,8 @@
#define SDL_DYNAMIC_API 0 /* devkitARM doesn't support dynamic linking */
#elif defined(DYNAPI_NEEDS_DLOPEN) && !defined(HAVE_DLOPEN)
#define SDL_DYNAMIC_API 0 /* we need dlopen(), but don't have it.... */
+#elif defined(__OPENORBIS__) // Apparently __PS4__ getting defined is missed somewhere, I get broken static builds so force the issue
+#define SDL_DYNAMIC_API 0
#endif
/* everyone else. This is where we turn on the API if nothing forced it off. */
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 60b0daf790..34433166e8 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -106,6 +106,9 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = {
#ifdef SDL_JOYSTICK_N3DS
&SDL_N3DS_JoystickDriver
#endif
+#ifdef SDL_JOYSTICK_PS4
+ &SDL_PS4_JoystickDriver,
+#endif
#if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED)
&SDL_DUMMY_JoystickDriver
#endif
diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h
index d36f784143..6671aff2fd 100644
--- a/src/joystick/SDL_sysjoystick.h
+++ b/src/joystick/SDL_sysjoystick.h
@@ -243,6 +243,7 @@ extern SDL_JoystickDriver SDL_HAIKU_JoystickDriver;
extern SDL_JoystickDriver SDL_HIDAPI_JoystickDriver;
extern SDL_JoystickDriver SDL_RAWINPUT_JoystickDriver;
extern SDL_JoystickDriver SDL_IOS_JoystickDriver;
+extern SDL_JoystickDriver SDL_PS4_JoystickDriver;
extern SDL_JoystickDriver SDL_LINUX_JoystickDriver;
extern SDL_JoystickDriver SDL_VIRTUAL_JoystickDriver;
extern SDL_JoystickDriver SDL_WGI_JoystickDriver;
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 35f80664ab..cd8f9d3615 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -137,6 +137,10 @@ static const SDL_RenderDriver *render_drivers[] = {
#if SDL_VIDEO_RENDER_VITA_GXM
&VITA_GXM_RenderDriver,
#endif
+#if SDL_VIDEO_RENDER_PS4 && 0 // *FIXME* PS4_RenderDriver Disabled, it's software anyhow lets not reinvent...
+#error Use SoftRender for PS4 currently!
+ &PS4_RenderDriver,
+#endif
#if SDL_VIDEO_RENDER_SW
&SW_RenderDriver
#endif
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index ac5426b676..d9b5bfbc39 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -307,6 +307,7 @@ extern SDL_RenderDriver DirectFB_RenderDriver;
extern SDL_RenderDriver METAL_RenderDriver;
extern SDL_RenderDriver PS2_RenderDriver;
extern SDL_RenderDriver PSP_RenderDriver;
+extern SDL_RenderDriver PS4_RenderDriver;
extern SDL_RenderDriver SW_RenderDriver;
extern SDL_RenderDriver VITA_GXM_RenderDriver;
diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c
index 212fe9c000..a920afba0b 100644
--- a/src/thread/pthread/SDL_systhread.c
+++ b/src/thread/pthread/SDL_systhread.c
@@ -29,8 +29,10 @@
#include <pthread_np.h>
#endif
+#ifdef HAVE_SIGNAL_H
#include <signal.h>
#include <errno.h>
+#endif
#ifdef __LINUX__
#include <sys/time.h>
@@ -60,7 +62,7 @@
#endif
-#ifndef __NACL__
+#if !defined(__NACL__) && !defined(__OPENORBIS__)
/* List of signals to mask in the subthreads */
static const int sig_list[] = {
SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
@@ -162,7 +164,7 @@ void SDL_SYS_SetupThread(const char *name)
}
/* NativeClient does not yet support signals.*/
-#if !defined(__NACL__)
+#if !defined(__NACL__) && !defined(__OPENORBIS__)
/* Mask asynchronous signals for this thread */
sigemptyset(&mask);
for (i = 0; sig_list[i]; ++i) {
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index badb1a3edc..e17beb9f5c 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -471,6 +471,7 @@ extern VideoBootStrap PSP_bootstrap;
extern VideoBootStrap VITA_bootstrap;
extern VideoBootStrap RISCOS_bootstrap;
extern VideoBootStrap N3DS_bootstrap;
+extern VideoBootStrap PS4_bootstrap;
extern VideoBootStrap RPI_bootstrap;
extern VideoBootStrap KMSDRM_bootstrap;
extern VideoBootStrap KMSDRM_LEGACY_bootstrap;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 134cc05e13..f40d6104e2 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -121,6 +121,9 @@ static VideoBootStrap *bootstrap[] = {
#ifdef SDL_VIDEO_DRIVER_N3DS
&N3DS_bootstrap,
#endif
+#ifdef SDL_VIDEO_DRIVER_PS4
+ &PS4_bootstrap,
+#endif
#ifdef SDL_VIDEO_DRIVER_KMSDRM
&KMSDRM_bootstrap,
#endif
@@ -241,6 +244,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
SDL_GetWindowSizeInPixels(window, &w, &h);
if (!data) {
+
SDL_Renderer *renderer = NULL;
const char *render_driver = NULL;
const char *hint;
@@ -297,7 +301,7 @@ static int SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window, U
SDL_assert(renderer != NULL); /* should have explicitly checked this above. */
/* Create the data after we successfully create the renderer (bug #1116) */
- data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data));
+ data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(SDL_WindowTextureData));
if (!data) {
SDL_DestroyRenderer(renderer);
return SDL_OutOfMemory();

View file

@ -0,0 +1,25 @@
diff --git a/source/opt/loop_dependence.cpp b/source/opt/loop_dependence.cpp
index e41c044..a51b53b 100644
--- a/source/opt/loop_dependence.cpp
+++ b/source/opt/loop_dependence.cpp
@@ -12,6 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// PS4: issue?
+#ifdef __PS4__
+#pragma clang diagnostic ignored "-Wabsolute-value"
+#pragma clang diagnostic ignored "-Wshorten-64-to-32"
+#endif
+
#include "source/opt/loop_dependence.h"
#include <functional>
@@ -19,6 +25,7 @@
#include <string>
#include <utility>
#include <vector>
+#include <cstdlib>
#include "source/opt/instruction.h"
#include "source/opt/scalar_analysis_nodes.h"

View file

@ -0,0 +1,21 @@
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index ed7706a..51b520d 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -37,6 +37,7 @@
#define XBYAK_GNUC_PREREQ(major, minor) 0
#endif
+#if !defined(XBYAK_STD_UNORDERED_SET)
// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft.
#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)))
@@ -71,6 +72,8 @@
#define XBYAK_STD_UNORDERED_MAP std::map
#define XBYAK_STD_UNORDERED_MULTIMAP std::multimap
#endif
+#endif
+
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN

View file

@ -0,0 +1,21 @@
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index ed7706a..51b520d 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -37,6 +37,7 @@
#define XBYAK_GNUC_PREREQ(major, minor) 0
#endif
+#if !defined(XBYAK_STD_UNORDERED_SET)
// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft.
#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)))
@@ -71,6 +72,8 @@
#define XBYAK_STD_UNORDERED_MAP std::map
#define XBYAK_STD_UNORDERED_MULTIMAP std::multimap
#endif
+#endif
+
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN

View file

@ -20,6 +20,7 @@ include(UseCcache)
include(CMakeDependentOption)
include(CTest)
include(CPMUtil)
include(OpenOrbis)
if (NOT DEFINED ARCHITECTURE)
message(FATAL_ERROR "Architecture didn't make it out of scope, did you delete DetectArchitecture.cmake?")
@ -196,7 +197,7 @@ option(YUZU_USE_BUNDLED_SIRIT "Download bundled sirit" ${BUNDLED_SIRIT_DEFAULT})
# FreeBSD 15+ has libusb, versions below should disable it
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "WIN32 OR PLATFORM_LINUX OR PLATFORM_FREEBSD OR APPLE" OFF)
cmake_dependent_option(ENABLE_OPENGL "Enable OpenGL" ON "NOT WIN32 OR NOT ARCHITECTURE_arm64" OFF)
cmake_dependent_option(ENABLE_OPENGL "Enable OpenGL" ON "NOT (WIN32 AND ARCHITECTURE_arm64) AND NOT APPLE" OFF)
mark_as_advanced(FORCE ENABLE_OPENGL)
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)

View file

@ -18,10 +18,13 @@ if (DEFINED GIT_RELEASE)
set(BUILD_VERSION "${GIT_TAG}")
set(GIT_REFSPEC "${GIT_RELEASE}")
set(IS_DEV_BUILD false)
else()
elseif(DEFINED GIT_COMMIT)
string(SUBSTRING ${GIT_COMMIT} 0 10 BUILD_VERSION)
set(BUILD_VERSION "${BUILD_VERSION}-${GIT_REFSPEC}")
set(IS_DEV_BUILD true)
else()
set(BUILD_VERSION "NoGitInfo")
set(IS_DEV_BUILD true)
endif()
if (NIGHTLY_BUILD)

View file

@ -0,0 +1,46 @@
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
function(create_ps4_eboot project target content_id)
set(sce_sys_dir sce_sys)
set(sce_sys_param ${sce_sys_dir}/param.sfo)
add_custom_command(
OUTPUT "${target}.pkg"
COMMAND ${CMAKE_SYSROOT}/bin/create-fself -in=bin/${target} -out=${target}.oelf --eboot ${target}_eboot.bin
VERBATIM
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS ${project}
)
add_custom_target(${project}_pkg ALL DEPENDS "${target}.pkg")
endfunction()
function(create_ps4_pkg project target content_id)
set(sce_sys_dir sce_sys)
set(sce_sys_param ${sce_sys_dir}/param.sfo)
add_custom_command(
OUTPUT "${target}.pkg"
COMMAND ${CMAKE_SYSROOT}/bin/create-fself -in=bin/${target} -out=${target}.oelf --eboot ${target}_eboot.bin
COMMAND mkdir -p ${sce_sys_dir}
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_new ${sce_sys_param}
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} APP_TYPE --type Integer --maxsize 4 --value 1
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} APP_VER --type Utf8 --maxsize 8 --value 1.03
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} ATTRIBUTE --type Integer --maxsize 4 --value 0
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} CATEGORY --type Utf8 --maxsize 4 --value gd
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} CONTENT_ID --type Utf8 --maxsize 48 --value ${content_id}
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} DOWNLOAD_DATA_SIZE --type Integer --maxsize 4 --value 0
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} SYSTEM_VER --type Integer --maxsize 4 --value 0
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} TITLE --type Utf8 --maxsize 128 --value ${target}
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} TITLE_ID --type Utf8 --maxsize 12 --value BREW00090
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core sfo_setentry ${sce_sys_param} VERSION --type Utf8 --maxsize 8 --value 1.03
COMMAND ${CMAKE_SYSROOT}/bin/create-gp4 -out ${target}.gp4 --content-id=${content_id} --files "${target}_eboot.bin ${sce_sys_param} sce_module/libc.prx sce_module/libSceFios2.prx"
COMMAND ${CMAKE_SYSROOT}/bin/PkgTool.Core pkg_build ${target}.gp4 .
VERBATIM
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS ${project}
)
add_custom_target(${project}_pkg ALL DEPENDS "${target}.pkg")
endfunction()
if (NOT DEFINED ENV{OO_PS4_TOOLCHAIN})
set(ENV{OO_PS4_TOOLCHAIN} ${CMAKE_SYSROOT})
endif ()

View file

@ -17,7 +17,8 @@
"version": "1.57",
"find_args": "CONFIG OPTIONAL_COMPONENTS headers context system fiber filesystem",
"patches": [
"0001-clang-cl.patch"
"0001-clang-cl.patch",
"0004-openorbis.patch"
]
},
"fmt": {

215
dist/icon_variations/ps4.svg vendored Normal file
View file

@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="512"
height="512"
fill="none"
viewBox="0 0 512 512"
version="1.1"
id="svg7"
sodipodi:docname="ps4.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
inkscape:export-filename="base.svg.2026_01_12_14_43_47.0.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs7">
<linearGradient
id="linearGradient5"
inkscape:collect="always">
<stop
style="stop-color:#003e74;stop-opacity:1;"
offset="0"
id="stop4" />
<stop
style="stop-color:#2ea8ff;stop-opacity:1;"
offset="1"
id="stop5" />
</linearGradient>
<linearGradient
id="linearGradient1"
inkscape:collect="always">
<stop
style="stop-color:#3579ff;stop-opacity:1;"
offset="0"
id="stop2" />
<stop
style="stop-color:#0b00ff;stop-opacity:1;"
offset="1"
id="stop3" />
</linearGradient>
<linearGradient
id="swatch37"
inkscape:swatch="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop37" />
</linearGradient>
<linearGradient
id="swatch28"
inkscape:swatch="solid">
<stop
style="stop-color:#252525;stop-opacity:1;"
offset="0"
id="stop28" />
</linearGradient>
<linearGradient
id="swatch27"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop27" />
</linearGradient>
<linearGradient
id="swatch15"
inkscape:swatch="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop16" />
</linearGradient>
<linearGradient
id="linearGradient14"
inkscape:swatch="gradient">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop14" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop15" />
</linearGradient>
<linearGradient
id="swatch9"
inkscape:swatch="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop10" />
</linearGradient>
<linearGradient
id="swatch8"
inkscape:swatch="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop9" />
</linearGradient>
<rect
x="22.627417"
y="402.76802"
width="521.34025"
height="248.94868"
id="rect24" />
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath18">
<circle
style="opacity:1;mix-blend-mode:normal;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10.8382;stroke-opacity:0.566238;paint-order:stroke fill markers"
id="circle18"
cx="-246.8315"
cy="246.8338"
inkscape:label="Circle"
r="191.89999" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath22">
<circle
style="opacity:1;mix-blend-mode:normal;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10.8382;stroke-opacity:0.566238;paint-order:stroke fill markers"
id="circle22"
cx="256"
cy="256"
inkscape:label="Circle"
r="191.89999" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath128">
<circle
style="fill:none;fill-opacity:1;stroke:#03ffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
id="circle128"
cx="256"
cy="256"
r="192" />
</clipPath>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1"
id="linearGradient3"
x1="256"
y1="64"
x2="256"
y2="448"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1874952,0,0,-1.1874952,-47.370662,560.66391)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5"
id="linearGradient4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1.1874952,0,0,1.1874952,560.61528,-47.345282)"
x1="256"
y1="64"
x2="256"
y2="448" />
</defs>
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1"
inkscape:cx="286.49999"
inkscape:cy="236.99999"
inkscape:window-width="1600"
inkscape:window-height="849"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" />
<path
id="path8-7"
style="display:inline;mix-blend-mode:color;fill:url(#linearGradient3);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:0.566238;paint-order:stroke fill markers"
inkscape:label="Circle"
d="m 256.62812,484.66422 a 227.99908,228.00372 0 0 1 -94.5288,-20.52182 c 17.54241,-0.96226 34.77843,-4.71825 46.2868,-10.46733 12.69502,-6.3416 25.70492,-17.24174 35.38366,-26.3736 h 36.45053 c 0.93211,0.61234 1.88758,1.23061 2.86668,1.85086 4.89722,14.18571 13.27668,38.80747 17.49933,51.23264 a 227.99908,228.00372 0 0 1 -43.9582,4.27925 z m 55.26491,-6.80041 -16.39068,-41.47736 c 6.99845,3.71973 14.6813,7.07649 22.62503,9.76921 20.75463,7.03513 39.46594,9.14022 49.31353,9.76688 a 227.99908,228.00372 0 0 1 -55.54788,21.94127 z m 58.6952,-23.72487 c -8.69086,-4.31956 -29.66977,-14.9556 -49.97917,-26.83747 h 87.23219 a 227.99908,228.00372 0 0 1 -37.25302,26.83747 z m -241.49988,-8.48659 a 227.99908,228.00372 0 0 1 -23.67337,-18.35088 h 95.80906 c -1.32304,0.72101 -2.11058,1.13186 -2.11058,1.13186 l 9.37935,10.63433 -34.47214,-6.30174 c 0,-2e-5 -10.96427,4.13624 -36.05858,11.02861 -3.09966,0.85131 -6.06162,1.45425 -8.87374,1.85782 z M 96.054184,418.52496 A 227.99908,228.00372 0 0 1 64.743277,379.80069 h 53.833883 c 16.2593,10.82121 36.03109,20.56336 55.93056,22.04797 47.50893,3.54468 62.979,-1.67459 62.979,-1.67459 0,0 -4.13964,4.3321 -13.0323,12.01204 -2.4447,2.11135 -5.46123,4.28998 -8.54904,6.33885 z m 156.603246,0 c 4.10483,-4.24043 6.54978,-7.04162 6.54978,-7.04162 0,0 3.17296,2.8621 8.63949,7.04162 z m 54.10293,0 c -19.35695,-13.88741 -22.86161,-25.14433 -22.86161,-25.14433 0,0 49.2172,17.2685 90.39112,0.28064 10.4477,-4.31055 19.37408,-9.1049 26.88099,-13.86058 h 47.3421 a 227.99908,228.00372 0 0 1 -31.31091,38.72427 z M 59.385631,371.02418 A 227.99908,228.00372 0 0 1 41.543041,332.29992 H 159.20017 c 1.30773,2.3199 2.75142,4.57103 4.34409,6.73083 12.77878,17.32895 25.06121,26.96783 33.0852,31.99343 h -27.15468 c -5.2719,-0.84 -10.81534,-1.78919 -16.40924,-2.84819 -27.04349,-5.11994 -72.845405,-20.48007 -72.845405,-20.48007 0,0 10.296355,11.13669 26.131855,23.32826 z m 238.424449,0 c 30.05703,-10.10404 47.05829,-24.07021 56.34572,-38.72426 h 117.55739 a 227.99908,228.00372 0 0 1 -17.84258,38.72426 h -40.22176 c 13.33114,-10.41219 19.38725,-18.85882 19.38725,-18.85882 0,0 -30.08919,11.11726 -59.29823,18.85882 z m -41.2585,-14.62133 c -0.90134,-0.01 -9.08983,-0.64727 -40.38179,-18.55498 -2.80164,-1.60327 -5.61377,-3.47048 -8.41452,-5.54795 h 37.53597 c 6.43727,15.58979 11.34615,24.10293 11.34615,24.10293 0,0 -0.0258,6.4e-4 -0.0858,0 z m 12.72847,-0.0418 c 0,0 -2.97304,-8.3824 -6.55675,-24.06118 h 46.48163 c -24.16151,23.08045 -39.92488,24.06123 -39.92488,24.06123 z M 38.653164,323.52341 a 227.99908,228.00372 0 0 1 -8.28,-38.72426 H 147.25331 c 0.50409,11.4347 2.40394,25.61361 7.73264,38.72426 z m 158.567726,0 c -12.80955,-11.77756 -24.77977,-26.58932 -33.71374,-38.72426 h 65.85729 c 4.01234,15.08912 8.39298,28.09557 12.44549,38.72426 z m 63.60057,0 c -2.16662,-10.57203 -4.40101,-23.55135 -6.23667,-38.72426 h 95.8253 c -7.46906,9.7857 -18.55287,23.51811 -32.62829,38.72426 z m 97.99155,0 c 5.95644,-13.69644 6.2152,-27.44278 5.00743,-38.72426 h 119.06262 a 227.99908,228.00372 0 0 1 -8.28,38.72426 z M 29.452392,276.02264 A 227.99908,228.00372 0 0 1 28.62903,256.6605 227.99908,228.00372 0 0 1 29.452392,237.29836 H 219.64878 c 2.02639,13.95226 4.61647,26.90106 7.48446,38.72428 H 157.2241 c -5.80191,-8.33616 -9.27267,-13.98815 -9.27267,-13.98815 0,0 -0.7416,5.5263 -0.8396,13.98815 z m 224.144368,0 c -1.22897,-11.76966 -2.19512,-24.70616 -2.7113,-38.72428 h 232.91837 a 227.99908,228.00372 0 0 1 0.82337,19.36214 227.99908,228.00372 0 0 1 -0.82337,19.36214 H 362.56568 c -0.39943,-2.2888 -0.8157,-4.40137 -1.19214,-6.30638 0,0 -1.52342,2.281 -4.43454,6.30638 z M 30.373164,228.52186 a 227.99908,228.00372 0 0 1 8.28,-38.72427 H 218.96921 c -1.16001,13.8461 -1.41371,26.99937 -0.37573,38.72427 z m 220.252536,0 c -0.27246,-12.17105 -0.19776,-25.09608 0.33166,-38.72427 h 223.6457 a 227.99908,228.00372 0 0 1 8.28,38.72427 z M 41.540725,181.02109 a 227.99908,228.00372 0 0 1 17.84259,-38.72427 H 225.63264 c -2.42151,12.98777 -4.45297,26.07281 -5.81919,38.72427 z m 209.892105,0 c 1.03997,-13.90922 3.42234,-26.81596 6.74692,-38.72427 h 195.69317 a 227.99908,228.00372 0 0 1 17.84258,38.72427 z M 64.740961,133.52032 A 227.99908,228.00372 0 0 1 96.051856,94.796041 H 236.06961 c -3.05987,12.287259 -6.07477,25.390049 -8.74155,38.724279 z m 196.112969,0 c 4.80192,-14.52175 10.96848,-27.42708 17.67095,-38.724279 h 138.6795 a 227.99908,228.00372 0 0 1 31.3109,38.724279 z M 105.41267,86.019537 A 227.99908,228.00372 0 0 1 254.61726,28.666053 c -3.30134,10.858112 -9.7429,31.901037 -16.31878,57.353484 z m 178.62756,0 C 299.82749,62.260898 317.24402,46.83239 326.52798,39.636692 a 227.99908,228.00372 0 0 1 81.31559,46.382845 z" />
<path
id="path8-7-2"
style="display:inline;mix-blend-mode:color;fill:url(#linearGradient4);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-dasharray:none;stroke-opacity:0.566238;paint-order:stroke fill markers"
inkscape:label="Circle"
d="m 256.61651,28.654412 a 227.99908,228.00372 0 0 1 94.5288,20.521817 C 333.6029,50.138492 316.36688,53.89448 304.85851,59.64356 292.1635,65.985164 279.15359,76.8853 269.47486,86.017162 h -36.45054 c -0.93211,-0.612343 -1.88758,-1.230613 -2.86668,-1.850865 -4.89722,-14.18571 -13.27667,-38.807461 -17.49932,-51.232639 a 227.99908,228.00372 0 0 1 43.95819,-4.279246 z m -55.26491,6.800405 16.39068,41.477366 c -6.99844,-3.719734 -14.6813,-7.076497 -22.62503,-9.769213 -20.75463,-7.035126 -39.46594,-9.140222 -49.31352,-9.766875 A 227.99908,228.00372 0 0 1 201.3516,35.454817 Z m -58.6952,23.724872 c 8.69086,4.319561 29.66977,14.955598 49.97917,26.837473 H 105.40338 A 227.99908,228.00372 0 0 1 142.6564,59.179689 Z m 241.49988,8.486589 a 227.99908,228.00372 0 0 1 23.67337,18.350884 h -95.80906 c 1.32305,-0.721011 2.11058,-1.131861 2.11058,-1.131861 l -9.37935,-10.634328 34.47215,6.30174 c 0,1.2e-5 10.96426,-4.136248 36.05857,-11.028611 3.09966,-0.851315 6.06162,-1.454254 8.87374,-1.857824 z m 33.03417,27.127388 a 227.99908,228.00372 0 0 1 31.31091,38.724274 h -53.83388 c -16.25931,-10.82121 -36.0311,-20.56336 -55.93057,-22.04797 -47.50892,-3.54468 -62.97899,1.67459 -62.97899,1.67459 0,0 4.13963,-4.3321 13.03229,-12.01204 2.4447,-2.111347 5.46123,-4.289985 8.54904,-6.338854 z m -156.60325,0 c -4.10482,4.240439 -6.54978,7.041624 -6.54978,7.041624 0,0 -3.17295,-2.862104 -8.63949,-7.041624 z m -54.10293,0 c 19.35695,13.887414 22.86161,25.144334 22.86161,25.144334 0,0 -49.2172,-17.2685 -90.39112,-0.28064 -10.4477,4.31055 -19.37408,9.1049 -26.88099,13.86058 H 64.73166 A 227.99908,228.00372 0 0 1 96.042582,94.793666 Z m 247.37474,47.500784 a 227.99908,228.00372 0 0 1 17.84257,38.72426 H 354.04446 c -1.30773,-2.3199 -2.75142,-4.57103 -4.34409,-6.73083 -12.77878,-17.32895 -25.06121,-26.96783 -33.0852,-31.99343 h 27.15468 c 5.2719,0.84 10.81534,1.78919 16.40924,2.84819 27.04349,5.11994 72.84541,20.48007 72.84541,20.48007 0,0 -10.29636,-11.13669 -26.13186,-23.32826 z m -238.42446,0 c -30.05702,10.10404 -47.05829,24.07021 -56.34572,38.72426 H 41.531435 a 227.99908,228.00372 0 0 1 17.842579,-38.72426 h 40.221767 c -13.331141,10.41219 -19.387248,18.85882 -19.387248,18.85882 0,0 30.089197,-11.11726 59.298227,-18.85882 z m 41.2585,14.62133 c 0.90134,0.009 9.08984,0.64727 40.38179,18.55498 2.80164,1.60327 5.61377,3.47048 8.41452,5.54795 h -37.53597 c -6.43727,-15.58979 -11.34615,-24.10293 -11.34615,-24.10293 0,0 0.0258,-6.4e-4 0.0859,0 z m -12.72847,0.0418 c 0,0 2.97304,8.3824 6.55675,24.06118 H 204.0397 c 24.16152,-23.08045 39.92488,-24.06123 39.92488,-24.06123 z m 230.62688,32.83764 a 227.99908,228.00372 0 0 1 8.28,38.72426 H 365.99132 c -0.50409,-11.4347 -2.40394,-25.61361 -7.73264,-38.72426 z m -158.56772,0 c 12.80955,11.77756 24.77977,26.58932 33.71374,38.72426 h -65.85729 c -4.01234,-15.08912 -8.39298,-28.09557 -12.44549,-38.72426 z m -63.60057,0 c 2.16662,10.57203 4.40101,23.55135 6.23667,38.72426 h -95.8253 c 7.46906,-9.7857 18.55287,-23.51811 32.62829,-38.72426 z m -97.99154,0 c -5.95644,13.69644 -6.21521,27.44278 -5.00743,38.72426 H 30.361558 a 227.99908,228.00372 0 0 1 8.280001,-38.72426 z m 329.3606,47.50077 a 227.99908,228.00372 0 0 1 0.82336,19.36214 227.99908,228.00372 0 0 1 -0.82336,19.36214 H 293.59585 c -2.02639,-13.95226 -4.61647,-26.90106 -7.48446,-38.72428 h 69.90914 c 5.80191,8.33616 9.27267,13.98815 9.27267,13.98815 0,0 0.74161,-5.5263 0.8396,-13.98815 z m -224.14436,0 c 1.22897,11.76966 2.19512,24.70616 2.7113,38.72428 H 29.440786 a 227.99908,228.00372 0 0 1 -0.823361,-19.36214 227.99908,228.00372 0 0 1 0.823361,-19.36214 H 150.67895 c 0.39943,2.2888 0.8157,4.40137 1.19214,6.30638 0,0 1.52343,-2.281 4.43455,-6.30638 z m 223.22359,47.50078 a 227.99908,228.00372 0 0 1 -8.28,38.72427 H 294.27542 c 1.16002,-13.8461 1.41371,-26.99937 0.37574,-38.72427 z m -220.25252,0 c 0.27245,12.17105 0.19775,25.09608 -0.33167,38.72427 H 38.641559 a 227.99908,228.00372 0 0 1 -8.280001,-38.72427 z m 209.08496,47.50077 a 227.99908,228.00372 0 0 1 -17.84258,38.72427 H 287.61199 c 2.42151,-12.98777 4.45297,-26.07281 5.81919,-38.72427 z m -209.89209,0 c -1.03998,13.90921 -3.42235,26.81596 -6.74692,38.72427 H 59.371698 A 227.99908,228.00372 0 0 1 41.52912,332.29754 Z m 186.69187,47.50077 a 227.99908,228.00372 0 0 1 -31.3109,38.72428 H 277.17503 c 3.05986,-12.28726 6.07476,-25.39005 8.74154,-38.72428 z m -196.11297,0 c -4.80193,14.52175 -10.96849,27.42708 -17.67095,38.72428 H 96.040255 A 227.99908,228.00372 0 0 1 64.729344,379.79831 Z m 155.44125,47.50078 a 227.99908,228.00372 0 0 1 -149.20459,57.35348 c 3.30135,-10.85811 9.7429,-31.90104 16.31879,-57.35348 z m -178.62756,0 c -15.78726,23.75863 -33.20379,39.18714 -42.48775,46.38284 a 227.99908,228.00372 0 0 1 -81.31558,-46.38284 z" />
<ellipse
style="fill:none;fill-opacity:0.679924;stroke:#97f0e5;stroke-width:17.5749;stroke-dasharray:none;stroke-opacity:1"
id="path192"
cx="88.20919"
cy="216.80666"
rx="43.306744"
ry="42.75507" />
<path
style="fill:none;fill-opacity:0.679924;stroke:#97f0e5;stroke-width:17.5749;stroke-dasharray:none;stroke-opacity:1"
d="M 211.35225,346.71976 151.38374,303.96994 137.1338,384.12586 Z"
id="path195" />
<path
id="path196-7"
style="fill:none;fill-opacity:0.679924;stroke:#97f0e5;stroke-width:17.5749;stroke-dasharray:none;stroke-opacity:1"
d="m 309.50171,362.30735 86.0678,57.93833 m -75.48269,11.93227 57.93833,-86.0678" />
<rect
style="fill:none;fill-opacity:0.679924;stroke:#97f0e5;stroke-width:13.9781;stroke-dasharray:none;stroke-opacity:1"
id="rect197"
width="66.112526"
height="59.501274"
x="93.831078"
y="-503.61469"
transform="rotate(108)" />
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

2984
dist/languages/ar.ts vendored

File diff suppressed because it is too large Load diff

3193
dist/languages/ca.ts vendored

File diff suppressed because it is too large Load diff

2895
dist/languages/cs.ts vendored

File diff suppressed because it is too large Load diff

2893
dist/languages/da.ts vendored

File diff suppressed because it is too large Load diff

3155
dist/languages/de.ts vendored

File diff suppressed because it is too large Load diff

2893
dist/languages/el.ts vendored

File diff suppressed because it is too large Load diff

4067
dist/languages/es.ts vendored

File diff suppressed because it is too large Load diff

2893
dist/languages/fi.ts vendored

File diff suppressed because it is too large Load diff

2906
dist/languages/fr.ts vendored

File diff suppressed because it is too large Load diff

2851
dist/languages/hu.ts vendored

File diff suppressed because it is too large Load diff

2893
dist/languages/id.ts vendored

File diff suppressed because it is too large Load diff

2997
dist/languages/it.ts vendored

File diff suppressed because it is too large Load diff

2974
dist/languages/ja_JP.ts vendored

File diff suppressed because it is too large Load diff

2841
dist/languages/ko_KR.ts vendored

File diff suppressed because it is too large Load diff

3968
dist/languages/nb.ts vendored

File diff suppressed because it is too large Load diff

2844
dist/languages/nl.ts vendored

File diff suppressed because it is too large Load diff

2860
dist/languages/pl.ts vendored

File diff suppressed because it is too large Load diff

3138
dist/languages/pt_BR.ts vendored

File diff suppressed because it is too large Load diff

2851
dist/languages/pt_PT.ts vendored

File diff suppressed because it is too large Load diff

3985
dist/languages/ru_RU.ts vendored

File diff suppressed because it is too large Load diff

2869
dist/languages/sv.ts vendored

File diff suppressed because it is too large Load diff

2848
dist/languages/tr_TR.ts vendored

File diff suppressed because it is too large Load diff

2947
dist/languages/uk.ts vendored

File diff suppressed because it is too large Load diff

2841
dist/languages/vi.ts vendored

File diff suppressed because it is too large Load diff

2841
dist/languages/vi_VN.ts vendored

File diff suppressed because it is too large Load diff

2921
dist/languages/zh_CN.ts vendored

File diff suppressed because it is too large Load diff

2854
dist/languages/zh_TW.ts vendored

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,7 @@
- [NetBSD](#netbsd)
- [MSYS2](#msys2)
- [RedoxOS](#redoxos)
- [PlayStation 4](#playstation-4)
- [Windows](#windows)
- [Windows 7, Windows 8 and Windows 8.1](#windows-7-windows-8-and-windows-81)
- [Windows Vista and below](#windows-vista-and-below)
@ -220,6 +221,17 @@ The package install may randomly hang at times, in which case it has to be resta
When CMake invokes certain file syscalls - it may sometimes cause crashes or corruptions on the (kernel?) address space - so reboot the system if there is a "hang" in CMake.
## PlayStation 4
```sh
export OO_PS4_TOOLCHAIN="$HOME/OpenOrbis/PS4Toolchain/prefix"
export DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
```
```sh
cp $OO_PS4_TOOLCHAIN/include/endian.h $OO_PS4_TOOLCHAIN/include/sys/endian.h
```
## Windows
### Windows 7, Windows 8 and Windows 8.1

View file

@ -70,8 +70,8 @@ These options control executables and build flavors.
The following options are desktop only.
- `ENABLE_LIBUSB` (ON) Enable the use of the libusb input frontend (HIGHLY RECOMMENDED)
- `ENABLE_OPENGL` (ON) Enable the OpenGL graphics frontend
- `ENABLE_LIBUSB` (ON) Enable the use of the libusb input backend (HIGHLY RECOMMENDED)
- `ENABLE_OPENGL` (ON) Enable the OpenGL graphics backend
- Unavailable on Windows/ARM64
- You probably shouldn't turn this off.

View file

@ -1,6 +1,6 @@
# Setting a Custom Date/Time in Eden
Use this guide whenever you want to modify the Date or Time that Eden reports to games. This can be useful for modifying RNG elements, skipping wait times in games, etc.
Use this guide whenever you want to modify the Date or Time that Eden reports to games. This can be useful for modifying RNG elements, skipping wait times in games, etc.
**Click [Here](https://evilperson1337.notion.site/Setting-a-Custom-Date-Time-in-Eden-2b357c2edaf680acb8d4e63ccc126564) for a version of this guide with images & visual elements.**
@ -16,5 +16,5 @@ Use this guide whenever you want to modify the Date or Time that Eden reports to
1. Navigate to *Emulation → Configure*.
2. Click on the **System** item on the left-hand side navigation, then check the *Custom RTC Date* box.
3. The Date/Time option now becomes editable. Set it to the value you want and hit **OK**.
4. GREAT SCOTT! We have time traveled! You can of course go forward or backward in time (as long as it is not before the year 1970) and your game should update accordingly (e.g. certain *Super Mario Odyssey* moons that take time for flowers to grow will now be fully grown.).
3. The Date/Time option now becomes editable. Set it to the value you want and hit **OK**.
4. GREAT SCOTT! We have time traveled! You can of course go forward or backward in time (as long as it is not before the year 1970) and your game should update accordingly (e.g. certain *Super Mario Odyssey* moons that take time for flowers to grow will now be fully grown.).

View file

@ -16,6 +16,15 @@ The CPU must support FMA for an optimal gameplay experience. The GPU needs to su
If your GPU doesn't support or is just behind by a minor version, see Mesa environment variables below (*nix only).
## Releases and versions
- Stable releases/Versioned releases: Has a version number and it's the versions we expect 3rd party repositories to host (package managers and such), these are, well, stable, have low amount of regressions (wrt. to master and nightlies) and generally focus on "keeping things without regressions", recommended for the average user.
- RC releases: Release candidate, generally "less stable but still stable" versions.
- Full release: "The stablest possible you could get".
- Nightly: Builds done around 2PM UTC (if there are any changes), generally stable, but not recommended for the average user. These contain daily updates and may contain critical fixes for some games.
- Master: Unstable builds, can lead from a game working exceptionally fine to absolute crashing in some systems because someone forgot to check if NixOS or Solaris worked. These contain straight from the oven fixes, please don't use them unless you plan to contribute something! They're very experimental! Still 95% of the time it will work just fine.
- PR builds: Highly experimental builds, testers may grab from these. The average user should treat them the same as master builds, except sometimes they straight up don't build/work.
## User configuration
### Configuration directories
@ -26,6 +35,7 @@ Eden will store configuration files in the following directories:
- **Android**: Data is stored internally.
- **Linux, macOS, FreeBSD, Solaris, OpenBSD**: `$XDG_DATA_HOME`, `$XDG_CACHE_HOME`, `$XDG_CONFIG_HOME`.
- **HaikuOS**: `/boot/home/config/settings/eden`
- **PlayStation 4**: `/data/eden`
If a `user` directory is present in the current working directory, that will override all global configuration directories and the emulator will use that instead.

View file

@ -7,6 +7,7 @@ There are two main applications, an SDL2 based app (`eden-cli`) and a Qt based a
- `-g <path>`: Alternate way to specify what to load, overrides. However let it be noted that arguments that use `-` will be treated as options/ignored, if your game, for some reason, starts with `-`, in order to safely handle it you may need to specify it as an argument.
- `-f`: Use fullscreen.
- `-u <number>`: Select the index of the user to load as.
- `-input-profile <name>`: Specifies input profile name to use (for player #0 only).
- `-qlaunch`: Launch QLaunch.
- `-setup`: Launch setup applet.
@ -20,3 +21,4 @@ There are two main applications, an SDL2 based app (`eden-cli`) and a Qt based a
- `--program/-p`: Specify the program arguments to pass (optional).
- `--user/-u`: Specify the user index.
- `--version/-v`: Display version and quit.
- `--input-profile/-i`: Specifies input profile name to use (for player #0 only).

View file

@ -1,49 +0,0 @@
# Configuring Controller Profiles
Use this guide for when you want to configure specific controller settings to be reused.
**Click [Here](https://evilperson1337.notion.site/Configuring-Controller-Profiles-2be57c2edaf680eabc3ac8c333ec75c4) for a version of this guide with images & visual elements.**
---
### Pre-Requisites
- Eden Set Up and Configured
---
### Steps
1. Launch Eden and wait for it to load.
2. Navigate to *Emulation > Configure…*
3. Select **Controls** from the left-hand menu and configure your controller for the way you want it to be in game.
4. Select **New** and enter a name for the profile in the box that appears. Press **OK** to save the profile settings.
5. Select **OK** to close the settings menu.
## Setting Controller Profiles By Game
Use this guide when you want to set up specific controller profiles for specific games. This can be useful for certain games like *Captain Toad Treasure Tracker* where a blue dot appears in the middle of the screen when you have docked mode enabled, but not handheld mode.
**Click [Here](https://evilperson1337.notion.site/Setting-Controller-Profiles-By-Game-2b057c2edaf681658a57f0c199cb6083) for a version of this guide with images & visual elements.**
---
### Pre-Requisites
- Eden Emulator set up and fully configured
- Controller Profile Created
- See [*Configuring Controller Profiles*](./ControllerProfiles.md) for instructions on how to do this if needed.
---
### Steps
1. *Right-Click* the game you want to apply the profile to in the main window and select **Properties.**
2. Navigate to the **Input Profiles** tab in the window that appears. Drop down on *Player 1 profile* (or whatever player profile you want to apply it to) and select the profile you want.
<aside>
***NOTE***: You may have to resize the window to see all tabs, or press the arrows by the tabs to see **Input Profiles**.
</aside>
1. Click **OK** to apply the profile mapping.
2. Launch the game and confirm that the profile is applied, regardless of what the global configuration is.

65
docs/user/Controllers.md Normal file
View file

@ -0,0 +1,65 @@
# User Handbook - Controllers
Most of the controls should work out of the box. If not, please use a joystick calibrator to ensure it's not an issue with your own controller, for example:
- https://github.com/dkosmari/calibrate-joystick
## Using external controllers on the Steamdeck
In desktop mode ignore your pro controller/xbox contoller external controller and use **Steam Virtual Gamepad 0 as Player 1**. If you have multiple external controllers set **Player 2 to Steam Virtual Gamepad 1**. Steam app must not be closed on desktop mode.
Here's the annoying part of it. When waking up the steam deck from sleep try not to touch any button on the Steamdeck and turn on your external controller. Then open the Eden.AppImage. If you're lucky you can get your external controller to be position 0 and also Steam Virtual Gamepad 0 in desktop mode. If not that is ok too unless you need to configure player 1 to have gyro. You might need to repeat this to get your external controller as Steam Virtual Gamepad 0 so you can config Player 1 having gyro. You might be able to config player 1 to have gyro with the Steamdeck itself. Or you can also config player 1, 2, 3, etc, to have gyro somehow. Make sure they are all using Virtual Gamepads though.
Turn off controller then go to gaming mode. Try not to touch any buttons on the physical Steamdeck. When in gaming mode turn on the external controller. If lucky it will be assigned as Steam Virtual Gamepad 0. If not just use steam Gamemode feature to rearrange controller positions order.
Basically the Steamdeck or the external controller is fighting for position 0 and it depends on what is touched first after waking from sleep.
## Configuring Controller Profiles
Use this guide for when you want to configure specific controller settings to be reused.
**Click [Here](https://evilperson1337.notion.site/Configuring-Controller-Profiles-2be57c2edaf680eabc3ac8c333ec75c4) for a version of this guide with images & visual elements.**
---
#### Pre-Requisites
- Eden Set Up and Configured
---
#### Steps
1. Launch Eden and wait for it to load.
2. Navigate to *Emulation > Configure…*
3. Select **Controls** from the left-hand menu and configure your controller for the way you want it to be in game.
4. Select **New** and enter a name for the profile in the box that appears. Press **OK** to save the profile settings.
5. Select **OK** to close the settings menu.
### Setting Controller Profiles By Game
Use this guide when you want to set up specific controller profiles for specific games. This can be useful for certain games like *Captain Toad Treasure Tracker* where a blue dot appears in the middle of the screen when you have docked mode enabled, but not handheld mode.
**Click [Here](https://evilperson1337.notion.site/Setting-Controller-Profiles-By-Game-2b057c2edaf681658a57f0c199cb6083) for a version of this guide with images & visual elements.**
---
#### Pre-Requisites
- Eden Emulator set up and fully configured
- Controller Profile Created
- See [*Configuring Controller Profiles*](./ControllerProfiles.md) for instructions on how to do this if needed.
---
#### Steps
1. *Right-Click* the game you want to apply the profile to in the main window and select **Properties.**
2. Navigate to the **Input Profiles** tab in the window that appears. Drop down on *Player 1 profile* (or whatever player profile you want to apply it to) and select the profile you want.
<aside>
***NOTE***: You may have to resize the window to see all tabs, or press the arrows by the tabs to see **Input Profiles**.
</aside>
1. Click **OK** to apply the profile mapping.
2. Launch the game and confirm that the profile is applied, regardless of what the global configuration is.

View file

@ -11,10 +11,12 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
- **[The Basics](Basics.md)**
- **[Quickstart](./QuickStart.md)**
- **[Settings](./Settings.md)**
- **[Installing Mods](./Mods.md)**
- **[Run On macOS](./RunOnMacOS.md)**
- **[Controllers](./Controllers.md)**
- **[Controller profiles](./Controllers.md#configuring-controller-profiles)**
- **[Audio](Audio.md)**
- **[Graphics](Graphics.md)**
- **[Installing Mods](./Mods.md)**
- **[Run On macOS](./RunOnMacOS.md)**
- **[Data, Savefiles and Storage](Storage.md)**
- **[Orphaned Profiles](Orphaned.md)**
- **[Troubleshooting](./Troubleshoot.md)**
@ -23,7 +25,6 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
- **[Importing Saves](./ImportingSaves.md)**
- **[Installing Atmosphere Mods](./InstallingAtmosphereMods.md)**
- **[Installing Updates & DLCs](./InstallingUpdatesDLC.md)**
- **[Controller Profiles](./ControllerProfiles.md)**
- **[Alter Date & Time](./AlterDateTime.md)**
## 3rd-party Integration
@ -35,6 +36,7 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
- **[Obtainium](./ThirdParty.md#configuring-obtainium)**
- **[ES-DE](./ThirdParty.md#configuring-es-de)**
- **[Mirrors](./ThirdParty.md#mirrors)**
- **[GameMode](./ThirdParty.md#configuring-gamemode)**
## Advanced

View file

@ -1,4 +1,12 @@
# Allowing Eden to Run on MacOS
# User Handbook - Run on macOS
Current macOS support is still experimental and very reliant on MoltenVK developments, plans have shifted to properly provide support for KosmicKrisp and similar new GPU endeavours, but macOS users still are bound to MoltenVK itself.
Users of macOS may wish to use [Asahi Linux](https://wiki.gentoo.org/wiki/Project:Asahi/Guide) for the rising KosmicKrisp support.
As of writing, neither macOS nor Asahi has support for NCE; additionally Asahi has extraneous paging bugs with fastmem.
## Allowing Eden to Run on MacOS
Use this guide when you need to allow Eden to run on a Mac system, but are being blocked by Apple Security policy.
@ -6,19 +14,19 @@ Use this guide when you need to allow Eden to run on a Mac system, but are being
---
### Pre-Requisites
#### Pre-Requisites
- Permissions to modify settings in MacOS
---
## Why am I Seeing This?
### Why am I Seeing This?
Recent versions of MacOS (Catalina & newer) introduced the **Gatekeeper** security functionality, requiring software to be signed by Apple or a trusted (aka - paying) developer. If the signature isnt on the list of trusted ones, it will stop the program from executing and display the message above.
---
## Steps
### Steps
1. Open the *System Settings* panel.
2. Navigate to *Privacy & Security*.

View file

@ -50,5 +50,4 @@ See also [an extended breakdown of some options](./Graphics.md).
## Controls
Most of the controls should work out of the box. If not, please use a joystick calibrator to ensure it's not an issue with your own controller, for example:
- https://github.com/dkosmari/calibrate-joystick
See [controllers](./Controllers.md).

View file

@ -1,39 +1,99 @@
# User Handbook - Testing
While this is mainly aimed for testers - normal users can benefit from these guidelines to make their life easier when trying to outline and/or report an issue.
## Getting logs
In order to get more information, you can find logs in the following location:
## How to Test a PR Against the Based Master When Issues Arise
# Testing
When you're testing a pull request (PR) and encounter unexpected behavior, it's important to determine whether the issue was introduced by the PR or if it already exists in the base code. To do this, compare the behavior against the based master branch.
Even before an issue occurs, it is best practice to keep the same settings and delete the shader cache. Using an already made shader cache can make the PR look like it is having a regression in some rare cases.
### What to Do When Something Seems Off
Try not to test PRs which are for documentation or extremely trivial changes (like a PR that changes the app icon), unless you really want to; generally avoid any PRs marked `[docs]`.
If a PR specifies it is for a given platform (i.e `linux`) then just test on Linux. If it says `NCE` then test on Android and Linux ARM64 (Raspberry Pi and such). macOS fixes may also affect Asahi, test that if you can too.
You may also build artifacts yourself, be aware that the resulting builds are NOT the same as those from CI, because of package versioning and build environment differences. One famous example is FFmpeg randomly breaking on many Arch distros due to packaging differences.
## Quickstart
Think of the source code as a "tree", with the "trunk" of that tree being our `master` branch, any other branches are PRs or separate development branches, only our stable releases pull from `master` - all other branches are considered unstable and aren't recommended to pull from unless you're testing multiple branches at once.
Here's some terminology you may want to familiarize yourself with:
- PR: Pull request, a change in the codebase; from which the author of said change (the programmer) requests a pull of that branch into master (make it so the new code makes it into a release basically).
- Bisect: Bilinear method of searching regressions, some regressions may be sporadic and can't be bisected, but the overwhelming majority are.
- WIP: Work-in-progress.
- Regression: A new bug/glitch caused by new code, i.e "Zelda broke in android after commit xyz".
- Master: The "root" branch, this is where all merged code goes to, traditionally called `main`, `trunk` or just `master`, it contains all the code that eventually make it to stable releases.
- `HEAD`: Latest commit in a given branch, `HEAD` of `master` is the latest commit on branch `master`.
- `origin`: The default "remote", basically the URL from where git is located at, for most of the time that location is https://git.eden-emu.dev/eden-emu/eden.
## Testing checklist
For regressions/bugs from PRs or commits:
- [ ] Occurs in master?
- If it occurs on master:
- [ ] Occurs on previous stable release? (before this particular PR).
- If it occurs on previous stable release:
- [ ] Occurs on previous-previous stable release?
- And so on and so forth... some bugs come from way before Eden was even conceived.
- Otherwise, try bisecting between the previous stable release AND the latest `HEAD` of master
- [ ] Occurs in given commit?
- [ ] Occurs in PR?
- If it occurs on PR:
- [ ] Bisected PR? (if it has commits)
- [ ] Found bisected commit?
If an issue sporadically appears, try to do multiple runs, try if possible, to count the number of times it has failed and the number of times it has "worked just fine"; say it worked 3 times but failed 1. then there is a 1/4th chance every run that the issue is replicated - so every bisect step would require 4 runs to ensure there is atleast a chance of triggering the bug.
## What to do when something seems off
If you notice something odd during testing:
- Reproduce the issue using the based master branch.
- Observe whether the same behavior occurs.
### Two Possible Outcomes
From there onwards there can be two possible outcomes:
- If the issue exists in the based master: This means the problem was already present before the PR. The PR most likely did not introduce the regression.
- If the issue does not exist in the based master: This suggests the PR most likely introduced the regression and needs further investigation.
### Report your findings
## Reporting Your Findings
When you report your results:
- Clearly state whether the behavior was observed in the based master.
- Indicate whether the result is good (expected behavior) or bad (unexpected or broken behavior). Without mentioning if your post/report/log is good or bad it may confuse the Developer of the PR.
- Example:
```
1. "Tested on based master — issue not present. Bad result for PR, likely regression introduced."
2. "Tested on based master — issue already present. Good result for PR, not a regression."
```
- Indicate whether the result is good (expected behavior) or bad (unexpected or broken behavior). Without mentioning if your post/report/log is good or bad it may confuse the developer of the PR.
For example:
1. "Bad result for PR: Tested on based master - issue not present. Likely regression introduced."
2. "Good result for PR: Tested on based master - issue already present. Not a regression."
This approach helps maintain clarity and accountability in the testing process and ensures regressions are caught and addressed efficiently.
If the behavior seems normal for a certain game/feature then it may not be always required to check against the based master.
This approach helps maintain clarity and accountability in the testing process and ensures regressions are caught and addressed efficiently. If the behavior seems normal for a certain game/feature then it may not be always required to check against the based master.
If a master build for the PR' based master does not exist. It will be helpful to just test past and future builds nearby. That would help with gathering more information about the problem.
**Always include [debugging info](../Debug.md) as needed**.
**Always include [debugging info](../Debug.md) as needed**.
## Bisecting
One happy reminder, when testing, *know how to bisect!*
Say you're trying to find an issue between 1st of Jan and 8th of Jan, you can search by dividing "in half" the time between each commit:
- Check for 4th of Jan
- If 4th of Jan is "working" then the issue must be in the future
- So then check 6th of Jan
- If 6th of Jan isn't working then the issue must be in the past
- So then check 5th of Jan
- If 5th of Jan worked, then the issue starts at 6th of Jan
The faulty commit then, is 6th of Jan. This is called bisection https://git-scm.com/docs/git-bisect
## Notes
- PR's marked with **WIP** do NOT need to be tested unless explicitly asked (check the git in case)
- Sometimes license checks may fail, hover over the build icon to see if builds did succeed, as the CI will push builds even if license checks fail.
- All open PRs can be viewed [here](https://git.eden-emu.dev/eden-emu/eden/pulls/).
- If site is down use one of the [mirrors](./user/ThirdParty.md#mirrors).

View file

@ -4,7 +4,6 @@ The Eden emulator by itself lacks some functionality - or otherwise requires ext
While most of the links mentioned in this guide are relatively "safe"; we urge users to use their due diligence and appropriatedly verify the integrity of all files downloaded and ensure they're not compromised.
- [Nightly Eden builds](https://github.com/pflyly/eden-nightly)
- [NixOS Eden Flake](https://github.com/Grantimatter/eden-flake)
- [ES-DE Frontend Support](https://github.com/GlazedBelmont/es-de-android-custom-systems)
@ -66,3 +65,9 @@ Note: Even though the site isn't Codeberg, it uses the same Forgejo/Gitea backen
```xml
<command label="Eden (Standalone)">%EMULATOR_EDEN% %ACTION%=android.nfc.action.TECH_DISCOVERED %DATA%=%ROMPROVIDER%</command>
```
## Configuring GameMode
There is a checkbox to enable gamemode automatically. The `libgamemode.so` library must be findable on the standard `LD_LIBRARY_PATH` otherwise it will not properly be enabled. If for whatever reason it doesn't work, see [Arch wiki: GameMode](https://wiki.archlinux.org/title/GameMode) for more info.
You may launch the emulator directly via the wrapper `gamemode <program>`, and things should work out of the box.

View file

@ -159,6 +159,10 @@ if (NOT ANDROID)
if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck")
set(SDL_PIPEWIRE OFF) # build errors out with this on
AddJsonPackage("sdl2_steamdeck")
elseif (PLATFORM_PS4)
set(PS4 ON)
set(ORBIS ON)
AddJsonPackage("sdl2_ps4")
else()
AddJsonPackage("sdl2_generic")
endif()
@ -259,6 +263,11 @@ target_include_directories(tz PUBLIC ./tz)
add_library(bc_decoder bc_decoder/bc_decoder.cpp)
target_include_directories(bc_decoder PUBLIC ./bc_decoder)
if (PLATFORM_PS4)
add_library(ps4sup ps4sup/emutls.c ps4sup/stub.cpp)
target_include_directories(ps4sup PUBLIC ./ps4sup)
endif()
if (NOT TARGET RenderDoc::API)
add_library(renderdoc INTERFACE)
target_include_directories(renderdoc SYSTEM INTERFACE ./renderdoc)

View file

@ -17,6 +17,8 @@
if (${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")
set(PLATFORM_SUN ON)
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenOrbis")
set(PLATFORM_PS4 ON)
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
set(PLATFORM_FREEBSD ON)
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")

View file

@ -36,7 +36,7 @@
"0002-fix-zstd.patch"
],
"options": [
"HTTPLIB_REQUIRE_OPENSSL ON"
"HTTPLIB_REQUIRE_OPENSSL OFF"
]
},
"cpp-jwt": {
@ -98,7 +98,10 @@
"hash": "a0d2fa8c957704dd49e00a726284ac5ca034b50b00d2b20a94fa1bbfbb80841467834bfdc84aa0ed0d6aab894608fd6c86c3b94eee46343f0e6d9c22e391dbf9",
"version": "1.3",
"git_version": "1.3.18",
"find_args": "MODULE"
"find_args": "MODULE",
"patches": [
"0001-openorbis.patch"
]
},
"spirv-tools": {
"package": "SPIRV-Tools",
@ -111,7 +114,8 @@
],
"patches": [
"0001-netbsd-fix.patch",
"0002-allow-static-only.patch"
"0002-allow-static-only.patch",
"0003-openorbis.patch"
]
},
"spirv-headers": {
@ -140,7 +144,7 @@
"package": "SDL2",
"name": "SDL2",
"repo": "crueter-ci/SDL2",
"version": "2.32.10-cf5dabd6ea",
"version": "2.32.10-3c28e8ecc0",
"min_version": "2.26.4"
},
"catch2": {
@ -186,6 +190,18 @@
"bundled": true,
"skip_updates": "true"
},
"sdl2_ps4": {
"package": "SDL2",
"repo": "libsdl-org/SDL",
"sha": "0c7042477a",
"hash": "91d897257fe1134e65234618a96bc8f4f9b61dd3ba42241a65c293cd406139e308a6c79eadfa7c3969271c88d73149e75c4310fff37c79387c80d9c982c1f322",
"key": "ps4",
"bundled": true,
"skip_updates": true,
"patches": [
"0001-ps4.patch"
]
},
"moltenvk": {
"repo": "V380-Ori/Ryujinx.MoltenVK",
"tag": "v%VERSION%-ryujinx",

View file

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2021 yuzu Emulator Project
@ -11,63 +11,106 @@ set(FFmpeg_HWACCEL_FLAGS)
set(FFmpeg_HWACCEL_INCLUDE_DIRS)
set(FFmpeg_HWACCEL_LDFLAGS)
if (UNIX AND NOT ANDROID)
find_package(PkgConfig REQUIRED)
if (NOT ANDROID)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
pkg_check_modules(VDPAU vdpau)
if (NOT YUZU_USE_BUNDLED_FFMPEG)
set(FFmpeg_CROSS_COMPILE_FLAGS "")
if (ANDROID)
# TODO: Maybe use CMAKE_SYSROOT? and probably provide a toolchain file for android
# I mean isn't that the "proper" way anyways?
string(TOLOWER "${CMAKE_HOST_SYSTEM_NAME}" FFmpeg_HOST_SYSTEM_NAME)
set(TOOLCHAIN "${ANDROID_NDK}/toolchains/llvm/prebuilt/${FFmpeg_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}")
set(SYSROOT "${TOOLCHAIN}/sysroot")
set(FFmpeg_CPU "armv8-a")
list(APPEND FFmpeg_CROSS_COMPILE_FLAGS
--enable-cross-compile
--arch=arm64
#--cpu=${FFmpeg_CPU}
--cross-prefix="${TOOLCHAIN}/bin/aarch64-linux-android-"
--sysroot="${SYSROOT}"
--target-os=android
--extra-ldflags="--ld-path=${TOOLCHAIN}/bin/ld.lld"
--extra-ldflags="-nostdlib"
)
set(FFmpeg_IS_CROSS_COMPILING TRUE)
# User attempts to do a FFmpeg cross compilation because...
# Here we just quickly test against host/system processors not matching
# TODO: Test for versions not matching as well?
elseif (NOT (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES CMAKE_SYSTEM_PROCESSOR
AND CMAKE_HOST_SYSTEM_NAME MATCHES CMAKE_SYSTEM_NAME))
string(TOLOWER "${CMAKE_SYSTEM_NAME}" FFmpeg_SYSTEM_NAME)
if (FFmpeg_SYSTEM_NAME STREQUAL "openorbis")
set(FFmpeg_SYSTEM_NAME "freebsd") # Emulates FBSD :)
endif()
# TODO: Can we really do better? Auto-detection? Something clever?
list(APPEND FFmpeg_CROSS_COMPILE_FLAGS
--enable-cross-compile
--arch="${CMAKE_SYSTEM_PROCESSOR}"
--target-os="${FFmpeg_SYSTEM_NAME}"
--sysroot="${CMAKE_SYSROOT}"
)
if (DEFINED FFmpeg_CROSS_PREFIX)
list(APPEND FFmpeg_CROSS_COMPILE_FLAGS --cross-prefix="${FFmpeg_CROSS_PREFIX}")
else()
message(WARNING "Please set FFmpeg_CROSS_PREFIX to your cross toolchain prefix, for example: \${CMAKE_STAGING_PREFIX}/bin/${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}-")
endif()
set(FFmpeg_IS_CROSS_COMPILING TRUE)
endif()
endif()
if (NOT APPLE)
# In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so
if(PLATFORM_SUN)
find_library(LIBDRM_LIB libdrm PATHS /usr/lib/64 /usr/lib/amd64 /usr/lib)
if(LIBDRM_LIB)
if (PLATFORM_PS4)
list(APPEND FFmpeg_HWACCEL_FLAGS
--disable-vaapi
)
elseif (UNIX AND NOT DEFINED FFmpeg_IS_CROSS_COMPILING)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
pkg_check_modules(VDPAU vdpau)
find_package(X11)
if(X11_FOUND)
if (NOT APPLE)
# In Solaris needs explicit linking for ffmpeg which links to /lib/amd64/libX11.so
if(PLATFORM_SUN)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
X11
"${LIBDRM_LIB}")
message(STATUS "Found libdrm at: ${LIBDRM_LIB}")
"${CMAKE_SYSROOT}/usr/lib/xorg/amd64/libdrm.so")
else()
message(WARNING "libdrm not found, disabling libdrm support")
list(APPEND FFmpeg_HWACCEL_FLAGS
--disable-libdrm)
pkg_check_modules(LIBDRM libdrm REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS})
endif()
else()
pkg_check_modules(LIBDRM libdrm REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-libdrm)
endif()
endif()
if(LIBVA_FOUND)
find_package(X11 REQUIRED)
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${X11_LIBRARIES}
${LIBVA-DRM_LIBRARIES}
${LIBVA-X11_LIBRARIES}
${LIBVA_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-hwaccel=h264_vaapi
--enable-hwaccel=vp8_vaapi
--enable-hwaccel=vp9_vaapi)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${X11_INCLUDE_DIRS}
${LIBVA-DRM_INCLUDE_DIRS}
${LIBVA-X11_INCLUDE_DIRS}
${LIBVA_INCLUDE_DIRS}
)
message(STATUS "ffmpeg: va-api libraries version ${LIBVA_VERSION} found")
if(LIBVA_FOUND)
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${X11_LIBRARIES}
${LIBVA-DRM_LIBRARIES}
${LIBVA-X11_LIBRARIES}
${LIBVA_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-hwaccel=h264_vaapi
--enable-hwaccel=vp8_vaapi
--enable-hwaccel=vp9_vaapi)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${X11_INCLUDE_DIRS}
${LIBVA-DRM_INCLUDE_DIRS}
${LIBVA-X11_INCLUDE_DIRS}
${LIBVA_INCLUDE_DIRS}
)
message(STATUS "ffmpeg: va-api libraries version ${LIBVA_VERSION} found")
else()
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vaapi)
message(WARNING "ffmpeg: libva-dev not found, disabling Video Acceleration API (VA-API)...")
endif()
else()
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vaapi)
message(WARNING "ffmpeg: libva-dev not found, disabling Video Acceleration API (VA-API)...")
message(WARNING "ffmpeg: X11 libraries not found, disabling VA-API...")
endif()
if (FFNVCODEC_FOUND)
@ -111,6 +154,23 @@ if (UNIX AND NOT ANDROID)
endif()
endif()
if (PLATFORM_PS4)
list(APPEND FFmpeg_CROSS_COMPILE_LIBS
-lc
-lkernel
-lSceUserService
-lSceSysmodule
-lSceNet
-lSceLibcInternal
)
list(APPEND FFmpeg_CROSS_COMPILE_FLAGS
--disable-pthreads
--extra-cflags=${CMAKE_SYSROOT}/usr/include
--extra-cxxflags=${CMAKE_SYSROOT}/usr/include
--extra-libs="${FFmpeg_CROSS_COMPILE_LIBS}"
)
endif()
if (YUZU_USE_BUNDLED_FFMPEG)
AddJsonPackage(ffmpeg-ci)
@ -181,24 +241,6 @@ else()
find_program(BASH_PROGRAM bash REQUIRED)
set(FFmpeg_CROSS_COMPILE_FLAGS "")
if (ANDROID)
string(TOLOWER "${CMAKE_HOST_SYSTEM_NAME}" FFmpeg_HOST_SYSTEM_NAME)
set(TOOLCHAIN "${ANDROID_NDK}/toolchains/llvm/prebuilt/${FFmpeg_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}")
set(SYSROOT "${TOOLCHAIN}/sysroot")
set(FFmpeg_CPU "armv8-a")
list(APPEND FFmpeg_CROSS_COMPILE_FLAGS
--arch=arm64
#--cpu=${FFmpeg_CPU}
--enable-cross-compile
--cross-prefix=${TOOLCHAIN}/bin/aarch64-linux-android-
--sysroot=${SYSROOT}
--target-os=android
--extra-ldflags="--ld-path=${TOOLCHAIN}/bin/ld.lld"
--extra-ldflags="-nostdlib"
)
endif()
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
# `--disable-vdpau` is needed to avoid linking issues
set(FFmpeg_CC ${CMAKE_C_COMPILER_LAUNCHER} ${CMAKE_C_COMPILER})
@ -221,8 +263,12 @@ else()
--enable-decoder=vp9
--enable-filter=yadif,scale
--enable-pic
--cc="${FFmpeg_CC}"
--cxx="${FFmpeg_CXX}"
--cc=${FFmpeg_CC}
--cxx=${FFmpeg_CXX}
--ld=${CMAKE_LINKER}
--extra-cflags=${CMAKE_C_FLAGS}
--extra-cxxflags=${CMAKE_CXX_FLAGS}
--extra-ldflags=${CMAKE_C_LINK_FLAGS}
${FFmpeg_HWACCEL_FLAGS}
${FFmpeg_CROSS_COMPILE_FLAGS}
WORKING_DIRECTORY
@ -254,7 +300,7 @@ else()
OUTPUT
${FFmpeg_BUILD_LIBRARIES}
COMMAND
make ${FFmpeg_MAKE_ARGS}
gmake ${FFmpeg_MAKE_ARGS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)

181
externals/ps4sup/emutls.c vendored Normal file
View file

@ -0,0 +1,181 @@
/* ===---------- emutls.c - Implements __emutls_get_address ---------------===
*
* The LLVM Compiler Infrastructure
*
* This file is dual licensed under the MIT and the University of Illinois Open
* Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*/
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
//#include "int_util.h"
/* Default is not to use posix_memalign, so systems like Android
* can use thread local data without heavier POSIX memory allocators.
*/
#ifndef EMUTLS_USE_POSIX_MEMALIGN
#define EMUTLS_USE_POSIX_MEMALIGN 0
#endif
/* For every TLS variable xyz,
* there is one __emutls_control variable named __emutls_v.xyz.
* If xyz has non-zero initial value, __emutls_v.xyz's "value"
* will point to __emutls_t.xyz, which has the initial value.
*/
typedef struct __emutls_control {
size_t size; /* size of the object in bytes */
size_t align; /* alignment of the object in bytes */
union {
uintptr_t index; /* data[index-1] is the object address */
void* address; /* object address, when in single thread env */
} object;
void* value; /* null or non-zero initial value for the object */
} __emutls_control;
static inline void* emutls_memalign_alloc(size_t align, size_t size) {
void *base;
#if EMUTLS_USE_POSIX_MEMALIGN
if (posix_memalign(&base, align, size) != 0)
abort();
#else
#define EXTRA_ALIGN_PTR_BYTES (align - 1 + sizeof(void*))
char* object;
if ((object = malloc(EXTRA_ALIGN_PTR_BYTES + size)) == NULL)
abort();
base = (void*)(((uintptr_t)(object + EXTRA_ALIGN_PTR_BYTES))
& ~(uintptr_t)(align - 1));
((void**)base)[-1] = object;
#endif
return base;
}
static inline void emutls_memalign_free(void* base) {
#if EMUTLS_USE_POSIX_MEMALIGN
free(base);
#else
/* The mallocated address is in ((void**)base)[-1] */
free(((void**)base)[-1]);
#endif
}
/* Emulated TLS objects are always allocated at run-time. */
static inline void* emutls_allocate_object(__emutls_control* control) {
/* Use standard C types, check with gcc's emutls.o. */
//typedef unsigned int gcc_word __attribute__((mode(word)));
//typedef unsigned int gcc_pointer __attribute__((mode(pointer)));
//COMPILE_TIME_ASSERT(sizeof(size_t) == sizeof(gcc_word));
//COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(gcc_pointer));
//COMPILE_TIME_ASSERT(sizeof(uintptr_t) == sizeof(void*));
size_t size = control->size;
size_t align = control->align;
if (align < sizeof(void*))
align = sizeof(void*);
/* Make sure that align is power of 2. */
if ((align & (align - 1)) != 0)
abort();
void* base = emutls_memalign_alloc(align, size);
if (control->value)
memcpy(base, control->value, size);
else
memset(base, 0, size);
return base;
}
static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER;
static size_t emutls_num_object = 0; /* number of allocated TLS objects */
typedef struct emutls_address_array {
uintptr_t size; /* number of elements in the 'data' array */
void* data[];
} emutls_address_array;
static pthread_key_t emutls_pthread_key;
static void emutls_key_destructor(void* ptr) {
emutls_address_array* array = (emutls_address_array*)ptr;
uintptr_t i;
for (i = 0; i < array->size; ++i) {
if (array->data[i])
emutls_memalign_free(array->data[i]);
}
free(ptr);
}
static void emutls_init(void) {
if (pthread_key_create(&emutls_pthread_key, emutls_key_destructor) != 0)
abort();
}
/* Returns control->object.index; set index if not allocated yet. */
static inline uintptr_t emutls_get_index(__emutls_control* control) {
uintptr_t index = __atomic_load_n(&control->object.index, __ATOMIC_ACQUIRE);
if (!index) {
static pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, emutls_init);
pthread_mutex_lock(&emutls_mutex);
index = control->object.index;
if (!index) {
index = ++emutls_num_object;
__atomic_store_n(&control->object.index, index, __ATOMIC_RELEASE);
}
pthread_mutex_unlock(&emutls_mutex);
}
return index;
}
/* Updates newly allocated thread local emutls_address_array. */
static inline void emutls_check_array_set_size(emutls_address_array* array,
uintptr_t size) {
if (array == NULL)
abort();
array->size = size;
pthread_setspecific(emutls_pthread_key, (void*)array);
}
/* Returns the new 'data' array size, number of elements,
* which must be no smaller than the given index.
*/
static inline uintptr_t emutls_new_data_array_size(uintptr_t index) {
/* Need to allocate emutls_address_array with one extra slot
* to store the data array size.
* Round up the emutls_address_array size to multiple of 16.
*/
return ((index + 1 + 15) & ~((uintptr_t)15)) - 1;
}
/* Returns the thread local emutls_address_array.
* Extends its size if necessary to hold address at index.
*/
static inline emutls_address_array* emutls_get_address_array(uintptr_t index) {
emutls_address_array* array = pthread_getspecific(emutls_pthread_key);
if (array == NULL) {
uintptr_t new_size = emutls_new_data_array_size(index);
array = calloc(new_size + 1, sizeof(void*));
emutls_check_array_set_size(array, new_size);
} else if (index > array->size) {
uintptr_t orig_size = array->size;
uintptr_t new_size = emutls_new_data_array_size(index);
array = realloc(array, (new_size + 1) * sizeof(void*));
if (array)
memset(array->data + orig_size, 0,
(new_size - orig_size) * sizeof(void*));
emutls_check_array_set_size(array, new_size);
}
return array;
}
void* __emutls_get_address(__emutls_control* control) {
uintptr_t index = emutls_get_index(control);
emutls_address_array* array = emutls_get_address_array(index);
if (array->data[index - 1] == NULL)
array->data[index - 1] = emutls_allocate_object(control);
return array->data[index - 1];
}

31
externals/ps4sup/stub.cpp vendored Normal file
View file

@ -0,0 +1,31 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <stdio.h>
#define STUB_WEAK(name) \
extern "C" void name() { \
printf("called " #name); \
asm volatile("ud2"); \
}
extern "C" int __pthread_cxa_finalize();
extern "C" void __cxa_thread_atexit_impl() {
//printf("__cxa_thread_atexit_impl called!\n");
//__pthread_cxa_finalize();
}
STUB_WEAK(__assert)
STUB_WEAK(ZSTD_trace_compress_begin)
STUB_WEAK(ZSTD_trace_compress_end)
STUB_WEAK(ZSTD_trace_decompress_begin)
STUB_WEAK(ZSTD_trace_decompress_end)
FILE* __stderrp = stdout;
FILE* __stdinp = stdin;
#undef STUB_WEAK
// THIS MAKES STD::COUT AND SUCH WORK :)
#include <iostream>
std::ios_base::Init init;

View file

@ -242,7 +242,6 @@ if (YUZU_CMD)
endif()
if (ENABLE_QT)
add_definitions(-DYUZU_QT_WIDGETS)
add_subdirectory(qt_common)
add_subdirectory(yuzu)
endif()

View file

@ -73,6 +73,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
android:theme="@style/Theme.Yuzu.Main"
android:label="@string/preferences_settings"/>
<activity
android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreenActivity"
android:theme="@style/Theme.Yuzu.Main"
android:label="@string/preferences_settings"/>
<activity
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
android:theme="@style/Theme.Yuzu.Main"

View file

@ -40,11 +40,21 @@ class AddonAdapter(val addonViewModel: AddonViewModel) :
}
}
val deleteAction = {
addonViewModel.setAddonToDelete(model)
val canDelete = model.isRemovable
binding.deleteCard.isEnabled = canDelete
binding.buttonDelete.isEnabled = canDelete
binding.deleteCard.alpha = if (canDelete) 1f else 0.38f
if (canDelete) {
val deleteAction = {
addonViewModel.setAddonToDelete(model)
}
binding.deleteCard.setOnClickListener { deleteAction() }
binding.buttonDelete.setOnClickListener { deleteAction() }
} else {
binding.deleteCard.setOnClickListener(null)
binding.buttonDelete.setOnClickListener(null)
}
binding.deleteCard.setOnClickListener { deleteAction() }
binding.buttonDelete.setOnClickListener { deleteAction() }
}
}
}

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -6,10 +9,10 @@ package org.yuzu.yuzu_emu.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.FragmentActivity
import androidx.navigation.findNavController
import org.yuzu.yuzu_emu.HomeNavigationDirections
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
@ -67,8 +70,13 @@ class AppletAdapter(val activity: FragmentActivity, applets: List<Applet>) :
title = YuzuApplication.appContext.getString(applet.titleId),
path = appletPath
)
val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame)
binding.root.findNavController().navigate(action)
binding.root.findNavController().navigate(
R.id.action_global_emulationActivity,
bundleOf(
"game" to appletGame,
"custom" to false
)
)
}
}
}

View file

@ -27,6 +27,20 @@ class GpuUnswizzleSetting(
override val isSaveable = true
override val isRuntimeModifiable = true
override val isSwitchable = true
override val pairedSettingKey: String = ""
override var global: Boolean
get() {
return BooleanSetting.GPU_UNSWIZZLE_ENABLED.global &&
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE.global &&
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE.global &&
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE.global
}
set(value) {
BooleanSetting.GPU_UNSWIZZLE_ENABLED.global = value
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE.global = value
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE.global = value
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE.global = value
}
override fun getValueAsString(needsGlobal: Boolean): String = "combined"
override fun reset() {
BooleanSetting.GPU_UNSWIZZLE_ENABLED.reset()
@ -72,4 +86,4 @@ class GpuUnswizzleSetting(
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE.setInt(value)
fun reset() = setting.reset()
}
}

View file

@ -989,6 +989,7 @@ abstract class SettingsItem(
override val isRuntimeModifiable: Boolean = false
override val defaultValue: Boolean = true
override val isSwitchable: Boolean = true
override val pairedSettingKey: String = ""
override var global: Boolean
get() {
return BooleanSetting.FASTMEM.global &&

View file

@ -111,18 +111,10 @@ class SettingsActivity : AppCompatActivity() {
if (navHostFragment.childFragmentManager.backStackEntryCount > 0) {
navHostFragment.navController.popBackStack()
} else {
finishWithFragmentLikeAnimation()
finish()
}
}
private fun finishWithFragmentLikeAnimation() {
finish()
overridePendingTransition(
androidx.navigation.ui.R.anim.nav_default_pop_enter_anim,
androidx.navigation.ui.R.anim.nav_default_pop_exit_anim
)
}
override fun onStart() {
super.onStart()
if (!DirectoryInitialization.areDirectoriesReady) {
@ -178,7 +170,7 @@ class SettingsActivity : AppCompatActivity() {
getString(R.string.settings_reset),
Toast.LENGTH_LONG
).show()
finishWithFragmentLikeAnimation()
finish()
}
private fun setInsets() {

View file

@ -0,0 +1,152 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.features.settings.ui
import android.content.Context
import android.os.Bundle
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.navArgs
import com.google.android.material.color.MaterialColors
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.databinding.ActivitySettingsBinding
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.InsetsHelper
import org.yuzu.yuzu_emu.utils.ThemeHelper
enum class SettingsSubscreen {
PROFILE_MANAGER,
DRIVER_MANAGER,
DRIVER_FETCHER,
FREEDRENO_SETTINGS,
APPLET_LAUNCHER,
INSTALLABLE,
GAME_FOLDERS,
ABOUT,
LICENSES,
GAME_INFO,
ADDONS,
}
class SettingsSubscreenActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingsBinding
private val args by navArgs<SettingsSubscreenActivityArgs>()
override fun attachBaseContext(base: Context) {
super.attachBaseContext(YuzuApplication.applyLanguage(base))
}
override fun onCreate(savedInstanceState: Bundle?) {
ThemeHelper.setTheme(this)
super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
if (savedInstanceState == null) {
val navController = navHostFragment.navController
val navGraph = navController.navInflater.inflate(
R.navigation.settings_subscreen_navigation
)
navGraph.setStartDestination(resolveStartDestination())
navController.setGraph(navGraph, createStartDestinationArgs())
}
WindowCompat.setDecorFitsSystemWindows(window, false)
if (InsetsHelper.getSystemGestureType(applicationContext) !=
InsetsHelper.GESTURE_NAVIGATION
) {
binding.navigationBarShade.setBackgroundColor(
ThemeHelper.getColorWithOpacity(
MaterialColors.getColor(
binding.navigationBarShade,
com.google.android.material.R.attr.colorSurface
),
ThemeHelper.SYSTEM_BAR_ALPHA
)
)
}
onBackPressedDispatcher.addCallback(
this,
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() = navigateBack()
}
)
setInsets()
}
override fun onStart() {
super.onStart()
if (!DirectoryInitialization.areDirectoriesReady) {
DirectoryInitialization.start()
}
}
fun navigateBack() {
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
if (!navHostFragment.navController.popBackStack()) {
finish()
}
}
private fun resolveStartDestination(): Int =
when (args.destination) {
SettingsSubscreen.PROFILE_MANAGER -> R.id.profileManagerFragment
SettingsSubscreen.DRIVER_MANAGER -> R.id.driverManagerFragment
SettingsSubscreen.DRIVER_FETCHER -> R.id.driverFetcherFragment
SettingsSubscreen.FREEDRENO_SETTINGS -> R.id.freedrenoSettingsFragment
SettingsSubscreen.APPLET_LAUNCHER -> R.id.appletLauncherFragment
SettingsSubscreen.INSTALLABLE -> R.id.installableFragment
SettingsSubscreen.GAME_FOLDERS -> R.id.gameFoldersFragment
SettingsSubscreen.ABOUT -> R.id.aboutFragment
SettingsSubscreen.LICENSES -> R.id.licensesFragment
SettingsSubscreen.GAME_INFO -> R.id.gameInfoFragment
SettingsSubscreen.ADDONS -> R.id.addonsFragment
}
private fun createStartDestinationArgs(): Bundle =
when (args.destination) {
SettingsSubscreen.DRIVER_MANAGER,
SettingsSubscreen.FREEDRENO_SETTINGS -> bundleOf("game" to args.game)
SettingsSubscreen.GAME_INFO,
SettingsSubscreen.ADDONS -> bundleOf(
"game" to requireNotNull(args.game) {
"Game is required for ${args.destination}"
}
)
else -> Bundle()
}
private fun setInsets() {
ViewCompat.setOnApplyWindowInsetsListener(
binding.navigationBarShade
) { _: View, windowInsets: WindowInsetsCompat ->
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
val mlpNavShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
mlpNavShade.height = barInsets.bottom
binding.navigationBarShade.layoutParams = mlpNavShade
windowInsets
}
}
}

View file

@ -21,9 +21,10 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import com.google.android.material.transition.MaterialSharedAxis
import org.yuzu.yuzu_emu.BuildConfig
import org.yuzu.yuzu_emu.HomeNavigationDirections
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.FragmentAboutBinding
import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
import org.yuzu.yuzu_emu.NativeLibrary
@ -54,7 +55,7 @@ class AboutFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
homeViewModel.setStatusBarShadeVisibility(visible = false)
binding.toolbarAbout.setNavigationOnClickListener {
binding.root.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
binding.imageLogo.setOnLongClickListener {
@ -72,8 +73,11 @@ class AboutFragment : Fragment() {
)
}
binding.buttonLicenses.setOnClickListener {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
binding.root.findNavController().navigate(R.id.action_aboutFragment_to_licensesFragment)
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.LICENSES,
null
)
binding.root.findNavController().navigate(action)
}
val buildName = getString(R.string.app_name_suffixed)

View file

@ -15,7 +15,6 @@ import androidx.core.view.updatePadding
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.transition.MaterialSharedAxis
@ -61,7 +60,7 @@ class AddonsFragment : Fragment() {
homeViewModel.setStatusBarShadeVisibility(false)
binding.toolbarAddons.setNavigationOnClickListener {
binding.root.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
binding.toolbarAddons.title = getString(R.string.addons_game, args.game.title)

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.fragments
@ -12,7 +12,6 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.transition.MaterialSharedAxis
import org.yuzu.yuzu_emu.R
@ -50,7 +49,7 @@ class AppletLauncherFragment : Fragment() {
homeViewModel.setStatusBarShadeVisibility(visible = false)
binding.toolbarApplets.setNavigationOnClickListener {
binding.root.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
val applets = listOf(

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -5,15 +8,18 @@ package org.yuzu.yuzu_emu.fragments
import android.app.Dialog
import android.content.DialogInterface
import android.net.Uri
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.preference.PreferenceManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.model.AddonViewModel
import org.yuzu.yuzu_emu.ui.main.MainActivity
import org.yuzu.yuzu_emu.utils.InstallableActions
class ContentTypeSelectionDialogFragment : DialogFragment() {
private val addonViewModel: AddonViewModel by activityViewModels()
@ -23,6 +29,52 @@ class ContentTypeSelectionDialogFragment : DialogFragment() {
private var selectedItem = 0
private val installGameUpdateLauncher =
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { documents ->
if (documents.isEmpty()) {
return@registerForActivityResult
}
val game = addonViewModel.game
if (game == null) {
installContent(documents)
return@registerForActivityResult
}
ProgressDialogFragment.newInstance(
requireActivity(),
R.string.verifying_content,
false
) { _, _ ->
var updatesMatchProgram = true
for (document in documents) {
val valid = NativeLibrary.doesUpdateMatchProgram(
game.programId,
document.toString()
)
if (!valid) {
updatesMatchProgram = false
break
}
}
requireActivity().runOnUiThread {
if (updatesMatchProgram) {
installContent(documents)
} else {
MessageDialogFragment.newInstance(
requireActivity(),
titleId = R.string.content_install_notice,
descriptionId = R.string.content_install_notice_description,
positiveAction = { installContent(documents) },
negativeAction = {}
).show(parentFragmentManager, MessageDialogFragment.TAG)
}
}
return@newInstance Any()
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val launchOptions =
arrayOf(getString(R.string.updates_and_dlc), getString(R.string.mods_and_cheats))
@ -31,12 +83,11 @@ class ContentTypeSelectionDialogFragment : DialogFragment() {
selectedItem = savedInstanceState.getInt(SELECTED_ITEM)
}
val mainActivity = requireActivity() as MainActivity
return MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.select_content_type)
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
when (selectedItem) {
0 -> mainActivity.installGameUpdate.launch(arrayOf("*/*"))
0 -> installGameUpdateLauncher.launch(arrayOf("*/*"))
else -> {
if (!preferences.getBoolean(MOD_NOTICE_SEEN, false)) {
preferences.edit().putBoolean(MOD_NOTICE_SEEN, true).apply()
@ -47,7 +98,7 @@ class ContentTypeSelectionDialogFragment : DialogFragment() {
}
}
}
.setSingleChoiceItems(launchOptions, 0) { _: DialogInterface, i: Int ->
.setSingleChoiceItems(launchOptions, selectedItem) { _: DialogInterface, i: Int ->
selectedItem = i
}
.setNegativeButton(android.R.string.cancel, null)
@ -65,4 +116,13 @@ class ContentTypeSelectionDialogFragment : DialogFragment() {
private const val SELECTED_ITEM = "SelectedItem"
private const val MOD_NOTICE_SEEN = "ModNoticeSeen"
}
private fun installContent(documents: List<Uri>) {
InstallableActions.installContent(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
addonViewModel = addonViewModel,
documents = documents
)
}
}

View file

@ -13,7 +13,6 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
@ -142,7 +141,7 @@ class DriverFetcherFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
homeViewModel.setStatusBarShadeVisibility(visible = false)
binding.toolbarDrivers.setNavigationOnClickListener {
binding.root.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
binding.listDrivers.layoutManager = LinearLayoutManager(context)

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.fragments
@ -19,6 +19,7 @@ import androidx.navigation.fragment.navArgs
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.transition.MaterialSharedAxis
import org.yuzu.yuzu_emu.HomeNavigationDirections
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -27,6 +28,7 @@ import org.yuzu.yuzu_emu.adapters.DriverAdapter
import org.yuzu.yuzu_emu.databinding.FragmentDriverManagerBinding
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen
import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver
import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.model.HomeViewModel
@ -105,7 +107,7 @@ class DriverManagerFragment : Fragment() {
}
binding.toolbarDrivers.setNavigationOnClickListener {
binding.root.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
binding.buttonInstall.setOnClickListener {
@ -113,9 +115,11 @@ class DriverManagerFragment : Fragment() {
}
binding.buttonFetch.setOnClickListener {
binding.root.findNavController().navigate(
R.id.action_driverManagerFragment_to_driverFetcherFragment
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.DRIVER_FETCHER,
null
)
binding.root.findNavController().navigate(action)
}
binding.listDrivers.apply {

View file

@ -4,20 +4,21 @@
package org.yuzu.yuzu_emu.fragments
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.transition.MaterialSharedAxis
import kotlinx.coroutines.launch
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.adapters.FolderAdapter
import org.yuzu.yuzu_emu.databinding.FragmentFoldersBinding
@ -25,7 +26,6 @@ import org.yuzu.yuzu_emu.model.DirectoryType
import org.yuzu.yuzu_emu.model.GameDir
import org.yuzu.yuzu_emu.model.GamesViewModel
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.ui.main.MainActivity
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
import org.yuzu.yuzu_emu.utils.collect
@ -36,6 +36,20 @@ class GameFoldersFragment : Fragment() {
private val homeViewModel: HomeViewModel by activityViewModels()
private val gamesViewModel: GamesViewModel by activityViewModels()
private val getGamesDirectory =
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
if (result != null) {
processGamesDir(result)
}
}
private val getExternalContentDirectory =
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
if (result != null) {
processExternalContentDir(result)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
@ -59,7 +73,7 @@ class GameFoldersFragment : Fragment() {
homeViewModel.setStatusBarShadeVisibility(visible = false)
binding.toolbarFolders.setNavigationOnClickListener {
binding.root.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
binding.listFolders.apply {
@ -74,7 +88,6 @@ class GameFoldersFragment : Fragment() {
(binding.listFolders.adapter as FolderAdapter).submitList(it)
}
val mainActivity = requireActivity() as MainActivity
binding.buttonAdd.setOnClickListener {
// Show a model to choose between Game and External Content
val options = arrayOf(
@ -87,10 +100,10 @@ class GameFoldersFragment : Fragment() {
.setItems(options) { _, which ->
when (which) {
0 -> { // Game Folder
mainActivity.getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data)
getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data)
}
1 -> { // External Content Folder
mainActivity.getExternalContentDirectory.launch(null)
getExternalContentDirectory.launch(null)
}
}
}
@ -105,6 +118,50 @@ class GameFoldersFragment : Fragment() {
gamesViewModel.onCloseGameFoldersFragment()
}
private fun processGamesDir(result: Uri) {
requireContext().contentResolver.takePersistableUriPermission(
result,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val uriString = result.toString()
val folder = gamesViewModel.folders.value.firstOrNull { it.uriString == uriString }
if (folder != null) {
Toast.makeText(
requireContext().applicationContext,
R.string.folder_already_added,
Toast.LENGTH_SHORT
).show()
return
}
AddGameFolderDialogFragment.newInstance(uriString, calledFromGameFragment = false)
.show(parentFragmentManager, AddGameFolderDialogFragment.TAG)
}
private fun processExternalContentDir(result: Uri) {
requireContext().contentResolver.takePersistableUriPermission(
result,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val uriString = result.toString()
val folder = gamesViewModel.folders.value.firstOrNull {
it.uriString == uriString && it.type == DirectoryType.EXTERNAL_CONTENT
}
if (folder != null) {
Toast.makeText(
requireContext().applicationContext,
R.string.folder_already_added,
Toast.LENGTH_SHORT
).show()
return
}
val externalContentDir = GameDir(uriString, deepScan = false, DirectoryType.EXTERNAL_CONTENT)
gamesViewModel.addFolder(externalContentDir, savedFromGameFragment = false)
}
private fun setInsets() =
ViewCompat.setOnApplyWindowInsetsListener(
binding.root

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.fragments
@ -18,7 +18,6 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.navigation.fragment.navArgs
import com.google.android.material.transition.MaterialSharedAxis
import org.yuzu.yuzu_emu.NativeLibrary
@ -64,7 +63,7 @@ class GameInfoFragment : Fragment() {
binding.apply {
toolbarInfo.title = args.game.title
toolbarInfo.setNavigationOnClickListener {
view.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
val pathString = Uri.parse(args.game.path).path ?: ""

View file

@ -35,6 +35,7 @@ import org.yuzu.yuzu_emu.adapters.GamePropertiesAdapter
import org.yuzu.yuzu_emu.databinding.FragmentGamePropertiesBinding
import org.yuzu.yuzu_emu.features.DocumentProvider
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen
import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.model.GameProperty
import org.yuzu.yuzu_emu.model.GamesViewModel
@ -250,8 +251,10 @@ class GamePropertiesFragment : Fragment() {
R.string.info_description,
R.drawable.ic_info_outline,
action = {
val action = GamePropertiesFragmentDirections
.actionPerGamePropertiesFragmentToGameInfoFragment(args.game)
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.GAME_INFO,
args.game
)
binding.root.findNavController().navigate(action)
}
)
@ -317,8 +320,11 @@ class GamePropertiesFragment : Fragment() {
R.string.add_ons_description,
R.drawable.ic_edit,
action = {
val action = GamePropertiesFragmentDirections
.actionPerGamePropertiesFragmentToAddonsFragment(args.game)
val action =
HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.ADDONS,
args.game
)
binding.root.findNavController().navigate(action)
}
)
@ -333,8 +339,11 @@ class GamePropertiesFragment : Fragment() {
R.drawable.ic_build,
detailsFlow = driverViewModel.selectedDriverTitle,
action = {
val action = GamePropertiesFragmentDirections
.actionPerGamePropertiesFragmentToDriverManagerFragment(args.game)
val action =
HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.DRIVER_MANAGER,
args.game
)
binding.root.findNavController().navigate(action)
}
)
@ -347,8 +356,11 @@ class GamePropertiesFragment : Fragment() {
R.string.freedreno_per_game_description,
R.drawable.ic_graphics,
action = {
val action = GamePropertiesFragmentDirections
.actionPerGamePropertiesFragmentToFreedrenoSettingsFragment(args.game)
val action =
HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.FREEDRENO_SETTINGS,
args.game
)
binding.root.findNavController().navigate(action)
}
)

View file

@ -36,6 +36,7 @@ import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding
import org.yuzu.yuzu_emu.features.DocumentProvider
import org.yuzu.yuzu_emu.features.fetcher.SpacingItemDecoration
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen
import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.model.HomeSetting
import org.yuzu.yuzu_emu.model.HomeViewModel
@ -126,8 +127,11 @@ class HomeSettingsFragment : Fragment() {
R.string.profile_manager_description,
R.drawable.ic_account_circle,
{
binding.root.findNavController()
.navigate(R.id.action_homeSettingsFragment_to_profileManagerFragment)
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.PROFILE_MANAGER,
null
)
binding.root.findNavController().navigate(action)
}
)
)
@ -137,8 +141,10 @@ class HomeSettingsFragment : Fragment() {
R.string.install_gpu_driver_description,
R.drawable.ic_build,
{
val action = HomeSettingsFragmentDirections
.actionHomeSettingsFragmentToDriverManagerFragment(null)
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.DRIVER_MANAGER,
null
)
binding.root.findNavController().navigate(action)
},
{ true },
@ -154,7 +160,12 @@ class HomeSettingsFragment : Fragment() {
R.string.gpu_driver_settings,
R.drawable.ic_graphics,
{
binding.root.findNavController().navigate(R.id.freedrenoSettingsFragment)
val action =
HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.FREEDRENO_SETTINGS,
null
)
binding.root.findNavController().navigate(action)
}
)
)
@ -175,8 +186,11 @@ class HomeSettingsFragment : Fragment() {
R.string.applets_description,
R.drawable.ic_applet,
{
binding.root.findNavController()
.navigate(R.id.action_homeSettingsFragment_to_appletLauncherFragment)
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.APPLET_LAUNCHER,
null
)
binding.root.findNavController().navigate(action)
},
{ NativeLibrary.isFirmwareAvailable() },
R.string.applets_error_firmware,
@ -189,8 +203,11 @@ class HomeSettingsFragment : Fragment() {
R.string.manage_yuzu_data_description,
R.drawable.ic_install,
{
binding.root.findNavController()
.navigate(R.id.action_homeSettingsFragment_to_installableFragment)
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.INSTALLABLE,
null
)
binding.root.findNavController().navigate(action)
}
)
)
@ -200,8 +217,11 @@ class HomeSettingsFragment : Fragment() {
R.string.select_games_folder_description,
R.drawable.ic_add,
{
binding.root.findNavController()
.navigate(R.id.action_homeSettingsFragment_to_gameFoldersFragment)
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.GAME_FOLDERS,
null
)
binding.root.findNavController().navigate(action)
}
)
)
@ -284,9 +304,11 @@ class HomeSettingsFragment : Fragment() {
R.string.about_description,
R.drawable.ic_info_outline,
{
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
parentFragmentManager.primaryNavigationFragment?.findNavController()
?.navigate(R.id.action_homeSettingsFragment_to_aboutFragment)
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.ABOUT,
null
)
binding.root.findNavController().navigate(action)
}
)
)

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.fragments
@ -14,23 +14,23 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.transition.MaterialSharedAxis
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.adapters.InstallableAdapter
import org.yuzu.yuzu_emu.databinding.FragmentInstallablesBinding
import org.yuzu.yuzu_emu.model.AddonViewModel
import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.model.GamesViewModel
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.model.Installable
import org.yuzu.yuzu_emu.model.TaskState
import org.yuzu.yuzu_emu.ui.main.MainActivity
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.FileUtil
import org.yuzu.yuzu_emu.utils.InstallableActions
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
import org.yuzu.yuzu_emu.utils.collect
@ -45,6 +45,9 @@ class InstallableFragment : Fragment() {
private val binding get() = _binding!!
private val homeViewModel: HomeViewModel by activityViewModels()
private val gamesViewModel: GamesViewModel by activityViewModels()
private val addonViewModel: AddonViewModel by activityViewModels()
private val driverViewModel: DriverViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -65,12 +68,10 @@ class InstallableFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val mainActivity = requireActivity() as MainActivity
homeViewModel.setStatusBarShadeVisibility(visible = false)
binding.toolbarInstallables.setNavigationOnClickListener {
binding.root.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
homeViewModel.openImportSaves.collect(viewLifecycleOwner) {
@ -84,8 +85,8 @@ class InstallableFragment : Fragment() {
Installable(
R.string.user_data,
R.string.user_data_description,
install = { mainActivity.importUserData.launch(arrayOf("application/zip")) },
export = { mainActivity.exportUserData.launch("export.zip") }
install = { importUserDataLauncher.launch(arrayOf("application/zip")) },
export = { exportUserDataLauncher.launch("export.zip") }
),
Installable(
R.string.manage_save_data,
@ -127,27 +128,33 @@ class InstallableFragment : Fragment() {
Installable(
R.string.install_game_content,
R.string.install_game_content_description,
install = { mainActivity.installGameUpdate.launch(arrayOf("*/*")) }
install = { installGameUpdateLauncher.launch(arrayOf("*/*")) }
),
Installable(
R.string.install_firmware,
R.string.install_firmware_description,
install = { mainActivity.getFirmware.launch(arrayOf("application/zip")) }
install = { getFirmwareLauncher.launch(arrayOf("application/zip")) }
),
Installable(
R.string.uninstall_firmware,
R.string.uninstall_firmware_description,
install = { mainActivity.uninstallFirmware() }
install = {
InstallableActions.uninstallFirmware(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
homeViewModel = homeViewModel
)
}
),
Installable(
R.string.install_prod_keys,
R.string.install_prod_keys_description,
install = { mainActivity.getProdKey.launch(arrayOf("*/*")) }
install = { getProdKeyLauncher.launch(arrayOf("*/*")) }
),
Installable(
R.string.install_amiibo_keys,
R.string.install_amiibo_keys_description,
install = { mainActivity.getAmiiboKey.launch(arrayOf("*/*")) }
install = { getAmiiboKeyLauncher.launch(arrayOf("*/*")) }
)
)
@ -180,6 +187,132 @@ class InstallableFragment : Fragment() {
windowInsets
}
private val getProdKeyLauncher =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
InstallableActions.processKey(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
gamesViewModel = gamesViewModel,
result = result,
extension = "keys"
)
}
}
private val getAmiiboKeyLauncher =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
InstallableActions.processKey(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
gamesViewModel = gamesViewModel,
result = result,
extension = "bin"
)
}
}
private val getFirmwareLauncher =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
InstallableActions.processFirmware(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
homeViewModel = homeViewModel,
result = result
)
}
}
private val installGameUpdateLauncher =
registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { documents ->
if (documents.isEmpty()) {
return@registerForActivityResult
}
if (addonViewModel.game == null) {
InstallableActions.installContent(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
addonViewModel = addonViewModel,
documents = documents
)
return@registerForActivityResult
}
ProgressDialogFragment.newInstance(
requireActivity(),
R.string.verifying_content,
false
) { _, _ ->
var updatesMatchProgram = true
for (document in documents) {
val valid = NativeLibrary.doesUpdateMatchProgram(
addonViewModel.game!!.programId,
document.toString()
)
if (!valid) {
updatesMatchProgram = false
break
}
}
if (updatesMatchProgram) {
requireActivity().runOnUiThread {
InstallableActions.installContent(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
addonViewModel = addonViewModel,
documents = documents
)
}
} else {
requireActivity().runOnUiThread {
MessageDialogFragment.newInstance(
requireActivity(),
titleId = R.string.content_install_notice,
descriptionId = R.string.content_install_notice_description,
positiveAction = {
InstallableActions.installContent(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
addonViewModel = addonViewModel,
documents = documents
)
},
negativeAction = {}
).show(parentFragmentManager, MessageDialogFragment.TAG)
}
}
return@newInstance Any()
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
}
private val importUserDataLauncher =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
InstallableActions.importUserData(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
gamesViewModel = gamesViewModel,
driverViewModel = driverViewModel,
result = result
)
}
}
private val exportUserDataLauncher =
registerForActivityResult(ActivityResultContracts.CreateDocument("application/zip")) { result ->
if (result != null) {
InstallableActions.exportUserData(
activity = requireActivity(),
fragmentManager = parentFragmentManager,
result = result
)
}
}
private val importSaves =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result == null) {

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.fragments
@ -13,7 +13,6 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.transition.MaterialSharedAxis
import org.yuzu.yuzu_emu.R
@ -48,7 +47,7 @@ class LicensesFragment : Fragment() {
homeViewModel.setStatusBarShadeVisibility(visible = false)
binding.toolbarLicenses.setNavigationOnClickListener {
binding.root.findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
val licenses = listOf(

View file

@ -51,7 +51,7 @@ class ProfileManagerFragment : Fragment() {
homeViewModel.setStatusBarShadeVisibility(visible = false)
binding.toolbarProfiles.setNavigationOnClickListener {
findNavController().popBackStack()
requireActivity().onBackPressedDispatcher.onBackPressed()
}
setupRecyclerView()

View file

@ -16,5 +16,17 @@ data class Patch(
val type: Int,
val programId: String,
val titleId: String,
val numericVersion: Long = 0
)
val numericVersion: Long = 0,
val source: Int = 0
) {
companion object {
const val SOURCE_UNKNOWN = 0
const val SOURCE_NAND = 1
const val SOURCE_SDMC = 2
const val SOURCE_EXTERNAL = 3
const val SOURCE_PACKED = 4
}
val isRemovable: Boolean
get() = source != SOURCE_EXTERNAL && source != SOURCE_PACKED
}

View file

@ -26,7 +26,6 @@ import androidx.preference.PreferenceManager
import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.io.File
import java.io.FilenameFilter
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
@ -39,16 +38,10 @@ import org.yuzu.yuzu_emu.model.AddonViewModel
import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.model.GamesViewModel
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.model.InstallResult
import android.os.Build
import org.yuzu.yuzu_emu.model.TaskState
import org.yuzu.yuzu_emu.model.TaskViewModel
import org.yuzu.yuzu_emu.utils.*
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import androidx.core.content.edit
import org.yuzu.yuzu_emu.activities.EmulationActivity
import kotlin.text.compareTo
@ -453,35 +446,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
fun processKey(result: Uri, extension: String = "keys") {
contentResolver.takePersistableUriPermission(
result,
Intent.FLAG_GRANT_READ_URI_PERMISSION
InstallableActions.processKey(
activity = this,
fragmentManager = supportFragmentManager,
gamesViewModel = gamesViewModel,
result = result,
extension = extension
)
val resultCode: Int = NativeLibrary.installKeys(result.toString(), extension)
if (resultCode == 0) {
// TODO(crueter): It may be worth it to switch some of these Toasts to snackbars,
// since most of it is foreground-only anyways.
Toast.makeText(
applicationContext,
R.string.keys_install_success,
Toast.LENGTH_SHORT
).show()
gamesViewModel.reloadGames(true)
return
}
val resultString: String =
resources.getStringArray(R.array.installKeysResults)[resultCode]
MessageDialogFragment.newInstance(
titleId = R.string.keys_failed,
descriptionString = resultString,
helpLinkId = R.string.keys_missing_help
).show(supportFragmentManager, MessageDialogFragment.TAG)
}
val getFirmware = registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
@ -491,75 +462,21 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
fun processFirmware(result: Uri, onComplete: (() -> Unit)? = null) {
val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") }
val firmwarePath =
File(NativeConfig.getNandDir() + "/system/Contents/registered/")
val cacheFirmwareDir = File("${cacheDir.path}/registered/")
ProgressDialogFragment.newInstance(
this,
R.string.firmware_installing
) { progressCallback, _ ->
var messageToShow: Any
try {
FileUtil.unzipToInternalStorage(
result.toString(),
cacheFirmwareDir,
progressCallback
)
val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
messageToShow = if (unfilteredNumOfFiles != filteredNumOfFiles) {
MessageDialogFragment.newInstance(
this,
titleId = R.string.firmware_installed_failure,
descriptionId = R.string.firmware_installed_failure_description
)
} else {
firmwarePath.deleteRecursively()
cacheFirmwareDir.copyRecursively(firmwarePath, true)
NativeLibrary.initializeSystem(true)
homeViewModel.setCheckKeys(true)
getString(R.string.save_file_imported_success)
}
} catch (e: Exception) {
Log.error("[MainActivity] Firmware install failed - ${e.message}")
messageToShow = getString(R.string.fatal_error)
} finally {
cacheFirmwareDir.deleteRecursively()
}
messageToShow
}.apply {
onDialogComplete = onComplete
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
InstallableActions.processFirmware(
activity = this,
fragmentManager = supportFragmentManager,
homeViewModel = homeViewModel,
result = result,
onComplete = onComplete
)
}
fun uninstallFirmware() {
val firmwarePath =
File(NativeConfig.getNandDir() + "/system/Contents/registered/")
ProgressDialogFragment.newInstance(
this,
R.string.firmware_uninstalling
) { progressCallback, _ ->
var messageToShow: Any
try {
// Ensure the firmware directory exists before attempting to delete
if (firmwarePath.exists()) {
firmwarePath.deleteRecursively()
// Optionally reinitialize the system or perform other necessary steps
NativeLibrary.initializeSystem(true)
homeViewModel.setCheckKeys(true)
messageToShow = getString(R.string.firmware_uninstalled_success)
} else {
messageToShow = getString(R.string.firmware_uninstalled_failure)
}
} catch (e: Exception) {
Log.error("[MainActivity] Firmware uninstall failed - ${e.message}")
messageToShow = getString(R.string.fatal_error)
}
messageToShow
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
InstallableActions.uninstallFirmware(
activity = this,
fragmentManager = supportFragmentManager,
homeViewModel = homeViewModel
)
}
val installGameUpdate = registerForActivityResult(
@ -606,101 +523,12 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
private fun installContent(documents: List<Uri>) {
ProgressDialogFragment.newInstance(
this@MainActivity,
R.string.installing_game_content
) { progressCallback, messageCallback ->
var installSuccess = 0
var installOverwrite = 0
var errorBaseGame = 0
var error = 0
documents.forEach {
messageCallback.invoke(FileUtil.getFilename(it))
when (
InstallResult.from(
NativeLibrary.installFileToNand(
it.toString(),
progressCallback
)
)
) {
InstallResult.Success -> {
installSuccess += 1
}
InstallResult.Overwrite -> {
installOverwrite += 1
}
InstallResult.BaseInstallAttempted -> {
errorBaseGame += 1
}
InstallResult.Failure -> {
error += 1
}
}
}
addonViewModel.refreshAddons(force = true)
val separator = System.lineSeparator() ?: "\n"
val installResult = StringBuilder()
if (installSuccess > 0) {
installResult.append(
getString(
R.string.install_game_content_success_install,
installSuccess
)
)
installResult.append(separator)
}
if (installOverwrite > 0) {
installResult.append(
getString(
R.string.install_game_content_success_overwrite,
installOverwrite
)
)
installResult.append(separator)
}
val errorTotal: Int = errorBaseGame + error
if (errorTotal > 0) {
installResult.append(separator)
installResult.append(
getString(
R.string.install_game_content_failed_count,
errorTotal
)
)
installResult.append(separator)
if (errorBaseGame > 0) {
installResult.append(separator)
installResult.append(
getString(R.string.install_game_content_failure_base)
)
installResult.append(separator)
}
if (error > 0) {
installResult.append(
getString(R.string.install_game_content_failure_description)
)
installResult.append(separator)
}
return@newInstance MessageDialogFragment.newInstance(
this,
titleId = R.string.install_game_content_failure,
descriptionString = installResult.toString().trim(),
helpLinkId = R.string.install_game_content_help_link
)
} else {
return@newInstance MessageDialogFragment.newInstance(
this,
titleId = R.string.install_game_content_success,
descriptionString = installResult.toString().trim()
)
}
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
InstallableActions.installContent(
activity = this,
fragmentManager = supportFragmentManager,
addonViewModel = addonViewModel,
documents = documents
)
}
val exportUserData = registerForActivityResult(
@ -709,25 +537,11 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
if (result == null) {
return@registerForActivityResult
}
ProgressDialogFragment.newInstance(
this,
R.string.exporting_user_data,
true
) { progressCallback, _ ->
val zipResult = FileUtil.zipFromInternalStorage(
File(DirectoryInitialization.userDirectory!!),
DirectoryInitialization.userDirectory!!,
BufferedOutputStream(contentResolver.openOutputStream(result)),
progressCallback,
compression = false
)
return@newInstance when (zipResult) {
TaskState.Completed -> getString(R.string.user_data_export_success)
TaskState.Failed -> R.string.export_failed
TaskState.Cancelled -> R.string.user_data_export_cancelled
}
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
InstallableActions.exportUserData(
activity = this,
fragmentManager = supportFragmentManager,
result = result
)
}
val importUserData =
@ -735,58 +549,12 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
if (result == null) {
return@registerForActivityResult
}
ProgressDialogFragment.newInstance(
this,
R.string.importing_user_data
) { progressCallback, _ ->
val checkStream =
ZipInputStream(BufferedInputStream(contentResolver.openInputStream(result)))
var isYuzuBackup = false
checkStream.use { stream ->
var ze: ZipEntry? = null
while (stream.nextEntry?.also { ze = it } != null) {
val itemName = ze!!.name.trim()
if (itemName == "/config/config.ini" || itemName == "config/config.ini") {
isYuzuBackup = true
return@use
}
}
}
if (!isYuzuBackup) {
return@newInstance MessageDialogFragment.newInstance(
this,
titleId = R.string.invalid_yuzu_backup,
descriptionId = R.string.user_data_import_failed_description
)
}
// Clear existing user data
NativeConfig.unloadGlobalConfig()
File(DirectoryInitialization.userDirectory!!).deleteRecursively()
// Copy archive to internal storage
try {
FileUtil.unzipToInternalStorage(
result.toString(),
File(DirectoryInitialization.userDirectory!!),
progressCallback
)
} catch (e: Exception) {
return@newInstance MessageDialogFragment.newInstance(
this,
titleId = R.string.import_failed,
descriptionId = R.string.user_data_import_failed_description
)
}
// Reinitialize relevant data
NativeLibrary.initializeSystem(true)
NativeConfig.initializeGlobalConfig()
gamesViewModel.reloadGames(false)
driverViewModel.reloadDriverData()
return@newInstance getString(R.string.user_data_import_success)
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
InstallableActions.importUserData(
activity = this,
fragmentManager = supportFragmentManager,
gamesViewModel = gamesViewModel,
driverViewModel = driverViewModel,
result = result
)
}
}

View file

@ -0,0 +1,327 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.utils
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
import org.yuzu.yuzu_emu.fragments.ProgressDialogFragment
import org.yuzu.yuzu_emu.model.AddonViewModel
import org.yuzu.yuzu_emu.model.DriverViewModel
import org.yuzu.yuzu_emu.model.GamesViewModel
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.model.InstallResult
import org.yuzu.yuzu_emu.model.TaskState
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.File
import java.io.FilenameFilter
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
object InstallableActions {
fun processKey(
activity: FragmentActivity,
fragmentManager: FragmentManager,
gamesViewModel: GamesViewModel,
result: Uri,
extension: String = "keys"
) {
activity.contentResolver.takePersistableUriPermission(
result,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val resultCode = NativeLibrary.installKeys(result.toString(), extension)
if (resultCode == 0) {
Toast.makeText(
activity.applicationContext,
R.string.keys_install_success,
Toast.LENGTH_SHORT
).show()
gamesViewModel.reloadGames(true)
return
}
val resultString = activity.resources.getStringArray(R.array.installKeysResults)[resultCode]
MessageDialogFragment.newInstance(
titleId = R.string.keys_failed,
descriptionString = resultString,
helpLinkId = R.string.keys_missing_help
).show(fragmentManager, MessageDialogFragment.TAG)
}
fun processFirmware(
activity: FragmentActivity,
fragmentManager: FragmentManager,
homeViewModel: HomeViewModel,
result: Uri,
onComplete: (() -> Unit)? = null
) {
val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") }
val firmwarePath = File(NativeConfig.getNandDir() + "/system/Contents/registered/")
val cacheFirmwareDir = File("${activity.cacheDir.path}/registered/")
ProgressDialogFragment.newInstance(
activity,
R.string.firmware_installing
) { progressCallback, _ ->
var messageToShow: Any
try {
FileUtil.unzipToInternalStorage(
result.toString(),
cacheFirmwareDir,
progressCallback
)
val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
messageToShow = if (unfilteredNumOfFiles != filteredNumOfFiles) {
MessageDialogFragment.newInstance(
activity,
titleId = R.string.firmware_installed_failure,
descriptionId = R.string.firmware_installed_failure_description
)
} else {
firmwarePath.deleteRecursively()
cacheFirmwareDir.copyRecursively(firmwarePath, overwrite = true)
NativeLibrary.initializeSystem(true)
homeViewModel.setCheckKeys(true)
activity.getString(R.string.save_file_imported_success)
}
} catch (_: Exception) {
messageToShow = activity.getString(R.string.fatal_error)
} finally {
cacheFirmwareDir.deleteRecursively()
}
messageToShow
}.apply {
onDialogComplete = onComplete
}.show(fragmentManager, ProgressDialogFragment.TAG)
}
fun uninstallFirmware(
activity: FragmentActivity,
fragmentManager: FragmentManager,
homeViewModel: HomeViewModel
) {
val firmwarePath = File(NativeConfig.getNandDir() + "/system/Contents/registered/")
ProgressDialogFragment.newInstance(
activity,
R.string.firmware_uninstalling
) { _, _ ->
val messageToShow: Any = try {
if (firmwarePath.exists()) {
firmwarePath.deleteRecursively()
NativeLibrary.initializeSystem(true)
homeViewModel.setCheckKeys(true)
activity.getString(R.string.firmware_uninstalled_success)
} else {
activity.getString(R.string.firmware_uninstalled_failure)
}
} catch (_: Exception) {
activity.getString(R.string.fatal_error)
}
messageToShow
}.show(fragmentManager, ProgressDialogFragment.TAG)
}
fun installContent(
activity: FragmentActivity,
fragmentManager: FragmentManager,
addonViewModel: AddonViewModel,
documents: List<Uri>
) {
ProgressDialogFragment.newInstance(
activity,
R.string.installing_game_content
) { progressCallback, messageCallback ->
var installSuccess = 0
var installOverwrite = 0
var errorBaseGame = 0
var error = 0
documents.forEach {
messageCallback.invoke(FileUtil.getFilename(it))
when (
InstallResult.from(
NativeLibrary.installFileToNand(
it.toString(),
progressCallback
)
)
) {
InstallResult.Success -> installSuccess += 1
InstallResult.Overwrite -> installOverwrite += 1
InstallResult.BaseInstallAttempted -> errorBaseGame += 1
InstallResult.Failure -> error += 1
}
}
addonViewModel.refreshAddons(force = true)
val separator = System.lineSeparator() ?: "\n"
val installResult = StringBuilder()
if (installSuccess > 0) {
installResult.append(
activity.getString(
R.string.install_game_content_success_install,
installSuccess
)
)
installResult.append(separator)
}
if (installOverwrite > 0) {
installResult.append(
activity.getString(
R.string.install_game_content_success_overwrite,
installOverwrite
)
)
installResult.append(separator)
}
val errorTotal = errorBaseGame + error
if (errorTotal > 0) {
installResult.append(separator)
installResult.append(
activity.getString(
R.string.install_game_content_failed_count,
errorTotal
)
)
installResult.append(separator)
if (errorBaseGame > 0) {
installResult.append(separator)
installResult.append(activity.getString(R.string.install_game_content_failure_base))
installResult.append(separator)
}
if (error > 0) {
installResult.append(
activity.getString(R.string.install_game_content_failure_description)
)
installResult.append(separator)
}
return@newInstance MessageDialogFragment.newInstance(
activity,
titleId = R.string.install_game_content_failure,
descriptionString = installResult.toString().trim(),
helpLinkId = R.string.install_game_content_help_link
)
} else {
return@newInstance MessageDialogFragment.newInstance(
activity,
titleId = R.string.install_game_content_success,
descriptionString = installResult.toString().trim()
)
}
}.show(fragmentManager, ProgressDialogFragment.TAG)
}
fun exportUserData(
activity: FragmentActivity,
fragmentManager: FragmentManager,
result: Uri
) {
val userDirectory = DirectoryInitialization.userDirectory
if (userDirectory == null) {
Toast.makeText(
activity.applicationContext,
R.string.fatal_error,
Toast.LENGTH_SHORT
).show()
return
}
ProgressDialogFragment.newInstance(
activity,
R.string.exporting_user_data,
true
) { progressCallback, _ ->
val zipResult = FileUtil.zipFromInternalStorage(
File(userDirectory),
userDirectory,
BufferedOutputStream(activity.contentResolver.openOutputStream(result)),
progressCallback,
compression = false
)
return@newInstance when (zipResult) {
TaskState.Completed -> activity.getString(R.string.user_data_export_success)
TaskState.Failed -> R.string.export_failed
TaskState.Cancelled -> R.string.user_data_export_cancelled
}
}.show(fragmentManager, ProgressDialogFragment.TAG)
}
fun importUserData(
activity: FragmentActivity,
fragmentManager: FragmentManager,
gamesViewModel: GamesViewModel,
driverViewModel: DriverViewModel,
result: Uri
) {
val userDirectory = DirectoryInitialization.userDirectory
if (userDirectory == null) {
Toast.makeText(
activity.applicationContext,
R.string.fatal_error,
Toast.LENGTH_SHORT
).show()
return
}
ProgressDialogFragment.newInstance(
activity,
R.string.importing_user_data
) { progressCallback, _ ->
val checkStream = ZipInputStream(
BufferedInputStream(activity.contentResolver.openInputStream(result))
)
var isYuzuBackup = false
checkStream.use { stream ->
var ze: ZipEntry? = null
while (stream.nextEntry?.also { ze = it } != null) {
val itemName = ze!!.name.trim()
if (itemName == "/config/config.ini" || itemName == "config/config.ini") {
isYuzuBackup = true
return@use
}
}
}
if (!isYuzuBackup) {
return@newInstance MessageDialogFragment.newInstance(
activity,
titleId = R.string.invalid_yuzu_backup,
descriptionId = R.string.user_data_import_failed_description
)
}
NativeConfig.unloadGlobalConfig()
File(userDirectory).deleteRecursively()
try {
FileUtil.unzipToInternalStorage(
result.toString(),
File(userDirectory),
progressCallback
)
} catch (_: Exception) {
return@newInstance MessageDialogFragment.newInstance(
activity,
titleId = R.string.import_failed,
descriptionId = R.string.user_data_import_failed_description
)
}
NativeLibrary.initializeSystem(true)
NativeConfig.initializeGlobalConfig()
gamesViewModel.reloadGames(false)
driverViewModel.reloadDriverData()
return@newInstance activity.getString(R.string.user_data_import_success)
}.show(fragmentManager, ProgressDialogFragment.TAG)
}
}

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include <common/fs/path_util.h>
#include <common/logging/log.h>
#include <common/logging.h>
#include <common/settings.h>
#include <input_common/main.h>
#include "android_config.h"

View file

@ -7,7 +7,7 @@
#include <android/native_window_jni.h>
#include "common/android/id_cache.h"
#include "common/logging/log.h"
#include "common/logging.h"
#include "input_common/drivers/android.h"
#include "input_common/drivers/touch_screen.h"
#include "input_common/drivers/virtual_amiibo.h"

View file

@ -42,8 +42,7 @@
#include "common/detached_tasks.h"
#include "common/dynamic_library.h"
#include "common/fs/path_util.h"
#include "common/logging/backend.h"
#include "common/logging/log.h"
#include "common/logging.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
#include "common/settings.h"
@ -1407,7 +1406,7 @@ jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env
Common::Android::ToJString(env, patch.version), static_cast<jint>(patch.type),
Common::Android::ToJString(env, std::to_string(patch.program_id)),
Common::Android::ToJString(env, std::to_string(patch.title_id)),
static_cast<jlong>(patch.numeric_version));
static_cast<jlong>(patch.numeric_version), static_cast<jint>(patch.source));
env->SetObjectArrayElement(jpatchArray, i, jpatch);
++i;
}

View file

@ -10,7 +10,7 @@
#include "common/android/android_common.h"
#include "common/android/id_cache.h"
#include "common/fs/path_util.h"
#include "common/logging/log.h"
#include "common/logging.h"
#include "common/settings.h"
#include "frontend_common/config.h"
#include "frontend_common/settings_generator.h"

View file

@ -23,7 +23,7 @@
#include <jni.h>
#include "common/android/android_common.h"
#include "common/logging/log.h"
#include "common/logging.h"
#include "native.h"
namespace {

View file

@ -1,8 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <common/android/android_common.h>
#include <common/logging/log.h>
#include <common/logging.h>
#include <jni.h>
extern "C" {

View file

@ -10,12 +10,11 @@
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_about"
style="@style/Widget.Eden.TransparentTopAppBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false"
android:background="@android:color/transparent"
app:elevation="0dp">
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_about"
@ -41,15 +40,41 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="24dp">
android:paddingBottom="24dp"
android:paddingStart="24dp"
android:paddingTop="0dp"
android:paddingEnd="24dp">
<ImageView
android:id="@+id/image_logo"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_vertical"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:src="@drawable/ic_yuzu" />
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/image_logo"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginBottom="8dp"
android:src="@drawable/ic_yuzu" />
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textAlignment="center" />
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="220dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/about_app_description"
android:textAlignment="center" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
@ -57,39 +82,6 @@
android:layout_weight="1"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="16dp"
app:cardBackgroundColor="?attr/colorSurface"
app:strokeColor="?attr/colorOutline"
app:strokeWidth="1dp"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="24dp"
android:paddingVertical="20dp">
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/about"
android:textAlignment="viewStart" />
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/about_app_description"
android:textAlignment="viewStart" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/button_contributors"
android:layout_width="match_parent"
@ -205,7 +197,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginTop="12dp"
android:gravity="start"
android:orientation="horizontal">

View file

@ -10,12 +10,11 @@
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_about"
style="@style/Widget.Eden.TransparentTopAppBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false"
android:background="@android:color/transparent"
app:elevation="0dp">
android:touchscreenBlocksFocus="false">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_about"
@ -43,48 +42,35 @@
android:orientation="vertical"
android:paddingBottom="24dp">
<ImageView
android:id="@+id/image_logo"
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_marginVertical="24dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_yuzu" />
<com.google.android.material.card.MaterialCardView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
app:strokeColor="?attr/colorOutline"
app:strokeWidth="1dp">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/image_logo"
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_marginBottom="8dp"
android:src="@drawable/ic_yuzu" />
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingVertical="20dp"
android:paddingHorizontal="20dp"
android:orientation="vertical">
android:text="@string/app_name"
android:textAlignment="center" />
<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="viewStart"
android:text="@string/about" />
<com.google.android.material.textview.MaterialTextView
style="@style/SynthwaveText.Body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textAlignment="center"
android:text="@string/about_app_description" />
<com.google.android.material.textview.MaterialTextView
style="@style/SynthwaveText.Body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:textAlignment="viewStart"
android:text="@string/about_app_description" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<com.google.android.material.card.MaterialCardView
android:id="@+id/button_contributors"
@ -206,7 +192,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:layout_marginTop="24dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="16dp"
android:layout_marginHorizontal="40dp">
@ -220,7 +206,9 @@
app:icon="@drawable/ic_discord"
app:iconSize="24dp"
app:iconGravity="textStart"
app:iconPadding="0dp" />
app:iconPadding="0dp"
app:strokeColor="?attr/colorOutline"
app:strokeWidth="1dp" />
<com.google.android.material.button.MaterialButton
style="@style/EdenButton.Secondary"
@ -232,7 +220,9 @@
app:icon="@drawable/ic_stoat"
app:iconSize="24dp"
app:iconGravity="textStart"
app:iconPadding="0dp" />
app:iconPadding="0dp"
app:strokeColor="?attr/colorOutline"
app:strokeWidth="1dp" />
<com.google.android.material.button.MaterialButton
style="@style/EdenButton.Secondary"
@ -244,7 +234,9 @@
app:icon="@drawable/ic_x"
app:iconSize="24dp"
app:iconGravity="textStart"
app:iconPadding="0dp" />
app:iconPadding="0dp"
app:strokeColor="?attr/colorOutline"
app:strokeWidth="1dp" />
<com.google.android.material.button.MaterialButton
style="@style/EdenButton.Secondary"
@ -256,7 +248,9 @@
app:icon="@drawable/ic_website"
app:iconSize="24dp"
app:iconGravity="textStart"
app:iconPadding="0dp" />
app:iconPadding="0dp"
app:strokeColor="?attr/colorOutline"
app:strokeWidth="1dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_github"
@ -268,7 +262,9 @@
app:icon="@drawable/ic_github"
app:iconSize="24dp"
app:iconGravity="textStart"
app:iconPadding="0dp" />
app:iconPadding="0dp"
app:strokeColor="?attr/colorOutline"
app:strokeWidth="1dp" />
</LinearLayout>

View file

@ -40,10 +40,6 @@
<action
android:id="@+id/action_global_settingsActivity"
app:destination="@id/settingsActivity"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
app:destination="@id/settingsActivity" />
</navigation>

View file

@ -20,26 +20,7 @@
<fragment
android:id="@+id/homeSettingsFragment"
android:name="org.yuzu.yuzu_emu.fragments.HomeSettingsFragment"
android:label="HomeSettingsFragment" >
<action
android:id="@+id/action_homeSettingsFragment_to_aboutFragment"
app:destination="@id/aboutFragment" />
<action
android:id="@+id/action_homeSettingsFragment_to_installableFragment"
app:destination="@id/installableFragment" />
<action
android:id="@+id/action_homeSettingsFragment_to_driverManagerFragment"
app:destination="@id/driverManagerFragment" />
<action
android:id="@+id/action_homeSettingsFragment_to_appletLauncherFragment"
app:destination="@id/appletLauncherFragment" />
<action
android:id="@+id/action_homeSettingsFragment_to_gameFoldersFragment"
app:destination="@id/gameFoldersFragment" />
<action
android:id="@+id/action_homeSettingsFragment_to_profileManagerFragment"
app:destination="@id/profileManagerFragment" />
</fragment>
android:label="HomeSettingsFragment" />
<fragment
android:id="@+id/firstTimeSetupFragment"
@ -55,11 +36,7 @@
<fragment
android:id="@+id/aboutFragment"
android:name="org.yuzu.yuzu_emu.fragments.AboutFragment"
android:label="AboutFragment" >
<action
android:id="@+id/action_aboutFragment_to_licensesFragment"
app:destination="@id/licensesFragment" />
</fragment>
android:label="AboutFragment" />
<fragment
android:id="@+id/licensesFragment"
@ -101,11 +78,23 @@
<action
android:id="@+id/action_global_settingsActivity"
app:destination="@id/settingsActivity"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
app:destination="@id/settingsActivity" />
<activity
android:id="@+id/settingsSubscreenActivity"
android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreenActivity"
android:label="SettingsSubscreenActivity">
<argument
android:name="destination"
app:argType="org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen" />
<argument
android:name="game"
app:argType="org.yuzu.yuzu_emu.model.Game"
app:nullable="true"
android:defaultValue="@null" />
</activity>
<action
android:id="@+id/action_global_settingsSubscreenActivity"
app:destination="@id/settingsSubscreenActivity" />
<fragment
android:id="@+id/installableFragment"
android:name="org.yuzu.yuzu_emu.fragments.InstallableFragment"
@ -119,9 +108,6 @@
app:argType="org.yuzu.yuzu_emu.model.Game"
app:nullable="true"
android:defaultValue="@null" />
<action
android:id="@+id/action_driverManagerFragment_to_driverFetcherFragment"
app:destination="@id/driverFetcherFragment" />
</fragment>
<fragment
android:id="@+id/appletLauncherFragment"

View file

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/settings_subscreen_navigation"
app:startDestination="@id/profileManagerFragment">
<fragment
android:id="@+id/profileManagerFragment"
android:name="org.yuzu.yuzu_emu.fragments.ProfileManagerFragment"
android:label="ProfileManagerFragment">
<action
android:id="@+id/action_profileManagerFragment_to_newUserDialog"
app:destination="@id/newUserDialogFragment" />
</fragment>
<fragment
android:id="@+id/newUserDialogFragment"
android:name="org.yuzu.yuzu_emu.fragments.EditUserDialogFragment"
android:label="NewUserDialogFragment" />
<fragment
android:id="@+id/driverManagerFragment"
android:name="org.yuzu.yuzu_emu.fragments.DriverManagerFragment"
android:label="DriverManagerFragment">
<argument
android:name="game"
app:argType="org.yuzu.yuzu_emu.model.Game"
app:nullable="true"
android:defaultValue="@null" />
</fragment>
<fragment
android:id="@+id/driverFetcherFragment"
android:name="org.yuzu.yuzu_emu.fragments.DriverFetcherFragment"
android:label="fragment_driver_fetcher"
tools:layout="@layout/fragment_driver_fetcher" />
<fragment
android:id="@+id/freedrenoSettingsFragment"
android:name="org.yuzu.yuzu_emu.fragments.FreedrenoSettingsFragment"
android:label="@string/freedreno_settings_title">
<argument
android:name="game"
app:argType="org.yuzu.yuzu_emu.model.Game"
app:nullable="true"
android:defaultValue="@null" />
</fragment>
<fragment
android:id="@+id/appletLauncherFragment"
android:name="org.yuzu.yuzu_emu.fragments.AppletLauncherFragment"
android:label="AppletLauncherFragment">
<action
android:id="@+id/action_appletLauncherFragment_to_cabinetLauncherDialogFragment"
app:destination="@id/cabinetLauncherDialogFragment" />
</fragment>
<dialog
android:id="@+id/cabinetLauncherDialogFragment"
android:name="org.yuzu.yuzu_emu.fragments.CabinetLauncherDialogFragment"
android:label="CabinetLauncherDialogFragment" />
<fragment
android:id="@+id/aboutFragment"
android:name="org.yuzu.yuzu_emu.fragments.AboutFragment"
android:label="AboutFragment" />
<fragment
android:id="@+id/licensesFragment"
android:name="org.yuzu.yuzu_emu.fragments.LicensesFragment"
android:label="LicensesFragment" />
<fragment
android:id="@+id/gameInfoFragment"
android:name="org.yuzu.yuzu_emu.fragments.GameInfoFragment"
android:label="GameInfoFragment">
<argument
android:name="game"
app:argType="org.yuzu.yuzu_emu.model.Game" />
</fragment>
<fragment
android:id="@+id/addonsFragment"
android:name="org.yuzu.yuzu_emu.fragments.AddonsFragment"
android:label="AddonsFragment">
<argument
android:name="game"
app:argType="org.yuzu.yuzu_emu.model.Game" />
</fragment>
<fragment
android:id="@+id/installableFragment"
android:name="org.yuzu.yuzu_emu.fragments.InstallableFragment"
android:label="InstallableFragment" />
<fragment
android:id="@+id/gameFoldersFragment"
android:name="org.yuzu.yuzu_emu.fragments.GameFoldersFragment"
android:label="GameFoldersFragment" />
<activity
android:id="@+id/emulationActivity"
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
android:label="EmulationActivity">
<argument
android:name="game"
app:argType="org.yuzu.yuzu_emu.model.Game"
app:nullable="true"
android:defaultValue="@null" />
<argument
android:name="custom"
app:argType="boolean"
android:defaultValue="false" />
</activity>
<action
android:id="@+id/action_global_emulationActivity"
app:destination="@id/emulationActivity"
app:launchSingleTop="true" />
<activity
android:id="@+id/settingsSubscreenActivity"
android:name="org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreenActivity"
android:label="SettingsSubscreenActivity">
<argument
android:name="destination"
app:argType="org.yuzu.yuzu_emu.features.settings.ui.SettingsSubscreen" />
<argument
android:name="game"
app:argType="org.yuzu.yuzu_emu.model.Game"
app:nullable="true"
android:defaultValue="@null" />
</activity>
<action
android:id="@+id/action_global_settingsSubscreenActivity"
app:destination="@id/settingsSubscreenActivity" />
</navigation>

View file

@ -31,6 +31,8 @@
<string name="enable_input_overlay_auto_hide">تمكين إخفاء الطبقة تلقائيًا</string>
<string name="hide_overlay_on_controller_input">إخفاء الطبقة عند إدخال ذراع التحكم</string>
<string name="hide_overlay_on_controller_input_description">إخفاء تلقائي لطبقة عناصر التحكم باللمس عند استخدام ذراع تحكم فعلية. تظهر الطبقة مرة أخرى عند فصل ذراع التحكم.</string>
<string name="invert_confirm_back_controller_buttons">عكس أزرار التأكيد/الرجوع في وحدة التحكم</string>
<string name="invert_confirm_back_controller_buttons_description">قم بتبديل طريقة عمل زري التأكيد والرجوع في نظام Android لتتوافق مع أنماط Switch و Xbox أثناء استخدام واجهة المستخدم الخاصة بالتطبيق.</string>
<string name="input_overlay_options">طبقة الإدخال</string>
<string name="input_overlay_options_description">ضبط ذراع التحكم على الشاشة</string>
@ -315,6 +317,9 @@
<string name="share_log">مشاركة سجلات التصحيح</string>
<string name="share_log_description">مشاركة ملف سجل Eden لتصحيح الأخطاء</string>
<string name="share_log_missing">لم يتم العثور على ملف السجل</string>
<string name="share_gpu_log">مشاركة سجلات وحدة معالجة الرسومات</string>
<string name="share_gpu_log_description">شارك ملف سجل وحدة معالجة الرسومات الخاص بـ Eden لتصحيح مشكلات الرسومات</string>
<string name="share_gpu_log_missing">لم يتم العثور على ملف سجل وحدة معالجة الرسومات</string>
<string name="install_game_content">تثبيت محتوى اللعبة</string>
<string name="install_game_content_description">تثبيت تحديثات اللعبة أو المحتوى القابل للتنزيل</string>
<string name="installing_game_content">جارٍ تثبيت المحتوى...</string>
@ -376,9 +381,9 @@
<string name="qlaunch_description">تشغيل التطبيقات من شاشة النظام الرئيسية</string>
<string name="applets">مشغل التطبيقات الصغيرة</string>
<string name="applets_description">تشغيل تطبيقات الصغيرة للنظام باستخدام الفيرموير المثبت</string>
<string name="applets_error_firmware">الفيرموير غير مثبت أو إصدار غير صالح</string>
<string name="applets_error_firmware">الفيرموير غير مثبت</string>
<string name="applets_error_applet">التطبيق الصغير غير متوفر</string>
<string name="applets_error_description"><![CDATA[يرجى التأكد من أن ملف <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> الخاص بك و <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">الفيرموير</a> مثبتة وحاول مرة أخرى.<br>بالإضافة إلى ذلك، تأكد من أن الفيرموير الخاص بك هو من الإصدار 19.0.1 أو أقدم.]]></string>
<string name="applets_error_description"><![CDATA[يرجى التأكد من <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ملف و <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">الفيرموير</a> تم تثبيتها وحاول مرة أخرى.]]></string>
<string name="album_applet">الألبوم</string>
<string name="album_applet_description">عرض الصور المخزنة في مجلد لقطات شاشة المستخدم باستخدام عارض صور النظام</string>
<string name="mii_edit_applet">تعديل Mii</string>
@ -396,7 +401,7 @@
<string name="copied_to_clipboard">نسخ إلى الحافظة</string>
<string name="about_app_description">محاكي Switch مفتوح المصدر</string>
<string name="contributors">المساهمين</string>
<string name="contributors_description">المساهمون الذين جعلوا تطبيق Eden لنظام Android ممكناً</string>
<string name="contributors_description">الأشخاص الذين جعلوا تطبيق Eden لنظام Android ممكنًا</string>
<string name="licenses_description">المشاريع التي تجعل Eden لأجهزة Android ممكنة</string>
<string name="build">البناء</string>
<string name="user_data">بيانات المستخدم</string>
@ -412,7 +417,11 @@
<string name="frame_limit_enable">الحد من السرعة</string>
<string name="frame_limit_enable_description">يحدد سرعة المحاكاة بنسبة مئوية محددة من السرعة العادية.</string>
<string name="frame_limit_slider">نسبة الحد الأقصى للسرعة</string>
<string name="frame_limit_slider_description">يحدد النسبة المئوية للحد من سرعة المحاكاة. 100٪ هي السرعة العادية. القيم الأعلى أو الأقل ستزيد أو تقلل من الحد الأقصى للسرعة.</string>
<string name="frame_limit_slider_description">يحدد النسبة المئوية للحد من سرعة المحاكاة. %100 هي السرعة الطبيعية. القيم الأعلى أو الأقل ستزيد أو تقلل من الحد الأقصى للسرعة.</string>
<string name="turbo_speed_limit">سرعة تيربو</string>
<string name="turbo_speed_limit_description">عند تمكين وضع التيربو، سيتم تشغيل المحاكاة بهذه السرعة.</string>
<string name="slow_speed_limit">سرعة بطيئة</string>
<string name="slow_speed_limit_description">عند تمكين الوضع البطيء، سيتم تشغيل المحاكاة بهذه السرعة.</string>
<string name="cpu_backend">خلفية وحدة المعالجة المركزية</string>
<string name="cpu_accuracy">دقة وحدة المعالجة المركزية</string>
<string name="value_with_units">%1$s%2$s</string>
@ -431,7 +440,7 @@
<!-- CPU -->
<string name="fast_cpu_time">رفع تردد المعالج</string>
<string name="fast_cpu_time_description">يُجبر هذا الخيار المعالج المُحاكى على العمل بتردد أعلى، مما يُقلل من بعض مُحددات معدل الإطارات. استخدم وضع Boost (1700 ميجاهرتز) للتشغيل بأعلى تردد أصلي لجهاز Switch، أو وضع Fast (2000 ميجاهرتز) للتشغيل بتردد مُضاعف.</string>
<string name="fast_cpu_time_description">يجبر وحدة المعالجة المركزية المحاكاة على العمل بتردد أعلى، مما يقلل بعض محددات معدل الإطارات. استخدم وضع التعزيز (1700 ميجاهرتز) لتشغيلها عند أعلى تردد أصلي لجهاز Switch، أو وضع السرعة (2000 ميجاهرتز) لتشغيلها بتردد مضاعف.</string>
<string name="custom_cpu_ticks">تخصيص دورات المعالج</string>
<string name="custom_cpu_ticks_description">قم بتعيين قيمة مخصصة لدورات المعالج. القيم الأعلى يمكن أن تزيد من الأداء، ولكنها قد تتسبب أيضًا في تجميد اللعبة. يوصى باستخدام نطاق 77-21000.</string>
<string name="cpu_ticks">دورات</string>
@ -464,6 +473,8 @@
<string name="renderer_accuracy_description">يتحكم في وضع محاكاة وحدة معالجة الرسومات. تعمل معظم الألعاب بشكل جيد مع وضعي سريع أو متوازن، لكن الوضع الدقيق لا يزال مطلوبًا لبعض الألعاب. تميل الجسيمات إلى العرض بشكل صحيح فقط عند استخدام الوضع الدقيق.</string>
<string name="dma_accuracy">دقة DMA</string>
<string name="dma_accuracy_description">يتحكم في دقة DMA. يمكن أن تؤدي الدقة الآمنة إلى حل المشكلات في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا لم تكن متأكدًا، فاترك هذا الخيار على الإعداد الافتراضي.</string>
<string name="frame_pacing_mode">وضع توقيت الإطارات</string>
<string name="frame_pacing_mode_description">يتحكم في كيفية إدارة المحاكي لسرعة الإطارات لتقليل التقطع وجعل معدل الإطارات أكثر سلاسة واتساقًا.</string>
<string name="anisotropic_filtering">تصفية متباينة الخواص</string>
<string name="anisotropic_filtering_description">يحسن جودة الأنسجة عند عرضها بزوايا مائلة</string>
<string name="vram_usage_mode">وضع استخدام ذاكرة VRAM</string>
@ -481,7 +492,10 @@
<string name="renderer_force_max_clock_description">يجبر وحدة معالجة الرسومات على العمل بأقصى سرعة ممكنة (سيظل يتم تطبيق القيود الحرارية).</string>
<string name="renderer_reactive_flushing">استخدم التنظيف التفاعلي</string>
<string name="renderer_reactive_flushing_description">يحسن دقة العرض في بعض الألعاب على حساب الأداء.</string>
<string name="enable_buffer_history">تمكين سجل التخزين المؤقت</string>
<string name="enable_buffer_history_description">يُتيح هذا الخيار الوصول إلى حالات التخزين المؤقت السابقة. وقد يُحسّن جودة العرض وثبات الأداء في بعض الألعاب.</string>
<string name="use_optimized_vertex_buffers">مخازن الرؤوس المُحسّنة</string>
<string name="use_optimized_vertex_buffers_description">يُتيح ربطًا مُحسَّنًا لمخازن الرؤوس لتحسين الأداء. يتطلب برامج تشغيل Turnip من Mesa 26.0 أو أحدث. قد يتعطل على برامج التشغيل الأقدم.</string>
<string name="hacks">اختراقات</string>
@ -490,15 +504,20 @@
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
<string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string>
<string name="fix_bloom_effects_description">يقلل من ضبابية التوهج في وضع LA/EOW (مخصص ل Adreno 700)، ويزيل التوهج في وضع الإحتراق</string>
<string name="fix_bloom_effects_description">يقلل من ضبابية التوهج في LA/EOW (Adreno 700)، ويزيل التوهج في Burnout. تحذير: قد يسبب ظهور خلل رسومي في ألعاب أخرى.</string>
<string name="renderer_asynchronous_shaders">استخدم تظليل غير متزامن</string>
<string name="renderer_asynchronous_shaders_description">يقوم بتجميع التظليل بشكل غير متزامن. قد يقلل ذلك من التقطعات ولكنه قد يؤدي أيضًا إلى حدوث أخطاء.</string>
<string name="gpu_unswizzle_settings">إعدادات إلغاء ترتيب بيانات وحدة معالجة الرسومات</string>
<string name="gpu_unswizzle_settings_description">قم بضبط معلمات فكّ تشابك النسيج المستندة إلى وحدة معالجة الرسومات أو تعطيلها تمامًا. اضبط هذه الإعدادات لتحقيق التوازن بين الأداء وجودة تحميل النسيج.</string>
<string name="gpu_unswizzle_enable">تفعيل إلغاء ترتيب بيانات وحدة معالجة الرسومات</string>
<string name="gpu_unswizzle_disabled">تعطيل</string>
<string name="gpu_unswizzle_texture_size">الحد الأقصى لحجم النسيج في وحدة معالجة الرسومات بعد إعادة ترتيب البيانات</string>
<string name="gpu_unswizzle_texture_size_description">يُحدد هذا الخيار الحد الأقصى لحجم (ميغابايت) معالجة الصور باستخدام وحدة معالجة الرسومات. مع أن وحدة معالجة الرسومات أسرع في معالجة الصور المتوسطة والكبيرة، إلا أن وحدة المعالجة المركزية قد تكون أكثر كفاءة في معالجة الصور الصغيرة جدًا. اضبط هذا الخيار لتحقيق التوازن الأمثل بين سرعة معالجة الرسومات واستهلاك وحدة المعالجة المركزية.</string>
<string name="gpu_unswizzle_stream_size">حجم تدفق إلغاء ترتيب بيانات وحدة معالجة الرسومات</string>
<string name="gpu_unswizzle_stream_size_description">يحدد هذا الخيار حد البيانات لكل إطار لمعالجة الصور الكبيرة. القيم الأعلى تُسرّع تحميل الصور على حساب زيادة زمن استجابة الإطارات؛ أما القيم الأقل فتُقلل من الحمل الزائد على وحدة معالجة الرسومات، ولكنها قد تتسبب في ظهور الصور بشكل مفاجئ.</string>
<string name="gpu_unswizzle_chunk_size">حجم كتلة إلغاء ترتيب بيانات وحدة معالجة الرسومات</string>
<string name="gpu_unswizzle_chunk_size_description">يُحدد هذا الخيار عدد شرائح العمق التي تتم معالجتها لكل دفعة من الصور ثلاثية الأبعاد (3D). زيادة هذا العدد تُحسّن كفاءة الإنتاجية على وحدات معالجة الرسومات القوية، ولكنها قد تُسبب تقطعًا أو انقطاعًا في عمل برنامج التشغيل على الأجهزة ذات المواصفات الأقل قوة.</string>
<string name="gpu_unswizzle_default_button">افتراضي</string>
<string name="extensions">إضافات</string>
@ -543,6 +562,24 @@
<string name="flush_by_line">تفريغ سجلات التصحيح حسب السطر</string>
<string name="flush_by_line_description">يفرغ سجلات التصحيح عند كتابة كل سطر، مما يجعل التصحيح أسهل في حالات التوقف أو التجميد.</string>
<!-- GPU Logging strings -->
<string name="gpu_logging_header">تسجيل وحدة معالجة الرسومات</string>
<string name="gpu_logging_enabled">تمكين تسجيل وحدة معالجة الرسومات</string>
<string name="gpu_logging_enabled_description">تسجيل عمليات وحدة معالجة الرسومات في ملف eden_gpu.log لتصحيح أخطاء برامج تشغيل Adreno</string>
<string name="gpu_log_level">مستوى السجل</string>
<string name="gpu_log_level_description">مستوى التفاصيل لسجلات وحدة معالجة الرسومات (كلما زاد المستوى، زادت التفاصيل وزادت التكاليف الإضافية)</string>
<string name="gpu_log_vulkan_calls">تسجيل استدعاءات واجهة برمجة تطبيقات Vulkan</string>
<string name="gpu_log_vulkan_calls_description">تتبع جميع استدعاءات واجهة برمجة تطبيقات Vulkan في المخزن المؤقت الحلقي</string>
<string name="gpu_log_shader_dumps">تفريغ التظليل</string>
<string name="gpu_log_shader_dumps_description">حفظ تظليل SPIR-V المجمع في ملفات</string>
<string name="gpu_log_memory_tracking">تتبع ذاكرة وحدة معالجة الرسومات</string>
<string name="gpu_log_memory_tracking_description">مراقبة تخصيصات ذاكرة وحدة معالجة الرسومات وإلغاء تخصيصها</string>
<string name="gpu_log_driver_debug">معلومات تصحيح أخطاء برنامج التشغيل</string>
<string name="gpu_log_driver_debug_description">التقاط معلومات تصحيح الأخطاء الخاصة ببرنامج التشغيل (مسارات Turnip، وما إلى ذلك).</string>
<string name="gpu_log_ring_buffer_size">حجم المخزن المؤقت الحلقي</string>
<string name="gpu_log_ring_buffer_size_description">عدد استدعاءات Vulkan الأخيرة المراد تتبعها (الافتراضي: 512)</string>
<string name="gpu_log_ring_buffer_size_hint">من 64 إلى 4096 مدخلاً</string>
<string name="general">عام</string>
<!-- Audio settings strings -->
@ -631,7 +668,7 @@
<string name="loading">جارٍ التحميل…</string>
<string name="shutting_down">جارٍ إيقاف التشغيل...</string>
<string name="reset_setting_confirmation">هل تريد إعادة تعيين هذا الإعداد إلى قيمته الافتراضية؟</string>
<string name="reset_to_default">إعادة التعيين إلى الوضع الافتراضي</string>
<string name="reset_to_default">إعادة التعيين إلى الإعدادات الافتراضية</string>
<string name="reset_to_default_description">إعادة تعيين جميع الإعدادات المتقدمة</string>
<string name="reset_all_settings">إعادة تعيين جميع الإعدادات؟</string>
<string name="reset_all_settings_description">سيتم إعادة تعيين جميع الإعدادات المتقدمة إلى ضبطها الافتراضي. لا يمكن التراجع عن هذا الإجراء.</string>
@ -697,6 +734,8 @@
<string name="preferences_graphics">الرسومات</string>
<string name="preferences_graphics_description">مستوى الدقة، الدقة، ذاكرة التخزين المؤقتة للتظليل</string>
<string name="quick_settings">الإعدادات السريعة</string>
<string name="enable_quick_settings">تمكين الإعدادات السريعة</string>
<string name="enable_quick_settings_description">السماح بالوصول إلى قائمة الإعدادات السريعة عن طريق التمرير و زر القائمة</string>
<string name="preferences_audio">الصوت</string>
<string name="preferences_audio_description">محرك الإخراج، مستوى الصوت</string>
<string name="preferences_controls">ذراع التحكم</string>
@ -729,7 +768,7 @@
<!-- Game properties -->
<string name="info">معلومات</string>
<string name="info_description">معرف العنوان، المطور، الإصدار</string>
<string name="per_game_settings">إعدادات خاصة للعبة</string>
<string name="per_game_settings">الإعدادات الخاصة للعبة</string>
<string name="per_game_settings_description">تعديل الإعدادات الخاصة بهذه اللعبة</string>
<string name="launch_options">تشغيل الإعدادات</string>
<string name="path">المسار</string>
@ -960,6 +999,13 @@
<string name="dma_accuracy_unsafe">غير آمن</string>
<string name="dma_accuracy_safe">آمن</string>
<!-- Frame Pacing Mode -->
<string name="frame_pacing_mode_target_Auto">تلقائي</string>
<string name="frame_pacing_mode_target_30">30 إطارًا في الثانية</string>
<string name="frame_pacing_mode_target_60">60 إطارًا في الثانية</string>
<string name="frame_pacing_mode_target_90">90 إطارًا في الثانية</string>
<string name="frame_pacing_mode_target_120">120 إطارًا في الثانية</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">غير مضغوط</string>
<!-- ASTC Recompression Method Choices -->
@ -1042,18 +1088,24 @@
<string name="use_black_backgrounds">خلفيات سوداء</string>
<string name="use_black_backgrounds_description">عند استخدام السمة الداكنة، قم بتطبيق خلفيات سوداء.</string>
<!-- Buttons -->
<string name="enable_folder_button">مجلد</string>
<string name="enable_folder_button_description">عرض زر إضافة مجلدات الألعاب</string>
<string name="enable_qlaunch_button">القائمة الرئيسية</string>
<string name="enable_qlaunch_button_description">عرض زر تشغيل القائمة الرئيسية</string>
<!-- App Language -->
<string name="app_language">لغة التطبيق</string>
<string name="app_language_description">تغيير لغة واجهة التطبيق</string>
<string name="app_language_system">اتبع النظام</string>
<!-- Static Themes -->
<string name="static_theme_color">لون السمة</string>
<string name="eden_theme">Eden (افتراضي)</string>
<string name="eden_theme">إيدن</string>
<string name="violet">بنفسجي</string>
<string name="blue">أزرق</string>
<string name="cyan">سماوي</string>
<string name="red">أحمر</string>
<string name="green">أخضر</string>
<string name="green">أخضر (افتراضي)</string>
<string name="yellow">أصفر</string>
<string name="orange">برتقالي</string>
<string name="pink">وردي</string>
@ -1085,7 +1137,39 @@
<string name="enable_overlay">تمكين التطبيق الصغير للطبقة</string>
<string name="enable_overlay_description">تمكين التطبيق الصغير المدمج في Horizon. اضغط مع الاستمرار على زر الشاشة الرئيسية لمدة 1 ثانية لإظهاره.</string>
<!-- Profile Management -->
<string name="profile_manager">مدير الملف الشخصي</string>
<string name="profile_manager_description">إدارة ملفات تعريف المستخدمين</string>
<string name="profile_add_user">إضافة مستخدم</string>
<string name="profile_new_user">مستخدم جديد</string>
<string name="profile_edit_user">تعديل المستخدم</string>
<string name="profile_edit">تعديل</string>
<string name="profile_delete">حذف</string>
<string name="profile_username">اسم المستخدم</string>
<string name="profile_uuid">معرف المستخدم (UUID)</string>
<string name="profile_uuid_description">هذا هو المعرف الفريد لملف تعريف المستخدم هذا. لا يمكن تغييره بعد إنشائه.</string>
<string name="profile_generate">إنشاء</string>
<string name="profile_avatar">صورة المستخدم</string>
<string name="profile_select_image">اختر صورة</string>
<string name="profile_firmware_avatars">صور رمزية للفيرموير</string>
<string name="profile_firmware_avatars_unavailable">الصور الرمزية للفيرموير غير متوفرة. يرجى تثبيت الفيرموير لاستخدام هذه الميزة.</string>
<string name="profile_revert_image">العودة إلى الإعدادات الافتراضية</string>
<string name="profile_current_user">المستخدم الحالي</string>
<string name="profile_max_users_title">تم الوصول إلى الحد الأقصى للمستخدمين</string>
<string name="profile_max_users_message">لا يمكنك إنشاء أكثر من 8 ملفات تعريف مستخدم. يرجى حذف ملف تعريف موجود لإنشاء ملف تعريف جديد.</string>
<string name="profile_delete_confirm_title">حذف ملف التعريف؟</string>
<string name="profile_delete_confirm_message">هل تريد حذفها حقًا %1$s؟ سيتم حذف جميع البيانات المحفوظة لهذا المستخدم.</string>
<string name="profile_delete_current_user_message">هل تريد حذف هذا المستخدم %1$s؟ هذا هو المستخدم المحدد حالياً. سيتم تحديد أول مستخدم متاح بدلاً منه.</string>
<string name="profile_create_failed">فشل إنشاء ملف تعريف المستخدم</string>
<string name="profile_update_failed">فشل تحديث ملف تعريف المستخدم</string>
<string name="profile_image_load_error">فشل تحميل الصورة: %1$s</string>
<string name="profile_image_save_error">فشل حفظ الصورة: %1$s</string>
<string name="error">خطأ</string>
<!-- Licenses screen strings -->
<string name="licenses">التراخيص</string>
<string name="license_fidelityfx_fsr_description">تحسين الجودة بدرجة عالية من AMD</string>
</resources>
<string name="external_content">محتوى خارجي</string>
<string name="add_folders">إضافة مجلد</string>
</resources>

View file

@ -272,9 +272,7 @@
<string name="qlaunch_description">ئەپەکان لە شاشەی سەرەکی سیستەم دەستپێبکە</string>
<string name="applets">دەستپێکەری ئەپلێت</string>
<string name="applets_description">ئەپلێتی سیستەم دەستپێبکە بە بەکارهێنانی پتەوواڵای دامەزراو</string>
<string name="applets_error_firmware">فریموێر نەنێردراوە یان وەشانێکی نادروستە</string>
<string name="applets_error_applet">ئەپلێت بەردەست نییە</string>
<string name="applets_error_description"><![CDATA[تکایە دڵنیابە لەوەی فایلی <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> و <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">فریموێر</a>ەکەت نێردراوە و هەوڵ بدەرەوە.<br>هەروەها دڵنیابە لەوەی فریموێرەکەت وەشانی ١٩.٠.١ یان کەمتر بێت.]]></string>
<string name="album_applet">ئەلبوم</string>
<string name="album_applet_description">وێنەکان لە فۆڵدەری وێنەی بەکارهێنەر ببینە</string>
<string name="mii_edit_applet">دەستکاریی Mii</string>
@ -292,7 +290,6 @@
<string name="copied_to_clipboard">کۆپی کرا بۆ تەختەی نووسین</string>
<string name="about_app_description">ئیمۆلیتەرێکی سەرچاوە-کراوەی سویچ</string>
<string name="contributors">بەشداربووان</string>
<string name="contributors_description">دروستکراوە لەگەڵ \u2764 لەلایەن تیمەکەی یوزو</string>
<string name="licenses_description">ئەو پڕۆژانەی کە یوزوی بۆ ئەندرۆید ڕەخساند</string>
<string name="build">بونیات</string>
<!-- General settings strings -->
@ -357,8 +354,6 @@
<string name="renderer_force_max_clock_description">GPU ناچار دەکات بە زۆرترین کاتژمێر کاربکات (هێشتا سنووردارکردنی گەرمی جێبەجێ دەکرێت).</string>
<string name="renderer_reactive_flushing">بەکارهێنانی بەرپێچدەرەوە</string>
<string name="renderer_reactive_flushing_description">وردی ڕێندەرکردن لە هەندێک یاریدا باشتر دەکات لەسەر تێچووی کارایی.</string>
<string name="skip_cpu_inner_invalidation">بازنەکردنی ناوەکی CPU</string>
<string name="skip_cpu_inner_invalidation_description">هەندێک لە بازنەکردنەکانی هەڵگر لە کاتی نوێکردنەوەی بیرگە دەنێرێت، کەمکردنەوەی بەکارهێنانی CPU و باشترکردنی کارایی. لەوانەیە لە هەندێک یاری کێشە درووست بکات.</string>
<string name="renderer_asynchronous_shaders">بەکارهێنانی سێبەری ناهاوسەنگ</string>
@ -634,7 +629,6 @@
<string name="blue">شین</string>
<string name="cyan">سایان</string>
<string name="red">سوور</string>
<string name="green">سەوز</string>
<string name="yellow">زەرد</string>
<string name="orange">پرتەقاڵی</string>
<string name="pink">پەمەیی</string>

View file

@ -29,7 +29,6 @@
<string name="enable_input_overlay_auto_hide">Zapnout automatické skrývání</string>
<string name="hide_overlay_on_controller_input">Skrýt při použití ovladače</string>
<string name="hide_overlay_on_controller_input_description">Automaticky skryje dotykové prvky, pokud použijete fyzický ovladač. Po jeho odpojení se prvky znovu objeví.</string>
<string name="input_overlay_options">Dotykové ovládání</string>
<string name="input_overlay_options_description">Nastavení ovládacích prvků na obrazovce</string>
<string name="edit_overlay_layout">Upravit rozvržení</string>
@ -368,9 +367,7 @@
<string name="qlaunch_description">Spusťte aplikace ze systémové domovské obrazovky</string>
<string name="applets">Spouštěč appletů</string>
<string name="applets_description">Spusťte systémové applety prostřednictvím nainstalovaného firmwaru</string>
<string name="applets_error_firmware">Firmware není nainstalován nebo je jeho verze neplatná</string>
<string name="applets_error_applet">Applet není dostupný</string>
<string name="applets_error_description"><![CDATA[Ujistěte se, že máte nainstalovaný soubor <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> a <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">firmware</a>, a zkuste to znovu.<br>Dále se ujistěte, že verze vašeho firmware je 19.0.1 nebo starší.]]></string>
<string name="album_applet">Album</string>
<string name="album_applet_description">Podívejte se na obrázky uložené v uživatelské složce se snímky obrazovky pomocí systémového prohlížeče fotografií</string>
<string name="mii_edit_applet">Editor Mii</string>
@ -388,7 +385,6 @@
<string name="copied_to_clipboard">Zkopírováno do schránky</string>
<string name="about_app_description">Open-source emulátor konzole Switch</string>
<string name="contributors">Přispěvatelé</string>
<string name="contributors_description">Lidé, díky kterým Eden pro Android vznikl</string>
<string name="licenses_description">Eden pro Android bylo možné zrealizovat díky těmto projektům</string>
<string name="build">Číslo sestavení</string>
<string name="user_data">Uživatelská data</string>
@ -456,6 +452,8 @@
<string name="renderer_accuracy_description">Určuje režim emulovaného GPU. Většina her běží bez problémů v rychlém, nebo vyváženém režimu, ale některé stále vyžadují přesný režim. Částicové efekty se většinou zobrazují korektně pouze v přesném režimu. </string>
<string name="dma_accuracy">Přesnost DMA</string>
<string name="dma_accuracy_description">Ovládá přesnost DMA. Bezpečná přesnost může vyřešit problémy v některých hrách, ale v některých případech může také ovlivnit výkon. Pokud si nejste jisti, použijte výchozí nastavení.</string>
<string name="frame_pacing_mode">Režim Framepacingu</string>
<string name="frame_pacing_mode_description">Řídí způsob jakým emulátor spravuje časování snímku aby snížil trhání a zlepšení plynulost a stabilitu snímkové frekvence.</string>
<string name="anisotropic_filtering">Anizotropní filtrování</string>
<string name="anisotropic_filtering_description">Zlepšuje kvalitu textur při pohledu pod úhlem</string>
<string name="vram_usage_mode">Režim využití VRAM</string>
@ -473,8 +471,8 @@
<string name="renderer_force_max_clock_description">Vynutí běh GPU na maximální možné frekvenci (teplotní limity stále platí).</string>
<string name="renderer_reactive_flushing">Reaktivní flushing</string>
<string name="renderer_reactive_flushing_description">Zlepšuje přesnost vykreslování v některých hrách na úkor výkonu.</string>
<string name="enable_buffer_history">Zapnout historii bufferu</string>
<string name="enable_buffer_history_description">Umožňuje přístup k předchozím stavům bufferu. Tato volba může u některých her zvýšit kvalitu vykreslování a zlepšit stabilitu výkonu.</string>
<string name="hacks">Hacky</string>
<string name="fast_gpu_time">Rychlé časování GPU</string>
@ -768,7 +766,6 @@
<string name="blue">Modrá</string>
<string name="cyan">Tyrkysová</string>
<string name="red">Červená</string>
<string name="green">Zelená</string>
<string name="yellow">Žlutá</string>
<string name="orange">Oranžová</string>
<string name="pink">Růžová</string>

View file

@ -29,7 +29,6 @@
<string name="enable_input_overlay_auto_hide">Automatisches Ausblenden des Overlays aktivieren</string>
<string name="hide_overlay_on_controller_input">Overlay bei Controller-Eingabe ausblenden</string>
<string name="hide_overlay_on_controller_input_description">Blende die Touch-Bedienelemente automatisch aus wenn ein physischer Controller benutzt wird. Das Overlay wird wieder eingeblendet, wenn die Verbindung zum Controller getrennt wird.</string>
<string name="input_overlay_options">Eingabe-Overlay</string>
<string name="input_overlay_options_description">Bedienelemente auf dem Bildschirm konfigurieren</string>
<string name="edit_overlay_layout">Overlay-Layout bearbeiten</string>
@ -325,7 +324,7 @@ Wirklich fortfahren?</string>
<string name="install_game_content_help_link">https://yuzu-mirror.github.io/help/quickstart/#dumping-installed-updates</string>
<string name="custom_driver_not_supported">Benutzerdefinierte Treiber werden nicht unterstützt</string>
<string name="custom_driver_not_supported_description">Das Laden von benutzerdefinierten Treibern wird für dieses Gerät momentan nicht unterstützt.\nSchau später einfach nochmal nach, ob die Unterstützung hinzugefügt wurde!</string>
<string name="manage_yuzu_data">Eden-Daten Verwalten</string>
<string name="manage_yuzu_data">Eden-Daten verwalten</string>
<string name="manage_yuzu_data_description">Importieren/Exportieren Sie Firmware, Schlüssel, Benutzerdaten und mehr!</string>
<string name="game_folders">Spiele-Ordner</string>
<string name="deep_scan">Tiefer Scan</string>
@ -365,9 +364,7 @@ Wirklich fortfahren?</string>
<string name="qlaunch_description">Anwendungen vom Systemstartbildschirm aus starten</string>
<string name="applets">Applet-Launcher</string>
<string name="applets_description">System-Applets mit Firmware starten</string>
<string name="applets_error_firmware">Firmware nicht installiert oder ungültige Version</string>
<string name="applets_error_applet">Applet nicht verfügbar</string>
<string name="applets_error_description"><![CDATA[Bitte stellen Sie sicher, dass Ihre <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a>-Datei und <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">Firmware</a> installiert sind, und versuchen Sie es erneut.<br>Stellen Sie außerdem sicher, dass Ihre Firmware Version 19.0.1 oder älter ist.]]></string>
<string name="album_applet">Album</string>
<string name="album_applet_description">Bilder im Screenshot-Ordner anzeigen</string>
<string name="mii_edit_applet">Mii-Editor</string>
@ -385,7 +382,6 @@ Wirklich fortfahren?</string>
<string name="copied_to_clipboard">In die Zwischenablage kopiert</string>
<string name="about_app_description">Ein quelloffener Switch-Emulator</string>
<string name="contributors">Beitragende</string>
<string name="contributors_description">Gemacht mit \u2764 vom Eden Team</string>
<string name="licenses_description">Projekte, die Eden für Android möglich machen </string>
<string name="build">Build</string>
<string name="user_data">Nutzerdaten</string>
@ -402,6 +398,8 @@ Wirklich fortfahren?</string>
<string name="frame_limit_enable_description">Limitiert die Geschwindigkeit auf einen von dir festgelegten Prozentsatz.</string>
<string name="frame_limit_slider">Geschwindkeitsbegrenzung in Prozent</string>
<string name="frame_limit_slider_description">Gibt die prozentuale Geschwindigkeit der Emulation an. 100% sind normal. Werte darüber oder drunter werden die Geschwindigkeit entsprechend verändern.</string>
<string name="turbo_speed_limit">Turbo Geschwindigkeit</string>
<string name="slow_speed_limit">Langsame Geschwindigkeit</string>
<string name="cpu_backend">CPU-Backend</string>
<string name="cpu_accuracy">CPU-Genauigkeit</string>
<string name="value_with_units">%1$s%2$s</string>
@ -471,8 +469,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
<string name="renderer_force_max_clock_description">Erzwingt maximale GPU-Taktfrequenz. (thermische Einschränkungen werden weiterhin angewendet).</string>
<string name="renderer_reactive_flushing">Reaktives Flushing</string>
<string name="renderer_reactive_flushing_description">Verbessert die Genauigkeit in einigen Spielen.</string>
<string name="hacks">Hacks</string>
<string name="fast_gpu_time">Schnelle GPU-Zeit</string>
@ -1027,12 +1023,10 @@ Wirklich fortfahren?</string>
<string name="app_language_system">System folgen</string>
<!-- Static Themes -->
<string name="static_theme_color">Designfarbe</string>
<string name="eden_theme">Eden (Standard)</string>
<string name="violet">Violett </string>
<string name="blue">Blau</string>
<string name="cyan">Cyan</string>
<string name="red">Rot</string>
<string name="green">Grün</string>
<string name="yellow">Gelb</string>
<string name="orange">Orange</string>
<string name="pink">Rosa</string>

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