Compare commits

...

173 Commits

Author SHA1 Message Date
lizzie 580f0bce83 change ps4 icon to be more like shadPS4 2026-08-31 18:17:32 +00:00
lizzie 9031104538 use vulkan_radeon 2026-08-31 18:17:12 +00:00
lizzie bc5cacdd16 we love vulkan here 2026-08-31 18:17:12 +00:00
lizzie ea5d76013a evil staging buffers for PS4 2026-08-31 18:17:12 +00:00
lizzie dbfece8ff4 vk open icd 2026-08-31 18:17:12 +00:00
lizzie 809cb841dc fix emu cmd 2026-08-31 18:17:12 +00:00
lizzie 52ced1b8b3 hook back the patches 2026-08-31 18:17:12 +00:00
lizzie 696c05119e fix fullscreen stuff on debian? 2026-08-31 18:17:12 +00:00
lizzie 7a9efed9c5 FIX FOR DETECT PLATFORM 2026-08-31 18:17:12 +00:00
lizzie a4cf8021bd remove unused run_on_host 2026-08-31 18:17:12 +00:00
lizzie 139f30e8ab softpipe enabled mesa support 2026-08-31 18:17:12 +00:00
lizzie 307d9a74e2 all audio issues magically fixed 2026-08-31 18:17:12 +00:00
lizzie 3fcad7eec8 fix mappings 2026-08-31 18:17:12 +00:00
lizzie 866d4a5e2f fix input finally 2026-08-31 18:17:12 +00:00
lizzie fa998bd90b various SDL driver fixes for joystick, initialize video 2026-08-31 18:17:12 +00:00
lizzie de7fbb4cb5 better PS4 patches for SDL3 2026-08-31 18:17:12 +00:00
lizzie f079011ae3 ps4 joystick 2026-08-31 18:17:12 +00:00
lizzie f863da7465 guard bundled openssl 2026-08-31 18:17:12 +00:00
lizzie 81bd80fc48 fixup for new openssl 2026-08-31 18:17:12 +00:00
lizzie 99c4a1355b properly build with new openssl cpm mechanism 2026-08-31 18:17:11 +00:00
lizzie 708c2a80b2 license fix? 2026-08-31 18:17:11 +00:00
lizzie e049b65dfe novideo 2026-08-31 18:17:11 +00:00
lizzie 5ca896f8d3 random fixes 2026-08-31 18:17:11 +00:00
lizzie d3c3a8f7c0 sdl3 compiles now 2026-08-31 18:17:11 +00:00
lizzie 7a6ca9274f SDL3 port 2026-08-31 18:17:11 +00:00
lizzie 9a6d2e47f3 adjust samples to PS4<->switch 2026-08-31 18:17:11 +00:00
lizzie 38e27023c7 use 16k pages again 2026-08-31 18:17:11 +00:00
lizzie f5873292d7 restore old audio size 2026-08-31 18:17:11 +00:00
lizzie 7d0181e3c8 wait after audio process 2026-08-31 18:17:11 +00:00
lizzie 5420910b9b hostmem doesn't exist? 2026-08-31 18:17:11 +00:00
lizzie 881ac5a8cf fix pagesize 2026-08-31 18:17:11 +00:00
lizzie 2444cb0617 fix timestamps due to wrong stat 2026-08-31 18:17:11 +00:00
lizzie 0caea31739 fix stat being wrong 2026-08-31 18:17:11 +00:00
lizzie a02c4ee8eb fix std exchange, fix host mem unused funcs 2026-08-31 18:17:11 +00:00
lizzie 5cf3da0410 checkout useless changs 2026-08-31 18:17:11 +00:00
lizzie f2c57111fb make fiber bigger, build.sh 2026-08-31 18:17:11 +00:00
lizzie 043ad66b59 disable openssl on httplib hdr 2026-08-31 18:17:11 +00:00
lizzie 88ea96a4ae update license 2026-08-31 18:17:11 +00:00
lizzie 4eb17116a1 remove outdated make-toolchain 2026-08-31 18:17:11 +00:00
lizzie bfd02a3143 put swap proper 2026-08-31 18:17:11 +00:00
lizzie 440628347e file loggin is safe now, settings too 2026-08-31 18:17:11 +00:00
lizzie 01a9cc6762 properly define orbis page size 2026-08-31 18:17:11 +00:00
lizzie 89dafa64ca exclude tests that dont work 2026-08-31 18:17:11 +00:00
lizzie 2946eb5263 proper virtual base, remove uneeded sysconf things 2026-08-31 18:17:11 +00:00
lizzie 7c21a30291 skip exception handler register on PS4 and use xbyak::inner:getpagesize 2026-08-31 18:17:11 +00:00
lizzie 9b5298826d remove thread remnants 2026-08-31 18:17:11 +00:00
lizzie 1a1b1d8d47 ryujinx was never ported to PS4 2026-08-31 18:17:11 +00:00
lizzie 61d505e518 fucking rng 2026-08-31 18:17:11 +00:00
lizzie 76d8d271ce random stray devices ugh 2026-08-31 18:17:11 +00:00
lizzie 5ae07226d9 httplib partial thing 2026-08-31 18:17:11 +00:00
lizzie 4596b0e69e fix shit 2026-08-31 18:17:11 +00:00
lizzie 293d8dde19 fix nproc 2026-08-31 18:17:11 +00:00
lizzie 4339dab1e4 disable openssl and register user 2026-08-31 18:17:11 +00:00
lizzie 335df75e48 needs libscienternal 2026-08-31 18:17:11 +00:00
lizzie 0d1e725bbd try fix musl 2 2026-08-31 18:17:11 +00:00
lizzie 4d805796d5 native ps4 audio sink 2026-08-31 18:17:11 +00:00
lizzie 334311c416 init audio 2026-08-31 18:17:11 +00:00
lizzie ec33611182 fix virtual buffers 2026-08-31 18:17:11 +00:00
lizzie 6c1ab0bb54 fix openssl 2026-08-31 18:17:11 +00:00
lizzie 4c5fd8cdbf disable stdio buffering 2026-08-31 18:17:11 +00:00
lizzie 350e57eb27 FX 2026-08-31 18:17:11 +00:00
lizzie 5090a2ab0e let it rip 2026-08-31 18:17:11 +00:00
lizzie d634ad21f0 leave pending param package stuff 2026-08-31 18:17:11 +00:00
lizzie 4229f71ad5 restore protection 2026-08-31 18:17:11 +00:00
lizzie c6fe6d574c immediately terminate in OO, use 2MB swap handler 2026-08-31 18:17:11 +00:00
lizzie 609cf8d9ca use btver2 2026-08-31 18:17:11 +00:00
lizzie 133d8095c2 reduce fiber sizes 2026-08-31 18:17:11 +00:00
lizzie 0f829ae4b4 fix yuzu cpp 2026-08-31 18:17:11 +00:00
lizzie 051f48245a use dmem for swap buffers, restore full jit sizes 2026-08-31 18:17:11 +00:00
lizzie 6c7aefa3e1 force ankerl + fixup for OO with prelude commits 2026-08-31 18:17:11 +00:00
lizzie 0bc405d548 fix 2026-08-31 18:17:11 +00:00
lizzie 9367b46988 fixup shit 2026-08-31 18:17:11 +00:00
lizzie 920824912c SDL2 PS4 patch 2026-08-31 18:17:11 +00:00
lizzie 86f90d9455 use newer sdl2, make bigger stack 2026-08-31 18:17:10 +00:00
lizzie aa4aef2f2a mark codeblocks as noexcept 2026-08-31 18:17:10 +00:00
lizzie effb12e8a7 fix2 2026-08-31 18:17:10 +00:00
lizzie 0713c725e7 make a bit more mergeable 2026-08-31 18:17:10 +00:00
lizzie 44b7f1fdb0 Use updated SDL2 2026-08-31 18:17:10 +00:00
lizzie b5bc63a9c9 revert input system to main 2026-08-31 18:17:10 +00:00
lizzie 5abd3b4d8d stub add proper iostream init 2026-08-31 18:17:10 +00:00
lizzie 56dd8a932d ps4 icon 2026-08-31 18:17:10 +00:00
lizzie 43fb6eeab4 update loicense 2026-08-31 18:17:10 +00:00
lizzie 09cf2b9c8d restore stupid lock, make ps4sup library 2026-08-31 18:17:10 +00:00
lizzie 6d405315a4 bs fix 2026-08-31 18:17:10 +00:00
lizzie e6ab98811e fix eboot 2026-08-31 18:17:10 +00:00
lizzie d5aeeefcc8 temp fix for dpad 2026-08-31 18:17:10 +00:00
lizzie 72ae77943b add emutls.c 2026-08-31 18:17:10 +00:00
lizzie a882007534 reduce arm codeisze, force 16x4 pages again 2026-08-31 18:17:10 +00:00
lizzie 2f31e47c8c extra buffer precautions to not exhaust DMem, format better + perf history nerf 2026-08-31 18:17:10 +00:00
lizzie ba3df73048 more inline pt2 2026-08-31 18:17:10 +00:00
lizzie 3f42aeb2e6 fix atexit impl 2026-08-31 18:17:10 +00:00
lizzie e328b6cd30 fibers that don't immediately crash?!!?!?!!? 2026-08-31 18:17:10 +00:00
lizzie 61bcbe26cf force running services on host 2026-08-31 18:17:10 +00:00
lizzie 3301a9c0ce fix alloc failures 2026-08-31 18:17:10 +00:00
lizzie 3f5e386c56 fix for crashes on TLS due to openorbis being W E I R D 2026-08-31 18:17:10 +00:00
lizzie 5236396069 opengl bullshit 2026-08-31 18:17:10 +00:00
lizzie 52b6631e2a proper memswap mechanism 2026-08-31 18:17:10 +00:00
lizzie 23d1185c8b more stupid stuff 2026-08-31 18:17:10 +00:00
lizzie 8a5c52c82d fixes 4 stuff 2026-08-31 18:17:10 +00:00
lizzie 6e4ccef9b4 swap handling 2026-08-31 18:17:10 +00:00
lizzie 2945066ca4 license 2026-08-31 18:17:10 +00:00
lizzie 59afffbcd7 add sce_module so it loads on real hw 2026-08-31 18:17:10 +00:00
lizzie 1d29303163 fixes for mbedtls 2026-08-31 18:17:10 +00:00
lizzie e852c7a7dc adapt to new master 2026-08-31 18:17:10 +00:00
lizzie d1fc50b9ec evil haxx 2026-08-31 18:17:10 +00:00
lizzie bf85d208b5 extra ps4 defs 2026-08-31 18:17:10 +00:00
lizzie 3233b00a04 force NO fastmem 2026-08-31 18:17:10 +00:00
lizzie fa6845bf33 more memory shit 2026-08-31 18:17:10 +00:00
lizzie c2cfe8a15c MAP_SYSTEM 2026-08-31 18:17:09 +00:00
lizzie 9e07b57677 (likely) fixes for virtual dmem? 2026-08-31 18:17:09 +00:00
lizzie 423632e7fa disable fastmem 2026-08-31 18:17:09 +00:00
lizzie 303057c7f3 try to fix the paths 2026-08-31 18:17:09 +00:00
lizzie 449a3fb9f0 sysconf stub cuz crash(?) + some stderrp stuff 2026-08-31 18:17:09 +00:00
lizzie e9f1ab417f the orb 2026-08-31 18:17:09 +00:00
lizzie 216c03e903 fself + pkg stuffs 2026-08-31 18:17:09 +00:00
lizzie 6189554bf6 make .pkg and .self 2026-08-31 18:17:09 +00:00
lizzie 639188bd57 exclude more stuff from vulkan 2026-08-31 18:17:09 +00:00
lizzie 2c6cda0911 exclude from vulkan surface selection 2026-08-31 18:17:09 +00:00
lizzie 13eb46c2fe buildable toolchain script + fixes for ffmpeg 2026-08-31 18:17:09 +00:00
lizzie ac5a90cf56 merge 2026-08-31 18:17:09 +00:00
lizzie a85403064e merge 2026-08-31 18:17:09 +00:00
lizzie b0897f35fd merge 2026-08-31 18:17:09 +00:00
lizzie e30ac7213e fix 2026-08-31 18:17:09 +00:00
lizzie 421f9608cd toolchain-fix 2026-08-31 18:17:09 +00:00
xbzk b7f0f98519 [android] expose log filter setting (#4327)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
Takes log filter to android and fixes qt "loads after setting, but ignore in next runs" issue

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4327
Reviewed-by: Lizzie and Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-31 04:22:15 +02:00
crueter 7fda6dde73 [common] Switch to boost::unordered_flat containers (#4326)
Replaces all instances of ankerl's unordered map/set with boost's
`unordered_flat_*` classes. This uses std::hash since boost::hash is
actually a lot slower.

Also adds an abstraction layer in `Common` so future changes are quicker
and easier.

Other implementation details:
- ankerl provided hash specializations for tuple and pair, so those were
  ported here
- std::erase_if doesn't work on boost, so just used the ADL'd erase_if

This should be about equal or superior performance as unordered_dense for everything except iteration.

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

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4326
Reviewed-by: Lizzie and Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-31 02:58:09 +02:00
lizzie 106a61c943 [core/file_sys] fix IPS not applying due to wrong NSObuild-id (#4323)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

NSO build id was being read wrongly... oops
also fixed some minor issues as well

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4323
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-30 20:08:40 +02:00
lizzie e5b656e372 [common/logging] Fix long logs, remove clutter on Android logcat (#4310)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

logs normally are like this:
```
08-27 02:58:48.188 12511  4743 W YuzuNative: [18534.062505] Shader <Warning> shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp:141:Read: (STUBBED) SR_WSCALEFACTOR_XY
08-27 02:58:48.188 12511  4743 W YuzuNative: [18534.062513] Shader <Warning> shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp:144:Read: (STUBBED) SR_WSCALEFACTOR_Z
08-27 02:58:48.188 12511  4743 W YuzuNative: [18534.062520] Shader <Warning> shader_recompiler/frontend/maxwell/translate/impl/vote.cpp:50:VOTE_vtg: (STUBBED) called
08-27 02:58:48.188 12511  4743 W YuzuNative: [18534.062523] Shader <Warning> shader_recompiler/frontend/ir/ir_emitter.cpp:267:GetFlowTest: (STUBBED) FCSM_TR
```
bunch of redundant info imo

instead they should just be
```
08-27 02:58:48.188 12511  4743 W YuzuNative: Shader shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp:141:Read: (STUBBED) SR_WSCALEFACTOR_XY
08-27 02:58:48.188 12511  4743 W YuzuNative: Shader shader_recompiler/frontend/maxwell/translate/impl/move_special_register.cpp:144:Read: (STUBBED) SR_WSCALEFACTOR_Z
08-27 02:58:48.188 12511  4743 W YuzuNative: Shader shader_recompiler/frontend/maxwell/translate/impl/vote.cpp:50:VOTE_vtg: (STUBBED) called
08-27 02:58:48.188 12511  4743 W YuzuNative: Shader shader_recompiler/frontend/ir/ir_emitter.cpp:267:GetFlowTest: (STUBBED) FCSM_TR
```

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4310
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-30 08:24:00 +02:00
lizzie 297e797a32 [hle/kernel] remove flusher thread from OutputDebugString (#4291)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Unneeded abstraction?
either way it seems this thread is not required
anyone thinking otherwise feel free to lmk
directly contradicts with #4290
and #3744

Remember that messages will be displayed out of order
this can make actual debugging much harder I'm afraid

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4291
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-08-30 08:18:50 +02:00
xbzk 48a95da874 [debug] debug knobs adjustments (#4317)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
minor changes to debug knobs:

-changed its category to System so it becomes per-game-able (believe me, it's useful)
-fixed kotlin field type to UShort
-changed get to Get for proper standard
-added spacings and more info to docs

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4317
Reviewed-by: Lizzie and Samuel <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-08-30 08:17:54 +02:00
rayanmargham 2fd1dc0ff9 [qt] fix closing software dialog color (#4305)
Signed-off-by: rayanmargham <rayanmargham4@gmail.com>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
This change fixes the closing software dialogue box having really grayish to white text on a white background making it impossible to read. This fixes default-dark giving it this look with the attached screenshot![image](/attachments/ad7dd13c-3808-4a0e-b29b-1a001a1106e0)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4305
Reviewed-by: Lizzie and Samuel <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-08-30 08:16:32 +02:00
Lizzie and Samuel 45b6ecff05 [vulkan, vk_pipeline_cache] PSO Optimizations (#4294)
PR/Commit Owner: CamilleLaVey

This PR prevents the recompilation of shaders when a new session has been started, based on data found on the recompiler, each new session does still recompile already cached shader cache, reducing the reaction and speed of games by at certain level, this prevent the warm-up with post sessions, only needed the initial warm-up and works globally for all games.

Co-authored-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4294
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-08-30 08:15:29 +02:00
lizzie 672bcbae01 [file_sys] robust-er IPSwitch compiler (#3911)
this PR reworks IPS parser to be less stupid
what do i mean by this? well generally give it a bit of
love so it doesn't do a lot of unsound allocations
also simplify the logic greatly (and use memcmp() string idiom
instead of trusting the compiler so blindly...)

no this doesn't mean to uber optimize IPS to handle 999 gb/s
it's more so it doesn't outright crash with edge cases
as the previous codebase was quite spaghetty

also the major overhead is obviously the vector shenanigans
and the I/O -- but thats out of scope

Test that IPSwitch mods still properly work WITH ANY GAME
IF THERE IS ANY REGRESSION IN SOME GAME/MOD THEN
TELL ME

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3911
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-30 08:10:51 +02:00
Maufeat 28ab4a1a01 [kernel, service] Return ResultSessionClosed when a session is closed (#4318)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

I tried to run a homebrew game which tried to reply to a closed service. nnSdk expected ResultSessionClosed, we replied with ResultSuccess which mostly works but some have stricter handling and would terminate with abort.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4318
Reviewed-by: Lizzie and Samuel <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-08-30 08:00:18 +02:00
lizzie ccf3de02cf [dynarmic] optimise BlockOfCode to use less memory (#4303)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

removes unique_ptr indireciton with argCallback (lmao)
reorders jitState to be more cache friendly and yadda yadda
removes redundant BlockOfCode& ptr on constantPool
reorder blockOfCode to be btter
update dynarmic because it removes 3kb worth of useless data :)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4303
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-08-30 07:43:21 +02:00
PavelBARABANOV 1f03dee126 [fs] Add RenameDirectory support for same-parent directory renaming (#4312)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
Fixes save corruption in Warhammer 40k: Mechanicus and other games
that rename directories within the same parent folder.

- Added RenameDirectory handler in IFileSystem (command 6)
- Implemented same-parent directory renaming using RenameDir

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4312
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-30 01:46:02 +02:00
xbzk 3df41c1e7a [android, ui] carousel: display-wise scaling, snapping fix, bottom insets rework (#4307)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
Another batch of improvements and fixes for Carousel.

- Added display wise scaling factor for compatibility with 16:9 and 4:3 devices;
- Fixed snap to center feature being lost sometimes;
- Reworked entire bottom inset mechanism (made it event driven, and added use of getInsetsIgnoringVisibility) to avoid weird resizing on Recents (alt+tab) transitions.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4307
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-29 22:04:18 +02:00
lizzie f4a8f9421a [common/net] fix linking errors due to C++11 ABI typedef mishandle (#4260)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

basically bunch of linking errors due to gcc not liking
to compile HFA/whatever typedef stuffs
this is on non-x86_64 arch, ppc64

compiler where this occurs

```
gcc (Debian 14.2.0-19) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4260
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-08-29 20:59:57 +02:00
xbzk c0a85d0e53 [service, nvhost] added machinery to allow microsleep between nvdec read requests to avoid guest panic in some games (#4316)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
This one deserves a long story, but imma try to resume:

During investigating Absolum 1.2 black screen of death upon loading intro video, i've discovered guest was aborting for failing to allocate room for the video.

By logging everything prior to crash and decoding guest side instructions managed to confirm its media allocator was reading data faster than it was updating free available bucket list.

Since the IStorage::Read was happening 247 times before the crash, i've decided to add a very small sleep there, and boom, not only Absolum but some other titles got the same issue fixed.

But i was unsatisfied with the sleep and kept tracking guest instructions upstream in order to find a sync point for the read worker and the memory allocation update. But unfortunately the media allocator helpers live in guest, accessing memory directly via MMU, so any sync signaling would need to come from some dynarmic hack.

It's been 6 days now, so i've decided to polish the sleep: Moved it upstream to where i could have access for proper predicate, and added machinery to service and nvhost to support that. Now the sleep is restricted only for nvdec istorage reads. Any other reads will flow normally.

TL;DR: currently our code is so blazing async that guest is capable to request reads before its very self refresh it have freed room to do so. The sleep accepted as broadly stable was 600 us (MICROseconds), and it affects ONLY nvdec chunk reading.
Reports confirm that now videos are smoother now.

Code was polished at my knowledge limits.
Mostly machinery to track when a request comes from a process with nvdec active, and is istorage read.
I can provide more details if it comes to be needed.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4316
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-29 14:22:09 +02:00
Maufeat 54cd5fb8eb [core, hle, video_core, memory] Improve multi-process, display layers, dynamic shader cache and rework overlay (#4238)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

- Dynamic shader cache reloading capability for qlaunch
- Multi-process improvements (thanks to @frank1734), instead of just using the main application we now respect caller process (also did it for HID devices while I was at it)
- Layer stack masks & shared buffer screenshot for video core, added different masks (screenshot, recording, etc.) this was discovered as an issue due to how in qlaunch the transition was not right between applications. May not be perfect but also fixes screenshots while using qlaunch
- Reworked overlay display management (input and visibility) - instead of random numbers as I've previously did, I decided to add an AppletZIndex enum for better readability. Also split capability of input by touch and gamepad.
- etc.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4238
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-29 01:04:02 +02:00
lizzie 119291dc77 [qt_common/discord] fix boxart not being used (#4275)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

issue was first reported here
https://github.com/eden-emulator/Issue-Reports/issues/607

tl;dr wrong boolean, now boxarts should work

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4275
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-28 03:46:36 +02:00
lizzie f7dbff2157 [core/hle/services/am] Fix MK8D crash (#4313)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

This fixes a random mk8d crash when connecting via LDN

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4313
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-28 03:44:45 +02:00
lizzie b859d7fdf4 [dynarmic/backend/exception_handler] normalize EH for arches, use LOG_ERROR instead of fmt::print (#4283)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

this should simplify a bit of code logic
akin to NetBSD's UC_CONTEXT_PC...
additionally use LOG_ERROR so the
"unhandled ..."
is logged unto a file
before sigsegv'ing

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4283
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-28 02:30:18 +02:00
lizzie f635827fa6 [common/stb] remove unused I/O funcs from non-LTO builds, use common/stb.h on ns service (#4282)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

- remove I/O functions that are unused from LTO builds
- use common/stb.h on ns
simple change really, not much to explain here

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4282
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-28 02:29:52 +02:00
lizzie 243453c172 [dynarmic, loong64] fix build error due to new term handlers (#4286)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

trivial fix

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4286
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-28 02:24:39 +02:00
lizzie 39158b67a7 [audio/sdl3] fix mismatches OS mixer settings for sdl3/cubeb audio backends (#4298)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

basically makes it so SDL3 and cubeb audio backends now share the same
identifier string so OS mixers (ok a bit of a misnormer, its like pulseaudio
pipewire and such, but yknow what i mean) -- dont conflate due to the
fact that "Eden" != "yuzu Latency Getter".
fix taken from pcsx2 https://github.com/PCSX2/pcsx2/pull/12312

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4298
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-28 01:50:55 +02:00
CamilleLaVey 50cb8fd1c9 [vulkan] Implementation for VK_EXT_shader_quad_control (#4168)
An experimental approach to introduce an smarter way to use and access QUAD's capabilities on shaders, suggested by @gidoly some months ago, finally came into something usable; current implementation checks GLASM, GLSL and Vulkan on their own way, stablishes proper emitters and receivers for Quads inside our recompiler, which are the introductions for future changes; checks for support and actual feature bit, OpCodes and mask were added within this PR. Meanwhile the expected behavior was to reduce graphical issues (on games with Quad shaders reliant), we encountered a very slight performance increase depending on what game and shader are actually compiled.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4168
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-28 01:21:22 +02:00
lizzie faaf1bac64 [common/logging] Fix logging overflow on logging settings (#4308)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Apparently on FBSD we have plenty of stack space -- but not on Linux.
Just fixes a stack overflow thing.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4308
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-26 20:38:52 +02:00
CamilleLaVey 0295dc5fff [vulkan] Removal of QCOM sampler limiters + CustomBorderColor and ColorBorderSwizzle adjustments (#4301)
This PR removes the artificial limit added for QCOM drivers based on a sampler budget limit (based on #3280 work), removes the ban on CustomBorderColor/BorderColorSwizzle for also QCOM driver, reduce the amount of combination required to created a sampler with custom border color/ color border swizzle; adds cases on R16 formats not able to swizzle on BGR565 formats; degrades samplers and color combinations when there's no color border swizzle available; fixes the srgb (LUT) values from legacy and now all the color variations are cached in the same key, instead of having 7 different handlers for them. In resume, rather than performance (due to the reduced amount of process on duplicated/ synced code on pipeline/texture cache), it's a graphica accuracy work that will improve image quality at the cost of almost 0 performance hit, rather than certain hitch if the color combination wasn't cached before. This applies to all platform.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4301
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-25 20:03:18 +02:00
CamilleLaVey 60a474b8df [vulkan, qcom] Fix shader float controls on QCOM driver (#4297)
Finishes my torture to find the culprit behind the broken behavior with float controls, even if device does support flush denorm on fp32 it doesn't really support it and provokes bad rounding modes by not flushing correctly denorms; this also returns the other working rounding modes on QCOM drivers.

_Special Thanks_

1.- Smoly The Big (@Gidoly)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4297
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-24 17:57:12 +02:00
lizzie d9336ce6ce [common, settings] Fixes misaligned Aniso levels (#4295)
PR/Commit Owner: CamilleLaVey

Just quick fixes to ANISO bugged level selector, removes x32 and x64 from choices, also fixes the none value to actully use default.

Co-authored-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4295
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-24 00:06:11 +02:00
PavelBARABANOV 4eb8dd1458 partial revert a41a98028a (#4292)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
This commit fix launch Assassin's creed 3

changes nvdrv:a - break launch with fw 20+
changes ldr:ro - break skip loading menu with all fw

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4292
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-08-24 00:01:21 +02:00
PavelBARABANOV 4a3cc9a3c2 [android] Fix Nvdec None (#4288)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
Nvdec None is working now; I removed the unnecessary comments — the variable names make everything clear enough.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4288
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-23 23:58:50 +02:00
Samuel 86ba79b1ba [vulkan, sgsr] Adjustments to SGSR implementation (#4293)
PR/ Commit Owner: CamiileLaVey

This change has specified fixes on the SGSR initial implementation, it brought a wider sharpening level limits and better image quality.

Co-authored-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4293
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-08-23 23:36:24 +02:00
lizzie b610b03d29 [common/logging] eliminate uneeded std::string{} allocations per each logging (#4273)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

the idea is simple, `std::string{}` adds pressure to the memory allocator
so whats the best next thing we can do? well of course use our stack
its plenty, but we shouldn't be greedy either, BUFSIZ should be a fair amount of
space for any would-be messages anyways

the main idea behind this PR is to remove std::string{} allocations
done with libfmt, that way we have 0-allocs per logging entry
this should 100% remove pressure uneeded from the memory allocator
we should only allocate things that are important, we can use our
trusty fast stack for any string manip we need to do
not await/global lock or do evil things with the memory allocator

obviously stack is thread local already sooo... this is even better
than having to deal with malloc()/free() in any capacity whatsoever

and no clang can't heap ellide this (how would you even?)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4273
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-23 22:37:17 +02:00
lizzie 421e0b834c Revert "[dynarmic] Remove Ignore Global Monitor from CPU Accuracy Auto (#3846)" (#4276)
This reverts commit 3a823de605.

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

kills performance and doesn't fix graphical glitches
(according to gido)
"It improved nothing but kills performance on default setting"

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4276
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-23 22:10:22 +02:00
John 55acf5d260 [Vulkan] Apply MK8D Buffer Fix to Linux (#4289)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Credit: MaranBR
- Adds the Rainbow Graphics Bug Fix to Linux as the game needs MAX_STREAM_BUFFER_SIZE = 256_MiB

![image](/attachments/722d4014-9449-47a0-be47-730b99e0b464)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4289
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-23 17:43:35 +02:00
crueter 3e07b466eb [vulkan] Adjustments on MSAA and BlitHelpers (#4287)
PR/Commit Owner: CamilleLaVey

This PR contains changes complementary to the MSAA refactor from some weeks ago, adds proper shader convert to depth, stencil for msaa and non msaa convertions; removes redundant helpers and unify paths on the resolve functions, just to make the readability and maintainability better; includes fixes for the blit operations on Nvidia, Intel/Windows (previously banned) and ensures Linux retain the fix without extra burden; fixes the QCOM driver bug on resolution upscaling on any games above x1 (includes turnip on A8xx series) and fixes crashes/ resolution upscaled bugs on certain games that used to have wrong viewporting effect on screen or directly device loss on Vulkan. Adds fixes for regressions caused by previous MSAA refactor on games as Fire Emblem: Engage.

Special Thanks

1.- Big Smolio (@Gidoly)

Co-authored-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4287
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-23 17:31:09 +02:00
xbzk 5b86242313 [android, ui] remove the wash (white tint) of focused game cards (#4285)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

This removes the ugly wash from focused game cards, without removing the interaction's cool ripple effects.
I've stumbled upon a reddit complaining about it, and in fact i always hated it but hadn't realized yet.

It happens to any layout.
Joypad users notice more since navigation consists on focusing cards.
Carousel users notice even more coz cards are bigger and always focused.

Border is more than enough to highlight a card, and we want to cherish colors just like creator artists wanted it to be, right?

No chance of bugs. No chance of disagreement (¬¬).
Approve it already so Youtube videos with carousel thumbs get prettier earlier ^^.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4285
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-23 00:29:59 +02:00
xbzk d24e79c991 [android, ui] refresh game icons when updates are discovered (#4284)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

This small impl aims to fix an android old visual bug where it could cache/read a base game icon before its update was mounted, so games with update-specific icons kept showing the base icon like almost always (in a way that some players may never have seen the updated icons).

Fix: when scan detects an update matching an already found base game, reload that game’s metadata and refresh only its visible icon if the icon actually changed.

I believe it's polished to the max. No find/scans. When base is found it is tracked via hashmap, and when update is found and conditions met the refresh is triggered.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4284
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-23 00:25:55 +02:00
xbzk df05d3de23 [android, ui] lsfg: make "target frame rate" show/hide "frame multiplier" (#4274)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4274
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-22 07:52:16 +02:00
PavelBARABANOV c249ff462b [android] Restore the nvdec toggle (#4280)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4280
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-22 02:40:32 +02:00
crueter 056d11027c [internal_network] Fix WiFi scanner compilation on GCC 15.3.0 (#4279)
No idea why this didn't show up earlier.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4279
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-21 23:29:24 +02:00
xbzk 61ffb309a3 [android,ui] carousel view improvements (#4277)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

One major change to make on carousel, one yoozoo era bug fixed, and some other minor adjustments.

Commits squashed:

[android, ui] Fixed carousel card size scaling over bottom insets
[android, ui] Removed old shapingFunctions
[android, ui] Implemented carousel true elliptic movement model
[android, ui] Fixed overheighted flicker on cards after refresh
[android, ui] Fixed full opaque secondary cards after refresh
[android, ui] Fixed flickers due to doubled list redraw after refreshes

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4277
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-21 23:29:04 +02:00
crueter 65a3cfd2be [common, yuzu] Fix compilation on newer httplib versions (#4278)
Required for newer httplib versions to compile.

has_header is at least present on 0.38.0 on my local machine. Let's hope
it works on Trixie

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

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4278
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-21 23:17:46 +02:00
Maufeat 5c54abf353 [nim] unstub IShopServiceAsync (#4272)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
 unstub IShopServiceAsync (but still stub Request, with empty JSON response)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4272
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-19 19:56:06 +02:00
lizzie 0465292a81 [docs] overview doc for newcomers (#4266)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

documents basic stuff about the emu and "hey eden is HLE" (like most yuzu forks!)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4266
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-08-18 19:00:26 +02:00
lizzie a41a98028a [hle/service] stub missing homebrew services, fix NPad/caps crashes (#4264)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

this PR adds various missing services (acc:e, acc:e:u1)
to expand homebrew compatibility
notably this also fixes NPad related crashes due to nullref

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4264
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-18 18:11:33 +02:00
xbzk 265c27f391 [cmake] drop invalid c98 warning suppression (#4269)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
The -Wno-c98-compat breaks clang build on windows.
I believe it's a typo, since i couldn't find about it elsewhere.
The -Wno-c99-compat is in place.
As a bonus removed a doubled -Wno-c99-extensions right after.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4269
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-18 00:56:26 +02:00
Eden CI fb2202d69c [dist, android] Update translations from Transifex for Aug 17 (#4267)
Automatic translation update for Aug 17

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4267
2026-08-17 23:02:25 +02:00
CamilleLaVey 2000fdfb7b [vulkan, android] Initial implementation of LSFG-VK (#4263)
Pretty much self explanatory, own implementation based on LSFG-VK available with some additional reverse engineer work for the actual use of shaders inside Lossless.dll, we don't store/ bundle any tools that bypass security and self ownership: to use this feature is required to own your own copy of Lossless Scaling and I encourage to support developers behind this work.

Special thanks:

1.- THS - Original developer behind Lossless Scaling
2.- PancakeTAS - Developer behind LSFG-VK
3.- The Big Smolio The Sleeper (@gidoly)

Co-authored-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4263
2026-08-17 00:30:19 +02:00
xbzk dc95cd09ee [android] Add Samsung DeX fullscreen probes (#4245)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
Shotgun attempt to fix fullscreen issue on samsung dex.

External test mapping:
bit 1, value 2: disable runtime fullscreen attempts
bit 2, value 4: force runtime user-landscape
bit 3, value 8: add legacy sticky system UI flags
bit 4, value 16: add delayed retries
bit 5, value 32: runtime orientation unspecified
bit 6, value 64: add FLAG_LAYOUT_NO_LIMITS
Good smoke masks: 0, 8, 16, 24, 4, 12, 20, 28, 32, 40, 64, 72, 88, 2.

EDIT: 8 (bit 3) did the trick. All cleaned up.
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4245
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-15 14:21:52 +02:00
lizzie e7a931d06b [eden-cli] rework loop to use new SDL3 event dispatch system (#4108)
modernized into the new SDL3 API for event dispatching.

also stopped using the periodic comparison and just added a SDL timer like it wants us to do
is it better than before? well it's certainly more portable now. docs say this improves battery usage on busywaits for event polling.

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4108
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-08-12 18:10:24 +02:00
531 changed files with 29789 additions and 17910 deletions
+66
View File
@@ -0,0 +1,66 @@
#!/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
# cmake
[ -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 -femulated-tls")
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 -femulated-tls")
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[@]}" $@)
[ -f "build/Makefile" ] || 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_OPENGL=ON \
-DENABLE_WEB_SERVICE=OFF \
-DUSE_DISCORD_PRESENCE=OFF \
-DCPMUTIL_FORCE_BUNDLED=ON \
-DYUZU_USE_EXTERNAL_FFMPEG=ON \
-DYUZU_USE_CPM=ON \
-DDYNARMIC_ENABLE_NO_EXECUTE_SUPPORT=OFF \
-DDYNARMIC_TESTS=ON \
-DYUZU_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
+3
View File
@@ -63,3 +63,6 @@ artifacts
/install*
vulkansdk*.exe
*.tar.zst
# PS4 toolchain stuff
ps4-toolchain.cmake
+17
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>
+13
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
+15
View File
@@ -0,0 +1,15 @@
diff --git a/libavutil/cpu.c b/libavutil/cpu.c
index 03e2720..874258f 100644
--- a/libavutil/cpu.c
+++ b/libavutil/cpu.c
@@ -43,8 +43,10 @@
#include <sys/param.h>
#endif
#include <sys/types.h>
+#ifndef __OPENORBIS__
#include <sys/sysctl.h>
#endif
+#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -0,0 +1,40 @@
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
index 3012e05..2ae23ff 100644
--- a/cmake/ConfigureOpenSSL.cmake
+++ b/cmake/ConfigureOpenSSL.cmake
@@ -108,7 +108,8 @@ function(configure_openssl)
)
if(NOT "${CONFIGURE_OPTIONS_OLD}" STREQUAL "")
- if(CONFIGURE_OPTIONS STREQUAL CONFIGURE_OPTIONS_OLD)
+ # TODO(lizzie): Emscripten has issues with rebuilding due to the wrapper it uses
+ if(CMAKE_SYSTEM_NAME MATCHES "Emscripten" OR CONFIGURE_OPTIONS STREQUAL CONFIGURE_OPTIONS_OLD)
message(STATUS "Found previous configure results. Don't perform configuration")
return()
endif()
@@ -134,10 +135,24 @@ function(configure_openssl)
set(VERBOSE_OPTION OUTPUT_QUIET)
endif()
+ if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
+ set(EMSCRIPTEN_CMAKE_WRAPPER "emcmake")
+ find_program(EMCC emcc REQUIRED)
+ set(EMSCRIPTEN_LINKER ${EMCC})
+ list(APPEND CONFIGURE_COMMAND wasm64)
+ else()
+ set(EMSCRIPTEN_CMAKE_WRAPPER "")
+ set(EMSCRIPTEN_LINKER ${CMAKE_LINKER})
+ endif ()
+
execute_process(
- COMMAND ${CMAKE_COMMAND} -E env
+ COMMAND ${EMSCRIPTEN_CMAKE_WRAPPER} ${CMAKE_COMMAND} -E env
"CFLAGS=${CMAKE_C_FLAGS}"
"CXXFLAGS=${CMAKE_CXX_FLAGS}"
+ "LDFLAGS=${CMAKE_CXX_LINK_FLAGS}"
+ "CC=${CMAKE_C_COMPILER}"
+ "CXX=${CMAKE_CXX_COMPILER}"
+ "LD=${EMSCRIPTEN_LINKER}"
${CONFIGURE_COMMAND}
WORKING_DIRECTORY ${CONFIGURE_BUILD_DIR}
${VERBOSE_OPTION}
@@ -0,0 +1,33 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1ca57e1..593fd62 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -148,6 +148,16 @@ if(NOT BUILD_SHARED_LIBS)
list(APPEND OPENSSL_CONFIGURE_OPTIONS no-shared)
endif()
+list(APPEND OPENSSL_CONFIGURE_OPTIONS
+ no-threads no-thread-pool no-shared no-afalgeng no-async no-capieng no-cmp no-cms no-comp no-ct
+ no-docs no-dgram no-dso no-dynamic-engine no-engine no-filenames no-gost
+ no-http no-legacy no-module no-nextprotoneg no-ocsp no-padlockeng no-quic
+ no-srp no-srtp no-ssl-trace no-static-engine no-tests no-thread-pool no-ts
+ no-ui-console no-uplink no-ssl3-method no-tls1-method no-tls1_1-method
+ no-dtls1-method no-dtls1_2-method no-argon2 no-bf no-blake2 no-cast
+ no-dsa no-idea no-md4 no-mdc2 no-ocb no-rc2 no-rc4 no-rmd160 no-scrypt
+ no-siphash no-siv no-sm2 no-sm3 no-sm4 no-whirlpool no-apps)
+
list(SORT OPENSSL_CONFIGURE_OPTIONS)
list(REMOVE_DUPLICATES OPENSSL_CONFIGURE_OPTIONS)
list(PREPEND OPENSSL_CONFIGURE_OPTIONS ${OPENSSL_TARGET_PLATFORM})
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
index 2ae23ff..22a4a27 100644
--- a/cmake/ConfigureOpenSSL.cmake
+++ b/cmake/ConfigureOpenSSL.cmake
@@ -154,6 +154,7 @@ function(configure_openssl)
"CXX=${CMAKE_CXX_COMPILER}"
"LD=${EMSCRIPTEN_LINKER}"
${CONFIGURE_COMMAND}
+ "--prefix=${CMAKE_SYSROOT}"
WORKING_DIRECTORY ${CONFIGURE_BUILD_DIR}
${VERBOSE_OPTION}
COMMAND_ERROR_IS_FATAL ANY
@@ -0,0 +1,13 @@
diff --git a/crypto/o_str.c b/crypto/o_str.c
index 8aadff5..ba427c9 100644
--- a/crypto/o_str.c
+++ b/crypto/o_str.c
@@ -385,7 +385,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen)
* It can return a pointer to some (immutable) static string in which case
* buf is left unused.
*/
- err = strerror_r(errnum, buf, buflen);
+ err = (char *)strerror_r(errnum, buf, buflen);
if (err == NULL || buflen == 0)
return 0;
/*
+196
View File
@@ -0,0 +1,196 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8872895..b0eeca8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1770,7 +1770,6 @@ elseif(EMSCRIPTEN)
CheckPTHREAD()
CheckLibUnwind()
-
elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
set(SDL_DISABLE_DLOPEN_NOTES TRUE)
@@ -3647,10 +3646,30 @@ if(NOT HAVE_CAMERA)
)
endif()
+# Always on?
+if (OPENORBIS)
+ sdl_sources(
+ "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_systhread.c"
+ "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_sysmutex.c" # Can be faked, if necessary
+ "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_syscond.c" # Can be faked, if necessary
+ "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_sysrwlock.c" # Can be faked, if necessary
+ "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_systls.c"
+ "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syssem.c"
+ )
+ sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c")
+ sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c")
+ set(HAVE_SDL_THREADS TRUE)
+ set(HAVE_SDL_TIMERS TRUE)
+ set(HAVE_SDL_TIME TRUE)
+ set(SDL_TIME_UNIX 1)
+ set(SDL_TIMER_UNIX 1)
+ set(SDL_THREAD_PTHREAD 1)
+endif ()
+
# We always need to have threads and timers around
if(NOT HAVE_SDL_THREADS)
# The Emscripten and N-Gage platform has been carefully vetted to work without threads
- if(EMSCRIPTEN OR NGAGE)
+ if(EMSCRIPTEN OR NGAGE OR OPENORBIS)
set(SDL_THREADS_DISABLED 1)
sdl_glob_sources(
"${SDL3_SOURCE_DIR}/src/thread/generic/*.c"
diff --git a/build-scripts/rename_macros.py b/build-scripts/rename_macros.py
index 978120c..b6063dd 100755
--- a/build-scripts/rename_macros.py
+++ b/build-scripts/rename_macros.py
@@ -124,6 +124,7 @@ RENAMED_MACROS = {
"__RISCOS__": "SDL_PLATFORM_RISCOS",
"__SOLARIS__": "SDL_PLATFORM_SOLARIS",
"__PSP__": "SDL_PLATFORM_PSP",
+ "__PS4__": "SDL_PLATFORM_PS4",
"__PS2__": "SDL_PLATFORM_PS2",
"__VITA__": "SDL_PLATFORM_VITA",
"__3DS__": "SDL_PLATFORM_3DS",
diff --git a/include/SDL3/SDL_platform_defines.h b/include/SDL3/SDL_platform_defines.h
index 7963149..6c0dd5d 100644
--- a/include/SDL3/SDL_platform_defines.h
+++ b/include/SDL3/SDL_platform_defines.h
@@ -442,6 +442,16 @@
#define SDL_PLATFORM_PSP 1
#endif
+#if defined(__PS4__) || defined(__OPENORBIS__)
+
+/**
+ * A preprocessor macro that is only defined if compiling for Sony PSP.
+ *
+ * \since This macro is available since SDL 3.2.0.
+ */
+#define SDL_PLATFORM_PS4 1
+#endif
+
#if defined(__PS2__) || defined(PS2)
/**
diff --git a/src/SDL.c b/src/SDL.c
index b1a1a56..0a3fec6 100644
--- a/src/SDL.c
+++ b/src/SDL.c
@@ -714,7 +714,7 @@ void SDL_Quit(void)
SDL_DBus_Quit();
#endif
-#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) && !defined(SDL_PLATFORM_EMSCRIPTEN) && !defined(SDL_PLATFORM_PRIVATE)
+#if defined(SDL_PLATFORM_UNIX) && !defined(SDL_PLATFORM_ANDROID) && !defined(SDL_PLATFORM_EMSCRIPTEN) && !defined(SDL_PLATFORM_PRIVATE) && !defined(SDL_PLATFORM_PS4)
SDL_Gtk_Quit();
#endif
@@ -813,6 +813,8 @@ const char *SDL_GetPlatform(void)
return "tvOS";
#elif defined(SDL_PLATFORM_PS2)
return "PlayStation 2";
+#elif defined(SDL_PLATFORM_PS4)
+ return "PlayStation 4";
#elif defined(SDL_PLATFORM_PSP)
return "PlayStation Portable";
#elif defined(SDL_PLATFORM_VITA)
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index c1e4241..65b1e6d 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -80,6 +80,9 @@ static const AudioBootStrap *const bootstrap[] = {
#ifdef SDL_AUDIO_DRIVER_NGAGE
&NGAGEAUDIO_bootstrap,
#endif
+#ifdef SDL_AUDIO_DRIVER_PS4
+ &PS4AUDIO_bootstrap,
+#endif
#ifdef SDL_AUDIO_DRIVER_EMSCRIPTEN
&EMSCRIPTENAUDIO_bootstrap,
#endif
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 60c9743..2d12c3a 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 47ce42c..42ab9de 100644
--- a/src/joystick/SDL_sysjoystick.h
+++ b/src/joystick/SDL_sysjoystick.h
@@ -253,6 +253,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_sysrender.h b/src/render/SDL_sysrender.h
index a1bb44a..51843c4 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -381,6 +381,7 @@ extern SDL_RenderDriver NGAGE_RenderDriver;
extern SDL_RenderDriver VULKAN_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;
extern SDL_RenderDriver GPU_RenderDriver;
diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c
index 4a870f6..69ca1db 100644
--- a/src/stdlib/SDL_string.c
+++ b/src/stdlib/SDL_string.c
@@ -32,7 +32,9 @@
#include "SDL_casefolding.h"
-#if defined(__SIZEOF_WCHAR_T__)
+#if defined(SDL_PLATFORM_PS4)
+#define SDL_SIZEOF_WCHAR_T 2
+#elif defined(__SIZEOF_WCHAR_T__)
#define SDL_SIZEOF_WCHAR_T __SIZEOF_WCHAR_T__
#elif defined(SDL_PLATFORM_NGAGE)
#define SDL_SIZEOF_WCHAR_T 2
@@ -43,7 +45,6 @@
#endif
SDL_COMPILE_TIME_ASSERT(sizeof_wchar_t, sizeof(wchar_t) == SDL_SIZEOF_WCHAR_T);
-
char *SDL_UCS4ToUTF8(Uint32 codepoint, char *dst)
{
if (!dst) {
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index f650f27..e23424f 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -131,6 +131,9 @@ static VideoBootStrap *bootstrap[] = {
#ifdef SDL_VIDEO_DRIVER_NGAGE
&NGAGE_bootstrap,
#endif
+#ifdef SDL_VIDEO_DRIVER_PS4
+ &PS4_bootstrap,
+#endif
#ifdef SDL_VIDEO_DRIVER_KMSDRM
&KMSDRM_bootstrap,
#endif
@@ -314,6 +317,7 @@ static bool SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window *window,
SDL_GetWindowSizeInPixels(window, &w, &h);
if (!data) {
+
SDL_Renderer *renderer = NULL;
const char *render_driver = NULL;
File diff suppressed because it is too large Load Diff
+25
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"
@@ -1,26 +0,0 @@
From b3622608433c183ba868a1dc8dd9cf285eb3b916 Mon Sep 17 00:00:00 2001
From: Dario Petrillo <dario.pk1@gmail.com>
Date: Thu, 27 Nov 2025 23:12:38 +0100
Subject: [PATCH] avoid extra memset when clearing an empty table
---
include/ankerl/unordered_dense.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/ankerl/unordered_dense.h b/include/ankerl/unordered_dense.h
index 0835342..4938212 100644
--- a/include/ankerl/unordered_dense.h
+++ b/include/ankerl/unordered_dense.h
@@ -1490,8 +1490,10 @@ class table : public std::conditional_t<is_map_v<T>, base_table_type_map<T>, bas
// modifiers //////////////////////////////////////////////////////////////
void clear() {
- m_values.clear();
- clear_buckets();
+ if (!empty()) {
+ m_values.clear();
+ clear_buckets();
+ }
}
auto insert(value_type const& value) -> std::pair<iterator, bool> {
+7 -5
View File
@@ -22,6 +22,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?")
@@ -81,6 +82,9 @@ cmake_dependent_option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSV
option(ENABLE_DEBUG_TOOLS "Enable debugging tools (maxwell disassembler, SPIRV translator, etc)" OFF)
option(ENABLE_WERROR "Enable -Werror diagnostics" ON)
# Lossless Scaling frame generation. Only Android.
cmake_dependent_option(ENABLE_LSFG "Enable Lossless Scaling frame generation" ON "ANDROID" OFF)
# non-linux bundled qt are static
if (YUZU_USE_BUNDLED_QT AND (APPLE OR NOT UNIX))
set(YUZU_STATIC_BUILD ON)
@@ -169,8 +173,6 @@ if (CXX_CLANG_CL)
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat-pedantic>
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c++98-compat>
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c99-compat>
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c98-compat>
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-c99-extensions>
$<$<COMPILE_LANGUAGE:C,CXX>:/EHsc>)
# REQUIRED CPU features IN Windows-amd64
if (ARCHITECTURE_x86_64)
@@ -339,11 +341,12 @@ if (CXX_GCC OR CXX_CLANG)
endif()
elseif(ARCHITECTURE_arm64)
# See https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html
set(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, generic, armv9, native")
set(YUZU_BUILD_PRESET "custom" CACHE STRING "Build preset to use. One of: custom, generic, optimized, armv9, native")
set(mtune generic)
if (${YUZU_BUILD_PRESET} STREQUAL "generic")
set(march armv8-a)
elseif (${YUZU_BUILD_PRESET} STREQUAL "optimized")
set(march armv8.2-a+lse+rcpc)
elseif (${YUZU_BUILD_PRESET} STREQUAL "armv9")
set(march armv9-a)
endif()
@@ -538,7 +541,6 @@ add_subdirectory(externals)
# pass targets from externals
# TODO(crueter): CPMUtil Propagate func?
find_package(enet)
find_package(unordered_dense REQUIRED)
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
find_package(xbyak)
+4 -1
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)
+46
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 ()
+17 -2
View File
@@ -15,8 +15,9 @@
<br>
</h1>
<h4 align="center"><b>Eden</b> is a free and opensource (FOSS) Switch 1 emulator, derived from Yuzu and Sudachi - started by developer Camille LaVey.
It's written in C++ with portability in mind, with builds for Windows, Linux, macOS, Android, FreeBSD and more.
<h4 align="center"><b>Eden</b> is a free and opensource (FOSS) Switch 1 emulator started by developer Camille LaVey.
<br>
Written in C++, with builds for Windows, Linux, macOS, Android, FreeBSD and more.
</h4>
<p align="center">
@@ -73,3 +74,17 @@ Save us some bandwidth! We have [mirrors available](./docs/user/ThirdParty.md#mi
## License
Eden is licensed under the GPLv3 (or any later version). Refer to the [LICENSE.txt](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt) file.
## Special thanks
Super special thanks to Cloudflare for preventing the git server from blowing up.
- Yuzu
- Ryujinx
- Sudachi
- Citron
- Torzu
- Suyu
- Ryubing
And everyone who continues or had contributed to the project! <3
+22 -19
View File
@@ -12,7 +12,8 @@
"min_version": "1.57",
"package": "Boost",
"patches": [
"0001-clang-cl.patch"
"0001-clang-cl.patch",
"0004-openorbis.patch"
],
"repo": "boostorg/boost",
"version": "boost-1.90.0"
@@ -70,12 +71,18 @@
"hash": "a0d2fa8c957704dd49e00a726284ac5ca034b50b00d2b20a94fa1bbfbb80841467834bfdc84aa0ed0d6aab894608fd6c86c3b94eee46343f0e6d9c22e391dbf9",
"min_version": "1.3",
"repo": "lsalzman/enet",
"version": "v1.3.18"
"version": "v1.3.18",
"patches": [
"0001-openorbis.patch"
]
},
"ffmpeg": {
"hash": "ed177621176b3961bdcaa339187d3a7688c1c8b060b79c4bb0257cbc67ad7021ae5d5adca5303b45625abbbe3d9aafdd87ce777b8690ac295290d744c875489a",
"repo": "FFmpeg/FFmpeg",
"version": "c7b5f1537d"
"version": "c7b5f1537d",
"patches": [
"0001-sysctl-openorbis.patch"
]
},
"ffmpeg-ci": {
"ci": true,
@@ -190,7 +197,8 @@
"min_version": "3.0.0",
"package": "OpenSSL",
"patches": [
"0001-add-bundled-cert.patch"
"0001-add-bundled-cert.patch",
"0002-fix-gnu-openorbis.patch"
],
"repo": "openssl/openssl",
"version": "openssl-3.6.2"
@@ -213,7 +221,9 @@
"0001-cpmutil-compat.patch",
"0002-use-ccache.patch",
"0003-use-cmake-compiler-flags.patch",
"0004-use-shell-wrapper.patch"
"0004-use-shell-wrapper.patch",
"0005-wasm-support.patch",
"0006-openorbis-prefix.patch"
],
"repo": "jimmy-park/openssl-cmake",
"version": "3.6.2"
@@ -251,7 +261,11 @@
"min_version": "3.2.10",
"package": "SDL3",
"repo": "libsdl-org/SDL",
"version": "release-3.4.8"
"version": "release-3.4.8",
"patches": [
"0001-ps4.patch",
"0002-ps4-drivers.patch"
]
},
"sdl3-ci": {
"ci": true,
@@ -301,17 +315,6 @@
"repo": "eden-emu/tzdb_to_nx",
"version": "230326"
},
"unordered-dense": {
"bundled": true,
"find_args": "CONFIG",
"hash": "d2106f6640f6bfb81755e4b8bfb64982e46ec4a507cacdb38f940123212ccf35a20b43c70c6f01d7bfb8c246d1a16f7845d8052971949cea9def1475e3fa02c8",
"package": "unordered_dense",
"patches": [
"0001-avoid-memset-when-clearing-an-empty-table.patch"
],
"repo": "martinus/unordered_dense",
"version": "7b55cab841"
},
"vulkan-headers": {
"hash": "d2846ea228415772645eea4b52a9efd33e6a563043dd3de059e798be6391a8f0ca089f455ae420ff22574939ed0f48ed7c6ff3d5a9987d5231dbf3b3f89b484b",
"min_version": "1.4.317",
@@ -340,10 +343,10 @@
"version": "vulkan-sdk-%NUMERIC_VERSION%"
},
"xbyak": {
"hash": "b6475276b2faaeb315734ea8f4f8bd87ededcee768961b39679bee547e7f3e98884d8b7851e176d861dab30a80a76e6ea302f8c111483607dde969b4797ea95a",
"hash": "e0aa0a603dd3ac1a39d82213df1e73c042831aec2d6b2fe382c899651eaae4ed7e8aeb6be9c41ea0097087c9d091961ab18f313cd6a9e10d621715ffd49bfe36",
"package": "xbyak",
"repo": "herumi/xbyak",
"version": "v7.35.2"
"version": "v7.40.1"
},
"zlib": {
"hash": "16fea4df307a68cf0035858abe2fd550250618a97590e202037acd18a666f57afc10f8836cbbd472d54a0e76539d0e558cb26f059d53de52ff90634bbf4f47d4",
+223
View File
@@ -0,0 +1,223 @@
<?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.3 (0d15f75042, 2025-12-25)"
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.4142136"
inkscape:cx="262.69017"
inkscape:cy="76.367532"
inkscape:window-width="1600"
inkscape:window-height="849"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" />
<circle
style="opacity:1;mix-blend-mode:screen;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:15.907;stroke-dasharray:none;stroke-opacity:1"
id="path1"
cx="256.61652"
cy="257.31778"
r="227.33479" />
<path
id="path8-7"
style="display:inline;mix-blend-mode:multiply;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"
sodipodi:insensitive="true" />
<path
id="path8-7-2"
style="display:inline;mix-blend-mode:multiply;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"
sodipodi:insensitive="true" />
<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

+540 -531
View File
File diff suppressed because it is too large Load Diff
+538 -529
View File
File diff suppressed because it is too large Load Diff
+534 -525
View File
File diff suppressed because it is too large Load Diff
+534 -525
View File
File diff suppressed because it is too large Load Diff
+539 -532
View File
File diff suppressed because it is too large Load Diff
+534 -525
View File
File diff suppressed because it is too large Load Diff
+539 -532
View File
File diff suppressed because it is too large Load Diff
+534 -525
View File
File diff suppressed because it is too large Load Diff
+537 -529
View File
File diff suppressed because it is too large Load Diff
+534 -525
View File
File diff suppressed because it is too large Load Diff
+533 -525
View File
File diff suppressed because it is too large Load Diff
+539 -532
View File
File diff suppressed because it is too large Load Diff
+536 -527
View File
File diff suppressed because it is too large Load Diff
+599 -591
View File
File diff suppressed because it is too large Load Diff
+541 -532
View File
File diff suppressed because it is too large Load Diff
+535 -528
View File
File diff suppressed because it is too large Load Diff
+539 -532
View File
File diff suppressed because it is too large Load Diff
+539 -532
View File
File diff suppressed because it is too large Load Diff
+534 -525
View File
File diff suppressed because it is too large Load Diff
+569 -553
View File
File diff suppressed because it is too large Load Diff
+539 -532
View File
File diff suppressed because it is too large Load Diff
+539 -531
View File
File diff suppressed because it is too large Load Diff
+539 -532
View File
File diff suppressed because it is too large Load Diff
+534 -525
View File
File diff suppressed because it is too large Load Diff
+534 -525
View File
File diff suppressed because it is too large Load Diff
+556 -541
View File
File diff suppressed because it is too large Load Diff
+535 -527
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -509,6 +509,8 @@ QWidget#contentRichDialog QLabel#label_title_rich {
}
QWidget#contentDialog QLabel#label_dialog {
background: #2E2E2E;
padding: 20px 65px;
}
+12
View File
@@ -12,6 +12,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)
@@ -245,6 +246,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
+4 -5
View File
@@ -80,7 +80,6 @@ Certain other dependencies will be fetched by CPM regardless. System packages *c
* [httplib](https://github.com/yhirose/cpp-httplib) - if `ENABLE_UPDATE_CHECKER` or `ENABLE_WEB_SERVICE` are on
* This package is known to be broken on the AUR.
* [cpp-jwt](https://github.com/arun11299/cpp-jwt) 1.4+ - if `ENABLE_WEB_SERVICE` is on
* [unordered-dense](https://github.com/martinus/unordered_dense)
On amd64:
@@ -119,7 +118,7 @@ Now, install all deps:
sudo emerge -a \
app-arch/lz4 app-arch/zstd app-arch/unzip \
dev-libs/libfmt dev-libs/libusb dev-libs/mcl dev-libs/sirit \
dev-libs/unordered_dense dev-libs/boost dev-libs/openssl dev-libs/discord-rpc \
dev-libs/boost dev-libs/openssl dev-libs/discord-rpc \
dev-util/spirv-tools dev-util/spirv-headers dev-util/vulkan-headers \
dev-util/vulkan-utility-libraries dev-util/glslang \
media-gfx/renderdoc media-libs/libva media-libs/opus media-video/ffmpeg \
@@ -260,7 +259,7 @@ brew install molten-vk
<details>
<summary>FreeBSD</summary>
As root run: `pkg install devel/cmake sdl3 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/qt6-charts devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/unordered-dense vulkan-headers quazip-qt6`
As root run: `pkg install devel/cmake sdl3 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/qt6-charts devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib vulkan-headers quazip-qt6`
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
@@ -294,7 +293,7 @@ pkg_add cmake nasm git boost unzip--iconv autoconf-2.72p0 bash ffmpeg glslang gm
<summary>DragonFlyBSD</summary>
```sh
pkg install gcc14 git cmake unzip nasm autoconf bash pkgconf ffmpeg glslang gmake jq nlohmann-json enet spirv-tools sdl3 vulkan-utility-libraries vulkan-headers catch2 libfmt openssl liblz4 boost-libs cpp-httplib qt6-base qt6-charts quazip-qt6 unordered-dense libva-vdpau-driver libva-utils libva-intel-driver
pkg install gcc14 git cmake unzip nasm autoconf bash pkgconf ffmpeg glslang gmake jq nlohmann-json enet spirv-tools sdl3 vulkan-utility-libraries vulkan-headers catch2 libfmt openssl liblz4 boost-libs cpp-httplib qt6-base qt6-charts quazip-qt6 libva-vdpau-driver libva-utils libva-intel-driver
```
[Caveats](./Caveats.md#dragonflybsd).
@@ -328,7 +327,7 @@ sudo pkgin install git cmake autoconf build-essential libusb-1 nasm gcc13
```sh
BASE="git make autoconf libtool automake-wrapper jq patch"
MINGW="qt6-base qt6-charts qt6-tools qt6-translations qt6-svg cmake toolchain clang python-pip openssl vulkan-memory-allocator vulkan-devel glslang boost fmt lz4 nlohmann-json zlib zstd enet opus libusb unordered_dense openssl SDL3"
MINGW="qt6-base qt6-charts qt6-tools qt6-translations qt6-svg cmake toolchain clang python-pip openssl vulkan-memory-allocator vulkan-devel glslang boost fmt lz4 nlohmann-json zlib zstd enet opus libusb openssl SDL3"
# Either x86_64 or clang-aarch64 (Windows on ARM)
packages="$BASE"
for pkg in $MINGW; do
+47
View File
@@ -0,0 +1,47 @@
# Design Overview
Modern game consoles require heavy power to be emulated appropriatedly. This is why the emulator uses an approach known as HLE (High-Level-Emulation), in a nuthsell: Instead of accurately emulating every subsystem that forms part of a component, emulate the resulting visible I/O interface instead.
For example, take a disk write, instead of emulating a proper SD card we instead use the C++ standard library for I/O. Additionally we use the abstractions provided by the `fs` service to "lie" to programs about certain SD card properties. Notably this includes making up sizes for the fake SD card, giving "realistic" values or expected outputs for a given card, and so on. And instead of writing to an actual SD card, the emulator simply writes to a file.
This also means grand part of the emulator consists of just re-implementing firmware but using HLE primitives; for example audio doesn't go to an emulated audio device, but rather gets processed on the fly by a dedicated service and then passed to SDL3/cubeb/etc.
As such, many of the systems implemented are not 100% accurate to the original software, but they're "good enough" to pass as being so. While we do strive to maintain high compatibility (especially with homebrew), there are realistic limitations to these approaches.
No formal fuzzing or formal verification has been done on the emulator as a whole, this means there may be hundreds of bugs hiding in each subsystem. As such, output may also not correctly match due to those aforementioned issues.
## src/android/
Entire Android frontend, written mostly in Kotlin and generally having asinine hacks (thanks Android) due to the particularly horrific (and particular way) to do things.
## src/audio_core/
Handles everything related to audio, this is where most of the filtering and processing occurs (CPU intensive task!).
## src/common/
The [common](../src/common) folder contains just your basic pollyfills for whatever missing functionality. We heavily encourage new PRs to make use of one of the dependencies, or the standard C++ library. Minimizing the amount of things we reinvent the wheel for is always a good thing.
## src/core/
The [core folder](../src/core) is the main heart of the emulator, while we don't officially support having other frontends out of the box (RetroArch, for example); any prospective developer can reuse this library (compiled as one by CMake) to stitch up their own RetroArch core, for example.
## src/dynarmic/
See [Dynarmic](./dynarmic).
## src/hid_core/
Input, joysticks, controllers and everything related to input devices.
## src/shader_recompiler/
Dedicated shader recompiler to translate Maxwell assembly code to either SPIR-V, GLSL or GLASM.
## src/video_core/
Most of the things here have their own dedicated section. In short this is basically the entire Tegra NVIDIA Maxwell GPU emulation. Additionally it includes some [extra effects](../src/video_core/host_ahders) to emulate MSAA, D24 copies or as polyfill.
Available backends are: Null, Vulkan, and OpenGL.
See [NVIDIA GPU](./NvidiaGpu.md).
+1
View File
@@ -20,6 +20,7 @@ This contains documentation created by developers. This contains build instructi
- **[Driver Bugs](./DriverBugs.md)**
- **[Building Older Commits](./build/OlderCommits.md)**
- Subsystems:
- **[Design Overview](./DesignOverview.md)**
- **[Dynarmic](./dynarmic/README.md)**
- **[HOS Kernel](./HosKernel.md)**
- **[Settings](./Settings.md)**
+27 -11
View File
@@ -43,6 +43,7 @@ This guide will walk you through adding a new boolean toggle setting to Eden's c
Firstly add your desired toggle:
Example: `src/common/setting.h`
```cpp
SwitchableSetting<bool> your_setting_name{linkage, false, "your_setting_name", Category::RendererExtensions};
```
@@ -67,6 +68,7 @@ Common Categories:
Add the toggle to the Qt UI, where you wish for it to appear and place it there.
Example: `src/qt_common/config/shared_translation.cpp`
```cpp
INSERT(Settings,
your_setting_name,
@@ -91,6 +93,7 @@ INSERT(Settings,
Add where it should be in the settings.
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt`
```kts
RENDERER_YOUR_SETTING_NAME("your_setting_name"),
```
@@ -106,6 +109,7 @@ RENDERER_YOUR_SETTING_NAME("your_setting_name"),
Add the toggle to the Kotlin (Android) UI
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt`
```kts
put(
SwitchSetting(
@@ -123,6 +127,7 @@ put(
Add your setting within the right category.
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt`
```kts
add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
```
@@ -137,6 +142,7 @@ add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
Add your setting and description in the appropriate place.
Example: `src/android/app/src/main/res/values/strings.xml`
```xml
<string name="your_setting_name">Your Setting Display Name</string>
<string name="your_setting_name_description">Detailed description of what this setting does. Explain any caveats, requirements, or warnings here.</string>
@@ -150,6 +156,7 @@ Now the UI part is done find a place in the code for the toggle,
And use it to your heart's desire!
Example:
```cpp
const bool your_value = Settings::values.your_setting_name.GetValue();
@@ -196,25 +203,31 @@ Common advantages recap:
#### Accessing Debug Knobs (dev side)
Use the `Settings::getDebugKnobAt(u8 i)` function to check if a specific bit is set:
Use the `Settings::GetDebugKnobAt(u8 i)` function to check if a specific bit is set:
```cpp
//cpp side
#include "common/settings.h"
//To use it as a general purpose uint var:
unsigned int debug_knobs = Settings::values.debug_knobs.GetValue();
// Check if bit 0 is set
bool feature_enabled = Settings::getDebugKnobAt(0);
bool feature_enabled = Settings::GetDebugKnobAt(0);
// Check if bit 15 is set
bool another_feature = Settings::getDebugKnobAt(15);
bool another_feature = Settings::GetDebugKnobAt(15);
```
```kts
//kotlin side
import org.yuzu.yuzu_emu.features.settings.model.Settings
//To use it as a general purpose uint var
val debug_knobs: Int = UShortSetting.DEBUG_KNOBS.getInt()
// Check if bit x is set
bool feature_enabled = Settings.getDebugKnobAt(x); //x as integer from 0 to 15
bool feature_enabled = Settings.GetDebugKnobAt(x); //x as integer from 0 to 15
```
The function returns `true` if the specified bit (0-15) is set in the `debug_knobs` value, `false` otherwise.
@@ -247,6 +260,7 @@ There are two main confusions when talking about knobs:
Sometimes when an user reports: knobs 1 and 2 gets better performance, dev may get confuse whether he means the knobs 1 and 2 literally, or the 1st and 2nd knobs (knobs 0 and 1).
Debug knobs are **zero-based**, which means:
* The first knob is the knob(0) (or knob0 henceforth), and the last one is the 15 (knob15, likewise)
* You can talk: "knob0 is enabled/disabled", "In this video i was using only knobs 0 and 2", etc.
@@ -259,6 +273,7 @@ Whenever you're instructing tests or reporting results, be precise about whether
ALWAYS use the word in PLURAL (knobs), without mentioning which one, to refer to the setting, aka multiple knobs at once:
Examples:
- **knobs=0**: no knobs enabled
- **knobs=1**: knob0 enabled, others disabled
- **knobs=2**: knob1 enabled, others disabled
@@ -270,6 +285,7 @@ Examples:
Use the word in SINGULAR (knob), or in plural but referring which ones, when meaning multiple knobs at once:
Examples:
- **knob0**: knob 0 enabled, others disabled
- **knob1**: knob 1 enabled, others disabled
- **knobs 0 and 1**: knobs 0 and 1 enabled, others disabled
@@ -282,12 +298,12 @@ Examples:
```cpp
void SomeFunction() {
if (Settings::getDebugKnobAt(0)) {
if (Settings::GetDebugKnobAt(0)) {
LOG_DEBUG(Common, "Debug feature 0 is enabled");
// Additional debug code here
}
if (Settings::getDebugKnobAt(1)) {
if (Settings::GetDebugKnobAt(1)) {
LOG_DEBUG(Common, "Debug feature 1 is enabled");
// Different debug behavior
}
@@ -299,7 +315,7 @@ void SomeFunction() {
```cpp
bool UseOptimizedPath() {
// Skip optimization if debug bit 2 is set for testing
return !Settings::getDebugKnobAt(2);
return !Settings::GetDebugKnobAt(2);
}
```
@@ -308,13 +324,13 @@ bool UseOptimizedPath() {
```cpp
void ExperimentalFeature() {
static constexpr u8 EXPERIMENTAL_FEATURE_BIT = 3;
if (!Settings::getDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) {
if (!Settings::GetDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) {
// Fallback to stable implementation
StableImplementation();
return;
}
// Experimental implementation
ExperimentalImplementation();
}
-26
View File
@@ -308,32 +308,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
### unordered_dense
```
MIT License
Copyright (c) 2022 Martin Leitner-Ankerl
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
### xbyak
```
+1
View File
@@ -35,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.
+38
View File
@@ -77,3 +77,41 @@ Use this guide to get starting using the Eden emulator.
8. Double-Click the main window to add the folder containing your games.
9. Go to *Emulation > Configure > Input* and set up your controller. Click **OK** to close the dialog window.
10. Double-Click a game to run it.
## 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.
**Click [Here](https://evilperson1337.notion.site/Allowing-Eden-to-Run-on-MacOS-2b057c2edaf681fea63dc81027efeffd) for a version of this guide with images & visual elements.**
---
##### Pre-Requisites
- Permissions to modify settings in MacOS
---
#### 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 isn't on the list of trusted ones, it will stop the program from executing and display the message above.
---
#### Steps
1. Open the *System Settings* panel.
2. Navigate to *Privacy & Security*.
3. Scroll down and observe the following message under the **Security** settings.
4. Select **Open Anyway** to tell your Mac that you trust the application.
5. You will now get another window appearing to verify you want to open Eden. Select **Open Anyway**.
6. You will be prompted for your password to authorize the request. Enter the credentials of an account that has permission to modify settings and press **OK**.
7. Eden will now open and any subsequent launches of the program will not prompt this.
+3 -1
View File
@@ -10,13 +10,15 @@ A copy of this handbook is [available online](https://git.eden-emu.dev/eden-emu/
- **[The Basics](Basics.md)**
- **[Quickstart](./QuickStart.md)**
- **[Windows](./QuickStart.md#windows)**
- **[Steamdeck](./QuickStart.md#steamdeck)**
- **[macOS](./QuickStart.md#macos)**
- **[Settings](./Settings.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)**
-37
View File
@@ -1,37 +0,0 @@
# 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.
**Click [Here](https://evilperson1337.notion.site/Allowing-Eden-to-Run-on-MacOS-2b057c2edaf681fea63dc81027efeffd) for a version of this guide with images & visual elements.**
---
#### Pre-Requisites
- Permissions to modify settings in MacOS
---
### 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 isn't on the list of trusted ones, it will stop the program from executing and display the message above.
---
### Steps
1. Open the *System Settings* panel.
2. Navigate to *Privacy & Security*.
3. Scroll down and observe the following message under the **Security** settings.
4. Select **Open Anyway** to tell your Mac that you trust the application.
5. You will now get another window appearing to verify you want to open Eden. Select **Open Anyway**.
6. You will be prompted for your password to authorize the request. Enter the credentials of an account that has permission to modify settings and press **OK**.
7. Eden will now open and any subsequent launches of the program will not prompt this.
+5 -3
View File
@@ -58,9 +58,6 @@ if (WIN32 AND NOT TARGET LLVM::Demangle)
add_library(LLVM::Demangle ALIAS demangle)
endif()
# unordered_dense
AddJsonPackage(unordered-dense)
# httplib
if (IOS)
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF)
@@ -260,6 +257,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 (OPENORBIS)
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)
+184
View File
@@ -0,0 +1,184 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* ===---------- 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];
}
+44
View File
@@ -0,0 +1,44 @@
// 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"); \
}
#define STUB_ZERO(name) \
extern "C" int name() { \
printf("called " #name " = ret zero"); \
return 0; \
}
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(ZSTD_trace_compress_begin)
STUB_WEAK(ZSTD_trace_compress_end)
STUB_WEAK(ZSTD_trace_decompress_begin)
STUB_WEAK(ZSTD_trace_decompress_end)
extern "C" thread_local struct {
char pad[512];
} _ThreadRuneLocale = {};
extern "C" struct {
char pad[512];
} __h_errno = {};
FILE* __stderrp = stdout;
FILE* __stdinp = stdin;
#undef STUB_WEAK
// THIS MAKES STD::COUT AND SUCH WORK :)
#include <iostream>
std::ios_base::Init init;
@@ -220,7 +220,7 @@ object NativeLibrary {
external fun refreshThreadPolicies()
external fun getDebugKnobAt(index: Int): Boolean
external fun GetDebugKnobAt(index: Int): Boolean
/**
* Set the current speed limit to the configured turbo speed.
@@ -539,6 +539,40 @@ object NativeLibrary {
*/
external fun installKeys(path: String, ext: String): Int
/**
* @return Whether this GPU can run the Lossless Scaling frame generation shaders,
* which are built against the Vulkan memory model.
*/
external fun supportsFrameGeneration(): Boolean
/**
* @return Path the user-supplied Lossless Scaling library is expected at.
*/
external fun getLosslessDllPath(): String
/**
* Parses the installed Lossless Scaling library and checks that every shader the
* frame generation chain needs is present.
*
* @return The result code, matching the losslessDllResults array.
*/
external fun validateLosslessDll(): Int
/**
* Translates the frame generation shaders out of the installed Lossless Scaling library
* and writes them to the SPIR-V cache. Slow, so call it off the main thread.
*
* @return The result code, matching the losslessDllResults array.
*/
external fun prepareLosslessDll(): Int
/**
* Deletes the installed Lossless Scaling library.
*
* @return Whether the library is gone after the call.
*/
external fun removeLosslessDll(): Boolean
/**
* Checks the PatchManager for any addons that are available
*
@@ -559,6 +559,15 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
private fun enableFullscreenImmersive() {
WindowCompat.setDecorFitsSystemWindows(window, false)
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
controller.hide(WindowInsetsCompat.Type.systemBars())
controller.systemBarsBehavior =
@@ -37,6 +37,10 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
RENDERER_SAMPLE_SHADING("sample_shading"),
RENDERER_FRAME_GEN("frame_gen"),
RENDERER_FRAME_GEN_FP16("frame_gen_fp16"),
RENDERER_FRAME_GEN_FLOW_SCALE_AUTO("frame_gen_flow_scale_auto"),
RENDERER_FRAME_GEN_DUMP_FLOW("frame_gen_dump_flow"),
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
PICTURE_IN_PICTURE("picture_in_picture"),
USE_CUSTOM_RTC("custom_rtc_enabled"),
@@ -19,6 +19,10 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
RENDERER_ACCURACY("gpu_accuracy"),
RENDERER_RESOLUTION("resolution_setup"),
RENDERER_FRAME_GEN_MULTIPLIER("frame_gen_multiplier"),
RENDERER_FRAME_GEN_TARGET_RATE("frame_gen_target_rate"),
RENDERER_FRAME_GEN_QUEUE_TARGET("frame_gen_queue_target"),
RENDERER_FRAME_GEN_FLOW_SCALE("frame_gen_flow_scale"),
RENDERER_VSYNC("use_vsync"),
RENDERER_SCALING_FILTER("scaling_filter"),
RENDERER_ANTI_ALIASING("anti_aliasing"),
@@ -11,6 +11,7 @@ object Settings {
SECTION_ROOT(R.string.advanced_settings),
SECTION_SYSTEM(R.string.preferences_system),
SECTION_RENDERER(R.string.preferences_graphics),
SECTION_FRAME_GEN(R.string.frame_gen),
SECTION_PERFORMANCE_STATS(R.string.stats_overlay_options),
SECTION_INPUT_OVERLAY(R.string.input_overlay_options),
SECTION_SOC_OVERLAY(R.string.soc_overlay_options),
@@ -34,8 +35,8 @@ object Settings {
fun getPlayerString(player: Int): String =
YuzuApplication.appContext.getString(R.string.preferences_player, player)
fun getDebugKnobAt(index: Int): Boolean {
return org.yuzu.yuzu_emu.NativeLibrary.getDebugKnobAt(index)
fun GetDebugKnobAt(index: Int): Boolean {
return org.yuzu.yuzu_emu.NativeLibrary.GetDebugKnobAt(index)
}
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
@@ -11,8 +11,7 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
enum class ShortSetting(override val key: String) : AbstractShortSetting {
RENDERER_SPEED_LIMIT("speed_limit"),
RENDERER_TURBO_SPEED_LIMIT("turbo_speed_limit"),
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit"),
DEBUG_KNOBS("debug_knobs")
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit")
;
override fun getShort(needsGlobal: Boolean): Short = NativeConfig.getShort(key, needsGlobal)
@@ -29,4 +28,4 @@ enum class ShortSetting(override val key: String) : AbstractShortSetting {
override fun getValueAsString(needsGlobal: Boolean): String = getShort(needsGlobal).toString()
override fun reset() = NativeConfig.setShort(key, defaultValue)
}
}
@@ -11,6 +11,7 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
enum class StringSetting(override val key: String) : AbstractStringSetting {
DRIVER_PATH("driver_path"),
DEVICE_NAME("device_name"),
LOG_FILTER("log_filter"),
PROGRAM_ARGS("program_args"),
WEB_TOKEN("eden_token"),
@@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.features.settings.model
import org.yuzu.yuzu_emu.utils.NativeConfig
enum class UShortSetting(override val key: String) : AbstractIntSetting {
DEBUG_KNOBS("debug_knobs")
;
override fun getInt(needsGlobal: Boolean): Int =
NativeConfig.getUnsignedShort(key, needsGlobal)
override fun setInt(value: Int) {
if (NativeConfig.isPerGameConfigLoaded()) {
global = false
}
NativeConfig.setUnsignedShort(key, value)
}
override val defaultValue: Int by lazy { NativeConfig.getDefaultToString(key).toInt() }
override fun getValueAsString(needsGlobal: Boolean): String = getInt(needsGlobal).toString()
override fun reset() = NativeConfig.setUnsignedShort(key, defaultValue)
}
@@ -20,7 +20,9 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.LongSetting
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.features.settings.model.UShortSetting
import org.yuzu.yuzu_emu.network.NetDataValidators
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
import org.yuzu.yuzu_emu.utils.NativeConfig
/**
@@ -65,6 +67,19 @@ abstract class SettingsItem(
return NativeLibrary.isFirmwareAvailable()
}
if (setting.key in frameGenKeys &&
!(LosslessScalingHelper.isInstalled() && LosslessScalingHelper.isSupportedByGpu())
) {
return false
}
// A frame rate target moves the multiplier on its own
if (setting.key == IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key &&
frameGenTargetRate != 0
) {
return false
}
// Can't edit settings that aren't saveable in per-game config even if they are switchable
if (NativeConfig.isPerGameConfigLoaded() && !setting.isSaveable) {
return false
@@ -88,7 +103,31 @@ abstract class SettingsItem(
val clearable: Boolean
get() = !setting.global && NativeConfig.isPerGameConfigLoaded()
private val frameGenTargetRate: Int
get() {
val key = IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key
val needsGlobal = if (NativeLibrary.isRunning() &&
!NativeConfig.isPerGameConfigLoaded()
) {
!NativeConfig.usingGlobal(key)
} else {
NativeConfig.usingGlobal(key)
}
return IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.getInt(needsGlobal)
}
companion object {
private val frameGenKeys = setOf(
BooleanSetting.RENDERER_FRAME_GEN.key,
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key,
IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key,
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key,
BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key,
IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key,
BooleanSetting.RENDERER_FRAME_GEN_FP16.key,
BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW.key
)
const val TYPE_HEADER = 0
const val TYPE_SWITCH = 1
const val TYPE_SINGLE_CHOICE = 2
@@ -586,6 +625,7 @@ abstract class SettingsItem(
IntSetting.FSR_SHARPENING_SLIDER,
titleId = R.string.fsr_sharpness,
descriptionId = R.string.fsr_sharpness_description,
max = 200,
units = "%"
)
)
@@ -607,6 +647,71 @@ abstract class SettingsItem(
valuesId = R.array.rendererAntiAliasingValues
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_FRAME_GEN,
titleId = R.string.frame_gen,
descriptionId = R.string.frame_gen_description
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_FRAME_GEN_MULTIPLIER,
titleId = R.string.frame_gen_multiplier,
descriptionId = R.string.frame_gen_multiplier_description,
choicesId = R.array.frameGenMultiplierNames,
valuesId = R.array.frameGenMultiplierValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_FRAME_GEN_TARGET_RATE,
titleId = R.string.frame_gen_target_rate,
descriptionId = R.string.frame_gen_target_rate_description,
choicesId = R.array.frameGenTargetRateNames,
valuesId = R.array.frameGenTargetRateValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET,
titleId = R.string.frame_gen_queue_target,
descriptionId = R.string.frame_gen_queue_target_description,
choicesId = R.array.frameGenQueueTargetNames,
valuesId = R.array.frameGenQueueTargetValues
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO,
titleId = R.string.frame_gen_flow_scale_auto,
descriptionId = R.string.frame_gen_flow_scale_auto_description
)
)
put(
SliderSetting(
IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE,
titleId = R.string.frame_gen_flow_scale,
descriptionId = R.string.frame_gen_flow_scale_description,
min = 25,
max = 100,
units = "%"
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_FRAME_GEN_FP16,
titleId = R.string.frame_gen_fp16,
descriptionId = R.string.frame_gen_fp16_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW,
titleId = R.string.frame_gen_dump_flow,
descriptionId = R.string.frame_gen_dump_flow_description
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_SCREEN_LAYOUT,
@@ -928,9 +1033,16 @@ abstract class SettingsItem(
descriptionId = R.string.use_auto_stub_description
)
)
put(
StringInputSetting(
StringSetting.LOG_FILTER,
titleId = R.string.log_filter,
descriptionId = R.string.log_filter_description
)
)
put(
SpinBoxSetting(
ShortSetting.DEBUG_KNOBS,
UShortSetting.DEBUG_KNOBS,
titleId = R.string.debug_knobs,
descriptionId = R.string.debug_knobs_description,
valueHint = R.string.debug_knobs_hint,
@@ -382,7 +382,9 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
}
scSetting.setSelectedValue(value)
if (scSetting.setting.key == IntSetting.RENDERER_SCALING_FILTER.key) {
if (scSetting.setting.key == IntSetting.RENDERER_SCALING_FILTER.key ||
scSetting.setting.key == IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key
) {
settingsViewModel.setShouldReloadSettingsList(true)
}
@@ -25,8 +25,10 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.features.settings.model.UShortSetting
import org.yuzu.yuzu_emu.features.settings.model.view.*
import org.yuzu.yuzu_emu.utils.InputHandler
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.FullscreenHelper
@@ -76,6 +78,46 @@ class SettingsFragmentPresenter(
}
}
private fun addFrameGenSettings(sl: ArrayList<SettingsItem>) {
sl.apply {
if (!LosslessScalingHelper.isSupportedByGpu()) {
add(
RunnableSetting(
titleId = R.string.frame_gen_unsupported,
descriptionId = R.string.frame_gen_unsupported_description,
isRunnable = false
) {}
)
} else if (!LosslessScalingHelper.isInstalled()) {
add(
RunnableSetting(
titleId = R.string.lossless_scaling_missing,
descriptionId = R.string.lossless_scaling_missing_description,
isRunnable = false
) {}
)
}
add(BooleanSetting.RENDERER_FRAME_GEN.key)
add(IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key)
if (IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.getInt(
getNeedsGlobalForKey(IntSetting.RENDERER_FRAME_GEN_TARGET_RATE.key)
) == 0
) {
add(IntSetting.RENDERER_FRAME_GEN_MULTIPLIER.key)
}
add(IntSetting.RENDERER_FRAME_GEN_QUEUE_TARGET.key)
add(BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key)
if (!BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.getBoolean(
getNeedsGlobalForKey(BooleanSetting.RENDERER_FRAME_GEN_FLOW_SCALE_AUTO.key)
)
) {
add(IntSetting.RENDERER_FRAME_GEN_FLOW_SCALE.key)
}
add(BooleanSetting.RENDERER_FRAME_GEN_FP16.key)
}
}
private fun isSharpnessScalingFilterSelected(): Boolean {
val needsGlobal = getNeedsGlobalForKey(IntSetting.RENDERER_SCALING_FILTER.key)
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal)
@@ -120,6 +162,7 @@ class SettingsFragmentPresenter(
MenuTag.SECTION_ROOT -> addConfigSettings(sl)
MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
MenuTag.SECTION_FRAME_GEN -> addFrameGenSettings(sl)
MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl)
MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl)
MenuTag.SECTION_INPUT_OVERLAY -> addInputOverlaySettings(sl)
@@ -270,8 +313,6 @@ class SettingsFragmentPresenter(
// TODO(crueter): sub-submenus?
private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
sl.apply {
// add(IntSetting.RENDERER_NVDEC_EMULATION.key)
add(IntSetting.RENDERER_RESOLUTION.key)
add(IntSetting.RENDERER_VSYNC.key)
add(IntSetting.RENDERER_SCALING_FILTER.key)
@@ -288,6 +329,7 @@ class SettingsFragmentPresenter(
add(IntSetting.MAX_ANISOTROPY.key)
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
add(IntSetting.RENDERER_NVDEC_EMULATION.key)
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
@@ -302,7 +344,6 @@ class SettingsFragmentPresenter(
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
add(BooleanSetting.EMULATE_BGR565.key)
add(BooleanSetting.RESCALE_HACK.key)
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
add(IntSetting.ANDROID_PIPELINE_WORKERS.key)
add(BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION.key)
@@ -1282,11 +1323,12 @@ class SettingsFragmentPresenter(
add(HeaderSetting(R.string.log))
add(BooleanSetting.DEBUG_FLUSH_BY_LINE.key)
add(StringSetting.LOG_FILTER.key)
}
add(HeaderSetting(R.string.general))
add(ShortSetting.DEBUG_KNOBS.key)
add(UShortSetting.DEBUG_KNOBS.key)
add(StringSetting.PROGRAM_ARGS.key)
if (!NativeConfig.isPerGameConfigLoaded()) {
@@ -1296,6 +1338,7 @@ class SettingsFragmentPresenter(
add(BooleanSetting.DUMP_GUEST_SHADERS.key)
add(BooleanSetting.GPU_LOG_SHADER_DUMPS.key)
add(BooleanSetting.DUMP_MACROS.key)
add(BooleanSetting.RENDERER_FRAME_GEN_DUMP_FLOW.key)
add(BooleanSetting.GPU_LOG_MEMORY_TRACKING.key)
add(BooleanSetting.GPU_LOG_DRIVER_DEBUG.key)
add(IntSetting.GPU_LOG_RING_BUFFER_SIZE.key)
@@ -29,6 +29,7 @@ enum class SettingsSubscreen {
DRIVER_MANAGER,
DRIVER_FETCHER,
FREEDRENO_SETTINGS,
LOSSLESS_MANAGER,
APPLET_LAUNCHER,
INSTALLABLE,
GAME_FOLDERS,
@@ -126,6 +127,7 @@ class SettingsSubscreenActivity : AppCompatActivity() {
SettingsSubscreen.DRIVER_MANAGER -> R.id.driverManagerFragment
SettingsSubscreen.DRIVER_FETCHER -> R.id.driverFetcherFragment
SettingsSubscreen.FREEDRENO_SETTINGS -> R.id.freedrenoSettingsFragment
SettingsSubscreen.LOSSLESS_MANAGER -> R.id.losslessManagerFragment
SettingsSubscreen.APPLET_LAUNCHER -> R.id.appletLauncherFragment
SettingsSubscreen.INSTALLABLE -> R.id.installableFragment
SettingsSubscreen.GAME_FOLDERS -> R.id.gameFoldersFragment
@@ -1182,7 +1182,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
container,
IntSetting.FSR_SHARPENING_SLIDER,
minValue = 0,
maxValue = 100,
maxValue = 200,
units = "%"
)
}
@@ -369,6 +369,21 @@ class GamePropertiesFragment : Fragment() {
)
)
}
add(
SubmenuProperty(
R.string.frame_gen,
R.string.frame_gen_per_game_description,
R.drawable.ic_duck,
action = {
val action = HomeNavigationDirections.actionGlobalSettingsActivity(
args.game,
Settings.MenuTag.SECTION_FRAME_GEN
)
binding.root.findNavController().navigate(action)
}
)
)
if (GpuDriverHelper.isAdrenoGpu()) {
add(
SubmenuProperty(
@@ -44,6 +44,7 @@ import org.yuzu.yuzu_emu.ui.main.MainActivity
import org.yuzu.yuzu_emu.utils.FileUtil
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
import org.yuzu.yuzu_emu.utils.Log
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
class HomeSettingsFragment : Fragment() {
@@ -170,6 +171,24 @@ class HomeSettingsFragment : Fragment() {
)
)
}
add(
HomeSetting(
R.string.lossless_scaling,
R.string.lossless_scaling_description,
R.drawable.ic_duck,
{
val action = HomeNavigationDirections.actionGlobalSettingsSubscreenActivity(
SettingsSubscreen.LOSSLESS_MANAGER,
null
)
binding.root.findNavController().navigate(action)
},
{ true },
0,
0,
LosslessScalingHelper.statusText
)
)
add(
HomeSetting(
R.string.multiplayer,
@@ -337,6 +356,7 @@ class HomeSettingsFragment : Fragment() {
override fun onResume() {
super.onResume()
driverViewModel.updateDriverNameForGame(null)
LosslessScalingHelper.refreshStatus()
}
override fun onDestroyView() {
@@ -0,0 +1,174 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.transition.MaterialSharedAxis
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
import org.yuzu.yuzu_emu.databinding.FragmentLosslessManagerBinding
import org.yuzu.yuzu_emu.features.fetcher.SpacingItemDecoration
import org.yuzu.yuzu_emu.model.HomeSetting
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
import org.yuzu.yuzu_emu.utils.collect
class LosslessManagerFragment : Fragment() {
private var _binding: FragmentLosslessManagerBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentLosslessManagerBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.toolbarLossless.setNavigationOnClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
binding.losslessOptionsList.apply {
layoutManager =
GridLayoutManager(requireContext(), resources.getInteger(R.integer.grid_columns))
addItemDecoration(
SpacingItemDecoration(resources.getDimensionPixelSize(R.dimen.spacing_small))
)
}
LosslessScalingHelper.statusText.collect(viewLifecycleOwner) { refreshOptions() }
setInsets()
}
private fun refreshOptions() {
binding.losslessOptionsList.adapter = HomeSettingAdapter(
requireActivity() as AppCompatActivity,
viewLifecycleOwner,
buildOptions()
)
}
private fun buildOptions(): List<HomeSetting> {
val installed = LosslessScalingHelper.isInstalled()
return listOf(
HomeSetting(
if (installed) R.string.lossless_scaling_replace else R.string.lossless_scaling_install,
if (installed) {
R.string.lossless_scaling_replace_description
} else {
R.string.lossless_scaling_install_description
},
R.drawable.ic_install,
{ dllPickerLauncher.launch(arrayOf("*/*")) },
{ !NativeLibrary.isRunning() },
R.string.lossless_scaling_locked,
R.string.lossless_scaling_locked_description,
LosslessScalingHelper.statusText
),
HomeSetting(
R.string.lossless_scaling_remove,
R.string.lossless_scaling_remove_description,
R.drawable.ic_delete,
{ confirmRemoval() },
{ installed && !NativeLibrary.isRunning() },
if (installed) {
R.string.lossless_scaling_locked
} else {
R.string.lossless_scaling_remove_unavailable
},
if (installed) {
R.string.lossless_scaling_locked_description
} else {
R.string.lossless_scaling_remove_unavailable_description
}
)
)
}
private fun confirmRemoval() {
MessageDialogFragment.newInstance(
requireActivity(),
titleId = R.string.lossless_scaling_remove,
descriptionId = R.string.lossless_scaling_remove_confirmation,
positiveButtonTitleId = R.string.lossless_scaling_remove,
positiveAction = { LosslessScalingHelper.remove() },
showNegativeButton = true,
negativeAction = {}
).show(parentFragmentManager, MessageDialogFragment.TAG)
}
private val dllPickerLauncher =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result == null) {
return@registerForActivityResult
}
val resultStrings = resources.getStringArray(R.array.losslessDllResults)
ProgressDialogFragment.newInstance(
requireActivity(),
R.string.lossless_scaling_installing,
false
) { _, _ ->
val installResult = LosslessScalingHelper.install(result)
if (installResult == LosslessScalingHelper.RESULT_OK) {
getString(R.string.lossless_scaling_install_success)
} else {
MessageDialogFragment.newInstance(
titleId = R.string.lossless_scaling_install_failed,
descriptionString = resultStrings[installResult]
)
}
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun setInsets() =
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
binding.appbarLossless.updateMargins(
left = barInsets.left + cutoutInsets.left,
right = barInsets.right + cutoutInsets.right
)
binding.scrollViewLossless.updatePadding(bottom = barInsets.bottom)
binding.losslessOptionsList.updatePadding(
left = barInsets.left + cutoutInsets.left,
right = barInsets.right + cutoutInsets.right
)
windowInsets
}
}
@@ -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
@@ -42,6 +42,7 @@ import org.yuzu.yuzu_emu.model.SetupPage
import org.yuzu.yuzu_emu.model.PageState
import org.yuzu.yuzu_emu.ui.main.MainActivity
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.ViewUtils
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
@@ -202,6 +203,24 @@ class SetupFragment : Fragment() {
R.string.install_firmware_warning_help,
)
)
add(
PageButton(
R.drawable.ic_duck,
R.string.lossless_scaling,
R.string.lossless_scaling_setup_description,
{
pageButtonCallback = it
getLosslessDll.launch(arrayOf("*/*"))
},
{
if (LosslessScalingHelper.isInstalled()) {
ButtonState.BUTTON_ACTION_COMPLETE
} else {
ButtonState.BUTTON_ACTION_INCOMPLETE
}
}
)
)
add(
PageButton(
R.drawable.ic_controller,
@@ -446,6 +465,32 @@ class SetupFragment : Fragment() {
}
}
val getLosslessDll =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result == null) {
return@registerForActivityResult
}
val resultStrings = resources.getStringArray(R.array.losslessDllResults)
ProgressDialogFragment.newInstance(
requireActivity(),
R.string.lossless_scaling_installing,
false
) { _, _ ->
val installResult = LosslessScalingHelper.install(result)
if (installResult == LosslessScalingHelper.RESULT_OK) {
getString(R.string.lossless_scaling_install_success)
} else {
MessageDialogFragment.newInstance(
titleId = R.string.lossless_scaling_install_failed,
descriptionString = resultStrings[installResult]
)
}
}.apply {
onDialogComplete = { checkForButtonState.invoke() }
}.show(parentFragmentManager, ProgressDialogFragment.TAG)
}
val getGamesDirectory =
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
if (result != null) {
@@ -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
@@ -72,6 +72,18 @@ class SystemInfoDialogFragment : DialogFragment() {
val vulkanDriver = NativeLibrary.getVulkanDriverVersion()
appendLine("${getString(R.string.vulkan_driver_version)}: $vulkanDriver")
val frameGen = NativeLibrary.supportsFrameGeneration()
appendLine(
"${getString(R.string.frame_generation_support)}: " +
getString(
if (frameGen) {
R.string.frame_generation_supported
} else {
R.string.frame_generation_unsupported
}
)
)
} catch (e: Exception) {
appendLine("${getString(R.string.error_getting_emulator_info)}: ${e.message}")
}
@@ -18,6 +18,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.doOnPreDraw
import androidx.core.view.updatePadding
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
@@ -46,7 +47,6 @@ import info.debatty.java.stringsimilarity.Jaccard
import info.debatty.java.stringsimilarity.JaroWinkler
import java.util.Locale
import androidx.core.content.edit
import androidx.core.view.doOnNextLayout
class GamesFragment : Fragment() {
private var _binding: FragmentGamesBinding? = null
@@ -58,7 +58,10 @@ class GamesFragment : Fragment() {
private var originalHeaderLeftMargin: Int? = null
private var lastViewType: Int = GameAdapter.VIEW_TYPE_GRID
private var fallbackBottomInset: Int = 0
private var pendingPostReloadListSettle = false
private var pendingPostReloadListSettleGeneration = 0
private var gameListSubmitGeneration = 0
private var committedGameListSubmitGeneration = 0
companion object {
private const val SEARCH_TEXT = "SearchText"
@@ -168,10 +171,9 @@ class GamesFragment : Fragment() {
gamesViewModel.shouldScrollAfterReload.collect(viewLifecycleOwner) { shouldScroll ->
if (shouldScroll) {
binding.gridGames.post {
(binding.gridGames as? CarouselRecyclerView)?.pendingScrollAfterReload = true
gameAdapter.notifyDataSetChanged()
}
pendingPostReloadListSettle = true
pendingPostReloadListSettleGeneration = gameListSubmitGeneration
schedulePostReloadListSettle()
gamesViewModel.setShouldScrollAfterReload(false)
}
}
@@ -223,12 +225,7 @@ class GamesFragment : Fragment() {
}
else -> throw IllegalArgumentException("Invalid view type: $savedViewType")
}
if (savedViewType == GameAdapter.VIEW_TYPE_CAROUSEL) {
(binding.gridGames as? View)?.let { it -> ViewCompat.requestApplyInsets(it)}
doOnNextLayout { //Carousel: important to avoid overlap issues
(this as? CarouselRecyclerView)?.notifyLaidOut(fallbackBottomInset)
}
} else {
if (savedViewType != GameAdapter.VIEW_TYPE_CAROUSEL) {
(this as? CarouselRecyclerView)?.setupCarousel(false)
}
adapter = gameAdapter
@@ -273,11 +270,42 @@ class GamesFragment : Fragment() {
lastSearchText = currentSearchText
lastFilter = currentFilter
} else {
((binding.gridGames as? RecyclerView)?.adapter as? GameAdapter)?.submitList(games)
submitGameList(games)
gamesViewModel.setFilteredGames(games)
}
}
private fun submitGameList(games: List<Game>) {
val adapter = (binding.gridGames as? RecyclerView)?.adapter as? GameAdapter
if (adapter == null) {
schedulePostReloadListSettle()
return
}
val submitGeneration = ++gameListSubmitGeneration
adapter.submitList(games) {
if (committedGameListSubmitGeneration < submitGeneration) {
committedGameListSubmitGeneration = submitGeneration
}
schedulePostReloadListSettle()
}
}
private fun schedulePostReloadListSettle() {
if (!pendingPostReloadListSettle || _binding == null) return
binding.gridGames.doOnPreDraw {
if (!pendingPostReloadListSettle || _binding == null) return@doOnPreDraw
if (committedGameListSubmitGeneration < pendingPostReloadListSettleGeneration) {
schedulePostReloadListSettle()
return@doOnPreDraw
}
pendingPostReloadListSettle = false
(binding.gridGames as? CarouselRecyclerView)?.refreshView()
}
}
private fun setupTopView() {
binding.searchText.doOnTextChanged() { text: CharSequence?, _: Int, _: Int, _: Int ->
if (text.toString().isNotEmpty()) {
@@ -414,9 +442,7 @@ class GamesFragment : Fragment() {
val searchTerm = binding.searchText.text.toString().lowercase(Locale.getDefault())
if (searchTerm.isEmpty()) {
((binding.gridGames as? RecyclerView)?.adapter as? GameAdapter)?.submitList(
filteredList
)
submitGameList(filteredList)
gamesViewModel.setFilteredGames(filteredList)
return
}
@@ -432,7 +458,7 @@ class GamesFragment : Fragment() {
}
}.sortedByDescending { it.score }.map { it.item }
((binding.gridGames as? RecyclerView)?.adapter as? GameAdapter)?.submitList(sortedList)
submitGameList(sortedList)
gamesViewModel.setFilteredGames(sortedList)
}
@@ -557,11 +583,6 @@ class GamesFragment : Fragment() {
qlaunchButton.layoutParams = mlpQLaunch
}
val navInsets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())
val gestureInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
val bottomInset = maxOf(navInsets.bottom, gestureInsets.bottom, cutoutInsets.bottom)
fallbackBottomInset = bottomInset
(binding.gridGames as? CarouselRecyclerView)?.notifyInsetsReady(bottomInset)
windowInsets
}
}
@@ -31,6 +31,7 @@ object GameHelper {
fun getGames(): List<Game> {
val games = mutableListOf<Game>()
val gamesByProgramId = mutableMapOf<String, Game>()
val context = YuzuApplication.appContext
preferences = PreferenceManager.getDefaultSharedPreferences(context)
@@ -63,6 +64,7 @@ object GameHelper {
addGamesRecursive(
games,
gamesByProgramId,
FileUtil.listFiles(gameDirUri),
scanDepth,
mountedContainerUris
@@ -136,6 +138,7 @@ object GameHelper {
private fun addGamesRecursive(
games: MutableList<Game>,
gamesByProgramId: MutableMap<String, Game>,
files: Array<MinimalDocumentFile>,
depth: Int,
mountedContainerUris: MutableSet<String>
@@ -148,6 +151,7 @@ object GameHelper {
if (it.isDirectory) {
addGamesRecursive(
games,
gamesByProgramId,
FileUtil.listFiles(it.uri),
depth - 1,
mountedContainerUris
@@ -156,8 +160,9 @@ object GameHelper {
val extension = FileUtil.getExtension(it.uri).lowercase()
val filePath = it.uri.toString()
if (externalContentExtensions.contains(extension) &&
mountedContainerUris.add(filePath)) {
val mountedContainer = externalContentExtensions.contains(extension) &&
mountedContainerUris.add(filePath)
if (mountedContainer) {
NativeLibrary.addGameFolderFileToFilesystemProvider(filePath)
}
@@ -165,6 +170,20 @@ object GameHelper {
val game = getGame(it.uri, true, false)
if (game != null) {
games.add(game)
if (game.programId != "0") {
gamesByProgramId[game.programId] = game
}
} else if (mountedContainer) {
GameMetadata.getProgramId(filePath).toLongOrNull()?.let { programId ->
gamesByProgramId[(programId and 0x800L.inv()).toString()]
}?.let { existingGame ->
NativeLibrary.getPatchesForFile(existingGame.path, existingGame.programId)
existingGame.version = GameMetadata.getVersion(
existingGame.path,
true
)
GameIconUtils.refreshGameIcon(existingGame)
}
}
}
}
@@ -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
@@ -24,6 +27,15 @@ import coil.request.Options
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.model.Game
import java.util.Collections
import java.util.WeakHashMap
private val gameIconHashes = Collections.synchronizedMap(mutableMapOf<String, Int>())
private val gameIconTargets = Collections.synchronizedMap(WeakHashMap<ImageView, GameIconTarget>())
private fun Game.iconCacheKey(): String = "$path|$version"
private data class GameIconTarget(val game: Game, var iconHash: Int? = null)
class GameIconFetcher(
private val game: Game,
@@ -31,14 +43,15 @@ class GameIconFetcher(
) : Fetcher {
override suspend fun fetch(): FetchResult {
return DrawableResult(
drawable = decodeGameIcon(game.path)!!.toDrawable(options.context.resources),
drawable = decodeGameIcon(game)!!.toDrawable(options.context.resources),
isSampled = false,
dataSource = DataSource.DISK
)
}
private fun decodeGameIcon(uri: String): Bitmap? {
val data = GameMetadata.getIcon(uri)
private fun decodeGameIcon(game: Game): Bitmap? {
val data = GameMetadata.getIcon(game.path)
gameIconHashes[game.iconCacheKey()] = data.contentHashCode()
return BitmapFactory.decodeByteArray(
data,
0,
@@ -54,7 +67,7 @@ class GameIconFetcher(
}
class GameIconKeyer : Keyer<Game> {
override fun key(data: Game, options: Options): String = data.path
override fun key(data: Game, options: Options): String = data.iconCacheKey()
}
object GameIconUtils {
@@ -71,14 +84,58 @@ object GameIconUtils {
.build()
fun loadGameIcon(game: Game, imageView: ImageView) {
gameIconTargets[imageView] = GameIconTarget(game)
val request = ImageRequest.Builder(YuzuApplication.appContext)
.data(game)
.target(imageView)
.error(R.drawable.default_icon)
.listener(
onSuccess = { _, _ ->
val target = gameIconTargets[imageView]
if (target?.game?.iconCacheKey() == game.iconCacheKey()) {
gameIconHashes[game.iconCacheKey()]?.let {
target.iconHash = it
}
}
},
onError = { _, _ ->
gameIconTargets[imageView]?.iconHash = null
}
)
.build()
imageLoader.enqueue(request)
}
fun refreshGameIcon(game: Game) {
val targets = synchronized(gameIconTargets) {
gameIconTargets
.filterValues { it.game.path == game.path && it.game.programId == game.programId }
.keys
.toList()
}
if (targets.isEmpty()) {
return
}
val iconHash = GameMetadata.getIcon(game.path).contentHashCode()
val targetsToRefresh = targets.filter { gameIconTargets[it]?.iconHash != iconHash }
if (targetsToRefresh.isEmpty()) {
return
}
imageLoader.memoryCache?.remove(MemoryCache.Key(game.iconCacheKey()))
targetsToRefresh.forEach { imageView ->
imageView.post {
val target = gameIconTargets[imageView] ?: return@post
if (target.game.path == game.path && target.game.programId == game.programId) {
if (target.iconHash != iconHash) {
loadGameIcon(game, imageView)
}
}
}
}
}
suspend fun getGameIcon(lifecycleOwner: LifecycleOwner, game: Game): Bitmap {
val request = ImageRequest.Builder(YuzuApplication.appContext)
.data(game)
@@ -0,0 +1,77 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
package org.yuzu.yuzu_emu.utils
import android.net.Uri
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import java.io.File
object LosslessScalingHelper {
const val RESULT_OK = 0
const val RESULT_NOT_INSTALLED = 1
private val _statusText = MutableStateFlow("")
val statusText: StateFlow<String> = _statusText.asStateFlow()
private var installed: Boolean? = null
private var gpuSupported: Boolean? = null
fun isInstalled(): Boolean = installed ?: refreshStatus()
fun isSupportedByGpu(): Boolean {
val cached = gpuSupported
if (cached != null) {
return cached
}
val result = NativeLibrary.supportsFrameGeneration()
gpuSupported = result
return result
}
fun refreshStatus(): Boolean {
val result = NativeLibrary.validateLosslessDll() == RESULT_OK
installed = result
val context = YuzuApplication.appContext
_statusText.value = if (result) {
context.getString(R.string.lossless_scaling_installed)
} else {
context.getString(R.string.lossless_scaling_not_installed)
}
return result
}
fun install(source: Uri): Int {
val destination = File(NativeLibrary.getLosslessDllPath())
destination.parentFile?.mkdirs()
val copied = FileUtil.copyUriToInternalStorage(
source,
destination.parent!!,
destination.name
)
if (copied == null) {
refreshStatus()
return RESULT_NOT_INSTALLED
}
val result = NativeLibrary.prepareLosslessDll()
if (result != RESULT_OK) {
NativeLibrary.removeLosslessDll()
}
refreshStatus()
return result
}
fun remove(): Boolean {
val removed = NativeLibrary.removeLosslessDll()
refreshStatus()
return removed
}
}
@@ -80,6 +80,12 @@ object NativeConfig {
@Synchronized
external fun setShort(key: String, value: Short)
@Synchronized
external fun getUnsignedShort(key: String, needsGlobal: Boolean): Int
@Synchronized
external fun setUnsignedShort(key: String, value: Int)
@Synchronized
external fun getInt(key: String, needsGlobal: Boolean): Int
@@ -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.ui
@@ -11,12 +11,17 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.sin
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.adapters.GameAdapter
import androidx.core.view.doOnNextLayout
import androidx.core.view.ViewCompat
import org.yuzu.yuzu_emu.YuzuApplication
import androidx.preference.PreferenceManager
import androidx.core.view.WindowInsetsCompat
import org.yuzu.yuzu_emu.utils.FullscreenHelper
/**
* CarouselRecyclerView encapsulates all carousel content for the games UI.
* It manages overlapping cards, center snapping, custom drawing order,
@@ -30,10 +35,13 @@ class CarouselRecyclerView @JvmOverloads constructor(
private var overlapFactor: Float = 0f
private var overlapPx: Int = 0
private var bottomInset: Int = -1
private var bottomInset: Int = 0
private var latestWindowInsets: WindowInsetsCompat? = null
private var cardGeometryInitialized: Boolean = false
private var overlapDecoration: OverlappingDecoration? = null
private var pagerSnapHelper: PagerSnapHelper? = null
private var scalingScrollListener: OnScrollListener? = null
private var savedItemAnimator: RecyclerView.ItemAnimator? = null
companion object {
private const val CAROUSEL_CARD_SIZE_FACTOR = "CarouselCardSizeMultiplier"
@@ -42,8 +50,13 @@ class CarouselRecyclerView @JvmOverloads constructor(
private const val CAROUSEL_OVERLAP_FACTOR = "CarouselOverlapFactor"
private const val CAROUSEL_MAX_FLING_COUNT = "CarouselMaxFlingCount"
private const val CAROUSEL_FLING_MULTIPLIER = "CarouselFlingMultiplier"
private const val CAROUSEL_CARDS_SCALING_SHAPE = "CarouselCardsScalingShape"
private const val CAROUSEL_CARDS_ALPHA_SHAPE = "CarouselCardsAlphaShape"
private const val CAROUSEL_ARC_ANGLE_STEP_DEGREES = 15.0
private const val CAROUSEL_ARC_MAX_ANGLE_DEGREES = 165.0
private const val CAROUSEL_ARC_DEPTH_MAX_ANGLE_DEGREES = 85.0
private const val CAROUSEL_ARC_DEPTH_STRETCH = 5.0f
private const val CAROUSEL_ARC_X_DEPTH_FACTOR = 0.55f
private const val CAROUSEL_ARC_FADE_OUT_START_DEGREES = 60.0
private const val CAROUSEL_ARC_FADE_OUT_END_DEGREES = 95.0
const val CAROUSEL_LAST_SCROLL_POSITION = "CarouselLastScrollPosition"
const val CAROUSEL_VIEW_TYPE_PORTRAIT = "GamesViewTypePortrait"
const val CAROUSEL_VIEW_TYPE_LANDSCAPE = "GamesViewTypeLandscape"
@@ -83,6 +96,38 @@ class CarouselRecyclerView @JvmOverloads constructor(
init {
setChildrenDrawingOrderEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
latestWindowInsets = insets
updateCardGeometry()
applyCarouselPadding()
insets
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
ViewCompat.requestApplyInsets(this)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
if (w != oldw || h != oldh) {
updateCardGeometry()
applyCarouselPadding()
}
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (isCarouselMode) updateChildScalesAndAlpha()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
ViewCompat.requestApplyInsets(this)
post { updateCardGeometry() }
}
}
override fun setAdapter(adapter: Adapter<*>?) {
@@ -95,6 +140,8 @@ class CarouselRecyclerView @JvmOverloads constructor(
super.setAdapter(adapter)
(adapter as? GameAdapter)?.registerAdapterDataObserver(carouselAdapterObserver)
updateCardGeometry()
applyCarouselPadding()
}
private fun calculateCenter(width: Int, paddingStart: Int, paddingEnd: Int): Int {
@@ -160,46 +207,52 @@ class CarouselRecyclerView @JvmOverloads constructor(
}
}
fun shapingFunction(x: Float, option: Int = 0): Float {
return when (option) {
0 -> 1f // Off
1 -> 1f - x // linear descending
2 -> (1f - x) * (1f - x) // Ease out
3 -> if (x < 0.05f) 1f else (1f - x) * 0.8f
4 -> kotlin.math.cos(x * Math.PI).toFloat() // Cosine
5 -> kotlin.math.cos((1.5f * x).coerceIn(0f, 1f) * Math.PI).toFloat() // Cosine 1.5x trimmed
else -> 1f // Default to Off
}
}
fun updateChildScaleAndAlphaForPosition(child: View) {
val cardSize = (adapter as? GameAdapter ?: return).cardSize
val position = getChildViewHolder(child).bindingAdapterPosition
if (position == RecyclerView.NO_POSITION || cardSize <= 0) {
return // No valid position or card size
}
child.layoutParams.width = cardSize
child.layoutParams.height = cardSize
val layoutParams = child.layoutParams
if (layoutParams.width != cardSize || layoutParams.height != cardSize) {
child.layoutParams = layoutParams.apply {
width = cardSize
height = cardSize
}
}
val signedDistance = getChildDistanceToCenter(child)
val itemStep = (cardSize - overlapPx).toFloat().coerceAtLeast(1f)
val angleStep = Math.toRadians(CAROUSEL_ARC_ANGLE_STEP_DEGREES).toFloat()
val maxAngle = Math.toRadians(CAROUSEL_ARC_MAX_ANGLE_DEGREES).toFloat()
val depthMaxAngle = Math.toRadians(CAROUSEL_ARC_DEPTH_MAX_ANGLE_DEGREES).toFloat()
val fadeOutStartAngle = Math.toRadians(CAROUSEL_ARC_FADE_OUT_START_DEGREES).toFloat()
val fadeOutEndAngle = Math.toRadians(CAROUSEL_ARC_FADE_OUT_END_DEGREES).toFloat()
val angle = (signedDistance / itemStep * angleStep).coerceIn(-maxAngle, maxAngle)
val arcRadius = itemStep / angleStep
val arcX = sin(angle) * arcRadius
val absoluteAngle = abs(angle)
val rawDepthInput = ((1f - cos(absoluteAngle)) / (1f - cos(depthMaxAngle)))
.coerceIn(0f, 1f)
val easedDepthTail = Math.pow(
(1f - rawDepthInput).toDouble(),
CAROUSEL_ARC_DEPTH_STRETCH.toDouble()
).toFloat()
val depthInput = (1f - easedDepthTail).coerceIn(0f, 1f)
val projectedArcX = arcX * (1f - rawDepthInput * CAROUSEL_ARC_X_DEPTH_FACTOR)
child.animate().cancel()
child.translationX = projectedArcX - signedDistance
val center = getRecyclerViewCenter()
val distance = abs(getChildDistanceToCenter(child))
val internalBorderScale = resources.getFraction(R.fraction.carousel_bordercards_scale, 1, 1)
val borderScale = preferences.getFloat(CAROUSEL_BORDERCARDS_SCALE, internalBorderScale).coerceIn(
0f,
1f
)
val shapeInput = (distance / center).coerceIn(0f, 1f)
val internalShapeSetting = resources.getInteger(R.integer.carousel_cards_scaling_shape)
val scalingShapeSetting = preferences.getInt(
CAROUSEL_CARDS_SCALING_SHAPE,
internalShapeSetting
)
val shapedScaling = shapingFunction(shapeInput, scalingShapeSetting)
val shapedScaling = 1f - depthInput
val scale = (borderScale + (1f - borderScale) * shapedScaling).coerceIn(0f, 1f)
val maxDistance = width / 2f
val alphaInput = (distance / maxDistance).coerceIn(0f, 1f)
val internalBordersAlpha = resources.getFraction(
R.fraction.carousel_bordercards_alpha,
1,
@@ -209,15 +262,12 @@ class CarouselRecyclerView @JvmOverloads constructor(
0f,
1f
)
val internalAlphaShapeSetting = resources.getInteger(R.integer.carousel_cards_alpha_shape)
val alphaShapeSetting = preferences.getInt(
CAROUSEL_CARDS_ALPHA_SHAPE,
internalAlphaShapeSetting
)
val shapedAlpha = shapingFunction(alphaInput, alphaShapeSetting)
val alpha = (borderAlpha + (1f - borderAlpha) * shapedAlpha).coerceIn(0f, 1f)
val shapedAlpha = cos(depthInput * Math.PI).toFloat()
val baseAlpha = (borderAlpha + (1f - borderAlpha) * shapedAlpha).coerceIn(0f, 1f)
val rearPresence = (1f - (absoluteAngle - fadeOutStartAngle) /
(fadeOutEndAngle - fadeOutStartAngle)).coerceIn(0f, 1f)
val alpha = (baseAlpha * rearPresence).coerceIn(0f, 1f)
child.animate().cancel()
child.alpha = alpha
child.scaleX = scale
child.scaleY = scale
@@ -242,38 +292,71 @@ class CarouselRecyclerView @JvmOverloads constructor(
}
}
fun notifyInsetsReady(newBottomInset: Int) {
if (bottomInset != newBottomInset) {
bottomInset = newBottomInset
}
if (isCarouselMode) {
setupCarousel(true)
private fun resolveBottomInset(windowInsets: WindowInsetsCompat): Int {
val navigationBottom = if (FullscreenHelper.isFullscreenEnabled(context)) {
0
} else {
setupCarousel(false)
windowInsets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.navigationBars()).bottom
}
val gestureInsets = windowInsets.getInsetsIgnoringVisibility(
WindowInsetsCompat.Type.systemGestures()
)
val cutoutInsets = windowInsets.getInsetsIgnoringVisibility(
WindowInsetsCompat.Type.displayCutout()
)
return maxOf(navigationBottom, gestureInsets.bottom, cutoutInsets.bottom)
}
fun notifyLaidOut(fallBackBottomInset: Int) {
if (bottomInset < 0) bottomInset = fallBackBottomInset
var gameAdapter = adapter as? GameAdapter ?: return
var newCardSize = cardSize(bottomInset)
if (gameAdapter.cardSize != newCardSize) {
gameAdapter.setCardSize(newCardSize)
}
private fun updateCardGeometry() {
if (!isCarouselMode || height <= 0) return
if (isCarouselMode) {
setupCarousel(true)
}
}
val gameAdapter = adapter as? GameAdapter ?: return
val windowInsets = latestWindowInsets ?: ViewCompat.getRootWindowInsets(this) ?: return
fun cardSize(bottomInset: Int): Int {
if (cardGeometryInitialized && !hasWindowFocus()) return
val newBottomInset = resolveBottomInset(windowInsets).coerceIn(0, height)
val internalFactor = resources.getFraction(R.fraction.carousel_card_size_factor, 1, 1)
val userFactor = preferences.getFloat(CAROUSEL_CARD_SIZE_FACTOR, internalFactor).coerceIn(
0f,
1f
)
return (userFactor * (height - bottomInset)).toInt()
val screenWidth = resources.displayMetrics.widthPixels.toFloat()
val screenHeight = resources.displayMetrics.heightPixels.toFloat()
val aspectFactor = ((screenWidth / screenHeight) / (20f / 9f))
.pow(0.75f)
.coerceIn(0.5f, 1f)
val newCardSize = minOf(
(height * userFactor).toInt(),
height - newBottomInset,
(height * aspectFactor).toInt()
)
if (newCardSize <= 0) return
val insetChanged = bottomInset != newBottomInset
val cardSizeChanged = gameAdapter.cardSize != newCardSize
bottomInset = newBottomInset
cardGeometryInitialized = true
if (cardSizeChanged) gameAdapter.setCardSize(newCardSize)
if (insetChanged || cardSizeChanged) setupCarousel(true)
}
private fun applyCarouselPadding() {
if (!isCarouselMode) return
val gameAdapter = adapter as? GameAdapter ?: return
val cardSize = gameAdapter.cardSize
if (cardSize <= 0 || bottomInset < 0) return
val topPadding = ((height - bottomInset - cardSize) / 2).coerceAtLeast(0)
val sidePadding = (width - cardSize) / 2
if (paddingLeft != sidePadding || paddingTop != topPadding ||
paddingRight != sidePadding || paddingBottom != 0
) {
setPadding(sidePadding, topPadding, sidePadding, 0)
}
clipToPadding = false
}
fun setupCarousel(enabled: Boolean) {
@@ -282,6 +365,13 @@ class CarouselRecyclerView @JvmOverloads constructor(
if (gameAdapter.cardSize == 0) return
if (bottomInset < 0) return
itemAnimator?.let {
if (savedItemAnimator == null) {
savedItemAnimator = it
}
itemAnimator = null
}
useCustomDrawingOrder = true
val cardSize = gameAdapter.cardSize
@@ -295,9 +385,6 @@ class CarouselRecyclerView @JvmOverloads constructor(
internalFlingMultiplier
).coerceIn(1f, 5f)
// Detach SnapHelper during setup
pagerSnapHelper?.attachToRecyclerView(null)
// Add overlap decoration if not present
if (overlapDecoration == null) {
overlapDecoration = OverlappingDecoration(overlapPx)
@@ -315,12 +402,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
addOnScrollListener(scalingScrollListener!!)
}
if (cardSize > 0) {
val topPadding = ((height - bottomInset - cardSize) / 2).coerceAtLeast(0) // Center vertically
val sidePadding = (width - cardSize) / 2 // Center first/last card
setPadding(sidePadding, topPadding, sidePadding, 0)
clipToPadding = false
}
applyCarouselPadding()
if (pagerSnapHelper == null) {
pagerSnapHelper = CenterPagerSnapHelper()
@@ -336,6 +418,13 @@ class CarouselRecyclerView @JvmOverloads constructor(
// Detach PagerSnapHelper
pagerSnapHelper?.attachToRecyclerView(null)
pagerSnapHelper = null
savedItemAnimator?.let {
if (itemAnimator == null) {
itemAnimator = it
}
savedItemAnimator = null
}
cardGeometryInitialized = false
useCustomDrawingOrder = false
// Reset padding and fling
setPadding(0, 0, 0, 0)
@@ -344,6 +433,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
// Reset scaling
for (i in 0 until childCount) {
val child = getChildAt(i)
child?.translationX = 0f
child?.scaleX = 1f
child?.scaleY = 1f
child?.alpha = 1f
@@ -33,8 +33,8 @@ void AndroidConfig::SaveAllValues() {
}
void AndroidConfig::ReadAndroidValues() {
ReadAndroidUIValues();
if (global) {
ReadAndroidUIValues();
ReadUIValues();
BeginGroup(Settings::TranslateCategory(Settings::Category::DataStorage));
Settings::values.ext_content_from_game_dirs = ReadBooleanSetting(
@@ -223,8 +223,8 @@ void AndroidConfig::ReadAndroidControlValues() {
}
void AndroidConfig::SaveAndroidValues() {
SaveAndroidUIValues();
if (global) {
SaveAndroidUIValues();
SaveUIValues();
SaveOverlayValues();
}
@@ -147,7 +147,7 @@ namespace AndroidSettings {
&show_performance_overlay};
Settings::Setting<s32> pipeline_worker_count{linkage, 4, "pipeline_worker_count",
Settings::SwitchableSetting<s32> pipeline_worker_count{linkage, 2, "pipeline_worker_count",
Settings::Category::Android,
Settings::Specialization::Default,
true,
@@ -124,9 +124,18 @@ float EmuWindow_Android::GetFrameTimeVerifiedHint() const {
return QuantizeFrameRateHint(verified_rate);
}
float EmuWindow_Android::GetPresentedFrameMultiplier() {
if (!Settings::values.frame_gen.GetValue()) {
return 1.0f;
}
return static_cast<float>(std::clamp<u32>(Settings::values.frame_gen_multiplier.GetValue(), 2, 4));
}
float EmuWindow_Android::GetFrameRateHint() const {
const float observed_rate = std::clamp(m_smoothed_present_rate, 0.0f, 240.0f);
const float frame_time_verified_hint = GetFrameTimeVerifiedHint();
const float presented_multiplier = GetPresentedFrameMultiplier();
const float observed_rate =
std::clamp(m_smoothed_present_rate * presented_multiplier, 0.0f, 240.0f);
const float frame_time_verified_hint = GetFrameTimeVerifiedHint() * presented_multiplier;
if (m_last_frame_rate_hint > 0.0f && observed_rate > 0.0f) {
const float tolerance = std::max(m_last_frame_rate_hint * 0.12f, 4.0f);
@@ -150,9 +159,9 @@ float EmuWindow_Android::GetFrameRateHint() const {
return frame_time_verified_hint;
}
constexpr float NominalFrameRate = 60.0f;
const float nominal_rate = 60.0f * presented_multiplier;
if (!Settings::values.use_speed_limit.GetValue()) {
return NominalFrameRate;
return QuantizeFrameRateHint(nominal_rate);
}
const u16 speed_limit = Settings::SpeedLimit();
@@ -161,7 +170,7 @@ float EmuWindow_Android::GetFrameRateHint() const {
}
const float speed_limited_rate =
NominalFrameRate * (static_cast<float>(std::min<u16>(speed_limit, 100)) / 100.0f);
nominal_rate * (static_cast<float>(std::min<u16>(speed_limit, 100)) / 100.0f);
return QuantizeFrameRateHint(speed_limited_rate);
}
@@ -61,6 +61,7 @@ private:
void UpdateObservedFrameRate();
[[nodiscard]] float GetFrameRateHint() const;
[[nodiscard]] float GetFrameTimeVerifiedHint() const;
[[nodiscard]] static float GetPresentedFrameMultiplier();
[[nodiscard]] static float QuantizeFrameRateHint(float frame_rate);
float m_window_width{};
@@ -20,7 +20,7 @@ struct RomMetadata {
std::vector<u8> icon;
bool isHomebrew;
};
static ankerl::unordered_dense::map<std::string, RomMetadata> m_rom_metadata_cache;
static ::Common::unordered_map<std::string, RomMetadata> m_rom_metadata_cache;
static RomMetadata CacheRomMetadata(const std::string& path) {
auto& instance = EmulationSession::GetInstance();
+153 -7
View File
@@ -44,6 +44,7 @@ extern "C" {
#include "common/android/android_common.h"
#include "common/android/id_cache.h"
#include "common/dynamic_library.h"
#include "common/fs/fs_util.h"
#include "common/fs/path_util.h"
#include "common/logging.h"
#include "common/scm_rev.h"
@@ -75,6 +76,7 @@ extern "C" {
#include "core/frontend/applets/software_keyboard.h"
#include "core/frontend/applets/web_browser.h"
#include "common/android/applets/web_browser.h"
#include "core/file_sys/common_funcs.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/frontend/applets.h"
#include "core/hle/service/filesystem/filesystem.h"
@@ -90,6 +92,7 @@ extern "C" {
#include "hid_core/hid_types.h"
#include "input_common/drivers/virtual_amiibo.h"
#include "jni/native.h"
#include "video_core/frame_gen/lossless_dll.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "video_core/capture.h"
@@ -309,11 +312,23 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
ConfigureFilesystemProvider(filepath);
// Load the ROM.
const u64 previous_program_id =
program_index != 0 && m_next_program_id.load() >
static_cast<u64>(Service::AM::AppletProgramId::MaxProgramId)
? m_next_program_id.load()
: 0;
Service::AM::FrontendAppletParameters params{
.program_id = previous_program_id,
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
: Service::AM::LaunchType::ApplicationInitiated,
.program_index = static_cast<s32>(program_index),
.previous_program_index =
previous_program_id != 0
? static_cast<s32>(previous_program_id -
FileSys::GetBaseTitleID(previous_program_id))
: -1,
};
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
@@ -326,8 +341,12 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
m_system.GetCpuManager().OnGpuReady();
m_system.RegisterExitCallback([&] { HaltEmulation(); });
m_system.RegisterApplicationChangedCallback(
[&](u64 changed_program_id) { RequestDiskShaderCacheReload(changed_program_id); });
// Register an ExecuteProgram callback such that Core can execute a sub-program
m_system.RegisterExecuteProgramCallback([&](std::size_t program_index_) {
m_next_program_id = m_system.GetApplicationProcessProgramID();
m_next_program_index = program_index_;
EmulationSession::GetInstance().HaltEmulation();
});
@@ -405,20 +424,58 @@ void EmulationSession::RunEmulation() {
}
while (true) {
std::optional<u64> reload_title;
{
[[maybe_unused]] std::unique_lock lock(m_mutex);
if (m_cv.wait_for(lock, std::chrono::milliseconds(800),
[&]() { return !m_is_running; })) {
// Emulation halted.
break;
if (m_cv.wait_for(lock, std::chrono::milliseconds(800), [&]() {
return !m_is_running || m_pending_shader_cache_title.has_value();
})) {
if (!m_is_running) {
break;
}
reload_title = std::exchange(m_pending_shader_cache_title, std::nullopt);
}
}
if (reload_title.has_value())
ReloadDiskShaderCache(*reload_title);
}
// Reset current applet ID.
m_applet_id = static_cast<int>(Service::AM::AppletId::Application);
}
void EmulationSession::RequestDiskShaderCacheReload(u64 program_id) {
{
std::scoped_lock lock(m_mutex);
m_pending_shader_cache_title = program_id;
}
m_cv.notify_one();
}
void EmulationSession::ReloadDiskShaderCache(u64 program_id) {
if (!Settings::values.use_disk_shader_cache.GetValue())
return;
LOG_INFO(Frontend, "Reloading disk shader cache for {:016X}", program_id);
const bool was_paused = m_is_paused;
m_system.Pause();
m_system.GPU().WaitForIdle();
m_system.GPU().ObtainContext();
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
m_system.Renderer().ReadRasterizer()->LoadDiskResources(program_id, std::stop_token{},
LoadDiskCacheProgress);
LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
m_system.GPU().ReleaseContext();
if (!was_paused)
m_system.Run();
}
Common::Android::SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() {
return m_software_keyboard;
}
@@ -998,7 +1055,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject
FILE* f = std::fopen(CPUINFO_PATH, "r");
if (!f) return Common::Android::ToJString(env, result);
char buf[512];
char buf[4096];
if (f) {
std::set<std::string> feature_set;
@@ -1029,7 +1086,13 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject
bool has_dotprod = feature_set.count("asimddp") || feature_set.count("dotprod");
bool has_i8mm = feature_set.count("i8mm");
bool has_bf16 = feature_set.count("bf16");
bool has_fp16 = feature_set.count("fphp") || feature_set.count("asimdhp");
bool has_atomics = feature_set.count("atomics") || feature_set.count("lse");
bool has_lse2 = feature_set.count("uscat");
bool has_rcpc = feature_set.count("lrcpc");
bool has_rcpc2 = feature_set.count("ilrcpc");
bool has_flagm = feature_set.count("flagm");
bool has_flagm2 = feature_set.count("flagm2");
std::string features;
if (has_neon || has_fp) {
@@ -1037,6 +1100,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject
if (has_dotprod) features += "+DP";
if (has_i8mm) features += "+I8MM";
if (has_bf16) features += "+BF16";
if (has_fp16) features += "+FP16";
}
if (has_sve) {
@@ -1053,6 +1117,19 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuSummary(JNIEnv* env, jobject
if (has_atomics) {
if (!features.empty()) features += " | ";
features += "LSE";
if (has_lse2) features += "2";
}
if (has_rcpc) {
if (!features.empty()) features += " | ";
features += "RCpc";
if (has_rcpc2) features += "2";
}
if (has_flagm) {
if (!features.empty()) features += " | ";
features += "FlagM";
if (has_flagm2) features += "2";
}
if (!features.empty()) {
@@ -1090,6 +1167,34 @@ VkPhysicalDeviceProperties GetVulkanDeviceProperties() {
const Vulkan::vk::PhysicalDevice physical_device(physical_devices[0], dld);
return physical_device.GetProperties();
}
bool GetVulkanMemoryModelSupport() {
Common::DynamicLibrary library;
if (!library.Open("libvulkan.so")) {
return false;
}
Vulkan::vk::InstanceDispatch dld;
const auto instance = Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_1);
const auto physical_devices = instance.EnumeratePhysicalDevices();
if (physical_devices.empty()) {
return false;
}
const Vulkan::vk::PhysicalDevice physical_device(physical_devices[0], dld);
VkPhysicalDeviceVulkanMemoryModelFeatures memory_model{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES,
.pNext = nullptr,
};
VkPhysicalDeviceFeatures2 features{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
.pNext = &memory_model,
};
physical_device.GetFeatures2(features);
return memory_model.vulkanMemoryModel == VK_TRUE;
}
} // namespace
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanDriverVersion(JNIEnv* env, jobject jobj) {
@@ -1165,6 +1270,14 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getVulkanApiVersion(JNIEnv* env, j
}
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_supportsFrameGeneration(JNIEnv* env, jobject jobj) {
try {
return static_cast<jboolean>(GetVulkanMemoryModelSupport());
} catch (...) {
return static_cast<jboolean>(false);
}
}
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGpuModel(JNIEnv* env, jobject jobj) {
const auto props = GetVulkanDeviceProperties();
if (props.deviceID == 0) {
@@ -1187,8 +1300,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_refreshThreadPolicies(JNIEnv* env, jo
Common::RefreshThreadPolicies();
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_getDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
return static_cast<jboolean>(Settings::getDebugKnobAt(static_cast<u8>(index)));
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_GetDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
return static_cast<jboolean>(Settings::GetDebugKnobAt(static_cast<u8>(index)));
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
@@ -1390,6 +1503,39 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_installKeys(JNIEnv* env, jclass clazz
return static_cast<int>(FirmwareManager::InstallKeys(path, ext));
}
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getLosslessDllPath(JNIEnv* env, jclass clazz) {
#ifdef HAS_LSFG
const auto path = VideoCore::FrameGen::GetLosslessDllPath();
return Common::Android::ToJString(env, Common::FS::PathToUTF8String(path));
#else
return Common::Android::ToJString(env, "");
#endif
}
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_validateLosslessDll(JNIEnv* env, jclass clazz) {
#ifdef HAS_LSFG
return static_cast<jint>(VideoCore::FrameGen::GetInstalledLosslessStatus());
#else
return static_cast<jint>(VideoCore::FrameGen::LosslessStatus::NotInstalled);
#endif
}
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_prepareLosslessDll(JNIEnv* env, jclass clazz) {
#ifdef HAS_LSFG
return static_cast<jint>(VideoCore::FrameGen::BuildShaderCache());
#else
return static_cast<jint>(VideoCore::FrameGen::LosslessStatus::NotInstalled);
#endif
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_removeLosslessDll(JNIEnv* env, jclass clazz) {
#ifdef HAS_LSFG
return static_cast<jboolean>(VideoCore::FrameGen::RemoveInstalledLosslessDll());
#else
return static_cast<jboolean>(false);
#endif
}
jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj,
jstring jpath,
jstring jprogramId) {
+6
View File
@@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <optional>
#include <android/native_window_jni.h>
#include "common/android/applets/software_keyboard.h"
#include "core/core.h"
@@ -44,6 +46,7 @@ public:
void HaltEmulation();
void RunEmulation();
void ShutdownEmulation();
void RequestDiskShaderCacheReload(u64 program_id);
const Core::PerfStatsResults& PerfStats();
int ShadersBuilding();
@@ -65,6 +68,7 @@ private:
static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
static void OnEmulationStopped(Core::SystemResultStatus result);
static void ChangeProgram(std::size_t program_index);
void ReloadDiskShaderCache(u64 program_id);
private:
// Window management
@@ -83,6 +87,7 @@ private:
Common::Android::SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
int m_applet_id{1};
std::optional<u64> m_pending_shader_cache_title;
// GPU driver parameters
std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
@@ -93,4 +98,5 @@ private:
// Program index for next boot
std::atomic<s32> m_next_program_index = -1;
std::atomic<u64> m_next_program_id = 0;
};
@@ -130,6 +130,25 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setShort(JNIEnv* env, jobject ob
setting->SetValue(value);
}
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getUnsignedShort(JNIEnv* env, jobject obj,
jstring jkey,
jboolean needGlobal) {
auto setting = getSetting<u16>(env, jkey);
if (setting == nullptr) {
return -1;
}
return static_cast<jint>(setting->GetValue(static_cast<bool>(needGlobal)));
}
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setUnsignedShort(JNIEnv* env, jobject obj,
jstring jkey, jint value) {
auto setting = getSetting<u16>(env, jkey);
if (setting == nullptr) {
return;
}
setting->SetValue(static_cast<u16>(value));
}
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getInt(JNIEnv* env, jobject obj, jstring jkey,
jboolean needGlobal) {
auto setting = getSetting<int>(env, jkey);
@@ -21,7 +21,7 @@
#include "input_common/drivers/virtual_gamepad.h"
#include "native.h"
ankerl::unordered_dense::map<std::string, std::unique_ptr<AndroidConfig>> map_profiles;
::Common::unordered_map<std::string, std::unique_ptr<AndroidConfig>> map_profiles;
bool IsHandheldOnly() {
const auto npad_style_set =
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="?attr/colorControlHighlight" />
<item android:state_focused="true" android:color="@android:color/transparent" />
<item android:state_selected="true" android:color="@android:color/transparent" />
<item android:state_hovered="true" android:color="@android:color/transparent" />
<item android:color="@android:color/transparent" />
</selector>
@@ -0,0 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M11,10.6a8,5.2 0 1,0 0,10.4a8,5.2 0 1,0 0,-10.4z" />
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M4.6,12.6L0.8,10.2L3.2,15.5z" />
<path
android:fillColor="?attr/colorControlNormal"
android:fillType="evenOdd"
android:pathData="M15.3,3.5a4,4 0 1,0 0,8a4,4 0 1,0 0,-8zM16.6,4.9a1,1 0 1,0 0,2a1,1 0 1,0 0,-2z" />
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M18.6,6.5L23.2,7.8L18.6,9.3z" />
</vector>
@@ -10,6 +10,7 @@
android:clipChildren="true"
android:layout_margin="0dp"
app:cardBackgroundColor="@color/eden_card_background"
app:rippleColor="@color/game_card_ripple"
app:strokeWidth="1dp"
app:strokeColor="@color/eden_border">
@@ -11,6 +11,7 @@
app:cardCornerRadius="16dp"
app:cardPreventCornerOverlap="true"
android:clipChildren="true"
app:rippleColor="@color/game_card_ripple"
android:layout_margin="4dp">
<androidx.constraintlayout.widget.ConstraintLayout
@@ -22,6 +22,7 @@
android:focusable="true"
android:transitionName="card_game"
app:cardCornerRadius="16dp"
app:rippleColor="@color/game_card_ripple"
android:foreground="@color/eden_border_gradient_start">
<androidx.constraintlayout.widget.ConstraintLayout
@@ -22,6 +22,7 @@
android:focusable="true"
android:transitionName="card_game_compact"
app:cardCornerRadius="16dp"
app:rippleColor="@color/game_card_ripple"
android:foreground="@color/eden_border_gradient_start">
<androidx.constraintlayout.widget.ConstraintLayout
@@ -12,6 +12,7 @@
app:cardCornerRadius="16dp"
app:cardElevation="0dp"
app:cardBackgroundColor="@android:color/transparent"
app:rippleColor="@color/game_card_ripple"
app:strokeWidth="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_lossless"
style="@style/Widget.Eden.TransparentTopAppBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:touchscreenBlocksFocus="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_lossless"
style="@style/Widget.Eden.TransparentTopToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:touchscreenBlocksFocus="false"
app:navigationIcon="@drawable/ic_back"
app:title="@string/lossless_scaling" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_view_lossless"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@android:color/transparent"
android:clipToPadding="false"
android:defaultFocusHighlightEnabled="false"
android:fadeScrollbars="false"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/appbar_lossless">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingTop="16dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lossless_options_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:nestedScrollingEnabled="false" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

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