Просмотр исходного кода

Use different timing for motion

german 5 лет назад
Родитель
Сommit
ddff03cff5

+ 4 - 0
src/core/hle/service/hid/controllers/controller_base.h

@@ -31,6 +31,10 @@ public:
     virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
     virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
                           std::size_t size) = 0;
                           std::size_t size) = 0;
 
 
+    // When the controller is requesting a motion update for the shared memory
+    virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
+                                std::size_t size) {}
+
     // Called when input devices should be loaded
     // Called when input devices should be loaded
     virtual void OnLoadInputDevices() = 0;
     virtual void OnLoadInputDevices() = 0;
 
 

+ 129 - 73
src/core/hle/service/hid/controllers/npad.cpp

@@ -365,6 +365,135 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
         }
         }
         const u32 npad_index = static_cast<u32>(i);
         const u32 npad_index = static_cast<u32>(i);
 
 
+        RequestPadStateUpdate(npad_index);
+        auto& pad_state = npad_pad_states[npad_index];
+
+        auto& main_controller =
+            npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
+        auto& handheld_entry =
+            npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
+        auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
+        auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
+        auto& right_entry =
+            npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
+        auto& pokeball_entry =
+            npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
+        auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
+
+        libnx_entry.connection_status.raw = 0;
+        libnx_entry.connection_status.IsConnected.Assign(1);
+        auto& full_sixaxis_entry =
+            npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
+        auto& handheld_sixaxis_entry =
+            npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
+        auto& dual_left_sixaxis_entry =
+            npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
+        auto& dual_right_sixaxis_entry =
+            npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
+        auto& left_sixaxis_entry =
+            npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
+        auto& right_sixaxis_entry =
+            npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
+
+        switch (controller_type) {
+        case NPadControllerType::None:
+            UNREACHABLE();
+            break;
+        case NPadControllerType::ProController:
+            main_controller.connection_status.raw = 0;
+            main_controller.connection_status.IsConnected.Assign(1);
+            main_controller.connection_status.IsWired.Assign(1);
+            main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
+            main_controller.pad.l_stick = pad_state.l_stick;
+            main_controller.pad.r_stick = pad_state.r_stick;
+
+            libnx_entry.connection_status.IsWired.Assign(1);
+            break;
+        case NPadControllerType::Handheld:
+            handheld_entry.connection_status.raw = 0;
+            handheld_entry.connection_status.IsConnected.Assign(1);
+            handheld_entry.connection_status.IsWired.Assign(1);
+            handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
+            handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
+            handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
+            handheld_entry.connection_status.IsRightJoyWired.Assign(1);
+            handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
+            handheld_entry.pad.l_stick = pad_state.l_stick;
+            handheld_entry.pad.r_stick = pad_state.r_stick;
+
+            libnx_entry.connection_status.IsWired.Assign(1);
+            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
+            libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
+            libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
+            libnx_entry.connection_status.IsRightJoyWired.Assign(1);
+            break;
+        case NPadControllerType::JoyDual:
+            dual_entry.connection_status.raw = 0;
+            dual_entry.connection_status.IsConnected.Assign(1);
+            dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
+            dual_entry.connection_status.IsRightJoyConnected.Assign(1);
+            dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
+            dual_entry.pad.l_stick = pad_state.l_stick;
+            dual_entry.pad.r_stick = pad_state.r_stick;
+
+            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
+            libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
+            break;
+        case NPadControllerType::JoyLeft:
+            left_entry.connection_status.raw = 0;
+            left_entry.connection_status.IsConnected.Assign(1);
+            left_entry.connection_status.IsLeftJoyConnected.Assign(1);
+            left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
+            left_entry.pad.l_stick = pad_state.l_stick;
+            left_entry.pad.r_stick = pad_state.r_stick;
+
+            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
+            break;
+        case NPadControllerType::JoyRight:
+            right_entry.connection_status.raw = 0;
+            right_entry.connection_status.IsConnected.Assign(1);
+            right_entry.connection_status.IsRightJoyConnected.Assign(1);
+            right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
+            right_entry.pad.l_stick = pad_state.l_stick;
+            right_entry.pad.r_stick = pad_state.r_stick;
+
+            libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
+            break;
+        case NPadControllerType::Pokeball:
+            pokeball_entry.connection_status.raw = 0;
+            pokeball_entry.connection_status.IsConnected.Assign(1);
+            pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
+            pokeball_entry.pad.l_stick = pad_state.l_stick;
+            pokeball_entry.pad.r_stick = pad_state.r_stick;
+            break;
+        }
+
+        // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
+        // any controllers.
+        libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
+        libnx_entry.pad.l_stick = pad_state.l_stick;
+        libnx_entry.pad.r_stick = pad_state.r_stick;
+
+        press_state |= static_cast<u32>(pad_state.pad_states.raw);
+    }
+    std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
+                shared_memory_entries.size() * sizeof(NPadEntry));
+}
+
+void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
+                                     std::size_t data_len) {
+    if (!IsControllerActivated()) {
+        return;
+    }
+    for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
+        auto& npad = shared_memory_entries[i];
+
+        const auto& controller_type = connected_controllers[i].type;
+
+        if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
+            continue;
+        }
+
         const std::array<SixAxisGeneric*, 6> controller_sixaxes{
         const std::array<SixAxisGeneric*, 6> controller_sixaxes{
             &npad.sixaxis_full,       &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
             &npad.sixaxis_full,       &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
             &npad.sixaxis_dual_right, &npad.sixaxis_left,     &npad.sixaxis_right,
             &npad.sixaxis_dual_right, &npad.sixaxis_left,     &npad.sixaxis_right,
@@ -403,9 +532,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             }
             }
         }
         }
 
 
