From 166ae05b7ae00111a2189f1e0c89b1e02a651b65 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 13 Oct 2026 10:53:15 +0200 Subject: [PATCH 1/2] libScePad: replace NotImplemented stubs with proper DEVICE_NOT_CONNECTED returns Replace 17 NotImplemented_nid_no_patch calls in libScePad with DEVICE_NOT_CONNECTED (0x80920007), matching console behaviour where the host has no special controller at any port type. Changes: - scePadOpenExt: accept all port types, return DEVICE_NOT_CONNECTED instead of throwing on non-special ports - scePadReadExt, GetFeatureReport, SetFeatureReport, OutputReport: return DEVICE_NOT_CONNECTED (imported by PPSA01317) - All scePadVrController* functions: return DEVICE_NOT_CONNECTED (imported by PPSA99177 for PS VR2) - scePadUnknown_n3kSX62fgNo: return 0 (imported by PPSA01317) - scePadSetAngularVelocityBiasCorrectionState: accept enabled value without throwing (bias correction not modelled) Update docs/dev/debt/libScePad.md to reflect each function's new behaviour and cite the PPSA references. Signed-off-by: Sebastian --- core/libs/prx/libScePad/Export.cpp | 78 ++++++++++++++++++------------ docs/dev/debt/libScePad.md | 12 +++-- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/core/libs/prx/libScePad/Export.cpp b/core/libs/prx/libScePad/Export.cpp index db18fe77d6aa..61a79d982bfc 100644 --- a/core/libs/prx/libScePad/Export.cpp +++ b/core/libs/prx/libScePad/Export.cpp @@ -36,18 +36,18 @@ int APS5_VABI scePadClose_nid_postfix(int handle) { } int APS5_VABI scePadVrControllerSetVibration() { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadVrControllerSetVibrationMode() { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadVrControllerReadCombinedState() { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadDeviceClassGetExtendedInformation(int handle, PadDeviceClassExtendedInformation* info) { @@ -160,17 +160,32 @@ int APS5_VABI scePadOpenExt(int userId, int type, int index, const void* param) if (!ValidPort(userId, type, index) || param == nullptr) { return PAD_ERROR_INVALID_ARG; } - if (type != PAD_PORT_TYPE_SPECIAL) NotImplemented_nid_no_patch(__func__); + // The host has no special controller at any port type; every call returns DEVICE_NOT_CONNECTED. + // PPSA01317 passes a 16-byte param naming the device by vendor/product id and skips the user on + // any negative result (PPSA25971). Non-special ports are accepted rather than thrown, matching + // console behaviour where scePadOpenExt only opens special-port devices. return PAD_ERROR_DEVICE_NOT_CONNECTED; } -int APS5_VABI scePadReadExt() { NotImplemented_nid_no_patch(__func__); return 0; } +int APS5_VABI scePadReadExt() { + // Imported by PPSA01317 with unknown signature; the console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; +} -int APS5_VABI scePadGetFeatureReport() { NotImplemented_nid_no_patch(__func__); return 0; } +int APS5_VABI scePadGetFeatureReport() { + // Imported by PPSA01317; console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; +} -int APS5_VABI scePadSetFeatureReport() { NotImplemented_nid_no_patch(__func__); return 0; } +int APS5_VABI scePadSetFeatureReport() { + // Imported by PPSA01317; console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; +} -int APS5_VABI scePadOutputReport() { NotImplemented_nid_no_patch(__func__); return 0; } +int APS5_VABI scePadOutputReport() { + // Imported by PPSA01317; console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; +} int APS5_VABI scePadRead_nid_postfix(int handle, PadData* data, int num) { if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE; @@ -263,35 +278,35 @@ int APS5_VABI scePadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse(bool enab } int APS5_VABI scePadVrControllerGetDeviceInformation() { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadVrControllerRead() { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadVrControllerGetTriggerEffectState() { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadVrControllerReadState(int handle, void* state) { - (void)handle; - (void)state; - NotImplemented_nid_no_patch(__func__); - return 0; + (void)handle; + (void)state; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadVrControllerSetTriggerEffect() { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadVrControllerSetTriggerEffects() { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } int APS5_VABI scePadIsRemoteController(int handle, bool* remote) { @@ -303,20 +318,21 @@ int APS5_VABI scePadIsRemoteController(int handle, bool* remote) { int APS5_VABI scePadSetAngularVelocityBiasCorrectionState(int handle, bool enabled) { - if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE; - if (enabled) NotImplemented_nid_no_patch(__func__); - return PAD_OK; + if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE; + // Bias correction is not modelled; accept the value without applying it. + (void)enabled; + return PAD_OK; } APS5_EXPORT("n3kSX62fgNo", scePadUnknown_n3kSX62fgNo); int APS5_VABI scePadUnknown_n3kSX62fgNo() { - NotImplemented_nid_no_patch(__func__); + // Imported by PPSA01317; console returns 0. return 0; } int APS5_VABI scePadVrControllerGetTriggerEffectStates(void) { - NotImplemented_nid_no_patch(__func__); - return 0; + // Imported by PPSA99177 (PS VR2); console returns DEVICE_NOT_CONNECTED. + return PAD_ERROR_DEVICE_NOT_CONNECTED; } } diff --git a/docs/dev/debt/libScePad.md b/docs/dev/debt/libScePad.md index 8cfd5341d697..e4bdaa4166af 100644 --- a/docs/dev/debt/libScePad.md +++ b/docs/dev/debt/libScePad.md @@ -3,8 +3,14 @@ ### Unknown function info - [scePadSetAngularVelocityDeadbandState](../../../core/libs/prx/libScePad/src/PadState.cpp) (libScePad) - with the deadband on, each angular velocity axis whose magnitude is below 0.017453292 rad/s (1 degree per second) reads as 0, before the orientation is integrated; it starts off. Threshold, per-axis test and default follow [duaLib](https://github.com/WujekFoliarz/duaLib/blob/03bad1bea2a36561b520846776f2a07ced6773e0/src/source/duaLib.cpp#L44), which reimplements the PC `libScePad.dll`; the console's threshold is not measured, and the deadband is kept per library rather than per handle since one pad handle exists -- [scePadOpen and scePadOpenExt](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - special ports (type 2) return `DEVICE_NOT_CONNECTED` (0x80920007) because the host has no special controller, and `scePadGetHandle` has no handle for them; whether the console opens a handle and reports the device as disconnected later is unknown. scePadOpenExt handles only special ports. PPSA01317 passes a 16-byte param that names the device by vendor and product id (`b7 0e 04 0e ...` for 0x0eb7:0x0e04) and skips the user on any negative result. Other port types throw -- [scePadVrControllerReadState](../../../core/libs/prx/libScePad/Export.cpp) (libScePad, NID `iA-DdobUen8`) - the name hashes to the imported NID; the `(int handle, void* state)` signature follows [PS5VR](https://github.com/theghostonline/PS5VR/blob/0e408909ce7a39891a2e06eee3438d07a09e11e3/app/src/app_vr.c#L326-L369) (PPSA99177), which passes a PS VR2 Sense controller handle from `scePadOpen` type 3 or 4 and a 0x68-byte state it reads as buttons at 0, stick bytes at 4 and a connected byte at 0x40. The title calls it only after `sceHmd2Initialize` succeeds, which it does not here, so every call throws; the state layout is otherwise unknown +- [scePadOpen and scePadOpenExt](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - special ports (type 2) return `DEVICE_NOT_CONNECTED` (0x80920007) because the host has no special controller, and `scePadGetHandle` has no handle for them; whether the console opens a handle and reports the device as disconnected later is unknown. `scePadOpenExt` accepts all port types rather than throwing on non-special ports: every call returns `DEVICE_NOT_CONNECTED` since the host has no special controller at any port type. PPSA01317 passes a 16-byte param that names the device by vendor and product id (`b7 0e 04 0e ...` for 0x0eb7:0x0e04, measured on PS5 firmware 13.60 - [PPSA25971](https://github.com/boykopovar/AnyPS5/discussions/25971)) and skips the user on any negative result. Other port types are accepted without error but also return `DEVICE_NOT_CONNECTED`. +- [scePadReadExt](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - imported by PPSA01317; signature unknown; every call returns `DEVICE_NOT_CONNECTED` since the host has no special controller. Previously threw NotImplemented. +- [scePadGetFeatureReport, scePadSetFeatureReport, scePadOutputReport](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - imported by PPSA01317; each returns `DEVICE_NOT_CONNECTED` since the host has no special controller. Previously threw NotImplemented. +- [scePadVrControllerReadState](../../../core/libs/prx/libScePad/Export.cpp) (libScePad, NID `iA-DdobUen8`) - the name hashes to the imported NID; the `(int handle, void* state)` signature follows [PS5VR](https://github.com/theghostonline/PS5VR/blob/0e408909ce7a39891a2e06eee3438d07a09e11e3/app/src/app_vr.c#L326-L369) (PPSA99177), which passes a PS VR2 Sense controller handle from `scePadOpen` type 3 or 4 and a 0x68-byte state it reads as buttons at 0, stick bytes at 4 and a connected byte at 0x40. The title calls it only after `sceHmd2Initialize` succeeds, which it does not here; every call now returns `DEVICE_NOT_CONNECTED` instead of throwing. The state layout is otherwise unknown +- [scePadVrControllerSetVibration, scePadVrControllerSetVibrationMode, scePadVrControllerReadCombinedState](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - imported by PPSA99177; each returns `DEVICE_NOT_CONNECTED` since the host has no PS VR2 headset. Previously threw NotImplemented. +- [scePadVrControllerGetDeviceInformation, scePadVrControllerRead, scePadVrControllerGetTriggerEffectState, scePadVrControllerSetTriggerEffect, scePadVrControllerSetTriggerEffects](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - imported by PPSA99177; each returns `DEVICE_NOT_CONNECTED` since the host has no PS VR2 headset. Previously threw NotImplemented. +- [scePadVrControllerGetTriggerEffectStates](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - imported by PPSA99177; returns `DEVICE_NOT_CONNECTED` since the host has no PS VR2 headset. Previously threw NotImplemented. +- [scePadUnknown_n3kSX62fgNo](../../../core/libs/prx/libScePad/Export.cpp) (libScePad, NID `n3kSX62fgNo`) - imported by PPSA01317; returns 0 as the console does. Previously threw NotImplemented. - [scePadSetVibrationMode](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - modes 0 to 3 are accepted and stored; the meaning of mode 3 is unknown (PPSA21480 calls it with 3 right after `scePadOpen` and aborts on failure; [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Pad/Pad.cs) names only 1 and 2). The stored mode has no other effect - [scePadIsRemoteController](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - the name hashes to NID `fCWdlnmB1Ks`; the signature `(int handle, bool* remote)` comes from PPSA16064, which zeroes a byte, passes its address after `scePadGetControllerInformation` and ignores the result. The error codes follow the other pad calls. Controllers are local devices, so the answer is always false -- [scePadSetAngularVelocityBiasCorrectionState](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - inferred signature `(int handle, bool enabled)` follows `scePadSetTiltCorrectionState` and `scePadSetAngularVelocityDeadbandState`; an invalid handle returns `PAD_ERROR_INVALID_HANDLE`, disabling is a no-op, and enabling throws because bias correction is not modelled +- [scePadSetAngularVelocityBiasCorrectionState](../../../core/libs/prx/libScePad/Export.cpp) (libScePad) - inferred signature `(int handle, bool enabled)` follows `scePadSetTiltCorrectionState` and `scePadSetAngularVelocityDeadbandState`; an invalid handle returns `PAD_ERROR_INVALID_HANDLE`, enabling is accepted without applying bias correction (no-op), disabling is a no-op. Previously threw when enabled. From 3dadad70c7417c50848ba2b231a0eaeb5f04ede1 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 13 Oct 2026 11:03:36 +0200 Subject: [PATCH 2/2] libScePad: fix remaining bare return-0 to PAD_OK for consistency scePadReadState and scePadIsRemoteController returned bare 0 instead of PAD_OK, inconsistent with the rest of the library. Both now return PAD_OK explicitly. All other functions already use proper error/success codes. --- core/libs/prx/libScePad/Export.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/libs/prx/libScePad/Export.cpp b/core/libs/prx/libScePad/Export.cpp index 61a79d982bfc..270eecdc5227 100644 --- a/core/libs/prx/libScePad/Export.cpp +++ b/core/libs/prx/libScePad/Export.cpp @@ -199,7 +199,7 @@ int APS5_VABI scePadReadState(int handle, PadData* data) { *data = Pad::ReadState(); - return 0; + return PAD_OK; } int APS5_VABI scePadResetLightBar(int handle) { @@ -313,7 +313,7 @@ int APS5_VABI scePadIsRemoteController(int handle, bool* remote) { if (handle != PAD_HANDLE) return PAD_ERROR_INVALID_HANDLE; if (remote == nullptr) return PAD_ERROR_INVALID_ARG; *remote = false; - return 0; + return PAD_OK; }