Compare commits

...

33 commits

Author SHA1 Message Date
xbzk
c864f08b62 [shader_recompiler] IPA perspective-inject extended to legacy attrs + generic fixed check made vector-level 2026-06-02 18:10:51 -03:00
xbzk
17eb266d93 [shader_env] add termination detection for MESA nv50_ir like homebrews 2026-06-02 18:10:44 -03:00
xbzk
0f0adc8872 [fsp] silence annoying GetFileTimeStampRaw reminder 2026-06-02 18:08:28 -03:00
lizzie
5027aecf77
[vk] handle mali/adreno5xx driver bug returning VK_INCOMPLETE on graphics pipeline creation (#3383)
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3383
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-06-02 21:57:23 +02:00
crueter
f39e985434
[cmake] Link to UniformTypeIdentifiers framework on macOS (#4046)
Needed for local LLVM builds

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4046
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-06-02 21:40:51 +02:00
Eden CI
f8f5a9b1a2
[dist, android] Update translations from Transifex for Jun 02 (#4051)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Automatic translation update for Jun 02

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4051
2026-06-02 16:25:06 +02:00
crueter
a8047d3b12
[cmake] Fix OpenSSL flaky build by using a CMake script (#4047)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Something weird is happening with the CI that causes frequent build errors. For reasons I am not entirely certain of, Ninja fails to properly spawn a POSIX shell instance during the Make phase.

More investigation is in order, but for now fix it with the grand power of shelling out to CMake script

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4047
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-06-02 07:02:31 +02:00
crueter
cc8451f764
[desktop] Rework game list to use MVP architecture (#4042)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Closes #3480

moves the game list model/worker/private stuff to qt_common for later
use in QML

- `qt_common/game_list/model.{cpp,h}` is the model
- `yuzu/game/game_{grid,tree}.*` are the views
- `yuzu/game/game_list.cpp` is the presenter

This was done very lazily in a manner that "works" while largely
maintaining existing structure as much as possible. Most of it is
copy-paste, with some bonus reworks/cleanups thrown in.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4042
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-06-02 04:08:24 +02:00
crueter
27189f39d2
[desktop] Prefer extracred folder name over zip name for non-Atmosphere zip mods (#4043)
e.g. Serfrost's Defogger will now be named "Serfrosts Defogger" by
default, instead of "serfrosts_base_defogger_v2-4"

Note that for atmosphere mods it still uses the zip folder name, since otherwise their default name will just be the game's Title ID.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4043
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-06-02 04:08:09 +02:00
crueter
683e6249c3
[cmake] Allow building OpenSSL from source (#4032)
If YUZU_USE_BUNDLED_OPENSSL is off and OpenSSL is *not* installed to the
system, pulls in OpenSSL and Jimmy Park's CMake wrapper, then configures + builds from source.

Some patches were made on top of OpenSSL and openssl-cmake:
- USE_CCACHE is respected from UseCcache.cmake
- CXX/CFLAGS are passed from CMake to the configure script, which sends
  those to the compiler
- Uses a bundled cert.h akin to the bundled OpenSSL build

Closes #3614

~~Before merge: remove verbose stuff~~ actually useful so nvm

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4032
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-06-02 03:40:28 +02:00
crueter
eaece15dbd
[svc] Stub BreakDebugProcess (#4044)
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4044
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-06-02 03:33:38 +02:00
xbzk
8e5419209c
[video,buffer] rewrite storagebufferbinding size() lambda to be full data driven instead of cbuf_index based (#4041)
fixes an yxzx era bug where eden assumed NVN-style packed SSBO descriptors (u64 gpu_addr followed by size) only happen in cbuf_index == 0.

Mega Man Star Force Collection proves that assumption is false. It has an unbiased/global-memory SSBO descriptor in cbuf_index == 3, offsets 0x100/0x300, but the descriptor still appears to be { address, size }.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4041
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-06-02 03:31:59 +02:00
lizzie
8fac95dcc0
[vk] Fix regressions introduced by #3997 w.r.t to marked stages for pipeline barriers (#4037)
evil barriers :)

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4037
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-06-02 01:28:39 +02:00
crueter
706a3d0764
[cmake] Disable no-cast-function-type-mismatch on Clang 19 (#4038)
Suppresses this annoying warning during Android builds

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4038
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-06-02 01:28:16 +02:00
CamilleLaVey
3d19743d95
[vulkan] Fix regressions found in last stable release (#3953)
This PR aims to fix some regressions found in the latest release 0.2.0, which were a bunch of constant crashes/ random on certain Android devices with issues with the PiP configuration, addressing some problems founds for AMD after the maintenance of 2nd Global Vulkan Maintenance.

-> Fixes Final Fantasy Tactics on AMD (no longer requires of generic bits to work "all commands bit")
-> Fixes some performance regressions on android due to the Tomodachi fix applied globally as common behavior (#3898, #3900)
-> Fixes blittering of screen found on ARM Windows devices and QCOM stock drivers (Android and ARM Windows) related to Mario Kart 8 Deluxe strange blittering in races, caused by a strange race condition with the ResetQueryPool and mostly the workaround for presync
-> Fixes issues on Luigi's Mansion 3 issue where the pause screen became black on AMD due to the early reset of queries.
-> Fixes crashes on Mario Party Jamboree for AMD/ Nvidia.
-> Keeps previous fixes related to crashes on AMD with other games such as Astral Chain, Fire Emblem Three Houses and Xenoblade 3 based on the lack of access to vertex fragment replaced with generic flags.
-> Fixes TOTK RADV skybox lighting.

--------
Credits:
@melod-y
@Gidoly
@MaranBr
@AlexWolff
@Lizzie

And all the people who contributed into the reporting issues/ helping with the bisect.

Co-authored-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3953
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-06-02 01:06:12 +02:00
crueter
bd2d344040
[desktop] Restore metal layer search (#4033)
Some checks failed
tx-src / sources (push) Has been cancelled
Check Strings / check-strings (push) Has been cancelled
This was cut out in #3916 by accident.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4033
2026-05-31 04:19:49 +02:00
lizzie
5f4a286046
[dynarmic] cleanup duplicate code and reimpls of std::* bit stuff (#4017)
A bit of a minor cleanup
- std::rotr instead of mcl::bit::rotate_right
- std::rotl likewise
- std::popcount instaed of "count ones"
- use ConvertRoundingModeToX64Immediate where appropiate
- std integral

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4017
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-31 04:18:12 +02:00
crueter
b7fcec4985
[desktop] Increase rlimit on UNIX/Apple (#4030)
Sets max open fd limit to 8192 on non-windows platforms (or bounds it to
the system hard limit). Complement to the previous VFS PR.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4030
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-05-31 04:13:56 +02:00
MaranBr
0473747f94
[am] Fix application state notification (#4027)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
This fixed issues in Mario Kart 8 multiplayer where the native controller applet would pop up, then once A was pressed and it exited, it would freeze the game but music would continue playing.

The issue was that UpdateRequestedFocusState() updates the focus state but never sets m_has_focus_state_changed for applications. Since ShouldSignalSystemEvent() checks that flag for applications, they never receive FocusStateChanged messages when LLE library applets exit. The game keeps running (hence the music) but is stuck waiting for a focus notification that never arrives. HLE applets aren't affected because their dummy process has is_process_running=false, so the game is never considered obscured in the first place.

Credits: [davidcollini](https://github.com/davidcollini)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4027
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-31 03:55:12 +02:00
lizzie
23bb909bc9
[audio_core] fix OOB copy when silencing channel on shutdown (#3969)
when shutting down the emulator will silence any remaining audio from the output buffer
however this is for some reason stored in an array instead of being a simple memset
additionally, said array can be small enough (`frame_size_bytes > silence.size()`) to cause a funky noise to play at the end

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3969
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-31 02:38:26 +02:00
lizzie
e94ac63a5e
[common/thread] fix MSVC build error with _rdstc (#4029)
fixes issue reported by @bruno

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4029
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-31 02:32:21 +02:00
Eden CI
88ff086d13
[dist, android] Update translations from Transifex for May 30 (#4028)
Automatic translation update for May 30

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4028
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-05-31 02:32:12 +02:00
lizzie
116377f6d9
[vk] fix oversight with #3874 with invalid image ids (#4026)
oopsie, forgot we had a GC
fixes SSBU

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4026
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-30 21:59:18 +02:00
lizzie
7c32cf03a1
[core/core_timing] better MWAITX and WAITPKG delays (#3984)
This implements MWAITX and WAITPKG extensions (umonitor, mwait) for CPUs that support them.

Reduces wait times and bypasses the timing stuff from the OS that is slow (windows notably). generally it should answer within 0.2 to 0.5 microsecs (since most requests wait for that long).

Also does a general rework of static ctors and stuff

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3984
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-30 21:59:10 +02:00
Yang Liu
ff7bbaea7d
[dynarmic] bootstrap loongarch64 host build (#4015)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Minimal additions to make Eden compile.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4015
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-30 01:42:23 +02:00
MaranBr
c84d605426
[buffer_cache] Fix buffer upload overwriting GPU-modified regions (#4000)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
This fixes a bug in Super Mario Odyssey, in Bowser's Kingdom, where particles rapidly freeze and unfreeze in midair.

It also fixes vertex explosions in Super Mario Party Jamboree.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4000
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-05-29 14:01:06 +02:00
lizzie
def03f6589
[video_core] fix redundant resize-copy overload and just use default-init resize, to reduce stutter on Mario BP (#3874)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
before vs. after

Mario Brothership kept remaking vectors of sizes 256 AND 4095 (TIC) and 1215 AND 524287 (TSC) every single frame, which resulted in a noticeable overhead

the main cause was because of using `resize(n, c)` instead of `resize(n)` (also to aggressively resize for more room beforehand), the copy overload of resize does a copy of... well.. the value over the entire vector, additionally __append() keeps getting called because the capacity goes bonkers and all over the place

![image](/attachments/e3ba07fb-1c85-4d56-9b81-bb16a8150c15)
![image](/attachments/5c4eba26-015a-4c95-9b24-b41695a62e51)

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3874
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-05-29 03:28:47 +02:00
lizzie
5ea24621cf
[vk] fix LM3 and TL:LTD multiple NonUniform annotations (#3997)
should fix AMD

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3997
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-05-29 03:28:10 +02:00
crueter
251a3470dc
[desktop] Set max stdio limit to 2048 on MSVCRT environments (#4023)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
Such as MINGW64.

I legitimately don't have an explanation for this.

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4023
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-05-28 21:22:28 +02:00
crueter
08f65cbd01
[frontend] Fix auto updater flavors on Windows (#4019)
Matches the build ID and compiler now.

Note that this could still use some work on the Windows side of things.
Ideally, it would just replace the executables in place; however, I
think using the setup files will be better.

Most of my concerns w.r.t this issue is that users will want to install
multiple in the same place; however, I think it's fair to just not
support the older versions at all for now. If users really want to do
that, they can use the portable versions and cry about it.

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4019
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-05-28 20:36:16 +02:00
lizzie
8fd495f906
[video_core] fix std::bitset<> dirty tracker OOB, fix slightly wrong index format estimate (#4006)
Some checks failed
tx-src / sources (push) Has been cancelled
Check Strings / check-strings (push) Has been cancelled
u8 may have been 0xff, (aka. 255), but bitset was only 255 elements, so doing bitset[255] is technically OOB

additionally the max size estimate for index formats was not correct, there can be up to 256 elements with a u8 format index, not just 255

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4006
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-05-27 00:04:27 +02:00
lizzie
9d55875377
[*] fix missing '#pragma once' on header files (#4014)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
`find src -type f -name '*.h' -not -exec grep -q "#pragma once" {} \; -print`

- ignore qt with header guards already
- smaa too

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4014
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-26 06:37:59 +02:00
xbzk
8a11bec55a
[vk,fence_manager] improvement for antiflicker showed bad for some games, so it was removed from balanced/accurate and kept for antiflicker toggle only (#4010)
Some checks are pending
tx-src / sources (push) Waiting to run
Check Strings / check-strings (push) Waiting to run
in short:

unrelated to the toggle, we found a missing piece that improved antiflicker and shader issues in some games, and we integrated it to balanced/accurate.
now testers confirmed side effects in some other games, so we reverted the integration.

the toggle itself is innocent. and the missing piece was kept for the toggle.
now, when the toggle is off, things are as they were before it.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4010
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-05-26 01:41:11 +02:00
194 changed files with 19642 additions and 14025 deletions

View file

@ -0,0 +1,214 @@
From ec4c1fdf526cb9ad045abf59b29ee495bbf5023a Mon Sep 17 00:00:00 2001
From: crueter <crueter@eden-emu.dev>
Date: Sat, 30 May 2026 20:56:35 -0400
Subject: [PATCH] cpmutil compat
---
CMakeLists.txt | 31 ++++++++-----------
cmake/FetchOpenSSL.cmake | 64 ----------------------------------------
cmake/GetCPM.cmake | 5 ----
3 files changed, 13 insertions(+), 87 deletions(-)
delete mode 100644 cmake/FetchOpenSSL.cmake
delete mode 100644 cmake/GetCPM.cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5420ecc..9ffd5a0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,9 +19,7 @@ include(FetchContent)
include(ProcessorCount)
include(cmake/ConfigureOpenSSL.cmake)
include(cmake/DetectTargetPlatform.cmake)
-include(cmake/FetchOpenSSL.cmake)
include(cmake/FindVcvarsall.cmake)
-include(cmake/GetCPM.cmake)
# Custom options
option(OPENSSL_BUILD_VERBOSE "Enable verbose output from build" OFF)
@@ -47,9 +45,6 @@ if("${OPENSSL_TARGET_PLATFORM}" STREQUAL "")
detect_target_platform(OPENSSL_TARGET_PLATFORM)
endif()
-# Fetch OpenSSL source
-fetch_openssl()
-
# Apply patches
foreach(patch IN LISTS OPENSSL_PATCH)
if(EXISTS "${patch}" AND NOT IS_DIRECTORY "${patch}")
@@ -59,13 +54,13 @@ foreach(patch IN LISTS OPENSSL_PATCH)
execute_process(
COMMAND git init
- WORKING_DIRECTORY ${openssl_SOURCE_DIR}
+ WORKING_DIRECTORY ${OpenSSL_SOURCE_DIR}
OUTPUT_QUIET
ERROR_QUIET
)
execute_process(
COMMAND git apply ${patch}
- WORKING_DIRECTORY ${openssl_SOURCE_DIR}
+ WORKING_DIRECTORY ${OpenSSL_SOURCE_DIR}
OUTPUT_QUIET
ERROR_QUIET
)
@@ -161,8 +156,8 @@ list(PREPEND OPENSSL_CONFIGURE_OPTIONS ${OPENSSL_TARGET_PLATFORM})
# Configure OpenSSL
configure_openssl(
COMMAND ${VCVARSALL_COMMAND}
- FILE ${openssl_SOURCE_DIR}/Configure
- BUILD_DIR ${openssl_BINARY_DIR}
+ FILE ${OpenSSL_SOURCE_DIR}/Configure
+ BUILD_DIR ${OpenSSL_BINARY_DIR}
OPTIONS ${OPENSSL_CONFIGURE_OPTIONS}
)
@@ -203,8 +198,8 @@ endif()
# Parse Makefile
parse_makefile(${OPENSSL_MAKEFILE} "INSTALL_LIBS" OPENSSL_STATIC_LIBS)
parse_makefile(${OPENSSL_MAKEFILE} "INSTALL_SHLIBS" OPENSSL_SHARED_LIBS)
-list(TRANSFORM OPENSSL_STATIC_LIBS PREPEND "${openssl_BINARY_DIR}/")
-list(TRANSFORM OPENSSL_SHARED_LIBS PREPEND "${openssl_BINARY_DIR}/")
+list(TRANSFORM OPENSSL_STATIC_LIBS PREPEND "${OpenSSL_BINARY_DIR}/")
+list(TRANSFORM OPENSSL_SHARED_LIBS PREPEND "${OpenSSL_BINARY_DIR}/")
foreach(LIBRARY IN LISTS OPENSSL_STATIC_LIBS)
if(LIBRARY MATCHES "crypto")
@@ -239,14 +234,14 @@ endif()
# Provide same targets and variables as FindOpenSSL module
set(OPENSSL_FOUND ON CACHE BOOL "Override FindOpenSSL variables" FORCE)
-set(OPENSSL_INCLUDE_DIR ${openssl_SOURCE_DIR}/include ${openssl_BINARY_DIR}/include CACHE STRING "Override FindOpenSSL variables" FORCE)
+set(OPENSSL_INCLUDE_DIR ${OpenSSL_SOURCE_DIR}/include ${OpenSSL_BINARY_DIR}/include CACHE STRING "Override FindOpenSSL variables" FORCE)
set(OPENSSL_CRYPTO_LIBRARY ${OPENSSL_${OPENSSL_LIBRARY_TYPE}_CRYPTO_LIBRARY} CACHE STRING "Override FindOpenSSL variables" FORCE)
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
set(OPENSSL_SSL_LIBRARY ${OPENSSL_${OPENSSL_LIBRARY_TYPE}_SSL_LIBRARY} CACHE STRING "Override FindOpenSSL variables" FORCE)
set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
set(OPENSSL_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
set(OPENSSL_VERSION ${OPENSSL_CONFIGURED_VERSION} CACHE STRING "Override FindOpenSSL variables" FORCE)
-set(OPENSSL_APPLINK_SOURCE ${openssl_SOURCE_DIR}/ms/applink.c CACHE STRING "Override FindOpenSSL variables" FORCE)
+set(OPENSSL_APPLINK_SOURCE ${OpenSSL_SOURCE_DIR}/ms/applink.c CACHE STRING "Override FindOpenSSL variables" FORCE)
add_library(OpenSSL::Crypto ${OPENSSL_LIBRARY_TYPE} IMPORTED GLOBAL)
add_library(OpenSSL::SSL ${OPENSSL_LIBRARY_TYPE} IMPORTED GLOBAL)
@@ -308,8 +303,8 @@ if(ANDROID)
endif()
file(GLOB_RECURSE OPENSSL_SOURCES
- ${openssl_SOURCE_DIR}/*.[ch]
- ${openssl_SOURCE_DIR}/*.[ch].in
+ ${OpenSSL_SOURCE_DIR}/*.[ch]
+ ${OpenSSL_SOURCE_DIR}/*.[ch].in
)
set(OPENSSL_BUILD_OUTPUT
@@ -322,7 +317,7 @@ add_custom_command(
OUTPUT ${OPENSSL_BUILD_OUTPUT}
COMMAND ${OPENSSL_BUILD_COMMAND}
DEPENDS ${OPENSSL_SOURCES}
- WORKING_DIRECTORY ${openssl_BINARY_DIR}
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
VERBATIM
)
@@ -341,7 +336,7 @@ if(OPENSSL_TEST AND NOT CMAKE_CROSSCOMPILING)
add_test(
NAME openssl-test
COMMAND ${OPENSSL_BUILD_TOOL} test VERBOSE_FAILURE=yes HARNESS_JOBS=${NUMBER_OF_THREADS}
- WORKING_DIRECTORY ${openssl_BINARY_DIR}
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
)
endif()
@@ -356,7 +351,7 @@ if(OPENSSL_INSTALL)
install(CODE
"execute_process(
COMMAND ${OPENSSL_INSTALL_COMMAND}
- WORKING_DIRECTORY \"${openssl_BINARY_DIR}\"
+ WORKING_DIRECTORY \"${OpenSSL_BINARY_DIR}\"
)"
)
endif()
diff --git a/cmake/FetchOpenSSL.cmake b/cmake/FetchOpenSSL.cmake
deleted file mode 100644
index a43505d..0000000
--- a/cmake/FetchOpenSSL.cmake
+++ /dev/null
@@ -1,64 +0,0 @@
-function(fetch_openssl)
- if(EXISTS "${OPENSSL_SOURCE}" AND IS_DIRECTORY "${OPENSSL_SOURCE}")
- # Fetch the local OpenSSL source
- if(NOT IS_ABSOLUTE "${OPENSSL_SOURCE}")
- string(PREPEND OPENSSL_SOURCE ${CMAKE_SOURCE_DIR}/)
- endif()
-
- string(REPLACE "\\" "/" openssl-source_SOURCE_DIR "${OPENSSL_SOURCE}")
- set(openssl-source_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl-source-build)
- else()
- set(CPM_OPTIONS
- NAME openssl-source
- DOWNLOAD_ONLY ON
- )
-
- if(NOT OPENSSL_CONFIGURE_VERBOSE)
- list(APPEND CPM_OPTIONS QUIET)
- endif()
-
- if("${OPENSSL_SOURCE}" MATCHES "^http")
- # Download OpenSSL source from the internet
- list(APPEND CPM_OPTIONS URL ${OPENSSL_SOURCE})
- else()
- # Download OpenSSL source from the official website
- if("${OPENSSL_TARGET_VERSION}" STREQUAL "")
- set(OPENSSL_TARGET_VERSION ${PROJECT_VERSION})
- endif()
-
- if(OPENSSL_TARGET_VERSION VERSION_EQUAL PROJECT_VERSION)
- list(APPEND CPM_OPTIONS URL_HASH SHA256=aaf51a1fe064384f811daeaeb4ec4dce7340ec8bd893027eee676af31e83a04f)
- endif()
-
- if(OPENSSL_TARGET_VERSION MATCHES "^1\.1\.1[a-w]$")
- string(REPLACE "." "_" OPENSSL_TAGGED_VERSION ${OPENSSL_TARGET_VERSION})
- list(APPEND CPM_OPTIONS URL https://github.com/openssl/openssl/releases/download/OpenSSL_${OPENSSL_TAGGED_VERSION}/openssl-${OPENSSL_TARGET_VERSION}.tar.gz)
- else()
- list(APPEND CPM_OPTIONS URL https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_TARGET_VERSION}/openssl-${OPENSSL_TARGET_VERSION}.tar.gz)
- endif()
- endif()
-
- CPMAddPackage(${CPM_OPTIONS})
- endif()
-
- # Clean build directory if source directory has changed
- if(DEFINED CACHE{openssl-source_SOURCE_DIR_OLD} AND NOT openssl-source_SOURCE_DIR STREQUAL openssl-source_SOURCE_DIR_OLD)
- set(openssl-source_SOURCE_DIR_OLD ${openssl-source_SOURCE_DIR} CACHE INTERNAL "Previously fetched OpenSSL source")
-
- if(IS_DIRECTORY ${openssl-source_BINARY_DIR})
- file(REMOVE_RECURSE ${openssl-source_BINARY_DIR})
- file(MAKE_DIRECTORY ${openssl-source_BINARY_DIR})
- endif()
- endif()
-
- # Override the FindOpenSSL module
- FetchContent_Declare(
- OpenSSL
- SOURCE_DIR ${openssl-source_SOURCE_DIR}
- BINARY_DIR ${openssl-source_BINARY_DIR}
- OVERRIDE_FIND_PACKAGE
- )
- FetchContent_MakeAvailable(OpenSSL)
-
- return(PROPAGATE openssl_SOURCE_DIR openssl_BINARY_DIR)
-endfunction()
diff --git a/cmake/GetCPM.cmake b/cmake/GetCPM.cmake
deleted file mode 100644
index bfc50f5..0000000
--- a/cmake/GetCPM.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-file(
- DOWNLOAD https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake
- ${CMAKE_CURRENT_BINARY_DIR}/get_cpm.cmake
-)
-include(${CMAKE_CURRENT_BINARY_DIR}/get_cpm.cmake)
--
2.54.0

View file

@ -0,0 +1,54 @@
From d46675fbb61eb6d51e478023ce4075e545ad4cfd Mon Sep 17 00:00:00 2001
From: crueter <crueter@eden-emu.dev>
Date: Sat, 30 May 2026 21:11:55 -0400
Subject: [PATCH] use ccache
---
CMakeLists.txt | 1 -
cmake/ConfigureOpenSSL.cmake | 12 +++---------
2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9ffd5a0..9ff14c8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,7 +28,6 @@ option(OPENSSL_ENABLE_PARALLEL "Build and test in parallel if possible" ON)
option(OPENSSL_INSTALL "Install OpenSSL components to the <prefix> directory" OFF)
option(OPENSSL_INSTALL_CERT "Install cert.pem to the <openssldir> directory" OFF)
option(OPENSSL_TEST "Enable testing and build OpenSSL self tests" OFF)
-option(OPENSSL_USE_CCACHE "Use ccache if available" ON)
if("${OPENSSL_BUILD_TARGET}" STREQUAL "")
# Makefile target for build
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
index 211c18b..3d8cbed 100644
--- a/cmake/ConfigureOpenSSL.cmake
+++ b/cmake/ConfigureOpenSSL.cmake
@@ -69,15 +69,9 @@ function(apply_ccache FILE)
message(FATAL_ERROR "Couldn't find Makefile")
endif()
- if(OPENSSL_USE_CCACHE)
- find_program(CCACHE ccache)
-
- if(NOT CCACHE)
- return()
- endif()
-
+ if(USE_CCACHE)
file(READ ${FILE} MAKEFILE)
- string(REPLACE "\nCC=" "\nCC=ccache " MAKEFILE "${MAKEFILE}")
+ string(REPLACE "\nCC=" "\nCC=${CCACHE_BINARY} " MAKEFILE "${MAKEFILE}")
if(MSVC)
string(REPLACE "/Zi /Fdossl_static.pdb " "" MAKEFILE "${MAKEFILE}")
@@ -171,4 +165,4 @@ function(configure_openssl)
string(REPLACE "/W3" "/W0" MAKEFILE "${MAKEFILE}")
file(WRITE ${OPENSSL_MAKEFILE} "${MAKEFILE}")
endif()
-endfunction()
\ No newline at end of file
+endfunction()
--
2.54.0

View file

@ -0,0 +1,28 @@
From 4a3cc92a7abad403529ed1cb4255ca63d9252de4 Mon Sep 17 00:00:00 2001
From: crueter <crueter@eden-emu.dev>
Date: Sat, 30 May 2026 21:48:42 -0400
Subject: [PATCH 2/2] use cmake compiler flags
---
cmake/ConfigureOpenSSL.cmake | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
index 3d8cbed..3012e05 100644
--- a/cmake/ConfigureOpenSSL.cmake
+++ b/cmake/ConfigureOpenSSL.cmake
@@ -135,7 +135,10 @@ function(configure_openssl)
endif()
execute_process(
- COMMAND ${CONFIGURE_COMMAND}
+ COMMAND ${CMAKE_COMMAND} -E env
+ "CFLAGS=${CMAKE_C_FLAGS}"
+ "CXXFLAGS=${CMAKE_CXX_FLAGS}"
+ ${CONFIGURE_COMMAND}
WORKING_DIRECTORY ${CONFIGURE_BUILD_DIR}
${VERBOSE_OPTION}
COMMAND_ERROR_IS_FATAL ANY
--
2.54.0

View file

@ -0,0 +1,39 @@
--- a/CMakeLists.txt 2026-06-01 23:53:16.498043856 -0400
+++ b/CMakeLists.txt 2026-06-01 23:53:23.910543615 -0400
@@ -312,13 +312,29 @@
${OPENSSL_SHARED_CRYPTO_LIBRARY}
${OPENSSL_SHARED_SSL_LIBRARY}
)
-add_custom_command(
- OUTPUT ${OPENSSL_BUILD_OUTPUT}
- COMMAND ${OPENSSL_BUILD_COMMAND}
- DEPENDS ${OPENSSL_SOURCES}
- WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
- VERBATIM
-)
+if (WIN32)
+ add_custom_command(
+ OUTPUT ${OPENSSL_BUILD_OUTPUT}
+ COMMAND ${OPENSSL_BUILD_COMMAND}
+ DEPENDS ${OPENSSL_SOURCES}
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
+ VERBATIM)
+else()
+ set(_openssl_build_script "${CMAKE_CURRENT_BINARY_DIR}/BuildOpenSSL.cmake")
+ file(WRITE ${_openssl_build_script}
+ "execute_process(\n"
+ " COMMAND ${OPENSSL_BUILD_COMMAND}\n"
+ " WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}\n"
+ " RESULT_VARIABLE _r)\n"
+ "if(_r)\n"
+ " message(FATAL_ERROR \"OpenSSL build failed: \${_r}\")\n"
+ "endif()\n")
+ add_custom_command(
+ OUTPUT ${OPENSSL_BUILD_OUTPUT}
+ COMMAND ${CMAKE_COMMAND} -P ${_openssl_build_script}
+ DEPENDS ${OPENSSL_SOURCES}
+ VERBATIM)
+endif()
if(PROJECT_IS_TOP_LEVEL)
add_custom_target(openssl-build ALL DEPENDS ${OPENSSL_BUILD_OUTPUT})

File diff suppressed because it is too large Load diff

View file

@ -383,13 +383,20 @@ find_package(RenderDoc MODULE)
# openssl funniness
if (YUZU_USE_BUNDLED_OPENSSL)
set(BUILD_SHARED_LIBS OFF)
AddJsonPackage(openssl-ci)
else()
AddJsonPackage(openssl)
set(OPENSSL_BUILD_VERBOSE ON)
set(OPENSSL_CONFIGURE_VERBOSE ON)
if (OpenSSL_ADDED)
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
AddJsonPackage(openssl-cmake)
endif()
endif()
find_package(OpenSSL 3 REQUIRED)
if (OpenSSL_ADDED)
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
endif()
message(STATUS "Fetching needed dependencies with CPM")
@ -505,7 +512,7 @@ endfunction()
# =============================================
if (APPLE)
foreach(fw Carbon Metal Cocoa IOKit CoreVideo CoreMedia Security)
foreach(fw Carbon Metal Cocoa IOKit CoreVideo CoreMedia Security UniformTypeIdentifiers)
find_library(${fw}_LIBRARY ${fw} REQUIRED)
list(APPEND PLATFORM_LIBRARIES ${${fw}_LIBRARY})
endforeach()

View file

@ -1,5 +1,5 @@
{
"openssl": {
"openssl-ci": {
"ci": true,
"package": "OpenSSL",
"name": "openssl",
@ -7,6 +7,34 @@
"version": "3.6.0-1cb0d36b39",
"min_version": "3"
},
"openssl-cmake": {
"repo": "jimmy-park/openssl-cmake",
"hash": "2cc185c924fd70e7d886257ca0caa42b3b8f7f712f2052b4f94dde74759e27022de76178460e18c9bdfc57c366583999e198fbb6052d4e7d91c099d15a0ca63e",
"git_version": "3.6.2",
"tag": "%VERSION%",
"bundled": true,
"options": [
"OPENSSL_CONFIGURE_OPTIONS threads"
],
"patches": [
"0001-cpmutil-compat.patch",
"0002-use-ccache.patch",
"0003-use-cmake-compiler-flags.patch",
"0004-use-shell-wrapper.patch"
]
},
"openssl": {
"repo": "openssl/openssl",
"package": "OpenSSL",
"min_version": "3",
"version": "3",
"hash": "29002ce50cb95a4f4f1d0e9d3f684401fbd4eac34203dc2eef3b6334af5d44aa46bf788b63a6f5c139c383eafb7269ae87a58a9a3ad5912903b9773e545ccc0a",
"git_version": "3.6.2",
"tag": "openssl-%VERSION%",
"patches": [
"0001-add-bundled-cert.patch"
]
},
"boost": {
"package": "Boost",
"repo": "boostorg/boost",

890
dist/languages/ar.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/ca.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/cs.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/da.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/de.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/el.ts vendored

File diff suppressed because it is too large Load diff

902
dist/languages/es.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/fi.ts vendored

File diff suppressed because it is too large Load diff

891
dist/languages/fr.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/hu.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/id.ts vendored

File diff suppressed because it is too large Load diff

891
dist/languages/it.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

889
dist/languages/nb.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/nl.ts vendored

File diff suppressed because it is too large Load diff

891
dist/languages/pl.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

891
dist/languages/sv.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

890
dist/languages/uk.ts vendored

File diff suppressed because it is too large Load diff

889
dist/languages/vi.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -82,6 +82,11 @@ if (ARCHITECTURE_riscv64)
AddJsonPackage(biscuit)
endif()
# Lagoon
if (ARCHITECTURE_loongarch64)
AddJsonPackage(lagoon)
endif()
# Vulkan stuff
AddDependentPackages(vulkan-headers vulkan-utility-libraries)

View file

@ -67,6 +67,12 @@
"tag": "v%VERSION%",
"hash": "9697e80a7d5d9bcb3ce51051a9a24962fb90ca79d215f1f03ae6b58da8ba13a63b5dda1b4dde3d26ac6445029696b8ef2883f4e5a777b342bba01283ed293856"
},
"lagoon": {
"repo": "loongson-community/lagoon",
"tag": "%VERSION%",
"version": "1.0.0",
"hash": "b9380f99c6effaeccc6d8f81d4942e852c11ad28613df637e155451556ae5826f93765bee57a5c87a9740d2bd1db463ad0f55a947772fe9d57eeabae3efa373e"
},
"libadrenotools": {
"repo": "eden-emulator/libadrenotools",
"sha": "8ba23b42d7",

View file

@ -8,7 +8,7 @@
include_directories(.)
# Dynarmic
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64) AND NOT YUZU_STATIC_ROOM)
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM)
add_subdirectory(dynarmic)
add_library(dynarmic::dynarmic ALIAS dynarmic)
endif()
@ -21,20 +21,41 @@ if (YUZU_STATIC_BUILD)
add_compile_definitions(QT_STATICPLUGIN)
endif()
# Build identifiers
if (NIGHTLY_BUILD)
add_compile_definitions(NIGHTLY_BUILD)
endif()
# Legacy (android only)
if (YUZU_LEGACY)
message(WARNING "Making legacy build. Performance may suffer.")
add_compile_definitions(YUZU_LEGACY)
endif()
# Genshin Spoof (android only)
if (GENSHIN_SPOOF)
message(WARNING "Making Genshin spoof build")
add_compile_definitions(GENSHIN_SPOOF)
endif()
# Build ID (mingw only right now)
# Pretty much just refers to the CI "target" for this build
if (NOT BUILD_ID)
if (ARCHITECTURE_x86_64)
set(BUILD_ID amd64)
elseif(ARCHITECTURE_arm64)
if (WIN32)
set(BUILD_ID arm64)
else()
set(BUILD_ID aarch64)
endif()
else()
set(BUILD_ID "${ARCHITECTURE}")
endif()
endif()
add_compile_definitions(BUILD_ID="${BUILD_ID}")
# Set compilation flags
if (MSVC AND NOT CXX_CLANG)
set(CMAKE_CONFIGURATION_TYPES Debug Release CACHE STRING "" FORCE)

View file

@ -15,7 +15,6 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Rect
import android.graphics.drawable.Icon
@ -101,7 +100,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
private var romSwapGeneration = 0
private var hasEmulationSession = processHasEmulationSession
private val romSwapStopTimeoutRunnable = Runnable { onRomSwapStopTimeout() }
private val pictureInPictureFailureActions: MutableSet<String> = mutableSetOf()
private fun onRomSwapStopTimeout() {
if (!isWaitingForRomSwapStop) {
@ -270,20 +268,14 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
}
override fun onUserLeaveHint() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ||
!isPictureInPictureSupported() ||
!BooleanSetting.PICTURE_IN_PICTURE.getBoolean() ||
isInPictureInPictureMode
) {
return
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) {
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
runPictureInPictureAction("enter picture-in-picture mode") {
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
}
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
@ -661,29 +653,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
return this.apply { setActions(pictureInPictureActions) }
}
private fun isPictureInPictureSupported() =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
private fun runPictureInPictureAction(actionName: String, action: () -> Unit) {
try {
action()
} catch (e: IllegalStateException) {
if (pictureInPictureFailureActions.add(actionName)) {
Log.warning("[PiP] Failed to $actionName: ${e.message}")
}
} catch (e: UnsupportedOperationException) {
if (pictureInPictureFailureActions.add(actionName)) {
Log.warning("[PiP] Failed to $actionName: ${e.message}")
}
}
}
fun buildPictureInPictureParams() {
if (!isPictureInPictureSupported()) {
return
}
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@ -693,10 +663,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive
)
}
runPictureInPictureAction("set picture-in-picture params") {
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
}
}
fun displayMultiplayerDialog() {
val dialog = NetPlayDialog(this)

View file

@ -462,8 +462,8 @@
<string name="renderer_resolution">الدقة (الإرساء/محمول)</string>
<string name="renderer_vsync">VSync وضع</string>
<string name="renderer_scaling_filter">مرشح ملائم للنافذة</string>
<string name="fsr_sharpness">حدة FSR</string>
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام التباين الديناميكي لـ FSR</string>
<string name="fsr_sharpness">حدة FSR/SGSR</string>
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام مرشحات FSR أو SGSR</string>
<string name="renderer_anti_aliasing">طريقة مضاد التعرج</string>
@ -503,6 +503,8 @@
<string name="fast_gpu_time_description">يُجبر هذا الخيار معظم الألعاب على العمل بأعلى دقة عرض أصلية. استخدم 256 للحصول على أقصى أداء و512 للحصول على أعلى جودة رسومات.</string>
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
<string name="antiflicker">مضاد الوميض</string>
<string name="antiflicker_description">يُجبر هذا الوضع وظائف وحدة معالجة الرسومات على الانتظار حتى يتم إرسال العمل إليها. استخدمه مع وضع وحدة معالجة الرسومات السريع لتجنب الوميض مع تأثير أقل على الأداء.</string>
<string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string>
<string name="fix_bloom_effects_description">يقلل من ضبابية التوهج في LA/EOW (Adreno A6XX - A7XX/ Turnip)، ويزيل التوهج في Burnout. تحذير: قد يسبب تشوهات رسومية في ألعاب أخرى.</string>
<string name="emulate_bgr565">محاكاة BGR565</string>

View file

@ -329,8 +329,6 @@
<string name="renderer_resolution">ڕوونی (دۆخی دەستی/دۆخی دۆک)</string>
<string name="renderer_vsync">دۆخی VSync</string>
<string name="renderer_scaling_filter">فلتەری گونجاندنی پەنجەرە</string>
<string name="fsr_sharpness">تیژی FSR</string>
<string name="fsr_sharpness_description">دیاریکردنی تیژی وێنە لە کاتی بەکارهێنانی FSR</string>
<string name="renderer_anti_aliasing">شێوازی دژە-خاوڕۆیی</string>

View file

@ -439,8 +439,6 @@
<string name="renderer_resolution">Rozlišení (Handheld/V doku)</string>
<string name="renderer_vsync">Režim VSync</string>
<string name="renderer_scaling_filter">Škálovací filtr</string>
<string name="fsr_sharpness">Ostrost FSR</string>
<string name="fsr_sharpness_description">Určuje jak ostře bude obraz vypadat při použití dynamického kontrastu FSR.</string>
<string name="renderer_anti_aliasing">Metoda anti-aliasingu</string>

View file

@ -439,8 +439,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
<string name="renderer_resolution">Auflösung (Handheld/Gedockt)</string>
<string name="renderer_vsync">VSync-Modus</string>
<string name="renderer_scaling_filter">Skalierungsfilter</string>
<string name="fsr_sharpness">FSR-Schärfe</string>
<string name="fsr_sharpness_description">Bestimmt die Schärfe bei FSR-Nutzung.</string>
<string name="renderer_anti_aliasing">Kantenglättung</string>

View file

@ -376,7 +376,7 @@
<string name="qlaunch_applet">Qlaunch</string>
<string name="qlaunch_description">Iniciar aplicaciones desde la pantalla de inicio del sistema</string>
<string name="applets">Lanzador de Applet</string>
<string name="applets_description">Ejecutar applets de sistema usando el firmware instalado</string>
<string name="applets_description">Ejecutar applets del sistema usando el firmware instalado</string>
<string name="applets_error_firmware">El firmware no está instalado</string>
<string name="applets_error_applet">Applet no disponible</string>
<string name="applets_error_description"><![CDATA[Por favor, asegúrese de que su archivo <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> y el <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">firmware</a> están instalados e inténtelo de nuevo.]]></string>
@ -456,8 +456,8 @@
<string name="renderer_resolution">Resolución (Portátil/Sobremesa)</string>
<string name="renderer_vsync">Modo de sincronización vertical</string>
<string name="renderer_scaling_filter">Filtro de adaptación de ventana</string>
<string name="fsr_sharpness">Nitidez FSR</string>
<string name="fsr_sharpness_description">Ajusta la intensidad del filtro de enfoque al usar el contraste dinámico de FSR.</string>
<string name="fsr_sharpness">Nitidez FSR/SGSR</string>
<string name="fsr_sharpness_description">Determina el grado de nitidez de la imagen al usar filtros FSR o SGSR</string>
<string name="renderer_anti_aliasing">Método de suavizado de bordes</string>
@ -497,6 +497,8 @@
<string name="fast_gpu_time_description">Fuerza a la mayoría de los juegos a ejecutarse a su resolución nativa más alta. Usa 256 para un máximo rendimiento y 512 para una fidelidad gráfica óptima.</string>
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
<string name="antiflicker">Antiparpadeo</string>
<string name="antiflicker_description">Fuerza a las funciones de devolución de llamada de la GPU a esperar a que se envíen las tareas a la GPU.\nÚsalo con el modo de GPU rápida para evitar el parpadeo con un menor impacto en el rendimiento.</string>
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
<string name="fix_bloom_effects_description">Reduce el efecto de resplandor en LA/EOW (Adreno A6XX - A7XX/ Turnip), elimina el resplandor en Burnout. Advertencia: puede causar artefactos gráficos en otros juegos.</string>
<string name="emulate_bgr565">Emular BGR565</string>
@ -1072,7 +1074,7 @@
<!-- Black backgrounds theme -->
<string name="use_black_backgrounds">Fondos oscuros</string>
<string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string>
<string name="use_black_backgrounds_description">Cuando se usa el modo oscuro, aplicar fondos de pantalla negros.</string>
<!-- Buttons -->
<string name="enable_folder_button">Carpeta</string>

View file

@ -454,8 +454,6 @@
<string name="renderer_resolution">Résolution (Mode Portable/Mode TV)</string>
<string name="renderer_vsync">Mode VSync</string>
<string name="renderer_scaling_filter">Filtre de fenêtre adaptatif</string>
<string name="fsr_sharpness">Netteté FSR</string>
<string name="fsr_sharpness_description">Détermine à quel point l\'image sera affinée lors de l\'utilisation du contraste dynamique FSR.</string>
<string name="renderer_anti_aliasing">Méthode d\'anticrénelage</string>

View file

@ -359,8 +359,6 @@
<string name="renderer_resolution">רזולוציה (מעוגן/נייד)</string>
<string name="renderer_vsync">מצב VSync</string>
<string name="renderer_scaling_filter">פילטר מתאם חלון</string>
<string name="fsr_sharpness">חדות FSR</string>
<string name="fsr_sharpness_description">קובע את מידת החדות בעת שימוש ב-FSR.</string>
<string name="renderer_anti_aliasing">שיטת Anti-aliasing</string>

View file

@ -348,8 +348,6 @@
<string name="renderer_resolution">Felbontás (Kézi/Dockolt)</string>
<string name="renderer_vsync">VSync mód</string>
<string name="renderer_scaling_filter">Ablakhoz alkalmazkodó szűrő</string>
<string name="fsr_sharpness">FSR élesség</string>
<string name="fsr_sharpness_description">Meghatározza, milyen éles lesz a kép az FSR dinamikus kontraszt használata közben.</string>
<string name="renderer_anti_aliasing">Élsimítási módszer</string>

View file

@ -380,8 +380,6 @@
<string name="renderer_resolution">Resolusi (Handheld/Docked)</string>
<string name="renderer_vsync">Mode Sinkronisasi Vertikal</string>
<string name="renderer_scaling_filter">Filter penyesuaian jendela</string>
<string name="fsr_sharpness">Ketajaman FSR</string>
<string name="fsr_sharpness_description">Menentukan seberapa tajam gambar akan terlihat saat menggunakan kontras dinamis FSR</string>
<string name="renderer_anti_aliasing">Metode anti-aliasing</string>

View file

@ -387,8 +387,6 @@
<string name="renderer_resolution">Risoluzione (Portatile/Docked)</string>
<string name="renderer_vsync">Modalità VSync</string>
<string name="renderer_scaling_filter">Filtro adattivo della finestra </string>
<string name="fsr_sharpness">Nitidezza FSR</string>
<string name="fsr_sharpness_description">Determina quanto sarà nitida l\'immagine utilizzando il contrasto dinamico di FSR</string>
<string name="renderer_anti_aliasing">Metodo di anti-aliasing</string>

View file

@ -329,8 +329,6 @@
<string name="renderer_resolution">Oppløsning (håndholdt/dokket)</string>
<string name="renderer_vsync">VSync-modus</string>
<string name="renderer_scaling_filter">Filter for vindustilpasning</string>
<string name="fsr_sharpness">FSR-skarphet</string>
<string name="fsr_sharpness_description">Bestemmer bildekvalitet med FSR</string>
<string name="renderer_anti_aliasing">Anti-aliasing-metode</string>

View file

@ -439,8 +439,6 @@
<string name="renderer_resolution">Rozdzielczość (Handheld/Zadokowany)</string>
<string name="renderer_vsync">Synchronizacja pionowa VSync</string>
<string name="renderer_scaling_filter">Filtr adaptacji rozdzielczości</string>
<string name="fsr_sharpness">Ostrość FSR</string>
<string name="fsr_sharpness_description">Kontroluje ostrość obrazu w FSR.</string>
<string name="renderer_anti_aliasing">Metoda wygładzania krawędzi</string>

View file

@ -430,8 +430,6 @@
<string name="renderer_resolution">Resolução (Portátil/Modo TV)</string>
<string name="renderer_vsync">Modo de VSync</string>
<string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
<string name="fsr_sharpness">Nitidez do FSR</string>
<string name="fsr_sharpness_description">Determina a nitidez da imagem ao utilizar o contraste dinâmico do FSR</string>
<string name="renderer_anti_aliasing">Método de Anti-aliasing</string>

View file

@ -352,8 +352,6 @@
<string name="renderer_resolution">Resolução (Portátil/Ancorado)</string>
<string name="renderer_vsync">Modo VSync</string>
<string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
<string name="fsr_sharpness">Nitidez do FSR</string>
<string name="fsr_sharpness_description">Determina a nitidez da imagem ao usar contraste dinâmico do FSR</string>
<string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string>

View file

@ -458,8 +458,8 @@
<string name="renderer_resolution">Разрешение (портативное/в док-станции)</string>
<string name="renderer_vsync">Режим верт. синхронизации</string>
<string name="renderer_scaling_filter">Фильтр адаптации окна</string>
<string name="fsr_sharpness">Резкость FSR</string>
<string name="fsr_sharpness_description">Определяет, насколько чётким будет изображение при использовании динамического контраста FSR.</string>
<string name="fsr_sharpness">Резкость FSR/SGSR</string>
<string name="fsr_sharpness_description">Определяет, насколько чётким будет изображение при использовании динамического контраста FSR или SGSR фильтров</string>
<string name="renderer_anti_aliasing">Метод сглаживания</string>
@ -499,6 +499,8 @@
<string name="fast_gpu_time_description">Принудительно запускает большинство игр в их максимальном нативном разрешении. Используйте значение 256 для максимальной производительности и 512 для максимального качества графики.</string>
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
<string name="antiflicker">Анти-мерцание</string>
<string name="antiflicker_description">Принудительно заставляет обратные вызовы ГПУ-фильтра ожидать выполнения отправленных задач на ГПУ. Используйте с Быстрым режимом ГПУ, что бы избежать мерцаний с меньшим влиянием на производительность.</string>
<string name="fix_bloom_effects">Исправить эффекты размытия</string>
<string name="fix_bloom_effects_description">Частично убирает размытие в LA/EOW (Adreno A6XX - A7XX/ Turnip), полностью отключает его в Burnout. Внимание: может вызывать графические артефакты в других играх.</string>
<string name="emulate_bgr565">Эмулировать BGR565</string>

View file

@ -351,8 +351,6 @@
<string name="renderer_resolution">Резолуција (ручно / прикључено)</string>
<string name="renderer_vsync">Всинц мод</string>
<string name="renderer_scaling_filter">Филтер прилагођавања прозора</string>
<string name="fsr_sharpness">ФСР оштрина</string>
<string name="fsr_sharpness_description">Одређује колико ће се слика наоштрен трајати док користи \"ФСР\" динамички контраст</string>
<string name="renderer_anti_aliasing">Метода против алиасирања</string>

View file

@ -458,8 +458,8 @@
<string name="renderer_resolution">Роздільна здатність (Портативний/Док)</string>
<string name="renderer_vsync">Режим верт. синхронізації</string>
<string name="renderer_scaling_filter">Фільтр масштабування вікна</string>
<string name="fsr_sharpness">Різкість FSR</string>
<string name="fsr_sharpness_description">Визначає різкість зображення при використанні FSR.</string>
<string name="fsr_sharpness">Різкість FSR/SGSR</string>
<string name="fsr_sharpness_description">Визначає різкість зображення при використанні фільтрів FSR або SGSR.</string>
<string name="renderer_anti_aliasing">Згладжування</string>
@ -499,6 +499,8 @@
<string name="fast_gpu_time_description">Примушує більшість ігор працювати на їхній максимальній нативній роздільності. Використовуйте 256 для максимальної продуктивності та 512 для найкращої якості.</string>
<string name="skip_cpu_inner_invalidation">Пропустити внутрішнє інвалідування CPU</string>
<string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string>
<string name="antiflicker">Антимерехтіння</string>
<string name="antiflicker_description">Змушує механізм синхронізації чекати, доки ГП завершить подані завдання. Використовуйте з режимом ГП «Швидко», щоб уникнути мерехтіння з меншими втратами продуктивності.</string>
<string name="fix_bloom_effects">Виправити ефекти світіння</string>
<string name="fix_bloom_effects_description">Зменшує розмиття світіння в LA/EOW (Adreno A6XXA7XX / Turnip), прибирає світіння в Burnout. Увага: може спричинити графічні артефакти в інших іграх.</string>
<string name="emulate_bgr565">Емулювати BGR565</string>

View file

@ -327,8 +327,6 @@
<string name="renderer_resolution">Độ phân giải (Handheld/Docked)</string>
<string name="renderer_vsync">Chế độ VSync</string>
<string name="renderer_scaling_filter">Bộ lọc điều chỉnh cửa sổ</string>
<string name="fsr_sharpness">Độ sắc nét FSR</string>
<string name="fsr_sharpness_description">Độ sắc nét khi dùng FSR</string>
<string name="renderer_anti_aliasing">Phương pháp khử răng cưa</string>

View file

@ -452,8 +452,8 @@
<string name="renderer_resolution">分辨率 (掌机模式/主机模式)</string>
<string name="renderer_vsync">垂直同步模式</string>
<string name="renderer_scaling_filter">窗口滤镜</string>
<string name="fsr_sharpness">FSR 锐</string>
<string name="fsr_sharpness_description">确定使用 FSR 的动态对比度功能时的图像锐化程</string>
<string name="fsr_sharpness">FSR/SGSR 锐度</string>
<string name="fsr_sharpness_description">确定在使用 FSR 或 SGSR 过滤器时的图像锐</string>
<string name="renderer_anti_aliasing">抗锯齿方式</string>
@ -493,6 +493,8 @@
<string name="fast_gpu_time_description">强制大多数游戏以其最高原生分辨率运行。设置为 256 可获得最佳性能,设置为 512 可获得最佳画面保真度。</string>
<string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string>
<string name="skip_cpu_inner_invalidation_description">在内存更新期间跳过某些CPU端缓存无效化减少CPU使用率并提高其性能。可能会导致某些游戏出现故障或崩溃。</string>
<string name="antiflicker">防闪烁</string>
<string name="antiflicker_description">强制 GPU 围栏回调等待已提交的 GPU 任务。配合“快速 GPU 模式”一起使用,以避免画面闪烁现象,仅会牺牲少量性能。</string>
<string name="fix_bloom_effects">修复 Bloom 效果</string>
<string name="fix_bloom_effects_description">减少《塞尔达传说智慧的再现》Adreno A6XX - A7XX/ Turnip中的 bloom 模糊并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string>
<string name="emulate_bgr565">模拟 BGR565</string>

View file

@ -437,8 +437,6 @@
<string name="renderer_resolution">解析度 (手提/底座)</string>
<string name="renderer_vsync">垂直同步</string>
<string name="renderer_scaling_filter">視窗適應過濾器</string>
<string name="fsr_sharpness">FSR 銳化度</string>
<string name="fsr_sharpness_description">使用 FSR 時圖片的銳化程度</string>
<string name="renderer_anti_aliasing">抗鋸齒</string>

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@ -177,10 +177,8 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
queued_buffers.store(0);
release_cv.notify_one();
}
static constexpr std::array<s16, 6> silence{};
for (size_t i = 0; i < num_frames; i++)
std::memcpy(&output_buffer[i * frame_size], silence.data(), frame_size_bytes);
std::memset(&output_buffer[i * frame_size], 0, frame_size_bytes);
return;
}

View file

@ -141,12 +141,12 @@ add_library(
vector_math.h
virtual_buffer.cpp
virtual_buffer.h
wall_clock.cpp
wall_clock.h
zstd_compression.cpp
zstd_compression.h
fs/ryujinx_compat.h fs/ryujinx_compat.cpp
fs/symlink.h fs/symlink.cpp
cpu_features.cpp
cpu_features.h
httplib.h
net/net.h net/net.cpp)
@ -180,10 +180,7 @@ endif()
if(ARCHITECTURE_x86_64)
target_sources(
common
PRIVATE x64/cpu_detect.cpp
x64/cpu_detect.h
x64/cpu_wait.cpp
x64/cpu_wait.h
PRIVATE
x64/rdtsc.cpp
x64/rdtsc.h
x64/xbyak.h)
@ -234,7 +231,7 @@ if(CXX_CLANG)
endif()
if (BOOST_NO_HEADERS)
target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool)
target_link_libraries(common PUBLIC Boost::algorithm Boost::heap Boost::icl Boost::pool)
else()
target_link_libraries(common PUBLIC Boost::headers)
endif()

View file

@ -1,7 +1,12 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2005-2014 Daniel James
// SPDX-FileCopyrightText: 2016 Austin Appleby
// SPDX-License-Identifier: BSL-1.0
#pragma once
#include <array>
#include <climits>
#include <cstdint>

View file

@ -10,34 +10,32 @@
#include <fstream>
#include <iterator>
#include <optional>
#include <algorithm>
#include <string_view>
#include <thread>
#include <vector>
#include "common/bit_util.h"
#include "common/common_types.h"
#include "common/logging.h"
#include "common/x64/cpu_detect.h"
#include "common/x64/rdtsc.h"
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>
static inline u64 xgetbv(u32 index) {
return _xgetbv(index);
}
#else
#if defined(__DragonFly__) || defined(__FreeBSD__)
// clang-format off
#elif defined(__DragonFly__) || defined(__FreeBSD__)
#include <sys/types.h>
#include <machine/cpufunc.h>
// clang-format on
#elif defined(__ANDROID__)
#include <sys/system_properties.h>
#endif
#include "common/steady_clock.h"
#include "common/uint128.h"
#include "common/bit_util.h"
#include "common/common_types.h"
#include "common/cpu_features.h"
#include "common/logging.h"
#ifdef ARCHITECTURE_x86_64
#include "common/x64/rdtsc.h"
#ifdef _MSC_VER
#include <intrin.h>
static inline u64 xgetbv(u32 index) { return _xgetbv(index); }
#else
static inline void __cpuidex(int info[4], u32 function_id, u32 subfunction_id) {
#if defined(__DragonFly__) || defined(__FreeBSD__)
// Despite the name, this is just do_cpuid() with ECX as second input.
@ -50,11 +48,7 @@ static inline void __cpuidex(int info[4], u32 function_id, u32 subfunction_id) {
: "a"(function_id), "c"(subfunction_id));
#endif
}
static inline void __cpuid(int info[4], u32 function_id) {
return __cpuidex(info, function_id, 0);
}
static inline void __cpuid(int info[4], u32 function_id) { return __cpuidex(info, function_id, 0); }
#define _XCR_XFEATURE_ENABLED_MASK 0
static inline u64 xgetbv(u32 index) {
u32 eax, edx;
@ -62,9 +56,10 @@ static inline u64 xgetbv(u32 index) {
return ((u64)edx << 32) | eax;
}
#endif // _MSC_VER
#endif
namespace Common {
#ifdef ARCHITECTURE_x86_64
CPUCaps::Manufacturer CPUCaps::ParseManufacturer(std::string_view brand_string) {
if (brand_string == "GenuineIntel") {
return Manufacturer::Intel;
@ -76,13 +71,53 @@ CPUCaps::Manufacturer CPUCaps::ParseManufacturer(std::string_view brand_string)
return Manufacturer::Unknown;
}
// Detects the various CPU features
static CPUCaps Detect() {
std::optional<int> GetProcessorCount() {
#if defined(_WIN32)
// Get the buffer length.
DWORD length = 0;
GetLogicalProcessorInformation(nullptr, &length);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
LOG_ERROR(Frontend, "Failed to query core count.");
return std::nullopt;
}
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(
length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
// Now query the core count.
if (!GetLogicalProcessorInformation(buffer.data(), &length)) {
LOG_ERROR(Frontend, "Failed to query core count.");
return std::nullopt;
}
return static_cast<int>(
std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
return proc_info.Relationship == RelationProcessorCore;
}));
#elif defined(__unix__)
const int thread_count = std::thread::hardware_concurrency();
std::ifstream smt("/sys/devices/system/cpu/smt/active");
char state = '0';
if (smt) {
smt.read(&state, sizeof(state));
}
switch (state) {
case '0':
return thread_count;
case '1':
return thread_count / 2;
default:
return std::nullopt;
}
#else
// Shame on you
return std::nullopt;
#endif
}
/// @brief Detects the various CPU features
const CPUCaps g_cpu_caps = [] {
CPUCaps caps = {};
// Assumes the CPU supports the CPUID instruction. Those that don't would likely not support
// yuzu at all anyway
int cpu_id[4];
// Detect CPU's CPUID capabilities and grab manufacturer string
@ -183,9 +218,8 @@ static CPUCaps Detect() {
// https://github.com/torvalds/linux/blob/master/tools/power/x86/turbostat/turbostat.c#L5569
// but it's easier to just estimate the TSC tick rate for these cases.
if (caps.tsc_crystal_ratio_denominator) {
caps.tsc_frequency = static_cast<u64>(caps.crystal_frequency) *
caps.tsc_crystal_ratio_numerator /
caps.tsc_crystal_ratio_denominator;
caps.tsc_frequency = u64(caps.crystal_frequency)
* caps.tsc_crystal_ratio_numerator / caps.tsc_crystal_ratio_denominator;
} else {
caps.tsc_frequency = X64::EstimateRDTSCFrequency();
}
@ -197,54 +231,196 @@ static CPUCaps Detect() {
caps.max_frequency = cpu_id[1];
caps.bus_frequency = cpu_id[2];
}
return caps;
}
}();
const CPUCaps& GetCPUCaps() {
static CPUCaps caps = Detect();
return caps;
}
std::optional<int> GetProcessorCount() {
#if defined(_WIN32)
// Get the buffer length.
DWORD length = 0;
GetLogicalProcessorInformation(nullptr, &length);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
LOG_ERROR(Frontend, "Failed to query core count.");
return std::nullopt;
}
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(
length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
// Now query the core count.
if (!GetLogicalProcessorInformation(buffer.data(), &length)) {
LOG_ERROR(Frontend, "Failed to query core count.");
return std::nullopt;
}
return static_cast<int>(
std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
return proc_info.Relationship == RelationProcessorCore;
}));
#elif defined(__unix__)
const int thread_count = std::thread::hardware_concurrency();
std::ifstream smt("/sys/devices/system/cpu/smt/active");
char state = '0';
if (smt) {
smt.read(&state, sizeof(state));
}
switch (state) {
case '0':
return thread_count;
case '1':
return thread_count / 2;
default:
return std::nullopt;
}
#else
// Shame on you
return std::nullopt;
#endif
#if defined(ARCHITECTURE_x86_64)
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept
: rdtsc_frequency{rdtsc_frequency_}
, ns_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency_) : 0}
, us_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency_) : 0}
, ms_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency_) : 0}
, rdtsc_ns_factor{invariant_ ? GetFixedPoint64Factor(rdtsc_frequency_, NsRatio::den) : 1}
, cntpct_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency_) : 0}
, gputick_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency_) : 0}
, invariant{invariant_}
{}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
if (!invariant)
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch());
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
}
std::chrono::microseconds WallClock::GetTimeUS() const {
if (!invariant)
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch());
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
if (!invariant)
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch());
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
}
s64 WallClock::GetCNTPCT() const {
if (!invariant)
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
}
s64 WallClock::GetGPUTick() const {
if (!invariant)
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
}
s64 WallClock::GetUptime() const {
if (!invariant)
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
return s64(Common::X64::FencedRDTSC());
}
bool WallClock::IsNative() const {
return invariant;
}
u64 WallClock::NsToTicks(std::chrono::nanoseconds ns) const {
return invariant ? MultiplyHigh(ns.count(), rdtsc_ns_factor) : ns.count();
}
#elif defined(HAS_NCE)
namespace {
[[nodiscard]] Common::WallClock::FactorType GetFixedPointFactor(u64 num, u64 den) noexcept {
return (Common::WallClock::FactorType(num) << 64) / den;
}
[[nodiscard]] u64 MultiplyHigh(u64 m, Common::WallClock::FactorType factor) noexcept {
return static_cast<u64>((m * factor) >> 64);
}
[[nodiscard]] s64 GetHostCNTFRQ() noexcept {
u64 cntfrq_el0 = 0;
#ifdef ANDROID
std::string_view board{""};
char buffer[PROP_VALUE_MAX];
int len{__system_property_get("ro.product.board", buffer)};
board = std::string_view(buffer, static_cast<size_t>(len));
if (board == "s5e9925") { // Exynos 2200
cntfrq_el0 = 25600000;
} else if (board == "exynos2100") { // Exynos 2100
cntfrq_el0 = 26000000;
} else if (board == "exynos9810") { // Exynos 9810
cntfrq_el0 = 26000000;
} else if (board == "s5e8825") { // Exynos 1280
cntfrq_el0 = 26000000;
} else {
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
}
return cntfrq_el0;
#else
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
return cntfrq_el0;
#endif
}
} // namespace
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {
const u64 host_cntfrq = std::max<u64>(GetHostCNTFRQ(), 1);
ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
cntfrq_ns_factor = GetFixedPointFactor(host_cntfrq, NsRatio::den);
guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
}
std::chrono::microseconds WallClock::GetTimeUS() const {
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
}
s64 WallClock::GetCNTPCT() const {
return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
}
s64 WallClock::GetGPUTick() const {
return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
}
s64 WallClock::GetUptime() const {
s64 cntvct_el0 = 0;
asm volatile(
"dsb ish\n\t"
"mrs %[cntvct_el0], cntvct_el0\n\t"
"dsb ish\n\t"
: [cntvct_el0] "=r"(cntvct_el0)
);
return cntvct_el0;
}
bool WallClock::IsNative() const {
return true;
}
u64 WallClock::NsToTicks(std::chrono::nanoseconds ns) const {
return MultiplyHigh(ns.count(), cntfrq_ns_factor);
}
#else
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch());
}
std::chrono::microseconds WallClock::GetTimeUS() const {
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch());
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch());
}
s64 WallClock::GetCNTPCT() const {
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
}
s64 WallClock::GetGPUTick() const {
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
}
s64 WallClock::GetUptime() const {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
bool WallClock::IsNative() const {
return false;
}
u64 WallClock::NsToTicks(std::chrono::nanoseconds ns) const {
return ns.count();
}
#endif
// Wall clock MUST be initialized AFTER g_cpu_caps
// C++ only guarantees ctor init in the order they appear in TU
const WallClock g_wall_clock = [] {
#if defined(ARCHITECTURE_x86_64)
auto const& caps = Common::g_cpu_caps;
return WallClock(caps.invariant_tsc && caps.tsc_frequency >= std::nano::den, caps.tsc_frequency);
#elif defined(HAS_NCE)
return WallClock(false, 1);
#else
return WallClock(true, 1);
#endif
}();
} // namespace Common

View file

@ -1,11 +1,14 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <optional>
#include <string_view>
#include <chrono>
#include <memory>
#include <ratio>
@ -43,6 +46,9 @@ public:
/// @returns Whether the clock directly uses the host's hardware clock.
bool IsNative() const;
// @returns Nanoseconds to native ticks
u64 NsToTicks(std::chrono::nanoseconds ns) const;
static inline u64 NSToCNTPCT(u64 ns) {
return ns * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
}
@ -69,7 +75,6 @@ public:
return cpu_tick * CPUTickToGPUTickRatio::num / CPUTickToGPUTickRatio::den;
}
protected:
using NsRatio = std::nano;
using UsRatio = std::micro;
using MsRatio = std::milli;
@ -87,31 +92,96 @@ protected:
using CPUTickToGPUTickRatio = std::ratio<GPUTickFreq, CPUTickFreq>;
#if defined(ARCHITECTURE_x86_64)
bool invariant;
u64 rdtsc_frequency;
u64 ns_rdtsc_factor;
u64 us_rdtsc_factor;
u64 ms_rdtsc_factor;
u64 rdtsc_ns_factor;
u64 cntpct_rdtsc_factor;
u64 gputick_rdtsc_factor;
bool invariant;
#elif defined(HAS_NCE)
public:
using FactorType = unsigned __int128;
FactorType GetGuestCNTFRQFactor() const {
[[nodiscard]] inline FactorType GetGuestCNTFRQFactor() const {
return guest_cntfrq_factor;
}
protected:
FactorType ns_cntfrq_factor;
FactorType us_cntfrq_factor;
FactorType ms_cntfrq_factor;
FactorType cntfrq_ns_factor;
FactorType guest_cntfrq_factor;
FactorType gputick_cntfrq_factor;
#else
#endif
};
[[nodiscard]] WallClock CreateOptimalClock() noexcept;
#ifdef ARCHITECTURE_x86_64
/// x86/x64 CPU capabilities that may be detected by this module
struct CPUCaps {
enum class Manufacturer : u8 {
Unknown = 0,
Intel = 1,
AMD = 2,
Hygon = 3,
};
static Manufacturer ParseManufacturer(std::string_view brand_string);
Manufacturer manufacturer;
char brand_string[13];
char cpu_string[48];
u32 base_frequency;
u32 max_frequency;
u32 bus_frequency;
u32 tsc_crystal_ratio_denominator;
u32 tsc_crystal_ratio_numerator;
u32 crystal_frequency;
u64 tsc_frequency; // Derived from the above three values
bool sse3 : 1;
bool ssse3 : 1;
bool sse4_1 : 1;
bool sse4_2 : 1;
bool avx : 1;
bool avx2 : 1;
bool avx512f : 1;
bool avx512dq : 1;
bool avx512cd : 1;
bool avx512bw : 1;
bool avx512vl : 1;
bool avx512vbmi : 1;
bool avx512bitalg : 1;
bool aes : 1;
bool bmi1 : 1;
bool bmi2 : 1;
bool f16c : 1;
bool fma : 1;
bool gfni : 1;
bool invariant_tsc : 1;
bool lzcnt : 1;
bool monitorx : 1;
bool movbe : 1;
bool pclmulqdq : 1;
bool popcnt : 1;
bool sha : 1;
bool waitpkg : 1;
};
#else
struct CPUCaps {
bool padding;
};
#endif
/// Detects CPU core count
std::optional<int> GetProcessorCount();
/// @brief Global cpu caps
extern const CPUCaps g_cpu_caps;
/// @brief Global wall clock
extern const WallClock g_wall_clock;
} // namespace Common

View file

@ -62,16 +62,20 @@ std::vector<Asset> Release::GetPlatformAssets() const {
#ifdef _WIN32
#ifdef ARCHITECTURE_x86_64
find_asset("Standard", {"amd64-msvc-standard.exe", "amd64-msvc-standard.zip", "mingw-amd64-gcc-standard.exe", "mingw-amd64-gcc-standard.zip"});
find_asset("PGO", {"mingw-amd64-clang-pgo.exe", "mingw-amd64-clang-pgo.zip"});
#ifdef _MSC_VER
find_asset("Standard", {"amd64-msvc-standard.exe", "amd64-msvc-standard.zip"});
#else // _MSC_VER
find_asset("Standard", {BUILD_ID "-gcc-standard.exe", BUILD_ID "-gcc-standard.zip"});
find_asset("PGO", {BUILD_ID "-clang-pgo.exe", BUILD_ID "-clang-pgo.zip"});
#endif // _MSC_VER
#elif defined(ARCHITECTURE_arm64)
find_asset("Standard", {"mingw-arm64-clang-standard.exe", "mingw-arm64-clang-standard.zip"});
find_asset("PGO", {"mingw-arm64-clang-pgo.exe", "mingw-arm64-clang-pgo.zip"});
#endif
find_asset("Standard", {"arm64-clang-standard.exe", "arm64-clang-standard.zip"});
find_asset("PGO", {"arm64-clang-pgo.exe", "arm64-clang-pgo.zip"});
#endif // ARCHITECTURE_arm64
#elif defined(__APPLE__)
#ifdef ARCHITECTURE_arm64
find_asset("Standard", {".dmg", ".tar.gz"});
#endif
#endif // ARCHITECTURE_arm64
#elif defined(__ANDROID__)
#ifdef ARCHITECTURE_x86_64
find_asset("Standard", {"chromeos.apk"});
@ -82,9 +86,9 @@ std::vector<Asset> Release::GetPlatformAssets() const {
find_asset("Standard", {"optimized.apk"});
#else
find_asset("Standard", {"standard.apk"});
#endif
#endif
#endif
#endif // GENSHIN_SPOOF
#endif // ARCHITECTURE_arm64
#endif // __APPLE__
return found_assets;
}

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@ -20,10 +20,14 @@
namespace Common {
struct SlotId {
static constexpr u32 TAGGED_MASK = 0x7fffffff;
static constexpr u32 TAGGED_VALUE = 0x80000000;
static constexpr u32 INVALID_INDEX = (std::numeric_limits<u32>::max)();
constexpr u32 Value() const noexcept {
return index & (~TAGGED_VALUE);
}
constexpr auto operator<=>(const SlotId&) const noexcept = default;
constexpr explicit operator bool() const noexcept {
return index != INVALID_INDEX;
}
@ -47,12 +51,12 @@ public:
Iterator& operator++() noexcept {
const u64* const bitset = slot_vector->stored_bitset.data();
const u32 size = static_cast<u32>(slot_vector->stored_bitset.size()) * 64;
if (id.index < size) {
if (id.Value() < size) {
do {
++id.index;
} while (id.index < size && !IsValid(bitset));
if (id.index == size) {
id.index = SlotId::INVALID_INDEX;
} while (id.Value() < size && !IsValid(bitset));
if (id.Value() == size) {
id = SlotId{};
}
}
return *this;
@ -85,7 +89,7 @@ public:
: slot_vector{slot_vector_}, id{id_} {}
bool IsValid(const u64* bitset) const noexcept {
return ((bitset[id.index / 64] >> (id.index % 64)) & 1) != 0;
return ((bitset[id.Value() / 64] >> (id.Value() % 64)) & 1) != 0;
}
SlotVector<T>* slot_vector;
@ -107,12 +111,12 @@ public:
[[nodiscard]] T& operator[](SlotId id) noexcept {
ValidateIndex(id);
return values[id.index].object;
return values[id.Value()].object;
}
[[nodiscard]] const T& operator[](SlotId id) const noexcept {
ValidateIndex(id);
return values[id.index].object;
return values[id.Value()].object;
}
template <typename... Args>
@ -125,9 +129,9 @@ public:
}
void erase(SlotId id) noexcept {
values[id.index].object.~T();
free_list.push_back(id.index);
ResetStorageBit(id.index);
values[id.Value()].object.~T();
free_list.push_back(id.Value());
ResetStorageBit(id.Value());
}
[[nodiscard]] Iterator begin() noexcept {
@ -141,7 +145,7 @@ public:
}
[[nodiscard]] Iterator end() noexcept {
return Iterator(this, SlotId{SlotId::INVALID_INDEX});
return Iterator(this, SlotId{});
}
[[nodiscard]] size_t size() const noexcept {
@ -175,8 +179,8 @@ private:
void ValidateIndex(SlotId id) const noexcept {
DEBUG_ASSERT(id);
DEBUG_ASSERT(id.index / 64 < stored_bitset.size());
DEBUG_ASSERT(((stored_bitset[id.index / 64] >> (id.index % 64)) & 1) != 0);
DEBUG_ASSERT(id.Value() / 64 < stored_bitset.size());
DEBUG_ASSERT(((stored_bitset[id.Value() / 64] >> (id.Value() % 64)) & 1) != 0);
}
[[nodiscard]] u32 FreeValueIndex() noexcept {
@ -208,9 +212,7 @@ private:
const size_t old_free_size = free_list.size();
free_list.resize(old_free_size + (new_capacity - values_capacity));
std::iota(free_list.begin() + old_free_size, free_list.end(),
static_cast<u32>(values_capacity));
std::iota(free_list.begin() + old_free_size, free_list.end(), u32(values_capacity));
delete[] values;
values = new_values;
values_capacity = new_capacity;

View file

@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <chrono>
#include <limits>
#include <string>
#include <thread>
@ -18,24 +20,35 @@
#elif defined(_WIN32)
#include <windows.h>
#include "common/string_util.h"
#include "common/windows/timer_resolution.h"
#else
#if defined(__FreeBSD__)
#include <sys/cpuset.h>
#include <sys/_cpuset.h>
#include <pthread_np.h>
// Compatibility with CPUset
#define cpu_set_t cpuset_t
#elif defined(__DragonFly__) || defined(__OpenBSD__) || defined(__Bitrig__)
#include <pthread_np.h>
#endif
#include <pthread.h>
#include <sched.h>
#endif
#ifndef _WIN32
#include <unistd.h>
#endif
#ifdef __FreeBSD__
# define cpu_set_t cpuset_t
#include "common/cpu_features.h"
#ifdef ARCHITECTURE_x86_64
#ifdef _MSC_VER
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#include "common/x64/rdtsc.h"
#endif
#include "core/core_timing.h"
namespace Common {
@ -144,4 +157,102 @@ void PinCurrentThreadToPerformanceCore(size_t core_id) {
}
}
#ifdef ARCHITECTURE_x86_64
// On Linux and UNIX systems, a futex would nominally be used to cover the costs
// the idea is that it's intuitivelly cheaper to use a direct instruction as opposed to a full futex call
// the underlying libc++ implementation uses pthread_cond_timedwait which MAY invoke a futex
// Let's pretend the OS is too expensive to jump into, and avoid ANY context switches
// this should *IN THEORY* lower CPU usage while just waiting for stuff effectively
// For windows the minimal quanta resolution is about 500us, and normal CRT cond var is 1.5ms(?)
// so may as well avoid that too
// Let's just give ALL platforms the same mechanisms (almost) for when they have umonitor OR waitpkg
#ifdef __clang__
__attribute__((target("waitpkg,mwaitx")))
#elif defined(__GNUC__)
#pragma GCC target("waitpkg")
#pragma GCC target("mwaitx")
#endif
bool Event::WaitFor(const std::chrono::nanoseconds time) {
#ifdef _WIN32
auto const start = Common::X64::FencedRDTSC();
auto const& caps = Common::g_cpu_caps;
[[maybe_unused]] auto const end = start + Common::g_wall_clock.NsToTicks(time);
if (caps.monitorx) {
while (true) {
// Armed monitor, as per manual, MWAITX must be conditional if the condition isn't satisfied
// to prevent a race condition.
_mm_monitorx(reinterpret_cast<u64*>(std::addressof(is_set)), 0, 0);
if (!is_set.load()) {
// RDTSC may be fenced here due to atomic load
#ifdef _MSC_VER
auto const now = __rdtsc();
#else
auto const now = _rdtsc();
#endif
if (end > now) {
u32 const cycles = std::min<u32>((std::numeric_limits<u32>::max)(), s64(end) - s64(now));
// See here: https://github.com/torvalds/linux/blob/948a64995aca6820abefd17f1a4258f5835c5ad9/arch/x86/lib/delay.c#L93
// MWAITX accepts a 32-bit input timer which determines the total number of cycles to wait for
// NOT THE TOTAL ABSOLUTE TSC VALUE, it's just a delta
// BIT[1] = use a timer
// Hint = 0: Use C1 state when sleepy (means slower wakeup but better savings)
_mm_mwaitx(1 << 1, 0u, cycles);
if (!is_set.load())
return false;
} else
return false; //timeout
}
bool expected = true;
if (is_set.compare_exchange_weak(expected, false, std::memory_order_release))
return true;
}
} else if (caps.waitpkg) {
// #UD If CPUID.7.0:ECX.WAITPKG[bit 5]=0.
while (true) {
_umonitor(std::addressof(is_set));
if (!is_set.load() && !_umwait(0, end)) //umwait is absolute time!!!
return false;
bool expected = true;
if (is_set.compare_exchange_weak(expected, false, std::memory_order_release))
return true;
}
} else {
#ifdef _MSC_VER
while (!is_set.load() && end > __rdtsc())
Common::Windows::SleepForOneTick();
#else
while (!is_set.load() && end > _rdtsc())
Common::Windows::SleepForOneTick();
#endif
if (is_set.load())
Reset();
return true;
}
#else
std::unique_lock lk{mutex};
if (!condvar.wait_for(lk, time, [this] { return is_set.load(); }))
return false;
is_set = false;
return true;
#endif
}
#else
bool Event::WaitFor(const std::chrono::nanoseconds time) {
#ifdef _WIN32
auto const end = Common::g_wall_clock.GetTimeNS() + time;
while (!is_set.load() && end > Common::g_wall_clock.GetTimeNS())
Common::Windows::SleepForOneTick();
if (is_set.load())
Reset();
return true;
#else
std::unique_lock lk{mutex};
if (!condvar.wait_for(lk, time, [this] { return is_set.load(); }))
return false;
is_set = false;
return true;
#endif
}
#endif
} // namespace Common

View file

@ -34,16 +34,10 @@ public:
is_set = false;
}
bool WaitFor(const std::chrono::nanoseconds& time) {
std::unique_lock lk{mutex};
if (!condvar.wait_for(lk, time, [this] { return is_set.load(); }))
return false;
is_set = false;
return true;
}
bool WaitFor(const std::chrono::nanoseconds time);
template <class Clock, class Duration>
bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
template<class Clock, class Duration>
bool WaitUntil(const std::chrono::time_point<Clock, Duration> time) {
std::unique_lock lk{mutex};
if (!condvar.wait_until(lk, time, [this] { return is_set.load(); }))
return false;
@ -63,9 +57,9 @@ public:
}
private:
alignas(64) std::atomic<bool> is_set{false};
std::condition_variable condvar;
std::mutex mutex;
std::atomic_bool is_set{false};
};
class Barrier {

View file

@ -1,197 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/steady_clock.h"
#include "common/uint128.h"
#include "common/wall_clock.h"
#ifdef __ANDROID__
#include <sys/system_properties.h>
#endif
#ifdef ARCHITECTURE_x86_64
#include "common/x64/cpu_detect.h"
#include "common/x64/rdtsc.h"
#endif
namespace Common {
#if defined(ARCHITECTURE_x86_64)
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept
: invariant{invariant_}
, rdtsc_frequency{rdtsc_frequency_}
, ns_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency_)}
, us_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency_)}
, ms_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency_)}
, cntpct_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency_)}
, gputick_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency_)}
{}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
if (invariant)
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
}
std::chrono::microseconds WallClock::GetTimeUS() const {
if (invariant)
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
if (invariant)
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
}
s64 WallClock::GetCNTPCT() const {
if (invariant)
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
}
s64 WallClock::GetGPUTick() const {
if (invariant)
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
}
s64 WallClock::GetUptime() const {
if (invariant)
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
return s64(Common::X64::FencedRDTSC());
}
bool WallClock::IsNative() const {
if (invariant)
return false;
return true;
}
#elif defined(HAS_NCE)
namespace {
[[nodiscard]] WallClock::FactorType GetFixedPointFactor(u64 num, u64 den) noexcept {
return (WallClock::FactorType(num) << 64) / den;
}
[[nodiscard]] u64 MultiplyHigh(u64 m, WallClock::FactorType factor) noexcept {
return static_cast<u64>((m * factor) >> 64);
}
[[nodiscard]] s64 GetHostCNTFRQ() noexcept {
u64 cntfrq_el0 = 0;
#ifdef ANDROID
std::string_view board{""};
char buffer[PROP_VALUE_MAX];
int len{__system_property_get("ro.product.board", buffer)};
board = std::string_view(buffer, static_cast<size_t>(len));
if (board == "s5e9925") { // Exynos 2200
cntfrq_el0 = 25600000;
} else if (board == "exynos2100") { // Exynos 2100
cntfrq_el0 = 26000000;
} else if (board == "exynos9810") { // Exynos 9810
cntfrq_el0 = 26000000;
} else if (board == "s5e8825") { // Exynos 1280
cntfrq_el0 = 26000000;
} else {
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
}
return cntfrq_el0;
#else
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
return cntfrq_el0;
#endif
}
} // namespace
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {
const u64 host_cntfrq = std::max<u64>(GetHostCNTFRQ(), 1);
ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
}
std::chrono::microseconds WallClock::GetTimeUS() const {
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
}
s64 WallClock::GetCNTPCT() const {
return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
}
s64 WallClock::GetGPUTick() const {
return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
}
s64 WallClock::GetUptime() const {
s64 cntvct_el0 = 0;
asm volatile(
"dsb ish\n\t"
"mrs %[cntvct_el0], cntvct_el0\n\t"
"dsb ish\n\t"
: [cntvct_el0] "=r"(cntvct_el0)
);
return cntvct_el0;
}
bool WallClock::IsNative() const {
return true;
}
#else
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
}
std::chrono::microseconds WallClock::GetTimeUS() const {
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
}
s64 WallClock::GetCNTPCT() const {
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
}
s64 WallClock::GetGPUTick() const {
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
}
s64 WallClock::GetUptime() const {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
bool WallClock::IsNative() const {
return false;
}
#endif
WallClock CreateOptimalClock() noexcept {
#if defined(ARCHITECTURE_x86_64)
auto const& caps = GetCPUCaps();
return WallClock(!(caps.invariant_tsc && caps.tsc_frequency >= std::nano::den), caps.tsc_frequency);
#elif defined(HAS_NCE)
return WallClock(false, 1);
#else
return WallClock(true, 1);
#endif
}
} // namespace Common

View file

@ -1,82 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <optional>
#include <string_view>
#include "common/common_types.h"
namespace Common {
/// x86/x64 CPU capabilities that may be detected by this module
struct CPUCaps {
enum class Manufacturer : u8 {
Unknown = 0,
Intel = 1,
AMD = 2,
Hygon = 3,
};
static Manufacturer ParseManufacturer(std::string_view brand_string);
Manufacturer manufacturer;
char brand_string[13];
char cpu_string[48];
u32 base_frequency;
u32 max_frequency;
u32 bus_frequency;
u32 tsc_crystal_ratio_denominator;
u32 tsc_crystal_ratio_numerator;
u32 crystal_frequency;
u64 tsc_frequency; // Derived from the above three values
bool sse3 : 1;
bool ssse3 : 1;
bool sse4_1 : 1;
bool sse4_2 : 1;
bool avx : 1;
bool avx2 : 1;
bool avx512f : 1;
bool avx512dq : 1;
bool avx512cd : 1;
bool avx512bw : 1;
bool avx512vl : 1;
bool avx512vbmi : 1;
bool avx512bitalg : 1;
bool aes : 1;
bool bmi1 : 1;
bool bmi2 : 1;
bool f16c : 1;
bool fma : 1;
bool gfni : 1;
bool invariant_tsc : 1;
bool lzcnt : 1;
bool monitorx : 1;
bool movbe : 1;
bool pclmulqdq : 1;
bool popcnt : 1;
bool sha : 1;
bool waitpkg : 1;
};
/**
* Gets the supported capabilities of the host CPU
* @return Reference to a CPUCaps struct with the detected host CPU capabilities
*/
const CPUCaps& GetCPUCaps();
/// Detects CPU core count
std::optional<int> GetProcessorCount();
} // namespace Common

View file

@ -1,75 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <thread>
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include "common/x64/cpu_detect.h"
#include "common/x64/cpu_wait.h"
#include "common/x64/rdtsc.h"
namespace Common::X64 {
namespace {
// 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
// For reference:
// At 1 GHz, 100K cycles is 100us
// At 2 GHz, 100K cycles is 50us
// At 4 GHz, 100K cycles is 25us
constexpr auto PauseCycles = 100'000U;
} // Anonymous namespace
#if defined(_MSC_VER) && !defined(__clang__)
__forceinline static void TPAUSE() {
static constexpr auto RequestC02State = 0U;
_tpause(RequestC02State, FencedRDTSC() + PauseCycles);
}
__forceinline static void MWAITX() {
static constexpr auto EnableWaitTimeFlag = 1U << 1;
static constexpr auto RequestC1State = 0U;
// monitor_var should be aligned to a cache line.
alignas(64) u64 monitor_var{};
_mm_monitorx(&monitor_var, 0, 0);
_mm_mwaitx(EnableWaitTimeFlag, RequestC1State, PauseCycles);
}
#else
static void TPAUSE() {
static constexpr auto RequestC02State = 0U;
const auto tsc = FencedRDTSC() + PauseCycles;
const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF);
const auto edx = static_cast<u32>(tsc >> 32);
asm volatile("tpause %0" : : "r"(RequestC02State), "d"(edx), "a"(eax));
}
static void MWAITX() {
static constexpr auto EnableWaitTimeFlag = 1U << 1;
static constexpr auto RequestC1State = 0U;
// monitor_var should be aligned to a cache line.
alignas(64) u64 monitor_var{};
asm volatile("monitorx" : : "a"(&monitor_var), "c"(0), "d"(0));
asm volatile("mwaitx" : : "a"(RequestC1State), "b"(PauseCycles), "c"(EnableWaitTimeFlag));
}
#endif
void MicroSleep() {
static const bool has_waitpkg = GetCPUCaps().waitpkg;
static const bool has_monitorx = GetCPUCaps().monitorx;
if (has_waitpkg) {
TPAUSE();
} else if (has_monitorx) {
MWAITX();
} else {
std::this_thread::yield();
}
}
} // namespace Common::X64

View file

@ -1,10 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
namespace Common::X64 {
void MicroSleep();
} // namespace Common::X64

View file

@ -1200,7 +1200,7 @@ else()
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type>
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>)
# pre-clang19 will spam with "OH DID YOU MEAN THIS?" otherwise...
if (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19)
if (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20)
target_compile_options(core PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type-mismatch>)
endif()
endif()
@ -1246,7 +1246,7 @@ if (HAS_NCE)
target_link_libraries(core PRIVATE merry::oaknut)
endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64)
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64)
target_sources(core PRIVATE
arm/dynarmic/arm_dynarmic.h
arm/dynarmic/arm_dynarmic_64.cpp

View file

@ -1,9 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <dynarmic/interface/halt_reason.h>
#include "core/arm/arm_interface.h"

View file

@ -1,9 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 Skyline Team and Contributors
// SPDX-License-Identifier: MPL-2.0
#pragma once
#include "common/bit_field.h"
#include "common/common_types.h"

View file

@ -3,7 +3,7 @@
#include <numeric>
#include <bit>
#include "common/wall_clock.h"
#include "common/cpu_features.h"
#include "common/alignment.h"
#include "common/literals.h"
#include "core/arm/nce/arm_nce.h"

View file

@ -8,15 +8,13 @@
#include <mutex>
#include <string>
#include <tuple>
#include "common/cpu_features.h"
#include "common/cpu_features.h"
#ifdef _WIN32
#include "common/windows/timer_resolution.h"
#endif
#ifdef ARCHITECTURE_x86_64
#include "common/x64/cpu_wait.h"
#endif
#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hardware_properties.h"
@ -47,8 +45,7 @@ struct CoreTiming::Event {
}
};
CoreTiming::CoreTiming() : clock{Common::CreateOptimalClock()} {}
CoreTiming::CoreTiming() = default;
CoreTiming::~CoreTiming() {
Reset();
}
@ -64,31 +61,16 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
on_thread_init();
has_started = true;
// base frequency in MHz: 1ns (10^-9) = 1GHz (10^9)
while (!stop_token.stop_requested()) {
while (!paused && !stop_token.stop_requested()) {
paused_set = false;
if (auto const next_time = Advance(); next_time) {
// There are more events left in the queue, wait until the next event.
auto wait_time = *next_time - GetGlobalTimeNs().count();
auto const wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time > 0) {
#ifdef _WIN32
while (!paused && !event.IsSet() && wait_time > 0) {
wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time >= timer_resolution_ns) {
Common::Windows::SleepForOneTick();
} else {
#ifdef ARCHITECTURE_x86_64
Common::X64::MicroSleep();
#else
std::this_thread::yield();
#endif
}
}
if (event.IsSet())
event.Reset();
#else
event.WaitFor(std::chrono::nanoseconds(wait_time));
#endif
}
} else {
// Queue is empty, wait until another event is scheduled and signals us to
@ -226,7 +208,7 @@ void CoreTiming::ResetTicks() {
}
u64 CoreTiming::GetClockTicks() const {
u64 fres = is_multicore ? clock.GetCNTPCT() : Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
u64 fres = is_multicore ? Common::g_wall_clock.GetCNTPCT() : Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
if (auto const overclock = Settings::values.fast_cpu_time.GetValue(); overclock != Settings::CpuClock::Off) {
fres = u64(f64(fres) * (1.7 + 0.3 * u32(overclock)));
}
@ -240,7 +222,7 @@ u64 CoreTiming::GetClockTicks() const {
u64 CoreTiming::GetGPUTicks() const {
return is_multicore
? clock.GetGPUTick()
? Common::g_wall_clock.GetGPUTick()
: Common::WallClock::CPUTickToGPUTick(cpu_ticks);
}
@ -317,14 +299,14 @@ void CoreTiming::Reset() {
/// @brief Returns current time in nanoseconds.
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const noexcept {
return is_multicore
? clock.GetTimeNS()
? Common::g_wall_clock.GetTimeNS()
: std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};
}
/// @brief Returns current time in microseconds.
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const noexcept {
return is_multicore
? clock.GetTimeUS()
? Common::g_wall_clock.GetTimeUS()
: std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
}

View file

@ -19,7 +19,7 @@
#include "common/common_types.h"
#include "common/thread.h"
#include "common/wall_clock.h"
#include "common/cpu_features.h"
namespace Core::Timing {
@ -142,37 +142,28 @@ public:
void Reset();
Common::WallClock clock;
using heap_t = boost::heap::fibonacci_heap<CoreTiming::Event, boost::heap::compare<std::greater<>>>;
heap_t event_queue;
s64 global_timer = 0;
#ifdef _WIN32
s64 timer_resolution_ns;
#endif
using heap_t =
boost::heap::fibonacci_heap<CoreTiming::Event, boost::heap::compare<std::greater<>>>;
heap_t event_queue;
u64 event_fifo_id = 0;
s64 pause_end_time{};
/// Cycle timing
u64 cpu_ticks{};
s64 downcount{};
Common::Event event{};
Common::Event pause_event{};
std::function<void()> on_thread_init{};
std::jthread timer_thread;
mutable std::mutex basic_lock;
std::mutex advance_lock;
std::jthread timer_thread;
std::atomic<bool> paused{};
std::atomic<bool> paused_set{};
std::atomic<bool> wait_set{};
std::atomic<bool> has_started{};
std::function<void()> on_thread_init{};
bool is_multicore{};
s64 pause_end_time{};
/// Cycle timing
u64 cpu_ticks{};
s64 downcount{};
};
/// Creates a core timing event with the given name and callback.

View file

@ -1,6 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/typed_address.h"
namespace Kernel {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -12,8 +15,8 @@ Result DebugActiveProcess(Core::System& system, Handle* out_handle, uint64_t pro
}
Result BreakDebugProcess(Core::System& system, Handle debug_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
LOG_WARNING(Service, "(STUBBED) called");
R_SUCCEED();
}
Result TerminateDebugProcess(Core::System& system, Handle debug_handle) {

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -372,6 +375,10 @@ bool LifecycleManager::UpdateRequestedFocusState() {
// Mark the focus state as ready for update.
m_requested_focus_state = new_state;
if (m_is_application) {
m_has_focus_state_changed = true;
}
// We changed the focus state.
return true;
}

View file

@ -151,7 +151,7 @@ Result IFileSystem::GetTotalSpaceSize(
Result IFileSystem::GetFileTimeStampRaw(
Out<FileSys::FileTimeStampRaw> out_timestamp,
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path) {
LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", path->str);
LOG_DEBUG(Service_FS, "(Partial Implementation) called. file={}", path->str);
FileSys::FileTimeStampRaw vfs_timestamp{};
R_TRY(backend->GetFileTimeStampRaw(&vfs_timestamp, FileSys::Path(path->str)));

View file

@ -10,6 +10,7 @@
#include "common/assert.h"
#include "common/logging.h"
#include "common/settings.h"
#include "common/cpu_features.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
#include "core/hle/kernel/kernel.h"
@ -28,7 +29,6 @@ BufferQueueProducer::BufferQueueProducer(Service::KernelHelpers::ServiceContext&
Service::Nvidia::NvCore::NvMap& nvmap_)
: service_context{service_context_}, core{std::move(buffer_queue_core_)}
, slots(core->slots)
, clock{Common::CreateOptimalClock()}
, nvmap(nvmap_)
{
buffer_wait_event = service_context.CreateEvent("BufferQueue:WaitEvent");
@ -488,7 +488,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
slots[slot].buffer_state = BufferState::Queued;
slots[slot].frame_number = core->frame_counter;
slots[slot].queue_time = timestamp;
slots[slot].presentation_time = clock.GetTimeNS().count();
slots[slot].presentation_time = Common::g_wall_clock.GetTimeNS().count();
slots[slot].fence = fence;
item.slot = slot;

View file

@ -14,7 +14,7 @@
#include <mutex>
#include "common/common_funcs.h"
#include "common/wall_clock.h"
#include "common/cpu_features.h"
#include "core/hle/service/nvdrv/nvdata.h"
#include "core/hle/service/nvnflinger/binder.h"
#include "core/hle/service/nvnflinger/buffer_queue_defs.h"
@ -89,7 +89,6 @@ private:
s32 next_callback_ticket{};
s32 current_callback_ticket{};
std::condition_variable_any callback_condition;
Common::WallClock clock;
Service::Nvidia::NvCore::NvMap& nvmap;
};

View file

@ -1,6 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

View file

@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <ankerl/unordered_dense.h>
#include "common/uuid.h"

View file

@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

View file

@ -1,6 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ns/ns_types.h"
#include "core/hle/service/service.h"

View file

@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include "common/uuid.h"

View file

@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

View file

@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
@ -13,7 +13,7 @@
#include "common/common_types.h"
#include "common/intrusive_list.h"
#include "common/uuid.h"
#include "common/wall_clock.h"
#include "common/cpu_features.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/psc/time/errors.h"

View file

@ -1,6 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/result.h"
namespace Service::RO {

View file

@ -4,6 +4,8 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/assert.h"
#include "common/common_funcs.h"
#include "common/common_types.h"

View file

@ -1,6 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <map>
#include <set>

View file

@ -1,9 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/math_util.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/nvnflinger/ui/fence.h"

View file

@ -130,6 +130,10 @@ if ("riscv64" IN_LIST ARCHITECTURE)
find_package(biscuit 0.9.1 REQUIRED)
endif()
if ("loongarch64" IN_LIST ARCHITECTURE)
find_package(lagoon REQUIRED)
endif()
if ("x86_64" IN_LIST ARCHITECTURE)
find_package(xbyak 7 CONFIG)
endif()

View file

@ -295,6 +295,20 @@ if ("riscv64" IN_LIST ARCHITECTURE)
message(WARNING "TODO: Incomplete frontend for this host architecture")
endif()
if ("loongarch64" IN_LIST ARCHITECTURE)
target_link_libraries(dynarmic PRIVATE lagoon::lagoon)
target_sources(dynarmic PRIVATE
backend/loongarch64/exclusive_monitor.cpp
backend/loongarch64/a32_interface.cpp
backend/loongarch64/a64_interface.cpp
backend/loongarch64/code_block.h
common/spin_lock_loongarch64.cpp
)
message(WARNING "TODO: Incomplete frontend for this host architecture")
endif()
if (WIN32)
target_sources(dynarmic PRIVATE backend/exception_handler_windows.cpp)
elseif (APPLE)

View file

@ -6,6 +6,7 @@
* SPDX-License-Identifier: 0BSD
*/
#pragma once
#include <cstddef>
namespace oaknut {

View file

@ -24,7 +24,7 @@ using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
constexpr std::size_t xmrx(std::size_t x) noexcept {
x ^= x >> 32;
x *= 0xff51afd7ed558ccd;
x ^= mcl::bit::rotate_right(x, 47) ^ mcl::bit::rotate_right(x, 23);
x ^= std::rotr(x, 47) ^ std::rotr(x, 23);
return x;
}

View file

@ -26,6 +26,10 @@ class CodeBlock;
namespace Dynarmic::Backend::RV64 {
class CodeBlock;
} // namespace Dynarmic::Backend::RV64
#elif defined(ARCHITECTURE_loongarch64)
namespace Dynarmic::Backend::LoongArch64 {
class CodeBlock;
} // namespace Dynarmic::Backend::LoongArch64
#else
# error "Invalid architecture"
#endif
@ -45,6 +49,10 @@ struct FakeCall {
struct FakeCall {
u64 call_sepc;
};
#elif defined(ARCHITECTURE_loongarch64)
struct FakeCall {
u64 call_pc;
};
#else
# error "Invalid architecture"
#endif
@ -60,6 +68,8 @@ public:
void Register(oaknut::CodeBlock& mem, std::size_t mem_size);
#elif defined(ARCHITECTURE_riscv64)
void Register(RV64::CodeBlock& mem, std::size_t mem_size);
#elif defined(ARCHITECTURE_loongarch64)
void Register(LoongArch64::CodeBlock& mem, std::size_t mem_size);
#else
# error "Invalid architecture"
#endif

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