Compare commits

...

177 Commits

Author SHA1 Message Date
liushuyu 09f4f3f23b logging/log.h: move enum class formatter to a separate file ...
... to common/logging/formatter.h
2022-01-09 17:35:33 -07:00
liushuyu a1054a093c cmake: upgrade Conan package fmt to 8.1.1 ...
... requirements for fmt stays at ^8.0.1
2022-01-08 16:03:18 -07:00
liushuyu 099dd0c0d2 logging/log: use underlying_type instead of hardcoding types 2022-01-08 16:02:49 -07:00
liushuyu 42f653ab6f logging: adapt to changes in fmt 8.1 2022-01-08 01:49:26 -07:00
bunnei 26f4e92c1f Merge pull request #7680 from german77/accel_mapping
input_common: Allow to only have acceleration motion data
2022-01-08 00:06:15 -08:00
german77 50a7152941 core/hid: Set minimum gyro threshold 2022-01-06 20:05:59 -06:00
german77 4b4af29f86 input_common: Use accelerometer data for mapping 2022-01-06 20:05:49 -06:00
Fernando S a95c49e7d0 Merge pull request #7658 from ameerj/sparse-fixes
video_core/memory_manager: Fixes for sparse memory management
2022-01-06 13:50:14 +01:00
Mai M 2897ddb8f5 Merge pull request #7679 from liushuyu/update-dynarmic
externals/dynarmic: update to the latest revision
2022-01-06 07:42:55 -05:00
liushuyu b590e5572d externals/dynarmic: update to latest revision ...
... to resolve compilation errors with fmt 8.1
2022-01-06 04:06:43 -07:00
bunnei f46e1b8ca2 Merge pull request #7674 from lat9nq/fix-custom-highlight
configure_per_game: Initialize tabs after loading custom configuration
2022-01-05 16:14:15 -08:00
Mai M 7116a7d28b Merge pull request #7673 from german77/no_return
glsl: Remove unreachable return
2022-01-05 06:41:16 -05:00
Mai M 37a3b89e7a Merge pull request #7675 from zhaobot/tx-update-20220105075447
Update translations (2022-01-05)
2022-01-05 06:40:30 -05:00
The yuzu Community 7c88f4de2d Update translations (2022-01-05) 2022-01-05 07:55:04 +00:00
lat9nq 62c13e8318 configure_per_game: Initialize tabs after loading custom configuration
Changes tab initialization to happen after the configuration is loaded,
which means that it no longer happens as member initializers in the
ConfigurePerGame constructor. Removes the cluster of
??_tab->SetConfiguration's that I added earlier to get around this issue
initially.

