From 5d689110b671d5a6165ee427bfbcbfdc760d569d Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 29 Jun 2026 23:11:00 +0000 Subject: [PATCH] ps4 joystick --- .patch/sdl3/0002-ps4-joystick-driver.patch | 393 +++++++++++++++++++++ cpmfile.json | 6 +- src/tests/video_core/memory_tracker.cpp | 2 - 3 files changed, 398 insertions(+), 3 deletions(-) create mode 100644 .patch/sdl3/0002-ps4-joystick-driver.patch diff --git a/.patch/sdl3/0002-ps4-joystick-driver.patch b/.patch/sdl3/0002-ps4-joystick-driver.patch new file mode 100644 index 0000000000..793aae4283 --- /dev/null +++ b/.patch/sdl3/0002-ps4-joystick-driver.patch @@ -0,0 +1,393 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b0eeca8..171fb9c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -3655,15 +3655,18 @@ if (PLATFORM_PS4) + "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_sysrwlock.c" # Can be faked, if necessary + "${SDL3_SOURCE_DIR}/src/thread/pthread/SDL_systls.c" + "${SDL3_SOURCE_DIR}/src/thread/generic/SDL_syssem.c" ++ "${SDL3_SOURCE_DIR}/src/joystick/ps4/SDL_sysjoystick.c" + ) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") + set(HAVE_SDL_THREADS TRUE) + set(HAVE_SDL_TIMERS TRUE) + set(HAVE_SDL_TIME TRUE) ++ set(HAVE_SDL_JOYSTICK TRUE) + set(SDL_TIME_UNIX 1) + set(SDL_TIMER_UNIX 1) + set(SDL_THREAD_PTHREAD 1) ++ set(SDL_JOYSTICK_PS4 1) + endif () + + # We always need to have threads and timers around +diff --git a/build-scripts/rename_macros.py b/build-scripts/rename_macros.py +index b6063dd..363f4d4 100755 +--- a/build-scripts/rename_macros.py ++++ b/build-scripts/rename_macros.py +@@ -236,6 +236,7 @@ DEPRECATED_PLATFORM_MACROS = { + "SDL_JOYSTICK_N3DS", + "SDL_JOYSTICK_OS2", + "SDL_JOYSTICK_PS2", ++ "SDL_JOYSTICK_PS4", + "SDL_JOYSTICK_PSP", + "SDL_JOYSTICK_RAWINPUT", + "SDL_JOYSTICK_USBHID", +diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake +index 520b721..087d91b 100644 +--- a/include/build_config/SDL_build_config.h.cmake ++++ b/include/build_config/SDL_build_config.h.cmake +@@ -313,6 +313,7 @@ + #cmakedefine SDL_JOYSTICK_MFI 1 + #cmakedefine SDL_JOYSTICK_N3DS 1 + #cmakedefine SDL_JOYSTICK_PS2 1 ++#cmakedefine SDL_JOYSTICK_PS4 1 + #cmakedefine SDL_JOYSTICK_PSP 1 + #cmakedefine SDL_JOYSTICK_RAWINPUT 1 + #cmakedefine SDL_JOYSTICK_USBHID 1 +diff --git a/src/joystick/ps4/SDL_sysjoystick.c b/src/joystick/ps4/SDL_sysjoystick.c +new file mode 100644 +index 0000000..bd67ef6 +--- /dev/null ++++ b/src/joystick/ps4/SDL_sysjoystick.c +@@ -0,0 +1,339 @@ ++/* ++Simple DirectMedia Layer ++Copyright (C) 1997-2019 Sam Lantinga ++ ++This software is provided 'as-is', without any express or implied ++warranty. In no event will the authors be held liable for any damages ++arising from the use of this software. ++ ++Permission is granted to anyone to use this software for any purpose, ++including commercial applications, and to alter it and redistribute it ++freely, subject to the following restrictions: ++ ++1. The origin of this software must not be misrepresented; you must not ++ claim that you wrote the original software. If you use this software ++ in a product, an acknowledgment in the product documentation would be ++ appreciated but is not required. ++2. Altered source versions must be plainly marked as such, and must not be ++ misrepresented as being the original software. ++3. This notice may not be removed or altered from any source distribution. ++*/ ++#include "../../SDL_internal.h" ++ ++#ifdef __INTELLISENSE__ ++#define SDL_JOYSTICK_PS4 1 ++#endif ++ ++#if SDL_JOYSTICK_PS4 ++ ++/* This is the PSP implementation of the SDL joystick API */ ++#include ++#include ++#include ++ ++#include /* For the definition of NULL */ ++#include ++ ++#include "../SDL_sysjoystick.h" ++#include "../SDL_joystick_c.h" ++ ++// #include "SDL_events.h" ++// #include "SDL_error.h" ++// #include "SDL_mutex.h" ++// #include "SDL_timer.h" ++#include "../../thread/SDL_systhread.h" ++ ++#define MAX_PADS 4 ++#define DS4_BTN_COUNT 20 ++#define DS4_AXE_COUNT 6 // lsX/Y, rsX/Y, L2, R2 ++#define DS4_HAT_COUNT 1 ++ ++uint32_t nPads = 0; ++ ++OrbisUserServiceUserId userId, pad_users[MAX_PADS]; ++OrbisUserServiceLoginUserIdList userIdList; ++ ++int PS4_JoystickGetCount(void) ++{ ++ return nPads; ++} ++ ++void PS4_JoystickDetect(void) ++{ ++ if(ORBIS_OK != sceUserServiceGetLoginUserIdList(&userIdList)) { ++ printf("WARNING, sceUserServiceGetLoginUserIdList() failed for JoystickDetect()!\n"); ++ } ++ ++ nPads = 0; ++ for (int i = 0; i < ORBIS_USER_SERVICE_MAX_LOGIN_USERS; i++) { ++ userId = userIdList.userId[i]; ++ if (ORBIS_USER_SERVICE_USER_ID_INVALID != userId) { ++ int32_t handle = scePadOpen(userId, ORBIS_PAD_PORT_TYPE_STANDARD, 0, NULL); ++ if (handle > 0 || handle== ORBIS_PAD_ERROR_ALREADY_OPENED) { ++ if(handle>0) { ++ printf("@@@@ got pad[%d] handle %X\n", nPads, handle); ++ } ++ pad_users[nPads++] = userId; ++ if (nPads >= MAX_PADS) { ++ break; ++ } ++ } ++ } ++ } ++} ++ ++//#include "SDL_hints.h" ++ ++ ++/* Function to scan the system for joysticks. ++* Joystick 0 should be the system default joystick. ++* It should return number of joysticks, or -1 on an unrecoverable fatal error. ++*/ ++static bool PS4_JoystickInit(void) ++{ ++ SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); // Checks for keyboard focus ability, 'or something' ++ ++ int32_t res = sceUserServiceInitialize(NULL); ++ if(ORBIS_OK != res && ORBIS_USER_SERVICE_ERROR_ALREADY_INITIALIZED != res) { ++ return SDL_SetError("Error sceUserServiceInitialize() failed!"); ++ } ++ ++ if (ORBIS_OK != sceUserServiceGetInitialUser(&userId)) { ++ return SDL_SetError("Error sceUserServiceGetInitialUser() failed!"); ++ } ++ ++ if(ORBIS_OK != scePadInit()) { ++ return SDL_SetError("Error scePadInit() failed!"); ++ } ++ ++ PS4_JoystickDetect(); ++ return nPads; ++} ++ ++/* Function to get the device-dependent name of a joystick */ ++static const char * PS4_JoystickGetDeviceName(int device_index) ++{ ++ return "Dualshock4"; ++} ++ ++/* Function to get the player index of a joystick */ ++static int PS4_JoystickGetDevicePlayerIndex(int device_index) ++{ ++ if (device_index >= MAX_PADS) { ++ device_index = MAX_PADS - 1; ++ } ++ ++ for (int i = 0; i < ORBIS_USER_SERVICE_MAX_LOGIN_USERS; i++) { ++ if(pad_users[device_index] == userIdList.userId[i]) { ++ return i; ++ } ++ } ++ return -1; ++} ++ ++static SDL_GUID PS4_JoystickGetDeviceGUID(int device_index) ++{ ++ if (device_index >= MAX_PADS) { ++ device_index = MAX_PADS - 1; ++ } ++ ++ SDL_GUID guid; ++ SDL_zero(guid); ++ ((Uint32*)guid.data)[0] = 0x00000005; // 05000000; ++ ((Uint32*)guid.data)[0] = 0x00004c05; // 4c050000; ++ ((Uint32*)guid.data)[0] = 0x000009cc; // cc090000; ++ ((Uint32*)guid.data)[0] = 0x00008001; // 01800000; ++ // "050000004c050000cc09000001800000,PS4 Controller, ++ return guid; ++} ++ ++ ++/* Function to perform the mapping from device index to the instance id for this index */ ++static SDL_JoystickID PS4_JoystickGetDeviceInstanceID(int device_index) ++{ ++ if (device_index >= MAX_PADS) { ++ device_index = MAX_PADS - 1; ++ } ++ return scePadGetHandle(pad_users[device_index], ORBIS_PAD_PORT_TYPE_STANDARD, 0); ++} ++ ++/* Function to open a joystick for use. ++The joystick to open is specified by the device index. ++This should fill the nbuttons and naxes fields of the joystick structure. ++It returns 0, or -1 if there is an error. ++*/ ++static bool PS4_JoystickOpen(SDL_Joystick *joystick, int device_index) ++{ ++ if (device_index >= MAX_PADS) { ++ device_index = MAX_PADS - 1; ++ } ++ ++ PS4_JoystickDetect(); // should already be done but ... ++ ++ int32_t handle = PS4_JoystickGetDeviceInstanceID(device_index); // They are already open , ++ if (handle > 0) { ++ joystick->nbuttons = DS4_BTN_COUNT; ++ joystick->naxes = DS4_AXE_COUNT; ++ joystick->nhats = DS4_HAT_COUNT; ++ /* Create the joystick data structure */ ++ joystick->instance_id = handle; ++ return true; ++ } ++ printf("PS4_JoystickOpen(idx: %d) failed to get handled!\n", device_index); ++ return false; ++} ++ ++static bool PS4_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) ++{ ++ return SDL_Unsupported(); ++} ++ ++/* Function to update the state of a joystick - called as a device poll. ++* This function shouldn't update the joystick structure directly, ++* but instead should call SDL_PrivateJoystick*() to deliver events ++* and update joystick device state. ++*/ ++static void PS4_JoystickUpdate(SDL_Joystick *joystick) ++{ ++ OrbisPadData data; ++ ++ int ret = scePadReadState(joystick->instance_id, &data); ++ if (ret != ORBIS_OK || !data.connected) { ++ printf("Warning, Controller is not connected or failed to read data! \n"); ++ return; ++ } ++ ++ //a:b0,b:b1,x:b3,y:b2,leftshoulder:b4,rightshoulder:b5 ++ //back:b8,start:b9,guide:b10,leftstick:b11,rightstick:b12, ++ //dpdown:h0.4, dpleft:h0.8, dpright:h0.2, dpup:h0.1, ++ //leftx:a0,lefty:a1,lefttrigger:a2,rightx:a3,righty:a4,righttrigger:a5, ++ const static uint32_t ds4_map[DS4_BTN_COUNT] = { ++ ORBIS_PAD_BUTTON_CROSS, ORBIS_PAD_BUTTON_CIRCLE, ORBIS_PAD_BUTTON_SQUARE, ORBIS_PAD_BUTTON_TRIANGLE, ORBIS_PAD_BUTTON_L1, ORBIS_PAD_BUTTON_R1, ++ 0, /* b6? */ 0, /* b7? */ 0, /* no share/back btn atm */ ++ ORBIS_PAD_BUTTON_OPTIONS, 0 /* no guide button atm */, ORBIS_PAD_BUTTON_L3, ORBIS_PAD_BUTTON_R3, ++ ORBIS_PAD_BUTTON_UP, ORBIS_PAD_BUTTON_DOWN, ORBIS_PAD_BUTTON_LEFT, ORBIS_PAD_BUTTON_RIGHT, ++ ORBIS_PAD_BUTTON_TOUCH_PAD, ORBIS_PAD_BUTTON_L2, ORBIS_PAD_BUTTON_R2, ++ }; ++ ++ Uint32 s_btns = data.buttons; ++ Uint64 timestamp = SDL_GetTicksNS(); ++ ++ for (uint32_t bn = 0; bn < DS4_BTN_COUNT; bn++) { ++ SDL_SendJoystickButton(timestamp, joystick, bn, s_btns & ds4_map[bn]); ++ } ++ ++#define aS16(axe) -32768 + ((axe) << 8) ++ ++#define setA(n,axe) { Sint16 tmp = aS16(axe); if (tmp < -1000 || tmp > 1000) { SDL_SendJoystickButton(timestamp, joystick, (n), tmp); } } ++ setA(0, data.leftStick.x); ++ setA(1, data.leftStick.y); ++ setA(2, data.analogButtons.l2); ++ ++ setA(4, data.rightStick.x); ++ setA(5, data.rightStick.y); ++ setA(6, data.analogButtons.r2); ++ ++ Uint8 hat = SDL_HAT_CENTERED; ++ if (s_btns & ORBIS_PAD_BUTTON_UP) { hat |= SDL_HAT_UP; } ++ if (s_btns & ORBIS_PAD_BUTTON_DOWN) { hat |= SDL_HAT_DOWN; } ++ if (s_btns & ORBIS_PAD_BUTTON_LEFT) { hat |= SDL_HAT_LEFT; } ++ if (s_btns & ORBIS_PAD_BUTTON_RIGHT) { hat |= SDL_HAT_RIGHT; } ++ SDL_SendJoystickAxis(timestamp, joystick, 0, hat); ++} ++ ++/* Function to close a joystick after use */ ++void PS4_JoystickClose(SDL_Joystick *joystick) ++{ ++ scePadClose(joystick->instance_id); ++#if 0 ++ if (joystick->hwdata) ++ SDL_free(joystick->hwdata); ++#endif ++} ++ ++/* Function to perform any system-specific joystick related cleanup */ ++static void PS4_JoystickQuit(void) ++{ ++ nPads = 0; ++} ++ ++/* New shit in SDL3 */ ++static bool PS4_JoystickIsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name) ++{ ++ // We don't override any other drivers ++ return false; ++} ++ ++// Function to get the device-dependent path of a joystick ++static const char *PS4_JoystickGetDevicePath(int index) ++{ ++ return NULL; ++} ++ ++// Function to get the Steam virtual gamepad slot of a joystick ++static int PS4_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index) ++{ ++ return -1; ++} ++ ++// Function to set the player index of a joystick ++static void PS4_JoystickSetDevicePlayerIndex(int device_index, int player_index) ++{ ++} ++ ++// Rumble functionality ++static bool PS4_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint16 right) ++{ ++ return SDL_Unsupported(); ++} ++ ++// LED functionality ++static bool PS4_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) ++{ ++ return SDL_Unsupported(); ++} ++ ++// General effects ++static bool PS4_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size) ++{ ++ return SDL_Unsupported(); ++} ++ ++// Sensor functionality ++static bool PS4_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled) ++{ ++ return SDL_Unsupported(); ++} ++ ++static bool PS4_GetGamepadMapping(int device_index, SDL_GamepadMapping *out) ++{ ++ return false; ++} ++ ++SDL_JoystickDriver SDL_PS4_JoystickDriver = ++{ ++ PS4_JoystickInit, ++ PS4_JoystickGetCount, ++ PS4_JoystickDetect, ++ PS4_JoystickIsDevicePresent, ++ PS4_JoystickGetDeviceName, ++ PS4_JoystickGetDevicePath, ++ PS4_JoystickGetDeviceSteamVirtualGamepadSlot, ++ PS4_JoystickGetDevicePlayerIndex, ++ PS4_JoystickSetDevicePlayerIndex, ++ PS4_JoystickGetDeviceGUID, ++ PS4_JoystickGetDeviceInstanceID, ++ PS4_JoystickOpen, ++ PS4_JoystickRumble, ++ PS4_JoystickRumbleTriggers, ++ PS4_JoystickSetLED, ++ PS4_JoystickSendEffect, ++ PS4_JoystickSetSensorsEnabled, ++ PS4_JoystickUpdate, ++ PS4_JoystickClose, ++ PS4_JoystickQuit, ++ PS4_GetGamepadMapping, ++}; ++ ++ ++#endif /* SDL_JOYSTICK_PS4 */ +\ No newline at end of file diff --git a/cpmfile.json b/cpmfile.json index 2210fa4690..a7217cfdf6 100644 --- a/cpmfile.json +++ b/cpmfile.json @@ -276,7 +276,11 @@ "package": "SDL3", "repo": "libsdl-org/SDL", "tag": "release-%VERSION%", - "version": "3.4.8" + "version": "3.4.8", + "patches": [ + "0001-ps4.patch", + "0002-ps4-joystick-driver.patch" + ] }, "sdl3-ci": { "ci": true, diff --git a/src/tests/video_core/memory_tracker.cpp b/src/tests/video_core/memory_tracker.cpp index 70a469586f..5fd8037446 100644 --- a/src/tests/video_core/memory_tracker.cpp +++ b/src/tests/video_core/memory_tracker.cpp @@ -573,7 +573,6 @@ TEST_CASE("MemoryTracker: FlushCachedWrites batching") { REQUIRE(std::get<1>(calls[0]) == PAGE * 3); } -#if 0 TEST_CASE("DeviceMemoryManager: UpdatePagesCachedBatch basic") { Core::DeviceMemory device_memory; Tegra::MaxwellDeviceMemoryManager manager(device_memory); @@ -588,4 +587,3 @@ TEST_CASE("DeviceMemoryManager: UpdatePagesCachedBatch basic") { manager.UpdatePagesCachedBatch(ranges, 1); SUCCEED("UpdatePagesCachedBatch executed without error"); } -#endif