mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-07-01 22:16:28 +02:00
393 lines
12 KiB
Diff
393 lines
12 KiB
Diff
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 <slouken@libsdl.org>
|
|
+
|
|
+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 <orbis/Pad.h>
|
|
+#include <orbis/UserService.h>
|
|
+#include <orbis/libkernel.h>
|
|
+
|
|
+#include <stdio.h> /* For the definition of NULL */
|
|
+#include <stdlib.h>
|
|
+
|
|
+#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
|