-        RequestPadStateUpdate(npad_index);
-        auto& pad_state = npad_pad_states[npad_index];
-
         auto& main_controller =
         auto& main_controller =
             npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
             npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
         auto& handheld_entry =
         auto& handheld_entry =
@@ -418,8 +544,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
             npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
         auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
         auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
 
 
-        libnx_entry.connection_status.raw = 0;
-        libnx_entry.connection_status.IsConnected.Assign(1);
         auto& full_sixaxis_entry =
         auto& full_sixaxis_entry =
             npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
             npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
         auto& handheld_sixaxis_entry =
         auto& handheld_sixaxis_entry =
@@ -438,15 +562,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             UNREACHABLE();
             UNREACHABLE();
             break;
             break;
         case NPadControllerType::ProController:
         case NPadControllerType::ProController:
-            main_controller.connection_status.raw = 0;
-            main_controller.connection_status.IsConnected.Assign(1);
-            main_controller.connection_status.IsWired.Assign(1);
-            main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
-            main_controller.pad.l_stick = pad_state.l_stick;
-            main_controller.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.IsWired.Assign(1);
-
             if (sixaxis_sensors_enabled && motions[i][0]) {
             if (sixaxis_sensors_enabled && motions[i][0]) {
                 full_sixaxis_entry.accel = motion_devices[0].accel;
                 full_sixaxis_entry.accel = motion_devices[0].accel;
                 full_sixaxis_entry.gyro = motion_devices[0].gyro;
                 full_sixaxis_entry.gyro = motion_devices[0].gyro;
@@ -455,23 +570,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             }
             }
             break;
             break;
         case NPadControllerType::Handheld:
         case NPadControllerType::Handheld:
-            handheld_entry.connection_status.raw = 0;
-            handheld_entry.connection_status.IsConnected.Assign(1);
-            handheld_entry.connection_status.IsWired.Assign(1);
-            handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
-            handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
-            handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
-            handheld_entry.connection_status.IsRightJoyWired.Assign(1);
-            handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            handheld_entry.pad.l_stick = pad_state.l_stick;
-            handheld_entry.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.IsWired.Assign(1);
-            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
-            libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
-            libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
-            libnx_entry.connection_status.IsRightJoyWired.Assign(1);
-
             if (sixaxis_sensors_enabled && motions[i][0]) {
             if (sixaxis_sensors_enabled && motions[i][0]) {
                 handheld_sixaxis_entry.accel = motion_devices[0].accel;
                 handheld_sixaxis_entry.accel = motion_devices[0].accel;
                 handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
                 handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
@@ -480,17 +578,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             }
             }
             break;
             break;
         case NPadControllerType::JoyDual:
         case NPadControllerType::JoyDual:
-            dual_entry.connection_status.raw = 0;
-            dual_entry.connection_status.IsConnected.Assign(1);
-            dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
-            dual_entry.connection_status.IsRightJoyConnected.Assign(1);
-            dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            dual_entry.pad.l_stick = pad_state.l_stick;
-            dual_entry.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
-            libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
-
             if (sixaxis_sensors_enabled && motions[i][0]) {
             if (sixaxis_sensors_enabled && motions[i][0]) {
                 // Set motion for the left joycon
                 // Set motion for the left joycon
                 dual_left_sixaxis_entry.accel = motion_devices[0].accel;
                 dual_left_sixaxis_entry.accel = motion_devices[0].accel;
@@ -507,15 +594,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             }
             }
             break;
             break;
         case NPadControllerType::JoyLeft:
         case NPadControllerType::JoyLeft:
-            left_entry.connection_status.raw = 0;
-            left_entry.connection_status.IsConnected.Assign(1);
-            left_entry.connection_status.IsLeftJoyConnected.Assign(1);
-            left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            left_entry.pad.l_stick = pad_state.l_stick;
-            left_entry.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
-
             if (sixaxis_sensors_enabled && motions[i][0]) {
             if (sixaxis_sensors_enabled && motions[i][0]) {
                 left_sixaxis_entry.accel = motion_devices[0].accel;
                 left_sixaxis_entry.accel = motion_devices[0].accel;
                 left_sixaxis_entry.gyro = motion_devices[0].gyro;
                 left_sixaxis_entry.gyro = motion_devices[0].gyro;
@@ -524,15 +602,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             }
             }
             break;
             break;
         case NPadControllerType::JoyRight:
         case NPadControllerType::JoyRight:
-            right_entry.connection_status.raw = 0;
-            right_entry.connection_status.IsConnected.Assign(1);
-            right_entry.connection_status.IsRightJoyConnected.Assign(1);
-            right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            right_entry.pad.l_stick = pad_state.l_stick;
-            right_entry.pad.r_stick = pad_state.r_stick;
-
-            libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
-
             if (sixaxis_sensors_enabled && motions[i][1]) {
             if (sixaxis_sensors_enabled && motions[i][1]) {
                 right_sixaxis_entry.accel = motion_devices[1].accel;
                 right_sixaxis_entry.accel = motion_devices[1].accel;
                 right_sixaxis_entry.gyro = motion_devices[1].gyro;
                 right_sixaxis_entry.gyro = motion_devices[1].gyro;
@@ -541,21 +610,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
             }
             }
             break;
             break;
         case NPadControllerType::Pokeball:
         case NPadControllerType::Pokeball:
-            pokeball_entry.connection_status.raw = 0;
-            pokeball_entry.connection_status.IsConnected.Assign(1);
-            pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-            pokeball_entry.pad.l_stick = pad_state.l_stick;
-            pokeball_entry.pad.r_stick = pad_state.r_stick;
             break;
             break;
         }
         }
-
-        // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
-        // any controllers.
-        libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
-        libnx_entry.pad.l_stick = pad_state.l_stick;
-        libnx_entry.pad.r_stick = pad_state.r_stick;
-
-        press_state |= static_cast<u32>(pad_state.pad_states.raw);
     }
     }
     std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
     std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
                 shared_memory_entries.size() * sizeof(NPadEntry));
                 shared_memory_entries.size() * sizeof(NPadEntry));

+ 4 - 0
src/core/hle/service/hid/controllers/npad.h

@@ -32,6 +32,10 @@ public:
     // When the controller is requesting an update for the shared memory
     // When the controller is requesting an update for the shared memory
     void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
     void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 
 
+    // When the controller is requesting a motion update for the shared memory
+    void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
+                        std::size_t size) override;
+
     // Called when input devices should be loaded
     // Called when input devices should be loaded
     void OnLoadInputDevices() override;
     void OnLoadInputDevices() override;
 
 

+ 18 - 3
src/core/hle/service/hid/hid.cpp

@@ -40,7 +40,8 @@ namespace Service::HID {
 // Updating period for each HID device.
 // Updating period for each HID device.
 // HID is polled every 15ms, this value was derived from
 // HID is polled every 15ms, this value was derived from
 // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet
 // https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet
-constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz)
+constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000};         // (1ms, 1000Hz)
+constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz)
 constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
 constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
 
 
 IAppletResource::IAppletResource(Core::System& system)
 IAppletResource::IAppletResource(Core::System& system)
@@ -79,10 +80,14 @@ IAppletResource::IAppletResource(Core::System& system)
         [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
         [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
             UpdateControllers(user_data, ns_late);
             UpdateControllers(user_data, ns_late);
         });
         });
-
-    // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
+    motion_update_event = Core::Timing::CreateEvent(
+        "HID::MotionPadCallback",
+        [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+            UpdateMotion(user_data, ns_late);
+        });
 
 
     system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
     system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
+    system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event);
 
 
     ReloadInputDevices();
     ReloadInputDevices();
 }
 }
@@ -122,6 +127,16 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,
     core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
     core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event);
 }
 }
 
 
+void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
+    auto& core_timing = system.CoreTiming();
+
+    for (const auto& controller : controllers) {
+        controller->OnMotionUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
+    }
+
+    core_timing.ScheduleEvent(motion_update_ns - ns_late, motion_update_event);
+}
+
 class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
 class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
 public:
 public:
     IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") {
     IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") {

+ 2 - 0
src/core/hle/service/hid/hid.h

@@ -65,10 +65,12 @@ private:
 
 
     void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
     void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx);
     void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
     void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
+    void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 
 
     std::shared_ptr<Kernel::SharedMemory> shared_mem;
     std::shared_ptr<Kernel::SharedMemory> shared_mem;
 
 
     std::shared_ptr<Core::Timing::EventType> pad_update_event;
     std::shared_ptr<Core::Timing::EventType> pad_update_event;
+    std::shared_ptr<Core::Timing::EventType> motion_update_event;
     Core::System& system;
     Core::System& system;
 
 
     std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>
     std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)>