Fixes a regression in #6774
2022-01-04 23:43:19 -05:00
Narr the Reg 41bbb31af4 video_core: Remove unnecesary maybe_unused flag 2022-01-04 21:25:47 -06:00
Narr the Reg 524674aafc glsl: Remove unreachable return 2022-01-04 20:23:39 -06:00
bunnei 6af82fd070 Merge pull request #7610 from Tatsh/more-system-libs
Add support for linking against system Opus
2022-01-04 17:32:35 -08:00
bunnei afb06b1495 Merge pull request #7636 from vonchenplus/buffer_queue_query
core:hle:service:nvflinger Implement few type in bufferqueue query method
2022-01-04 11:28:49 -08:00
Fernando S 118d5fa3b0 Merge pull request #7670 from ameerj/vsync-block
gpu: Add shut down method to synchronize threads before destruction
2022-01-04 14:16:24 +01:00
bunnei c68a0d17fc Merge pull request #7251 from FernandoS27/shader-dump
ShaderDecompiler: Add a debug option to dump the game's shaders.
2022-01-03 17:56:30 -08:00
ameerj c17938f96b gpu: Add shut down method to synchronize threads before destruction 2022-01-03 20:47:26 -05:00
Fernando Sahmkow f58ee3f15f ShaderDecompiler: Add a debug option to dump the game's shaders. 2022-01-04 02:39:00 +01:00
ameerj 7652543231 Revert "Merge pull request #7668 from ameerj/fence-stop-token"
This reverts commit e773354477, reversing
changes made to abbbdc2bc0.
2022-01-03 20:28:54 -05:00
bunnei e773354477 Merge pull request #7668 from ameerj/fence-stop-token
gpu: Use std::stop_token in WaitFence for VSync thread
2022-01-03 16:40:36 -08:00
bunnei abbbdc2bc0 Merge pull request #7664 from german77/fallback
core/hid: Add fallback to fullkey controllers
2022-01-03 15:04:37 -08:00
bunnei 05b7b177f6 Merge pull request #7662 from german77/uistatus
yuzu: Fix UI elements not updating correctly
2022-01-03 13:24:15 -08:00
bunnei b89d096652 Merge pull request #7663 from german77/applet
controller_applet: Only populate supported controllers
2022-01-03 10:51:51 -08:00
ameerj d866916f42 gpu: Use std::stop_token in WaitFence for VSync thread
Fixes a hang that may occur when stopping emulation and the VSync thread is blocked on the syncpoint condition variable.
2022-01-03 12:31:33 -05:00
Fernando S da8e0f6571 Merge pull request #7648 from bunnei/thread-pinning
core: hle: kernel: Implement thread pinning.
2022-01-03 02:01:26 +01:00
Fernando S 3fa9702952 Merge pull request #7624 from ameerj/intel-msaa-scale
vk_texture_cache: Use 3D scale helpers for MSAA texture scaling on Intel Windows drivers
2022-01-03 00:40:14 +01:00
Fernando S ae7da0b12d Merge pull request #7629 from ameerj/nv-driver-fixes
shaders: Add fixes for NVIDIA drivers 495+
2022-01-03 00:39:59 +01:00
german77 7a13a515d9 core/hid: Add fallback to fullkey controllers 2022-01-01 22:01:13 -06:00
german77 133f497f84 controller_applet: Only populate supported controllers 2022-01-01 21:42:17 -06:00
german77 a9ad983c13 yuzu: Fix UI elements not updating correctly 2022-01-01 17:57:43 -06:00
Fernando S 214b9fc9a7 Merge pull request #7659 from ameerj/overlap-overflow
texture_cache/util: Fix s32 overflow when resolving overlaps
2022-01-01 22:10:29 +01:00
ameerj 951c61aeaa texture_cache/util: Fix s32 overflow when resolving overlaps 2021-12-31 20:03:22 -05:00
ameerj 285b6dbc39 video_core/memory_manager: Fixes for sparse memory management 2021-12-31 17:04:02 -05:00
Mai M eb7d361657 Merge pull request #7654 from Morph1984/dynarmic
externals: Update dynarmic to 28714ee7
2021-12-31 02:49:16 -05:00
ameerj 2428214c4b video_core/memory_manager: Deduplicate Read/WriteBlock 2021-12-31 02:08:22 -05:00
Morph af89f7683d externals: Update dynarmic to 28714ee7
Reduces compilation times on MSVC.
2021-12-30 22:28:27 -05:00
bunnei 667a8ae163 Merge pull request #7647 from german77/toad
core/hid: Fix controller type validation
2021-12-30 16:54:35 -08:00
bunnei 3a89723d97 core: hle: kernel: Implement thread pinning.
- We largely had the mechanics in place for thread pinning, this change hooks these up.
- Validated with tests https://github.com/Atmosphere-NX/Atmosphere/blob/master/tests/TestSvc/source/test_thread_pinning.cpp.
2021-12-30 15:50:45 -08:00
german77 9ee5c4ec56 core/hid: Fix controller type validation 2021-12-29 22:51:53 -06:00
bunnei 5e58271903 Merge pull request #7635 from bunnei/set-heap-size
core: hle: kernel: Updated implementation of svcSetHeapSize.
2021-12-29 20:30:12 -08:00
ameerj 8c907c620d glsl: Add boolean reference workaround 2021-12-29 19:03:50 -05:00
ameerj b84d429c2e glsl_context_get_set: Add alternative cbuf type for broken drivers
some drivers have a bug bitwise converting floating point cbuf values to uint variables. This adds a workaround for these drivers to make all cbufs uint and convert to floating point as needed.
2021-12-29 19:03:50 -05:00
ameerj 9f34be5a61 emit_glsl_integer: Use negation work around 2021-12-29 19:03:50 -05:00
ameerj 14ac0c2923 shader: Add integer attribute get optimization pass
Works around an nvidia driver bug, where casting the integer attributes to float and back to an integer always returned 0.
2021-12-29 19:03:49 -05:00
bunnei 279c7bcc1a Merge pull request #7618 from goldenx86/patch-4
Increase boost requirement to 1.78.0
2021-12-28 16:25:37 -08:00
Matías Locatti c7235e67ef Empty spaces 2021-12-28 18:50:51 -03:00
Matías Locatti 840d5520d2 Changes to avoid warnings in SSE4.2 optimized SPIR-V 2021-12-28 17:35:55 -03:00
Feng Chen 1eec9590c3 Remove invalid assertion statement 2021-12-28 18:51:11 +08:00
Feng Chen e18bf4b062 Remove invalid header include 2021-12-28 18:51:11 +08:00
Feng Chen 88e1e7f14b Implement few type in bufferqueue query method 2021-12-28 18:51:03 +08:00
bunnei 091463a429 core: hle: kernel: Updated implementation of svcSetHeapSize.
- Updates our svcSetHeapSize with latest HOS, furthermore allowing heap size to properly be extended/shrunk.
- Validated with tests https://github.com/Atmosphere-NX/Atmosphere/blob/master/tests/TestSvc/source/test_set_heap_size.cpp.
2021-12-28 01:25:20 -08:00
bunnei f67605e6aa Merge pull request #7622 from ameerj/vk-rescale-invalid-ptr
vk_texture_cache: Fix invalidated pointer access
2021-12-28 00:46:37 -08:00
bunnei 9a0648ff0a Merge pull request #7621 from bunnei/set-mem-perm
core: hle: kernel: Implement SetMemoryPermission.
2021-12-27 23:33:11 -08:00
bunnei c9e4acc4e2 Merge pull request #7630 from ameerj/glasm-get-int
emit_glasm_context_get_set: Fix GetAttribute return value type.
2021-12-27 16:35:11 -08:00
bunnei 292dfac25e Merge pull request #7620 from bunnei/kernel-thread-x18
core: hle: kernel: KThread: X18 should be a cryptographically random number.
2021-12-25 00:42:54 -08:00
ameerj 37addf7a94 emit_glasm_context_get_set: Fix GetAttribute return value type.
GetAttribute expects an F32 result type at the IR level, this fixes the return value of attributes which were not returning an F32
2021-12-24 20:45:07 -05:00
ameerj 640fc1418b emit_glsl_floating_point: Fix FPNeg on newer Nvidia drivers 2021-12-24 20:03:54 -05:00
bunnei 8a48c4ed1c Merge pull request #7623 from ameerj/unused-func
blit_image: Remove unused function
2021-12-23 22:21:28 -08:00
ameerj f9e0681d59 vk_texture_cache: Use 3D scale helpers for MSAA texture scaling on Intel Windows drivers
Fixes a crash when scaling MSAA textures in titles such as Sonic Colors Ultimate.
2021-12-23 22:35:19 -05:00
ameerj cbc0f0a66e blit_image: Remove unused function 2021-12-23 21:06:32 -05:00
ameerj 481b210c0d vk_texture_cache: Fix invalidated pointer access
The vulkan ImageView held a reference to its source image for rescale status checking. This pointer is sometimes invalidated when the texture cache slot_images container is resized.
To avoid an invalid pointer dereference, the ImageView now holds a reference to the container itself.
2021-12-23 20:55:48 -05:00
bunnei 4e7a6639d2 core: hle: kernel: Implement SetMemoryPermission.
- Not seen in any games yet, but validated with kernel tests.
2021-12-23 01:10:36 -08:00
bunnei a0c7d93b84 core: hle: kernel: KThread: X18 should be a cryptographically random number.
- This was added with firmware 11.0.0 (https://switchbrew.org/wiki/11.0.0).
    - X18 is OR'd by kernel with 1, to make sure it is odd.
2021-12-23 00:03:39 -08:00
bunnei 516325eba8 Merge pull request #7614 from liushuyu/fix-linux-inhibit
main: Fix wake lock (prevent sleep) in Flatpak
2021-12-22 16:53:54 -08:00
Matías Locatti e0193e2be5 Increase boost requirement to 1.78.0
Liu's finding, this allows to build yuzu on VS 2022.
Ignore at will.
2021-12-22 16:10:21 -03:00
Fernando S b85f5b1332 Merge pull request #7616 from bunnei/fix-get-idle-ticks
hle: kernel: svc: GetInfo: Fix error checking with IdleTickCount.
2021-12-22 17:39:17 +01:00
Fernando S 648c7b4ed6 Merge pull request #7375 from vonchenplus/convert_legacy
Convert all legacy attributes to generic attributes
2021-12-22 17:36:05 +01:00
liushuyu 14fc1bec17 main: reword inhibit reason 2021-12-22 02:33:01 -07:00
liushuyu fa7abafa5f main: fix wake lock in Flatpak ...
... by using the XDP system
2021-12-22 02:27:09 -07:00
bunnei 36df305b13 Merge pull request #7599 from FernandoS27/primrestart-vulkan
Vulkan: Fix Primitive Restart and implement Logical Operations
2021-12-22 00:19:23 -08:00
bunnei f1eff447bb Merge pull request #7602 from jbeich/freebsd-vaapi
build: enable VA-API on FreeBSD
2021-12-21 22:46:49 -08:00
bunnei 49e3c073a5 hle: kernel: svc: GetInfo: Fix error checking with IdleTickCount.
- Enforce tha the supplied handle is invalid, not valid.
- This gets Witcher 3 booting.
2021-12-21 22:41:23 -08:00
bunnei 6991d447d4 Merge pull request #7604 from ameerj/fullscreen-render-window
main: Make separate render window fullscreen toggle on the monitor it resides in
2021-12-21 18:05:11 -08:00
bunnei b30a1d49ff Merge pull request #7608 from Tatsh/scm-ver-override
Allow overriding SCM version info
2021-12-21 16:07:27 -08:00
Andrew Udvare 78759d98dc Add support for linking against system opus 2021-12-21 05:05:23 -05:00
bunnei 5e24f7ed31 Merge pull request #7481 from german77/gyro-bias
service/hid: Improve console motion accuracy
2021-12-21 00:13:54 -08:00
bunnei cf221ca92d Merge pull request #7609 from Tatsh/file-assoc
dist/XDG: add more file associations
2021-12-20 21:55:43 -08:00
Andrew Udvare 59c6f45e7a dist/XDG: add more file associations 2021-12-20 19:18:02 -05:00
Andrew Udvare caf38725ae Allow overriding SCM version info
If the build is from a non-repository, these functions will return empty. This
patch allows using defines to CMake to set version info such as
-DGIT_BRANCH=master.
2021-12-20 19:13:07 -05:00
bunnei ee6d40d414 Merge pull request #7597 from bunnei/remove-global-lock
core: hle: Remove global HLE lock.
2021-12-20 14:24:50 -08:00
bunnei eb4ea7e5c7 Merge pull request #7603 from ameerj/here-we-go-again
kernel: Manually destroy the current process during shut down
2021-12-19 02:09:53 -08:00
ameerj 3074b2eb93 main: Refactor to reduce code duplication in ShowFullscreen() 2021-12-19 02:09:37 -05:00
ameerj 39bb6851e4 main: Make render window borderless fullscreen toggle on the monitor it resides in
Toggling borderless fullscreen on the separate render window made it fullscreen on the monitor which the main yuzu window resided in.

This change allows the render window to go fullscreen on the monitor it resides in, independent of the main window location.
2021-12-19 02:08:48 -05:00
ameerj 55650c5b75 kernel: Manually destroy the current process during shut down
Avoids a memory leak.
2021-12-19 01:38:25 -05:00
Jan Beich e57b13ad94 video_core/codecs: re-enable VAAPI/VDPAU on BSDs after 72aa418b0b 2021-12-18 20:57:30 +00:00
Jan Beich 1a9576fdff cmake: enable VA-API on more Unix-like after 0be4e402e2 2021-12-18 20:57:30 +00:00
Morph 8e33cf1c2b Merge pull request #7593 from german77/brrr_test
core/hid: Cancel any vibration after the test
2021-12-18 15:53:15 -05:00
Morph 6fb212784e Merge pull request #7600 from bunnei/fix-kip-loading
core: loader: kip: Minimal changes to fix KIP loading.
2021-12-18 15:50:25 -05:00
bunnei 2030522d86 Merge pull request #7587 from liushuyu/fix-linux-decoding
[Patch v2] externals/ffmpeg: refactor ffmpeg searching and handling in cmake
2021-12-18 02:33:07 -08:00
bunnei 1490b49fa9 Merge pull request #7596 from Tatsh/externals-sdl-config-joycon-fix
externals/CMakeLists: fix detection/init of Switch controllers in SDL 2.0.18
2021-12-18 01:00:17 -08:00
bunnei 212b497d5c Merge pull request #7302 from VPeruS/check-deadlock
[input_common] Fixed thread hang
2021-12-17 23:43:19 -08:00
bunnei 7feac8ba46 core: loader: kip: Minimal changes to fix KIP loading.
- Allows us to boot KIP (kernal apps), useful for testing the kernel.
2021-12-17 23:08:51 -08:00
vonchenplus 4908a07c20 Address format clang 2021-12-18 14:27:07 +08:00
Fernando Sahmkow 6c00151d17 Vulkan: Fix the checks for primitive restart extension. 2021-12-18 07:17:08 +01:00
Fernando S 04b4f3b051 Merge pull request #7399 from ameerj/art-refactor
video_core: Refactoring post A.R.T. merge
2021-12-18 07:09:58 +01:00
vonchenplus 6ebc972c2b Remove spirv handle legacy related code 2021-12-18 14:08:50 +08:00
vonchenplus 94652e122d Remove glsl handle legacy related code 2021-12-18 14:03:40 +08:00
Feng Chen e49184e606 Merge branch 'yuzu-emu:master' into convert_legacy 2021-12-18 13:57:14 +08:00
Fernando Sahmkow 14d2c77f91 Vulkan: implement Logical Operations. 2021-12-18 06:52:28 +01:00
Fernando Sahmkow 6430fc29a9 Vulkan: Implement VK_EXT_primitive_topology_list_restart 2021-12-18 05:47:48 +01:00
bunnei 77d06d5df0 Merge pull request #7570 from ameerj/favorites-expanded
game_list: Add persistent setting for the favorites row expanded state
2021-12-17 16:09:05 -08:00
bunnei c73841500a core: hle: Remove global HLE lock.
- This was added early on as a hack to protect against some concurrency issues.
- It's not clear that this serves any purpose anymore, and if it does, individual components should be fixed rather than using a global recursive mutex.
2021-12-17 16:05:51 -08:00
vperus 11f4bf8a9a [input_common] Move variable declaration closer to usage
MSVC supplied with VS2022 generates "warning C4189: 'CALIBRATION_THRESHOLD':
local variable is initialized but not referenced" which is treated as an
error.

Circumvent it by moving constexpr variable directly into body of lambda function.
2021-12-17 20:51:47 +02:00
Andrew Udvare 9b3611eb8d externals/SDL: update SDL to version with Wayland build fix 2021-12-17 09:38:46 -05:00
Andrew Udvare e610485cd2 externals/CMakeLists: fix detection/init of Switch controllers in SDL 2.0.18
Enable SDL_THREADS and SDL_ATOMIC
Also set SDL_WAYLAND=OFF due to build issue

Closes #7572
2021-12-16 21:49:39 -05:00
Narr the Reg c82e6dc810 core/hid: Cancel any vibration after the test 2021-12-16 13:35:15 -06:00
bunnei e242f16986 Merge pull request #7532 from goldenx86/patch-3
Update video core popup
2021-12-15 22:32:27 -08:00
Matías Locatti 333ccf23f8 Suggestions from CrusadingNinja 2021-12-16 02:57:45 -03:00
Matías Locatti 1cdddd17d2 Changed link 2021-12-16 02:40:30 -03:00
bunnei 7cf74abbf5 Merge pull request #7551 from vonchenplus/fix_blit_image_view_mismatching
Fix blit image/view not compatible
2021-12-15 21:39:53 -08:00
liushuyu 476637d143 externals/ffmpeg: set the cmake variable twice ...
... to avoid leaving variable undefined in the current scope
2021-12-15 21:17:33 -07:00
liushuyu 3ae9258efe externals: fix a regression when using MSVC 2021-12-15 20:57:01 -07:00
liushuyu 3f765ea9a4 video_core/codecs: (re-spin) refactor ffmpeg searching and handling 2021-12-15 20:57:01 -07:00
bunnei b3fc36d989 Merge pull request #7588 from Wunkolo/gibibibi-bytes
yuzu/main: Fix host memory byte units. GB to GiB
2021-12-15 12:04:37 -08:00
bunnei 2a24c415c1 Merge pull request #7589 from yuzu-emu/revert-7565-fix-linux-decoding
Revert "video_core/codecs: refactor ffmpeg searching and handling in cmake"
2021-12-15 00:03:20 -08:00
bunnei 2f32133ad5 Revert "video_core/codecs: refactor ffmpeg searching and handling in cmake" 2021-12-15 00:02:53 -08:00
Wunkolo 44b3abdfc0 yuzu/main: Fix host memory byte units. GB to GiB
I have `134850146304` bytes of ram and Yuzu was saying that I had `125.59 GB`
of ram. But `125.59` is actually the amount of gi**bi**bytes I have. In
gi**ga**bytes I would have `134.9`.

Additionally, I changed the `1024 / 1024 / 1024` here into the `_GiB`
user-literals that I added a while ago(#6519).

https://www.wolframalpha.com/input/?i=134850146304+bytes
2021-12-14 23:57:33 -08:00
bunnei 156215d1fa Merge pull request #7565 from liushuyu/fix-linux-decoding
video_core/codecs: refactor ffmpeg searching and handling in cmake
2021-12-14 22:27:13 -08:00
Mai M 019ae82c94 Merge pull request #7558 from Morph1984/unused-cpu-family-model
common/cpu_detect: Remove CPU family and model
2021-12-14 23:43:16 -05:00
Mai M 822259a3f2 Merge pull request #7549 from Morph1984/astc-8x5
maxwell_to_vk: Add ASTC_2D_8X5_UNORM
2021-12-14 23:42:44 -05:00
Mai M f0ed11e318 Merge pull request #7579 from Morph1984/swkbd-oob-array-access
qt_software_keyboard: Fix out of bounds array access
2021-12-14 23:42:07 -05:00
Ghost 935fee18ed Merge pull request #7583 from german77/triggered
core/hid: Fix faulty analog triggers
2021-12-14 22:48:53 -05:00
Narr the Reg 6aac5d4c27 core/hid: Fix faulty analog triggers 2021-12-14 19:49:44 -06:00
Narr the Reg 5e732e7aec Merge pull request #7581 from lioncash/input-iface
common/input: Avoid numerous large copies of CallbackStatus
2021-12-14 19:10:39 -06:00
Narr the Reg ac0c5be7c0 Merge pull request #7577 from v1993/patch-2
input/SDL: Update SDL hints
2021-12-14 10:12:17 -06:00
Valeri 7f965172c5 input/SDL: Update SDL hints
SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED is no longer needed thanks to new default in SDL 2.0.18.
SDL_HINT_JOYSTICK_HIDAPI_XBOX is reported to cause conflicts with native driver Xbox driver on Linux, and Xbox controllers don't benefit from hidapi anyways.
2021-12-14 15:02:03 +03:00
liushuyu dd72e4dce4 CI: fix CI on Linux 2021-12-13 22:31:19 -07:00
liushuyu a2d73eaa10 video_core/codecs: skip decoders that use hw frames ...
... this would resolve some edge-cases where multiple devices are
present and ffmpeg is unable to auto-supply the hw surfaces
2021-12-13 22:29:19 -07:00
bunnei 9fa1cf3e01 Merge pull request #7580 from lioncash/input-doc
input_poller/input_mapping: Silence several -Wdocumentation warnings
2021-12-13 20:21:18 -08:00
Lioncash e05d2a70b2 common/input: Avoid numerous large copies of CallbackStatus
CallbackStatus instances aren't the cheapest things to copy around
(relative to everything else), given that they're currently 520 bytes in
size and are currently copied numerous times when callbacks are invoked.

Instead, we can pass the status by const reference to avoid all the
copying.
2021-12-13 21:22:02 -05:00
Morph 4af413623b common/cpu_detect: Remove CPU family and model
We currently do not make use of these fields, remove them for now.
2021-12-13 20:45:18 -05:00
Lioncash 54eafbaf17 common/input: Remove unnecessary returns
Given these return void, these can be omitted.
2021-12-13 20:43:12 -05:00
Lioncash 5e7e38ac72 input_poller: Add missing override specifiers 2021-12-13 20:41:17 -05:00
Lioncash 6497fbfa96 input_mapping: Amend specification of parameters
param tags are supposed to specify the parameter name without any
quoting.

Silences several -Wdocumentation warnings.
2021-12-13 20:31:59 -05:00
Lioncash 7783c0aaef input_poller: Remove several unnecessary @param tags
Silences quite a bit of -Wdocumentation warnings, given the @param tag
is only intended to be used to identify function parameters, not what it
contains.
2021-12-13 20:28:30 -05:00
bunnei ad45963b45 Merge pull request #7575 from lioncash/input
input_engine: Minor object churn cleanup
2021-12-13 16:50:54 -08:00
liushuyu 37f1c76613 CI: fix MinGW installation step 2021-12-13 17:48:05 -07:00
liushuyu f91b6fbbcb ffmpeg: move the whole tree into externals/ffmpeg/ffmpeg ...
* this resolves the todo items in the CMakeLists.txt
* a version requirement check for ffmpeg is added to catch issues early
* for future-proof reasons, nasm/yasm is now only required when build on
  x86/AMD64 systems
2021-12-13 17:48:05 -07:00
liushuyu ccc0a1e621 cmake: refactor ffmpeg searching and handling logic on Linux 2021-12-13 17:48:05 -07:00
Morph 96579e515a qt_software_keyboard: Fix out of bounds array access
We were unconditionally accessing the keyboard_buttons array, even if the bottom_osk_index was for the numberpad, leading to an out of bounds array access. Fix this by accessing the proper array for the current button when the index is for the numberpad.
2021-12-13 19:04:07 -05:00
bunnei 7276aaf907 Merge pull request #7576 from lioncash/tasenum
tas_input: Minor cleanup
2021-12-13 14:47:24 -08:00
Lioncash e4de1783e1 input_engine: Fix typo in TriggerOnAxisChange() parameter name 2021-12-13 10:21:37 -05:00
Lioncash a9d39b6895 input_engine: Simplify PreSet* family of functions
We can make use of try_emplace() to insert values only if they don't
already exist.
2021-12-13 10:18:04 -05:00
Lioncash 4d4a234476 input_engine: Avoid redundant map lookups
We can use iterators to avoid looking up into maps twice in the getter
functions.

At the same time we can also avoid copying the ControllerData structs,
since they're 264 bytes in size.
2021-12-13 09:57:51 -05:00
Lioncash e51b852aee input_engine: Remove left-over namespace qualifiers
These types are part of the InputCommon namespace.
2021-12-13 09:57:51 -05:00
Lioncash e826e6715a input_engine: Iterate by reference rather than by value where applicable
Avoids creating copies of several object instances (some of which being
over 100 bytes in size).
2021-12-13 09:57:51 -05:00
Lioncash 755822ceec input_engine: Take BasicMotion by const reference with SetMotion() and TriggerOnMotionChange()
Copies the BasicMotion instance once instead of twice.
2021-12-13 09:57:39 -05:00
Lioncash a92dbec962 input_engine: std::move InputIdentifier in SetCallback()
Allows avoiding std::function allocations.
2021-12-13 09:23:23 -05:00
Lioncash 985599e485 input_engine: Pass LedStatus by const reference
Avoids copies where reasonably applicable
2021-12-13 09:20:58 -05:00
Lioncash 38f3442ea5 input_engine: Pass VibrationStatus by const reference in SetRumble()
Avoids creating copies of the struct where not necessary.
2021-12-13 09:16:10 -05:00
Lioncash 2b92d22bda input_engine: std::move engine name where applicable
We can allow the name to be moved into, allowing allocations to be
avoided.
2021-12-13 09:05:50 -05:00
Lioncash 9a104e2b60 input_engine: Remove callback clearing in constructor
The callback map is a member variable, so this will always be empty on
initial construction.
2021-12-13 08:54:23 -05:00
Lioncash 479369db43 input_engine: Remove unnecessary semi-colons
Silences -Wextra-semi warnings
2021-12-13 08:53:01 -05:00
Lioncash 3c618a3306 input_engine: Remove unnecessary return
This is a void function, so it doesn't need this.
2021-12-13 08:52:09 -05:00
Narr the Reg 316f80af87 service/hid: Improve console motion accuracy 2021-12-12 23:26:04 -06:00
ameerj b64d28492a game_list: Add persistent setting for the favorites row expanded state
Previously, the favorites row was always expanded on launch. This change introduces a persistent setting that allows the favorites row's expanded state to be remembered between launches.
2021-12-12 15:46:42 -05:00
Morph 14110230c7 maxwell_to_vk: Add ASTC_2D_5X4_UNORM 2021-12-10 22:44:24 -05:00
Feng Chen 1598426493 Fix blit image/view not compatible 2021-12-10 12:41:09 +08:00
Morph ae4869650a maxwell_to_vk: Add ASTC_2D_8X5_UNORM
- Used by Lego City Undercover
2021-12-09 13:53:53 -05:00
Matías Locatti 60bdedc7dd main: Update video core popup
Old version had formatting issues, and I want to provide an answer to the most common reason this pops up in the first place, outdated drivers.
2021-12-06 20:35:07 -05:00
ameerj 228a381aed vk_texture_cache: Add ABGR src format check for D24S8 conversions 2021-12-05 15:54:58 -05:00
ameerj c22c4f5d59 renderer_opengl: Minor refactoring of filter selection 2021-12-05 15:42:45 -05:00
ameerj 218d790bd6 texture_cache: Fix image convert dimensions assertion 2021-12-05 15:42:45 -05:00
ameerj b8f3e5157b blit_image: Refactor upscale factors usage
The image view itself can be queried to see if it is being rescaled or not, removing the need to pass the upscale/down shift factors from the texture cache.
2021-12-05 15:42:44 -05:00
ameerj 35d94dcb2b vk_texture_cache: Add a function to ImageView to check if src image is rescaled 2021-12-05 15:39:00 -05:00
ameerj 4a13f9eecd blit_image: Refactor ConvertPipeline functions 2021-12-05 15:39:00 -05:00
ameerj ad99bbf5fe blit_image: Refactor ConvertPipelineEx functions
reduces much of the duplication between the color/depth variants
2021-12-05 15:38:59 -05:00
ameerj b387a26f30 vk_blit_screen: Minor refactor of filter pipeline selection 2021-12-05 15:35:35 -05:00
ameerj 75c4aec8ab Revert "Merge pull request #7395 from Morph1984/resolve-comments"
This reverts commit d20f91da11, reversing
changes made to 5082712b4e.
2021-12-05 15:35:35 -05:00
vperus 660c6bec22 Revert of b01aa72
Caused worker_thread to be stuck in Stage1Completed state until job's destruction.
2021-11-29 16:37:11 +02:00
vperus 04fa990b0c [input_common] Add completion test for CalibrationConfigurationJob 2021-11-29 16:33:12 +02:00
Feng Chen 4dd85f86a8 Implement convert legacy to generic 2021-11-19 22:53:58 +08:00
169 changed files with 10318 additions and 8826 deletions
+2 -3
View File
@@ -41,12 +41,11 @@ for i in package/*.exe; do
done
pip3 install pefile
python3 .ci/scripts/windows/scan_dll.py package/*.exe "package/"
python3 .ci/scripts/windows/scan_dll.py package/imageformats/*.dll "package/"
python3 .ci/scripts/windows/scan_dll.py package/*.exe package/imageformats/*.dll "package/"
# copy FFmpeg libraries
EXTERNALS_PATH="$(pwd)/build/externals"
FFMPEG_DLL_PATH="$(find ${EXTERNALS_PATH} -maxdepth 1 -type d | grep ffmpeg)/bin"
FFMPEG_DLL_PATH="$(find "${EXTERNALS_PATH}" -maxdepth 1 -type d | grep 'ffmpeg-')/bin"
find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -v {} package/ ';'
# copy libraries from yuzu.exe path
+3 -3
View File
@@ -34,12 +34,12 @@
[submodule "opus"]
path = externals/opus/opus
url = https://github.com/xiph/opus.git
[submodule "ffmpeg"]
path = externals/ffmpeg
url = https://git.ffmpeg.org/ffmpeg.git
[submodule "SDL"]
path = externals/SDL
url = https://github.com/libsdl-org/SDL.git
[submodule "externals/cpp-httplib"]
path = externals/cpp-httplib
url = https://github.com/yhirose/cpp-httplib.git
[submodule "externals/ffmpeg/ffmpeg"]
path = externals/ffmpeg/ffmpeg
url = https://git.ffmpeg.org/ffmpeg.git
+8 -220
View File
@@ -33,6 +33,8 @@ option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
option(YUZU_USE_BUNDLED_OPUS "Compile bundled opus" ON)
# Default to a Release build
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
@@ -167,7 +169,7 @@ macro(yuzu_find_packages)
set(REQUIRED_LIBS
# Cmake Pkg Prefix Version Conan Pkg
"Catch2 2.13.7 catch2/2.13.7"
"fmt 8.0.1 fmt/8.0.1"
"fmt 8.0.1 fmt/8.1.1"
"lz4 1.8 lz4/1.9.2"
"nlohmann_json 3.8 nlohmann_json/3.8.0"
"ZLIB 1.2 zlib/1.2.11"
@@ -229,7 +231,7 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR YUZU_USE_BUNDLED_BOOST)
include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
else()
message(STATUS "Boost 1.73.0 or newer not found, falling back to Conan")
list(APPEND CONAN_REQUIRED_LIBS "boost/1.73.0")
list(APPEND CONAN_REQUIRED_LIBS "boost/1.78.0")
endif()
# Attempt to locate any packages that are required and report the missing ones in CONAN_REQUIRED_LIBS
@@ -249,7 +251,7 @@ if(ENABLE_QT)
# Check for system Qt on Linux, fallback to bundled Qt
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if (NOT YUZU_USE_BUNDLED_QT)
find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets)
find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets DBus)
endif()
if (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT)
# Check for dependencies, then enable bundled Qt download
@@ -508,13 +510,13 @@ set(FFmpeg_COMPONENTS
avutil
swscale)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if (UNIX AND NOT APPLE)
Include(FindPkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
endif()
if (NOT YUZU_USE_BUNDLED_FFMPEG)
# Use system installed FFmpeg
find_package(FFmpeg QUIET COMPONENTS ${FFmpeg_COMPONENTS})
find_package(FFmpeg 4.3 QUIET COMPONENTS ${FFmpeg_COMPONENTS})
if (FFmpeg_FOUND)
# Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries.
@@ -527,225 +529,11 @@ if (NOT YUZU_USE_BUNDLED_FFMPEG)
set(FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_DIR} ${FFmpeg_INCLUDE_${COMPONENT}} CACHE PATH "Path to FFmpeg headers" FORCE)
endforeach()
else()
message(WARNING "FFmpeg not found, falling back to externals")
message(WARNING "FFmpeg not found or too old, falling back to externals")
set(YUZU_USE_BUNDLED_FFMPEG ON)
endif()
endif()
if (YUZU_USE_BUNDLED_FFMPEG)
if (NOT WIN32)
# TODO(lat9nq): Move this to externals/ffmpeg/CMakeLists.txt (and move externals/ffmpeg to
# externals/ffmpeg/ffmpeg)
# Build FFmpeg from externals
message(STATUS "Using FFmpeg from externals")
# FFmpeg has source that requires one of nasm or yasm to assemble it.
# REQUIRED throws an error if not found here during configuration rather than during compilation.
find_program(ASSEMBLER NAMES nasm yasm)
if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
endif()
find_program(AUTOCONF autoconf)
if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
message(FATAL_ERROR "Required program `autoconf` not found.")
endif()
set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg)
set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg)
set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile)
make_directory(${FFmpeg_BUILD_DIR})
# Read version string from external
file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION)
set(FFmpeg_FOUND NO)
if (NOT FFmpeg_VERSION STREQUAL "")
set(FFmpeg_FOUND YES)
endif()
unset(FFmpeg_LIBRARIES CACHE)
foreach(COMPONENT ${FFmpeg_COMPONENTS})
set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}")
set(FFmpeg_LIBRARIES
${FFmpeg_LIBRARIES}
${FFmpeg_${COMPONENT}_LIBRARY}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
endforeach()
Include(FindPkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
pkg_check_modules(VDPAU vdpau)
set(FFmpeg_HWACCEL_LIBRARIES)
set(FFmpeg_HWACCEL_FLAGS)
set(FFmpeg_HWACCEL_INCLUDE_DIRS)
set(FFmpeg_HWACCEL_LDFLAGS)
if(LIBVA_FOUND)
pkg_check_modules(LIBDRM libdrm REQUIRED)
find_package(X11 REQUIRED)
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES}
${X11_LIBRARIES}
${LIBVA-DRM_LIBRARIES}
${LIBVA-X11_LIBRARIES}
${LIBVA_LIBRARIES})
set(FFmpeg_HWACCEL_FLAGS
--enable-hwaccel=h264_vaapi
--enable-hwaccel=vp8_vaapi
--enable-hwaccel=vp9_vaapi
--enable-libdrm)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS}
${X11_INCLUDE_DIRS}
${LIBVA-DRM_INCLUDE_DIRS}
${LIBVA-X11_INCLUDE_DIRS}
${LIBVA_INCLUDE_DIRS}
)
message(STATUS "VA-API found")
else()
set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
endif()
if (FFNVCODEC_FOUND AND CUDA_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-cuvid
--enable-ffnvcodec
--enable-nvdec
--enable-hwaccel=h264_nvdec
--enable-hwaccel=vp8_nvdec
--enable-hwaccel=vp9_nvdec
--extra-cflags=-I${CUDA_INCLUDE_DIRS}
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${FFNVCODEC_LIBRARIES}
${CUDA_LIBRARIES}
)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${FFNVCODEC_INCLUDE_DIRS}
${CUDA_INCLUDE_DIRS}
)
list(APPEND FFmpeg_HWACCEL_LDFLAGS
${FFNVCODEC_LDFLAGS}
${CUDA_LDFLAGS}
)
message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
endif()
if (VDPAU_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-vdpau
--enable-hwaccel=h264_vdpau
--enable-hwaccel=vp9_vdpau
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
else()
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
endif()
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
# `--disable-vdpau` is needed to avoid linking issues
add_custom_command(
OUTPUT
${FFmpeg_MAKEFILE}
COMMAND
/bin/bash ${FFmpeg_PREFIX}/configure
--disable-avdevice
--disable-avfilter
--disable-avformat
--disable-doc
--disable-everything
--disable-ffmpeg
--disable-ffprobe
--disable-network
--disable-postproc
--disable-swresample
--enable-decoder=h264
--enable-decoder=vp8
--enable-decoder=vp9
--cc="${CMAKE_C_COMPILER}"
--cxx="${CMAKE_CXX_COMPILER}"
${FFmpeg_HWACCEL_FLAGS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
unset(FFmpeg_HWACCEL_FLAGS)
# Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
# with context of the jobserver. Also helps ninja users.
execute_process(
COMMAND
nproc
OUTPUT_VARIABLE
SYSTEM_THREADS)
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
add_custom_command(
OUTPUT
${FFmpeg_BUILD_LIBRARIES}
COMMAND
make -j${SYSTEM_THREADS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
set(FFmpeg_INCLUDE_DIR
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LDFLAGS
"${FFmpeg_HWACCEL_LDFLAGS}"
CACHE STRING "FFmpeg linker flags" FORCE)
# ALL makes this custom target build every time
# but it won't actually build if the DEPENDS parameter is up to date
add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
link_libraries(${FFmpeg_LIBVA_LIBRARIES})
set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
unset(FFmpeg_BUILD_LIBRARIES)
unset(FFmpeg_HWACCEL_FLAGS)
unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
unset(FFmpeg_HWACCEL_LDFLAGS)
unset(FFmpeg_HWACCEL_LIBRARIES)
if (FFmpeg_FOUND)
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
else()
message(FATAL_ERROR "FFmpeg not found")
endif()
else() # WIN32
# Use yuzu FFmpeg binaries
set(FFmpeg_EXT_NAME "ffmpeg-4.4")
set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
set(FFmpeg_FOUND YES)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
set(FFmpeg_LIBRARIES
${FFmpeg_LIBRARY_DIR}/swscale.lib
${FFmpeg_LIBRARY_DIR}/avcodec.lib
${FFmpeg_LIBRARY_DIR}/avutil.lib
CACHE PATH "Paths to FFmpeg libraries" FORCE)
endif()
endif()
unset(FFmpeg_COMPONENTS)
# Prefer the -pthread flag on Linux.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
+9 -3
View File
@@ -11,9 +11,15 @@ find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")
# generate git/build information
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
if(NOT GIT_REF_SPEC)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
endif()
if(NOT GIT_DESC)
git_describe(GIT_DESC --always --long --dirty)
endif()
if (NOT GIT_BRANCH)
git_branch_name(GIT_BRANCH)
endif()
get_timestamp(BUILD_DATE)
# Generate cpp with Git revision from template
+1004 -930
View File
File diff suppressed because it is too large Load Diff
+353 -312
View File
File diff suppressed because it is too large Load Diff
+347 -306
View File
File diff suppressed because it is too large Load Diff
+353 -312
View File
File diff suppressed because it is too large Load Diff
+371 -330
View File
File diff suppressed because it is too large Load Diff
+360 -319
View File
File diff suppressed because it is too large Load Diff
+422 -373
View File
File diff suppressed because it is too large Load Diff
+348 -307
View File
File diff suppressed because it is too large Load Diff
+348 -307
View File
File diff suppressed because it is too large Load Diff
+353 -312
View File
File diff suppressed because it is too large Load Diff
+353 -312
View File
File diff suppressed because it is too large Load Diff
+353 -312
View File
File diff suppressed because it is too large Load Diff
+491 -444
View File
File diff suppressed because it is too large Load Diff
+352 -311
View File
File diff suppressed because it is too large Load Diff
+348 -307
View File
File diff suppressed because it is too large Load Diff
+352 -311
View File
File diff suppressed because it is too large Load Diff
+401 -360
View File
File diff suppressed because it is too large Load Diff
+352 -311
View File
File diff suppressed because it is too large Load Diff
+348 -307
View File
File diff suppressed because it is too large Load Diff
+396 -355
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -8,5 +8,5 @@ Icon=yuzu
TryExec=yuzu
Exec=yuzu %f
Categories=Game;Emulator;Qt;
MimeType=application/x-nx-nro;application/x-nx-nso;
MimeType=application/x-nx-nro;application/x-nx-nso;application/x-nx-nsp;application/x-nx-xci;
Keywords=Switch;Nintendo;
+15
View File
@@ -15,4 +15,19 @@
<glob pattern="*.nso"/>
<magic><match value="NSO" type="string" offset="0"/></magic>
</mime-type>
<mime-type type="application/x-nx-nsp">
<comment>Nintendo Switch Package</comment>
<acronym>NSP</acronym>
<icon name="yuzu"/>
<glob pattern="*.nsp"/>
<magic><match value="PFS" type="string" offset="0"/></magic>
</mime-type>
<mime-type type="application/x-nx-xci">
<comment>Nintendo Switch Card Image</comment>
<acronym>XCI</acronym>
<icon name="yuzu"/>
<glob pattern="*.xci"/>
</mime-type>
</mime-info>
+16 -6
View File
@@ -52,11 +52,12 @@ endif()
# SDL2
if (YUZU_USE_EXTERNAL_SDL2)
if (NOT WIN32)
# Yuzu itself needs: Events Joystick Haptic Sensor Timers Audio
# Yuzu itself needs: Atomic Audio Events Joystick Haptic Sensor Threads Timers
# Since 2.0.18 Atomic+Threads required for HIDAPI/libusb (see https://github.com/libsdl-org/SDL/issues/5095)
# Yuzu-cmd also needs: Video (depends on Loadso/Dlopen)
set(SDL_UNUSED_SUBSYSTEMS
Atomic Render Power Threads
File CPUinfo Filesystem Locale)
CPUinfo File Filesystem
Locale Power Render)
foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS})
string(TOUPPER ${_SUB} _OPT)
option(SDL_${_OPT} "" OFF)
@@ -116,8 +117,17 @@ if (ENABLE_WEB_SERVICE)
endif()
# Opus
find_package(opus 1.3)
if (NOT opus_FOUND)
message(STATUS "opus 1.3 or newer not found, falling back to externals")
if (YUZU_USE_BUNDLED_OPUS)
add_subdirectory(opus EXCLUDE_FROM_ALL)
else()
find_package(opus 1.3 REQUIRED)
endif()
# FFMpeg
if (YUZU_USE_BUNDLED_FFMPEG)
add_subdirectory(ffmpeg)
set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
endif()
+1 -1
-1
Submodule externals/ffmpeg deleted from 79e8d17024
+214
View File
@@ -0,0 +1,214 @@
if (NOT WIN32)
# Build FFmpeg from externals
message(STATUS "Using FFmpeg from externals")
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|amd64)")
# FFmpeg has source that requires one of nasm or yasm to assemble it.
# REQUIRED throws an error if not found here during configuration rather than during compilation.
find_program(ASSEMBLER NAMES nasm yasm)
if ("${ASSEMBLER}" STREQUAL "ASSEMBLER-NOTFOUND")
message(FATAL_ERROR "One of either `nasm` or `yasm` not found but is required.")
endif()
endif()
find_program(AUTOCONF autoconf)
if ("${AUTOCONF}" STREQUAL "AUTOCONF-NOTFOUND")
message(FATAL_ERROR "Required program `autoconf` not found.")
endif()
set(FFmpeg_PREFIX ${PROJECT_SOURCE_DIR}/externals/ffmpeg/ffmpeg)
set(FFmpeg_BUILD_DIR ${PROJECT_BINARY_DIR}/externals/ffmpeg-build)
set(FFmpeg_MAKEFILE ${FFmpeg_BUILD_DIR}/Makefile)
make_directory(${FFmpeg_BUILD_DIR})
# Read version string from external
file(READ ${FFmpeg_PREFIX}/RELEASE FFmpeg_VERSION)
set(FFmpeg_FOUND NO)
if (NOT FFmpeg_VERSION STREQUAL "")
set(FFmpeg_FOUND YES)
endif()
unset(FFmpeg_LIBRARIES CACHE)
foreach(COMPONENT ${FFmpeg_COMPONENTS})
set(FFmpeg_${COMPONENT}_PREFIX "${FFmpeg_BUILD_DIR}/lib${COMPONENT}")
set(FFmpeg_${COMPONENT}_LIB_NAME "lib${COMPONENT}.a")
set(FFmpeg_${COMPONENT}_LIBRARY "${FFmpeg_${COMPONENT}_PREFIX}/${FFmpeg_${COMPONENT}_LIB_NAME}")
set(FFmpeg_LIBRARIES
${FFmpeg_LIBRARIES}
${FFmpeg_${COMPONENT}_LIBRARY}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
endforeach()
Include(FindPkgConfig REQUIRED)
pkg_check_modules(LIBVA libva)
pkg_check_modules(CUDA cuda)
pkg_check_modules(FFNVCODEC ffnvcodec)
pkg_check_modules(VDPAU vdpau)
set(FFmpeg_HWACCEL_LIBRARIES)
set(FFmpeg_HWACCEL_FLAGS)
set(FFmpeg_HWACCEL_INCLUDE_DIRS)
set(FFmpeg_HWACCEL_LDFLAGS)
if(LIBVA_FOUND)
pkg_check_modules(LIBDRM libdrm REQUIRED)
find_package(X11 REQUIRED)
pkg_check_modules(LIBVA-DRM libva-drm REQUIRED)
pkg_check_modules(LIBVA-X11 libva-x11 REQUIRED)
list(APPEND FFmpeg_HWACCEL_LIBRARIES
${LIBDRM_LIBRARIES}
${X11_LIBRARIES}
${LIBVA-DRM_LIBRARIES}
${LIBVA-X11_LIBRARIES}
${LIBVA_LIBRARIES})
set(FFmpeg_HWACCEL_FLAGS
--enable-hwaccel=h264_vaapi
--enable-hwaccel=vp8_vaapi
--enable-hwaccel=vp9_vaapi
--enable-libdrm)
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
${LIBDRM_INCLUDE_DIRS}
${X11_INCLUDE_DIRS}
${LIBVA-DRM_INCLUDE_DIRS}
${LIBVA-X11_INCLUDE_DIRS}
${LIBVA_INCLUDE_DIRS}
)
message(STATUS "VA-API found")
else()
set(FFmpeg_HWACCEL_FLAGS --disable-vaapi)
endif()
if (FFNVCODEC_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-cuvid
--enable-ffnvcodec
--enable-nvdec
--enable-hwaccel=h264_nvdec
--enable-hwaccel=vp8_nvdec
--enable-hwaccel=vp9_nvdec
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${FFNVCODEC_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${FFNVCODEC_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${FFNVCODEC_LDFLAGS})
message(STATUS "ffnvcodec libraries version ${FFNVCODEC_VERSION} found")
# ffnvenc could load CUDA libraries at the runtime using dlopen/dlsym or LoadLibrary/GetProcAddress
# here we handle the hard-linking senario where CUDA is linked during compilation
if (CUDA_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS --extra-cflags=-I${CUDA_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${CUDA_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${CUDA_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${CUDA_LDFLAGS})
message(STATUS "CUDA libraries found, hard-linking will be performed")
endif(CUDA_FOUND)
endif()
if (VDPAU_FOUND)
list(APPEND FFmpeg_HWACCEL_FLAGS
--enable-vdpau
--enable-hwaccel=h264_vdpau
--enable-hwaccel=vp9_vdpau
)
list(APPEND FFmpeg_HWACCEL_LIBRARIES ${VDPAU_LIBRARIES})
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS ${VDPAU_INCLUDE_DIRS})
list(APPEND FFmpeg_HWACCEL_LDFLAGS ${VDPAU_LDFLAGS})
message(STATUS "vdpau libraries version ${VDPAU_VERSION} found")
else()
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vdpau)
endif()
# `configure` parameters builds only exactly what yuzu needs from FFmpeg
# `--disable-vdpau` is needed to avoid linking issues
add_custom_command(
OUTPUT
${FFmpeg_MAKEFILE}
COMMAND
/bin/bash ${FFmpeg_PREFIX}/configure
--disable-avdevice
--disable-avfilter
--disable-avformat
--disable-doc
--disable-everything
--disable-ffmpeg
--disable-ffprobe
--disable-network
--disable-postproc
--disable-swresample
--enable-decoder=h264
--enable-decoder=vp8
--enable-decoder=vp9
--cc="${CMAKE_C_COMPILER}"
--cxx="${CMAKE_CXX_COMPILER}"
${FFmpeg_HWACCEL_FLAGS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
unset(FFmpeg_HWACCEL_FLAGS)
# Workaround for Ubuntu 18.04's older version of make not being able to call make as a child
# with context of the jobserver. Also helps ninja users.
execute_process(
COMMAND
nproc
OUTPUT_VARIABLE
SYSTEM_THREADS)
set(FFmpeg_BUILD_LIBRARIES ${FFmpeg_LIBRARIES})
add_custom_command(
OUTPUT
${FFmpeg_BUILD_LIBRARIES}
COMMAND
make -j${SYSTEM_THREADS}
WORKING_DIRECTORY
${FFmpeg_BUILD_DIR}
)
set(FFmpeg_INCLUDE_DIR
"${FFmpeg_PREFIX};${FFmpeg_BUILD_DIR};${FFmpeg_HWACCEL_INCLUDE_DIRS}"
CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LDFLAGS
"${FFmpeg_HWACCEL_LDFLAGS}"
CACHE STRING "FFmpeg linker flags" FORCE)
# ALL makes this custom target build every time
# but it won't actually build if the DEPENDS parameter is up to date
add_custom_target(ffmpeg-configure ALL DEPENDS ${FFmpeg_MAKEFILE})
add_custom_target(ffmpeg-build ALL DEPENDS ${FFmpeg_BUILD_LIBRARIES} ffmpeg-configure)
link_libraries(${FFmpeg_LIBVA_LIBRARIES})
set(FFmpeg_LIBRARIES ${FFmpeg_BUILD_LIBRARIES} ${FFmpeg_HWACCEL_LIBRARIES}
CACHE PATH "Paths to FFmpeg libraries" FORCE)
unset(FFmpeg_BUILD_LIBRARIES)
unset(FFmpeg_HWACCEL_FLAGS)
unset(FFmpeg_HWACCEL_INCLUDE_DIRS)
unset(FFmpeg_HWACCEL_LDFLAGS)
unset(FFmpeg_HWACCEL_LIBRARIES)
if (FFmpeg_FOUND)
message(STATUS "Found FFmpeg version ${FFmpeg_VERSION}")
else()
message(FATAL_ERROR "FFmpeg not found")
endif()
else(WIN32)
# Use yuzu FFmpeg binaries
set(FFmpeg_EXT_NAME "ffmpeg-4.4")
set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
set(FFmpeg_FOUND YES)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_PATH}/include" CACHE PATH "Path to FFmpeg headers" FORCE)
set(FFmpeg_LIBRARY_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg library directory" FORCE)
set(FFmpeg_LDFLAGS "" CACHE STRING "FFmpeg linker flags" FORCE)
set(FFmpeg_DLL_DIR "${FFmpeg_PATH}/bin" CACHE PATH "Path to FFmpeg dll's" FORCE)
set(FFmpeg_LIBRARIES
${FFmpeg_LIBRARY_DIR}/swscale.lib
${FFmpeg_LIBRARY_DIR}/avcodec.lib
${FFmpeg_LIBRARY_DIR}/avutil.lib
CACHE PATH "Paths to FFmpeg libraries" FORCE)
# exported variables
set(FFmpeg_PATH "${FFmpeg_PATH}" PARENT_SCOPE)
set(FFmpeg_LDFLAGS "${FFmpeg_LDFLAGS}" PARENT_SCOPE)
set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
endif(WIN32)
unset(FFmpeg_COMPONENTS)
Vendored Submodule
+1
Submodule externals/ffmpeg/ffmpeg added at dc91b913b6
+6
View File
@@ -22,6 +22,11 @@ add_custom_command(OUTPUT scm_rev.cpp
-DTITLE_BAR_FORMAT_RUNNING=${TITLE_BAR_FORMAT_RUNNING}
-DBUILD_TAG=${BUILD_TAG}
-DBUILD_ID=${DISPLAY_VERSION}
-DGIT_REF_SPEC=${GIT_REF_SPEC}
-DGIT_REV=${GIT_REV}
-DGIT_DESC=${GIT_DESC}
-DGIT_BRANCH=${GIT_BRANCH}
-DBUILD_FULLNAME=${BUILD_FULLNAME}
-DGIT_EXECUTABLE=${GIT_EXECUTABLE}
-P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake
DEPENDS
@@ -80,6 +85,7 @@ add_library(common STATIC
logging/backend.h
logging/filter.cpp
logging/filter.h
logging/formatter.h
logging/log.h
logging/log_entry.h
logging/text_formatter.cpp
+6 -12
View File
@@ -227,7 +227,7 @@ struct CallbackStatus {
// Triggered once every input change
struct InputCallback {
std::function<void(CallbackStatus)> on_change;
std::function<void(const CallbackStatus&)> on_change;
};
/// An abstract class template for an input device (a button, an analog input, etc.).
@@ -236,14 +236,10 @@ public:
virtual ~InputDevice() = default;
// Request input device to update if necessary
virtual void SoftUpdate() {
return;
}
virtual void SoftUpdate() {}
// Force input device to update data regardless of the current state
virtual void ForceUpdate() {
return;
}
virtual void ForceUpdate() {}
// Sets the function to be triggered when input changes
void SetCallback(InputCallback callback_) {
@@ -251,7 +247,7 @@ public:
}
// Triggers the function set in the callback
void TriggerOnChange(CallbackStatus status) {
void TriggerOnChange(const CallbackStatus& status) {
if (callback.on_change) {
callback.on_change(status);
}
@@ -266,11 +262,9 @@ class OutputDevice {
public:
virtual ~OutputDevice() = default;
virtual void SetLED([[maybe_unused]] LedStatus led_status) {
return;
}
virtual void SetLED([[maybe_unused]] const LedStatus& led_status) {}
virtual VibrationError SetVibration([[maybe_unused]] VibrationStatus vibration_status) {
virtual VibrationError SetVibration([[maybe_unused]] const VibrationStatus& vibration_status) {
return VibrationError::NotSupported;
}
+23
View File
@@ -0,0 +1,23 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <type_traits>
#include <fmt/format.h>
// adapted from https://github.com/fmtlib/fmt/issues/2704
// a generic formatter for enum classes
#if FMT_VERSION >= 80100
template <typename T>
struct fmt::formatter<T, std::enable_if_t<std::is_enum_v<T>, char>>
: formatter<std::underlying_type_t<T>> {
template <typename FormatContext>
auto format(const T& value, FormatContext& ctx) -> decltype(ctx.out()) {
return fmt::formatter<std::underlying_type_t<T>>::format(
static_cast<std::underlying_type_t<T>>(value), ctx);
}
};
#endif
+2 -1
View File
@@ -7,8 +7,9 @@
#include <algorithm>
#include <string_view>
#include <fmt/core.h>
#include <fmt/format.h>
#include "common/logging/formatter.h"
#include "common/logging/types.h"
namespace Common::Log {
+1
View File
@@ -597,6 +597,7 @@ struct Values {
BasicSetting<std::string> program_args{std::string(), "program_args"};
BasicSetting<bool> dump_exefs{false, "dump_exefs"};
BasicSetting<bool> dump_nso{false, "dump_nso"};
BasicSetting<bool> dump_shaders{false, "dump_shaders"};
BasicSetting<bool> enable_fs_access_log{false, "enable_fs_access_log"};
BasicSetting<bool> reporting_services{false, "reporting_services"};
BasicSetting<bool> quest_flag{false, "quest_flag"};
-12
View File
@@ -71,9 +71,6 @@ static CPUCaps Detect() {
else
caps.manufacturer = Manufacturer::Unknown;
u32 family = {};
u32 model = {};
__cpuid(cpu_id, 0x80000000);
u32 max_ex_fn = cpu_id[0];
@@ -84,15 +81,6 @@ static CPUCaps Detect() {
// Detect family and other miscellaneous features
if (max_std_fn >= 1) {
__cpuid(cpu_id, 0x00000001);
family = (cpu_id[0] >> 8) & 0xf;
model = (cpu_id[0] >> 4) & 0xf;
if (family == 0xf) {
family += (cpu_id[0] >> 20) & 0xff;
}
if (family >= 6) {
model += ((cpu_id[0] >> 16) & 0xf) << 4;
}
if ((cpu_id[3] >> 25) & 1)
caps.sse = true;
if ((cpu_id[3] >> 26) & 1)
+2 -2
View File
@@ -187,6 +187,8 @@ add_library(core STATIC
hle/kernel/k_event.h
hle/kernel/k_handle_table.cpp
hle/kernel/k_handle_table.h
hle/kernel/k_interrupt_manager.cpp
hle/kernel/k_interrupt_manager.h
hle/kernel/k_light_condition_variable.cpp
hle/kernel/k_light_condition_variable.h
hle/kernel/k_light_lock.cpp
@@ -265,8 +267,6 @@ add_library(core STATIC
hle/kernel/svc_wrap.h
hle/kernel/time_manager.cpp
hle/kernel/time_manager.h
hle/lock.cpp
hle/lock.h
hle/result.h
hle/service/acc/acc.cpp
hle/service/acc/acc.h
+2
View File
@@ -317,6 +317,8 @@ struct System::Impl {
is_powered_on = false;
exit_lock = false;
gpu_core->NotifyShutdown();
services.reset();
service_manager.reset();
cheat_engine.reset();
+5 -5
View File
@@ -45,26 +45,26 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
// Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
if (parameters.allow_pro_controller) {
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
controller->Connect();
controller->Connect(true);
} else if (parameters.allow_dual_joycons) {
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual);
controller->Connect();
controller->Connect(true);
} else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
// Assign left joycons to even player indices and right joycons to odd player indices.
// We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
// a right Joycon for Player 2 in 2 Player Assist mode.
if (index % 2 == 0) {
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft);
controller->Connect();
controller->Connect(true);
} else {
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight);
controller->Connect();
controller->Connect(true);
}
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
!Settings::values.use_docked_mode.GetValue()) {
// We should *never* reach here under any normal circumstances.
controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
controller->Connect();
controller->Connect(true);
} else {
UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!");
}
+15 -9
View File
@@ -66,9 +66,10 @@ void EmulatedConsole::ReloadInput() {
motion_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(motion_params);
if (motion_devices) {
Common::Input::InputCallback motion_callback{
[this](Common::Input::CallbackStatus callback) { SetMotion(callback); }};
motion_devices->SetCallback(motion_callback);
motion_devices->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback) { SetMotion(callback); },
});
}
// Unique index for identifying touch device source
@@ -78,9 +79,12 @@ void EmulatedConsole::ReloadInput() {
if (!touch_device) {
continue;
}
Common::Input::InputCallback touch_callback{
[this, index](Common::Input::CallbackStatus callback) { SetTouch(callback, index); }};
touch_device->SetCallback(touch_callback);
touch_device->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetTouch(callback, index);
},
});
index++;
}
}
@@ -127,7 +131,7 @@ void EmulatedConsole::SetMotionParam(Common::ParamPackage param) {
ReloadInput();
}
void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) {
void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {
std::lock_guard lock{mutex};
auto& raw_status = console.motion_values.raw_status;
auto& emulated = console.motion_values.emulated;
@@ -157,13 +161,15 @@ void EmulatedConsole::SetMotion(Common::Input::CallbackStatus callback) {
motion.rotation = emulated.GetGyroscope();
motion.orientation = emulated.GetOrientation();
motion.quaternion = emulated.GetQuaternion();
motion.gyro_bias = emulated.GetGyroBias();
motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
// Find what is this value
motion.verticalization_error = 0.0f;
TriggerOnChange(ConsoleTriggerType::Motion);
}
void EmulatedConsole::SetTouch(Common::Input::CallbackStatus callback,
[[maybe_unused]] std::size_t index) {
void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) {
if (index >= console.touch_values.size()) {
return;
}
+4 -2
View File
@@ -50,6 +50,8 @@ struct ConsoleMotion {
Common::Vec3f rotation{};
std::array<Common::Vec3f, 3> orientation{};
Common::Quaternion<f32> quaternion{};
Common::Vec3f gyro_bias{};
f32 verticalization_error{};
bool is_at_rest{};
};
@@ -155,14 +157,14 @@ private:
* Updates the motion status of the console
* @param callback A CallbackStatus containing gyro and accelerometer data
*/
void SetMotion(Common::Input::CallbackStatus callback);
void SetMotion(const Common::Input::CallbackStatus& callback);
/**
* Updates the touch status of the console
* @param callback A CallbackStatus containing the touch position
* @param index Finger ID to be updated
*/
void SetTouch(Common::Input::CallbackStatus callback, std::size_t index);
void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index);
/**
* Triggers a callback that something has changed on the console status
+100 -64
View File
@@ -205,11 +205,12 @@ void EmulatedController::ReloadInput() {
continue;
}
const auto uuid = Common::UUID{button_params[index].Get("guid", "")};
Common::Input::InputCallback button_callback{
[this, index, uuid](Common::Input::CallbackStatus callback) {
SetButton(callback, index, uuid);
}};
button_devices[index]->SetCallback(button_callback);
button_devices[index]->SetCallback({
.on_change =
[this, index, uuid](const Common::Input::CallbackStatus& callback) {
SetButton(callback, index, uuid);
},
});
button_devices[index]->ForceUpdate();
}
@@ -218,11 +219,12 @@ void EmulatedController::ReloadInput() {
continue;
}
const auto uuid = Common::UUID{stick_params[index].Get("guid", "")};
Common::Input::InputCallback stick_callback{
[this, index, uuid](Common::Input::CallbackStatus callback) {
SetStick(callback, index, uuid);
}};
stick_devices[index]->SetCallback(stick_callback);
stick_devices[index]->SetCallback({
.on_change =
[this, index, uuid](const Common::Input::CallbackStatus& callback) {
SetStick(callback, index, uuid);
},
});
stick_devices[index]->ForceUpdate();
}
@@ -231,11 +233,12 @@ void EmulatedController::ReloadInput() {
continue;
}
const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")};
Common::Input::InputCallback trigger_callback{
[this, index, uuid](Common::Input::CallbackStatus callback) {
SetTrigger(callback, index, uuid);
}};
trigger_devices[index]->SetCallback(trigger_callback);
trigger_devices[index]->SetCallback({
.on_change =
[this, index, uuid](const Common::Input::CallbackStatus& callback) {
SetTrigger(callback, index, uuid);
},
});
trigger_devices[index]->ForceUpdate();
}
@@ -243,9 +246,12 @@ void EmulatedController::ReloadInput() {
if (!battery_devices[index]) {
continue;
}
Common::Input::InputCallback battery_callback{
[this, index](Common::Input::CallbackStatus callback) { SetBattery(callback, index); }};
battery_devices[index]->SetCallback(battery_callback);
battery_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetBattery(callback, index);
},
});
battery_devices[index]->ForceUpdate();
}
@@ -253,9 +259,12 @@ void EmulatedController::ReloadInput() {
if (!motion_devices[index]) {
continue;
}
Common::Input::InputCallback motion_callback{
[this, index](Common::Input::CallbackStatus callback) { SetMotion(callback, index); }};
motion_devices[index]->SetCallback(motion_callback);
motion_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetMotion(callback, index);
},
});
motion_devices[index]->ForceUpdate();
}
@@ -267,22 +276,24 @@ void EmulatedController::ReloadInput() {
if (!tas_button_devices[index]) {
continue;
}
Common::Input::InputCallback button_callback{
[this, index, tas_uuid](Common::Input::CallbackStatus callback) {
SetButton(callback, index, tas_uuid);
}};
tas_button_devices[index]->SetCallback(button_callback);
tas_button_devices[index]->SetCallback({
.on_change =
[this, index, tas_uuid](const Common::Input::CallbackStatus& callback) {
SetButton(callback, index, tas_uuid);
},
});
}
for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) {
if (!tas_stick_devices[index]) {
continue;
}
Common::Input::InputCallback stick_callback{
[this, index, tas_uuid](Common::Input::CallbackStatus callback) {
SetStick(callback, index, tas_uuid);
}};
tas_stick_devices[index]->SetCallback(stick_callback);
tas_stick_devices[index]->SetCallback({
.on_change =
[this, index, tas_uuid](const Common::Input::CallbackStatus& callback) {
SetStick(callback, index, tas_uuid);
},
});
}
}
@@ -440,7 +451,7 @@ void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage
if (index >= button_params.size()) {
return;
}
button_params[index] = param;
button_params[index] = std::move(param);
ReloadInput();
}
@@ -448,7 +459,7 @@ void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage p
if (index >= stick_params.size()) {
return;
}
stick_params[index] = param;
stick_params[index] = std::move(param);
ReloadInput();
}
@@ -456,11 +467,11 @@ void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage
if (index >= motion_params.size()) {
return;
}
motion_params[index] = param;
motion_params[index] = std::move(param);
ReloadInput();
}
void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index,
void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback, std::size_t index,
Common::UUID uuid) {
if (index >= controller.button_values.size()) {
return;
@@ -600,7 +611,7 @@ void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::
TriggerOnChange(ControllerTriggerType::Button, true);
}
void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index,
void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, std::size_t index,
Common::UUID uuid) {
if (index >= controller.stick_values.size()) {
return;
@@ -650,8 +661,8 @@ void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::s
TriggerOnChange(ControllerTriggerType::Stick, true);
}
void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index,
Common::UUID uuid) {
void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback,
std::size_t index, Common::UUID uuid) {
if (index >= controller.trigger_values.size()) {
return;
}
@@ -659,7 +670,7 @@ void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std:
const auto trigger_value = TransformToTrigger(callback);
// Only read trigger values that have the same uuid or are pressed once
if (controller.stick_values[index].uuid != uuid) {
if (controller.trigger_values[index].uuid != uuid) {
if (!trigger_value.pressed.value) {
return;
}
@@ -675,7 +686,7 @@ void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std:
return;
}
const auto trigger = controller.trigger_values[index];
const auto& trigger = controller.trigger_values[index];
switch (index) {
case Settings::NativeTrigger::LTrigger:
@@ -692,7 +703,8 @@ void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std:
TriggerOnChange(ControllerTriggerType::Trigger, true);
}
void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::size_t index) {
void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback,
std::size_t index) {
if (index >= controller.motion_values.size()) {
return;
}
@@ -730,7 +742,8 @@ void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::
TriggerOnChange(ControllerTriggerType::Motion, true);
}
void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std::size_t index) {
void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
std::size_t index) {
if (index >= controller.battery_values.size()) {
return;
}
@@ -830,23 +843,18 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
}
bool EmulatedController::TestVibration(std::size_t device_index) {
if (device_index >= output_devices.size()) {
return false;
}
if (!output_devices[device_index]) {
return false;
}
// Send a slight vibration to test for rumble support
constexpr Common::Input::VibrationStatus status = {
static constexpr VibrationValue test_vibration = {
.low_amplitude = 0.001f,
.low_frequency = 160.0f,
.high_amplitude = 0.001f,
.high_frequency = 320.0f,
.type = Common::Input::VibrationAmplificationType::Linear,
};
return output_devices[device_index]->SetVibration(status) ==
Common::Input::VibrationError::None;
// Send a slight vibration to test for rumble support
SetVibration(device_index, test_vibration);
// Stop any vibration and return the result
return SetVibration(device_index, DEFAULT_VIBRATION_VALUE);
}
void EmulatedController::SetLedPattern() {
@@ -871,15 +879,42 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
if (!is_connected) {
return;
}
if (!IsControllerSupported()) {
LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller",
npad_type);
Disconnect();
if (IsControllerSupported()) {
return;
}
Disconnect();
// Fallback fullkey controllers to Pro controllers
if (IsControllerFullkey() && supported_style_tag.fullkey) {
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
SetNpadStyleIndex(NpadStyleIndex::ProController);
Connect();
return;
}
LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller",
npad_type);
}
bool EmulatedController::IsControllerFullkey(bool use_temporary_value) const {
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
switch (type) {
case NpadStyleIndex::ProController:
case NpadStyleIndex::GameCube:
case NpadStyleIndex::NES:
case NpadStyleIndex::SNES:
case NpadStyleIndex::N64:
case NpadStyleIndex::SegaGenesis:
return true;
default:
return false;
}
}
bool EmulatedController::IsControllerSupported() const {
switch (npad_type) {
bool EmulatedController::IsControllerSupported(bool use_temporary_value) const {
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
switch (type) {
case NpadStyleIndex::ProController:
return supported_style_tag.fullkey;
case NpadStyleIndex::Handheld:
@@ -907,9 +942,10 @@ bool EmulatedController::IsControllerSupported() const {
}
}
void EmulatedController::Connect() {
if (!IsControllerSupported()) {
LOG_ERROR(Service_HID, "Controller type {} is not supported", npad_type);
void EmulatedController::Connect(bool use_temporary_value) {
if (!IsControllerSupported(use_temporary_value)) {
const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
LOG_ERROR(Service_HID, "Controller type {} is not supported", type);
return;
}
{
@@ -1110,7 +1146,7 @@ void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npa
int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) {
std::lock_guard lock{mutex};
callback_list.insert_or_assign(last_callback_key, update_callback);
callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
return last_callback_key++;
}
+21 -8
View File
@@ -167,8 +167,11 @@ public:
*/
void SetSupportedNpadStyleTag(NpadStyleTag supported_styles);
/// Sets the connected status to true
void Connect();
/**
* Sets the connected status to true
* @param use_temporary_value If true tmp_npad_type will be used
*/
void Connect(bool use_temporary_value = false);
/// Sets the connected status to false
void Disconnect();
@@ -317,46 +320,56 @@ private:
/// Set the params for TAS devices
void LoadTASParams();
/**
* @param use_temporary_value If true tmp_npad_type will be used
* @return true if the controller style is fullkey
*/
bool IsControllerFullkey(bool use_temporary_value = false) const;
/**
* Checks the current controller type against the supported_style_tag
* @param use_temporary_value If true tmp_npad_type will be used
* @return true if the controller is supported
*/
bool IsControllerSupported() const;
bool IsControllerSupported(bool use_temporary_value = false) const;
/**
* Updates the button status of the controller
* @param callback A CallbackStatus containing the button status
* @param index Button ID of the to be updated
*/
void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
void SetButton(const Common::Input::CallbackStatus& callback, std::size_t index,
Common::UUID uuid);
/**
* Updates the analog stick status of the controller
* @param callback A CallbackStatus containing the analog stick status
* @param index stick ID of the to be updated
*/
void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
void SetStick(const Common::Input::CallbackStatus& callback, std::size_t index,
Common::UUID uuid);
/**
* Updates the trigger status of the controller
* @param callback A CallbackStatus containing the trigger status
* @param index trigger ID of the to be updated
*/
void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
void SetTrigger(const Common::Input::CallbackStatus& callback, std::size_t index,
Common::UUID uuid);
/**
* Updates the motion status of the controller
* @param callback A CallbackStatus containing gyro and accelerometer data
* @param index motion ID of the to be updated
*/
void SetMotion(Common::Input::CallbackStatus callback, std::size_t index);
void SetMotion(const Common::Input::CallbackStatus& callback, std::size_t index);
/**
* Updates the battery status of the controller
* @param callback A CallbackStatus containing the battery status
* @param index Button ID of the to be updated
*/
void SetBattery(Common::Input::CallbackStatus callback, std::size_t index);
void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index);
/**
* Triggers a callback that something has changed on the controller status
+37 -29
View File
@@ -70,50 +70,55 @@ void EmulatedDevices::ReloadInput() {
if (!mouse_button_devices[index]) {
continue;
}
Common::Input::InputCallback button_callback{
[this, index](Common::Input::CallbackStatus callback) {
SetMouseButton(callback, index);
}};
mouse_button_devices[index]->SetCallback(button_callback);
mouse_button_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetMouseButton(callback, index);
},
});
}
for (std::size_t index = 0; index < mouse_analog_devices.size(); ++index) {
if (!mouse_analog_devices[index]) {
continue;
}
Common::Input::InputCallback button_callback{
[this, index](Common::Input::CallbackStatus callback) {
SetMouseAnalog(callback, index);
}};
mouse_analog_devices[index]->SetCallback(button_callback);
mouse_analog_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetMouseAnalog(callback, index);
},
});
}
if (mouse_stick_device) {
Common::Input::InputCallback button_callback{
[this](Common::Input::CallbackStatus callback) { SetMouseStick(callback); }};
mouse_stick_device->SetCallback(button_callback);
mouse_stick_device->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback) { SetMouseStick(callback); },
});
}
for (std::size_t index = 0; index < keyboard_devices.size(); ++index) {
if (!keyboard_devices[index]) {
continue;
}
Common::Input::InputCallback button_callback{
[this, index](Common::Input::CallbackStatus callback) {
SetKeyboardButton(callback, index);
}};
keyboard_devices[index]->SetCallback(button_callback);
keyboard_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetKeyboardButton(callback, index);
},
});
}
for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) {
if (!keyboard_modifier_devices[index]) {
continue;
}
Common::Input::InputCallback button_callback{
[this, index](Common::Input::CallbackStatus callback) {
SetKeyboardModifier(callback, index);
}};
keyboard_modifier_devices[index]->SetCallback(button_callback);
keyboard_modifier_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetKeyboardModifier(callback, index);
},
});
}
}
@@ -159,7 +164,8 @@ void EmulatedDevices::RestoreConfig() {
ReloadFromSettings();
}
void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index) {
void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& callback,
std::size_t index) {
if (index >= device_status.keyboard_values.size()) {
return;
}
@@ -216,7 +222,7 @@ void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
}
}
void EmulatedDevices::SetKeyboardModifier(Common::Input::CallbackStatus callback,
void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& callback,
std::size_t index) {
if (index >= device_status.keyboard_moddifier_values.size()) {
return;
@@ -286,7 +292,8 @@ void EmulatedDevices::SetKeyboardModifier(Common::Input::CallbackStatus callback
TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
}
void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index) {
void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callback,
std::size_t index) {
if (index >= device_status.mouse_button_values.size()) {
return;
}
@@ -347,7 +354,8 @@ void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std
TriggerOnChange(DeviceTriggerType::Mouse);
}
void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index) {
void EmulatedDevices::SetMouseAnalog(const Common::Input::CallbackStatus& callback,
std::size_t index) {
if (index >= device_status.mouse_analog_values.size()) {
return;
}
@@ -374,7 +382,7 @@ void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std
TriggerOnChange(DeviceTriggerType::Mouse);
}
void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callback) {
std::lock_guard lock{mutex};
const auto touch_value = TransformToTouch(callback);
@@ -435,7 +443,7 @@ void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) {
std::lock_guard lock{mutex};
callback_list.insert_or_assign(last_callback_key, update_callback);
callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
return last_callback_key++;
}
+5 -6
View File
@@ -156,35 +156,34 @@ private:
* @param callback A CallbackStatus containing the key status
* @param index key ID to be updated
*/
void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index);
void SetKeyboardButton(const Common::Input::CallbackStatus& callback, std::size_t index);
/**
* Updates the keyboard status of the keyboard device
* @param callback A CallbackStatus containing the modifier key status
* @param index modifier key ID to be updated
*/
void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index);
void SetKeyboardModifier(const Common::Input::CallbackStatus& callback, std::size_t index);
/**
* Updates the mouse button status of the mouse device
* @param callback A CallbackStatus containing the button status
* @param index Button ID to be updated
*/
void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index);
void SetMouseButton(const Common::Input::CallbackStatus& callback, std::size_t index);
/**
* Updates the mouse wheel status of the mouse device
* @param callback A CallbackStatus containing the wheel status
* @param index wheel ID to be updated
*/
void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index);
void SetMouseAnalog(const Common::Input::CallbackStatus& callback, std::size_t index);
/**
* Updates the mouse position status of the mouse device
* @param callback A CallbackStatus containing the position status
* @param index stick ID to be updated
*/
void SetMouseStick(Common::Input::CallbackStatus callback);
void SetMouseStick(const Common::Input::CallbackStatus& callback);
/**
* Triggers a callback that something has changed on the device status
+7
View File
@@ -496,6 +496,13 @@ struct VibrationValue {
};
static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size.");
constexpr VibrationValue DEFAULT_VIBRATION_VALUE{
.low_amplitude = 0.0f,
.low_frequency = 160.0f,
.high_amplitude = 0.0f,
.high_frequency = 320.0f,
};
// This is nn::hid::VibrationDeviceInfo
struct VibrationDeviceInfo {
VibrationDeviceType type{};
+9 -4
View File
@@ -10,6 +10,7 @@ namespace Core::HID {
MotionInput::MotionInput() {
// Initialize PID constants with default values
SetPID(0.3f, 0.005f, 0.0f);
SetGyroThreshold(0.001f);
}
void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) {
@@ -23,11 +24,11 @@ void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
}
void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
gyro = gyroscope - gyro_drift;
gyro = gyroscope - gyro_bias;
// Auto adjust drift to minimize drift
if (!IsMoving(0.1f)) {
gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f);
gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f);
}
if (gyro.Length2() < gyro_threshold) {
@@ -41,8 +42,8 @@ void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) {
quat = quaternion;
}
void MotionInput::SetGyroDrift(const Common::Vec3f& drift) {
gyro_drift = drift;
void MotionInput::SetGyroBias(const Common::Vec3f& bias) {
gyro_bias = bias;
}
void MotionInput::SetGyroThreshold(f32 threshold) {
@@ -192,6 +193,10 @@ Common::Vec3f MotionInput::GetGyroscope() const {
return gyro;
}
Common::Vec3f MotionInput::GetGyroBias() const {
return gyro_bias;
}
Common::Quaternion<f32> MotionInput::GetQuaternion() const {
return quat;
}
+3 -2
View File
@@ -24,7 +24,7 @@ public:
void SetAcceleration(const Common::Vec3f& acceleration);
void SetGyroscope(const Common::Vec3f& gyroscope);
void SetQuaternion(const Common::Quaternion<f32>& quaternion);
void SetGyroDrift(const Common::Vec3f& drift);
void SetGyroBias(const Common::Vec3f& bias);
void SetGyroThreshold(f32 threshold);
void EnableReset(bool reset);
@@ -36,6 +36,7 @@ public:
[[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
[[nodiscard]] Common::Vec3f GetAcceleration() const;
[[nodiscard]] Common::Vec3f GetGyroscope() const;
[[nodiscard]] Common::Vec3f GetGyroBias() const;
[[nodiscard]] Common::Vec3f GetRotations() const;
[[nodiscard]] Common::Quaternion<f32> GetQuaternion() const;
@@ -69,7 +70,7 @@ private:
Common::Vec3f gyro;
// Vector to be substracted from gyro measurements
Common::Vec3f gyro_drift;
Common::Vec3f gyro_bias;
// Minimum gyro amplitude to detect if the device is moving
f32 gyro_threshold = 0.0f;
@@ -9,6 +9,7 @@
#include "core/hle/kernel/global_scheduler_context.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
namespace Kernel {
@@ -42,6 +43,11 @@ void GlobalSchedulerContext::PreemptThreads() {
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
const u32 priority = preemption_priorities[core_id];
kernel.Scheduler(core_id).RotateScheduledQueue(core_id, priority);
// Signal an interrupt occurred. For core 3, this is a certainty, as preemption will result
// in the rotator thread being scheduled. For cores 0-2, this is to simulate or system
// interrupts that may have occurred.
kernel.PhysicalCore(core_id).Interrupt();
}
}
@@ -0,0 +1,34 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/kernel/k_interrupt_manager.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
namespace Kernel::KInterruptManager {
void HandleInterrupt(KernelCore& kernel, s32 core_id) {
auto* process = kernel.CurrentProcess();
if (!process) {
return;
}
auto& scheduler = kernel.Scheduler(core_id);
auto& current_thread = *scheduler.GetCurrentThread();
// If the user disable count is set, we may need to pin the current thread.
if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) {
KScopedSchedulerLock sl{kernel};
// Pin the current thread.
process->PinCurrentThread(core_id);
// Set the interrupt flag for the thread.
scheduler.GetCurrentThread()->SetInterruptFlag();
}
}
} // namespace Kernel::KInterruptManager
+17
View File
@@ -0,0 +1,17 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
namespace Kernel {
class KernelCore;
namespace KInterruptManager {
void HandleInterrupt(KernelCore& kernel, s32 core_id);
}
} // namespace Kernel
+1 -1
View File
@@ -120,7 +120,7 @@ static_assert(static_cast<u32>(KMemoryState::CodeOut) == 0x00402015);
enum class KMemoryPermission : u8 {
None = 0,
Mask = static_cast<u8>(~None),
All = static_cast<u8>(~None),
Read = 1 << 0,
Write = 1 << 1,
+139 -49
View File
@@ -264,9 +264,9 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_
ASSERT(heap_last < stack_start || stack_last < heap_start);
ASSERT(heap_last < kmap_start || kmap_last < heap_start);
current_heap_addr = heap_region_start;
heap_capacity = 0;
physical_memory_usage = 0;
current_heap_end = heap_region_start;
max_heap_size = 0;
mapped_physical_memory_size = 0;
memory_pool = pool;
page_table_impl.Resize(address_space_width, PageBits);
@@ -306,7 +306,7 @@ ResultCode KPageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std:
KMemoryState state{};
KMemoryPermission perm{};
CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All,
KMemoryState::Normal, KMemoryPermission::Mask,
KMemoryState::Normal, KMemoryPermission::All,
KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask,
KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
@@ -465,7 +465,7 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
MapPhysicalMemory(page_linked_list, addr, end_addr);
physical_memory_usage += remaining_size;
mapped_physical_memory_size += remaining_size;
const std::size_t num_pages{size / PageSize};
block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None,
@@ -507,7 +507,7 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
auto process{system.Kernel().CurrentProcess()};
process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size);
physical_memory_usage -= mapped_size;
mapped_physical_memory_size -= mapped_size;
return ResultSuccess;
}
@@ -554,7 +554,7 @@ ResultCode KPageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
KMemoryState src_state{};
CASCADE_CODE(CheckMemoryState(
&src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::ReadAndWrite,
KMemoryState::FlagCanAlias, KMemoryPermission::All, KMemoryPermission::ReadAndWrite,
KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
if (IsRegionMapped(dst_addr, size)) {
@@ -593,7 +593,7 @@ ResultCode KPageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
KMemoryState src_state{};
CASCADE_CODE(CheckMemoryState(
&src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::None,
KMemoryState::FlagCanAlias, KMemoryPermission::All, KMemoryPermission::None,
KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
KMemoryPermission dst_perm{};
@@ -784,7 +784,7 @@ ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemo
CASCADE_CODE(CheckMemoryState(
&state, nullptr, &attribute, addr, size,
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted,
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::Mask,
KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::All,
KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None,
KMemoryAttribute::IpcAndDeviceMapped));
@@ -806,6 +806,33 @@ ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite);
return ResultSuccess;
}
ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
Svc::MemoryPermission svc_perm) {
const size_t num_pages = size / PageSize;
// Lock the table.
std::lock_guard lock{page_table_lock};
// Verify we can change the memory permission.
KMemoryState old_state;
KMemoryPermission old_perm;
R_TRY(this->CheckMemoryState(
std::addressof(old_state), std::addressof(old_perm), nullptr, addr, size,
KMemoryState::FlagCanReprotect, KMemoryState::FlagCanReprotect, KMemoryPermission::None,
KMemoryPermission::None, KMemoryAttribute::All, KMemoryAttribute::None));
// Determine new perm.
const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm);
R_SUCCEED_IF(old_perm == new_perm);
// Perform mapping operation.
R_TRY(Operate(addr, num_pages, new_perm, OperationType::ChangePermissions));
// Update the blocks.
block_manager->Update(addr, num_pages, old_state, new_perm, KMemoryAttribute::None);
return ResultSuccess;
}
@@ -832,61 +859,125 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryA
return ResultSuccess;
}
ResultCode KPageTable::SetHeapCapacity(std::size_t new_heap_capacity) {
ResultCode KPageTable::SetMaxHeapSize(std::size_t size) {
// Lock the table.
std::lock_guard lock{page_table_lock};
heap_capacity = new_heap_capacity;
// Only process page tables are allowed to set heap size.
ASSERT(!this->IsKernel());
max_heap_size = size;
return ResultSuccess;
}
ResultVal<VAddr> KPageTable::SetHeapSize(std::size_t size) {
ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
// Try to perform a reduction in heap, instead of an extension.
VAddr cur_address{};
std::size_t allocation_size{};
{
// Lock the table.
std::lock_guard lk(page_table_lock);
if (size > heap_region_end - heap_region_start) {
return ResultOutOfMemory;
// Validate that setting heap size is possible at all.
R_UNLESS(!is_kernel, ResultOutOfMemory);
R_UNLESS(size <= static_cast<std::size_t>(heap_region_end - heap_region_start),
ResultOutOfMemory);
R_UNLESS(size <= max_heap_size, ResultOutOfMemory);
if (size < GetHeapSize()) {
// The size being requested is less than the current size, so we need to free the end of
// the heap.
// Validate memory state.
std::size_t num_allocator_blocks;
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks),
heap_region_start + size, GetHeapSize() - size,
KMemoryState::All, KMemoryState::Normal,
KMemoryPermission::All, KMemoryPermission::ReadAndWrite,
KMemoryAttribute::All, KMemoryAttribute::None));
// Unmap the end of the heap.
const auto num_pages = (GetHeapSize() - size) / PageSize;
R_TRY(Operate(heap_region_start + size, num_pages, KMemoryPermission::None,
OperationType::Unmap));
// Release the memory from the resource limit.
system.Kernel().CurrentProcess()->GetResourceLimit()->Release(
LimitableResource::PhysicalMemory, num_pages * PageSize);
// Apply the memory block update.
block_manager->Update(heap_region_start + size, num_pages, KMemoryState::Free,
KMemoryPermission::None, KMemoryAttribute::None);
// Update the current heap end.
current_heap_end = heap_region_start + size;
// Set the output.
*out = heap_region_start;
return ResultSuccess;
} else if (size == GetHeapSize()) {
// The size requested is exactly the current size.
*out = heap_region_start;
return ResultSuccess;
} else {
// We have to allocate memory. Determine how much to allocate and where while the table
// is locked.
cur_address = current_heap_end;
allocation_size = size - GetHeapSize();
}
}
const u64 previous_heap_size{GetHeapSize()};
// Reserve memory for the heap extension.
KScopedResourceReservation memory_reservation(
system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
allocation_size);
R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
UNIMPLEMENTED_IF_MSG(previous_heap_size > size, "Heap shrink is unimplemented");
// Allocate pages for the heap extension.
KPageLinkedList page_linked_list;
R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize,
memory_pool));
// Increase the heap size
// Map the pages.
{
std::lock_guard lock{page_table_lock};
// Lock the table.
std::lock_guard lk(page_table_lock);
const u64 delta{size - previous_heap_size};
// Ensure that the heap hasn't changed since we began executing.
ASSERT(cur_address == current_heap_end);
// Reserve memory for the heap extension.
KScopedResourceReservation memory_reservation(
system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
delta);
// Check the memory state.
std::size_t num_allocator_blocks{};
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), current_heap_end,
allocation_size, KMemoryState::All, KMemoryState::Free,
KMemoryPermission::None, KMemoryPermission::None,
KMemoryAttribute::None, KMemoryAttribute::None));
if (!memory_reservation.Succeeded()) {
LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta);
return ResultLimitReached;
// Map the pages.
const auto num_pages = allocation_size / PageSize;
R_TRY(Operate(current_heap_end, num_pages, page_linked_list, OperationType::MapGroup));
// Clear all the newly allocated pages.
for (std::size_t cur_page = 0; cur_page < num_pages; ++cur_page) {
std::memset(system.Memory().GetPointer(current_heap_end + (cur_page * PageSize)), 0,
PageSize);
}
KPageLinkedList page_linked_list;
const std::size_t num_pages{delta / PageSize};
CASCADE_CODE(
system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool));
if (IsRegionMapped(current_heap_addr, delta)) {
return ResultInvalidCurrentMemory;
}
CASCADE_CODE(
Operate(current_heap_addr, num_pages, page_linked_list, OperationType::MapGroup));
// Succeeded in allocation, commit the resource reservation
// We succeeded, so commit our memory reservation.
memory_reservation.Commit();
block_manager->Update(current_heap_addr, num_pages, KMemoryState::Normal,
KMemoryPermission::ReadAndWrite);
// Apply the memory block update.
block_manager->Update(current_heap_end, num_pages, KMemoryState::Normal,
KMemoryPermission::ReadAndWrite, KMemoryAttribute::None);
current_heap_addr = heap_region_start + size;
// Update the current heap end.
current_heap_end = heap_region_start + size;
// Set the output.
*out = heap_region_start;
return ResultSuccess;
}
return heap_region_start;
}
ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
@@ -978,7 +1069,7 @@ ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
if (const ResultCode result{CheckMemoryState(
nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
KMemoryState::FlagCanCodeMemory, KMemoryPermission::Mask,
KMemoryState::FlagCanCodeMemory, KMemoryPermission::All,
KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)};
result.IsError()) {
return result;
@@ -1031,9 +1122,8 @@ ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
bool KPageTable::IsRegionMapped(VAddr address, u64 size) {
return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free,
KMemoryPermission::Mask, KMemoryPermission::None,
KMemoryAttribute::Mask, KMemoryAttribute::None,
KMemoryAttribute::IpcAndDeviceMapped)
KMemoryPermission::All, KMemoryPermission::None, KMemoryAttribute::Mask,
KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)
.IsError();
}
+10 -10
View File
@@ -47,10 +47,11 @@ public:
KMemoryInfo QueryInfo(VAddr addr);
ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm);
ResultCode ResetTransferMemory(VAddr addr, std::size_t size);
ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm);
ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
KMemoryAttribute value);
ResultCode SetHeapCapacity(std::size_t new_heap_capacity);
ResultVal<VAddr> SetHeapSize(std::size_t size);
ResultCode SetMaxHeapSize(std::size_t size);
ResultCode SetHeapSize(VAddr* out, std::size_t size);
ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
bool is_map_only, VAddr region_start,
std::size_t region_num_pages, KMemoryState state,
@@ -182,14 +183,15 @@ public:
constexpr VAddr GetAliasCodeRegionSize() const {
return alias_code_region_end - alias_code_region_start;
}
size_t GetNormalMemorySize() {
std::lock_guard lk(page_table_lock);
return GetHeapSize() + mapped_physical_memory_size;
}
constexpr std::size_t GetAddressSpaceWidth() const {
return address_space_width;
}
constexpr std::size_t GetHeapSize() {
return current_heap_addr - heap_region_start;
}
constexpr std::size_t GetTotalHeapSize() {
return GetHeapSize() + physical_memory_usage;
constexpr std::size_t GetHeapSize() const {
return current_heap_end - heap_region_start;
}
constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const {
return address_space_start <= address && address + size - 1 <= address_space_end - 1;
@@ -269,10 +271,8 @@ private:
VAddr code_region_end{};
VAddr alias_code_region_start{};
VAddr alias_code_region_end{};
VAddr current_heap_addr{};
std::size_t heap_capacity{};
std::size_t physical_memory_usage{};
std::size_t mapped_physical_memory_size{};
std::size_t max_heap_size{};
std::size_t max_physical_memory_size{};
std::size_t address_space_width{};
+9 -13
View File
@@ -28,7 +28,6 @@
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/lock.h"
#include "core/memory.h"
namespace Kernel {
@@ -173,7 +172,7 @@ void KProcess::DecrementThreadCount() {
u64 KProcess::GetTotalPhysicalMemoryAvailable() const {
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
page_table->GetNormalMemorySize() + GetSystemResourceSize() + image_size +
main_thread_stack_size};
if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application);
capacity != pool_size) {
@@ -190,7 +189,7 @@ u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const {
}
u64 KProcess::GetTotalPhysicalMemoryUsed() const {
return image_size + main_thread_stack_size + page_table->GetTotalHeapSize() +
return image_size + main_thread_stack_size + page_table->GetNormalMemorySize() +
GetSystemResourceSize();
}
@@ -221,30 +220,28 @@ bool KProcess::ReleaseUserException(KThread* thread) {
}
}
void KProcess::PinCurrentThread() {
void KProcess::PinCurrentThread(s32 core_id) {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
// Get the current thread.
const s32 core_id = GetCurrentCoreId(kernel);
KThread* cur_thread = GetCurrentThreadPointer(kernel);
KThread* cur_thread = kernel.Scheduler(static_cast<std::size_t>(core_id)).GetCurrentThread();
// If the thread isn't terminated, pin it.
if (!cur_thread->IsTerminationRequested()) {
// Pin it.
PinThread(core_id, cur_thread);
cur_thread->Pin();
cur_thread->Pin(core_id);
// An update is needed.
KScheduler::SetSchedulerUpdateNeeded(kernel);
}
}
void KProcess::UnpinCurrentThread() {
void KProcess::UnpinCurrentThread(s32 core_id) {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
// Get the current thread.
const s32 core_id = GetCurrentCoreId(kernel);
KThread* cur_thread = GetCurrentThreadPointer(kernel);
KThread* cur_thread = kernel.Scheduler(static_cast<std::size_t>(core_id)).GetCurrentThread();
// Unpin it.
cur_thread->Unpin();
@@ -411,8 +408,8 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) {
resource_limit->Reserve(LimitableResource::Threads, 1);
resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
const std::size_t heap_capacity{memory_usage_capacity - main_thread_stack_size - image_size};
ASSERT(!page_table->SetHeapCapacity(heap_capacity).IsError());
const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)};
ASSERT(!page_table->SetMaxHeapSize(heap_capacity).IsError());
ChangeStatus(ProcessStatus::Running);
@@ -543,7 +540,6 @@ void KProcess::FreeTLSRegion(VAddr tls_address) {
}
void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) {
std::lock_guard lock{HLE::g_hle_lock};
const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
KMemoryPermission permission) {
page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
+2 -2
View File
@@ -345,8 +345,8 @@ public:
bool IsSignaled() const override;
void PinCurrentThread();
void UnpinCurrentThread();
void PinCurrentThread(s32 core_id);
void UnpinCurrentThread(s32 core_id);
void UnpinThread(KThread* thread);
KLightLock& GetStateLock() {
+8
View File
@@ -15,6 +15,7 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/cpu_manager.h"
#include "core/hle/kernel/k_interrupt_manager.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
@@ -53,6 +54,13 @@ void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedul
}
cores_pending_reschedule &= ~(1ULL << core);
}
for (std::size_t core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; ++core_id) {
if (kernel.PhysicalCore(core_id).IsInterrupted()) {
KInterruptManager::HandleInterrupt(kernel, static_cast<s32>(core_id));
}
}
if (must_context_switch) {
auto core_scheduler = kernel.CurrentScheduler();
kernel.ExitSVCProfile();
+43 -3
View File
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <atomic>
#include <cinttypes>
#include <optional>
#include <vector>
@@ -26,12 +27,14 @@
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_system_control.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/result.h"
#include "core/memory.h"
#ifdef ARCHITECTURE_x86_64
#include "core/arm/dynarmic/arm_dynarmic_32.h"
@@ -50,6 +53,7 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
VAddr entry_point, u64 arg) {
context = {};
context.cpu_registers[0] = arg;
context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
context.pc = entry_point;
context.sp = stack_top;
// TODO(merry): Perform a hardware test to determine the below value.
@@ -61,6 +65,13 @@ namespace Kernel {
namespace {
struct ThreadLocalRegion {
static constexpr std::size_t MessageBufferSize = 0x100;
std::array<u32, MessageBufferSize / sizeof(u32)> message_buffer;
std::atomic_uint16_t disable_count;
std::atomic_uint16_t interrupt_flag;
};
class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait {
public:
explicit ThreadQueueImplForKThreadSleep(KernelCore& kernel_)
@@ -344,7 +355,7 @@ void KThread::StartTermination() {
if (parent != nullptr) {
parent->ReleaseUserException(this);
if (parent->GetPinnedThread(GetCurrentCoreId(kernel)) == this) {
parent->UnpinCurrentThread();
parent->UnpinCurrentThread(core_id);
}
}
@@ -370,7 +381,7 @@ void KThread::StartTermination() {
this->Close();
}
void KThread::Pin() {
void KThread::Pin(s32 current_core) {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
// Set ourselves as pinned.
@@ -387,7 +398,6 @@ void KThread::Pin() {
// Bind ourselves to this core.
const s32 active_core = GetActiveCore();
const s32 current_core = GetCurrentCoreId(kernel);
SetActiveCore(current_core);
physical_ideal_core_id = current_core;
@@ -480,6 +490,36 @@ void KThread::Unpin() {
}
}
u16 KThread::GetUserDisableCount() const {
if (!IsUserThread()) {
// We only emulate TLS for user threads
return {};
}
auto& memory = kernel.System().Memory();
return memory.Read16(tls_address + offsetof(ThreadLocalRegion, disable_count));
}
void KThread::SetInterruptFlag() {
if (!IsUserThread()) {
// We only emulate TLS for user threads
return;
}
auto& memory = kernel.System().Memory();
memory.Write16(tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 1);
}
void KThread::ClearInterruptFlag() {
if (!IsUserThread()) {
// We only emulate TLS for user threads
return;
}
auto& memory = kernel.System().Memory();
memory.Write16(tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0);
}
ResultCode KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
KScopedSchedulerLock sl{kernel};
+5 -1
View File
@@ -307,6 +307,10 @@ public:
return parent != nullptr;
}
u16 GetUserDisableCount() const;
void SetInterruptFlag();
void ClearInterruptFlag();
[[nodiscard]] KThread* GetLockOwner() const {
return lock_owner;
}
@@ -490,7 +494,7 @@ public:
this->GetStackParameters().disable_count--;
}
void Pin();
void Pin(s32 current_core);
void Unpin();
+4 -1
View File
@@ -182,7 +182,10 @@ struct KernelCore::Impl {
// Shutdown all processes.
if (current_process) {
current_process->Finalize();
current_process->Close();
// current_process->Close();
// TODO: The current process should be destroyed based on accurate ref counting after
// calling Close(). Adding a manual Destroy() call instead to avoid a memory leak.
current_process->Destroy();
current_process = nullptr;
}
+67 -41
View File
@@ -41,7 +41,6 @@
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/kernel/svc_wrap.h"
#include "core/hle/lock.h"
#include "core/hle/result.h"
#include "core/memory.h"
#include "core/reporter.h"
@@ -136,25 +135,15 @@ enum class ResourceLimitValueType {
} // Anonymous namespace
/// Set the process heap to a given Size. It can both extend and shrink the heap.
static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
static ResultCode SetHeapSize(Core::System& system, VAddr* out_address, u64 size) {
LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size);
// Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB.
if ((heap_size % 0x200000) != 0) {
LOG_ERROR(Kernel_SVC, "The heap size is not a multiple of 2MB, heap_size=0x{:016X}",
heap_size);
return ResultInvalidSize;
}
// Validate size.
R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize);
R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
if (heap_size >= 0x200000000) {
LOG_ERROR(Kernel_SVC, "The heap size is not less than 8GB, heap_size=0x{:016X}", heap_size);
return ResultInvalidSize;
}
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
CASCADE_RESULT(*heap_addr, page_table.SetHeapSize(heap_size));
// Set the heap size.
R_TRY(system.Kernel().CurrentProcess()->PageTable().SetHeapSize(out_address, size));
return ResultSuccess;
}
@@ -166,9 +155,38 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s
return result;
}
constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
switch (perm) {
case MemoryPermission::None:
case MemoryPermission::Read:
case MemoryPermission::ReadWrite:
return true;
default:
return false;
}
}
static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size,
MemoryPermission perm) {
// Validate address / size.
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Validate the permission.
R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
// Validate that the region is in range for the current process.
auto& page_table = system.Kernel().CurrentProcess()->PageTable();
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
// Set the memory attribute.
return page_table.SetMemoryPermission(address, size, perm);
}
static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
u32 attribute) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_DEBUG(Kernel_SVC,
"called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address,
size, mask, attribute);
@@ -212,7 +230,6 @@ static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 si
/// Maps a memory range into a different range.
static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
@@ -232,7 +249,6 @@ static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr,
/// Unmaps a region that was previously mapped with svcMapMemory
static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
@@ -642,7 +658,6 @@ static void OutputDebugString(Core::System& system, VAddr address, u64 len) {
/// Gets system/memory information for the current process
static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle,
u64 info_sub_id) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
info_sub_id, handle);
@@ -886,22 +901,17 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
return ResultSuccess;
}
case GetInfoType::IdleTickCount: {
if (handle == 0) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
static_cast<Handle>(handle));
return ResultInvalidHandle;
}
// Verify the input handle is invalid.
R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
if (info_sub_id != 0xFFFFFFFFFFFFFFFF &&
info_sub_id != system.Kernel().CurrentPhysicalCoreIndex()) {
LOG_ERROR(Kernel_SVC, "Core is not the current core, got {}", info_sub_id);
return ResultInvalidCombination;
}
// Verify the requested core is valid.
const bool core_valid =
(info_sub_id == static_cast<u64>(-1ULL)) ||
(info_sub_id == static_cast<u64>(system.Kernel().CurrentPhysicalCoreIndex()));
R_UNLESS(core_valid, ResultInvalidCombination);
const auto& scheduler = *system.Kernel().CurrentScheduler();
const auto* const idle_thread = scheduler.GetIdleThread();
*result = idle_thread->GetCpuTime();
// Get the idle tick count.
*result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime();
return ResultSuccess;
}
default:
@@ -924,7 +934,6 @@ static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_h
/// Maps memory at a desired address
static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
if (!Common::Is4KBAligned(addr)) {
@@ -978,7 +987,6 @@ static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size)
/// Unmaps memory previously mapped via MapPhysicalMemory
static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
if (!Common::Is4KBAligned(addr)) {
@@ -1520,7 +1528,6 @@ static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_han
static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
VAddr page_info_address, Handle process_handle,
VAddr address) {
std::lock_guard lock{HLE::g_hle_lock};
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
@@ -2020,6 +2027,25 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign
count);
}
static void SynchronizePreemptionState(Core::System& system) {
auto& kernel = system.Kernel();
// Lock the scheduler.
KScopedSchedulerLock sl{kernel};
// If the current thread is pinned, unpin it.
KProcess* cur_process = system.Kernel().CurrentProcess();
const auto core_id = GetCurrentCoreId(kernel);
if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(kernel)) {
// Clear the current thread's interrupt flag.
GetCurrentThread(kernel).ClearInterruptFlag();
// Unpin the current thread.
cur_process->UnpinCurrentThread(core_id);
}
}
static ResultCode SignalToAddress32(Core::System& system, u32 address, Svc::SignalType signal_type,
s32 value, s32 count) {
return SignalToAddress(system, address, signal_type, value, count);
@@ -2738,7 +2764,7 @@ static const FunctionDef SVC_Table_32[] = {
static const FunctionDef SVC_Table_64[] = {
{0x00, nullptr, "Unknown"},
{0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
{0x02, nullptr, "SetMemoryPermission"},
{0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
{0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
{0x04, SvcWrap64<MapMemory>, "MapMemory"},
{0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},
@@ -2790,7 +2816,7 @@ static const FunctionDef SVC_Table_64[] = {
{0x33, SvcWrap64<GetThreadContext>, "GetThreadContext"},
{0x34, SvcWrap64<WaitForAddress>, "WaitForAddress"},
{0x35, SvcWrap64<SignalToAddress>, "SignalToAddress"},
{0x36, nullptr, "SynchronizePreemptionState"},
{0x36, SvcWrap64<SynchronizePreemptionState>, "SynchronizePreemptionState"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
{0x39, nullptr, "Unknown"},
+5
View File
@@ -5,6 +5,7 @@
#pragma once
#include "common/common_types.h"
#include "common/literals.h"
namespace Kernel {
using Handle = u32;
@@ -12,9 +13,13 @@ using Handle = u32;
namespace Kernel::Svc {
using namespace Common::Literals;
constexpr s32 ArgumentHandleCountMax = 0x40;
constexpr u32 HandleWaitMask{1u << 30};
constexpr inline std::size_t HeapSizeAlignment = 2_MiB;
constexpr inline Handle InvalidHandle = Handle(0);
enum PseudoHandle : Handle {
+8
View File
@@ -249,6 +249,14 @@ void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
}
// Used by SetMemoryPermission
template <ResultCode func(Core::System&, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<Svc::MemoryPermission>(Param(system, 2)))
.raw);
}
// Used by MapSharedMemory
template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
-9
View File
@@ -1,9 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <core/hle/lock.h>
namespace HLE {
std::recursive_mutex g_hle_lock;
}
-18
View File
@@ -1,18 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <mutex>
namespace HLE {
/*
* Synchronizes access to the internal HLE kernel structures, it is acquired when a guest
* application thread performs a syscall. It should be acquired by any host threads that read or
* modify the HLE kernel state. Note: Any operation that directly or indirectly reads from or writes
* to the emulated memory is not protected by this mutex, and should be avoided in any threads other
* than the CPU thread.
*/
extern std::recursive_mutex g_hle_lock;
} // namespace HLE
+1 -11
View File
@@ -6,7 +6,6 @@
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/lock.h"
#include "core/hle/service/bcat/backend/backend.h"
namespace Service::BCAT {
@@ -29,10 +28,6 @@ DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() {
return impl;
}
void ProgressServiceBackend::SetNeedHLELock(bool need) {
need_hle_lock = need;
}
void ProgressServiceBackend::SetTotalSize(u64 size) {
impl.total_bytes = size;
SignalUpdate();
@@ -88,12 +83,7 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) {
}
void ProgressServiceBackend::SignalUpdate() {
if (need_hle_lock) {
std::lock_guard lock(HLE::g_hle_lock);
update_event->GetWritableEvent().Signal();
} else {
update_event->GetWritableEvent().Signal();
}
update_event->GetWritableEvent().Signal();
}
Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {}
@@ -71,10 +71,6 @@ class ProgressServiceBackend {
public:
~ProgressServiceBackend();
// Clients should call this with true if any of the functions are going to be called from a
// non-HLE thread and this class need to lock the hle mutex. (default is false)
void SetNeedHLELock(bool need);
// Sets the number of bytes total in the entire download.
void SetTotalSize(u64 size);
@@ -109,7 +105,6 @@ private:
DeliveryCacheProgressImpl impl{};
Kernel::KEvent* update_event;
bool need_hle_lock = false;
};
// A class representing an abstract backend for BCAT functionality.
@@ -33,15 +33,14 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state;
next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1;
// Try to read sixaxis sensor states
const auto motion_status = console->GetMotion();
last_global_timestamp = core_timing.GetGlobalTimeNs().count();
console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
// This value increments every time the switch goes to sleep
next_seven_sixaxis_state.unknown = 1;
next_seven_sixaxis_state.timestamp = last_global_timestamp - last_saved_timestamp;
next_seven_sixaxis_state.accel = motion_status.accel;
// Zero gyro values as they just mess up with the camera
// Note: Probably a correct sensivity setting must be set
next_seven_sixaxis_state.gyro = {};
next_seven_sixaxis_state.gyro = motion_status.gyro;
next_seven_sixaxis_state.quaternion = {
{
motion_status.quaternion.xyz.y,
@@ -52,9 +51,9 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
};
console_six_axis.sampling_number++;
// TODO(German77): Find the purpose of those values
console_six_axis.verticalization_error = 0.0f;
console_six_axis.gyro_bias = {0.0f, 0.0f, 0.0f};
console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
console_six_axis.verticalization_error = motion_status.verticalization_error;
console_six_axis.gyro_bias = motion_status.gyro_bias;
// Update console six axis shared memory
std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis));
@@ -69,7 +68,6 @@ void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
}
void Controller_ConsoleSixAxis::ResetTimestamp() {
seven_sixaxis_lifo.buffer_count = 0;
seven_sixaxis_lifo.buffer_tail = 0;
last_saved_timestamp = last_global_timestamp;
}
} // namespace Service::HID
@@ -39,8 +39,9 @@ public:
private:
struct SevenSixAxisState {
INSERT_PADDING_WORDS(4); // unused
s64 sampling_number{};
INSERT_PADDING_WORDS(2); // unused
u64 timestamp{};
u64 sampling_number{};
u64 unknown{};
Common::Vec3f accel{};
Common::Vec3f gyro{};
@@ -52,9 +53,10 @@ private:
struct ConsoleSharedMemory {
u64 sampling_number{};
bool is_seven_six_axis_sensor_at_rest{};
INSERT_PADDING_BYTES(4); // padding
INSERT_PADDING_BYTES(3); // padding
f32 verticalization_error{};
Common::Vec3f gyro_bias{};
INSERT_PADDING_BYTES(4); // padding
};
static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
@@ -64,6 +66,8 @@ private:
Core::HID::EmulatedConsole* console;
u8* transfer_memory = nullptr;
bool is_transfer_memory_set = false;
u64 last_saved_timestamp{};
u64 last_global_timestamp{};
ConsoleSharedMemory console_six_axis{};
SevenSixAxisState next_seven_sixaxis_state{};
};
@@ -66,9 +66,9 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
auto& controller = controller_data[i];
controller.device = hid_core.GetEmulatedControllerByIndex(i);
controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
DEFAULT_VIBRATION_VALUE;
Core::HID::DEFAULT_VIBRATION_VALUE;
controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
DEFAULT_VIBRATION_VALUE;
Core::HID::DEFAULT_VIBRATION_VALUE;
Core::HID::ControllerUpdateCallback engine_callback{
.on_change = [this,
i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
@@ -781,7 +781,8 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
controller.device->SetVibration(device_index, vibration);
// Then reset the vibration value to its default value.
controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
controller.vibration[device_index].latest_vibration_value =
Core::HID::DEFAULT_VIBRATION_VALUE;
}
return false;
@@ -90,13 +90,6 @@ public:
Default = 3,
};
static constexpr Core::HID::VibrationValue DEFAULT_VIBRATION_VALUE{
.low_amplitude = 0.0f,
.low_frequency = 160.0f,
.high_amplitude = 0.0f,
.high_frequency = 320.0f,
};
void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
Core::HID::NpadStyleTag GetSupportedStyleSet() const;
+1 -1
View File
@@ -1404,7 +1404,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
.high_frequency = 0.0f,
};
default:
return Controller_NPad::DEFAULT_VIBRATION_VALUE;
return Core::HID::DEFAULT_VIBRATION_VALUE;
}
}();
-2
View File
@@ -9,7 +9,6 @@
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/lock.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"
@@ -337,7 +336,6 @@ void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
}
bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
std::lock_guard lock{HLE::g_hle_lock};
if (buffer.size() < sizeof(AmiiboFile)) {
return false;
}
@@ -186,6 +186,10 @@ u32 BufferQueue::Query(QueryType type) {
case QueryType::NativeWindowWidth:
case QueryType::NativeWindowHeight:
break;
case QueryType::NativeWindowMinUndequeuedBuffers:
return 0;
case QueryType::NativeWindowConsumerUsageBits:
return 0;
}
UNIMPLEMENTED_MSG("Unimplemented query type={}", type);
return 0;
@@ -57,6 +57,11 @@ public:
NativeWindowWidth = 0,
NativeWindowHeight = 1,
NativeWindowFormat = 2,
/// The minimum number of buffers that must remain un-dequeued after a buffer has been
/// queued
NativeWindowMinUndequeuedBuffers = 3,
/// The consumer gralloc usage bits currently set by the consumer
NativeWindowConsumerUsageBits = 10,
};
explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_,
@@ -100,9 +100,6 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
LOG_DEBUG(Service, "Opening \"{}\" display", name);
// TODO(Subv): Currently we only support the Default display.
ASSERT(name == "Default");
const auto itr =
std::find_if(displays.begin(), displays.end(),
[&](const VI::Display& display) { return display.GetName() == name; });
+7 -1
View File
@@ -71,7 +71,6 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, 0x1FE00000,
kip->GetKernelCapabilities());
const VAddr base_address = process.PageTable().GetCodeRegionStart();
Kernel::CodeSet codeset;
Kernel::PhysicalMemory program_image;
@@ -91,7 +90,14 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize());
codeset.DataSegment().size += kip->GetBSSSize();
// Setup the process code layout
if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size())
.IsError()) {
return {ResultStatus::ErrorNotInitialized, {}};
}
codeset.memory = std::move(program_image);
const VAddr base_address = process.PageTable().GetCodeRegionStart();
process.LoadModule(std::move(codeset), base_address);
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
+3 -3
View File
@@ -69,7 +69,7 @@ private:
libusb_device_handle* handle{};
};
GCAdapter::GCAdapter(const std::string& input_engine_) : InputEngine(input_engine_) {
GCAdapter::GCAdapter(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
if (usb_adapter_handle) {
return;
}
@@ -325,8 +325,8 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
return true;
}
Common::Input::VibrationError GCAdapter::SetRumble(const PadIdentifier& identifier,
const Common::Input::VibrationStatus vibration) {
Common::Input::VibrationError GCAdapter::SetRumble(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
const auto processed_amplitude =
static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8);
+4 -4
View File
@@ -22,13 +22,13 @@ namespace InputCommon {
class LibUSBContext;
class LibUSBDeviceHandle;
class GCAdapter : public InputCommon::InputEngine {
class GCAdapter : public InputEngine {
public:
explicit GCAdapter(const std::string& input_engine_);
~GCAdapter();
explicit GCAdapter(std::string input_engine_);
~GCAdapter() override;
Common::Input::VibrationError SetRumble(
const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override;
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
/// Used for automapping features
std::vector<Common::ParamPackage> GetInputDevices() const override;
+1 -1
View File
@@ -24,7 +24,7 @@ constexpr PadIdentifier keyboard_modifier_identifier = {
.pad = 1,
};
Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) {
Keyboard::Keyboard(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
// Keyboard is broken into 3 diferent sets:
// key: Unfiltered intended for controllers.
// keyboard_key: Allows only Settings::NativeKeyboard::Keys intended for keyboard emulation.
+2 -2
View File
@@ -12,9 +12,9 @@ namespace InputCommon {
* A button device factory representing a keyboard. It receives keyboard events and forward them
* to all button devices it created.
*/
class Keyboard final : public InputCommon::InputEngine {
class Keyboard final : public InputEngine {
public:
explicit Keyboard(const std::string& input_engine_);
explicit Keyboard(std::string input_engine_);
/**
* Sets the status of all buttons bound with the key to pressed
+1 -1
View File
@@ -24,7 +24,7 @@ constexpr PadIdentifier identifier = {
.pad = 0,
};
Mouse::Mouse(const std::string& input_engine_) : InputEngine(input_engine_) {
Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
PreSetController(identifier);
PreSetAxis(identifier, mouse_axis_x);
PreSetAxis(identifier, mouse_axis_y);
+2 -2
View File
@@ -27,9 +27,9 @@ enum class MouseButton {
* A button device factory representing a keyboard. It receives keyboard events and forward them
* to all button devices it created.
*/
class Mouse final : public InputCommon::InputEngine {
class Mouse final : public InputEngine {
public:
explicit Mouse(const std::string& input_engine_);
explicit Mouse(std::string input_engine_);
/**
* Signals that mouse has moved.
+11 -8
View File
@@ -88,7 +88,7 @@ public:
return true;
}
BasicMotion GetMotion() {
const BasicMotion& GetMotion() const {
return motion;
}
@@ -367,7 +367,7 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {
if (joystick->UpdateMotion(event.csensor)) {
const PadIdentifier identifier = joystick->GetPadIdentifier();
SetMotion(identifier, 0, joystick->GetMotion());
};
}
}
break;
}
@@ -387,7 +387,7 @@ void SDLDriver::CloseJoysticks() {
joystick_map.clear();
}
SDLDriver::SDLDriver(const std::string& input_engine_) : InputEngine(input_engine_) {
SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
if (!Settings::values.enable_raw_input) {
// Disable raw input. When enabled this setting causes SDL to die when a web applet opens
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0");
@@ -403,10 +403,11 @@ SDLDriver::SDLDriver(const std::string& input_engine_) : InputEngine(input_engin
// Use hidapi driver for joycons. This will allow joycons to be detected as a GameController and
// not a generic one
SDL_SetHint("SDL_JOYSTICK_HIDAPI_JOY_CONS", "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
// Turn off Pro controller home led
SDL_SetHint("SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED", "0");
// Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native
// driver on Linux.
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0");
// If the frontend is going to manage the event loop, then we don't start one here
start_thread = SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == 0;
@@ -491,8 +492,9 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
}
return devices;
}
Common::Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifier,
const Common::Input::VibrationStatus vibration) {
Common::Input::VibrationError SDLDriver::SetRumble(
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
const auto joystick =
GetSDLJoystickByGUID(identifier.guid.Format(), static_cast<int>(identifier.port));
const auto process_amplitude_exp = [](f32 amplitude, f32 factor) {
@@ -526,6 +528,7 @@ Common::Input::VibrationError SDLDriver::SetRumble(const PadIdentifier& identifi
return Common::Input::VibrationError::None;
}
Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
s32 axis, float value) const {
Common::ParamPackage params{};
+7 -7
View File
@@ -19,19 +19,19 @@ using SDL_GameController = struct _SDL_GameController;
using SDL_Joystick = struct _SDL_Joystick;
using SDL_JoystickID = s32;
namespace InputCommon {
class SDLJoystick;
using ButtonBindings =
std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerButton>, 17>;
using ZButtonBindings =
std::array<std::pair<Settings::NativeButton::Values, SDL_GameControllerAxis>, 2>;
namespace InputCommon {
class SDLJoystick;
class SDLDriver : public InputCommon::InputEngine {
class SDLDriver : public InputEngine {
public:
/// Initializes and registers SDL device factories
SDLDriver(const std::string& input_engine_);
explicit SDLDriver(std::string input_engine_);
/// Unregisters SDL device factories and shut them down.
~SDLDriver() override;
@@ -59,7 +59,7 @@ public:
u8 GetHatButtonId(const std::string& direction_name) const override;
Common::Input::VibrationError SetRumble(
const PadIdentifier& identifier, const Common::Input::VibrationStatus vibration) override;
const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
private:
void InitJoystick(int joystick_index);
+1 -1
View File
@@ -46,7 +46,7 @@ constexpr std::array<std::pair<std::string_view, TasButton>, 20> text_to_tas_but
{"KEY_ZR", TasButton::TRIGGER_ZR},
};
Tas::Tas(const std::string& input_engine_) : InputCommon::InputEngine(input_engine_) {
Tas::Tas(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
for (size_t player_index = 0; player_index < PLAYER_NUMBER; player_index++) {
PadIdentifier identifier{
.guid = Common::UUID{},
+3 -3
View File
@@ -81,10 +81,10 @@ enum class TasState {
Stopped,
};
class Tas final : public InputCommon::InputEngine {
class Tas final : public InputEngine {
public:
explicit Tas(const std::string& input_engine_);
~Tas();
explicit Tas(std::string input_engine_);
~Tas() override;
/**
* Changes the input status that will be stored in each frame
+1 -1
View File
@@ -13,7 +13,7 @@ constexpr PadIdentifier identifier = {
.pad = 0,
};
TouchScreen::TouchScreen(const std::string& input_engine_) : InputEngine(input_engine_) {
TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
PreSetController(identifier);
}
+2 -2
View File
@@ -12,9 +12,9 @@ namespace InputCommon {
* A button device factory representing a keyboard. It receives keyboard events and forward them
* to all button devices it created.
*/
class TouchScreen final : public InputCommon::InputEngine {
class TouchScreen final : public InputEngine {
public:
explicit TouchScreen(const std::string& input_engine_);
explicit TouchScreen(std::string input_engine_);
/**
* Signals that mouse has moved.
+38 -34
View File
@@ -136,7 +136,7 @@ static void SocketLoop(Socket* socket) {
socket->Loop();
}
UDPClient::UDPClient(const std::string& input_engine_) : InputEngine(input_engine_) {
UDPClient::UDPClient(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
LOG_INFO(Input, "Udp Initialization started");
ReloadSockets();
}
@@ -536,42 +536,46 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
std::function<void(u16, u16, u16, u16)> data_callback) {
std::thread([=, this] {
u16 min_x{UINT16_MAX};
u16 min_y{UINT16_MAX};
u16 max_x{};
u16 max_y{};
Status current_status{Status::Initialized};
SocketCallback callback{
[](Response::Version) {}, [](Response::PortInfo) {},
[&](Response::PadData data) {
static constexpr u16 CALIBRATION_THRESHOLD = 100;
static constexpr u16 MAX_VALUE = UINT16_MAX;
SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {},
[&](Response::PadData data) {
constexpr u16 CALIBRATION_THRESHOLD = 100;
if (current_status == Status::Initialized) {
// Receiving data means the communication is ready now
current_status = Status::Ready;
status_callback(current_status);
}
const auto& touchpad_0 = data.touch[0];
if (touchpad_0.is_active == 0) {
return;
}
LOG_DEBUG(Input, "Current touch: {} {}", touchpad_0.x, touchpad_0.y);
const u16 min_x = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.x));
const u16 min_y = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.y));
if (current_status == Status::Ready) {
// First touch - min data (min_x/min_y)
current_status = Status::Stage1Completed;
status_callback(current_status);
}
if (touchpad_0.x - min_x > CALIBRATION_THRESHOLD &&
touchpad_0.y - min_y > CALIBRATION_THRESHOLD) {
// Set the current position as max value and finishes configuration
const u16 max_x = touchpad_0.x;
const u16 max_y = touchpad_0.y;
current_status = Status::Completed;
data_callback(min_x, min_y, max_x, max_y);
status_callback(current_status);
if (current_status == Status::Initialized) {
// Receiving data means the communication is ready now
current_status = Status::Ready;
status_callback(current_status);
}
if (data.touch[0].is_active == 0) {
return;
}
LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x,
data.touch[0].y);
min_x = std::min(min_x, static_cast<u16>(data.touch[0].x));
min_y = std::min(min_y, static_cast<u16>(data.touch[0].y));
if (current_status == Status::Ready) {
// First touch - min data (min_x/min_y)
current_status = Status::Stage1Completed;
status_callback(current_status);
}
if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD &&
data.touch[0].y - min_y > CALIBRATION_THRESHOLD) {
// Set the current position as max value and finishes
// configuration
max_x = data.touch[0].x;
max_y = data.touch[0].y;
current_status = Status::Completed;
data_callback(min_x, min_y, max_x, max_y);
status_callback(current_status);
complete_event.Set();
}
}};
complete_event.Set();
}
}};
Socket socket{host, port, std::move(callback)};
std::thread worker_thread{SocketLoop, &socket};
complete_event.Wait();
+3 -3
View File
@@ -49,10 +49,10 @@ struct DeviceStatus {
* A button device factory representing a keyboard. It receives keyboard events and forward them
* to all button devices it created.
*/
class UDPClient final : public InputCommon::InputEngine {
class UDPClient final : public InputEngine {
public:
explicit UDPClient(const std::string& input_engine_);
~UDPClient();
explicit UDPClient(std::string input_engine_);
~UDPClient() override;
void ReloadSockets();
+44 -31
View File
@@ -19,23 +19,36 @@ public:
: up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
modifier_angle(modifier_angle_) {
Common::Input::InputCallback button_up_callback{
[this](Common::Input::CallbackStatus callback_) { UpdateUpButtonStatus(callback_); }};
Common::Input::InputCallback button_down_callback{
[this](Common::Input::CallbackStatus callback_) { UpdateDownButtonStatus(callback_); }};
Common::Input::InputCallback button_left_callback{
[this](Common::Input::CallbackStatus callback_) { UpdateLeftButtonStatus(callback_); }};
Common::Input::InputCallback button_right_callback{
[this](Common::Input::CallbackStatus callback_) {
UpdateRightButtonStatus(callback_);
}};
Common::Input::InputCallback button_modifier_callback{
[this](Common::Input::CallbackStatus callback_) { UpdateModButtonStatus(callback_); }};
up->SetCallback(button_up_callback);
down->SetCallback(button_down_callback);
left->SetCallback(button_left_callback);
right->SetCallback(button_right_callback);
modifier->SetCallback(button_modifier_callback);
up->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback_) {
UpdateUpButtonStatus(callback_);
},
});
down->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback_) {
UpdateDownButtonStatus(callback_);
},
});
left->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback_) {
UpdateLeftButtonStatus(callback_);
},
});
right->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback_) {
UpdateRightButtonStatus(callback_);
},
});
modifier->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback_) {
UpdateModButtonStatus(callback_);
},
});
last_x_axis_value = 0.0f;
last_y_axis_value = 0.0f;
}
@@ -133,27 +146,27 @@ public:
}
}
void UpdateUpButtonStatus(Common::Input::CallbackStatus button_callback) {
void UpdateUpButtonStatus(const Common::Input::CallbackStatus& button_callback) {
up_status = button_callback.button_status.value;
UpdateStatus();
}
void UpdateDownButtonStatus(Common::Input::CallbackStatus button_callback) {
void UpdateDownButtonStatus(const Common::Input::CallbackStatus& button_callback) {
down_status = button_callback.button_status.value;
UpdateStatus();
}
void UpdateLeftButtonStatus(Common::Input::CallbackStatus button_callback) {
void UpdateLeftButtonStatus(const Common::Input::CallbackStatus& button_callback) {
left_status = button_callback.button_status.value;
UpdateStatus();
}
void UpdateRightButtonStatus(Common::Input::CallbackStatus button_callback) {
void UpdateRightButtonStatus(const Common::Input::CallbackStatus& button_callback) {
right_status = button_callback.button_status.value;
UpdateStatus();
}
void UpdateModButtonStatus(Common::Input::CallbackStatus button_callback) {
void UpdateModButtonStatus(const Common::Input::CallbackStatus& button_callback) {
modifier_status = button_callback.button_status.value;
UpdateStatus();
}
@@ -265,18 +278,18 @@ private:
Button left;
Button right;
Button modifier;
float modifier_scale;
float modifier_angle;
float modifier_scale{};
float modifier_angle{};
float angle{};
float goal_angle{};
float amplitude{};
bool up_status;
bool down_status;
bool left_status;
bool right_status;
bool modifier_status;
float last_x_axis_value;
float last_y_axis_value;
bool up_status{};
bool down_status{};
bool left_status{};
bool right_status{};
bool modifier_status{};
float last_x_axis_value{};
float last_y_axis_value{};
const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
std::chrono::time_point<std::chrono::steady_clock> last_update;
};
@@ -14,10 +14,13 @@ public:
using Button = std::unique_ptr<Common::Input::InputDevice>;
TouchFromButtonDevice(Button button_, int touch_id_, float x_, float y_)
: button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) {
Common::Input::InputCallback button_up_callback{
[this](Common::Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }};
last_button_value = false;
button->SetCallback(button_up_callback);
button->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback_) {
UpdateButtonStatus(callback_);
},
});
button->ForceUpdate();
}
@@ -47,7 +50,7 @@ public:
return status;
}
void UpdateButtonStatus(Common::Input::CallbackStatus button_callback) {
void UpdateButtonStatus(const Common::Input::CallbackStatus& button_callback) {
const Common::Input::CallbackStatus status{
.type = Common::Input::InputType::Touch,
.touch_status = GetStatus(button_callback.button_status.value),
+13 -8
View File
@@ -54,6 +54,18 @@ struct Message {
template <typename T>
constexpr Type GetMessageType();
template <typename T>
Message<T> CreateMessage(const u32 magic, const T data, const u32 sender_id) {
boost::crc_32_type crc;
Header header{
magic, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, sender_id, GetMessageType<T>(),
};
Message<T> message{header, data};
crc.process_bytes(&message, sizeof(Message<T>));
message.header.crc = crc.checksum();
return message;
}
namespace Request {
enum RegisterFlags : u8 {
@@ -101,14 +113,7 @@ static_assert(std::is_trivially_copyable_v<PadData>,
*/
template <typename T>
Message<T> Create(const T data, const u32 client_id = 0) {
boost::crc_32_type crc;
Header header{
CLIENT_MAGIC, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, client_id, GetMessageType<T>(),
};
Message<T> message{header, data};
crc.process_bytes(&message, sizeof(Message<T>));
message.header.crc = crc.checksum();
return message;
return CreateMessage(CLIENT_MAGIC, data, client_id);
}
} // namespace Request
+52 -46
View File
@@ -10,41 +10,31 @@ namespace InputCommon {
void InputEngine::PreSetController(const PadIdentifier& identifier) {
std::lock_guard lock{mutex};
if (!controller_list.contains(identifier)) {
controller_list.insert_or_assign(identifier, ControllerData{});
}
controller_list.try_emplace(identifier);
}
void InputEngine::PreSetButton(const PadIdentifier& identifier, int button) {
std::lock_guard lock{mutex};
ControllerData& controller = controller_list.at(identifier);
if (!controller.buttons.contains(button)) {
controller.buttons.insert_or_assign(button, false);
}
controller.buttons.try_emplace(button, false);
}
void InputEngine::PreSetHatButton(const PadIdentifier& identifier, int button) {
std::lock_guard lock{mutex};
ControllerData& controller = controller_list.at(identifier);
if (!controller.hat_buttons.contains(button)) {
controller.hat_buttons.insert_or_assign(button, u8{0});
}
controller.hat_buttons.try_emplace(button, u8{0});
}
void InputEngine::PreSetAxis(const PadIdentifier& identifier, int axis) {
std::lock_guard lock{mutex};
ControllerData& controller = controller_list.at(identifier);
if (!controller.axes.contains(axis)) {
controller.axes.insert_or_assign(axis, 0.0f);
}
controller.axes.try_emplace(axis, 0.0f);
}
void InputEngine::PreSetMotion(const PadIdentifier& identifier, int motion) {
std::lock_guard lock{mutex};
ControllerData& controller = controller_list.at(identifier);
if (!controller.motions.contains(motion)) {
controller.motions.insert_or_assign(motion, BasicMotion{});
}
controller.motions.try_emplace(motion);
}
void InputEngine::SetButton(const PadIdentifier& identifier, int button, bool value) {
@@ -91,7 +81,7 @@ void InputEngine::SetBattery(const PadIdentifier& identifier, BatteryLevel value
TriggerOnBatteryChange(identifier, value);
}
void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, BasicMotion value) {
void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value) {
{
std::lock_guard lock{mutex};
ControllerData& controller = controller_list.at(identifier);
@@ -104,85 +94,93 @@ void InputEngine::SetMotion(const PadIdentifier& identifier, int motion, BasicMo
bool InputEngine::GetButton(const PadIdentifier& identifier, int button) const {
std::lock_guard lock{mutex};
if (!controller_list.contains(identifier)) {
const auto controller_iter = controller_list.find(identifier);
if (controller_iter == controller_list.cend()) {
LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
identifier.pad, identifier.port);
return false;
}
ControllerData controller = controller_list.at(identifier);
if (!controller.buttons.contains(button)) {
const ControllerData& controller = controller_iter->second;
const auto button_iter = controller.buttons.find(button);
if (button_iter == controller.buttons.cend()) {
LOG_ERROR(Input, "Invalid button {}", button);
return false;
}
return controller.buttons.at(button);
return button_iter->second;
}
bool InputEngine::GetHatButton(const PadIdentifier& identifier, int button, u8 direction) const {
std::lock_guard lock{mutex};
if (!controller_list.contains(identifier)) {
const auto controller_iter = controller_list.find(identifier);
if (controller_iter == controller_list.cend()) {
LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
identifier.pad, identifier.port);
return false;
}
ControllerData controller = controller_list.at(identifier);
if (!controller.hat_buttons.contains(button)) {
const ControllerData& controller = controller_iter->second;
const auto hat_iter = controller.hat_buttons.find(button);
if (hat_iter == controller.hat_buttons.cend()) {
LOG_ERROR(Input, "Invalid hat button {}", button);
return false;
}
return (controller.hat_buttons.at(button) & direction) != 0;
return (hat_iter->second & direction) != 0;
}
f32 InputEngine::GetAxis(const PadIdentifier& identifier, int axis) const {
std::lock_guard lock{mutex};
if (!controller_list.contains(identifier)) {
const auto controller_iter = controller_list.find(identifier);
if (controller_iter == controller_list.cend()) {
LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
identifier.pad, identifier.port);
return 0.0f;
}
ControllerData controller = controller_list.at(identifier);
if (!controller.axes.contains(axis)) {
const ControllerData& controller = controller_iter->second;
const auto axis_iter = controller.axes.find(axis);
if (axis_iter == controller.axes.cend()) {
LOG_ERROR(Input, "Invalid axis {}", axis);
return 0.0f;
}
return controller.axes.at(axis);
return axis_iter->second;
}
BatteryLevel InputEngine::GetBattery(const PadIdentifier& identifier) const {
std::lock_guard lock{mutex};
if (!controller_list.contains(identifier)) {
const auto controller_iter = controller_list.find(identifier);
if (controller_iter == controller_list.cend()) {
LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
identifier.pad, identifier.port);
return BatteryLevel::Charging;
}
ControllerData controller = controller_list.at(identifier);
const ControllerData& controller = controller_iter->second;
return controller.battery;
}
BasicMotion InputEngine::GetMotion(const PadIdentifier& identifier, int motion) const {
std::lock_guard lock{mutex};
if (!controller_list.contains(identifier)) {
const auto controller_iter = controller_list.find(identifier);
if (controller_iter == controller_list.cend()) {
LOG_ERROR(Input, "Invalid identifier guid={}, pad={}, port={}", identifier.guid.Format(),
identifier.pad, identifier.port);
return {};
}
ControllerData controller = controller_list.at(identifier);
const ControllerData& controller = controller_iter->second;
return controller.motions.at(motion);
}
void InputEngine::ResetButtonState() {
for (std::pair<PadIdentifier, ControllerData> controller : controller_list) {
for (std::pair<int, bool> button : controller.second.buttons) {
for (const auto& controller : controller_list) {
for (const auto& button : controller.second.buttons) {
SetButton(controller.first, button.first, false);
}
for (std::pair<int, bool> button : controller.second.hat_buttons) {
for (const auto& button : controller.second.hat_buttons) {
SetHatButton(controller.first, button.first, false);
}
}
}
void InputEngine::ResetAnalogState() {
for (std::pair<PadIdentifier, ControllerData> controller : controller_list) {
for (std::pair<int, float> axis : controller.second.axes) {
for (const auto& controller : controller_list) {
for (const auto& axis : controller.second.axes) {
SetAxis(controller.first, axis.first, 0.0);
}
}
@@ -190,7 +188,7 @@ void InputEngine::ResetAnalogState() {
void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value) {
std::lock_guard lock{mutex_callback};
for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
for (const auto& poller_pair : callback_list) {
const InputIdentifier& poller = poller_pair.second;
if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Button, button)) {
continue;
@@ -218,7 +216,7 @@ void InputEngine::TriggerOnButtonChange(const PadIdentifier& identifier, int but
void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value) {
std::lock_guard lock{mutex_callback};
for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
for (const auto& poller_pair : callback_list) {
const InputIdentifier& poller = poller_pair.second;
if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::HatButton, button)) {
continue;
@@ -247,7 +245,7 @@ void InputEngine::TriggerOnHatButtonChange(const PadIdentifier& identifier, int
void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value) {
std::lock_guard lock{mutex_callback};
for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
for (const auto& poller_pair : callback_list) {
const InputIdentifier& poller = poller_pair.second;
if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Analog, axis)) {
continue;
@@ -274,7 +272,7 @@ void InputEngine::TriggerOnAxisChange(const PadIdentifier& identifier, int axis,
void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier,
[[maybe_unused]] BatteryLevel value) {
std::lock_guard lock{mutex_callback};
for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
for (const auto& poller_pair : callback_list) {
const InputIdentifier& poller = poller_pair.second;
if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Battery, 0)) {
continue;
@@ -286,9 +284,9 @@ void InputEngine::TriggerOnBatteryChange(const PadIdentifier& identifier,
}
void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
BasicMotion value) {
const BasicMotion& value) {
std::lock_guard lock{mutex_callback};
for (const std::pair<int, InputIdentifier> poller_pair : callback_list) {
for (const auto& poller_pair : callback_list) {
const InputIdentifier& poller = poller_pair.second;
if (!IsInputIdentifierEqual(poller, identifier, EngineInputType::Motion, motion)) {
continue;
@@ -300,8 +298,16 @@ void InputEngine::TriggerOnMotionChange(const PadIdentifier& identifier, int mot
if (!configuring || !mapping_callback.on_data) {
return;
}
if (std::abs(value.gyro_x) < 0.6f && std::abs(value.gyro_y) < 0.6f &&
std::abs(value.gyro_z) < 0.6f) {
bool is_active = false;
if (std::abs(value.accel_x) > 1.5f || std::abs(value.accel_y) > 1.5f ||
std::abs(value.accel_z) > 1.5f) {
is_active = true;
}
if (std::abs(value.gyro_x) > 0.6f || std::abs(value.gyro_y) > 0.6f ||
std::abs(value.gyro_z) > 0.6f) {
is_active = true;
}
if (!is_active) {
return;
}
mapping_callback.on_data(MappingData{
@@ -342,7 +348,7 @@ const std::string& InputEngine::GetEngineName() const {
int InputEngine::SetCallback(InputIdentifier input_identifier) {
std::lock_guard lock{mutex_callback};
callback_list.insert_or_assign(last_callback_key, input_identifier);
callback_list.insert_or_assign(last_callback_key, std::move(input_identifier));
return last_callback_key++;
}
+25 -28
View File
@@ -23,15 +23,15 @@ struct PadIdentifier {
friend constexpr bool operator==(const PadIdentifier&, const PadIdentifier&) = default;
};
// Basic motion data containing data from the sensors and a timestamp in microsecons
// Basic motion data containing data from the sensors and a timestamp in microseconds
struct BasicMotion {
float gyro_x;
float gyro_y;
float gyro_z;
float accel_x;
float accel_y;
float accel_z;
u64 delta_timestamp;
float gyro_x{};
float gyro_y{};
float gyro_z{};
float accel_x{};
float accel_y{};
float accel_z{};
u64 delta_timestamp{};
};
// Stages of a battery charge
@@ -102,9 +102,7 @@ struct InputIdentifier {
class InputEngine {
public:
explicit InputEngine(const std::string& input_engine_) : input_engine(input_engine_) {
callback_list.clear();
}
explicit InputEngine(std::string input_engine_) : input_engine{std::move(input_engine_)} {}
virtual ~InputEngine() = default;
@@ -116,14 +114,12 @@ public:
// Sets a led pattern for a controller
virtual void SetLeds([[maybe_unused]] const PadIdentifier& identifier,
[[maybe_unused]] const Common::Input::LedStatus led_status) {
return;
}
[[maybe_unused]] const Common::Input::LedStatus& led_status) {}
// Sets rumble to a controller
virtual Common::Input::VibrationError SetRumble(
[[maybe_unused]] const PadIdentifier& identifier,
[[maybe_unused]] const Common::Input::VibrationStatus vibration) {
[[maybe_unused]] const Common::Input::VibrationStatus& vibration) {
return Common::Input::VibrationError::NotSupported;
}
@@ -140,36 +136,36 @@ public:
/// Used for automapping features
virtual std::vector<Common::ParamPackage> GetInputDevices() const {
return {};
};
}
/// Retrieves the button mappings for the given device
virtual InputCommon::ButtonMapping GetButtonMappingForDevice(
virtual ButtonMapping GetButtonMappingForDevice(
[[maybe_unused]] const Common::ParamPackage& params) {
return {};
};
}
/// Retrieves the analog mappings for the given device
virtual InputCommon::AnalogMapping GetAnalogMappingForDevice(
virtual AnalogMapping GetAnalogMappingForDevice(
[[maybe_unused]] const Common::ParamPackage& params) {
return {};
};
}
/// Retrieves the motion mappings for the given device
virtual InputCommon::MotionMapping GetMotionMappingForDevice(
virtual MotionMapping GetMotionMappingForDevice(
[[maybe_unused]] const Common::ParamPackage& params) {
return {};
};
}
/// Retrieves the name of the given input.
virtual Common::Input::ButtonNames GetUIName(
[[maybe_unused]] const Common::ParamPackage& params) const {
return Common::Input::ButtonNames::Engine;
};
}
/// Retrieves the index number of the given hat button direction
virtual u8 GetHatButtonId([[maybe_unused]] const std::string& direction_name) const {
return 0;
};
}
void PreSetController(const PadIdentifier& identifier);
void PreSetButton(const PadIdentifier& identifier, int button);
@@ -194,7 +190,7 @@ protected:
void SetHatButton(const PadIdentifier& identifier, int button, u8 value);
void SetAxis(const PadIdentifier& identifier, int axis, f32 value);
void SetBattery(const PadIdentifier& identifier, BatteryLevel value);
void SetMotion(const PadIdentifier& identifier, int motion, BasicMotion value);
void SetMotion(const PadIdentifier& identifier, int motion, const BasicMotion& value);
virtual std::string GetHatButtonName([[maybe_unused]] u8 direction_value) const {
return "Unknown";
@@ -206,14 +202,15 @@ private:
std::unordered_map<int, u8> hat_buttons;
std::unordered_map<int, float> axes;
std::unordered_map<int, BasicMotion> motions;
BatteryLevel battery;
BatteryLevel battery{};
};
void TriggerOnButtonChange(const PadIdentifier& identifier, int button, bool value);
void TriggerOnHatButtonChange(const PadIdentifier& identifier, int button, u8 value);
void TriggerOnAxisChange(const PadIdentifier& identifier, int button, f32 value);
void TriggerOnAxisChange(const PadIdentifier& identifier, int axis, f32 value);
void TriggerOnBatteryChange(const PadIdentifier& identifier, BatteryLevel value);
void TriggerOnMotionChange(const PadIdentifier& identifier, int motion, BasicMotion value);
void TriggerOnMotionChange(const PadIdentifier& identifier, int motion,
const BasicMotion& value);
bool IsInputIdentifierEqual(const InputIdentifier& input_identifier,
const PadIdentifier& identifier, EngineInputType type,
+14 -14
View File
@@ -14,8 +14,8 @@ public:
MappingFactory();
/**
* Resets all varables to beggin the mapping process
* @param "type": type of input desired to be returned
* Resets all variables to begin the mapping process
* @param type type of input desired to be returned
*/
void BeginMapping(Polling::InputType type);
@@ -24,8 +24,8 @@ public:
/**
* Registers mapping input data from the driver
* @param "data": An struct containing all the information needed to create a proper
* ParamPackage
* @param data A struct containing all the information needed to create a proper
* ParamPackage
*/
void RegisterInput(const MappingData& data);
@@ -34,42 +34,42 @@ public:
private:
/**
* If provided data satisfies the requeriments it will push an element to the input_queue
* If provided data satisfies the requirements it will push an element to the input_queue
* Supported input:
* - Button: Creates a basic button ParamPackage
* - HatButton: Creates a basic hat button ParamPackage
* - Analog: Creates a basic analog ParamPackage
* @param "data": An struct containing all the information needed to create a proper
* @param data A struct containing all the information needed to create a proper
* ParamPackage
*/
void RegisterButton(const MappingData& data);
/**
* If provided data satisfies the requeriments it will push an element to the input_queue
* If provided data satisfies the requirements it will push an element to the input_queue
* Supported input:
* - Button, HatButton: Pass the data to RegisterButton
* - Analog: Stores the first axis and on the second axis creates a basic stick ParamPackage
* @param "data": An struct containing all the information needed to create a proper
* ParamPackage
* @param data A struct containing all the information needed to create a proper
* ParamPackage
*/
void RegisterStick(const MappingData& data);
/**
* If provided data satisfies the requeriments it will push an element to the input_queue
* If provided data satisfies the requirements it will push an element to the input_queue
* Supported input:
* - Button, HatButton: Pass the data to RegisterButton
* - Analog: Stores the first two axis and on the third axis creates a basic Motion
* ParamPackage
* - Motion: Creates a basic Motion ParamPackage
* @param "data": An struct containing all the information needed to create a proper
* ParamPackage
* @param data A struct containing all the information needed to create a proper
* ParamPackage
*/
void RegisterMotion(const MappingData& data);
/**
* Returns true if driver can be mapped
* @param "data": An struct containing all the information needed to create a proper
* ParamPackage
* @param data A struct containing all the information needed to create a proper
* ParamPackage
*/
bool IsDriverValid(const MappingData& data) const;

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