pad: real implementations for extended pad info/lightbar/trigger NIDs
Replace NotImplemented stubs with real implementations for scePadGetInfo, scePadDeviceClassGetExtendedInformation/ParseData, scePadGetExtControllerInformation, scePadSetLightBar, scePadResetLightBar, scePadResetOrientation, scePadSetMotionSensorState, scePadGetTriggerEffectState, scePadSetProcessPrivilege, and scePadSetParticularMode, wiring them to the new Pad:: output/orientation API. None of these NIDs are touched by upstream's existing keyboard/mouse binding work, so this is a clean additive change. scePadSetVibration, scePadSetVibrationMode, and scePadSetTriggerEffect are also given real implementations here, even though they were not named in the audit's NID list: they are the only guest entry points for the Pad::SetVibration/SetVibrationMode/SetTriggerCommand plumbing added in the previous commit, so leaving them NotImplemented would make the rumble/adaptive-trigger machinery unreachable from any title. Every other previously-NotImplemented NID in this file (scePadGetHandle, scePadSetAngularVelocityDeadbandState, scePadSetTiltCorrectionState, scePadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse) is left exactly as upstream had it; scePadOpen_nid_postfix, scePadRead_nid_postfix, and scePadReadState are untouched (upstream's APS5_INVALID_ARG_EX throw-based error handling is kept as-is, not replaced with plain error-code returns). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
4c349efe4f
commit
855176796b
|
|
@ -20,18 +20,21 @@ int APS5_VABI scePadClose_nid_postfix(int handle) {
|
|||
}
|
||||
|
||||
int APS5_VABI scePadDeviceClassGetExtendedInformation(int handle, PadDeviceClassExtendedInformation* info) {
|
||||
(void)handle;
|
||||
(void)info;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
if (info == nullptr) return PAD_ERROR_INVALID_ARG;
|
||||
// Standard digital pad: device class only, every class-specific field zero.
|
||||
std::memset(info, 0, sizeof(*info));
|
||||
info->deviceClass = PAD_DEVICE_CLASS_STANDARD;
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadDeviceClassParseData(int handle, const PadData* data, PadDeviceClassData* class_data) {
|
||||
(void)handle;
|
||||
(void)data;
|
||||
(void)class_data;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
if (data == nullptr || class_data == nullptr) return PAD_ERROR_INVALID_ARG;
|
||||
std::memset(class_data, 0, sizeof(*class_data));
|
||||
class_data->deviceClass = PAD_DEVICE_CLASS_STANDARD;
|
||||
class_data->dataValid = data->connected; // no steering/guitar/drum payload for a standard pad
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadGetControllerInformation(int handle, PadControllerInformation* info) {
|
||||
|
|
@ -62,11 +65,56 @@ int APS5_VABI scePadGetHandle(int user_id, int type, int index) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Port 0 holds the virtual DualSense while the host has no pad open; fields per the PadInfo layout.
|
||||
int APS5_VABI scePadGetInfo_nid_postfix(PadInfo* info) {
|
||||
if (info == nullptr) return PAD_ERROR_INVALID_ARG;
|
||||
std::memset(info, 0, sizeof(*info));
|
||||
info->maxConnectCount = 4;
|
||||
info->connectedCount[0] = 1; // standard ports
|
||||
info->connectedCount[1] = 0; // special ports
|
||||
PadInfo::PadTypeInfo& slot = info->padTypeInfo[0];
|
||||
slot.connectPort = 0;
|
||||
slot.status = 1;
|
||||
slot.deviceType = PAD_DEVICE_TYPE_DUAL_SENSE;
|
||||
slot.connectType = PAD_CONNECT_TYPE_BLUETOOTH;
|
||||
std::memcpy(slot.bluetoothMacAddress, PAD_BD_ADDRESS, sizeof(slot.bluetoothMacAddress));
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadGetTriggerEffectState(int handle, PadTriggerEffectStateInformation* info) {
|
||||
(void)handle;
|
||||
(void)info;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
if (info == nullptr) return PAD_ERROR_INVALID_ARG;
|
||||
// Both triggers report the neutral "no feedback engaged" state; the host pad has no trigger readback.
|
||||
std::memset(info, 0, sizeof(*info));
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadGetExtControllerInformation(int handle, void* info) {
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
if (info == nullptr) return PAD_ERROR_INVALID_ARG;
|
||||
// ScePadExtendedControllerInformation: base information followed by the class extension (all zero for a standard pad).
|
||||
std::memset(info, 0, 0x2c);
|
||||
PadControllerInformation* base = static_cast<PadControllerInformation*>(info);
|
||||
base->touchPadInfo.pixelDensity = 44.86f;
|
||||
base->touchPadInfo.resolution.x = 1920;
|
||||
base->touchPadInfo.resolution.y = 943;
|
||||
base->stickInfo.deadZoneLeft = 2;
|
||||
base->stickInfo.deadZoneRight = 2;
|
||||
base->connectionType = PAD_CONNECTION_TYPE_LOCAL;
|
||||
base->connectedCount = 1;
|
||||
base->connected = true;
|
||||
base->deviceClass = PAD_DEVICE_CLASS_STANDARD;
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadSetProcessPrivilege(int privilege) {
|
||||
(void)privilege;
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadSetParticularMode(bool mode) {
|
||||
(void)mode;
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadInit_nid_postfix(void) {
|
||||
|
|
@ -107,15 +155,15 @@ int APS5_VABI scePadReadState(int handle, PadData* data) {
|
|||
}
|
||||
|
||||
int APS5_VABI scePadResetLightBar(int handle) {
|
||||
(void)handle;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
Pad::SetLightBar(false, 0, 0, 0);
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadResetOrientation(int handle) {
|
||||
(void)handle;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
Pad::ResetOrientation();
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadSetAngularVelocityDeadbandState(int handle, bool enable) {
|
||||
|
|
@ -125,19 +173,17 @@ int APS5_VABI scePadSetAngularVelocityDeadbandState(int handle, bool enable) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// ScePadLightBarParam: u8 r, g, b at +0..2.
|
||||
int APS5_VABI scePadSetLightBar(int handle, const PadLightBarParam* param) {
|
||||
(void)handle;
|
||||
(void)param;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
if (param == nullptr) return PAD_ERROR_INVALID_ARG;
|
||||
Pad::SetLightBar(true, param->r, param->g, param->b);
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadSetMotionSensorState(int handle, bool enable) {
|
||||
(void)handle;
|
||||
(void)enable;
|
||||
// if (enable) {
|
||||
// throw std::runtime_error("scePadSetMotionSensorState: motion sensor not supported");
|
||||
// }
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
Pad::SetMotionEnabled(enable);
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
|
|
@ -148,25 +194,48 @@ int APS5_VABI scePadSetTiltCorrectionState(int handle, bool enabled) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// ScePadTriggerEffectParam: u8 triggerMask (bit 0 = L2, bit 1 = R2), u8 padding[7], ScePadTriggerEffectCommandData command[2] (56 bytes each).
|
||||
// Not one of the extended-info NIDs the audit called out by name, but wired to a real implementation here
|
||||
// because it is the guest entry point for the adaptive-trigger plumbing added alongside it (Pad::SetTriggerCommand);
|
||||
// leaving it NotImplemented would make the trigger effect state/output machinery unreachable from the guest.
|
||||
int APS5_VABI scePadSetTriggerEffect(int handle, const void* param) {
|
||||
(void)handle;
|
||||
(void)param;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
if (param == nullptr) return PAD_ERROR_INVALID_ARG;
|
||||
const std::uint8_t* bytes = static_cast<const std::uint8_t*>(param);
|
||||
const std::uint8_t mask = bytes[0];
|
||||
if ((mask & ~0x3u) != 0) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
std::uint32_t mode[2] = {};
|
||||
for (int trigger = 0; trigger < 2; ++trigger) std::memcpy(&mode[trigger], bytes + 8 + 56 * trigger, 4);
|
||||
// Modes 0..6 are the SDK ScePadTriggerEffectMode values; anything else means the struct was misread.
|
||||
if (mode[0] > 6 || mode[1] > 6) {
|
||||
return PAD_ERROR_INVALID_ARG;
|
||||
}
|
||||
for (int trigger = 0; trigger < 2; ++trigger) {
|
||||
if ((mask & (1u << trigger)) != 0) Pad::SetTriggerCommand(trigger, bytes + 8 + 56 * trigger);
|
||||
}
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
// ScePadVibrationParam: u8 largeMotor at +0, u8 smallMotor at +1 (vibration-mode motors only; the trigger
|
||||
// motors are driven through scePadSetTriggerEffect).
|
||||
// Also not in the audit's named list, but wired here for the same reason as scePadSetTriggerEffect: it is
|
||||
// the only guest entry point for Pad::SetVibration, which the rumble plumbing added alongside it needs.
|
||||
int APS5_VABI scePadSetVibration(int handle, const PadVibrationParam* param) {
|
||||
(void)handle;
|
||||
(void)param;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
if (param == nullptr) return PAD_ERROR_INVALID_ARG;
|
||||
Pad::SetVibration(param->large_motor, param->small_motor);
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
// mode: 0 = desktop (USB) vibration layout, 1 = embedded controller layout. Both drive the same host rumble.
|
||||
// Same rationale as scePadSetVibration: the only guest entry point for Pad::SetVibrationMode.
|
||||
int APS5_VABI scePadSetVibrationMode(int handle, int mode) {
|
||||
(void)handle;
|
||||
(void)mode;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE;
|
||||
if (mode != 0 && mode != 1) return PAD_ERROR_INVALID_ARG;
|
||||
Pad::SetVibrationMode(mode);
|
||||
return PAD_OK;
|
||||
}
|
||||
|
||||
int APS5_VABI scePadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse(bool enabled) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue