mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
* Pad: report the adaptive trigger state instead of always 0 scePadGetTriggerEffectState returned 0 for both triggers. Games that wait for the state of the trigger effect they set before acting on L2/R2 never saw it change; in Astro Bot, L2/R2 actions such as punches did nothing in some levels. The state now follows from the game's last effect per trigger (already kept for the DualSense output) and the trigger's travel, 0..255 over the effect's ten positions: feedback no force / pushing, weapon not / almost / fully pressed, vibration not firing / firing, with the values 1..7 that duaLib (WujekFoliarz/duaLib) reads from a DualSense input report. SDL does not expose that report, so this is an approximation; it also works with other pads and the keyboard, where a digital L2/R2 is full travel. The trigger intensity setting changes only the output, not the reported state. Tested in Astro Bot (PPSA21567 1.018) by a player in the levels where the triggers did nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * tests: controller_settings covers scePadGetTriggerEffectState Feedback, weapon and vibration states across the trigger travel, a trigger without an effect, a masked update keeping the other trigger's effect, and the intensity setting leaving the reported state unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pad: a feedback trigger reports pushing only while it is pressed A feedback effect from position 0 reported FEEDBACK_IS_PUSHING on an untouched trigger, so a game waiting for the change from no force to pushing never saw it. In Astro's Playroom the gacha capsules did not break on R2. Feedback states (modes 1, 4, 5) now need some travel (>= 8 of 255). Tested in Astro's Playroom (PPSA01325): the capsules break on R2 again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pad: a vibration trigger reports firing only while it is pressed A vibration effect from position 0 reported VIBRATION_IS_FIRING on an untouched trigger; in Astro's Playroom the gun fired by itself. Vibration states (modes 3 and 6) now need some travel, as the feedback states do. Tested in Astro's Playroom. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pad: reject invalid handles in scePadGetTriggerEffectState; test the remaining effect modes scePadGetTriggerEffectState ignored its handle and returned pad 1's state for any handle. It now returns SCE_PAD_ERROR_INVALID_HANDLE (0x80920003) for handles other than 1, like the other pad queries in libPad.cpp and duaLib. controller_settings now also covers multiple-position feedback (mode 4: pushes only at positions with a strength), slope feedback (mode 5: pushes from its start position, not on an untouched trigger) and multiple-position vibration (mode 6: fires only at positions with an amplitude and a frequency). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pad: scePadGetTriggerEffectState returns libScePad's invalid-argument code A null state returned 0x80960005, which is SCE_USER_SERVICE_ERROR_INVALID_ARGUMENT, not a pad error; libScePad's code is SCE_PAD_ERROR_INVALID_ARG (0x80920001), as scePadSetTriggerEffect returns. The call now lives with the other pad calls in controller.cpp so controller_settings tests its handle and argument checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pad: correct trigger effect state reporting --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: nmzik <Nmzik@mail.ru>
435 lines
11 KiB
C++
435 lines
11 KiB
C++
#include "common/abi.h"
|
|
#include "common/logging/log.h"
|
|
#include "libs/controller.h"
|
|
#include "libs/errno.h"
|
|
#include "libs/libs.h"
|
|
#include "libs/padData.h"
|
|
#include "loader/symbolDatabase.h"
|
|
|
|
#include <cstring>
|
|
|
|
namespace Libs {
|
|
|
|
LIB_VERSION("Pad", 1, "Pad", 1, 1);
|
|
|
|
static int KYTY_SYSV_ABI PadSetVibrationMode(int handle, int mode) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %d\n"
|
|
"\t mode = %d\n",
|
|
handle, mode);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI PadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse(bool enabled) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t enabled = %d\n", enabled ? 1 : 0);
|
|
|
|
return OK;
|
|
}
|
|
|
|
struct PadDeviceClassExtendedInformation {
|
|
int32_t device_class;
|
|
uint8_t reserved[4];
|
|
uint8_t class_data[12];
|
|
};
|
|
|
|
struct PadDeviceClassData {
|
|
int32_t device_class;
|
|
bool data_valid;
|
|
uint8_t reserved[3];
|
|
union {
|
|
struct {
|
|
float steering_wheel_angle;
|
|
uint16_t steering_wheel;
|
|
uint16_t accelerator_pedal;
|
|
uint16_t brake_pedal;
|
|
uint16_t clutch_pedal;
|
|
uint16_t hand_brake;
|
|
uint8_t gear;
|
|
uint8_t reserved[1];
|
|
} steering_wheel;
|
|
struct {
|
|
uint8_t data_len;
|
|
uint8_t reserved[3];
|
|
uint8_t data[12];
|
|
} others;
|
|
uint8_t raw[16];
|
|
} class_data;
|
|
};
|
|
|
|
static_assert(sizeof(PadDeviceClassData) == 24);
|
|
|
|
static int KYTY_SYSV_ABI
|
|
PadDeviceClassGetExtendedInformation(int handle, PadDeviceClassExtendedInformation* info) {
|
|
PRINT_NAME();
|
|
|
|
constexpr int pad_error_invalid_handle = -2137915389; /* 0x80920003 */
|
|
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
|
|
|
if (handle != 1) {
|
|
return pad_error_invalid_handle;
|
|
}
|
|
if (info == nullptr) {
|
|
return pad_error_invalid_arg;
|
|
}
|
|
|
|
std::memset(info, 0, sizeof(*info));
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI PadDeviceClassParseData(int handle, const Controller::PadData* data,
|
|
PadDeviceClassData* class_data) {
|
|
PRINT_NAME();
|
|
|
|
constexpr int pad_error_invalid_handle = -2137915389; /* 0x80920003 */
|
|
constexpr int pad_error_invalid_arg = -2137915391; /* 0x80920001 */
|
|
|
|
LOGF("\t handle = %d\n"
|
|
"\t data = 0x%016" PRIx64 "\n"
|
|
"\t class_data = 0x%016" PRIx64 "\n",
|
|
handle, reinterpret_cast<uint64_t>(data), reinterpret_cast<uint64_t>(class_data));
|
|
|
|
if (handle != 1) {
|
|
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->device_class = 0; // SCE_PAD_DEVICE_CLASS_STANDARD
|
|
class_data->data_valid = data->connected;
|
|
|
|
if (data->device_unique_data_len > 0) {
|
|
const auto data_len =
|
|
(data->device_unique_data_len > 12 ? 12 : data->device_unique_data_len);
|
|
class_data->device_class = -1; // SCE_PAD_DEVICE_CLASS_INVALID/unsupported device payload
|
|
class_data->class_data.others.data_len = data_len;
|
|
std::memcpy(class_data->class_data.others.data, data->device_unique_data, data_len);
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI PadSetTiltCorrectionState(int handle, bool enabled) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %d\n"
|
|
"\t enabled = %d\n",
|
|
handle, enabled ? 1 : 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI PadClose(int handle) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %d\n", handle);
|
|
|
|
return OK;
|
|
}
|
|
|
|
// PPSA02385
|
|
static int KYTY_SYSV_ABI PadOpenExtStub(int user_id, int type, int index, const void* param) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t user_id = %d\n"
|
|
"\t type = %d\n"
|
|
"\t index = %d\n"
|
|
"\t param = 0x%016" PRIx64 "\n",
|
|
user_id, type, index, reinterpret_cast<uint64_t>(param));
|
|
|
|
return OK;
|
|
}
|
|
|
|
// PPSA02385
|
|
static int KYTY_SYSV_ABI PadGetExtControllerInformationStub(int handle, void* info) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %d\n"
|
|
"\t info = 0x%016" PRIx64 "\n",
|
|
handle, reinterpret_cast<uint64_t>(info));
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI PadUnknownN3kSX62fgNo(uint64_t arg0, uint64_t arg1, uint64_t arg2,
|
|
uint64_t arg3, uint64_t arg4, uint64_t arg5) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t argc-style args = (0x%016" PRIx64 ", 0x%016" PRIx64 ", 0x%016" PRIx64 ", 0x%016" PRIx64
|
|
", 0x%016" PRIx64 ", 0x%016" PRIx64 ")\n",
|
|
arg0, arg1, arg2, arg3, arg4, arg5);
|
|
|
|
if (arg0 >= 0x10000 && arg3 > 0 && arg3 <= 0x1000) {
|
|
std::memset(reinterpret_cast<void*>(arg0), 0, static_cast<size_t>(arg3));
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
LIB_DEFINE(InitPad_1) {
|
|
PRINT_NAME_ENABLE(true);
|
|
|
|
LIB_FUNC("hv1luiJrqQM", Controller::PadInit);
|
|
LIB_FUNC("xk0AcarP3V4", Controller::PadOpen);
|
|
LIB_FUNC("WFIiSfXGUq8", PadOpenExtStub);
|
|
LIB_FUNC("u1GRHp+oWoY", Controller::PadGetHandle);
|
|
LIB_FUNC("AcslpN1jHR8", PadDeviceClassGetExtendedInformation);
|
|
LIB_FUNC("IHPqcbc0zCA", PadDeviceClassParseData);
|
|
LIB_FUNC("clVvL4ZDntw", Controller::PadSetMotionSensorState);
|
|
LIB_FUNC("r44mAxdSG+U", Controller::PadSetAngularVelocityDeadbandState);
|
|
LIB_FUNC("rIZnR6eSpvk", Controller::PadResetOrientation);
|
|
LIB_FUNC("vDLMoJLde8I", PadSetTiltCorrectionState);
|
|
LIB_FUNC("gjP9-KQzoUk", Controller::PadGetControllerInformation);
|
|
LIB_FUNC("fCWdlnmB1Ks", Controller::PadIsRemoteController);
|
|
LIB_FUNC("hGbf2QTBmqc", PadGetExtControllerInformationStub);
|
|
LIB_FUNC("2JgFB2n9oUM", Controller::PadSetTriggerEffect);
|
|
LIB_FUNC("YndgXqQVV7c", Controller::PadReadState);
|
|
LIB_FUNC("q1cHNfGycLI", Controller::PadRead);
|
|
LIB_FUNC("yFVnOdGxvZY", Controller::PadSetVibration);
|
|
LIB_FUNC("W2G-yoyMF5U", PadSetVibrationMode);
|
|
LIB_FUNC("Yq0zOH7YNOM", PadSetVibrationTriggerEffectWeakWhileEmbeddedMicInUse);
|
|
LIB_FUNC("znaWI0gpuo8", Controller::PadGetTriggerEffectState);
|
|
LIB_FUNC("DscD1i9HX1w", Controller::PadResetLightBar);
|
|
LIB_FUNC("RR4novUEENY", Controller::PadSetLightBar);
|
|
LIB_FUNC("6ncge5+l5Qs", PadClose);
|
|
LIB_FUNC("n3kSX62fgNo", PadUnknownN3kSX62fgNo);
|
|
}
|
|
|
|
namespace LibMouse {
|
|
|
|
LIB_VERSION("Mouse", 1, "Mouse", 1, 1);
|
|
|
|
namespace Mouse {
|
|
|
|
constexpr int MOUSE_ERROR_INVALID_ARG = -2132869119; /* 0x80DF0001 */
|
|
constexpr int MOUSE_ERROR_INVALID_HANDLE = -2132869117; /* 0x80DF0003 */
|
|
|
|
struct MouseData {
|
|
uint64_t timestamp;
|
|
bool connected;
|
|
uint8_t padding[3];
|
|
uint32_t buttons;
|
|
int32_t x_axis;
|
|
int32_t y_axis;
|
|
int32_t wheel;
|
|
int32_t tilt;
|
|
uint8_t reserved[8];
|
|
};
|
|
|
|
static int KYTY_SYSV_ABI MouseInit() {
|
|
PRINT_NAME();
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI MouseOpen(int user_id, int32_t type, int32_t index, const void* param) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t user_id = %d\n"
|
|
"\t type = %" PRId32 "\n"
|
|
"\t index = %" PRId32 "\n"
|
|
"\t param = 0x%016" PRIx64 "\n",
|
|
user_id, type, index, reinterpret_cast<uint64_t>(param));
|
|
|
|
if (type != 0 || index < 0 || index >= 2) {
|
|
return MOUSE_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI MouseClose(int32_t handle) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %" PRId32 "\n", handle);
|
|
|
|
if (handle <= 0) {
|
|
return MOUSE_ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI MouseRead(int32_t handle, MouseData* data, int32_t num) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %" PRId32 "\n"
|
|
"\t data = 0x%016" PRIx64 "\n"
|
|
"\t num = %" PRId32 "\n",
|
|
handle, reinterpret_cast<uint64_t>(data), num);
|
|
|
|
if (handle <= 0) {
|
|
return MOUSE_ERROR_INVALID_HANDLE;
|
|
}
|
|
if (data == nullptr || num <= 0) {
|
|
return MOUSE_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
std::memset(data, 0, sizeof(MouseData) * static_cast<size_t>(num));
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // namespace Mouse
|
|
|
|
LIB_DEFINE(InitMouse_1) {
|
|
LIB_FUNC("cAnT0Rw-IwU", Mouse::MouseClose);
|
|
LIB_FUNC("Qs0wWulgl7U", Mouse::MouseInit);
|
|
LIB_FUNC("RaqxZIf6DvE", Mouse::MouseOpen);
|
|
LIB_FUNC("x8qnXqh-tiM", Mouse::MouseRead);
|
|
}
|
|
|
|
} // namespace LibMouse
|
|
|
|
namespace LibKeyboard {
|
|
|
|
LIB_VERSION("Keyboard", 1, "Keyboard", 1, 1);
|
|
|
|
namespace Keyboard {
|
|
|
|
constexpr int KEYBOARD_ERROR_INVALID_ARG = -2133196799; /* 0x80da0001 */
|
|
constexpr int KEYBOARD_ERROR_INVALID_HANDLE = -2133196797; /* 0x80da0003 */
|
|
constexpr int KEYBOARD_MAX_KEYCODES = 16;
|
|
constexpr int KEYBOARD_MAX_DATA_NUM = 16;
|
|
constexpr int KEYBOARD_MAPPING_101 = 0;
|
|
constexpr int KEYBOARD_MAPPING_106 = 1;
|
|
|
|
struct KeyboardData {
|
|
uint64_t timestamp;
|
|
bool intercepted;
|
|
uint8_t reserve1[7];
|
|
bool connected;
|
|
int32_t length;
|
|
uint32_t led;
|
|
uint32_t modifier_key;
|
|
uint16_t key_code[KEYBOARD_MAX_KEYCODES];
|
|
uint8_t reserve2[32];
|
|
};
|
|
|
|
struct KeyboardCharData {
|
|
bool processed;
|
|
int32_t length;
|
|
uint16_t char_code;
|
|
uint8_t reserve[8];
|
|
};
|
|
|
|
static int KYTY_SYSV_ABI KeyboardInit() {
|
|
PRINT_NAME();
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI KeyboardOpen(int user_id, int32_t type, int32_t index, const void* param) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t user_id = %d\n"
|
|
"\t type = %" PRId32 "\n"
|
|
"\t index = %" PRId32 "\n"
|
|
"\t param = 0x%016" PRIx64 "\n",
|
|
user_id, type, index, reinterpret_cast<uint64_t>(param));
|
|
|
|
if (type != 0 || index < 0 || index >= 2) {
|
|
return KEYBOARD_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI KeyboardClose(int32_t handle) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %" PRId32 "\n", handle);
|
|
|
|
if (handle <= 0) {
|
|
return KEYBOARD_ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI KeyboardRead(int32_t handle, KeyboardData* data, int32_t num) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %" PRId32 "\n"
|
|
"\t data = 0x%016" PRIx64 "\n"
|
|
"\t num = %" PRId32 "\n",
|
|
handle, reinterpret_cast<uint64_t>(data), num);
|
|
|
|
if (handle <= 0) {
|
|
return KEYBOARD_ERROR_INVALID_HANDLE;
|
|
}
|
|
if (data == nullptr || num <= 0 || num > KEYBOARD_MAX_DATA_NUM) {
|
|
return KEYBOARD_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
std::memset(data, 0, sizeof(KeyboardData) * static_cast<size_t>(num));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI KeyboardReadState(int32_t handle, KeyboardData* data) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %" PRId32 "\n"
|
|
"\t data = 0x%016" PRIx64 "\n",
|
|
handle, reinterpret_cast<uint64_t>(data));
|
|
|
|
if (handle <= 0) {
|
|
return KEYBOARD_ERROR_INVALID_HANDLE;
|
|
}
|
|
if (data == nullptr) {
|
|
return KEYBOARD_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
std::memset(data, 0, sizeof(KeyboardData));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int KYTY_SYSV_ABI KeyboardGetKey2Char(int32_t handle, int32_t arrange, uint32_t led,
|
|
uint32_t modifier_key, uint16_t key_code,
|
|
KeyboardCharData* char_data) {
|
|
PRINT_NAME();
|
|
|
|
LOGF("\t handle = %" PRId32 "\n"
|
|
"\t arrange = %" PRId32 "\n"
|
|
"\t led = %" PRIu32 "\n"
|
|
"\t modifier_key = %" PRIu32 "\n"
|
|
"\t key_code = %" PRIu16 "\n"
|
|
"\t char_data = 0x%016" PRIx64 "\n",
|
|
handle, arrange, led, modifier_key, key_code, reinterpret_cast<uint64_t>(char_data));
|
|
|
|
if (handle <= 0) {
|
|
return KEYBOARD_ERROR_INVALID_HANDLE;
|
|
}
|
|
if (char_data == nullptr ||
|
|
(arrange != KEYBOARD_MAPPING_101 && arrange != KEYBOARD_MAPPING_106)) {
|
|
return KEYBOARD_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
std::memset(char_data, 0, sizeof(KeyboardCharData));
|
|
|
|
return OK;
|
|
}
|
|
|
|
} // namespace Keyboard
|
|
|
|
LIB_DEFINE(InitKeyboard_1) {
|
|
LIB_FUNC("wadT3QBCGY0", Keyboard::KeyboardInit);
|
|
LIB_FUNC("HJ+KnEHcaxI", Keyboard::KeyboardOpen);
|
|
LIB_FUNC("0LWei+c7RNc", Keyboard::KeyboardClose);
|
|
LIB_FUNC("6HpE68bzX6M", Keyboard::KeyboardReadState);
|
|
LIB_FUNC("xybbGMCr738", Keyboard::KeyboardRead);
|
|
LIB_FUNC("yO9JwdRhtSA", Keyboard::KeyboardGetKey2Char);
|
|
}
|
|
|
|
} // namespace LibKeyboard
|
|
|
|
} // namespace Libs
|