mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-21 08:12:09 -05:00
ContentBinder, CompanionUtil, ErrorDialog OpenDetail/OpenWithReport, ImeDialog ForTestFunction, HttpCache SystemTerm/SendStatistics, MoveTracker GetVersion/RecordStop, BluetoothHid and SystemGesture debug versions and Mbus Term/AcquireControlList are a single constant return in the firmware modules; these exports now return the same value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
318 lines
14 KiB
C++
318 lines
14 KiB
C++
#include <cstdint>
|
|
#include <cstddef>
|
|
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/General.hpp"
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include <mutex>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
static constexpr int32_t GESTURE_HANDLE = 1;
|
|
static constexpr int SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT = static_cast<int>(0x80D10002);
|
|
static constexpr int SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE = static_cast<int>(0x80D10003);
|
|
static constexpr int SCE_SYSTEM_GESTURE_ERROR_INDEX_OUT_OF_ARRAY = static_cast<int>(0x80D10005);
|
|
|
|
namespace {
|
|
|
|
constexpr std::uint64_t RECOGNIZER_STATE_MAGIC = 0x41505335'47455354ULL;
|
|
|
|
struct RecognizerState {
|
|
std::uint64_t magic;
|
|
std::int32_t gestureType;
|
|
std::uint32_t hasRectangle;
|
|
SystemGestureRectangle rectangle;
|
|
};
|
|
|
|
static_assert(sizeof(RecognizerState) <= sizeof(SystemGestureTouchRecognizer));
|
|
|
|
void storeRecognizerState(SystemGestureTouchRecognizer* recognizer, const RecognizerState& state) {
|
|
std::memcpy(recognizer->reserve, &state, sizeof(state));
|
|
}
|
|
|
|
bool loadRecognizerState(const SystemGestureTouchRecognizer* recognizer, RecognizerState& state) {
|
|
std::memcpy(&state, recognizer->reserve, sizeof(state));
|
|
return state.magic == RECOGNIZER_STATE_MAGIC;
|
|
}
|
|
|
|
constexpr std::int32_t TOUCH_STATE_BEGIN = 1;
|
|
constexpr std::int32_t TOUCH_STATE_ACTIVE = 2;
|
|
constexpr std::int32_t TOUCH_STATE_END = 3;
|
|
|
|
struct TrackedTouch {
|
|
std::uint16_t primitiveId;
|
|
std::int32_t eventState;
|
|
bool isUpdated;
|
|
bool sampled;
|
|
SystemGestureVector2 pressedPosition;
|
|
SystemGestureVector2 currentPosition;
|
|
SystemGestureVector2 deltaVector;
|
|
std::uint64_t pressedTime;
|
|
std::uint64_t updatedTime;
|
|
std::uint64_t deltaTime;
|
|
};
|
|
|
|
std::mutex primitiveTouchMutex;
|
|
std::vector<TrackedTouch> primitiveTouches;
|
|
|
|
struct TouchSample {
|
|
std::uint16_t primitiveId;
|
|
SystemGestureVector2 position;
|
|
};
|
|
|
|
std::vector<TouchSample> reportSamples(const PadData& report) {
|
|
std::vector<TouchSample> samples;
|
|
const std::uint8_t count = report.touch_data_touch_num;
|
|
if (count > 0)
|
|
samples.push_back(TouchSample{report.touch_data_touch0_id,
|
|
SystemGestureVector2{static_cast<float>(report.touch_data_touch0_x), static_cast<float>(report.touch_data_touch0_y)}});
|
|
if (count > 1)
|
|
samples.push_back(TouchSample{report.touch_data_touch1_id,
|
|
SystemGestureVector2{static_cast<float>(report.touch_data_touch1_x), static_cast<float>(report.touch_data_touch1_y)}});
|
|
return samples;
|
|
}
|
|
|
|
void sampleReport(const PadData& report) {
|
|
std::erase_if(primitiveTouches, [](const TrackedTouch& touch) { return touch.eventState == TOUCH_STATE_END; });
|
|
for (TrackedTouch& touch : primitiveTouches) {
|
|
touch.sampled = false;
|
|
touch.isUpdated = false;
|
|
}
|
|
const std::uint64_t time = report.timestamp;
|
|
for (const TouchSample& sample : reportSamples(report)) {
|
|
const auto tracked = std::find_if(primitiveTouches.begin(), primitiveTouches.end(),
|
|
[&](const TrackedTouch& touch) { return touch.primitiveId == sample.primitiveId; });
|
|
if (tracked == primitiveTouches.end()) {
|
|
TrackedTouch touch{};
|
|
touch.primitiveId = sample.primitiveId;
|
|
touch.eventState = TOUCH_STATE_BEGIN;
|
|
touch.isUpdated = true;
|
|
touch.sampled = true;
|
|
touch.pressedPosition = sample.position;
|
|
touch.currentPosition = sample.position;
|
|
touch.pressedTime = time;
|
|
touch.updatedTime = time;
|
|
primitiveTouches.push_back(touch);
|
|
continue;
|
|
}
|
|
const SystemGestureVector2 previous = tracked->currentPosition;
|
|
tracked->deltaVector = SystemGestureVector2{sample.position.x - previous.x, sample.position.y - previous.y};
|
|
tracked->currentPosition = sample.position;
|
|
tracked->deltaTime = time >= tracked->updatedTime ? time - tracked->updatedTime : 0;
|
|
tracked->isUpdated = tracked->eventState != TOUCH_STATE_ACTIVE || tracked->deltaVector.x != 0.0f || tracked->deltaVector.y != 0.0f;
|
|
tracked->eventState = TOUCH_STATE_ACTIVE;
|
|
tracked->sampled = true;
|
|
tracked->updatedTime = time;
|
|
}
|
|
for (TrackedTouch& touch : primitiveTouches) {
|
|
if (touch.sampled) continue;
|
|
touch.deltaVector = SystemGestureVector2{0.0f, 0.0f};
|
|
touch.deltaTime = time >= touch.updatedTime ? time - touch.updatedTime : 0;
|
|
touch.eventState = TOUCH_STATE_END;
|
|
touch.isUpdated = true;
|
|
touch.updatedTime = time;
|
|
}
|
|
}
|
|
|
|
SystemGesturePrimitiveTouchEvent buildPrimitiveTouchEvent(const TrackedTouch& touch) {
|
|
SystemGesturePrimitiveTouchEvent event{};
|
|
event.event_state = touch.eventState;
|
|
event.primitive_id = touch.primitiveId;
|
|
event.is_updated = touch.isUpdated ? 1 : 0;
|
|
event.pressed_position = touch.pressedPosition;
|
|
event.current_position = touch.currentPosition;
|
|
event.delta_vector = touch.deltaVector;
|
|
event.delta_time = touch.deltaTime;
|
|
event.elapsed_time = touch.updatedTime - touch.pressedTime;
|
|
return event;
|
|
}
|
|
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
int APS5_VABI sceSystemGestureAppendTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureClose(int32_t gesture_handle) {
|
|
return gesture_handle == GESTURE_HANDLE ? 0 : SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureCreateTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer, int32_t type, const SystemGestureRectangle* rectangle, const void* param) {
|
|
(void)param;
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
RecognizerState state{};
|
|
state.magic = RECOGNIZER_STATE_MAGIC;
|
|
state.gestureType = type;
|
|
state.hasRectangle = rectangle ? 1 : 0;
|
|
if (rectangle) state.rectangle = *rectangle;
|
|
storeRecognizerState(recognizer, state);
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureFinalizePrimitiveTouchRecognizer(void) {
|
|
std::lock_guard lock(primitiveTouchMutex);
|
|
primitiveTouches.clear();
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetPrimitiveTouchEventByIndex(int32_t gesture_handle, uint32_t index, SystemGesturePrimitiveTouchEvent* event) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
std::lock_guard lock(primitiveTouchMutex);
|
|
if (index >= primitiveTouches.size()) return SCE_SYSTEM_GESTURE_ERROR_INDEX_OUT_OF_ARRAY;
|
|
if (!event) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
*event = buildPrimitiveTouchEvent(primitiveTouches[index]);
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetPrimitiveTouchEventByPrimitiveID(int32_t gesture_handle, uint16_t primitiveId, SystemGesturePrimitiveTouchEvent* event) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!event) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
std::lock_guard lock(primitiveTouchMutex);
|
|
const auto tracked = std::find_if(primitiveTouches.begin(), primitiveTouches.end(),
|
|
[&](const TrackedTouch& touch) { return touch.primitiveId == primitiveId; });
|
|
if (tracked == primitiveTouches.end())
|
|
throw std::runtime_error(std::string(__func__) + ": no primitive touch event with id " + std::to_string(primitiveId));
|
|
*event = buildPrimitiveTouchEvent(*tracked);
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetPrimitiveTouchEvents(int32_t gesture_handle, SystemGesturePrimitiveTouchEvent* event_buffer, uint32_t capacity_of_buffer, uint32_t* number_of_event) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!number_of_event) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
std::lock_guard lock(primitiveTouchMutex);
|
|
const std::uint32_t reported = static_cast<std::uint32_t>(std::min<std::size_t>(primitiveTouches.size(), capacity_of_buffer));
|
|
if (reported > 0 && !event_buffer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
for (std::uint32_t i = 0; i < reported; ++i) event_buffer[i] = buildPrimitiveTouchEvent(primitiveTouches[i]);
|
|
*number_of_event = reported;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetPrimitiveTouchEventsCount(int32_t gesture_handle) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
std::lock_guard lock(primitiveTouchMutex);
|
|
return static_cast<int>(primitiveTouches.size());
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetTouchEventByEventID(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, uint32_t eventId, SystemGestureTouchEvent* event) {
|
|
(void)eventId;
|
|
(void)event;
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
return SCE_SYSTEM_GESTURE_ERROR_INDEX_OUT_OF_ARRAY;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetTouchEventByIndex(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, uint32_t index, SystemGestureTouchEvent* event) {
|
|
(void)index;
|
|
(void)event;
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
return SCE_SYSTEM_GESTURE_ERROR_INDEX_OUT_OF_ARRAY;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetTouchEvents(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, SystemGestureTouchEvent* event_buffer, uint32_t capacity_of_buffer, uint32_t* number_of_event) {
|
|
(void)recognizer;
|
|
(void)event_buffer;
|
|
(void)capacity_of_buffer;
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!number_of_event) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
*number_of_event = 0;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetTouchEventsCount(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer) {
|
|
(void)recognizer;
|
|
return gesture_handle == GESTURE_HANDLE ? 0 : SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureGetTouchRecognizerInformation(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, SystemGestureTouchRecognizerInformation* information) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer || !information) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
RecognizerState state{};
|
|
if (!loadRecognizerState(recognizer, state))
|
|
throw std::runtime_error(std::string(__func__) + ": recognizer was not created by sceSystemGestureCreateTouchRecognizer");
|
|
if (!state.hasRectangle)
|
|
throw std::runtime_error(std::string(__func__) + ": recognizer was created without a rectangle");
|
|
information->gesture_type = state.gestureType;
|
|
information->rectangle = state.rectangle;
|
|
information->updated_time = 0;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureInitializePrimitiveTouchRecognizer(const void* param) {
|
|
(void)param;
|
|
std::lock_guard lock(primitiveTouchMutex);
|
|
primitiveTouches.clear();
|
|
return 0;
|
|
}
|
|
|
|
int32_t APS5_VABI sceSystemGestureOpen(int32_t input_type, const void* param) {
|
|
(void)input_type;
|
|
(void)param;
|
|
return GESTURE_HANDLE;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureRemoveTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureResetPrimitiveTouchRecognizer(int32_t gesture_handle) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
std::lock_guard lock(primitiveTouchMutex);
|
|
primitiveTouches.clear();
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureResetTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureUpdateAllTouchRecognizer(int32_t gesture_handle) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureUpdatePrimitiveTouchRecognizer(int32_t gesture_handle, const void* param) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!param) return 0;
|
|
const auto* input = static_cast<const SystemGestureTouchPadData*>(param);
|
|
if (!input->pad_data_buffer || input->report_number <= 0) return 0;
|
|
std::lock_guard lock(primitiveTouchMutex);
|
|
for (std::int32_t i = 0; i < input->report_number; ++i) sampleReport(input->pad_data_buffer[i]);
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureUpdateTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureUpdateTouchRecognizerRectangle(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer, const SystemGestureRectangle* rectangle) {
|
|
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
|
|
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
if (!rectangle) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
|
|
RecognizerState state{};
|
|
if (loadRecognizerState(recognizer, state)) {
|
|
state.hasRectangle = 1;
|
|
state.rectangle = *rectangle;
|
|
storeRecognizerState(recognizer, state);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI sceSystemGestureDebugGetVersion() {
|
|
return 0x6a00;
|
|
}
|
|
|
|
}
|