eden-miror/.patch/sdl3/0002-ps4-drivers.patch
2026-06-30 04:24:00 +00:00

1084 lines
34 KiB
Diff

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b0eeca8..076cbe4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3655,15 +3655,21 @@ 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"
+ "${SDL3_SOURCE_DIR}/src/video/ps4/SDL_ps4video.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(HAVE_SDL_VIDEO TRUE)
set(SDL_TIME_UNIX 1)
set(SDL_TIMER_UNIX 1)
set(SDL_THREAD_PTHREAD 1)
+ set(SDL_JOYSTICK_PS4 1)
+ set(SDL_VIDEO_DRIVER_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..9360042 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",
@@ -315,6 +316,7 @@ DEPRECATED_PLATFORM_MACROS = {
"SDL_VIDEO_DRIVER_OFFSCREEN",
"SDL_VIDEO_DRIVER_OS2",
"SDL_VIDEO_DRIVER_PS2",
+ "SDL_VIDEO_DRIVER_PS4",
"SDL_VIDEO_DRIVER_PSP",
"SDL_VIDEO_DRIVER_QNX",
"SDL_VIDEO_DRIVER_RISCOS",
diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake
index 520b721..239a874 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
@@ -408,6 +409,7 @@
#cmakedefine SDL_VIDEO_DRIVER_NGAGE 1
#cmakedefine SDL_VIDEO_DRIVER_OFFSCREEN 1
#cmakedefine SDL_VIDEO_DRIVER_PS2 1
+#cmakedefine SDL_VIDEO_DRIVER_PS4 1
#cmakedefine SDL_VIDEO_DRIVER_PSP 1
#cmakedefine SDL_VIDEO_DRIVER_RISCOS 1
#cmakedefine SDL_VIDEO_DRIVER_ROCKCHIP 1
diff --git a/src/joystick/ps4/SDL_sysjoystick.c b/src/joystick/ps4/SDL_sysjoystick.c
new file mode 100644
index 0000000..975b419
--- /dev/null
+++ b/src/joystick/ps4/SDL_sysjoystick.c
@@ -0,0 +1,363 @@
+/*
+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
+uint32_t nPads = 0;
+
+//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,
+static const uint32_t button_map[] = {
+ [SDL_GAMEPAD_BUTTON_SOUTH] = ORBIS_PAD_BUTTON_CROSS,
+ [SDL_GAMEPAD_BUTTON_EAST] = ORBIS_PAD_BUTTON_CIRCLE,
+ [SDL_GAMEPAD_BUTTON_WEST] = ORBIS_PAD_BUTTON_SQUARE,
+ [SDL_GAMEPAD_BUTTON_NORTH] = ORBIS_PAD_BUTTON_TRIANGLE,
+ [SDL_GAMEPAD_BUTTON_BACK] = ORBIS_PAD_BUTTON_L1,
+ [SDL_GAMEPAD_BUTTON_GUIDE] = ORBIS_PAD_BUTTON_R1,
+ [SDL_GAMEPAD_BUTTON_START] = ORBIS_PAD_BUTTON_OPTIONS,
+ [SDL_GAMEPAD_BUTTON_LEFT_SHOULDER] = ORBIS_PAD_BUTTON_L3,
+ [SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER] = ORBIS_PAD_BUTTON_R3,
+ [SDL_GAMEPAD_BUTTON_DPAD_UP] = ORBIS_PAD_BUTTON_UP,
+ [SDL_GAMEPAD_BUTTON_DPAD_DOWN] = ORBIS_PAD_BUTTON_DOWN,
+ [SDL_GAMEPAD_BUTTON_DPAD_LEFT] = ORBIS_PAD_BUTTON_LEFT,
+ [SDL_GAMEPAD_BUTTON_DPAD_RIGHT] = ORBIS_PAD_BUTTON_RIGHT,
+ [SDL_GAMEPAD_BUTTON_MISC1] = ORBIS_PAD_BUTTON_TOUCH_PAD,
+ [SDL_GAMEPAD_BUTTON_LEFT_STICK] = ORBIS_PAD_BUTTON_L2,
+ [SDL_GAMEPAD_BUTTON_RIGHT_STICK] = ORBIS_PAD_BUTTON_R2,
+};
+
+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 "DualShock 4 Controller";
+}
+
+/* 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)[1] = 0x00004c05; // 4c050000;
+ ((Uint32*)guid.data)[2] = 0x000009cc; // cc090000;
+ ((Uint32*)guid.data)[3] = 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 = SDL_arraysize(button_map);
+ joystick->naxes = 6; // lsX/Y, rsX/Y, L2, R2
+ joystick->nhats = 1;
+ /* 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)
+{
+ static Uint32 old_buttons = 0;
+ Uint64 timestamp = SDL_GetTicksNS();
+
+ 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;
+ }
+
+ Uint32 buttons = data.buttons;
+ Uint32 changed = old_buttons ^ buttons;
+ old_buttons = data.buttons;
+ for (uint32_t bn = 0; bn < SDL_arraysize(button_map); bn++) {
+ if (changed & button_map[bn]) {
+ SDL_SendJoystickButton(timestamp, joystick, bn, buttons & button_map[bn]);
+ }
+ }
+
+#define setA(n, axe) \
+ do { \
+ Sint16 tmp = (-32768 + ((axe) << 8)); \
+ if (tmp < -1000 || tmp > 1000) { \
+ SDL_SendJoystickButton(timestamp, joystick, (n), tmp); \
+ } \
+ } while (0);
+
+ 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 (buttons & ORBIS_PAD_BUTTON_UP) {
+ hat |= SDL_HAT_UP;
+ }
+ if (buttons & ORBIS_PAD_BUTTON_DOWN) {
+ hat |= SDL_HAT_DOWN;
+ }
+ if (buttons & ORBIS_PAD_BUTTON_LEFT) {
+ hat |= SDL_HAT_LEFT;
+ }
+ if (buttons & 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/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 1fdc5bf..5c083bc 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -530,6 +530,7 @@ extern VideoBootStrap HAIKU_bootstrap;
extern VideoBootStrap UIKIT_bootstrap;
extern VideoBootStrap Android_bootstrap;
extern VideoBootStrap PS2_bootstrap;
+extern VideoBootStrap PS4_bootstrap;
extern VideoBootStrap PSP_bootstrap;
extern VideoBootStrap VITA_bootstrap;
extern VideoBootStrap RISCOS_bootstrap;
diff --git a/src/video/ps4/SDL_ps4video.c b/src/video/ps4/SDL_ps4video.c
new file mode 100644
index 0000000..34ca5a4
--- /dev/null
+++ b/src/video/ps4/SDL_ps4video.c
@@ -0,0 +1,498 @@
+/*
+ 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"
+#include "SDL3/SDL_error.h"
+
+#if SDL_VIDEO_DRIVER_PS4
+
+//#include <gnm.h>
+#include <orbis/Pad.h>
+#include <orbis/UserService.h>
+#include <orbis/VideoOut.h>
+#include <orbis/libkernel.h>
+
+/* SDL internals */
+#include "../SDL_sysvideo.h"
+//#include "SDL_version.h"
+//#include "SDL_syswm.h"
+//#include "SDL_events.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_keyboard_c.h"
+
+#include "SDL_ps4video.h"
+
+static int PS4_Available(void);
+static SDL_VideoDevice *PS4_Create();
+
+VideoBootStrap PS4_bootstrap = {
+ "PS4",
+ "PS4 Video Driver",
+ PS4_Create,
+ PS4_ShowMessageBox,
+ false
+};
+
+#define D_FN()
+
+static SDL_VideoData * GetVideoInternalData(SDL_VideoDevice *_this) {
+ return ((SDL_VideoData *)_this->internal);
+}
+#define VData GetVideoInternalData(_this)
+static uint8_t* CurrentBuffer(SDL_VideoDevice *_this) {
+ return VData->addrList[(VData->currBuffer) & 3];
+}
+
+static int32_t IsFlipPending(SDL_VideoDevice *_this) {
+ return sceVideoOutIsFlipPending(VData->h_vout) > 0;
+}
+
+static void WaitOnFlip(SDL_VideoDevice *_this) {
+ int out = 0;
+ OrbisKernelEvent ev;
+ while (IsFlipPending(_this)) {
+ sceKernelWaitEqueue(VData->flipQueue, &ev, 1, &out, 0);
+ }
+}
+
+static void SubmitFlip(SDL_VideoDevice *_this) //s64 buffer = -1, u64 arg = 0)
+{
+ sceVideoOutSubmitFlip(VData->h_vout, VData->currBuffer, ORBIS_VIDEO_OUT_FLIP_VSYNC, 0);
+ VData->currBuffer = ((VData->currBuffer + 1) % VOUT_NUM_BUFFERS);
+ WaitOnFlip(_this);
+}
+
+static void FreeFramebuffers(SDL_VideoDevice *_this)
+{
+ for (uint32_t i = 0; i < VOUT_NUM_BUFFERS; i++)
+ sceVideoOutUnregisterBuffers(VData->h_vout, i);
+
+ sceKernelMunmap((void*)VData->mapAddr, VData->memSize);
+ sceKernelReleaseDirectMemory(VData->phyAddr, VData->memSize);
+}
+
+static size_t AlignUp(size_t v, size_t a)
+{
+ return ((v) + (a - 1)) & ~(a - 1);
+}
+
+static int AllocFramebuffers(SDL_VideoDevice *_this)
+{
+ size_t alignTo = 1024 * 1024;
+ size_t pixelCount = VData->attr.width * VData->attr.height, Bpp = 4; // 32bpp
+ size_t alignedSize = AlignUp(pixelCount * Bpp, alignTo);
+
+ VData->bufSize = pixelCount * Bpp;
+ VData->memSize = alignedSize * VOUT_NUM_BUFFERS;
+
+ int32_t res = ORBIS_OK;
+
+ if (ORBIS_OK != (res = sceKernelAllocateDirectMemory(0, ORBIS_KERNEL_MAIN_DMEM_SIZE, VData->memSize, alignTo, ORBIS_KERNEL_WC_GARLIC, &VData->phyAddr))) {
+ SDL_SetError("sceKernelAllocateDirectMemory() Failed "); // printf("Error, sceKernelAllocateDirectMemory() Failed with 0x%08X\n", (uint32_t)res);
+ return -1;
+ }
+ if (ORBIS_OK != (res = sceKernelMapDirectMemory((void**)&VData->mapAddr, VData->memSize, ORBIS_KERNEL_PROT_CPU_RW | ORBIS_KERNEL_PROT_GPU_RW, 0, VData->phyAddr, alignTo))) {
+ SDL_SetError("sceKernelMapDirectMemory() Failed "); // printf("Error, sceKernelMapDirectMemory() Failed with 0x%08X\n", (uint32_t)res);
+ return -1;
+ }
+
+ for (uint32_t i = 0; i < VOUT_NUM_BUFFERS; i++) {
+ VData->addrList[i] = VData->mapAddr + (i * alignedSize); // fbAlloc(memSize, alignTo)
+ // printf("Buffer[%X] %p \n", i, (void*)VData->addrList[i]);
+ }
+
+ if (ORBIS_OK != (res = sceVideoOutRegisterBuffers(VData->h_vout, 0, (void* const*)VData->addrList, VOUT_NUM_BUFFERS, &VData->attr))) {
+ SDL_SetError("sceVideoOutRegisterBuffers() Failed "); // printf("Error, sceVideoOutRegisterBuffers() Failed with 0x%08X\n", (uint32_t)res);
+ FreeFramebuffers(_this);
+ return -1;
+ }
+ return res;
+}
+
+
+static int vout_init(SDL_VideoDevice *_this)
+{
+ int handle = 0;
+ OrbisVideoOutResolutionStatus res;
+
+ handle = sceVideoOutOpen(ORBIS_USER_SERVICE_USER_ID_SYSTEM, ORBIS_VIDEO_OUT_BUS_MAIN, 0, NULL);
+ if(handle <= 0) {
+ SDL_SetError("sceVideoOutOpen() failed");
+ return -1;
+ }
+ VData->h_vout = handle;
+
+ if (0 == sceVideoOutGetResolutionStatus(handle, &res)) {
+ VData->width = res.width;
+ VData->height = res.height;
+ }
+
+ memset(&VData->attr, 0, sizeof(VData->attr));
+ VData->attr.width = VData->width;
+ VData->attr.height = VData->height;
+ VData->attr.aspect = ORBIS_VIDEO_OUT_ASPECT_RATIO_16_9;
+ VData->attr.format = ORBIS_VIDEO_OUT_PIXEL_FORMAT_A8B8G8R8_SRGB;
+ VData->attr.tmode = ORBIS_VIDEO_OUT_TILING_MODE_LINEAR; // (!tile) ? : 0; // change to tiled later, GpuMode must be NEO for pro
+ VData->attr.pixelPitch = VData->width;
+
+ if (ORBIS_OK != sceKernelCreateEqueue(&VData->flipQueue, "flipQueue") ||
+ ORBIS_OK != sceVideoOutAddFlipEvent(VData->flipQueue, handle, NULL)) {
+ SDL_SetError("Failed to create/add flip queue\n");
+ return -1;
+ }
+
+ if (ORBIS_OK != AllocFramebuffers(_this)) {
+ SDL_SetError("Failed to AllocFramebuffers!\n");
+ return -1;
+ }
+ sceVideoOutSetFlipRate(handle, 0); // 0=60fps , 1=30fps, 2=20fps?
+ return 0;
+}
+
+void vout_term(SDL_VideoDevice *_this) {
+ FreeFramebuffers(_this);
+ sceVideoOutClose(VData->h_vout);
+ VData->h_vout = 0;
+}
+
+
+/* unused
+static bool PS4_initialized = false;
+*/
+static int PS4_Available(void)
+{
+ return 1;
+}
+
+static void PS4_Destroy(SDL_VideoDevice * device)
+{
+ if (device->internal != NULL) {
+ device->internal = NULL;
+ }
+}
+
+static SDL_VideoDevice *PS4_Create()
+{
+ SDL_VideoDevice *device;
+ SDL_VideoData *phdata;
+#if PS4_VIDEO_GL
+ SDL_GLDriverData *gldata;
+#endif
+
+ int status;
+
+ /* Check if PS4 could be initialized */
+ status = PS4_Available();
+ if (status == 0) {
+ /* PS4 could not be used */
+ return NULL;
+ }
+
+ /* Initialize SDL_VideoDevice structure */
+ device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+ if (device == NULL) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ /* Initialize internal PS4 specific data */
+ phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
+ if (phdata == NULL) {
+ SDL_OutOfMemory();
+ SDL_free(device);
+ return NULL;
+ }
+
+#if PS4_VIDEO_GL
+ gldata = (SDL_GLDriverData *) SDL_calloc(1, sizeof(SDL_GLDriverData));
+ if (gldata == NULL) {
+ SDL_OutOfMemory();
+ SDL_free(device);
+ SDL_free(phdata);
+ return NULL;
+ }
+ phdata->egl_initialized = false;
+ device->gl_data = gldata;
+#endif
+
+ phdata->h_vout = 0; // VideoOut handle
+ phdata->width = 1920;
+ phdata->height = 1080; // defaults
+
+ device->internal = phdata;
+
+ /* Setup amount of available displays */
+ device->num_displays = 0;
+
+ /* Set device free function */
+ device->free = PS4_Destroy;
+
+ /* Setup all functions which we can handle */
+ device->VideoInit = PS4_VideoInit;
+ device->VideoQuit = PS4_VideoQuit;
+ device->GetDisplayModes = PS4_GetDisplayModes;
+ device->SetDisplayMode = PS4_SetDisplayMode;
+ device->CreateSDLWindow = PS4_CreateWindow;
+ device->SetWindowTitle = PS4_SetWindowTitle;
+ device->SetWindowIcon = PS4_SetWindowIcon;
+ device->SetWindowPosition = PS4_SetWindowPosition;
+ device->SetWindowSize = PS4_SetWindowSize;
+ device->ShowWindow = PS4_ShowWindow;
+ device->HideWindow = PS4_HideWindow;
+ device->RaiseWindow = PS4_RaiseWindow;
+ device->MaximizeWindow = PS4_MaximizeWindow;
+ device->MinimizeWindow = PS4_MinimizeWindow;
+ device->RestoreWindow = PS4_RestoreWindow;
+ device->DestroyWindow = PS4_DestroyWindow;
+#if PS4_VIDEO_GL
+ device->GetWindowWMInfo = PS4_GetWindowWMInfo;
+ device->GL_LoadLibrary = PS4_GL_LoadLibrary;
+ device->GL_GetProcAddress = PS4_GL_GetProcAddress;
+ device->GL_UnloadLibrary = PS4_GL_UnloadLibrary;
+ device->GL_CreateContext = PS4_GL_CreateContext;
+ device->GL_MakeCurrent = PS4_GL_MakeCurrent;
+ device->GL_SetSwapInterval = PS4_GL_SetSwapInterval;
+ device->GL_GetSwapInterval = PS4_GL_GetSwapInterval;
+ device->GL_SwapWindow = PS4_GL_SwapWindow;
+ device->GL_DeleteContext = PS4_GL_DeleteContext;
+#endif
+ device->HasScreenKeyboardSupport = PS4_HasScreenKeyboardSupport;
+ /*
+ device->ShowScreenKeyboard = PS4_ShowScreenKeyboard;
+ device->HideScreenKeyboard = PS4_HideScreenKeyboard;
+ */
+ /*device->IsScreenKeyboardShown = PS4_IsScreenKeyboardShown;*/
+#if 1
+ device->CreateWindowFramebuffer = PS4_CreateWindowFramebuffer;
+ device->UpdateWindowFramebuffer = PS4_UpdateWindowFramebuffer;
+ device->DestroyWindowFramebuffer = PS4_DestroyWindowFramebuffer;
+#endif
+ device->PumpEvents = PS4_PumpEvents;
+
+ return device;
+}
+
+/*****************************************************************************/
+/* SDL Video and Display initialization/handling functions */
+/*****************************************************************************/
+bool PS4_VideoInit(SDL_VideoDevice *_this)
+{
+ uint8_t *ppp = (uint8_t*)SDL_malloc(1024 * 1024 * 128);
+ if (!ppp) {
+ return SDL_OutOfMemory();
+ }
+ SDL_free(ppp);
+
+ SDL_VideoDisplay display;
+ SDL_DisplayMode current_mode;
+ SDL_zero(current_mode);
+ if (ORBIS_OK != vout_init(_this)) {
+ return false;
+ }
+
+ current_mode.w = GetVideoInternalData(_this)->width;
+ current_mode.h = GetVideoInternalData(_this)->height;
+
+ current_mode.refresh_rate = 60;
+ /* 32 bpp for default */
+ current_mode.format = SDL_PIXELFORMAT_ABGR8888;
+ current_mode.internal = NULL;
+
+ SDL_zero(display);
+ display.desktop_mode = current_mode;
+ display.current_mode = &display.desktop_mode;
+ display.internal = NULL;
+ SDL_AddVideoDisplay(&display, false);
+ return true;
+}
+
+void PS4_VideoQuit(SDL_VideoDevice *_this)
+{
+ vout_term(_this);
+}
+
+bool PS4_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay * display)
+{
+ return true;
+}
+
+bool PS4_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
+{
+ return 0;
+}
+
+bool PS4_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
+{
+ /* Free the old framebuffer surface */
+ SDL_WindowData *data = (SDL_WindowData *) window->internal;
+ SDL_Surface *surface = data->surface;
+ SDL_DestroySurface(surface);
+
+ /* Create a new one */
+ int w, h;
+ SDL_GetWindowSize(window, &w, &h);
+ surface = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_XBGR8888);
+ if (!surface) {
+ SDL_SetError("SDL_CreateSurface() FAILED");
+ return false;
+ }
+
+ /* Save the info and return! */
+ data->surface = surface;
+ *format = SDL_PIXELFORMAT_XBGR8888;
+ *pixels = surface->pixels;
+ *pitch = surface->pitch;
+ return true;
+}
+
+bool PS4_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window, const SDL_Rect * rects, int numrects)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->internal;
+ SDL_Surface *surface = data->surface;
+ if (!surface) {
+ return SDL_SetError("Couldn't find framebuffer surface for window");
+ }
+
+ /* Send the data to the display */
+ uint32_t * pDst = (uint32_t*)CurrentBuffer(_this);
+ if (!pDst) {
+ SDL_SetError("GOT INVALID FB PTR");
+ return false;
+ }
+ memset(pDst, 0, VData->bufSize);
+
+ /// annoyances ... calculate actual window coords and clip
+ SDL_VideoData *videoData = VData;
+ uint32_t xOffs = window->x, yOffs = window->y;
+ uint32_t drawW = window->w, drawH = window->h;
+
+ xOffs = (xOffs < videoData->width) ? xOffs : videoData->width - 1;
+ yOffs = (yOffs < videoData->height)? yOffs : videoData->height- 1;
+
+ drawW = ((xOffs + drawW) <= videoData->width) ? drawW : (videoData->width - xOffs);
+ drawH = ((yOffs + drawH) <= videoData->height)? drawH : (videoData->height- yOffs);
+
+ for (uint32_t y = 0; y < drawH; y++) {
+ memcpy(&pDst[videoData->width * (yOffs+y) + xOffs], &((uint8_t*)surface->pixels)[y*surface->pitch], sizeof(uint32_t)*drawW); // surface->pitch);
+ }
+
+ SubmitFlip(_this);
+ return true;
+}
+
+void PS4_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window)
+{
+
+ SDL_WindowData *data = (SDL_WindowData *) window->internal;
+ SDL_DestroySurface(data->surface);
+ data->surface = NULL;
+}
+
+void PS4_PumpEvents(SDL_VideoDevice *_this)
+{
+}
+
+bool PS4_CreateWindow(SDL_VideoDevice *_this, SDL_Window * window, SDL_PropertiesID properties)
+{
+ SDL_WindowData *wdata;
+
+ /* Allocate window internal data */
+ wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
+ if (wdata == NULL) {
+ return SDL_OutOfMemory();
+ }
+
+ /* Setup driver data for this window */
+ if (window) {
+ window->internal = wdata;
+ SDL_VideoData *videoData = VData;
+ /*if (_this->num_displays > 0) {
+ _this->displays[0].fullscreen_window = window;
+ window->fullscreen_mode = _this->displays[0].current_mode;
+ }*/
+ }
+ /* Window has been successfully created */
+ return 0;
+}
+
+void PS4_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+bool PS4_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window * window, SDL_Surface * icon)
+{
+ return false;
+}
+bool PS4_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window * window)
+{
+ return false;
+}
+void PS4_SetWindowSize(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+void PS4_ShowWindow(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+void PS4_HideWindow(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+void PS4_RaiseWindow(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+void PS4_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+void PS4_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+void PS4_RestoreWindow(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+void PS4_DestroyWindow(SDL_VideoDevice *_this, SDL_Window * window)
+{
+}
+
+/*****************************************************************************/
+/* SDL Window Manager function */
+/*****************************************************************************/
+/* TO Write Me */
+bool PS4_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
+{
+ return false;
+}
+void PS4_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
+{
+}
+void PS4_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window)
+{
+}
+bool PS4_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window)
+{
+ return false;
+}
+
+bool PS4_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID)
+{
+ return false;
+}
+
+#endif /* SDL_VIDEO_DRIVER_PS4 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/ps4/SDL_ps4video.h b/src/video/ps4/SDL_ps4video.h
new file mode 100644
index 0000000..6cce9a2
--- /dev/null
+++ b/src/video/ps4/SDL_ps4video.h
@@ -0,0 +1,126 @@
+/*
+ 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.
+*/
+
+#ifndef SDL_ps4video_h_
+#define SDL_ps4video_h_
+
+
+#include "../../SDL_internal.h"
+#include "../SDL_sysvideo.h"
+
+#include <orbis/UserService.h>
+#include <orbis/VideoOut.h>
+#include <orbis/libkernel.h>
+
+#define VOUT_NUM_BUFFERS 2
+
+typedef struct SDL_VideoData
+{
+ int h_vout; // VideoOut handle
+ uint32_t width, height;
+
+ OrbisKernelEqueue flipQueue;
+ OrbisVideoOutBufferAttribute attr;
+
+ uint32_t currBuffer;
+ uint8_t * addrList[VOUT_NUM_BUFFERS];
+
+ off_t phyAddr;
+ uint8_t * mapAddr;
+ uint32_t bufSize, memSize;
+#if PS4_VIDEO_GL
+ SDL_bool egl_initialized; /* OpenGL ES device initialization status */
+ uint32_t egl_refcount; /* OpenGL ES reference count */
+#endif
+} SDL_VideoData;
+
+
+typedef struct SDL_DisplayData
+{
+
+} SDL_DisplayData;
+
+
+typedef struct SDL_WindowData
+{
+ SDL_Surface *surface;
+#if PS4_VIDEO_GL
+ SDL_bool uses_gles; /* if true window must support OpenGL ES */
+#endif
+} SDL_WindowData;
+
+/****************************************************************************/
+/* SDL_VideoDevice functions declaration */
+/****************************************************************************/
+extern void PS4_PumpEvents(SDL_VideoDevice *_this);
+
+/* Display and window functions */
+extern bool PS4_VideoInit(SDL_VideoDevice *_this);
+extern void PS4_VideoQuit(SDL_VideoDevice *_this);
+extern bool PS4_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay * display);
+extern bool PS4_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
+extern bool PS4_CreateWindow(SDL_VideoDevice *_this, SDL_Window * window, SDL_PropertiesID properties);
+extern bool PS4_CreateWindowFrom(SDL_VideoDevice *_this, SDL_Window * window, const void *data);
+extern void PS4_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window * window);
+extern bool PS4_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window * window, SDL_Surface * icon);
+extern bool PS4_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_SetWindowSize(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_ShowWindow(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_HideWindow(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_RaiseWindow(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_RestoreWindow(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_SetWindowGrab(SDL_VideoDevice *_this, SDL_Window * window, bool grabbed);
+extern void PS4_DestroyWindow(SDL_VideoDevice *_this, SDL_Window * window);
+
+extern bool PS4_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
+extern bool PS4_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window, const SDL_Rect * rects, int numrects);
+extern void PS4_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window);
+
+/* Window manager function */
+extern bool PS4_GetWindowWMInfo(SDL_VideoDevice *_this, SDL_Window * window, struct SDL_SysWMinfo *info);
+
+#if PS4_VIDEO_GL
+/* OpenGL/OpenGL ES functions */
+extern int PS4_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path);
+extern void *PS4_GL_GetProcAddress(SDL_VideoDevice *_this, const char *proc);
+extern void PS4_GL_UnloadLibrary(SDL_VideoDevice *_this);
+extern SDL_GLContext PS4_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window * window);
+extern int PS4_GL_MakeCurrent(SDL_VideoDevice *_this, SDL_Window * window, SDL_GLContext context);
+extern int PS4_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval);
+extern int PS4_GL_GetSwapInterval(SDL_VideoDevice *_this);
+extern int PS4_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window * window);
+extern void PS4_GL_DeleteContext(SDL_VideoDevice *_this, SDL_GLContext context);
+#endif
+
+/* PS4 on screen keyboard */
+extern bool PS4_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
+extern void PS4_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
+extern void PS4_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window);
+extern bool PS4_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window);
+
+/* Message boxes */
+extern bool PS4_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID);
+
+#endif /* SDL_ps4video_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */