summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/templates/build-msvc.yml2
-rw-r--r--.ci/yuzu-mainline-step2.yml2
-rw-r--r--.ci/yuzu-patreon-step2.yml2
-rw-r--r--CMakeLists.txt6
m---------externals/libressl0
-rw-r--r--src/core/arm/arm_interface.h3
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h1
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h1
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/core.h3
-rw-r--r--src/core/hid/hid_types.h72
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.cpp20
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.h11
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.h7
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.cpp19
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h29
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp32
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h45
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp19
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h27
-rw-r--r--src/core/hle/service/hid/controllers/mouse.cpp20
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h21
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp290
-rw-r--r--src/core/hle/service/hid/controllers/npad.h32
-rw-r--r--src/core/hle/service/hid/controllers/stubbed.cpp11
-rw-r--r--src/core/hle/service/hid/controllers/stubbed.h13
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp22
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h28
-rw-r--r--src/core/hle/service/hid/controllers/xpad.cpp21
-rw-r--r--src/core/hle/service/hid/controllers/xpad.h26
-rw-r--r--src/core/hle/service/hid/hid.cpp41
-rw-r--r--src/core/hle/service/hid/hid.h9
-rw-r--r--src/core/hle/service/jit/jit.cpp205
-rw-r--r--src/core/hle/service/jit/jit_context.cpp151
-rw-r--r--src/core/hle/service/jit/jit_context.h1
38 files changed, 660 insertions, 546 deletions
diff --git a/.ci/templates/build-msvc.yml b/.ci/templates/build-msvc.yml
index e5f8ea91e..cca3189fa 100644
--- a/.ci/templates/build-msvc.yml
+++ b/.ci/templates/build-msvc.yml
@@ -8,7 +8,7 @@ steps:
8 displayName: 'Install vulkan-sdk' 8 displayName: 'Install vulkan-sdk'
9- script: python -m pip install --upgrade pip conan 9- script: python -m pip install --upgrade pip conan
10 displayName: 'Install conan' 10 displayName: 'Install conan'
11- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release .. && cd .. 11- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release .. && cd ..
12 displayName: 'Configure CMake' 12 displayName: 'Configure CMake'
13- task: MSBuild@1 13- task: MSBuild@1
14 displayName: 'Build' 14 displayName: 'Build'
diff --git a/.ci/yuzu-mainline-step2.yml b/.ci/yuzu-mainline-step2.yml
index 91e21a126..b37eab6cd 100644
--- a/.ci/yuzu-mainline-step2.yml
+++ b/.ci/yuzu-mainline-step2.yml
@@ -47,7 +47,7 @@ stages:
47 timeoutInMinutes: 120 47 timeoutInMinutes: 120
48 displayName: 'msvc' 48 displayName: 'msvc'
49 pool: 49 pool:
50 vmImage: windows-2019 50 vmImage: windows-2022
51 steps: 51 steps:
52 - template: ./templates/sync-source.yml 52 - template: ./templates/sync-source.yml
53 parameters: 53 parameters:
diff --git a/.ci/yuzu-patreon-step2.yml b/.ci/yuzu-patreon-step2.yml
index ad61ac74e..119123a63 100644
--- a/.ci/yuzu-patreon-step2.yml
+++ b/.ci/yuzu-patreon-step2.yml
@@ -12,7 +12,7 @@ stages:
12 timeoutInMinutes: 120 12 timeoutInMinutes: 120
13 displayName: 'windows-msvc' 13 displayName: 'windows-msvc'
14 pool: 14 pool:
15 vmImage: windows-2019 15 vmImage: windows-2022
16 steps: 16 steps:
17 - template: ./templates/sync-source.yml 17 - template: ./templates/sync-source.yml
18 parameters: 18 parameters:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index caeb2ab8e..dcd4011a5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -405,13 +405,11 @@ if (CONAN_REQUIRED_LIBS)
405 # Download conan.cmake automatically, you can also just copy the conan.cmake file 405 # Download conan.cmake automatically, you can also just copy the conan.cmake file
406 if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake") 406 if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
407 message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan") 407 message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
408 # TODO: Use a tagged release. The latest tagged release does not support VS2022 as of this writing. 408 file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/release/0.18/conan.cmake" "${CMAKE_BINARY_DIR}/conan.cmake")
409 file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/43e385830ee35377dbd2dcbe8d5a9e750301ea00/conan.cmake"
410 "${CMAKE_BINARY_DIR}/conan.cmake")
411 endif() 409 endif()
412 include(${CMAKE_BINARY_DIR}/conan.cmake) 410 include(${CMAKE_BINARY_DIR}/conan.cmake)
413 411
414 conan_check(VERSION 1.41.0 REQUIRED) 412 conan_check(VERSION 1.45.0 REQUIRED)
415 413
416 # Manually add iconv to fix a dep conflict between qt and sdl2 414 # Manually add iconv to fix a dep conflict between qt and sdl2
417 # We don't need to add it through find_package or anything since the other two can find it just fine 415 # We don't need to add it through find_package or anything since the other two can find it just fine
diff --git a/externals/libressl b/externals/libressl
Subproject 8289d0d07de6553bf4b900bf60e808ea3f7f59d Subproject 8929f818fd748fd31a34fec7c04558399e13014
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index bcec4b3b8..8ce973a77 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -174,9 +174,6 @@ public:
174 /// Clears the exclusive monitor's state. 174 /// Clears the exclusive monitor's state.
175 virtual void ClearExclusiveState() = 0; 175 virtual void ClearExclusiveState() = 0;
176 176
177 /// Prepare core for thread reschedule (if needed to correctly handle state)
178 virtual void PrepareReschedule() = 0;
179
180 /// Signal an interrupt and ask the core to halt as soon as possible. 177 /// Signal an interrupt and ask the core to halt as soon as possible.
181 virtual void SignalInterrupt() = 0; 178 virtual void SignalInterrupt() = 0;
182 179
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 60e9edff2..781a77f6f 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -327,10 +327,6 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
327 jit.load()->LoadContext(context); 327 jit.load()->LoadContext(context);
328} 328}
329 329
330void ARM_Dynarmic_32::PrepareReschedule() {
331 jit.load()->HaltExecution(break_loop);
332}
333
334void ARM_Dynarmic_32::SignalInterrupt() { 330void ARM_Dynarmic_32::SignalInterrupt() {
335 jit.load()->HaltExecution(break_loop); 331 jit.load()->HaltExecution(break_loop);
336} 332}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index a25c9d277..abfe76644 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -57,7 +57,6 @@ public:
57 void LoadContext(const ThreadContext32& ctx) override; 57 void LoadContext(const ThreadContext32& ctx) override;
58 void LoadContext(const ThreadContext64& ctx) override {} 58 void LoadContext(const ThreadContext64& ctx) override {}
59 59
60 void PrepareReschedule() override;
61 void SignalInterrupt() override; 60 void SignalInterrupt() override;
62 void ClearExclusiveState() override; 61 void ClearExclusiveState() override;
63 62
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index d8d3a38db..1b1334598 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -395,10 +395,6 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
395 SetTPIDR_EL0(ctx.tpidr); 395 SetTPIDR_EL0(ctx.tpidr);
396} 396}
397 397
398void ARM_Dynarmic_64::PrepareReschedule() {
399 jit.load()->HaltExecution(break_loop);
400}
401
402void ARM_Dynarmic_64::SignalInterrupt() { 398void ARM_Dynarmic_64::SignalInterrupt() {
403 jit.load()->HaltExecution(break_loop); 399 jit.load()->HaltExecution(break_loop);
404} 400}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 9680c7b99..01a7e4dad 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -51,7 +51,6 @@ public:
51 void LoadContext(const ThreadContext32& ctx) override {} 51 void LoadContext(const ThreadContext32& ctx) override {}
52 void LoadContext(const ThreadContext64& ctx) override; 52 void LoadContext(const ThreadContext64& ctx) override;
53 53
54 void PrepareReschedule() override;
55 void SignalInterrupt() override; 54 void SignalInterrupt() override;
56 void ClearExclusiveState() override; 55 void ClearExclusiveState() override;
57 56
diff --git a/src/core/core.cpp b/src/core/core.cpp
index b5e2bcae2..8a887904d 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -505,10 +505,6 @@ bool System::IsPoweredOn() const {
505 return impl->is_powered_on.load(std::memory_order::relaxed); 505 return impl->is_powered_on.load(std::memory_order::relaxed);
506} 506}
507 507
508void System::PrepareReschedule() {
509 // Deprecated, does nothing, kept for backward compatibility.
510}
511
512void System::PrepareReschedule(const u32 core_index) { 508void System::PrepareReschedule(const u32 core_index) {
513 impl->kernel.PrepareReschedule(core_index); 509 impl->kernel.PrepareReschedule(core_index);
514} 510}
diff --git a/src/core/core.h b/src/core/core.h
index 52ff90359..4a0c7dc84 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -194,9 +194,6 @@ public:
194 [[nodiscard]] const Core::TelemetrySession& TelemetrySession() const; 194 [[nodiscard]] const Core::TelemetrySession& TelemetrySession() const;
195 195
196 /// Prepare the core emulation for a reschedule 196 /// Prepare the core emulation for a reschedule
197 void PrepareReschedule();
198
199 /// Prepare the core emulation for a reschedule
200 void PrepareReschedule(u32 core_index); 197 void PrepareReschedule(u32 core_index);
201 198
202 /// Gets and resets core performance statistics 199 /// Gets and resets core performance statistics
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index df2b1dfc5..26ec1091b 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -316,27 +316,27 @@ static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"
316 316
317// This is nn::hid::TouchState 317// This is nn::hid::TouchState
318struct TouchState { 318struct TouchState {
319 u64 delta_time; 319 u64 delta_time{};
320 TouchAttribute attribute; 320 TouchAttribute attribute{};
321 u32 finger; 321 u32 finger{};
322 Common::Point<u32> position; 322 Common::Point<u32> position{};
323 u32 diameter_x; 323 u32 diameter_x{};
324 u32 diameter_y; 324 u32 diameter_y{};
325 u32 rotation_angle; 325 u32 rotation_angle{};
326}; 326};
327static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); 327static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
328 328
329// This is nn::hid::NpadControllerColor 329// This is nn::hid::NpadControllerColor
330struct NpadControllerColor { 330struct NpadControllerColor {
331 u32 body; 331 u32 body{};
332 u32 button; 332 u32 button{};
333}; 333};
334static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size"); 334static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size");
335 335
336// This is nn::hid::AnalogStickState 336// This is nn::hid::AnalogStickState
337struct AnalogStickState { 337struct AnalogStickState {
338 s32 x; 338 s32 x{};
339 s32 y; 339 s32 y{};
340}; 340};
341static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size"); 341static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size");
342 342
@@ -354,10 +354,10 @@ static_assert(sizeof(NpadBatteryLevel) == 0x4, "NpadBatteryLevel is an invalid s
354 354
355// This is nn::hid::system::NpadPowerInfo 355// This is nn::hid::system::NpadPowerInfo
356struct NpadPowerInfo { 356struct NpadPowerInfo {
357 bool is_powered; 357 bool is_powered{};
358 bool is_charging; 358 bool is_charging{};
359 INSERT_PADDING_BYTES(0x6); 359 INSERT_PADDING_BYTES(0x6);
360 NpadBatteryLevel battery_level; 360 NpadBatteryLevel battery_level{8};
361}; 361};
362static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); 362static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
363 363
@@ -474,8 +474,8 @@ static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"
474 474
475// This is nn::hid::ConsoleSixAxisSensorHandle 475// This is nn::hid::ConsoleSixAxisSensorHandle
476struct ConsoleSixAxisSensorHandle { 476struct ConsoleSixAxisSensorHandle {
477 u8 unknown_1; 477 u8 unknown_1{};
478 u8 unknown_2; 478 u8 unknown_2{};
479 INSERT_PADDING_BYTES_NOINIT(2); 479 INSERT_PADDING_BYTES_NOINIT(2);
480}; 480};
481static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4, 481static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4,
@@ -483,9 +483,9 @@ static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4,
483 483
484// This is nn::hid::SixAxisSensorHandle 484// This is nn::hid::SixAxisSensorHandle
485struct SixAxisSensorHandle { 485struct SixAxisSensorHandle {
486 NpadStyleIndex npad_type; 486 NpadStyleIndex npad_type{NpadStyleIndex::None};
487 u8 npad_id; 487 u8 npad_id{};
488 DeviceIndex device_index; 488 DeviceIndex device_index{DeviceIndex::None};
489 INSERT_PADDING_BYTES_NOINIT(1); 489 INSERT_PADDING_BYTES_NOINIT(1);
490}; 490};
491static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size"); 491static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size");
@@ -500,19 +500,19 @@ static_assert(sizeof(SixAxisSensorFusionParameters) == 8,
500 500
501// This is nn::hid::VibrationDeviceHandle 501// This is nn::hid::VibrationDeviceHandle
502struct VibrationDeviceHandle { 502struct VibrationDeviceHandle {
503 NpadStyleIndex npad_type; 503 NpadStyleIndex npad_type{NpadStyleIndex::None};
504 u8 npad_id; 504 u8 npad_id{};
505 DeviceIndex device_index; 505 DeviceIndex device_index{DeviceIndex::None};
506 INSERT_PADDING_BYTES_NOINIT(1); 506 INSERT_PADDING_BYTES_NOINIT(1);
507}; 507};
508static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size"); 508static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size");
509 509
510// This is nn::hid::VibrationValue 510// This is nn::hid::VibrationValue
511struct VibrationValue { 511struct VibrationValue {
512 f32 low_amplitude; 512 f32 low_amplitude{};
513 f32 low_frequency; 513 f32 low_frequency{};
514 f32 high_amplitude; 514 f32 high_amplitude{};
515 f32 high_frequency; 515 f32 high_frequency{};
516}; 516};
517static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); 517static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size.");
518 518
@@ -561,7 +561,7 @@ static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid
561// This is nn::hid::KeyboardKey 561// This is nn::hid::KeyboardKey
562struct KeyboardKey { 562struct KeyboardKey {
563 // This should be a 256 bit flag 563 // This should be a 256 bit flag
564 std::array<u8, 32> key; 564 std::array<u8, 32> key{};
565}; 565};
566static_assert(sizeof(KeyboardKey) == 0x20, "KeyboardKey is an invalid size"); 566static_assert(sizeof(KeyboardKey) == 0x20, "KeyboardKey is an invalid size");
567 567
@@ -590,16 +590,16 @@ static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size"
590 590
591// This is nn::hid::detail::MouseState 591// This is nn::hid::detail::MouseState
592struct MouseState { 592struct MouseState {
593 s64 sampling_number; 593 s64 sampling_number{};
594 s32 x; 594 s32 x{};
595 s32 y; 595 s32 y{};
596 s32 delta_x; 596 s32 delta_x{};
597 s32 delta_y; 597 s32 delta_y{};
598 // Axis Order in HW is switched for the wheel 598 // Axis Order in HW is switched for the wheel
599 s32 delta_wheel_y; 599 s32 delta_wheel_y{};
600 s32 delta_wheel_x; 600 s32 delta_wheel_x{};
601 MouseButton button; 601 MouseButton button{};
602 MouseAttribute attribute; 602 MouseAttribute attribute{};
603}; 603};
604static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); 604static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size");
605 605
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index f9c72d160..66e0ce2d0 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -899,7 +899,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
899 899
900 // Verify the requested core is valid. 900 // Verify the requested core is valid.
901 const bool core_valid = 901 const bool core_valid =
902 (info_sub_id == static_cast<u64>(-1ULL)) || 902 (info_sub_id == 0xFFFFFFFFFFFFFFFF) ||
903 (info_sub_id == static_cast<u64>(system.Kernel().CurrentPhysicalCoreIndex())); 903 (info_sub_id == static_cast<u64>(system.Kernel().CurrentPhysicalCoreIndex()));
904 R_UNLESS(core_valid, ResultInvalidCombination); 904 R_UNLESS(core_valid, ResultInvalidCombination);
905 905
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index f5a0b94dd..bb3cba910 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -9,9 +9,14 @@
9namespace Service::HID { 9namespace Service::HID {
10constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; 10constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200;
11 11
12Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_) 12Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_,
13 u8* raw_shared_memory_)
13 : ControllerBase{hid_core_} { 14 : ControllerBase{hid_core_} {
14 console = hid_core.GetEmulatedConsole(); 15 console = hid_core.GetEmulatedConsole();
16 static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size,
17 "ConsoleSharedMemory is bigger than the shared memory");
18 shared_memory = std::construct_at(
19 reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
15} 20}
16 21
17Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default; 22Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default;
@@ -20,8 +25,7 @@ void Controller_ConsoleSixAxis::OnInit() {}
20 25
21void Controller_ConsoleSixAxis::OnRelease() {} 26void Controller_ConsoleSixAxis::OnRelease() {}
22 27
23void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 28void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
24 std::size_t size) {
25 if (!IsControllerActivated() || !is_transfer_memory_set) { 29 if (!IsControllerActivated() || !is_transfer_memory_set) {
26 seven_sixaxis_lifo.buffer_count = 0; 30 seven_sixaxis_lifo.buffer_count = 0;
27 seven_sixaxis_lifo.buffer_tail = 0; 31 seven_sixaxis_lifo.buffer_tail = 0;
@@ -48,13 +52,11 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
48 -motion_status.quaternion.xyz.z, 52 -motion_status.quaternion.xyz.z,
49 }; 53 };
50 54
51 console_six_axis.sampling_number++; 55 shared_memory->sampling_number++;
52 console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; 56 shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
53 console_six_axis.verticalization_error = motion_status.verticalization_error; 57 shared_memory->verticalization_error = motion_status.verticalization_error;
54 console_six_axis.gyro_bias = motion_status.gyro_bias; 58 shared_memory->gyro_bias = motion_status.gyro_bias;
55 59
56 // Update console six axis shared memory
57 std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis));
58 // Update seven six axis transfer memory 60 // Update seven six axis transfer memory
59 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); 61 seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);
60 std::memcpy(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo)); 62 std::memcpy(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo));
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index 6da5e9454..2fd11538f 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -17,7 +17,7 @@ class EmulatedConsole;
17namespace Service::HID { 17namespace Service::HID {
18class Controller_ConsoleSixAxis final : public ControllerBase { 18class Controller_ConsoleSixAxis final : public ControllerBase {
19public: 19public:
20 explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_); 20 explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
21 ~Controller_ConsoleSixAxis() override; 21 ~Controller_ConsoleSixAxis() override;
22 22
23 // Called when the controller is initialized 23 // Called when the controller is initialized
@@ -27,7 +27,7 @@ public:
27 void OnRelease() override; 27 void OnRelease() override;
28 28
29 // When the controller is requesting an update for the shared memory 29 // When the controller is requesting an update for the shared memory
30 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; 30 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
31 31
32 // Called on InitializeSevenSixAxisSensor 32 // Called on InitializeSevenSixAxisSensor
33 void SetTransferMemoryPointer(u8* t_mem); 33 void SetTransferMemoryPointer(u8* t_mem);
@@ -61,12 +61,13 @@ private:
61 Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{}; 61 Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};
62 static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); 62 static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size");
63 63
64 Core::HID::EmulatedConsole* console; 64 SevenSixAxisState next_seven_sixaxis_state{};
65 u8* transfer_memory = nullptr; 65 u8* transfer_memory = nullptr;
66 ConsoleSharedMemory* shared_memory = nullptr;
67 Core::HID::EmulatedConsole* console = nullptr;
68
66 bool is_transfer_memory_set = false; 69 bool is_transfer_memory_set = false;
67 u64 last_saved_timestamp{}; 70 u64 last_saved_timestamp{};
68 u64 last_global_timestamp{}; 71 u64 last_global_timestamp{};
69 ConsoleSharedMemory console_six_axis{};
70 SevenSixAxisState next_seven_sixaxis_state{};
71}; 72};
72} // namespace Service::HID 73} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h
index bb01ea643..d6f7a5073 100644
--- a/src/core/hle/service/hid/controllers/controller_base.h
+++ b/src/core/hle/service/hid/controllers/controller_base.h
@@ -26,12 +26,10 @@ public:
26 virtual void OnRelease() = 0; 26 virtual void OnRelease() = 0;
27 27
28 // When the controller is requesting an update for the shared memory 28 // When the controller is requesting an update for the shared memory
29 virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 29 virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing) = 0;
30 std::size_t size) = 0;
31 30
32 // When the controller is requesting a motion update for the shared memory 31 // When the controller is requesting a motion update for the shared memory
33 virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 32 virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {}
34 std::size_t size) {}
35 33
36 void ActivateController(); 34 void ActivateController();
37 35
@@ -40,6 +38,7 @@ public:
40 bool IsControllerActivated() const; 38 bool IsControllerActivated() const;
41 39
42 static const std::size_t hid_entry_count = 17; 40 static const std::size_t hid_entry_count = 17;
41 static const std::size_t shared_memory_size = 0x40000;
43 42
44protected: 43protected:
45 bool is_activated{false}; 44 bool is_activated{false};
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index 73309d64e..8ec9f4a95 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -13,8 +13,12 @@
13namespace Service::HID { 13namespace Service::HID {
14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; 14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000;
15 15
16Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_) 16Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
17 : ControllerBase{hid_core_} { 17 : ControllerBase{hid_core_} {
18 static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size,
19 "DebugPadSharedMemory is bigger than the shared memory");
20 shared_memory = std::construct_at(
21 reinterpret_cast<DebugPadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
18 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other); 22 controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);
19} 23}
20 24
@@ -24,16 +28,14 @@ void Controller_DebugPad::OnInit() {}
24 28
25void Controller_DebugPad::OnRelease() {} 29void Controller_DebugPad::OnRelease() {}
26 30
27void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 31void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
28 std::size_t size) {
29 if (!IsControllerActivated()) { 32 if (!IsControllerActivated()) {
30 debug_pad_lifo.buffer_count = 0; 33 shared_memory->debug_pad_lifo.buffer_count = 0;
31 debug_pad_lifo.buffer_tail = 0; 34 shared_memory->debug_pad_lifo.buffer_tail = 0;
32 std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo));
33 return; 35 return;
34 } 36 }
35 37
36 const auto& last_entry = debug_pad_lifo.ReadCurrentEntry().state; 38 const auto& last_entry = shared_memory->debug_pad_lifo.ReadCurrentEntry().state;
37 next_state.sampling_number = last_entry.sampling_number + 1; 39 next_state.sampling_number = last_entry.sampling_number + 1;
38 40
39 if (Settings::values.debug_pad_enabled) { 41 if (Settings::values.debug_pad_enabled) {
@@ -47,8 +49,7 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing,
47 next_state.r_stick = stick_state.right; 49 next_state.r_stick = stick_state.right;
48 } 50 }
49 51
50 debug_pad_lifo.WriteNextEntry(next_state); 52 shared_memory->debug_pad_lifo.WriteNextEntry(next_state);
51 std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo));
52} 53}
53 54
54} // namespace Service::HID 55} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 388d25b3c..68ff0ea79 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -17,7 +17,7 @@ struct AnalogStickState;
17namespace Service::HID { 17namespace Service::HID {
18class Controller_DebugPad final : public ControllerBase { 18class Controller_DebugPad final : public ControllerBase {
19public: 19public:
20 explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_); 20 explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
21 ~Controller_DebugPad() override; 21 ~Controller_DebugPad() override;
22 22
23 // Called when the controller is initialized 23 // Called when the controller is initialized
@@ -27,7 +27,7 @@ public:
27 void OnRelease() override; 27 void OnRelease() override;
28 28
29 // When the controller is requesting an update for the shared memory 29 // When the controller is requesting an update for the shared memory
30 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 30 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
31 31
32private: 32private:
33 // This is nn::hid::DebugPadAttribute 33 // This is nn::hid::DebugPadAttribute
@@ -41,19 +41,24 @@ private:
41 41
42 // This is nn::hid::DebugPadState 42 // This is nn::hid::DebugPadState
43 struct DebugPadState { 43 struct DebugPadState {
44 s64 sampling_number; 44 s64 sampling_number{};
45 DebugPadAttribute attribute; 45 DebugPadAttribute attribute{};
46 Core::HID::DebugPadButton pad_state; 46 Core::HID::DebugPadButton pad_state{};
47 Core::HID::AnalogStickState r_stick; 47 Core::HID::AnalogStickState r_stick{};
48 Core::HID::AnalogStickState l_stick; 48 Core::HID::AnalogStickState l_stick{};
49 }; 49 };
50 static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); 50 static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state");
51 51
52 // This is nn::hid::detail::DebugPadLifo 52 struct DebugPadSharedMemory {
53 Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{}; 53 // This is nn::hid::detail::DebugPadLifo
54 static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); 54 Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{};
55 DebugPadState next_state{}; 55 static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size");
56 INSERT_PADDING_WORDS(0x4E);
57 };
58 static_assert(sizeof(DebugPadSharedMemory) == 0x400, "DebugPadSharedMemory is an invalid size");
56 59
57 Core::HID::EmulatedController* controller; 60 DebugPadState next_state{};
61 DebugPadSharedMemory* shared_memory = nullptr;
62 Core::HID::EmulatedController* controller = nullptr;
58}; 63};
59} // namespace Service::HID 64} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index c8dd131dd..3eae1ae35 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -23,25 +23,28 @@ constexpr f32 Square(s32 num) {
23 return static_cast<f32>(num * num); 23 return static_cast<f32>(num * num);
24} 24}
25 25
26Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) { 26Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
27 : ControllerBase(hid_core_) {
28 static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size,
29 "GestureSharedMemory is bigger than the shared memory");
30 shared_memory = std::construct_at(
31 reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
27 console = hid_core.GetEmulatedConsole(); 32 console = hid_core.GetEmulatedConsole();
28} 33}
29Controller_Gesture::~Controller_Gesture() = default; 34Controller_Gesture::~Controller_Gesture() = default;
30 35
31void Controller_Gesture::OnInit() { 36void Controller_Gesture::OnInit() {
32 gesture_lifo.buffer_count = 0; 37 shared_memory->gesture_lifo.buffer_count = 0;
33 gesture_lifo.buffer_tail = 0; 38 shared_memory->gesture_lifo.buffer_tail = 0;
34 force_update = true; 39 force_update = true;
35} 40}
36 41
37void Controller_Gesture::OnRelease() {} 42void Controller_Gesture::OnRelease() {}
38 43
39void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 44void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
40 std::size_t size) {
41 if (!IsControllerActivated()) { 45 if (!IsControllerActivated()) {
42 gesture_lifo.buffer_count = 0; 46 shared_memory->gesture_lifo.buffer_count = 0;
43 gesture_lifo.buffer_tail = 0; 47 shared_memory->gesture_lifo.buffer_tail = 0;
44 std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
45 return; 48 return;
46 } 49 }
47 50
@@ -49,15 +52,15 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
49 52
50 GestureProperties gesture = GetGestureProperties(); 53 GestureProperties gesture = GetGestureProperties();
51 f32 time_difference = 54 f32 time_difference =
52 static_cast<f32>(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000); 55 static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) /
56 (1000 * 1000 * 1000);
53 57
54 // Only update if necesary 58 // Only update if necesary
55 if (!ShouldUpdateGesture(gesture, time_difference)) { 59 if (!ShouldUpdateGesture(gesture, time_difference)) {
56 return; 60 return;
57 } 61 }
58 62
59 last_update_timestamp = gesture_lifo.timestamp; 63 last_update_timestamp = shared_memory->gesture_lifo.timestamp;
60 UpdateGestureSharedMemory(data, size, gesture, time_difference);
61} 64}
62 65
63void Controller_Gesture::ReadTouchInput() { 66void Controller_Gesture::ReadTouchInput() {
@@ -97,7 +100,7 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
97 GestureType type = GestureType::Idle; 100 GestureType type = GestureType::Idle;
98 GestureAttribute attributes{}; 101 GestureAttribute attributes{};
99 102
100 const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; 103 const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state;
101 104
102 // Reset next state to default 105 // Reset next state to default
103 next_state.sampling_number = last_entry.sampling_number + 1; 106 next_state.sampling_number = last_entry.sampling_number + 1;
@@ -127,8 +130,7 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
127 next_state.points = gesture.points; 130 next_state.points = gesture.points;
128 last_gesture = gesture; 131 last_gesture = gesture;
129 132
130 gesture_lifo.WriteNextEntry(next_state); 133 shared_memory->gesture_lifo.WriteNextEntry(next_state);
131 std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo));
132} 134}
133 135
134void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type, 136void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type,
@@ -305,7 +307,7 @@ void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
305} 307}
306 308
307const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { 309const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const {
308 return gesture_lifo.ReadCurrentEntry().state; 310 return shared_memory->gesture_lifo.ReadCurrentEntry().state;
309} 311}
310 312
311Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { 313Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 7a9d28dc6..c62a341bf 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -14,7 +14,7 @@
14namespace Service::HID { 14namespace Service::HID {
15class Controller_Gesture final : public ControllerBase { 15class Controller_Gesture final : public ControllerBase {
16public: 16public:
17 explicit Controller_Gesture(Core::HID::HIDCore& hid_core_); 17 explicit Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
18 ~Controller_Gesture() override; 18 ~Controller_Gesture() override;
19 19
20 // Called when the controller is initialized 20 // Called when the controller is initialized
@@ -24,7 +24,7 @@ public:
24 void OnRelease() override; 24 void OnRelease() override;
25 25
26 // When the controller is requesting an update for the shared memory 26 // When the controller is requesting an update for the shared memory
27 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; 27 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
28 28
29private: 29private:
30 static constexpr size_t MAX_FINGERS = 16; 30 static constexpr size_t MAX_FINGERS = 16;
@@ -66,19 +66,19 @@ private:
66 66
67 // This is nn::hid::GestureState 67 // This is nn::hid::GestureState
68 struct GestureState { 68 struct GestureState {
69 s64 sampling_number; 69 s64 sampling_number{};
70 s64 detection_count; 70 s64 detection_count{};
71 GestureType type; 71 GestureType type{GestureType::Idle};
72 GestureDirection direction; 72 GestureDirection direction{GestureDirection::None};
73 Common::Point<s32> pos; 73 Common::Point<s32> pos{};
74 Common::Point<s32> delta; 74 Common::Point<s32> delta{};
75 f32 vel_x; 75 f32 vel_x{};
76 f32 vel_y; 76 f32 vel_y{};
77 GestureAttribute attributes; 77 GestureAttribute attributes{};
78 f32 scale; 78 f32 scale{};
79 f32 rotation_angle; 79 f32 rotation_angle{};
80 s32 point_count; 80 s32 point_count{};
81 std::array<Common::Point<s32>, 4> points; 81 std::array<Common::Point<s32>, 4> points{};
82 }; 82 };
83 static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); 83 static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size");
84 84
@@ -92,6 +92,14 @@ private:
92 f32 angle{}; 92 f32 angle{};
93 }; 93 };
94 94
95 struct GestureSharedMemory {
96 // This is nn::hid::detail::GestureLifo
97 Lifo<GestureState, hid_entry_count> gesture_lifo{};
98 static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
99 INSERT_PADDING_WORDS(0x3E);
100 };
101 static_assert(sizeof(GestureSharedMemory) == 0x800, "GestureSharedMemory is an invalid size");
102
95 // Reads input from all available input engines 103 // Reads input from all available input engines
96 void ReadTouchInput(); 104 void ReadTouchInput();
97 105
@@ -134,12 +142,9 @@ private:
134 // Returns the average distance, angle and middle point of the active fingers 142 // Returns the average distance, angle and middle point of the active fingers
135 GestureProperties GetGestureProperties(); 143 GestureProperties GetGestureProperties();
136 144
137 // This is nn::hid::detail::GestureLifo
138 Lifo<GestureState, hid_entry_count> gesture_lifo{};
139 static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");
140 GestureState next_state{}; 145 GestureState next_state{};
141 146 GestureSharedMemory* shared_memory = nullptr;
142 Core::HID::EmulatedConsole* console; 147 Core::HID::EmulatedConsole* console = nullptr;
143 148
144 std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{}; 149 std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};
145 GestureProperties last_gesture{}; 150 GestureProperties last_gesture{};
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index 8dc67757b..117d87433 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -12,8 +12,12 @@
12namespace Service::HID { 12namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; 13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
14 14
15Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_) 15Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
16 : ControllerBase{hid_core_} { 16 : ControllerBase{hid_core_} {
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size,
18 "KeyboardSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at(
20 reinterpret_cast<KeyboardSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
17 emulated_devices = hid_core.GetEmulatedDevices(); 21 emulated_devices = hid_core.GetEmulatedDevices();
18} 22}
19 23
@@ -23,16 +27,14 @@ void Controller_Keyboard::OnInit() {}
23 27
24void Controller_Keyboard::OnRelease() {} 28void Controller_Keyboard::OnRelease() {}
25 29
26void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 30void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
27 std::size_t size) {
28 if (!IsControllerActivated()) { 31 if (!IsControllerActivated()) {
29 keyboard_lifo.buffer_count = 0; 32 shared_memory->keyboard_lifo.buffer_count = 0;
30 keyboard_lifo.buffer_tail = 0; 33 shared_memory->keyboard_lifo.buffer_tail = 0;
31 std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
32 return; 34 return;
33 } 35 }
34 36
35 const auto& last_entry = keyboard_lifo.ReadCurrentEntry().state; 37 const auto& last_entry = shared_memory->keyboard_lifo.ReadCurrentEntry().state;
36 next_state.sampling_number = last_entry.sampling_number + 1; 38 next_state.sampling_number = last_entry.sampling_number + 1;
37 39
38 if (Settings::values.keyboard_enabled) { 40 if (Settings::values.keyboard_enabled) {
@@ -44,8 +46,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,
44 next_state.attribute.is_connected.Assign(1); 46 next_state.attribute.is_connected.Assign(1);
45 } 47 }
46 48
47 keyboard_lifo.WriteNextEntry(next_state); 49 shared_memory->keyboard_lifo.WriteNextEntry(next_state);
48 std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo));
49} 50}
50 51
51} // namespace Service::HID 52} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index 39c6085f1..7532f53c6 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -16,7 +16,7 @@ struct KeyboardKey;
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Keyboard final : public ControllerBase { 17class Controller_Keyboard final : public ControllerBase {
18public: 18public:
19 explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_); 19 explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
20 ~Controller_Keyboard() override; 20 ~Controller_Keyboard() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
@@ -26,23 +26,28 @@ public:
26 void OnRelease() override; 26 void OnRelease() override;
27 27
28 // When the controller is requesting an update for the shared memory 28 // When the controller is requesting an update for the shared memory
29 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 29 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
30 30
31private: 31private:
32 // This is nn::hid::detail::KeyboardState 32 // This is nn::hid::detail::KeyboardState
33 struct KeyboardState { 33 struct KeyboardState {
34 s64 sampling_number; 34 s64 sampling_number{};
35 Core::HID::KeyboardModifier modifier; 35 Core::HID::KeyboardModifier modifier{};
36 Core::HID::KeyboardAttribute attribute; 36 Core::HID::KeyboardAttribute attribute{};
37 Core::HID::KeyboardKey key; 37 Core::HID::KeyboardKey key{};
38 }; 38 };
39 static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); 39 static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size");
40 40
41 // This is nn::hid::detail::KeyboardLifo 41 struct KeyboardSharedMemory {
42 Lifo<KeyboardState, hid_entry_count> keyboard_lifo{}; 42 // This is nn::hid::detail::KeyboardLifo
43 static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); 43 Lifo<KeyboardState, hid_entry_count> keyboard_lifo{};
44 KeyboardState next_state{}; 44 static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size");
45 INSERT_PADDING_WORDS(0xA);
46 };
47 static_assert(sizeof(KeyboardSharedMemory) == 0x400, "KeyboardSharedMemory is an invalid size");
45 48
46 Core::HID::EmulatedDevices* emulated_devices; 49 KeyboardState next_state{};
50 KeyboardSharedMemory* shared_memory = nullptr;
51 Core::HID::EmulatedDevices* emulated_devices = nullptr;
47}; 52};
48} // namespace Service::HID 53} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp
index a0292f586..b11cb438d 100644
--- a/src/core/hle/service/hid/controllers/mouse.cpp
+++ b/src/core/hle/service/hid/controllers/mouse.cpp
@@ -12,7 +12,12 @@
12namespace Service::HID { 12namespace Service::HID {
13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; 13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400;
14 14
15Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { 15Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
16 : ControllerBase{hid_core_} {
17 static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size,
18 "MouseSharedMemory is bigger than the shared memory");
19 shared_memory = std::construct_at(
20 reinterpret_cast<MouseSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
16 emulated_devices = hid_core.GetEmulatedDevices(); 21 emulated_devices = hid_core.GetEmulatedDevices();
17} 22}
18 23
@@ -21,16 +26,14 @@ Controller_Mouse::~Controller_Mouse() = default;
21void Controller_Mouse::OnInit() {} 26void Controller_Mouse::OnInit() {}
22void Controller_Mouse::OnRelease() {} 27void Controller_Mouse::OnRelease() {}
23 28
24void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 29void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
25 std::size_t size) {
26 if (!IsControllerActivated()) { 30 if (!IsControllerActivated()) {
27 mouse_lifo.buffer_count = 0; 31 shared_memory->mouse_lifo.buffer_count = 0;
28 mouse_lifo.buffer_tail = 0; 32 shared_memory->mouse_lifo.buffer_tail = 0;
29 std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
30 return; 33 return;
31 } 34 }
32 35
33 const auto& last_entry = mouse_lifo.ReadCurrentEntry().state; 36 const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state;
34 next_state.sampling_number = last_entry.sampling_number + 1; 37 next_state.sampling_number = last_entry.sampling_number + 1;
35 38
36 next_state.attribute.raw = 0; 39 next_state.attribute.raw = 0;
@@ -50,8 +53,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
50 next_state.button = mouse_button_state; 53 next_state.button = mouse_button_state;
51 } 54 }
52 55
53 mouse_lifo.WriteNextEntry(next_state); 56 shared_memory->mouse_lifo.WriteNextEntry(next_state);
54 std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo));
55} 57}
56 58
57} // namespace Service::HID 59} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 62acdfb77..733d00577 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -16,7 +16,7 @@ struct AnalogStickState;
16namespace Service::HID { 16namespace Service::HID {
17class Controller_Mouse final : public ControllerBase { 17class Controller_Mouse final : public ControllerBase {
18public: 18public:
19 explicit Controller_Mouse(Core::HID::HIDCore& hid_core_); 19 explicit Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
20 ~Controller_Mouse() override; 20 ~Controller_Mouse() override;
21 21
22 // Called when the controller is initialized 22 // Called when the controller is initialized
@@ -26,15 +26,20 @@ public:
26 void OnRelease() override; 26 void OnRelease() override;
27 27
28 // When the controller is requesting an update for the shared memory 28 // When the controller is requesting an update for the shared memory
29 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 29 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
30 30
31private: 31private:
32 // This is nn::hid::detail::MouseLifo 32 struct MouseSharedMemory {
33 Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{}; 33 // This is nn::hid::detail::MouseLifo
34 static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); 34 Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{};
35 Core::HID::MouseState next_state{}; 35 static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size");
36 INSERT_PADDING_WORDS(0x2C);
37 };
38 static_assert(sizeof(MouseSharedMemory) == 0x400, "MouseSharedMemory is an invalid size");
36 39
37 Core::HID::AnalogStickState last_mouse_wheel_state; 40 Core::HID::MouseState next_state{};
38 Core::HID::EmulatedDevices* emulated_devices; 41 Core::HID::AnalogStickState last_mouse_wheel_state{};
42 MouseSharedMemory* shared_memory = nullptr;
43 Core::HID::EmulatedDevices* emulated_devices = nullptr;
39}; 44};
40} // namespace Service::HID 45} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 16e973b25..17f71beaf 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -61,11 +61,14 @@ bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle&
61 return npad_id && npad_type && device_index; 61 return npad_id && npad_type && device_index;
62} 62}
63 63
64Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, 64Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
65 KernelHelpers::ServiceContext& service_context_) 65 KernelHelpers::ServiceContext& service_context_)
66 : ControllerBase{hid_core_}, service_context{service_context_} { 66 : ControllerBase{hid_core_}, service_context{service_context_} {
67 static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
67 for (std::size_t i = 0; i < controller_data.size(); ++i) { 68 for (std::size_t i = 0; i < controller_data.size(); ++i) {
68 auto& controller = controller_data[i]; 69 auto& controller = controller_data[i];
70 controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>(
71 raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState))));
69 controller.device = hid_core.GetEmulatedControllerByIndex(i); 72 controller.device = hid_core.GetEmulatedControllerByIndex(i);
70 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = 73 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
71 Core::HID::DEFAULT_VIBRATION_VALUE; 74 Core::HID::DEFAULT_VIBRATION_VALUE;
@@ -115,11 +118,11 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
115 if (!controller.device->IsConnected()) { 118 if (!controller.device->IsConnected()) {
116 return; 119 return;
117 } 120 }
118 auto& shared_memory = controller.shared_memory_entry; 121 auto* shared_memory = controller.shared_memory;
119 const auto& battery_level = controller.device->GetBattery(); 122 const auto& battery_level = controller.device->GetBattery();
120 shared_memory.battery_level_dual = battery_level.dual.battery_level; 123 shared_memory->battery_level_dual = battery_level.dual.battery_level;
121 shared_memory.battery_level_left = battery_level.left.battery_level; 124 shared_memory->battery_level_left = battery_level.left.battery_level;
122 shared_memory.battery_level_right = battery_level.right.battery_level; 125 shared_memory->battery_level_right = battery_level.right.battery_level;
123 break; 126 break;
124 } 127 }
125 default: 128 default:
@@ -134,99 +137,100 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
134 } 137 }
135 LOG_DEBUG(Service_HID, "Npad connected {}", npad_id); 138 LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
136 const auto controller_type = controller.device->GetNpadStyleIndex(); 139 const auto controller_type = controller.device->GetNpadStyleIndex();
137 auto& shared_memory = controller.shared_memory_entry; 140 auto* shared_memory = controller.shared_memory;
138 if (controller_type == Core::HID::NpadStyleIndex::None) { 141 if (controller_type == Core::HID::NpadStyleIndex::None) {
139 controller.styleset_changed_event->GetWritableEvent().Signal(); 142 controller.styleset_changed_event->GetWritableEvent().Signal();
140 return; 143 return;
141 } 144 }
142 shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None; 145 shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None;
143 shared_memory.device_type.raw = 0; 146 shared_memory->device_type.raw = 0;
144 shared_memory.system_properties.raw = 0; 147 shared_memory->system_properties.raw = 0;
145 switch (controller_type) { 148 switch (controller_type) {
146 case Core::HID::NpadStyleIndex::None: 149 case Core::HID::NpadStyleIndex::None:
147 UNREACHABLE(); 150 UNREACHABLE();
148 break; 151 break;
149 case Core::HID::NpadStyleIndex::ProController: 152 case Core::HID::NpadStyleIndex::ProController:
150 shared_memory.style_tag.fullkey.Assign(1); 153 shared_memory->style_tag.fullkey.Assign(1);
151 shared_memory.device_type.fullkey.Assign(1); 154 shared_memory->device_type.fullkey.Assign(1);
152 shared_memory.system_properties.is_vertical.Assign(1); 155 shared_memory->system_properties.is_vertical.Assign(1);
153 shared_memory.system_properties.use_plus.Assign(1); 156 shared_memory->system_properties.use_plus.Assign(1);
154 shared_memory.system_properties.use_minus.Assign(1); 157 shared_memory->system_properties.use_minus.Assign(1);
155 shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController; 158 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController;
156 break; 159 break;
157 case Core::HID::NpadStyleIndex::Handheld: 160 case Core::HID::NpadStyleIndex::Handheld:
158 shared_memory.style_tag.handheld.Assign(1); 161 shared_memory->style_tag.handheld.Assign(1);
159 shared_memory.device_type.handheld_left.Assign(1); 162 shared_memory->device_type.handheld_left.Assign(1);
160 shared_memory.device_type.handheld_right.Assign(1); 163 shared_memory->device_type.handheld_right.Assign(1);
161 shared_memory.system_properties.is_vertical.Assign(1); 164 shared_memory->system_properties.is_vertical.Assign(1);
162 shared_memory.system_properties.use_plus.Assign(1); 165 shared_memory->system_properties.use_plus.Assign(1);
163 shared_memory.system_properties.use_minus.Assign(1); 166 shared_memory->system_properties.use_minus.Assign(1);
164 shared_memory.system_properties.use_directional_buttons.Assign(1); 167 shared_memory->system_properties.use_directional_buttons.Assign(1);
165 shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; 168 shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
166 shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; 169 shared_memory->applet_nfc_xcd.applet_footer.type =
170 AppletFooterUiType::HandheldJoyConLeftJoyConRight;
167 break; 171 break;
168 case Core::HID::NpadStyleIndex::JoyconDual: 172 case Core::HID::NpadStyleIndex::JoyconDual:
169 shared_memory.style_tag.joycon_dual.Assign(1); 173 shared_memory->style_tag.joycon_dual.Assign(1);
170 if (controller.is_dual_left_connected) { 174 if (controller.is_dual_left_connected) {
171 shared_memory.device_type.joycon_left.Assign(1); 175 shared_memory->device_type.joycon_left.Assign(1);
172 shared_memory.system_properties.use_minus.Assign(1); 176 shared_memory->system_properties.use_minus.Assign(1);
173 } 177 }
174 if (controller.is_dual_right_connected) { 178 if (controller.is_dual_right_connected) {
175 shared_memory.device_type.joycon_right.Assign(1); 179 shared_memory->device_type.joycon_right.Assign(1);
176 shared_memory.system_properties.use_plus.Assign(1); 180 shared_memory->system_properties.use_plus.Assign(1);
177 } 181 }
178 shared_memory.system_properties.use_directional_buttons.Assign(1); 182 shared_memory->system_properties.use_directional_buttons.Assign(1);
179 shared_memory.system_properties.is_vertical.Assign(1); 183 shared_memory->system_properties.is_vertical.Assign(1);
180 shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; 184 shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
181 if (controller.is_dual_left_connected && controller.is_dual_right_connected) { 185 if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
182 shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; 186 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual;
183 } else if (controller.is_dual_left_connected) { 187 } else if (controller.is_dual_left_connected) {
184 shared_memory.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly; 188 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
185 } else { 189 } else {
186 shared_memory.applet_footer.type = AppletFooterUiType::JoyDualRightOnly; 190 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
187 } 191 }
188 break; 192 break;
189 case Core::HID::NpadStyleIndex::JoyconLeft: 193 case Core::HID::NpadStyleIndex::JoyconLeft:
190 shared_memory.style_tag.joycon_left.Assign(1); 194 shared_memory->style_tag.joycon_left.Assign(1);
191 shared_memory.device_type.joycon_left.Assign(1); 195 shared_memory->device_type.joycon_left.Assign(1);
192 shared_memory.system_properties.is_horizontal.Assign(1); 196 shared_memory->system_properties.is_horizontal.Assign(1);
193 shared_memory.system_properties.use_minus.Assign(1); 197 shared_memory->system_properties.use_minus.Assign(1);
194 shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; 198 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
195 break; 199 break;
196 case Core::HID::NpadStyleIndex::JoyconRight: 200 case Core::HID::NpadStyleIndex::JoyconRight:
197 shared_memory.style_tag.joycon_right.Assign(1); 201 shared_memory->style_tag.joycon_right.Assign(1);
198 shared_memory.device_type.joycon_right.Assign(1); 202 shared_memory->device_type.joycon_right.Assign(1);
199 shared_memory.system_properties.is_horizontal.Assign(1); 203 shared_memory->system_properties.is_horizontal.Assign(1);
200 shared_memory.system_properties.use_plus.Assign(1); 204 shared_memory->system_properties.use_plus.Assign(1);
201 shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; 205 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
202 break; 206 break;
203 case Core::HID::NpadStyleIndex::GameCube: 207 case Core::HID::NpadStyleIndex::GameCube:
204 shared_memory.style_tag.gamecube.Assign(1); 208 shared_memory->style_tag.gamecube.Assign(1);
205 shared_memory.device_type.fullkey.Assign(1); 209 shared_memory->device_type.fullkey.Assign(1);
206 shared_memory.system_properties.is_vertical.Assign(1); 210 shared_memory->system_properties.is_vertical.Assign(1);
207 shared_memory.system_properties.use_plus.Assign(1); 211 shared_memory->system_properties.use_plus.Assign(1);
208 break; 212 break;
209 case Core::HID::NpadStyleIndex::Pokeball: 213 case Core::HID::NpadStyleIndex::Pokeball:
210 shared_memory.style_tag.palma.Assign(1); 214 shared_memory->style_tag.palma.Assign(1);
211 shared_memory.device_type.palma.Assign(1); 215 shared_memory->device_type.palma.Assign(1);
212 break; 216 break;
213 case Core::HID::NpadStyleIndex::NES: 217 case Core::HID::NpadStyleIndex::NES:
214 shared_memory.style_tag.lark.Assign(1); 218 shared_memory->style_tag.lark.Assign(1);
215 shared_memory.device_type.fullkey.Assign(1); 219 shared_memory->device_type.fullkey.Assign(1);
216 break; 220 break;
217 case Core::HID::NpadStyleIndex::SNES: 221 case Core::HID::NpadStyleIndex::SNES:
218 shared_memory.style_tag.lucia.Assign(1); 222 shared_memory->style_tag.lucia.Assign(1);
219 shared_memory.device_type.fullkey.Assign(1); 223 shared_memory->device_type.fullkey.Assign(1);
220 shared_memory.applet_footer.type = AppletFooterUiType::Lucia; 224 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lucia;
221 break; 225 break;
222 case Core::HID::NpadStyleIndex::N64: 226 case Core::HID::NpadStyleIndex::N64:
223 shared_memory.style_tag.lagoon.Assign(1); 227 shared_memory->style_tag.lagoon.Assign(1);
224 shared_memory.device_type.fullkey.Assign(1); 228 shared_memory->device_type.fullkey.Assign(1);
225 shared_memory.applet_footer.type = AppletFooterUiType::Lagon; 229 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lagon;
226 break; 230 break;
227 case Core::HID::NpadStyleIndex::SegaGenesis: 231 case Core::HID::NpadStyleIndex::SegaGenesis:
228 shared_memory.style_tag.lager.Assign(1); 232 shared_memory->style_tag.lager.Assign(1);
229 shared_memory.device_type.fullkey.Assign(1); 233 shared_memory->device_type.fullkey.Assign(1);
230 break; 234 break;
231 default: 235 default:
232 break; 236 break;
@@ -234,23 +238,23 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
234 238
235 const auto& body_colors = controller.device->GetColors(); 239 const auto& body_colors = controller.device->GetColors();
236 240
237 shared_memory.fullkey_color.attribute = ColorAttribute::Ok; 241 shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
238 shared_memory.fullkey_color.fullkey = body_colors.fullkey; 242 shared_memory->fullkey_color.fullkey = body_colors.fullkey;
239 243
240 shared_memory.joycon_color.attribute = ColorAttribute::Ok; 244 shared_memory->joycon_color.attribute = ColorAttribute::Ok;
241 shared_memory.joycon_color.left = body_colors.left; 245 shared_memory->joycon_color.left = body_colors.left;
242 shared_memory.joycon_color.right = body_colors.right; 246 shared_memory->joycon_color.right = body_colors.right;
243 247
244 // TODO: Investigate when we should report all batery types 248 // TODO: Investigate when we should report all batery types
245 const auto& battery_level = controller.device->GetBattery(); 249 const auto& battery_level = controller.device->GetBattery();
246 shared_memory.battery_level_dual = battery_level.dual.battery_level; 250 shared_memory->battery_level_dual = battery_level.dual.battery_level;
247 shared_memory.battery_level_left = battery_level.left.battery_level; 251 shared_memory->battery_level_left = battery_level.left.battery_level;
248 shared_memory.battery_level_right = battery_level.right.battery_level; 252 shared_memory->battery_level_right = battery_level.right.battery_level;
249 253
250 controller.is_connected = true; 254 controller.is_connected = true;
251 controller.device->Connect(); 255 controller.device->Connect();
252 SignalStyleSetChangedEvent(npad_id); 256 SignalStyleSetChangedEvent(npad_id);
253 WriteEmptyEntry(controller.shared_memory_entry); 257 WriteEmptyEntry(controller.shared_memory);
254} 258}
255 259
256void Controller_NPad::OnInit() { 260void Controller_NPad::OnInit() {
@@ -270,12 +274,12 @@ void Controller_NPad::OnInit() {
270 274
271 // Prefill controller buffers 275 // Prefill controller buffers
272 for (auto& controller : controller_data) { 276 for (auto& controller : controller_data) {
273 auto& npad = controller.shared_memory_entry; 277 auto* npad = controller.shared_memory;
274 npad.fullkey_color = { 278 npad->fullkey_color = {
275 .attribute = ColorAttribute::NoController, 279 .attribute = ColorAttribute::NoController,
276 .fullkey = {}, 280 .fullkey = {},
277 }; 281 };
278 npad.joycon_color = { 282 npad->joycon_color = {
279 .attribute = ColorAttribute::NoController, 283 .attribute = ColorAttribute::NoController,
280 .left = {}, 284 .left = {},
281 .right = {}, 285 .right = {},
@@ -287,25 +291,25 @@ void Controller_NPad::OnInit() {
287 } 291 }
288} 292}
289 293
290void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) { 294void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {
291 NPadGenericState dummy_pad_state{}; 295 NPadGenericState dummy_pad_state{};
292 NpadGcTriggerState dummy_gc_state{}; 296 NpadGcTriggerState dummy_gc_state{};
293 dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1; 297 dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
294 npad.fullkey_lifo.WriteNextEntry(dummy_pad_state); 298 npad->fullkey_lifo.WriteNextEntry(dummy_pad_state);
295 dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1; 299 dummy_pad_state.sampling_number = npad->handheld_lifo.ReadCurrentEntry().sampling_number + 1;
296 npad.handheld_lifo.WriteNextEntry(dummy_pad_state); 300 npad->handheld_lifo.WriteNextEntry(dummy_pad_state);
297 dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; 301 dummy_pad_state.sampling_number = npad->joy_dual_lifo.ReadCurrentEntry().sampling_number + 1;
298 npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state); 302 npad->joy_dual_lifo.WriteNextEntry(dummy_pad_state);
299 dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1; 303 dummy_pad_state.sampling_number = npad->joy_left_lifo.ReadCurrentEntry().sampling_number + 1;
300 npad.joy_left_lifo.WriteNextEntry(dummy_pad_state); 304 npad->joy_left_lifo.WriteNextEntry(dummy_pad_state);
301 dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1; 305 dummy_pad_state.sampling_number = npad->joy_right_lifo.ReadCurrentEntry().sampling_number + 1;
302 npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); 306 npad->joy_right_lifo.WriteNextEntry(dummy_pad_state);
303 dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1; 307 dummy_pad_state.sampling_number = npad->palma_lifo.ReadCurrentEntry().sampling_number + 1;
304 npad.palma_lifo.WriteNextEntry(dummy_pad_state); 308 npad->palma_lifo.WriteNextEntry(dummy_pad_state);
305 dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1; 309 dummy_pad_state.sampling_number = npad->system_ext_lifo.ReadCurrentEntry().sampling_number + 1;
306 npad.system_ext_lifo.WriteNextEntry(dummy_pad_state); 310 npad->system_ext_lifo.WriteNextEntry(dummy_pad_state);
307 dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; 311 dummy_gc_state.sampling_number = npad->gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1;
308 npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state); 312 npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
309} 313}
310 314
311void Controller_NPad::OnRelease() { 315void Controller_NPad::OnRelease() {
@@ -371,23 +375,19 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
371 } 375 }
372} 376}
373 377
374void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 378void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
375 std::size_t data_len) {
376 if (!IsControllerActivated()) { 379 if (!IsControllerActivated()) {
377 return; 380 return;
378 } 381 }
379 382
380 for (std::size_t i = 0; i < controller_data.size(); ++i) { 383 for (std::size_t i = 0; i < controller_data.size(); ++i) {
381 auto& controller = controller_data[i]; 384 auto& controller = controller_data[i];
382 auto& npad = controller.shared_memory_entry; 385 auto* npad = controller.shared_memory;
383 386
384 const auto& controller_type = controller.device->GetNpadStyleIndex(); 387 const auto& controller_type = controller.device->GetNpadStyleIndex();
385 388
386 if (controller_type == Core::HID::NpadStyleIndex::None || 389 if (controller_type == Core::HID::NpadStyleIndex::None ||
387 !controller.device->IsConnected()) { 390 !controller.device->IsConnected()) {
388 // Refresh shared memory
389 std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
390 &controller.shared_memory_entry, sizeof(NpadInternalState));
391 continue; 391 continue;
392 } 392 }
393 393
@@ -415,8 +415,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
415 415
416 libnx_state.connection_status.is_wired.Assign(1); 416 libnx_state.connection_status.is_wired.Assign(1);
417 pad_state.sampling_number = 417 pad_state.sampling_number =
418 npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; 418 npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
419 npad.fullkey_lifo.WriteNextEntry(pad_state); 419 npad->fullkey_lifo.WriteNextEntry(pad_state);
420 break; 420 break;
421 case Core::HID::NpadStyleIndex::Handheld: 421 case Core::HID::NpadStyleIndex::Handheld:
422 pad_state.connection_status.raw = 0; 422 pad_state.connection_status.raw = 0;
@@ -433,8 +433,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
433 libnx_state.connection_status.is_left_wired.Assign(1); 433 libnx_state.connection_status.is_left_wired.Assign(1);
434 libnx_state.connection_status.is_right_wired.Assign(1); 434 libnx_state.connection_status.is_right_wired.Assign(1);
435 pad_state.sampling_number = 435 pad_state.sampling_number =
436 npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; 436 npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
437 npad.handheld_lifo.WriteNextEntry(pad_state); 437 npad->handheld_lifo.WriteNextEntry(pad_state);
438 break; 438 break;
439 case Core::HID::NpadStyleIndex::JoyconDual: 439 case Core::HID::NpadStyleIndex::JoyconDual:
440 pad_state.connection_status.raw = 0; 440 pad_state.connection_status.raw = 0;
@@ -449,8 +449,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
449 } 449 }
450 450
451 pad_state.sampling_number = 451 pad_state.sampling_number =
452 npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; 452 npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
453 npad.joy_dual_lifo.WriteNextEntry(pad_state); 453 npad->joy_dual_lifo.WriteNextEntry(pad_state);
454 break; 454 break;
455 case Core::HID::NpadStyleIndex::JoyconLeft: 455 case Core::HID::NpadStyleIndex::JoyconLeft:
456 pad_state.connection_status.raw = 0; 456 pad_state.connection_status.raw = 0;
@@ -459,8 +459,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
459 459
460 libnx_state.connection_status.is_left_connected.Assign(1); 460 libnx_state.connection_status.is_left_connected.Assign(1);
461 pad_state.sampling_number = 461 pad_state.sampling_number =
462 npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; 462 npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
463 npad.joy_left_lifo.WriteNextEntry(pad_state); 463 npad->joy_left_lifo.WriteNextEntry(pad_state);
464 break; 464 break;
465 case Core::HID::NpadStyleIndex::JoyconRight: 465 case Core::HID::NpadStyleIndex::JoyconRight:
466 pad_state.connection_status.raw = 0; 466 pad_state.connection_status.raw = 0;
@@ -469,8 +469,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
469 469
470 libnx_state.connection_status.is_right_connected.Assign(1); 470 libnx_state.connection_status.is_right_connected.Assign(1);
471 pad_state.sampling_number = 471 pad_state.sampling_number =
472 npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; 472 npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
473 npad.joy_right_lifo.WriteNextEntry(pad_state); 473 npad->joy_right_lifo.WriteNextEntry(pad_state);
474 break; 474 break;
475 case Core::HID::NpadStyleIndex::GameCube: 475 case Core::HID::NpadStyleIndex::GameCube:
476 pad_state.connection_status.raw = 0; 476 pad_state.connection_status.raw = 0;
@@ -479,18 +479,18 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
479 479
480 libnx_state.connection_status.is_wired.Assign(1); 480 libnx_state.connection_status.is_wired.Assign(1);
481 pad_state.sampling_number = 481 pad_state.sampling_number =
482 npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; 482 npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
483 trigger_state.sampling_number = 483 trigger_state.sampling_number =
484 npad.gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; 484 npad->gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1;
485 npad.fullkey_lifo.WriteNextEntry(pad_state); 485 npad->fullkey_lifo.WriteNextEntry(pad_state);
486 npad.gc_trigger_lifo.WriteNextEntry(trigger_state); 486 npad->gc_trigger_lifo.WriteNextEntry(trigger_state);
487 break; 487 break;
488 case Core::HID::NpadStyleIndex::Pokeball: 488 case Core::HID::NpadStyleIndex::Pokeball:
489 pad_state.connection_status.raw = 0; 489 pad_state.connection_status.raw = 0;
490 pad_state.connection_status.is_connected.Assign(1); 490 pad_state.connection_status.is_connected.Assign(1);
491 pad_state.sampling_number = 491 pad_state.sampling_number =
492 npad.palma_lifo.ReadCurrentEntry().state.sampling_number + 1; 492 npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1;
493 npad.palma_lifo.WriteNextEntry(pad_state); 493 npad->palma_lifo.WriteNextEntry(pad_state);
494 break; 494 break;
495 default: 495 default:
496 break; 496 break;
@@ -499,17 +499,13 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
499 libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw; 499 libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;
500 libnx_state.l_stick = pad_state.l_stick; 500 libnx_state.l_stick = pad_state.l_stick;
501 libnx_state.r_stick = pad_state.r_stick; 501 libnx_state.r_stick = pad_state.r_stick;
502 npad.system_ext_lifo.WriteNextEntry(pad_state); 502 npad->system_ext_lifo.WriteNextEntry(pad_state);
503 503
504 press_state |= static_cast<u64>(pad_state.npad_buttons.raw); 504 press_state |= static_cast<u64>(pad_state.npad_buttons.raw);
505
506 std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
507 &controller.shared_memory_entry, sizeof(NpadInternalState));
508 } 505 }
509} 506}
510 507
511void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 508void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {
512 std::size_t data_len) {
513 if (!IsControllerActivated()) { 509 if (!IsControllerActivated()) {
514 return; 510 return;
515 } 511 }
@@ -524,7 +520,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
524 continue; 520 continue;
525 } 521 }
526 522
527 auto& npad = controller.shared_memory_entry; 523 auto* npad = controller.shared_memory;
528 const auto& motion_state = controller.device->GetMotions(); 524 const auto& motion_state = controller.device->GetMotions();
529 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state; 525 auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
530 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state; 526 auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
@@ -610,32 +606,30 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
610 } 606 }
611 607
612 sixaxis_fullkey_state.sampling_number = 608 sixaxis_fullkey_state.sampling_number =
613 npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; 609 npad->sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
614 sixaxis_handheld_state.sampling_number = 610 sixaxis_handheld_state.sampling_number =
615 npad.sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; 611 npad->sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
616 sixaxis_dual_left_state.sampling_number = 612 sixaxis_dual_left_state.sampling_number =
617 npad.sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1; 613 npad->sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
618 sixaxis_dual_right_state.sampling_number = 614 sixaxis_dual_right_state.sampling_number =
619 npad.sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1; 615 npad->sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
620 sixaxis_left_lifo_state.sampling_number = 616 sixaxis_left_lifo_state.sampling_number =
621 npad.sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1; 617 npad->sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
622 sixaxis_right_lifo_state.sampling_number = 618 sixaxis_right_lifo_state.sampling_number =
623 npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1; 619 npad->sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
624 620
625 if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) { 621 if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
626 // This buffer only is updated on handheld on HW 622 // This buffer only is updated on handheld on HW
627 npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); 623 npad->sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
628 } else { 624 } else {
629 // Handheld doesn't update this buffer on HW 625 // Handheld doesn't update this buffer on HW
630 npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); 626 npad->sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
631 } 627 }
632 628
633 npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); 629 npad->sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
634 npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); 630 npad->sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
635 npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); 631 npad->sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
636 npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state); 632 npad->sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
637 std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
638 &controller.shared_memory_entry, sizeof(NpadInternalState));
639 } 633 }
640} 634}
641 635
@@ -713,8 +707,8 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy
713 } 707 }
714 708
715 auto& controller = GetControllerFromNpadIdType(npad_id); 709 auto& controller = GetControllerFromNpadIdType(npad_id);
716 if (controller.shared_memory_entry.assignment_mode != assignment_mode) { 710 if (controller.shared_memory->assignment_mode != assignment_mode) {
717 controller.shared_memory_entry.assignment_mode = assignment_mode; 711 controller.shared_memory->assignment_mode = assignment_mode;
718 } 712 }
719 713
720 if (!controller.device->IsConnected()) { 714 if (!controller.device->IsConnected()) {
@@ -981,32 +975,32 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
981 controller.vibration[device_idx].device_mounted = false; 975 controller.vibration[device_idx].device_mounted = false;
982 } 976 }
983 977
984 auto& shared_memory_entry = controller.shared_memory_entry; 978 auto* shared_memory = controller.shared_memory;
985 // Don't reset shared_memory_entry.assignment_mode this value is persistent 979 // Don't reset shared_memory->assignment_mode this value is persistent
986 shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out 980 shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
987 shared_memory_entry.device_type.raw = 0; 981 shared_memory->device_type.raw = 0;
988 shared_memory_entry.system_properties.raw = 0; 982 shared_memory->system_properties.raw = 0;
989 shared_memory_entry.button_properties.raw = 0; 983 shared_memory->button_properties.raw = 0;
990 shared_memory_entry.battery_level_dual = 0; 984 shared_memory->battery_level_dual = 0;
991 shared_memory_entry.battery_level_left = 0; 985 shared_memory->battery_level_left = 0;
992 shared_memory_entry.battery_level_right = 0; 986 shared_memory->battery_level_right = 0;
993 shared_memory_entry.fullkey_color = { 987 shared_memory->fullkey_color = {
994 .attribute = ColorAttribute::NoController, 988 .attribute = ColorAttribute::NoController,
995 .fullkey = {}, 989 .fullkey = {},
996 }; 990 };
997 shared_memory_entry.joycon_color = { 991 shared_memory->joycon_color = {
998 .attribute = ColorAttribute::NoController, 992 .attribute = ColorAttribute::NoController,
999 .left = {}, 993 .left = {},
1000 .right = {}, 994 .right = {},
1001 }; 995 };
1002 shared_memory_entry.applet_footer.type = AppletFooterUiType::None; 996 shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::None;
1003 997
1004 controller.is_dual_left_connected = true; 998 controller.is_dual_left_connected = true;
1005 controller.is_dual_right_connected = true; 999 controller.is_dual_right_connected = true;
1006 controller.is_connected = false; 1000 controller.is_connected = false;
1007 controller.device->Disconnect(); 1001 controller.device->Disconnect();
1008 SignalStyleSetChangedEvent(npad_id); 1002 SignalStyleSetChangedEvent(npad_id);
1009 WriteEmptyEntry(controller.shared_memory_entry); 1003 WriteEmptyEntry(shared_memory);
1010} 1004}
1011 1005
1012ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, 1006ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index b42532b68..0a96825a5 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -35,7 +35,7 @@ namespace Service::HID {
35 35
36class Controller_NPad final : public ControllerBase { 36class Controller_NPad final : public ControllerBase {
37public: 37public:
38 explicit Controller_NPad(Core::HID::HIDCore& hid_core_, 38 explicit Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
39 KernelHelpers::ServiceContext& service_context_); 39 KernelHelpers::ServiceContext& service_context_);
40 ~Controller_NPad() override; 40 ~Controller_NPad() override;
41 41
@@ -46,11 +46,10 @@ public:
46 void OnRelease() override; 46 void OnRelease() override;
47 47
48 // When the controller is requesting an update for the shared memory 48 // When the controller is requesting an update for the shared memory
49 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 49 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
50 50
51 // When the controller is requesting a motion update for the shared memory 51 // When the controller is requesting a motion update for the shared memory
52 void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 52 void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override;
53 std::size_t size) override;
54 53
55 // This is nn::hid::GyroscopeZeroDriftMode 54 // This is nn::hid::GyroscopeZeroDriftMode
56 enum class GyroscopeZeroDriftMode : u32 { 55 enum class GyroscopeZeroDriftMode : u32 {
@@ -188,6 +187,8 @@ public:
188 static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle); 187 static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
189 188
190private: 189private:
190 static constexpr std::size_t NPAD_COUNT = 10;
191
191 // This is nn::hid::detail::ColorAttribute 192 // This is nn::hid::detail::ColorAttribute
192 enum class ColorAttribute : u32 { 193 enum class ColorAttribute : u32 {
193 Ok = 0, 194 Ok = 0,
@@ -409,6 +410,13 @@ private:
409 U, 410 U,
410 }; 411 };
411 412
413 struct AppletNfcXcd {
414 union {
415 AppletFooterUi applet_footer{};
416 Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo;
417 };
418 };
419
412 // This is nn::hid::detail::NpadInternalState 420 // This is nn::hid::detail::NpadInternalState
413 struct NpadInternalState { 421 struct NpadInternalState {
414 Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None}; 422 Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None};
@@ -435,10 +443,7 @@ private:
435 Core::HID::NpadBatteryLevel battery_level_dual{}; 443 Core::HID::NpadBatteryLevel battery_level_dual{};
436 Core::HID::NpadBatteryLevel battery_level_left{}; 444 Core::HID::NpadBatteryLevel battery_level_left{};
437 Core::HID::NpadBatteryLevel battery_level_right{}; 445 Core::HID::NpadBatteryLevel battery_level_right{};
438 union { 446 AppletNfcXcd applet_nfc_xcd{};
439 AppletFooterUi applet_footer{};
440 Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo;
441 };
442 INSERT_PADDING_BYTES(0x20); // Unknown 447 INSERT_PADDING_BYTES(0x20); // Unknown
443 Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{}; 448 Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{};
444 NpadLarkType lark_type_l_and_main{}; 449 NpadLarkType lark_type_l_and_main{};
@@ -465,9 +470,9 @@ private:
465 }; 470 };
466 471
467 struct NpadControllerData { 472 struct NpadControllerData {
468 Core::HID::EmulatedController* device;
469 Kernel::KEvent* styleset_changed_event{}; 473 Kernel::KEvent* styleset_changed_event{};
470 NpadInternalState shared_memory_entry{}; 474 NpadInternalState* shared_memory = nullptr;
475 Core::HID::EmulatedController* device = nullptr;
471 476
472 std::array<VibrationData, 2> vibration{}; 477 std::array<VibrationData, 2> vibration{};
473 bool unintended_home_button_input_protection{}; 478 bool unintended_home_button_input_protection{};
@@ -497,15 +502,14 @@ private:
497 SixAxisSensorState sixaxis_dual_right_state{}; 502 SixAxisSensorState sixaxis_dual_right_state{};
498 SixAxisSensorState sixaxis_left_lifo_state{}; 503 SixAxisSensorState sixaxis_left_lifo_state{};
499 SixAxisSensorState sixaxis_right_lifo_state{}; 504 SixAxisSensorState sixaxis_right_lifo_state{};
500 505 int callback_key{};
501 int callback_key;
502 }; 506 };
503 507
504 void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx); 508 void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx);
505 void InitNewlyAddedController(Core::HID::NpadIdType npad_id); 509 void InitNewlyAddedController(Core::HID::NpadIdType npad_id);
506 bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const; 510 bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const;
507 void RequestPadStateUpdate(Core::HID::NpadIdType npad_id); 511 void RequestPadStateUpdate(Core::HID::NpadIdType npad_id);
508 void WriteEmptyEntry(NpadInternalState& npad); 512 void WriteEmptyEntry(NpadInternalState* npad);
509 513
510 NpadControllerData& GetControllerFromHandle( 514 NpadControllerData& GetControllerFromHandle(
511 const Core::HID::SixAxisSensorHandle& device_handle); 515 const Core::HID::SixAxisSensorHandle& device_handle);
@@ -520,7 +524,7 @@ private:
520 524
521 std::atomic<u64> press_state{}; 525 std::atomic<u64> press_state{};
522 526
523 std::array<NpadControllerData, 10> controller_data{}; 527 std::array<NpadControllerData, NPAD_COUNT> controller_data{};
524 KernelHelpers::ServiceContext& service_context; 528 KernelHelpers::ServiceContext& service_context;
525 std::mutex mutex; 529 std::mutex mutex;
526 std::vector<Core::HID::NpadIdType> supported_npad_id_types{}; 530 std::vector<Core::HID::NpadIdType> supported_npad_id_types{};
diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp
index 4d3b9d2be..df9ee0c3f 100644
--- a/src/core/hle/service/hid/controllers/stubbed.cpp
+++ b/src/core/hle/service/hid/controllers/stubbed.cpp
@@ -9,15 +9,18 @@
9 9
10namespace Service::HID { 10namespace Service::HID {
11 11
12Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} 12Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
13 : ControllerBase{hid_core_} {
14 raw_shared_memory = raw_shared_memory_;
15}
16
13Controller_Stubbed::~Controller_Stubbed() = default; 17Controller_Stubbed::~Controller_Stubbed() = default;
14 18
15void Controller_Stubbed::OnInit() {} 19void Controller_Stubbed::OnInit() {}
16 20
17void Controller_Stubbed::OnRelease() {} 21void Controller_Stubbed::OnRelease() {}
18 22
19void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 23void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
20 std::size_t size) {
21 if (!smart_update) { 24 if (!smart_update) {
22 return; 25 return;
23 } 26 }
@@ -28,7 +31,7 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
28 header.entry_count = 0; 31 header.entry_count = 0;
29 header.last_entry_index = 0; 32 header.last_entry_index = 0;
30 33
31 std::memcpy(data + common_offset, &header, sizeof(CommonHeader)); 34 std::memcpy(raw_shared_memory + common_offset, &header, sizeof(CommonHeader));
32} 35}
33 36
34void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) { 37void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) {
diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h
index 512066eb3..1483a968e 100644
--- a/src/core/hle/service/hid/controllers/stubbed.h
+++ b/src/core/hle/service/hid/controllers/stubbed.h
@@ -9,7 +9,7 @@
9namespace Service::HID { 9namespace Service::HID {
10class Controller_Stubbed final : public ControllerBase { 10class Controller_Stubbed final : public ControllerBase {
11public: 11public:
12 explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_); 12 explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
13 ~Controller_Stubbed() override; 13 ~Controller_Stubbed() override;
14 14
15 // Called when the controller is initialized 15 // Called when the controller is initialized
@@ -19,19 +19,20 @@ public:
19 void OnRelease() override; 19 void OnRelease() override;
20 20
21 // When the controller is requesting an update for the shared memory 21 // When the controller is requesting an update for the shared memory
22 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 22 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
23 23
24 void SetCommonHeaderOffset(std::size_t off); 24 void SetCommonHeaderOffset(std::size_t off);
25 25
26private: 26private:
27 struct CommonHeader { 27 struct CommonHeader {
28 s64 timestamp; 28 s64 timestamp{};
29 s64 total_entry_count; 29 s64 total_entry_count{};
30 s64 last_entry_index; 30 s64 last_entry_index{};
31 s64 entry_count; 31 s64 entry_count{};
32 }; 32 };
33 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); 33 static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size");
34 34
35 u8* raw_shared_memory = nullptr;
35 bool smart_update{}; 36 bool smart_update{};
36 std::size_t common_offset{}; 37 std::size_t common_offset{};
37}; 38};
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 5b4b51a69..108ce5a41 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -15,8 +15,13 @@
15namespace Service::HID { 15namespace Service::HID {
16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; 16constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
17 17
18Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_) 18Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_,
19 u8* raw_shared_memory_)
19 : ControllerBase{hid_core_} { 20 : ControllerBase{hid_core_} {
21 static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size,
22 "TouchSharedMemory is bigger than the shared memory");
23 shared_memory = std::construct_at(
24 reinterpret_cast<TouchSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
20 console = hid_core.GetEmulatedConsole(); 25 console = hid_core.GetEmulatedConsole();
21} 26}
22 27
@@ -26,14 +31,12 @@ void Controller_Touchscreen::OnInit() {}
26 31
27void Controller_Touchscreen::OnRelease() {} 32void Controller_Touchscreen::OnRelease() {}
28 33
29void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 34void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
30 std::size_t size) { 35 shared_memory->touch_screen_lifo.timestamp = core_timing.GetCPUTicks();
31 touch_screen_lifo.timestamp = core_timing.GetCPUTicks();
32 36
33 if (!IsControllerActivated()) { 37 if (!IsControllerActivated()) {
34 touch_screen_lifo.buffer_count = 0; 38 shared_memory->touch_screen_lifo.buffer_count = 0;
35 touch_screen_lifo.buffer_tail = 0; 39 shared_memory->touch_screen_lifo.buffer_tail = 0;
36 std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo));
37 return; 40 return;
38 } 41 }
39 42
@@ -74,7 +77,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
74 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); 77 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
75 78
76 const u64 tick = core_timing.GetCPUTicks(); 79 const u64 tick = core_timing.GetCPUTicks();
77 const auto& last_entry = touch_screen_lifo.ReadCurrentEntry().state; 80 const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state;
78 81
79 next_state.sampling_number = last_entry.sampling_number + 1; 82 next_state.sampling_number = last_entry.sampling_number + 1;
80 next_state.entry_count = static_cast<s32>(active_fingers_count); 83 next_state.entry_count = static_cast<s32>(active_fingers_count);
@@ -106,8 +109,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
106 } 109 }
107 } 110 }
108 111
109 touch_screen_lifo.WriteNextEntry(next_state); 112 shared_memory->touch_screen_lifo.WriteNextEntry(next_state);
110 std::memcpy(data + SHARED_MEMORY_OFFSET, &touch_screen_lifo, sizeof(touch_screen_lifo));
111} 113}
112 114
113} // namespace Service::HID 115} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 424973b38..e57a3a80e 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -25,14 +25,14 @@ public:
25 25
26 // This is nn::hid::TouchScreenConfigurationForNx 26 // This is nn::hid::TouchScreenConfigurationForNx
27 struct TouchScreenConfigurationForNx { 27 struct TouchScreenConfigurationForNx {
28 TouchScreenModeForNx mode; 28 TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
29 INSERT_PADDING_BYTES_NOINIT(0x7); 29 INSERT_PADDING_BYTES_NOINIT(0x7);
30 INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved 30 INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved
31 }; 31 };
32 static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17, 32 static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
33 "TouchScreenConfigurationForNx is an invalid size"); 33 "TouchScreenConfigurationForNx is an invalid size");
34 34
35 explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_); 35 explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
36 ~Controller_Touchscreen() override; 36 ~Controller_Touchscreen() override;
37 37
38 // Called when the controller is initialized 38 // Called when the controller is initialized
@@ -42,26 +42,32 @@ public:
42 void OnRelease() override; 42 void OnRelease() override;
43 43
44 // When the controller is requesting an update for the shared memory 44 // When the controller is requesting an update for the shared memory
45 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 45 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
46 46
47private: 47private:
48 static constexpr std::size_t MAX_FINGERS = 16; 48 static constexpr std::size_t MAX_FINGERS = 16;
49 49
50 // This is nn::hid::TouchScreenState 50 // This is nn::hid::TouchScreenState
51 struct TouchScreenState { 51 struct TouchScreenState {
52 s64 sampling_number; 52 s64 sampling_number{};
53 s32 entry_count; 53 s32 entry_count{};
54 INSERT_PADDING_BYTES(4); // Reserved 54 INSERT_PADDING_BYTES(4); // Reserved
55 std::array<Core::HID::TouchState, MAX_FINGERS> states; 55 std::array<Core::HID::TouchState, MAX_FINGERS> states{};
56 }; 56 };
57 static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); 57 static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size");
58 58
59 // This is nn::hid::detail::TouchScreenLifo 59 struct TouchSharedMemory {
60 Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{}; 60 // This is nn::hid::detail::TouchScreenLifo
61 static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); 61 Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{};
62 static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size");
63 INSERT_PADDING_WORDS(0xF2);
64 };
65 static_assert(sizeof(TouchSharedMemory) == 0x3000, "TouchSharedMemory is an invalid size");
66
62 TouchScreenState next_state{}; 67 TouchScreenState next_state{};
68 TouchSharedMemory* shared_memory = nullptr;
69 Core::HID::EmulatedConsole* console = nullptr;
63 70
64 std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers; 71 std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{};
65 Core::HID::EmulatedConsole* console;
66}; 72};
67} // namespace Service::HID 73} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp
index fc6ac6457..62119e2c5 100644
--- a/src/core/hle/service/hid/controllers/xpad.cpp
+++ b/src/core/hle/service/hid/controllers/xpad.cpp
@@ -10,28 +10,31 @@
10namespace Service::HID { 10namespace Service::HID {
11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; 11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00;
12 12
13Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} 13Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)
14 : ControllerBase{hid_core_} {
15 static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size,
16 "XpadSharedMemory is bigger than the shared memory");
17 shared_memory = std::construct_at(
18 reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));
19}
14Controller_XPad::~Controller_XPad() = default; 20Controller_XPad::~Controller_XPad() = default;
15 21
16void Controller_XPad::OnInit() {} 22void Controller_XPad::OnInit() {}
17 23
18void Controller_XPad::OnRelease() {} 24void Controller_XPad::OnRelease() {}
19 25
20void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 26void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
21 std::size_t size) {
22 if (!IsControllerActivated()) { 27 if (!IsControllerActivated()) {
23 basic_xpad_lifo.buffer_count = 0; 28 shared_memory->basic_xpad_lifo.buffer_count = 0;
24 basic_xpad_lifo.buffer_tail = 0; 29 shared_memory->basic_xpad_lifo.buffer_tail = 0;
25 std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
26 return; 30 return;
27 } 31 }
28 32
29 const auto& last_entry = basic_xpad_lifo.ReadCurrentEntry().state; 33 const auto& last_entry = shared_memory->basic_xpad_lifo.ReadCurrentEntry().state;
30 next_state.sampling_number = last_entry.sampling_number + 1; 34 next_state.sampling_number = last_entry.sampling_number + 1;
31 // TODO(ogniK): Update xpad states 35 // TODO(ogniK): Update xpad states
32 36
33 basic_xpad_lifo.WriteNextEntry(next_state); 37 shared_memory->basic_xpad_lifo.WriteNextEntry(next_state);
34 std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo));
35} 38}
36 39
37} // namespace Service::HID 40} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h
index 8211b6ee3..d01dee5fc 100644
--- a/src/core/hle/service/hid/controllers/xpad.h
+++ b/src/core/hle/service/hid/controllers/xpad.h
@@ -12,7 +12,7 @@
12namespace Service::HID { 12namespace Service::HID {
13class Controller_XPad final : public ControllerBase { 13class Controller_XPad final : public ControllerBase {
14public: 14public:
15 explicit Controller_XPad(Core::HID::HIDCore& hid_core_); 15 explicit Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
16 ~Controller_XPad() override; 16 ~Controller_XPad() override;
17 17
18 // Called when the controller is initialized 18 // Called when the controller is initialized
@@ -22,7 +22,7 @@ public:
22 void OnRelease() override; 22 void OnRelease() override;
23 23
24 // When the controller is requesting an update for the shared memory 24 // When the controller is requesting an update for the shared memory
25 void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; 25 void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;
26 26
27private: 27private:
28 // This is nn::hid::BasicXpadAttributeSet 28 // This is nn::hid::BasicXpadAttributeSet
@@ -90,17 +90,23 @@ private:
90 90
91 // This is nn::hid::detail::BasicXpadState 91 // This is nn::hid::detail::BasicXpadState
92 struct BasicXpadState { 92 struct BasicXpadState {
93 s64 sampling_number; 93 s64 sampling_number{};
94 BasicXpadAttributeSet attributes; 94 BasicXpadAttributeSet attributes{};
95 BasicXpadButtonSet pad_states; 95 BasicXpadButtonSet pad_states{};
96 Core::HID::AnalogStickState l_stick; 96 Core::HID::AnalogStickState l_stick{};
97 Core::HID::AnalogStickState r_stick; 97 Core::HID::AnalogStickState r_stick{};
98 }; 98 };
99 static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size"); 99 static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size");
100 100
101 // This is nn::hid::detail::BasicXpadLifo 101 struct XpadSharedMemory {
102 Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{}; 102 // This is nn::hid::detail::BasicXpadLifo
103 static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size"); 103 Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{};
104 static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size");
105 INSERT_PADDING_WORDS(0x4E);
106 };
107 static_assert(sizeof(XpadSharedMemory) == 0x400, "XpadSharedMemory is an invalid size");
108
104 BasicXpadState next_state{}; 109 BasicXpadState next_state{};
110 XpadSharedMemory* shared_memory = nullptr;
105}; 111};
106} // namespace Service::HID 112} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index fb1ec52b2..36162ac97 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -39,7 +39,6 @@ constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};
39constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) 39constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)
40// TODO: Correct update rate for motion is 5ms. Check why some games don't behave at that speed 40// TODO: Correct update rate for motion is 5ms. Check why some games don't behave at that speed
41constexpr auto motion_update_ns = std::chrono::nanoseconds{10 * 1000 * 1000}; // (10ms, 100Hz) 41constexpr auto motion_update_ns = std::chrono::nanoseconds{10 * 1000 * 1000}; // (10ms, 100Hz)
42constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
43 42
44IAppletResource::IAppletResource(Core::System& system_, 43IAppletResource::IAppletResource(Core::System& system_,
45 KernelHelpers::ServiceContext& service_context_) 44 KernelHelpers::ServiceContext& service_context_)
@@ -48,20 +47,20 @@ IAppletResource::IAppletResource(Core::System& system_,
48 {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, 47 {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
49 }; 48 };
50 RegisterHandlers(functions); 49 RegisterHandlers(functions);
51 50 u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer();
52 MakeController<Controller_DebugPad>(HidController::DebugPad); 51 MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory);
53 MakeController<Controller_Touchscreen>(HidController::Touchscreen); 52 MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory);
54 MakeController<Controller_Mouse>(HidController::Mouse); 53 MakeController<Controller_Mouse>(HidController::Mouse, shared_memory);
55 MakeController<Controller_Keyboard>(HidController::Keyboard); 54 MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory);
56 MakeController<Controller_XPad>(HidController::XPad); 55 MakeController<Controller_XPad>(HidController::XPad, shared_memory);
57 MakeController<Controller_Stubbed>(HidController::HomeButton); 56 MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory);
58 MakeController<Controller_Stubbed>(HidController::SleepButton); 57 MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory);
59 MakeController<Controller_Stubbed>(HidController::CaptureButton); 58 MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory);
60 MakeController<Controller_Stubbed>(HidController::InputDetector); 59 MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory);
61 MakeController<Controller_Stubbed>(HidController::UniquePad); 60 MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory);
62 MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad); 61 MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory);
63 MakeController<Controller_Gesture>(HidController::Gesture); 62 MakeController<Controller_Gesture>(HidController::Gesture, shared_memory);
64 MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor); 63 MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory);
65 64
66 // Homebrew doesn't try to activate some controllers, so we activate them by default 65 // Homebrew doesn't try to activate some controllers, so we activate them by default
67 GetController<Controller_NPad>(HidController::NPad).ActivateController(); 66 GetController<Controller_NPad>(HidController::NPad).ActivateController();
@@ -135,8 +134,7 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
135 if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) { 134 if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {
136 continue; 135 continue;
137 } 136 }
138 controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), 137 controller->OnUpdate(core_timing);
139 SHARED_MEMORY_SIZE);
140 } 138 }
141 139
142 // If ns_late is higher than the update rate ignore the delay 140 // If ns_late is higher than the update rate ignore the delay
@@ -151,10 +149,8 @@ void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
151 std::chrono::nanoseconds ns_late) { 149 std::chrono::nanoseconds ns_late) {
152 auto& core_timing = system.CoreTiming(); 150 auto& core_timing = system.CoreTiming();
153 151
154 controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate( 152 controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing);
155 core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); 153 controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing);
156 controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(
157 core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
158 154
159 // If ns_late is higher than the update rate ignore the delay 155 // If ns_late is higher than the update rate ignore the delay
160 if (ns_late > mouse_keyboard_update_ns) { 156 if (ns_late > mouse_keyboard_update_ns) {
@@ -167,8 +163,7 @@ void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,
167void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { 163void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
168 auto& core_timing = system.CoreTiming(); 164 auto& core_timing = system.CoreTiming();
169 165
170 controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate( 166 controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing);
171 core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE);
172 167
173 // If ns_late is higher than the update rate ignore the delay 168 // If ns_late is higher than the update rate ignore the delay
174 if (ns_late > motion_update_ns) { 169 if (ns_late > motion_update_ns) {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 95778e673..e61f8ed08 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -58,13 +58,14 @@ public:
58 58
59private: 59private:
60 template <typename T> 60 template <typename T>
61 void MakeController(HidController controller) { 61 void MakeController(HidController controller, u8* shared_memory) {
62 controllers[static_cast<std::size_t>(controller)] = std::make_unique<T>(system.HIDCore()); 62 controllers[static_cast<std::size_t>(controller)] =
63 std::make_unique<T>(system.HIDCore(), shared_memory);
63 } 64 }
64 template <typename T> 65 template <typename T>
65 void MakeControllerWithServiceContext(HidController controller) { 66 void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {
66 controllers[static_cast<std::size_t>(controller)] = 67 controllers[static_cast<std::size_t>(controller)] =
67 std::make_unique<T>(system.HIDCore(), service_context); 68 std::make_unique<T>(system.HIDCore(), shared_memory, service_context);
68 } 69 }
69 70
70 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); 71 void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp
index 185d0387b..8f2920c51 100644
--- a/src/core/hle/service/jit/jit.cpp
+++ b/src/core/hle/service/jit/jit.cpp
@@ -21,9 +21,10 @@ struct CodeRange {
21 21
22class IJitEnvironment final : public ServiceFramework<IJitEnvironment> { 22class IJitEnvironment final : public ServiceFramework<IJitEnvironment> {
23public: 23public:
24 explicit IJitEnvironment(Core::System& system_, CodeRange user_rx, CodeRange user_ro) 24 explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx,
25 CodeRange user_ro)
25 : ServiceFramework{system_, "IJitEnvironment", ServiceThreadType::CreateNew}, 26 : ServiceFramework{system_, "IJitEnvironment", ServiceThreadType::CreateNew},
26 context{system_.Memory()} { 27 process{&process_}, context{system_.Memory()} {
27 // clang-format off 28 // clang-format off
28 static const FunctionInfo functions[] = { 29 static const FunctionInfo functions[] = {
29 {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, 30 {0, &IJitEnvironment::GenerateCode, "GenerateCode"},
@@ -43,54 +44,80 @@ public:
43 } 44 }
44 45
45 void GenerateCode(Kernel::HLERequestContext& ctx) { 46 void GenerateCode(Kernel::HLERequestContext& ctx) {
46 struct Parameters { 47 LOG_DEBUG(Service_JIT, "called");
48
49 struct InputParameters {
47 u32 data_size; 50 u32 data_size;
48 u64 command; 51 u64 command;
49 CodeRange cr1; 52 std::array<CodeRange, 2> ranges;
50 CodeRange cr2;
51 Struct32 data; 53 Struct32 data;
52 }; 54 };
53 55
56 struct OutputParameters {
57 s32 return_value;
58 std::array<CodeRange, 2> ranges;
59 };
60
54 IPC::RequestParser rp{ctx}; 61 IPC::RequestParser rp{ctx};
55 const auto parameters{rp.PopRaw<Parameters>()}; 62 const auto parameters{rp.PopRaw<InputParameters>()};
63
64 // Optional input/output buffers
56 std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()}; 65 std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()};
57 std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); 66 std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0);
58 67
59 const VAddr return_ptr{context.AddHeap(0u)}; 68 // Function call prototype:
60 const VAddr cr1_in_ptr{context.AddHeap(parameters.cr1)}; 69 // void GenerateCode(s32* ret, CodeRange* c0_out, CodeRange* c1_out, JITConfiguration* cfg,
61 const VAddr cr2_in_ptr{context.AddHeap(parameters.cr2)}; 70 // u64 cmd, u8* input_buf, size_t input_size, CodeRange* c0_in,
62 const VAddr cr1_out_ptr{ 71 // CodeRange* c1_in, Struct32* data, size_t data_size, u8* output_buf,
63 context.AddHeap(CodeRange{.offset = parameters.cr1.offset, .size = 0})}; 72 // size_t output_size);
64 const VAddr cr2_out_ptr{ 73 //
65 context.AddHeap(CodeRange{.offset = parameters.cr2.offset, .size = 0})}; 74 // The command argument is used to control the behavior of the plugin during code
75 // generation. The configuration allows the plugin to access the output code ranges, and the
76 // other arguments are used to transfer state between the game and the plugin.
77
78 const VAddr ret_ptr{context.AddHeap(0u)};
79 const VAddr c0_in_ptr{context.AddHeap(parameters.ranges[0])};
80 const VAddr c1_in_ptr{context.AddHeap(parameters.ranges[1])};
81 const VAddr c0_out_ptr{context.AddHeap(ClearSize(parameters.ranges[0]))};
82 const VAddr c1_out_ptr{context.AddHeap(ClearSize(parameters.ranges[1]))};
83
66 const VAddr input_ptr{context.AddHeap(input_buffer.data(), input_buffer.size())}; 84 const VAddr input_ptr{context.AddHeap(input_buffer.data(), input_buffer.size())};
67 const VAddr output_ptr{context.AddHeap(output_buffer.data(), output_buffer.size())}; 85 const VAddr output_ptr{context.AddHeap(output_buffer.data(), output_buffer.size())};
68 const VAddr data_ptr{context.AddHeap(parameters.data)}; 86 const VAddr data_ptr{context.AddHeap(parameters.data)};
69 const VAddr configuration_ptr{context.AddHeap(configuration)}; 87 const VAddr configuration_ptr{context.AddHeap(configuration)};
70 88
71 context.CallFunction(callbacks.GenerateCode, return_ptr, cr1_out_ptr, cr2_out_ptr, 89 // The callback does not directly return a value, it only writes to the output pointer
90 context.CallFunction(callbacks.GenerateCode, ret_ptr, c0_out_ptr, c1_out_ptr,
72 configuration_ptr, parameters.command, input_ptr, input_buffer.size(), 91 configuration_ptr, parameters.command, input_ptr, input_buffer.size(),
73 cr1_in_ptr, cr2_in_ptr, data_ptr, parameters.data_size, output_ptr, 92 c0_in_ptr, c1_in_ptr, data_ptr, parameters.data_size, output_ptr,
74 output_buffer.size()); 93 output_buffer.size());
75 94
76 const s32 return_value{context.GetHeap<s32>(return_ptr)}; 95 const s32 return_value{context.GetHeap<s32>(ret_ptr)};
77 96
78 if (return_value == 0) { 97 if (return_value == 0) {
98 // The callback has written to the output executable code range,
99 // requiring an instruction cache invalidation
79 system.InvalidateCpuInstructionCacheRange(configuration.user_rx_memory.offset, 100 system.InvalidateCpuInstructionCacheRange(configuration.user_rx_memory.offset,
80 configuration.user_rx_memory.size); 101 configuration.user_rx_memory.size);
81 102
103 // Write back to the IPC output buffer, if provided
82 if (ctx.CanWriteBuffer()) { 104 if (ctx.CanWriteBuffer()) {
83 context.GetHeap(output_ptr, output_buffer.data(), output_buffer.size()); 105 context.GetHeap(output_ptr, output_buffer.data(), output_buffer.size());
84 ctx.WriteBuffer(output_buffer.data(), output_buffer.size()); 106 ctx.WriteBuffer(output_buffer.data(), output_buffer.size());
85 } 107 }
86 const auto cr1_out{context.GetHeap<CodeRange>(cr1_out_ptr)}; 108
87 const auto cr2_out{context.GetHeap<CodeRange>(cr2_out_ptr)}; 109 const OutputParameters out{
110 .return_value = return_value,
111 .ranges =
112 {
113 context.GetHeap<CodeRange>(c0_out_ptr),
114 context.GetHeap<CodeRange>(c1_out_ptr),
115 },
116 };
88 117
89 IPC::ResponseBuilder rb{ctx, 8}; 118 IPC::ResponseBuilder rb{ctx, 8};
90 rb.Push(ResultSuccess); 119 rb.Push(ResultSuccess);
91 rb.Push<u64>(return_value); 120 rb.PushRaw(out);
92 rb.PushRaw(cr1_out);
93 rb.PushRaw(cr2_out);
94 } else { 121 } else {
95 LOG_WARNING(Service_JIT, "plugin GenerateCode callback failed"); 122 LOG_WARNING(Service_JIT, "plugin GenerateCode callback failed");
96 IPC::ResponseBuilder rb{ctx, 2}; 123 IPC::ResponseBuilder rb{ctx, 2};
@@ -99,25 +126,40 @@ public:
99 }; 126 };
100 127
101 void Control(Kernel::HLERequestContext& ctx) { 128 void Control(Kernel::HLERequestContext& ctx) {
129 LOG_DEBUG(Service_JIT, "called");
130
102 IPC::RequestParser rp{ctx}; 131 IPC::RequestParser rp{ctx};
103 const auto command{rp.PopRaw<u64>()}; 132 const auto command{rp.PopRaw<u64>()};
104 const auto input_buffer{ctx.ReadBuffer()}; 133
134 // Optional input/output buffers
135 std::vector<u8> input_buffer{ctx.CanReadBuffer() ? ctx.ReadBuffer() : std::vector<u8>()};
105 std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0); 136 std::vector<u8> output_buffer(ctx.CanWriteBuffer() ? ctx.GetWriteBufferSize() : 0);
106 137
107 const VAddr return_ptr{context.AddHeap(0u)}; 138 // Function call prototype:
139 // u64 Control(s32* ret, JITConfiguration* cfg, u64 cmd, u8* input_buf, size_t input_size,
140 // u8* output_buf, size_t output_size);
141 //
142 // This function is used to set up the state of the plugin before code generation, generally
143 // passing objects like pointers to VM state from the game. It is usually called once.
144
145 const VAddr ret_ptr{context.AddHeap(0u)};
108 const VAddr configuration_ptr{context.AddHeap(configuration)}; 146 const VAddr configuration_ptr{context.AddHeap(configuration)};
109 const VAddr input_ptr{context.AddHeap(input_buffer.data(), input_buffer.size())}; 147 const VAddr input_ptr{context.AddHeap(input_buffer.data(), input_buffer.size())};
110 const VAddr output_ptr{context.AddHeap(output_buffer.data(), output_buffer.size())}; 148 const VAddr output_ptr{context.AddHeap(output_buffer.data(), output_buffer.size())};
111 const u64 wrapper_value{ 149
112 context.CallFunction(callbacks.Control, return_ptr, configuration_ptr, command, 150 const u64 wrapper_value{context.CallFunction(callbacks.Control, ret_ptr, configuration_ptr,
113 input_ptr, input_buffer.size(), output_ptr, output_buffer.size())}; 151 command, input_ptr, input_buffer.size(),
114 const s32 return_value{context.GetHeap<s32>(return_ptr)}; 152 output_ptr, output_buffer.size())};
153
154 const s32 return_value{context.GetHeap<s32>(ret_ptr)};
115 155
116 if (wrapper_value == 0 && return_value == 0) { 156 if (wrapper_value == 0 && return_value == 0) {
157 // Write back to the IPC output buffer, if provided
117 if (ctx.CanWriteBuffer()) { 158 if (ctx.CanWriteBuffer()) {
118 context.GetHeap(output_ptr, output_buffer.data(), output_buffer.size()); 159 context.GetHeap(output_ptr, output_buffer.data(), output_buffer.size());
119 ctx.WriteBuffer(output_buffer.data(), output_buffer.size()); 160 ctx.WriteBuffer(output_buffer.data(), output_buffer.size());
120 } 161 }
162
121 IPC::ResponseBuilder rb{ctx, 3}; 163 IPC::ResponseBuilder rb{ctx, 3};
122 rb.Push(ResultSuccess); 164 rb.Push(ResultSuccess);
123 rb.Push(return_value); 165 rb.Push(return_value);
@@ -129,8 +171,13 @@ public:
129 } 171 }
130 172
131 void LoadPlugin(Kernel::HLERequestContext& ctx) { 173 void LoadPlugin(Kernel::HLERequestContext& ctx) {
174 LOG_DEBUG(Service_JIT, "called");
175
132 IPC::RequestParser rp{ctx}; 176 IPC::RequestParser rp{ctx};
133 const auto tmem_size{rp.PopRaw<u64>()}; 177 const auto tmem_size{rp.PopRaw<u64>()};
178 const auto tmem_handle{ctx.GetCopyHandle(0)};
179 const auto nro_plugin{ctx.ReadBuffer(1)};
180
134 if (tmem_size == 0) { 181 if (tmem_size == 0) {
135 LOG_ERROR(Service_JIT, "attempted to load plugin with empty transfer memory"); 182 LOG_ERROR(Service_JIT, "attempted to load plugin with empty transfer memory");
136 IPC::ResponseBuilder rb{ctx, 2}; 183 IPC::ResponseBuilder rb{ctx, 2};
@@ -138,9 +185,7 @@ public:
138 return; 185 return;
139 } 186 }
140 187
141 const auto tmem_handle{ctx.GetCopyHandle(0)}; 188 auto tmem{process->GetHandleTable().GetObject<Kernel::KTransferMemory>(tmem_handle)};
142 auto tmem{system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
143 tmem_handle)};
144 if (tmem.IsNull()) { 189 if (tmem.IsNull()) {
145 LOG_ERROR(Service_JIT, "attempted to load plugin with invalid transfer memory handle"); 190 LOG_ERROR(Service_JIT, "attempted to load plugin with invalid transfer memory handle");
146 IPC::ResponseBuilder rb{ctx, 2}; 191 IPC::ResponseBuilder rb{ctx, 2};
@@ -148,24 +193,24 @@ public:
148 return; 193 return;
149 } 194 }
150 195
151 configuration.work_memory.offset = tmem->GetSourceAddress(); 196 // Set up the configuration with the required TransferMemory address
152 configuration.work_memory.size = tmem_size; 197 configuration.transfer_memory.offset = tmem->GetSourceAddress();
198 configuration.transfer_memory.size = tmem_size;
153 199
154 const auto nro_plugin{ctx.ReadBuffer(1)}; 200 // Gather up all the callbacks from the loaded plugin
155 auto symbols{Core::Symbols::GetSymbols(nro_plugin, true)}; 201 auto symbols{Core::Symbols::GetSymbols(nro_plugin, true)};
156 const auto GetSymbol{[&](std::string name) { return symbols[name].first; }}; 202 const auto GetSymbol{[&](const std::string& name) { return symbols[name].first; }};
157 203
158 callbacks = 204 callbacks.rtld_fini = GetSymbol("_fini");
159 GuestCallbacks{.rtld_fini = GetSymbol("_fini"), 205 callbacks.rtld_init = GetSymbol("_init");
160 .rtld_init = GetSymbol("_init"), 206 callbacks.Control = GetSymbol("nnjitpluginControl");
161 .Control = GetSymbol("nnjitpluginControl"), 207 callbacks.ResolveBasicSymbols = GetSymbol("nnjitpluginResolveBasicSymbols");
162 .ResolveBasicSymbols = GetSymbol("nnjitpluginResolveBasicSymbols"), 208 callbacks.SetupDiagnostics = GetSymbol("nnjitpluginSetupDiagnostics");
163 .SetupDiagnostics = GetSymbol("nnjitpluginSetupDiagnostics"), 209 callbacks.Configure = GetSymbol("nnjitpluginConfigure");
164 .Configure = GetSymbol("nnjitpluginConfigure"), 210 callbacks.GenerateCode = GetSymbol("nnjitpluginGenerateCode");
165 .GenerateCode = GetSymbol("nnjitpluginGenerateCode"), 211 callbacks.GetVersion = GetSymbol("nnjitpluginGetVersion");
166 .GetVersion = GetSymbol("nnjitpluginGetVersion"), 212 callbacks.OnPrepared = GetSymbol("nnjitpluginOnPrepared");
167 .Keeper = GetSymbol("nnjitpluginKeeper"), 213 callbacks.Keeper = GetSymbol("nnjitpluginKeeper");
168 .OnPrepared = GetSymbol("nnjitpluginOnPrepared")};
169 214
170 if (callbacks.GetVersion == 0 || callbacks.Configure == 0 || callbacks.GenerateCode == 0 || 215 if (callbacks.GetVersion == 0 || callbacks.Configure == 0 || callbacks.GenerateCode == 0 ||
171 callbacks.OnPrepared == 0) { 216 callbacks.OnPrepared == 0) {
@@ -186,12 +231,16 @@ public:
186 configuration.sys_ro_memory.size); 231 configuration.sys_ro_memory.size);
187 context.MapProcessMemory(configuration.sys_rx_memory.offset, 232 context.MapProcessMemory(configuration.sys_rx_memory.offset,
188 configuration.sys_rx_memory.size); 233 configuration.sys_rx_memory.size);
189 context.MapProcessMemory(configuration.work_memory.offset, configuration.work_memory.size); 234 context.MapProcessMemory(configuration.transfer_memory.offset,
235 configuration.transfer_memory.size);
190 236
237 // Run ELF constructors, if needed
191 if (callbacks.rtld_init != 0) { 238 if (callbacks.rtld_init != 0) {
192 context.CallFunction(callbacks.rtld_init); 239 context.CallFunction(callbacks.rtld_init);
193 } 240 }
194 241
242 // Function prototype:
243 // u64 GetVersion();
195 const auto version{context.CallFunction(callbacks.GetVersion)}; 244 const auto version{context.CallFunction(callbacks.GetVersion)};
196 if (version != 1) { 245 if (version != 1) {
197 LOG_ERROR(Service_JIT, "unknown plugin version {}", version); 246 LOG_ERROR(Service_JIT, "unknown plugin version {}", version);
@@ -200,16 +249,26 @@ public:
200 return; 249 return;
201 } 250 }
202 251
252 // Function prototype:
253 // void ResolveBasicSymbols(void (*resolver)(const char* name));
203 const auto resolve{context.GetHelper("_resolve")}; 254 const auto resolve{context.GetHelper("_resolve")};
204 if (callbacks.ResolveBasicSymbols != 0) { 255 if (callbacks.ResolveBasicSymbols != 0) {
205 context.CallFunction(callbacks.ResolveBasicSymbols, resolve); 256 context.CallFunction(callbacks.ResolveBasicSymbols, resolve);
206 } 257 }
258
259 // Function prototype:
260 // void SetupDiagnostics(u32 enabled, void (**resolver)(const char* name));
207 const auto resolve_ptr{context.AddHeap(resolve)}; 261 const auto resolve_ptr{context.AddHeap(resolve)};
208 if (callbacks.SetupDiagnostics != 0) { 262 if (callbacks.SetupDiagnostics != 0) {
209 context.CallFunction(callbacks.SetupDiagnostics, 0u, resolve_ptr); 263 context.CallFunction(callbacks.SetupDiagnostics, 0u, resolve_ptr);
210 } 264 }
211 265
212 context.CallFunction(callbacks.Configure, 0u); 266 // Function prototype:
267 // void Configure(u32* memory_flags);
268 context.CallFunction(callbacks.Configure, 0ull);
269
270 // Function prototype:
271 // void OnPrepared(JITConfiguration* cfg);
213 const auto configuration_ptr{context.AddHeap(configuration)}; 272 const auto configuration_ptr{context.AddHeap(configuration)};
214 context.CallFunction(callbacks.OnPrepared, configuration_ptr); 273 context.CallFunction(callbacks.OnPrepared, configuration_ptr);
215 274
@@ -218,6 +277,8 @@ public:
218 } 277 }
219 278
220 void GetCodeAddress(Kernel::HLERequestContext& ctx) { 279 void GetCodeAddress(Kernel::HLERequestContext& ctx) {
280 LOG_DEBUG(Service_JIT, "called");
281
221 IPC::ResponseBuilder rb{ctx, 6}; 282 IPC::ResponseBuilder rb{ctx, 6};
222 rb.Push(ResultSuccess); 283 rb.Push(ResultSuccess);
223 rb.Push(configuration.user_rx_memory.offset); 284 rb.Push(configuration.user_rx_memory.offset);
@@ -243,11 +304,17 @@ private:
243 struct JITConfiguration { 304 struct JITConfiguration {
244 CodeRange user_rx_memory; 305 CodeRange user_rx_memory;
245 CodeRange user_ro_memory; 306 CodeRange user_ro_memory;
246 CodeRange work_memory; 307 CodeRange transfer_memory;
247 CodeRange sys_rx_memory; 308 CodeRange sys_rx_memory;
248 CodeRange sys_ro_memory; 309 CodeRange sys_ro_memory;
249 }; 310 };
250 311
312 static CodeRange ClearSize(CodeRange in) {
313 in.size = 0;
314 return in;
315 }
316
317 Kernel::KScopedAutoObject<Kernel::KProcess> process;
251 GuestCallbacks callbacks; 318 GuestCallbacks callbacks;
252 JITConfiguration configuration; 319 JITConfiguration configuration;
253 JITContext context; 320 JITContext context;
@@ -275,8 +342,9 @@ public:
275 342
276 IPC::RequestParser rp{ctx}; 343 IPC::RequestParser rp{ctx};
277 const auto parameters{rp.PopRaw<Parameters>()}; 344 const auto parameters{rp.PopRaw<Parameters>()};
278 const auto executable_mem_handle{ctx.GetCopyHandle(1)}; 345 const auto process_handle{ctx.GetCopyHandle(0)};
279 const auto readable_mem_handle{ctx.GetCopyHandle(2)}; 346 const auto rx_mem_handle{ctx.GetCopyHandle(1)};
347 const auto ro_mem_handle{ctx.GetCopyHandle(2)};
280 348
281 if (parameters.rx_size == 0 || parameters.ro_size == 0) { 349 if (parameters.rx_size == 0 || parameters.ro_size == 0) {
282 LOG_ERROR(Service_JIT, "attempted to init with empty code regions"); 350 LOG_ERROR(Service_JIT, "attempted to init with empty code regions");
@@ -285,42 +353,47 @@ public:
285 return; 353 return;
286 } 354 }
287 355
288 // The copy handle at index 0 is the process handle, but handle tables are 356 // Fetch using the handle table for the current process here,
289 // per-process, so there is no point reading it here until we are multiprocess 357 // since we are not multiprocess yet.
290 const auto& process{*system.CurrentProcess()}; 358 const auto& handle_table{system.CurrentProcess()->GetHandleTable()};
359
360 auto process{handle_table.GetObject<Kernel::KProcess>(process_handle)};
361 if (process.IsNull()) {
362 LOG_ERROR(Service_JIT, "process is null for handle=0x{:08X}", process_handle);
363 IPC::ResponseBuilder rb{ctx, 2};
364 rb.Push(ResultUnknown);
365 return;
366 }
291 367
292 auto executable_mem{ 368 auto rx_mem{handle_table.GetObject<Kernel::KCodeMemory>(rx_mem_handle)};
293 process.GetHandleTable().GetObject<Kernel::KCodeMemory>(executable_mem_handle)}; 369 if (rx_mem.IsNull()) {
294 if (executable_mem.IsNull()) { 370 LOG_ERROR(Service_JIT, "rx_mem is null for handle=0x{:08X}", rx_mem_handle);
295 LOG_ERROR(Service_JIT, "executable_mem is null for handle=0x{:08X}",
296 executable_mem_handle);
297 IPC::ResponseBuilder rb{ctx, 2}; 371 IPC::ResponseBuilder rb{ctx, 2};
298 rb.Push(ResultUnknown); 372 rb.Push(ResultUnknown);
299 return; 373 return;
300 } 374 }
301 375
302 auto readable_mem{ 376 auto ro_mem{handle_table.GetObject<Kernel::KCodeMemory>(ro_mem_handle)};
303 process.GetHandleTable().GetObject<Kernel::KCodeMemory>(readable_mem_handle)}; 377 if (ro_mem.IsNull()) {
304 if (readable_mem.IsNull()) { 378 LOG_ERROR(Service_JIT, "ro_mem is null for handle=0x{:08X}", ro_mem_handle);
305 LOG_ERROR(Service_JIT, "readable_mem is null for handle=0x{:08X}", readable_mem_handle);
306 IPC::ResponseBuilder rb{ctx, 2}; 379 IPC::ResponseBuilder rb{ctx, 2};
307 rb.Push(ResultUnknown); 380 rb.Push(ResultUnknown);
308 return; 381 return;
309 } 382 }
310 383
311 const CodeRange user_rx{ 384 const CodeRange user_rx{
312 .offset = executable_mem->GetSourceAddress(), 385 .offset = rx_mem->GetSourceAddress(),
313 .size = parameters.rx_size, 386 .size = parameters.rx_size,
314 }; 387 };
315 388
316 const CodeRange user_ro{ 389 const CodeRange user_ro{
317 .offset = readable_mem->GetSourceAddress(), 390 .offset = ro_mem->GetSourceAddress(),
318 .size = parameters.ro_size, 391 .size = parameters.ro_size,
319 }; 392 };
320 393
321 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 394 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
322 rb.Push(ResultSuccess); 395 rb.Push(ResultSuccess);
323 rb.PushIpcInterface<IJitEnvironment>(system, user_rx, user_ro); 396 rb.PushIpcInterface<IJitEnvironment>(system, *process, user_rx, user_ro);
324 } 397 }
325}; 398};
326 399
diff --git a/src/core/hle/service/jit/jit_context.cpp b/src/core/hle/service/jit/jit_context.cpp
index 17e58131c..19bd85b6c 100644
--- a/src/core/hle/service/jit/jit_context.cpp
+++ b/src/core/hle/service/jit/jit_context.cpp
@@ -17,61 +17,15 @@
17 17
18namespace Service::JIT { 18namespace Service::JIT {
19 19
20constexpr std::array<u8, 4> STOP_ARM64 = { 20constexpr std::array<u8, 8> SVC0_ARM64 = {
21 0x01, 0x00, 0x00, 0xd4, // svc #0 21 0x01, 0x00, 0x00, 0xd4, // svc #0
22};
23
24constexpr std::array<u8, 8> RESOLVE_ARM64 = {
25 0x21, 0x00, 0x00, 0xd4, // svc #1
26 0xc0, 0x03, 0x5f, 0xd6, // ret 22 0xc0, 0x03, 0x5f, 0xd6, // ret
27}; 23};
28 24
29constexpr std::array<u8, 4> PANIC_ARM64 = { 25constexpr std::array HELPER_FUNCTIONS{
30 0x41, 0x00, 0x00, 0xd4, // svc #2 26 "_stop", "_resolve", "_panic", "memcpy", "memmove", "memset",
31};
32
33constexpr std::array<u8, 60> MEMMOVE_ARM64 = {
34 0x1f, 0x00, 0x01, 0xeb, // cmp x0, x1
35 0x83, 0x01, 0x00, 0x54, // b.lo #+34
36 0x42, 0x04, 0x00, 0xd1, // sub x2, x2, 1
37 0x22, 0x01, 0xf8, 0xb7, // tbnz x2, #63, #+36
38 0x23, 0x68, 0x62, 0x38, // ldrb w3, [x1, x2]
39 0x03, 0x68, 0x22, 0x38, // strb w3, [x0, x2]
40 0xfc, 0xff, 0xff, 0x17, // b #-16
41 0x24, 0x68, 0x63, 0x38, // ldrb w4, [x1, x3]
42 0x04, 0x68, 0x23, 0x38, // strb w4, [x0, x3]
43 0x63, 0x04, 0x00, 0x91, // add x3, x3, 1
44 0x7f, 0x00, 0x02, 0xeb, // cmp x3, x2
45 0x8b, 0xff, 0xff, 0x54, // b.lt #-16
46 0xc0, 0x03, 0x5f, 0xd6, // ret
47 0x03, 0x00, 0x80, 0xd2, // mov x3, 0
48 0xfc, 0xff, 0xff, 0x17, // b #-16
49}; 27};
50 28
51constexpr std::array<u8, 28> MEMSET_ARM64 = {
52 0x03, 0x00, 0x80, 0xd2, // mov x3, 0
53 0x7f, 0x00, 0x02, 0xeb, // cmp x3, x2
54 0x4b, 0x00, 0x00, 0x54, // b.lt #+8
55 0xc0, 0x03, 0x5f, 0xd6, // ret
56 0x01, 0x68, 0x23, 0x38, // strb w1, [x0, x3]
57 0x63, 0x04, 0x00, 0x91, // add x3, x3, 1
58 0xfb, 0xff, 0xff, 0x17, // b #-20
59};
60
61struct HelperFunction {
62 const char* name;
63 const std::span<const u8> data;
64};
65
66constexpr std::array<HelperFunction, 6> HELPER_FUNCTIONS{{
67 {"_stop", STOP_ARM64},
68 {"_resolve", RESOLVE_ARM64},
69 {"_panic", PANIC_ARM64},
70 {"memcpy", MEMMOVE_ARM64},
71 {"memmove", MEMMOVE_ARM64},
72 {"memset", MEMSET_ARM64},
73}};
74
75struct Elf64_Dyn { 29struct Elf64_Dyn {
76 u64 d_tag; 30 u64 d_tag;
77 u64 d_un; 31 u64 d_un;
@@ -224,17 +178,24 @@ public:
224 InsertHelperFunctions(); 178 InsertHelperFunctions();
225 InsertStack(); 179 InsertStack();
226 return true; 180 return true;
227 } else {
228 return false;
229 } 181 }
182
183 return false;
230 } 184 }
231 185
232 bool FixupRelocations() { 186 bool FixupRelocations() {
187 // The loaded NRO file has ELF relocations that must be processed before it can run.
188 // Normally this would be processed by RTLD, but in HLE context, we don't have
189 // the linker available, so we have to do it ourselves.
190
233 const VAddr mod_offset{callbacks->MemoryRead32(4)}; 191 const VAddr mod_offset{callbacks->MemoryRead32(4)};
234 if (callbacks->MemoryRead32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) { 192 if (callbacks->MemoryRead32(mod_offset) != Common::MakeMagic('M', 'O', 'D', '0')) {
235 return false; 193 return false;
236 } 194 }
237 195
196 // For more info about dynamic entries, see the ELF ABI specification:
197 // https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html
198 // https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html
238 VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)}; 199 VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)};
239 VAddr rela_dyn = 0; 200 VAddr rela_dyn = 0;
240 size_t num_rela = 0; 201 size_t num_rela = 0;
@@ -266,13 +227,15 @@ public:
266 } 227 }
267 228
268 void InsertHelperFunctions() { 229 void InsertHelperFunctions() {
269 for (const auto& [name, contents] : HELPER_FUNCTIONS) { 230 for (const auto& name : HELPER_FUNCTIONS) {
270 helpers[name] = local_memory.size(); 231 helpers[name] = local_memory.size();
271 local_memory.insert(local_memory.end(), contents.begin(), contents.end()); 232 local_memory.insert(local_memory.end(), SVC0_ARM64.begin(), SVC0_ARM64.end());
272 } 233 }
273 } 234 }
274 235
275 void InsertStack() { 236 void InsertStack() {
237 // Allocate enough space to avoid any reasonable risk of
238 // overflowing the stack during plugin execution
276 const u64 pad_amount{Common::AlignUp(local_memory.size(), STACK_ALIGN) - 239 const u64 pad_amount{Common::AlignUp(local_memory.size(), STACK_ALIGN) -
277 local_memory.size()}; 240 local_memory.size()};
278 local_memory.insert(local_memory.end(), 0x10000 + pad_amount, 0); 241 local_memory.insert(local_memory.end(), 0x10000 + pad_amount, 0);
@@ -292,9 +255,21 @@ public:
292 } 255 }
293 256
294 void SetupArguments() { 257 void SetupArguments() {
258 // The first 8 integer registers are used for the first 8 integer
259 // arguments. Floating-point arguments are not handled at this time.
260 //
261 // If a function takes more than 8 arguments, then stack space is reserved
262 // for the remaining arguments, and the remaining arguments are inserted in
263 // ascending memory order, each argument aligned to an 8-byte boundary. The
264 // stack pointer must remain aligned to 16 bytes.
265 //
266 // For more info, see the AArch64 ABI PCS:
267 // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
268
295 for (size_t i = 0; i < 8 && i < argument_stack.size(); i++) { 269 for (size_t i = 0; i < 8 && i < argument_stack.size(); i++) {
296 jit->SetRegister(i, argument_stack[i]); 270 jit->SetRegister(i, argument_stack[i]);
297 } 271 }
272
298 if (argument_stack.size() > 8) { 273 if (argument_stack.size() > 8) {
299 const VAddr new_sp = Common::AlignDown( 274 const VAddr new_sp = Common::AlignDown(
300 top_of_stack - (argument_stack.size() - 8) * sizeof(u64), STACK_ALIGN); 275 top_of_stack - (argument_stack.size() - 8) * sizeof(u64), STACK_ALIGN);
@@ -303,6 +278,8 @@ public:
303 } 278 }
304 jit->SetSP(new_sp); 279 jit->SetSP(new_sp);
305 } 280 }
281
282 // Reset the call state for the next invocation
306 argument_stack.clear(); 283 argument_stack.clear();
307 heap_pointer = top_of_stack; 284 heap_pointer = top_of_stack;
308 } 285 }
@@ -322,11 +299,16 @@ public:
322 } 299 }
323 300
324 VAddr AddHeap(const void* data, size_t size) { 301 VAddr AddHeap(const void* data, size_t size) {
302 // Require all heap data types to have the same alignment as the
303 // stack pointer, for compatibility
325 const size_t num_bytes{Common::AlignUp(size, STACK_ALIGN)}; 304 const size_t num_bytes{Common::AlignUp(size, STACK_ALIGN)};
305
306 // Make additional memory space if required
326 if (heap_pointer + num_bytes > local_memory.size()) { 307 if (heap_pointer + num_bytes > local_memory.size()) {
327 local_memory.insert(local_memory.end(), 308 local_memory.insert(local_memory.end(),
328 (heap_pointer + num_bytes) - local_memory.size(), 0); 309 (heap_pointer + num_bytes) - local_memory.size(), 0);
329 } 310 }
311
330 const VAddr location{heap_pointer}; 312 const VAddr location{heap_pointer};
331 std::memcpy(local_memory.data() + location, data, size); 313 std::memcpy(local_memory.data() + location, data, size);
332 heap_pointer += num_bytes; 314 heap_pointer += num_bytes;
@@ -350,30 +332,67 @@ public:
350}; 332};
351 333
352void DynarmicCallbacks64::CallSVC(u32 swi) { 334void DynarmicCallbacks64::CallSVC(u32 swi) {
353 switch (swi) { 335 // Service calls are used to implement helper functionality.
354 case 0: 336 //
337 // The most important of these is the _stop helper, which transfers control
338 // from the plugin back to HLE context to return a value. However, a few more
339 // are also implemented to reduce the need for direct ARM implementations of
340 // basic functionality, like memory operations.
341 //
342 // When we receive a helper request, the swi number will be zero, and the call
343 // will have originated from an address we know is a helper function. Otherwise,
344 // the plugin may be trying to issue a service call, which we shouldn't handle.
345
346 if (swi != 0) {
347 LOG_CRITICAL(Service_JIT, "plugin issued unknown service call {}", swi);
355 parent.jit->HaltExecution(); 348 parent.jit->HaltExecution();
356 break; 349 return;
350 }
351
352 u64 pc{parent.jit->GetPC() - 4};
353 auto& helpers{parent.helpers};
354
355 if (pc == helpers["memcpy"] || pc == helpers["memmove"]) {
356 const VAddr dest{parent.jit->GetRegister(0)};
357 const VAddr src{parent.jit->GetRegister(1)};
358 const size_t n{parent.jit->GetRegister(2)};
359
360 if (dest < src) {
361 for (size_t i = 0; i < n; i++) {
362 MemoryWrite8(dest + i, MemoryRead8(src + i));
363 }
364 } else {
365 for (size_t i = n; i > 0; i--) {
366 MemoryWrite8(dest + i - 1, MemoryRead8(src + i - 1));
367 }
368 }
369 } else if (pc == helpers["memset"]) {
370 const VAddr dest{parent.jit->GetRegister(0)};
371 const u64 c{parent.jit->GetRegister(1)};
372 const size_t n{parent.jit->GetRegister(2)};
357 373
358 case 1: { 374 for (size_t i = 0; i < n; i++) {
375 MemoryWrite8(dest + i, static_cast<u8>(c));
376 }
377 } else if (pc == helpers["_resolve"]) {
359 // X0 contains a char* for a symbol to resolve 378 // X0 contains a char* for a symbol to resolve
360 std::string name{MemoryReadCString(parent.jit->GetRegister(0))}; 379 const auto name{MemoryReadCString(parent.jit->GetRegister(0))};
361 const auto helper{parent.helpers[name]}; 380 const auto helper{helpers[name]};
362 381
363 if (helper != 0) { 382 if (helper != 0) {
364 parent.jit->SetRegister(0, helper); 383 parent.jit->SetRegister(0, helper);
365 } else { 384 } else {
366 LOG_WARNING(Service_JIT, "plugin requested unknown function {}", name); 385 LOG_WARNING(Service_JIT, "plugin requested unknown function {}", name);
367 parent.jit->SetRegister(0, parent.helpers["_panic"]); 386 parent.jit->SetRegister(0, helpers["_panic"]);
368 } 387 }
369 break; 388 } else if (pc == helpers["_stop"]) {
370 } 389 parent.jit->HaltExecution();
371 390 } else if (pc == helpers["_panic"]) {
372 case 2:
373 default:
374 LOG_CRITICAL(Service_JIT, "plugin panicked!"); 391 LOG_CRITICAL(Service_JIT, "plugin panicked!");
375 parent.jit->HaltExecution(); 392 parent.jit->HaltExecution();
376 break; 393 } else {
394 LOG_CRITICAL(Service_JIT, "plugin issued syscall at unknown address 0x{:x}", pc);
395 parent.jit->HaltExecution();
377 } 396 }
378} 397}
379 398
diff --git a/src/core/hle/service/jit/jit_context.h b/src/core/hle/service/jit/jit_context.h
index 3cb935e3c..f17fc5e24 100644
--- a/src/core/hle/service/jit/jit_context.h
+++ b/src/core/hle/service/jit/jit_context.h
@@ -28,6 +28,7 @@ public:
28 template <typename T, typename... Ts> 28 template <typename T, typename... Ts>
29 u64 CallFunction(VAddr func, T argument, Ts... rest) { 29 u64 CallFunction(VAddr func, T argument, Ts... rest) {
30 static_assert(std::is_trivially_copyable_v<T>); 30 static_assert(std::is_trivially_copyable_v<T>);
31 static_assert(!std::is_floating_point_v<T>);
31 PushArgument(&argument, sizeof(argument)); 32 PushArgument(&argument, sizeof(argument));
32 33
33 if constexpr (sizeof...(rest) > 0) { 34 if constexpr (sizeof...(rest) > 0) {