vibration

This commit is contained in:
Narr the Reg
2023-12-31 13:07:29 -06:00
parent 94d1a9c761
commit 919b8fa000
17 changed files with 319 additions and 166 deletions

View File

@@ -12,7 +12,7 @@ class System;
}
namespace Service::HID {
class AppletResourceHolder;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;

View File

@@ -10,7 +10,7 @@
namespace Service::HID {
struct NpadSharedMemoryEntry;
class AppletResourceHolder;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;

View File

@@ -12,7 +12,7 @@ class System;
}
namespace Service::HID {
class AppletResourceHolder;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;

View File

@@ -8,7 +8,7 @@
#include "core/hle/result.h"
namespace Service::HID {
class IAbstractedPad;
struct IAbstractedPad;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;

View File

@@ -13,7 +13,7 @@
#include "core/hle/service/hid/controllers/types/npad_types.h"
namespace Service::HID {
class IAbstractedPad;
struct IAbstractedPad;
struct AbstracAssignmentHolder {
IAbstractedPad* abstracted_pad;

View File

@@ -10,7 +10,7 @@
namespace Service::HID {
struct NpadSharedMemoryEntry;
class AppletResourceHolder;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
struct ColorProperties {

View File

@@ -9,7 +9,7 @@
namespace Service::HID {
class SixAxisResource;
class AppletResourceHolder;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;

View File

@@ -10,7 +10,7 @@
#include "core/hle/result.h"
namespace Service::HID {
class AppletResourceHolder;
struct AppletResourceHolder;
class NpadAbstractedPadHolder;
class NpadAbstractPropertiesHandler;
class NpadGcVibrationDevice;

View File

@@ -11,7 +11,6 @@
#include "core/hle/service/hid/controllers/abstract/abstract_vibration_handler.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/controllers/npad/unique_pad.h"
#include "core/hle/service/hid/controllers/npad/vibration_handler.h"
#include "core/hle/service/hid/controllers/types/npad_types.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid_util.h"

View File

@@ -14,6 +14,7 @@
#include "core/hle/service/hid/controllers/npad/assignment_handler.h"
#include "core/hle/service/hid/controllers/npad/npad_resource.h"
#include "core/hle/service/hid/controllers/npad/palma_handler.h"
#include "core/hle/service/hid/controllers/npad/vibration_handler.h"
#include "core/hle/service/hid/controllers/types/npad_types.h"
namespace Kernel {
@@ -31,7 +32,7 @@ class UniquePads;
class UniquePadResource;
class NpadVibrationHandler;
class NpadHighestBattery;
class AppletResourceHolder;
struct AppletResourceHolder;
class NpadAppletResource;
class NpadN64VibrationDevice;
class NpadGcVibrationDevice;

View File

@@ -13,7 +13,7 @@
#include "core/hle/service/hid/controllers/types/npad_types.h"
namespace Service::HID {
class AppletResourceHolder;
struct AppletResourceHolder;
class AbstractPad;
using FullAbstractPad = std::array<AbstractPad, NpadCount>;
class LastActiveNpad;

View File

@@ -7,148 +7,239 @@
#include "core/hle/service/hid/errors.h"
namespace Service::HID {
void NpadGcVibration::FUN_7100087ed4(u64 param_2) {
*(u64*)&field_0x20 = param_2;
Result NpadVibrationDevice::IncrementRefCounter() {
int iVar1;
char local_4[4];
iVar1 = field10_0x14;
field10_0x14 = iVar1 + 1;
if (iVar1 == 0) {
FUN_71000b6a1c(param_1);
}
if (((is_mounted != false) &&
(iVar1 = FUN_710011a950(local_4, field9_0x10, field8_0x8), iVar1 == 0)) &&
(local_4[0] != '\x01')) {
FUN_710011a8f0(1, field9_0x10, field8_0x8);
}
return ResultSuccess;
}
void NpadVibrationDevice::FUN_71000b6a1c() {
char cVar1;
Result nVar2;
float local_30;
u32 local_2c;
float local_28;
u32 local_24;
float local_4;
cVar1 = is_mounted;
if (0 < (int)field10_0x14 && (bool)cVar1 != false) {
local_4 = 1.0;
nVar2 = VibrationVolume::GetVibrationVolume(npad_vibration, &local_4);
if (nVar2 == ResultSuccess) {
local_2c = 0x43200000;
local_24 = 0x43a00000;
local_30 = local_4 * 0.0;
if (local_4 <= 0.0) {
local_30 = 0.0;
}
local_28 = local_30;
FUN_710011a9b0(&local_30, field9_0x10, field8_0x8);
}
cVar1 = is_mounted;
}
if (cVar1 != '\0') {
local_30 = 1.0;
nVar2 = VibrationVolume::GetVibrationVolume(npad_vibration, &local_30);
if (nVar2 == ResultSuccess) {
FUN_710011ab70(field8_0x8, 0);
return;
}
}
return;
}
Result NpadGcVibration::IncrementRefCounter() {
if (ref_counter == 0 && is_initialized) {
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsSuccess()) {
FUN_7100088f4c(field_0x20, field_0x10, '\0');
}
Result NpadVibrationDevice::DecrementRefCounter() {
int iVar1;
char local_4[4];
iVar1 = field10_0x14;
if (iVar1 == 1) {
FUN_71000b6a1c(param_1);
iVar1 = field10_0x14;
}
field10_0x14 = iVar1 + -1;
if ((((iVar1 + -1 == 0 || iVar1 < 1) && (field10_0x14 = 0, is_mounted != false)) &&
(iVar1 = FUN_710011a950(local_4, field9_0x10, field8_0x8), iVar1 == 0)) &&
(local_4[0] != '\0')) {
FUN_710011a8f0(0, field9_0x10, field8_0x8);
}
ref_counter++;
return ResultSuccess;
}
Result NpadGcVibration::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) {
char cVar2;
Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) {
Result nVar1;
float local_38;
float local_34;
float fStack_30;
float local_2c;
float local_24;
if (!is_initialized) {
if ((int)field10_0x14 < 1) {
return Hid_0121_VibrationDisabled;
}
if (is_mounted != false) {
local_24 = 1.0;
nVar1 = VibrationVolume::GetVibrationVolume(npad_vibration, &local_24);
if (nVar1 != ResultSuccess) {
return nVar1;
}
if (local_24 <= 0.0) {
fStack_30 = 0.0;
local_38 = 0.0;
local_2c = 320.0;
local_34 = 160.0;
} else {
local_34 = param_2[1];
local_38 = local_24 * *param_2;
local_2c = param_2[3];
fStack_30 = local_24 * param_2[2];
}
nVar1 = FUN_710011a9b0(&local_38, field9_0x10, field8_0x8);
return nVar1;
}
return ResultSuccess;
}
Result NpadVibrationDevice::FUN_71000b6c40(u32 param_2) {
Result nVar1;
float local_24;
if (is_mounted == false) {
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
local_24 = 1.0;
nVar1 = VibrationVolume::GetVibrationVolume(npad_vibration, &local_24);
if (nVar1 != ResultSuccess) {
return nVar1;
}
if (volume == 0.0) {
cVar2 = '\0';
} else {
if (command > Core::HID::VibrationGcErmCommand::StopHard) {
// Abort
}
cVar2 = (char)(0x100100 >> (u64)(((u32)*param_2 & 3) << 3));
if (local_24 <= 0.0) {
param_2 = 0;
}
FUN_7100088f4c(field_0x20, field_0x10, cVar2);
return ResultSuccess;
nVar1 = FUN_710011ab70(field8_0x8, param_2);
return nVar1;
}
Result NpadGcVibration::DecrementRefCounter() {
if (ref_counter == 1 && !is_initialized) {
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsSuccess()) {
FUN_7100088f4c(field_0x20, field_0x10, '\0');
}
}
if (ref_counter > 1) {
ref_counter--;
}
return ResultSuccess;
}
NpadGcVibration* NpadGcVibration::FUN_7100088080() {
pNVar2 = param_1;
if (param_1->is_initialized) {
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsSuccess()) {
nVar1 = FUN_7100088f4c(field_0x20, field_0x10, '\0');
return (NpadGcVibration*)(u64)nVar1;
}
}
return pNVar2;
}
Result NpadGcVibration::FUN_71000880d8(u64 param_2, u64 param_3, NpadVibrationHandler* handler) {
Result NpadVibrationDevice::FUN_71000b6cc0(long* param_2, int param_3, NpadVibration* param_4) {
int iVar1;
Result nVar2;
u64 uVar3;
u32 uVar4;
undefined auVar5[16];
float local_48;
u32 local_44;
float local_40;
u32 local_3c;
float local_34;
iVar1 = (**(code**)(*param_2 + 0x18))(param_2);
if ((iVar1 == 0) && ((*(byte*)(param_2 + 1) >> 1 & 1) != 0)) {
auVar5 = GetXcdHandle(param_2);
uVar3 = auVar5._0_8_;
field8_0x8 = uVar3;
if (param_3 == 1) {
uVar4 = 0;
} else {
if (param_3 != 2) {
// WARNING: Subroutine does not return
nn::detail::UnexpectedDefaultImpl(uVar3, auVar5._8_8_, uVar3);
}
uVar4 = 1;
}
field9_0x10 = uVar4;
npad_vibration = param_4;
is_mounted = true;
if (0 < (int)field10_0x14) {
iVar1 = FUN_710011a950(&local_48);
if ((iVar1 == 0) && (local_48._0_1_ != '\x01')) {
FUN_710011a8f0(1, field9_0x10, field8_0x8);
}
if ((0 < (int)field10_0x14) && (is_mounted != false)) {
local_34 = 1.0;
nVar2 = VibrationVolume::GetVibrationVolume(npad_vibration, &local_34);
if (nVar2 == ResultSuccess) {
local_44 = 0x43200000;
local_3c = 0x43a00000;
local_48 = local_34 * 0.0;
if (local_34 <= 0.0) {
local_48 = 0.0;
}
local_40 = local_48;
FUN_710011a9b0(&local_48, field9_0x10, field8_0x8);
return ResultSuccess;
}
}
}
}
return ResultSuccess;
}
Result NpadVibrationDevice::FUN_71000b6e0c() {
Result nVar1;
float local_30;
u32 local_2c;
float local_28;
u32 local_24;
float local_4;
if (0 < (int)field10_0x14 && is_mounted != false) {
local_4 = 1.0;
nVar1 = VibrationVolume::GetVibrationVolume(npad_vibration, &local_4);
if (nVar1 == ResultSuccess) {
local_2c = 0x43200000;
local_24 = 0x43a00000;
local_30 = local_4 * 0.0;
if (local_4 <= 0.0) {
local_30 = 0.0;
}
local_28 = local_30;
FUN_710011a9b0(&local_30, field9_0x10, field8_0x8);
is_mounted = false;
return ResultSuccess;
}
}
is_mounted = false;
return ResultSuccess;
}
Result NpadVibrationDevice::FUN_71000b6eb8(u64* param_2) {
Result nVar1;
u32 local_30;
u64 local_2c;
u32 local_24;
*(u64*)&field_0x10 = param_2;
*(u64*)&field_0x18 = param_3;
is_initialized = true;
vibration_handler = handler;
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return ResultSuccess;
if ((int)field10_0x14 < 1) {
return Hid_0121_VibrationDisabled;
}
*param_2 = 0x4320000000000000;
param_2[1] = 0x43a0000000000000;
if (is_mounted != false) {
nVar1 = FUN_710011aa90(&local_30, field9_0x10, field8_0x8);
if (nVar1 != ResultSuccess) {
return nVar1;
}
*(u32*)param_2 = local_30;
*(u64*)((long)param_2 + 4) = local_2c;
*(u32*)((long)param_2 + 0xc) = local_24;
return nVar1;
}
FUN_7100088f4c(field_0x20, field_0x10, '\0');
return ResultSuccess;
}
Result NpadGcVibration::FUN_7100088150() {
if (!is_initialized) {
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsSuccess()) {
FUN_7100088f4c(field_0x20, field_0x10, '\0');
}
is_initialized = false;
return ResultSuccess;
}
Result NpadGcVibration::GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& command) {
if (!is_initialized) {
command = Core::HID::VibrationGcErmCommand::Stop;
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
if (volume == 0.0f) {
command = Core::HID::VibrationGcErmCommand::Stop;
return ResultSuccess;
}
command = FUN_7100089310(field_0x20, field_0x10);
return ResultSuccess;
}
Result NpadGcVibration::FUN_7100088270(Core::HID::VibrationGcErmCommand command) {
if (!is_initialized) {
return ResultSuccess;
}
f32 volume = 1.0f;
const auto result = vibration_handler->GetVibrationVolume(volume);
if (result.IsError()) {
return result;
}
if (volume <= 0.0f) {
command = Core::HID::VibrationGcErmCommand::Stop;
}
if (command > Core::HID::VibrationGcErmCommand::StopHard) {
// Abort
return ResultSuccess;
}
FUN_71000891d0(field_0x20, field_0x10, (&DAT_71001b99a0 + (long)(int)command * 4));
return ResultSuccess;
bool NpadVibrationDevice::IsVibrationMounted() {
return is_mounted;
}
} // namespace Service::HID

View File

@@ -20,24 +20,23 @@ public:
explicit NpadVibrationDevice();
~NpadVibrationDevice();
void FUN_7100087ed4(u64 param_2);
Result IncrementRefCounter();
Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command);
void FUN_71000b6a1c();
Result DecrementRefCounter();
NpadGcVibration* FUN_7100088080();
Result SendVibrationValue(const Core::HID::VibrationValue& value);
Result FUN_71000b6c40(u32 param_2);
Result FUN_71000880d8(u64 param_2, u64 param_3, NpadVibrationHandler* handler);
Result FUN_7100088150();
Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& command);
Result FUN_7100088270(Core::HID::VibrationGcErmCommand command);
Result FUN_71000b6cc0(long* param_2, int param_3, NpadVibration* param_4);
Result FUN_71000b6e0c();
Result FUN_71000b6eb8(u64* param_2);
bool IsVibrationMounted();
private:
u64 xcd_handle;
s32 ref_counter;
bool is_initialized;
bool is_mounted;
NpadVibrationHandler* vibration_handler;
};
} // namespace Service::HID

View File

@@ -16,6 +16,7 @@ constexpr Result ResultVibrationInvalidStyleIndex{ErrorModule::HID, 122};
constexpr Result ResultVibrationInvalidNpadId{ErrorModule::HID, 123};
constexpr Result ResultVibrationDeviceIndexOutOfRange{ErrorModule::HID, 124};
constexpr Result ResultVibrationStrenghtOutOfRange{ErrorModule::HID, 126};
constexpr Result ResultVibrationArraySizeMismatch{ErrorModule::HID, 131};
constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423};

View File

@@ -24,7 +24,9 @@
#include "core/hle/service/hid/controllers/keyboard.h"
#include "core/hle/service/hid/controllers/mouse.h"
#include "core/hle/service/hid/controllers/npad.h"
#include "core/hle/service/hid/controllers/npad/vibration_gc_handler.h"
#include "core/hle/service/hid/controllers/npad/gc_vibration_device.h"
#include "core/hle/service/hid/controllers/npad/n64_vibration_device.h"
#include "core/hle/service/hid/controllers/npad/vibration_device.h"
#include "core/hle/service/hid/controllers/npad/vibration_handler.h"
#include "core/hle/service/hid/controllers/palma.h"
#include "core/hle/service/hid/controllers/seven_six_axis.h"
@@ -1555,15 +1557,16 @@ void IHidServer::SendVibrationValue(HLERequestContext& ctx) {
const auto parameters{rp.PopRaw<Parameters>()};
GetResourceManager()->GetNpad()->VibrateController(parameters.vibration_device_handle,
parameters.vibration_value);
LOG_DEBUG(Service_HID,
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
parameters.vibration_device_handle.npad_type,
parameters.vibration_device_handle.npad_id,
parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
GetResourceManager()->SendVibrationValue(parameters.applet_resource_user_id,
parameters.vibration_device_handle,
parameters.vibration_value);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
@@ -1603,25 +1606,27 @@ void IHidServer::PermitVibration(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto can_vibrate{rp.Pop<bool>()};
// nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value
// by converting it to a bool
Settings::values.vibration_enabled.SetValue(can_vibrate);
LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
const auto result =
GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume(
can_vibrate ? 1.0f : 0.0f);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(result);
}
void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) {
LOG_DEBUG(Service_HID, "called");
// nnSDK checks if a float is greater than zero. We return the bool we stored earlier
const auto is_enabled = Settings::values.vibration_enabled.GetValue();
f32 master_volume{};
const auto result =
GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume(
master_volume);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(is_enabled);
rb.Push(result);
rb.Push(master_volume > 0.0f);
}
void IHidServer::SendVibrationValues(HLERequestContext& ctx) {
@@ -1639,12 +1644,22 @@ void IHidServer::SendVibrationValues(HLERequestContext& ctx) {
auto vibration_values = std::span(
reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
GetResourceManager()->GetNpad()->VibrateControllers(vibration_device_handles, vibration_values);
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
Result result = ResultSuccess;
if (handle_count != vibration_count) {
result = ResultVibrationArraySizeMismatch;
}
for (std::size_t i = 0; i < handle_count; i++) {
if (result.IsSuccess()) {
result = GetResourceManager()->SendVibrationValue(
applet_resource_user_id, vibration_device_handles[i], vibration_values[i]);
}
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
rb.Push(result);
}
void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
@@ -1668,7 +1683,7 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
parameters.gc_erm_command);
bool has_active_aruid{};
NpadGcVibration* gc_device{nullptr};
NpadGcVibrationDevice* gc_device{nullptr};
Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id,
has_active_aruid);
@@ -1703,7 +1718,7 @@ void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
bool has_active_aruid{};
NpadGcVibration* gc_device{nullptr};
NpadGcVibrationDevice* gc_device{nullptr};
Core::HID::VibrationGcErmCommand gc_erm_command{};
Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id,
has_active_aruid);
@@ -1766,10 +1781,21 @@ void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) {
parameters.vibration_device_handle.npad_id,
parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
bool is_mounted{};
NpadVibrationDevice* device{nullptr};
Result result = IsVibrationHandleValid(parameters.vibration_device_handle);
if (result.IsSuccess()) {
device = GetResourceManager()->GetVibrationDevice(parameters.vibration_device_handle);
}
if (device != nullptr) {
is_mounted = device->IsVibrationMounted();
}
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(GetResourceManager()->GetNpad()->IsVibrationDeviceMounted(
parameters.vibration_device_handle));
rb.Push(result);
rb.Push(is_mounted);
}
void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {

View File

@@ -6,6 +6,7 @@
#include "core/core_timing.h"
#include "core/hid/hid_core.h"
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/service/hid/hid_util.h"
#include "core/hle/service/hid/resource_manager.h"
#include "core/hle/service/ipc_helpers.h"
@@ -267,11 +268,42 @@ Result ResourceManager::IsVibrationAruidActive(u64 aruid, bool& is_active) {
return ResultSuccess;
}
NpadGcVibration* ResourceManager::GetGcVibrationDevice(
NpadN64VibrationDevice* ResourceManager::GetN64VibrationDevice(
const Core::HID::VibrationDeviceHandle& handle) {
return npad->GetN64VibrationDevice(handle);
}
NpadVibrationDevice* ResourceManager::GetVibrationDevice(
const Core::HID::VibrationDeviceHandle& handle) {
return npad->GetVibrationDevice(handle);
}
NpadGcVibrationDevice* ResourceManager::GetGcVibrationDevice(
const Core::HID::VibrationDeviceHandle& handle) {
return npad->GetGCVibrationDevice(handle);
}
Result ResourceManager::SendVibrationValue(u64 aruid,
const Core::HID::VibrationDeviceHandle& handle,
const Core::HID::VibrationValue& value) {
bool has_active_aruid{};
NpadVibrationDevice* device{nullptr};
Core::HID::VibrationGcErmCommand gc_erm_command{};
Result result = IsVibrationAruidActive(aruid, has_active_aruid);
if (result.IsSuccess() && has_active_aruid) {
result = IsVibrationHandleValid(handle);
}
if (result.IsSuccess() && has_active_aruid) {
device = GetVibrationDevice(handle);
}
if (device != nullptr) {
result = device->SendVibrationValue(value);
}
return result;
}
IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<ResourceManager> resource,
u64 applet_resource_user_id)
: ServiceFramework{system_, "IAppletResource"}, aruid{applet_resource_user_id},

View File

@@ -27,7 +27,7 @@ class Gesture;
class Keyboard;
class Mouse;
class NPad;
class NpadGcVibration;
class NpadGcVibrationDevice;
class Palma;
class SevenSixAxis;
class SixAxis;
@@ -88,7 +88,11 @@ public:
void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
Result IsVibrationAruidActive(u64 aruid, bool& is_active);
NpadGcVibration* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
NpadVibrationDevice* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
Result SendVibrationValue(u64 aruid, const Core::HID::VibrationDeviceHandle& handle,
const Core::HID::VibrationValue& value);
private:
Result CreateAppletResourceImpl(u64 aruid);