From 0aba0e49e789bcb688b9f8c045ea444099039a72 Mon Sep 17 00:00:00 2001 From: David Miller Date: Wed, 29 May 2019 15:21:24 -0400 Subject: [PATCH] PS4 --- CMakeLists.txt | 81 ++- CMakeSettings.json | 40 ++ cmake/ps4sdk.cmake | 166 ++++++ include/SDL_config.h | 2 + include/SDL_config_ps4.h | 174 ++++++ include/SDL_platform.h | 6 + src/SDL.c | 2 + src/SDL_log.c | 3 + src/audio/SDL_audio.c | 13 +- src/audio/SDL_sysaudio.h | 1 + src/audio/ps4/SDL_ps4audio.c | 218 ++++++++ src/audio/ps4/SDL_ps4audio.h | 55 ++ src/dynapi/SDL_dynapi.h | 6 + src/dynapi/SDL_dynapi_overrides.h | 2 + src/joystick/SDL_joystick.c | 3 + src/joystick/SDL_sysjoystick.h | 1 + src/joystick/haiku/SDL_haikujoystick.cc | 6 +- src/joystick/ps4/SDL_sysjoystick.c | 292 ++++++++++ src/render/SDL_render.c | 4 + src/render/SDL_sysrender.h | 1 + src/render/ps4/SDL_render_ps4.c | 39 ++ src/thread/pthread/SDL_systhread.c | 4 +- src/video/SDL_surface.c | 3 + src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 21 +- src/video/ps4/SDL_ps4video.c | 673 ++++++++++++++++++++++++ src/video/ps4/SDL_ps4video.h | 131 +++++ 27 files changed, 1921 insertions(+), 27 deletions(-) create mode 100644 CMakeSettings.json create mode 100644 cmake/ps4sdk.cmake create mode 100644 include/SDL_config_ps4.h create mode 100644 src/audio/ps4/SDL_ps4audio.c create mode 100644 src/audio/ps4/SDL_ps4audio.h create mode 100644 src/joystick/ps4/SDL_sysjoystick.c create mode 100644 src/render/ps4/SDL_render_ps4.c create mode 100644 src/video/ps4/SDL_ps4video.c create mode 100644 src/video/ps4/SDL_ps4video.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 03017169c4..d66fe7a495 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,9 +239,21 @@ if(CYGWIN) set(SDL_CFLAGS "${SDL_CFLAGS} -I/usr/include/mingw") endif() -add_definitions(-DUSING_GENERATED_CONFIG_H) -# General includes -include_directories(${SDL2_BINARY_DIR}/include ${SDL2_SOURCE_DIR}/include) + +######### *FIXME* + +if(PS4 OR ORBIS) + set(USE_GENERATED_CONFIG Off) +else() + set(USE_GENERATED_CONFIG On) +endif() + +if(USE_GENERATED_CONFIG) + add_definitions(-DUSING_GENERATED_CONFIG_H) + include_directories(${SDL2_BINARY_DIR}/include) +endif() + +include_directories(${SDL2_SOURCE_DIR}/include) if(USE_GCC OR USE_CLANG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -idirafter ${SDL2_SOURCE_DIR}/src/video/khronos") else() @@ -264,6 +276,15 @@ if(EMSCRIPTEN) set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF) endif() +if(PS4 OR ORBIS) + set(SDL_ATOMIC_ENABLED_BY_DEFAULT ON) + set(SDL_SHARED_ENABLED_BY_DEFAULT OFF) + set(SDL_THREADS_ENABLED_BY_DEFAULT ON) + set(SDL_PTHREADS_ENABLED_BY_DEFAULT ON) + set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF) + set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF) +endif() + if (NOT DEFINED SDL_SHARED_ENABLED_BY_DEFAULT) set(SDL_SHARED_ENABLED_BY_DEFAULT ON) endif() @@ -971,6 +992,42 @@ if(EMSCRIPTEN) set(SDL_VIDEO_RENDER_OGL_ES2 1) endif() endif() +elseif(PS4 OR ORBIS) + CheckPTHREAD() + if(SDL_AUDIO) + set(SDL_AUDIO_DRIVER_PS4 1) + file(GLOB PS4_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/ps4/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${PS4_AUDIO_SOURCES}) + set(HAVE_SDL_AUDIO TRUE) + endif() +# if(SDL_FILESYSTEM) +# set(SDL_FILESYSTEM_PS4 1) +# file(GLOB PS4_FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/ps4/*.c) +# set(SOURCE_FILES ${SOURCE_FILES} ${PS4_FILESYSTEM_SOURCES}) +# set(HAVE_SDL_FILESYSTEM TRUE) +# endif() + if(SDL_JOYSTICK) + set(SDL_JOYSTICK_PS4 1) + file(GLOB PS4_JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/ps4/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${PS4_JOYSTICK_SOURCES}) + set(HAVE_SDL_JOYSTICK TRUE) + endif() + if(SDL_TIMERS) + set(SDL_TIMER_UNIX 1) + file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${TIMER_SOURCES}) + set(HAVE_SDL_TIMERS TRUE) + + if(CLOCK_GETTIME) + set(HAVE_CLOCK_GETTIME 1) + endif() + endif() + if(SDL_VIDEO) + set(SDL_VIDEO_DRIVER_PS4 1) + file(GLOB PS4_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/ps4/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${PS4_VIDEO_SOURCES}) + set(HAVE_SDL_VIDEO TRUE) + endif() elseif(UNIX AND NOT APPLE AND NOT ANDROID) if(SDL_AUDIO) if(SYSV5 OR SOLARIS OR HPUX) @@ -1628,8 +1685,10 @@ endif() # endif() # endif() -configure_file("${SDL2_SOURCE_DIR}/include/SDL_config.h.cmake" - "${SDL2_BINARY_DIR}/include/SDL_config.h") +if(USE_GENERATED_CONFIG) + configure_file("${SDL2_SOURCE_DIR}/include/SDL_config.h.cmake" + "${SDL2_BINARY_DIR}/include/SDL_config.h") +endif() # Prepare the flags and remove duplicates if(EXTRA_LDFLAGS) @@ -1681,14 +1740,10 @@ if(NOT WINDOWS OR CYGWIN) # MESSAGE(STATUS "SDL_LIBS: ${SDL_LIBS}") # MESSAGE(STATUS "SDL_STATIC_LIBS: ${SDL_STATIC_LIBS}") - configure_file("${SDL2_SOURCE_DIR}/sdl2.pc.in" - "${SDL2_BINARY_DIR}/sdl2.pc" @ONLY) - configure_file("${SDL2_SOURCE_DIR}/sdl2-config.in" - "${SDL2_BINARY_DIR}/sdl2-config") - configure_file("${SDL2_SOURCE_DIR}/sdl2-config.in" - "${SDL2_BINARY_DIR}/sdl2-config" @ONLY) - configure_file("${SDL2_SOURCE_DIR}/SDL2.spec.in" - "${SDL2_BINARY_DIR}/SDL2.spec" @ONLY) + configure_file("${SDL2_SOURCE_DIR}/sdl2.pc.in" "${SDL2_BINARY_DIR}/sdl2.pc" @ONLY) + configure_file("${SDL2_SOURCE_DIR}/sdl2-config.in" "${SDL2_BINARY_DIR}/sdl2-config") + configure_file("${SDL2_SOURCE_DIR}/sdl2-config.in" "${SDL2_BINARY_DIR}/sdl2-config" @ONLY) + configure_file("${SDL2_SOURCE_DIR}/SDL2.spec.in" "${SDL2_BINARY_DIR}/SDL2.spec" @ONLY) endif() ##### Info output ##### diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 0000000000..55708e87b8 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,40 @@ +{ + "environments": [ + { + // Could set things up here instead of the toolchain file, instead make this global env. and use a TOOLCHAIN var + //"INCLUDE": "${env.INCLUDE};", + + "TOOLCHAIN_FILE": "ps4sdk.cmake", + "environment": "toolchain.generic" + } + ], + "configurations": [ + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "inheritEnvironments": [ + "msvc_x64_x64" + ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, + { + //"variables": [ { "TOOLCHAIN_FILE": "ps4sdk.cmake" } ], // This doesn't seem to override toolchain.generic:: [env.]TOOLCHAIN_FILE , or pass to the cmake cache + + "name": "PS4 SDK", + "generator": "Ninja", + "description": "TemplateDescription_Localize_PS4SDK", + "configurationType": "RelWithDebInfo", + "inheritEnvironments": [ "toolchain.generic" ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "D:\\dev\\orbis_sdk_500\\portlibs\\SDL", + "cmakeCommandArgs": "-DCMAKE_TOOLCHAIN_FILE=${projectDir}\\cmake\\ps4sdk.cmake", // ${projectDir}/cmake/${env.TOOLCHAIN_FILE} + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/cmake/ps4sdk.cmake b/cmake/ps4sdk.cmake new file mode 100644 index 0000000000..6e0ffc83d4 --- /dev/null +++ b/cmake/ps4sdk.cmake @@ -0,0 +1,166 @@ +## ps4sdk.cmake - Playstation4 cross-compile +# +set(CMAKE_SYSTEM_NAME Orbis) # this one is important +set(CMAKE_SYSTEM_PROCESSOR x86_64) +set(CMAKE_SYSTEM_VERSION 9) # this one not so much + + + +### This shit is very WIP ### +# +## TODO: Check for + + + + + +#SCE_ORBIS_SDK_DIR=D:\Dev\PS4\SCE\PS4SDK +#SCE_ROOT_DIR=D:\Dev\PS4\SCE + + +if (NOT "" STREQUAL "$ENV{SCE_ORBIS_SDK_DIR}") + + file(TO_CMAKE_PATH $ENV{SCE_ORBIS_SDK_DIR} SCESDK) + #set(SCESDK $ENV{SCE_ORBIS_SDK_DIR}) # SCE_ORBIS_SDK_DIR - requires change below ./SCE/PS4SDK : ./ +endif() + + +if (NOT "" STREQUAL "${SCESDK}") # defaults to sce sdk if available + set(USE_SCE ON) + set(PS4SDK ${SCESDK}) +endif() + + + +if ("" STREQUAL "${PS4SDK}") # Not found or passed in + + if(NOT "" STREQUAL "$ENV{PS4SDK}") # Try env var + set(PS4SDK $ENV{PS4SDK}) + else() # else defaults + if ("Windows" STREQUAL "${CMAKE_HOST_SYSTEM_NAME}") + set(PS4SDK "D:/Dev/ps4sdk") + else() + set(PS4SDK "/opt/ps4/sdk") + endif() + endif() + +endif() + + +set(TAUON_SDK ${PS4SDK}/tauon) + + + +if(USE_SCE) +# + set(PS4HOST ${PS4SDK}/host_tools) + set(PS4TARGET ${PS4SDK}/target) + + set(CMAKE_FIND_ROOT_PATH ${PS4TARGET}) # where is the target environment + + + set(toolPrefix "orbis-") + set(toolSuffix ".exe") + + + file(TO_CMAKE_PATH ${PS4HOST}/bin/${toolPrefix}clang${toolSuffix} CMAKE_C_COMPILER) + file(TO_CMAKE_PATH ${PS4HOST}/bin/${toolPrefix}clang++${toolSuffix} CMAKE_CXX_COMPILER) + +#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -masm=intel -fms-extensions -fasm-blocks ") + +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nobuiltininc ") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc -nostdinc++ ") + +# -nobuiltininc Disable builtin #include directories +# -nostdinc++ Disable standard #include directories for the C++ standard library + + + set (PS4_inc_dirs + # ${TAUON_SDK}/include + ${PS4TARGET}/include + ${PS4TARGET}/include_common + ) + +# set (PS4_link_dirs +# "${PS4TARGET}/lib" +# "${PS4TARGET}/tauon/lib" +# ) + + +#LDFLAGS += -L $(TAUON_SDK_DIR)/lib -L $(SCE_ORBIS_SDK_DIR)/target/lib + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s -Wl,--addressing=non-aslr,--strip-unused-data ") +# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L ${TAUON_SDK}/lib") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L ${PS4TARGET}/lib") + + message("CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}") +# +else() +# + set(triple "x86_64-scei-ps4") + + set(CMAKE_C_COMPILER_TARGET ${triple}) + set(CMAKE_CXX_COMPILER_TARGET ${triple}) + + set(CMAKE_C_COMPILER clang) + set(CMAKE_CXX_COMPILER clang++) + + + set (PS4_inc_dirs + ${TAUON_SDK}/include + + # ${PS4SDK}/include + # ${PS4SDK}/tauon/include + ) + +# set (PS4_link_dirs +# "${PS4SDK}/lib" +# "${PS4SDK}/tauon/lib" +# ) + + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s -Wl,--addressing=non-aslr,--strip-unused-data -L${TAUON_SDK}/lib") +# +endif() +### IF NOT SCE SDK +# + + + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search for programs in the build host directories +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) # for libraries and headers in the target directories +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) + + +include_directories(${PS4_inc_dirs}) + + + + +set(PS4 ON) +set(ORBIS ON) + +add_definitions(-DPS4) + +if(PS4) + set(binSuffix ".elf") + link_libraries(SceSystemService_stub_weak SceUserService_stub_weak ScePosix_stub_weak + ScePad_stub_weak SceAudioOut_stub_weak SceSysmodule_stub_weak + libc_stub_weak.a + #${PS4TARGET}/lib/libc_stub_weak.a + #SceLibcInternal_tau_stub + # SceSysmodule_tau_stub_weak + # kernel_tau_stub_weak SceSysmodule_tau_stub_weak SceSystemService_stub_weak SceSystemService_tau_stub_weak SceShellCoreUtil_tau_stub_weak ScePigletv2VSH_tau_stub_weak kernel_util + ) +endif() + + +#set(LINK_DIRECTORIES ${PS4_link_dirs}) +#link_directories(${PS4_link_dirs}) + + + + + + + + diff --git a/include/SDL_config.h b/include/SDL_config.h index 7d62d3e2ec..55a4c53c96 100644 --- a/include/SDL_config.h +++ b/include/SDL_config.h @@ -41,6 +41,8 @@ #include "SDL_config_android.h" #elif defined(__PSP__) #include "SDL_config_psp.h" +#elif defined(__ORBIS__) || defined(PS4) +#include "SDL_config_ps4.h" #elif defined(__OS2__) #include "SDL_config_os2.h" #else diff --git a/include/SDL_config_ps4.h b/include/SDL_config_ps4.h new file mode 100644 index 0000000000..e187832feb --- /dev/null +++ b/include/SDL_config_ps4.h @@ -0,0 +1,174 @@ +/* + 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. +*/ + +#ifndef SDL_config_ps4_h_ +#define SDL_config_ps4_h_ +#define SDL_config_h_ + +#include "SDL_platform.h" + + + +#ifdef __GNUC__ +#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1 +#endif + +#define HAVE_GCC_ATOMICS 1 + +#define STDC_HEADERS 1 +#define HAVE_ALLOCA_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_MATH_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDIO_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_TYPES_H 1 +//#define HAVE_SIGNAL_H 0 + +/* C library functions */ +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +//#define HAVE_GETENV 1 +//#define HAVE_SETENV 1 +//#define HAVE_PUTENV 1 +//#define HAVE_SETENV 1 +//#define HAVE_UNSETENV 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRNCASECMP 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_M_PI 1 +#define HAVE_ACOS 1 +#define HAVE_ACOSF 1 +#define HAVE_ASIN 1 +#define HAVE_ASINF 1 +#define HAVE_ATAN 1 +#define HAVE_ATANF 1 +#define HAVE_ATAN2 1 +#define HAVE_ATAN2F 1 +#define HAVE_CEIL 1 +#define HAVE_CEILF 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COPYSIGNF 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_EXP 1 +#define HAVE_EXPF 1 +#define HAVE_FABS 1 +#define HAVE_FABSF 1 +#define HAVE_FLOOR 1 +#define HAVE_FLOORF 1 +#define HAVE_FMOD 1 +#define HAVE_FMODF 1 +#define HAVE_LOG 1 +#define HAVE_LOGF 1 +#define HAVE_LOG10 1 +#define HAVE_LOG10F 1 +#define HAVE_POW 1 +#define HAVE_POWF 1 +#define HAVE_SCALBN 1 +#define HAVE_SCALBNF 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_SETJMP 1 +#define HAVE_NANOSLEEP 1 +/* #define HAVE_SYSCONF 1 */ +/* #define HAVE_SIGACTION 1 */ + + +//#define LACKS_SYS_MMAN_H 1 + +// Try to use C++ +#define SDL_THREAD_PTHREAD 1 +//#define SDL_THREAD_STDCPP 1 + +/* Enable the PS4 timer support (src/timer/ps4/\*.c) */ +//#define SDL_TIMERS_PS4 1 +#define SDL_TIMER_UNIX 1 + +/* Enable the PS4 joystick driver (src/joystick/ps4/\*.c) */ +#define SDL_JOYSTICK_PS4 1 + +/* Enable the dummy sensor driver */ +#define SDL_SENSOR_DUMMY 1 + + +#define SDL_AUDIO_DRIVER_PS4 1 // PS4 audio driver (src/audio/ps4/\*.c) +#define SDL_VIDEO_DRIVER_PS4 1 +#define SDL_VIDEO_RENDER_PS4 1 + +/* !!! FIXME: use std or wrap */ +#define SDL_FILESYSTEM_DUMMY 1 + +/* (src/haptic/dummy/\*.c) */ +#define SDL_HAPTIC_DISABLED 1 + +/* (src/loadso/dummy/\*.c) */ +#define SDL_LOADSO_DISABLED 1 + +#ifdef _DEBUG +#define D_FN() \ + printf(">>>>>>>>>>> %s() <<<<<<<<<<<< \n", __FUNCTION__) + +#define D_MSG(m) \ + printf("@@>>>>> %s(): %s <<<<<<<<<<<< \n", __FUNCTION__, m) +#else + +// If your compiler wants __noop you'll have to add // + +#define D_FN() +#define D_MSG(m) + +#endif + + +#endif /* SDL_config_ps4_h_ */ diff --git a/include/SDL_platform.h b/include/SDL_platform.h index c2cbc6b4e0..1a71ea57ad 100644 --- a/include/SDL_platform.h +++ b/include/SDL_platform.h @@ -154,11 +154,17 @@ #undef __WIN32__ #define __WIN32__ 1 #endif + #if defined(__PSP__) #undef __PSP__ #define __PSP__ 1 #endif +#if defined(__ORBIS__) || defined(PS4) +#undef __PS4__ +#define __PS4__ 1 +#endif + /* The NACL compiler defines __native_client__ and __pnacl__ * Ref: http://www.chromium.org/nativeclient/pnacl/stability-of-the-pnacl-bitcode-abi */ diff --git a/src/SDL.c b/src/SDL.c index 6e80178105..ef9834b226 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -474,6 +474,8 @@ SDL_GetPlatform() return "iOS"; #elif __PSP__ return "PlayStation Portable"; +#elif __PS4__ + return "PlayStation4"; #else return "Unknown (see SDL_platform.h)"; #endif diff --git a/src/SDL_log.c b/src/SDL_log.c index 486ce3417b..aadabe4715 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -299,6 +299,9 @@ SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list } } +#ifdef PS4 + printf(message); // just fucking do it +#endif SDL_log_function(SDL_log_userdata, category, priority, message); SDL_stack_free(message); } diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 836b7b6466..53585f1db3 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -98,6 +98,9 @@ static const AudioBootStrap *const bootstrap[] = { #if SDL_AUDIO_DRIVER_PSP &PSPAUDIO_bootstrap, #endif +#if SDL_AUDIO_DRIVER_PS4 + &PS4AUDIO_bootstrap, +#endif #if SDL_AUDIO_DRIVER_EMSCRIPTEN &EMSCRIPTENAUDIO_bootstrap, #endif @@ -1401,13 +1404,11 @@ open_audio_device(const char *devname, int iscapture, if (build_stream) { if (iscapture) { - device->stream = SDL_NewAudioStream(device->spec.format, - device->spec.channels, device->spec.freq, - obtained->format, obtained->channels, obtained->freq); + device->stream = SDL_NewAudioStream(device->spec.format, device->spec.channels, device->spec.freq, + obtained->format, obtained->channels, obtained->freq); } else { - device->stream = SDL_NewAudioStream(obtained->format, obtained->channels, - obtained->freq, device->spec.format, - device->spec.channels, device->spec.freq); + device->stream = SDL_NewAudioStream(obtained->format, obtained->channels, obtained->freq, + device->spec.format, device->spec.channels, device->spec.freq); } if (!device->stream) { diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 09a77c9676..a378ee8654 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -207,6 +207,7 @@ extern AudioBootStrap FUSIONSOUND_bootstrap; extern AudioBootStrap ANDROIDAUDIO_bootstrap; extern AudioBootStrap openslES_bootstrap; extern AudioBootStrap PSPAUDIO_bootstrap; +extern AudioBootStrap PS4AUDIO_bootstrap; extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap; #endif /* SDL_sysaudio_h_ */ diff --git a/src/audio/ps4/SDL_ps4audio.c b/src/audio/ps4/SDL_ps4audio.c new file mode 100644 index 0000000000..ef7689eea5 --- /dev/null +++ b/src/audio/ps4/SDL_ps4audio.c @@ -0,0 +1,218 @@ +/* + 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" + +#if SDL_AUDIO_DRIVER_PS4 + +#include +#include + +#include "SDL_audio.h" +/* +#include "SDL_error.h" +#include "SDL_timer.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "../SDL_sysaudio.h" +*/ +#include "SDL_ps4audio.h" + +static int PS4AUDIO_Init(SDL_AudioDriverImpl * impl); + +AudioBootStrap PS4AUDIO_bootstrap = { + "ps4", "PS4 audio driver", PS4AUDIO_Init, 0 +}; + +inline static +Uint16 ps4_sample_size(Uint16 ssize) +{ + if (ssize >= 2048) return 2048; + if (ssize >= 1792) return 1792; + if (ssize >= 1536) return 1536; + if (ssize >= 1280) return 1280; + if (ssize >= 1024) return 1024; + if (ssize >= 768) return 768; + if (ssize >= 512) return 512; + return 256; +} + + +/* The tag name used by PS4 audio */ +#define PS4AUDIO_DRIVER_NAME "ps4" + +static int +PS4AUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) +{ + int mixlen, i; + this->hidden = (struct SDL_PrivateAudioData *)SDL_malloc(sizeof(*this->hidden)); + if (this->hidden == NULL) { + return SDL_OutOfMemory(); + } + SDL_zerop(this->hidden); + + int mono = (1 == this->spec.channels) ? 1 : 0; + if (!mono) this->spec.channels = 2; + + uint8_t p_fmt = 0, p_attr = 0; + switch (this->spec.format) { + case AUDIO_S16LSB: p_fmt = (mono) ? SCE_AUDIO_OUT_PARAM_FORMAT_S16_MONO : SCE_AUDIO_OUT_PARAM_FORMAT_S16_STEREO; break; + case AUDIO_F32LSB: p_fmt = (mono) ? SCE_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO : SCE_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO; break; + default: return SDL_SetError("Unsupported audio format"); + } + + this->spec.samples = ps4_sample_size(this->spec.samples); // make sure it's specific granularity + this->spec.freq = 48000; // PS4 only does 48k, it's possible to get SDL to resample w.o libsamplerate?? + + /* Update the fragment size as size in bytes. */ + SDL_CalculateAudioSpec(&this->spec); + + + + + + /* Allocate the mixing buffer. Its size and starting address must + be a multiple of 64 bytes. Our sample count is already a multiple of + 64, so spec->size should be a multiple of 64 as well. */ + mixlen = this->spec.size * NUM_BUFFERS; + this->hidden->rawbuf = (Uint8 *)memalign(64, mixlen); + if (this->hidden->rawbuf == NULL) { + return SDL_SetError("Couldn't allocate mixing buffer"); + } + + + + this->hidden->h_aout = sceAudioOutOpen(SCE_USER_SERVICE_USER_ID_SYSTEM, SCE_AUDIO_OUT_PORT_TYPE_MAIN, + 0, this->spec.samples, 48000, ((p_fmt&255) | ((p_attr&15) << SCE_AUDIO_OUT_PARAM_ATTR_SHIFT))); + if (this->hidden->h_aout <= 0) { + free(this->hidden->rawbuf); + this->hidden->rawbuf = NULL; + return SDL_SetError("sceAudioOutOpen() failed!"); + } + + memset(this->hidden->rawbuf, 0, mixlen); + for (i = 0; i < NUM_BUFFERS; i++) { + this->hidden->mixbufs[i] = &this->hidden->rawbuf[i * this->spec.size]; + } + + this->hidden->next_buffer = 0; + return 0; +} + +static void PS4AUDIO_PlayDevice(_THIS) +{ + sceAudioOutOutput(this->hidden->h_aout, this->hidden->mixbufs[this->hidden->next_buffer]); + + this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS; +} + +/* This function waits until it is possible to write a full sound buffer */ +static void PS4AUDIO_WaitDevice(_THIS) +{ + sceAudioOutOutput(this->hidden->h_aout, NULL); // Call with NULL to wait until play of current buffer is complete +} + +static Uint8 *PS4AUDIO_GetDeviceBuf(_THIS) +{ + return this->hidden->mixbufs[this->hidden->next_buffer]; +} + +static void PS4AUDIO_CloseDevice(_THIS) +{ + sceAudioOutClose(this->hidden->h_aout); + + free(this->hidden->rawbuf); /* this uses memalign(), not SDL_malloc(). */ + SDL_free(this->hidden); +} + +static void PS4AUDIO_ThreadInit(_THIS) +{ +#if 0 + /* Increase the priority of this audio thread by 1 to put it + ahead of other SDL threads. */ + SceUID thid; + SceKernelThreadInfo status; + thid = sceKernelGetThreadId(); + status.size = sizeof(SceKernelThreadInfo); + if (sceKernelReferThreadStatus(thid, &status) == 0) { + sceKernelChangeThreadPriority(thid, status.currentPriority - 1); + } +#endif +} + + + +static int PS4AUDIO_Init(SDL_AudioDriverImpl * impl) +{ + + + sceUserServiceInitialize(NULL); + + if (0 != sceAudioOutInit()) { + SDL_SetError("sceAudioOutInit() failed!"); + return -1; + } +/* + void(*DetectDevices) (void); + int(*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture); + void(*ThreadInit) (_THIS); // Called by audio thread at start + void(*ThreadDeinit) (_THIS); // Called by audio thread at end + void(*BeginLoopIteration)(_THIS); // Called by audio thread at top of loop + void(*WaitDevice) (_THIS); + void(*PlayDevice) (_THIS); + int(*GetPendingBytes) (_THIS); + Uint8 *(*GetDeviceBuf) (_THIS); + int(*CaptureFromDevice) (_THIS, void *buffer, int buflen); + void(*FlushCapture) (_THIS); + void(*PrepareToClose) (_THIS); // Called between run and draining wait for playback devices + void(*CloseDevice) (_THIS); + void(*LockDevice) (_THIS); + void(*UnlockDevice) (_THIS); + void(*FreeDeviceHandle) (void *handle); // SDL is done with handle from SDL_AddAudioDevice() + void(*Deinitialize) (void); +*/ + /* Set the function pointers */ + impl->OpenDevice = PS4AUDIO_OpenDevice; + impl->PlayDevice = PS4AUDIO_PlayDevice; + impl->WaitDevice = PS4AUDIO_WaitDevice; + impl->GetDeviceBuf = PS4AUDIO_GetDeviceBuf; + impl->CloseDevice = PS4AUDIO_CloseDevice; + impl->ThreadInit = PS4AUDIO_ThreadInit; + + + + /* PSP audio device */ + impl->OnlyHasDefaultOutputDevice = 1; + /* + impl->HasCaptureSupport = 1; + impl->OnlyHasDefaultCaptureDevice = 1; + */ + /* + impl->DetectDevices = DSOUND_DetectDevices; + impl->Deinitialize = DSOUND_Deinitialize; + */ + return 1; /* this audio target is available. */ +} + + + + +#endif // SDL_AUDIO_DRIVER_PS4 \ No newline at end of file diff --git a/src/audio/ps4/SDL_ps4audio.h b/src/audio/ps4/SDL_ps4audio.h new file mode 100644 index 0000000000..df183e6eee --- /dev/null +++ b/src/audio/ps4/SDL_ps4audio.h @@ -0,0 +1,55 @@ +/* + 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. +*/ + +#ifndef _SDL_ps4audio_h +#define _SDL_ps4audio_h + + +#include "SDL_config_ps4.h" + +#include "../SDL_sysaudio.h" + +//#ifdef _THIS +//#undef _THIS +#define _THIS SDL_AudioDevice *this +//#endif + +#define NUM_BUFFERS 2 + +struct SDL_PrivateAudioData +{ + int32_t h_aout; + + /* The raw allocated mixing buffer. */ + Uint8 *rawbuf; + /* Individual mixing buffers. */ + Uint8 *mixbufs[NUM_BUFFERS]; + /* Index of the next available mixing buffer. */ + int next_buffer; +}; + + + + + + + +#endif // _SDL_ps4audio_h \ No newline at end of file diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index 0d2cf713c9..93360fb8b7 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -53,10 +53,16 @@ #define SDL_DYNAMIC_API 0 #elif defined(__PSP__) && __PSP__ #define SDL_DYNAMIC_API 0 +#elif defined(__PS4__) && __PS4__ +#define SDL_DYNAMIC_API 0 #elif defined(__clang_analyzer__) #define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */ #endif +#if defined(PS4) // Apparently __PS4__ getting defined is missed somewhere, I get broken static builds so force the issue +#define SDL_DYNAMIC_API 0 +#endif + /* everyone else. This is where we turn on the API if nothing forced it off. */ #ifndef SDL_DYNAMIC_API #define SDL_DYNAMIC_API 1 diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 25835246c3..6b34760b2e 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -27,6 +27,7 @@ #error You should not be here. #endif +#if 0 // *FIXME* stfu wrong intellisense on VS/cmake #define SDL_SetError SDL_SetError_REAL #define SDL_Log SDL_Log_REAL #define SDL_LogVerbose SDL_LogVerbose_REAL @@ -714,3 +715,4 @@ #define SDL_RenderCopyExF SDL_RenderCopyExF_REAL #define SDL_GetTouchDeviceType SDL_GetTouchDeviceType_REAL #define SDL_UIKitRunApp SDL_UIKitRunApp_REAL +#endif // *FIXME* \ No newline at end of file diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 430934c33d..129ca69a7a 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -73,6 +73,9 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = { #ifdef SDL_JOYSTICK_HIDAPI &SDL_HIDAPI_JoystickDriver, #endif +#ifdef SDL_JOYSTICK_PS4 + &SDL_PS4_JoystickDriver, +#endif #if defined(SDL_JOYSTICK_DUMMY) || defined(SDL_JOYSTICK_DISABLED) &SDL_DUMMY_JoystickDriver #endif diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index ef7f082e47..4211a88c02 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -149,6 +149,7 @@ extern SDL_JoystickDriver SDL_EMSCRIPTEN_JoystickDriver; extern SDL_JoystickDriver SDL_HAIKU_JoystickDriver; extern SDL_JoystickDriver SDL_HIDAPI_JoystickDriver; extern SDL_JoystickDriver SDL_IOS_JoystickDriver; +extern SDL_JoystickDriver SDL_PS4_JoystickDriver; extern SDL_JoystickDriver SDL_LINUX_JoystickDriver; extern SDL_JoystickDriver SDL_WINDOWS_JoystickDriver; diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index 1b18a51e06..9cf3f8606e 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -146,10 +146,8 @@ extern "C" joystick->naxes = stick->CountAxes(); joystick->nhats = stick->CountHats(); - joystick->hwdata->new_axes = (int16 *) - SDL_malloc(joystick->naxes * sizeof(int16)); - joystick->hwdata->new_hats = (uint8 *) - SDL_malloc(joystick->nhats * sizeof(uint8)); + joystick->hwdata->new_axes = (int16 *)SDL_malloc(joystick->naxes * sizeof(int16)); + joystick->hwdata->new_hats = (uint8 *)SDL_malloc(joystick->nhats * sizeof(uint8)); if (!joystick->hwdata->new_hats || !joystick->hwdata->new_axes) { HAIKU_JoystickClose(joystick); return SDL_OutOfMemory(); diff --git a/src/joystick/ps4/SDL_sysjoystick.c b/src/joystick/ps4/SDL_sysjoystick.c new file mode 100644 index 0000000000..9759668c30 --- /dev/null +++ b/src/joystick/ps4/SDL_sysjoystick.c @@ -0,0 +1,292 @@ +/* + 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" + +#if SDL_JOYSTICK_PS4 + +/* This is the PSP implementation of the SDL joystick API */ +#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" + + +#ifndef SCE_OK +#define SCE_OK 0 +#endif + +#define MAX_PADS 4 + +uint32_t nPads = 0; + +SceUserServiceUserId userId, pad_users[MAX_PADS]; +SceUserServiceLoginUserIdList userIdList; + +#define DS4_BTN_COUNT 16 + + +const uint32_t ds4_map[DS4_BTN_COUNT] = { + SCE_PAD_BUTTON_CROSS, SCE_PAD_BUTTON_CIRCLE, SCE_PAD_BUTTON_SQUARE, SCE_PAD_BUTTON_TRIANGLE, + SCE_PAD_BUTTON_L1, SCE_PAD_BUTTON_R1, SCE_PAD_BUTTON_L2, SCE_PAD_BUTTON_R2, + SCE_PAD_BUTTON_OPTIONS, SCE_PAD_BUTTON_L3, SCE_PAD_BUTTON_R3, + SCE_PAD_BUTTON_UP, SCE_PAD_BUTTON_DOWN, SCE_PAD_BUTTON_LEFT, SCE_PAD_BUTTON_RIGHT, + SCE_PAD_BUTTON_TOUCH_PAD +}; + + + +int PS4_JoystickGetCount(void) +{ + return nPads; +} + +void PS4_JoystickDetect(void) +{ + if(SCE_OK != sceUserServiceGetLoginUserIdList(&userIdList)) + printf("WARNING, sceUserServiceGetLoginUserIdList() failed for JoystickDetect()!\n"); + + nPads = 0; + + for (int i = 0; i < SCE_USER_SERVICE_MAX_LOGIN_USERS; i++) { + if (SCE_USER_SERVICE_USER_ID_INVALID != (userId = userIdList.userId[i])) { + int32_t handle = scePadOpen(userId, SCE_PAD_PORT_TYPE_STANDARD, 0, NULL); + if (handle > 0 || handle== SCE_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. + */ +int 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(SCE_OK != res && SCE_USER_SERVICE_ERROR_ALREADY_INITIALIZED != res) + return SDL_SetError("Error sceUserServiceInitialize() failed!"); + + if (SCE_OK != sceUserServiceGetInitialUser(&userId)) + return SDL_SetError("Error sceUserServiceGetInitialUser() failed!"); + + if(SCE_OK != scePadInit()) + return SDL_SetError("Error scePadInit() failed!"); + + PS4_JoystickDetect(); + + return nPads; +} + +/* Function to get the device-dependent name of a joystick */ +const char * PS4_JoystickGetDeviceName(int device_index) +{ + return "Dualshock4"; +} + +/* Function to get the player index of a joystick */ +int PS4_JoystickGetDevicePlayerIndex(int device_index) +{ + if (device_index >= MAX_PADS) device_index = MAX_PADS - 1; + + for (int i = 0; i < SCE_USER_SERVICE_MAX_LOGIN_USERS; i++) + if(pad_users[device_index] == userIdList.userId[i]) + return i; + + return -1; +} + + + +SDL_JoystickGUID PS4_JoystickGetDeviceGUID(int device_index) +{ + if (device_index >= MAX_PADS) device_index = MAX_PADS - 1; + + SDL_JoystickGUID guid; + SDL_zero(guid); + *(int*)&guid.data[0] = 0x20200420; + *(int*)&guid.data[4] = pad_users[device_index]; + *(int*)&guid.data[10] = device_index; + return guid; +} + + +/* Function to perform the mapping from device index to the instance id for this index */ +SDL_JoystickID PS4_JoystickGetDeviceInstanceID(int device_index) +{ + if (device_index >= MAX_PADS) device_index = MAX_PADS - 1; + + return scePadGetHandle(pad_users[device_index], SCE_PAD_PORT_TYPE_STANDARD, 0); +} + +#if 0 +typedef struct joystick_hwdata_t +{ +} joystick_hwdata; +#endif + +/* 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. + */ +int 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 = 16; + joystick->naxes = 2; + joystick->nhats = 0; + + /* Create the joystick data structure */ + joystick->instance_id = handle; +#if 0 + joystick->hwdata = (struct joystick_hwdata *)SDL_malloc(sizeof(*joystick->hwdata)); + if (joystick->hwdata == NULL) { + return SDL_OutOfMemory(); + } + SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); +#endif + } + + + return 0; +} + +int PS4_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) +{ + + return 0; +} + + + +/* 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. + */ +void PS4_JoystickUpdate(SDL_Joystick *joystick) +{ + static uint32_t s_btns=0; + uint32_t m_btns=0; + + ScePadData data; + +// printf("(((((((((( JS UPDATE %X ))))))))) \n", joystick->instance_id); + + int ret = scePadReadState(joystick->instance_id, &data); + if (ret != SCE_OK || !data.connected) { + printf("Warning, Controller is not connected or failed to read data! \n"); + return; + } + + m_btns = data.buttons ^ s_btns; + s_btns = data.buttons; + + if (m_btns) { + for (uint32_t bn = 0; bn < DS4_BTN_COUNT; bn++) { + if (m_btns & ds4_map[bn]) { + if (!SDL_PrivateJoystickButton(joystick, bn, s_btns & ds4_map[bn] ? SDL_PRESSED : SDL_RELEASED)) + ; // printf("$$$$$$$$$$$$$$ UPDATE BUTTON %d NOT POSTED \n", bn); + } + } + } + + Sint16 lX = -32768 + (data.leftStick.x << 8); //-128 + data.leftStick.x; + Sint16 lY = -32768 + (data.leftStick.y << 8); //-128 + data.leftStick.y; + + Sint16 rX = -32768 + (data.rightStick.x << 8); //-128 + data.rightStick.x; + Sint16 rY = -32768 + (data.rightStick.y << 8); //-128 + data.rightStick.y; + + // **FIXME** get actual deadzone and scale properly // + if (lX < -1000 || lX > 1000) SDL_PrivateJoystickAxis(joystick, 0, lX); + if (lY < -1000 || lY > 1000) SDL_PrivateJoystickAxis(joystick, 1, lY); + if (rX < -1000 || rX > 1000) SDL_PrivateJoystickAxis(joystick, 2, rX); + if (rY < -1000 || rY > 1000) SDL_PrivateJoystickAxis(joystick, 3, rY); + +} + +/* 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 */ +void PS4_JoystickQuit(void) +{ + nPads = 0; +} + + + + + + + +SDL_JoystickDriver SDL_PS4_JoystickDriver = +{ + PS4_JoystickInit, + PS4_JoystickGetCount, + PS4_JoystickDetect, + PS4_JoystickGetDeviceName, + PS4_JoystickGetDevicePlayerIndex, + PS4_JoystickGetDeviceGUID, + PS4_JoystickGetDeviceInstanceID, + PS4_JoystickOpen, + PS4_JoystickRumble, + PS4_JoystickUpdate, + PS4_JoystickClose, + PS4_JoystickQuit, +}; + + +#endif /* SDL_JOYSTICK_PS4 */ \ No newline at end of file diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 81f92969f1..0ba30cdd2b 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -97,6 +97,10 @@ static const SDL_RenderDriver *render_drivers[] = { #endif #if SDL_VIDEO_RENDER_PSP &PSP_RenderDriver, +#endif +#if SDL_VIDEO_RENDER_PS4 && 0 // *FIXME* PS4_RenderDriver Disabled, it's software anyhow lets not reinvent... +#error Use SoftRender for PS4 currently! + &PS4_RenderDriver, #endif &SW_RenderDriver }; diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 93865621c1..a9f25173df 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -250,6 +250,7 @@ extern SDL_RenderDriver GLES_RenderDriver; extern SDL_RenderDriver DirectFB_RenderDriver; extern SDL_RenderDriver METAL_RenderDriver; extern SDL_RenderDriver PSP_RenderDriver; +extern SDL_RenderDriver PS4_RenderDriver; extern SDL_RenderDriver SW_RenderDriver; /* Blend mode functions */ diff --git a/src/render/ps4/SDL_render_ps4.c b/src/render/ps4/SDL_render_ps4.c new file mode 100644 index 0000000000..7d514f5137 --- /dev/null +++ b/src/render/ps4/SDL_render_ps4.c @@ -0,0 +1,39 @@ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_PS4 + +#include "SDL_hints.h" +#include "SDL_assert.h" +#include "../SDL_sysrender.h" + + +SDL_Renderer * PS4_CreateRenderer(SDL_Window * window, Uint32 flags) +{ + printf("# ERROR %s(), please use software renderer on ps4!\n", __FUNCTION__); + return NULL; +} + + + + +SDL_RenderDriver PS4_RenderDriver = { + .CreateRenderer = PS4_CreateRenderer, + .info = { + .name = "PS4", + .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE, + .num_texture_formats = 4, + .texture_formats = { + [0] = SDL_PIXELFORMAT_BGR565, + [1] = SDL_PIXELFORMAT_ABGR1555, + [2] = SDL_PIXELFORMAT_ABGR4444, + [3] = SDL_PIXELFORMAT_ABGR8888, + }, + .max_texture_width = 4096, + .max_texture_height = 4096, + } +}; + + + +#endif // SDL_VIDEO_RENDER_PS4 \ No newline at end of file diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c index 96477d6e41..18c319574f 100644 --- a/src/thread/pthread/SDL_systhread.c +++ b/src/thread/pthread/SDL_systhread.c @@ -28,7 +28,9 @@ #include #endif +#ifdef HAVE_SIGNAL_H #include +#endif #ifdef __LINUX__ #include @@ -160,7 +162,7 @@ SDL_SYS_SetupThread(const char *name) } /* NativeClient does not yet support signals.*/ -#if !defined(__NACL__) +#if !defined(__NACL__) && !defined(__ORBIS__) && !defined(PS4) /* Mask asynchronous signals for this thread */ sigemptyset(&mask); for (i = 0; sig_list[i]; ++i) { diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index c0cc221871..f1795a6de8 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -109,6 +109,7 @@ SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, SDL_FreePalette(palette); } + /* Get the pixels */ if (surface->w && surface->h) { /* Assumptions checked in surface_size_assumptions assert above */ @@ -126,7 +127,9 @@ SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, SDL_OutOfMemory(); return NULL; } + surface->flags |= SDL_SIMD_ALIGNED; + /* This is important for bitmaps */ SDL_memset(surface->pixels, 0, surface->h * surface->pitch); } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index e88a8b60eb..1b6999a943 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -413,6 +413,7 @@ extern VideoBootStrap PND_bootstrap; extern VideoBootStrap UIKIT_bootstrap; extern VideoBootStrap Android_bootstrap; extern VideoBootStrap PSP_bootstrap; +extern VideoBootStrap PS4_bootstrap; extern VideoBootStrap RPI_bootstrap; extern VideoBootStrap KMSDRM_bootstrap; extern VideoBootStrap DUMMY_bootstrap; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 08590cafd6..ba6346bd92 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -94,6 +94,9 @@ static VideoBootStrap *bootstrap[] = { #if SDL_VIDEO_DRIVER_PSP &PSP_bootstrap, #endif +#if SDL_VIDEO_DRIVER_PS4 + &PS4_bootstrap, +#endif #if SDL_VIDEO_DRIVER_KMSDRM &KMSDRM_bootstrap, #endif @@ -259,6 +262,7 @@ SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * f data = SDL_GetWindowData(window, SDL_WINDOWTEXTUREDATA); if (!data) { + SDL_Renderer *renderer = NULL; int i; const char *hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION); @@ -290,12 +294,13 @@ SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * f } } } + if (!renderer) { return SDL_SetError("No hardware accelerated renderers available"); } /* Create the data after we successfully create the renderer (bug #1116) */ - data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(*data)); + data = (SDL_WindowTextureData *)SDL_calloc(1, sizeof(SDL_WindowTextureData)); if (!data) { SDL_DestroyRenderer(renderer); return SDL_OutOfMemory(); @@ -1028,7 +1033,7 @@ SDL_GetDisplay(int displayIndex) int SDL_GetWindowDisplayIndex(SDL_Window * window) { - int displayIndex; + int displayIndex=0; int i, dist; int closest = -1; int closest_dist = 0x7FFFFFFF; @@ -1426,6 +1431,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) h = 1; } + /* Some platforms blow up if the windows are too large. Raise it later? */ if ((w > 16384) || (h > 16384)) { SDL_SetError("Window is too large."); @@ -1438,6 +1444,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) flags |= SDL_WINDOW_OPENGL; } #endif + if (flags & SDL_WINDOW_OPENGL) { if (!_this->GL_CreateContext) { SDL_SetError("OpenGL support is either not configured in SDL " @@ -1450,6 +1457,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) } } + if (flags & SDL_WINDOW_VULKAN) { if (!_this->Vulkan_CreateSurface) { SDL_SetError("Vulkan support is either not configured in SDL " @@ -1466,6 +1474,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) } } + /* Unless the user has specified the high-DPI disabling hint, respect the * SDL_WINDOW_ALLOW_HIGHDPI flag. */ @@ -1480,6 +1489,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) SDL_OutOfMemory(); return NULL; } + window->magic = &_this->window_magic; window->id = _this->next_object_id++; window->x = x; @@ -1506,6 +1516,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) window->windowed.w = window->w; window->windowed.h = window->h; + if (flags & SDL_WINDOW_FULLSCREEN) { SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); int displayIndex; @@ -1532,6 +1543,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) } _this->windows = window; + if (_this->CreateSDLWindow && _this->CreateSDLWindow(_this, window) < 0) { SDL_DestroyWindow(window); return NULL; @@ -1558,6 +1570,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) flags = window->flags; #endif + if (title) { SDL_SetWindowTitle(window, title); } @@ -1566,6 +1579,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) /* If the window was created fullscreen, make sure the mode code matches */ SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window)); + return window; } @@ -2272,6 +2286,7 @@ SDL_CreateWindowFramebuffer(SDL_Window * window) int bpp; Uint32 Rmask, Gmask, Bmask, Amask; + if (!_this->CreateWindowFramebuffer || !_this->UpdateWindowFramebuffer) { return NULL; } @@ -2279,7 +2294,7 @@ SDL_CreateWindowFramebuffer(SDL_Window * window) if (_this->CreateWindowFramebuffer(_this, window, &format, &pixels, &pitch) < 0) { return NULL; } - + if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { return NULL; } diff --git a/src/video/ps4/SDL_ps4video.c b/src/video/ps4/SDL_ps4video.c new file mode 100644 index 0000000000..6670ea45c7 --- /dev/null +++ b/src/video/ps4/SDL_ps4video.c @@ -0,0 +1,673 @@ +/* + 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" + + +#if SDL_VIDEO_DRIVER_PS4 + +//#include + + +/* 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_Available, + PS4_Create +}; + +#define INLINE inline + +INLINE static SDL_VideoData * getVideoData(_THIS) { + return ((SDL_VideoData *)_this->driverdata); +} +#define VData getVideoData(_this) +#define PS4_VideoData SDL_VideoData *videoData = VData + + +INLINE static void setHandle(_THIS, int handle) { + VData->h_vout = handle; +} + +INLINE static int32_t Handle(_THIS) { return VData->h_vout; } + +INLINE static size_t Width(_THIS) { return VData->attr.width; } +INLINE static size_t Height(_THIS) { return VData->attr.height; } + +INLINE static size_t MemSize(_THIS) { return VData->memSize; } +INLINE static size_t BufferSize(_THIS) { return VData->bufSize; } +INLINE static size_t BufferCount(_THIS) { return VOUT_NUM_BUFFERS; } // (tripleBuffer ? 3 : 2); } + +INLINE static uint8_t* GetBuffer(_THIS, size_t n) { return VData->addrList[n & 3]; } +INLINE static uint8_t* CurrentBuffer(_THIS) { return GetBuffer(_this, VData->currBuffer); } +INLINE static uint8_t* NextBuffer(_THIS) { return GetBuffer(_this, ((VData->currBuffer + 1) % VOUT_NUM_BUFFERS)); } + + + +INLINE static int32_t IsFlipPending(_THIS) { + return sceVideoOutIsFlipPending(Handle(_this)) > 0; +} + +INLINE static void WaitOnFlip(_THIS) { + int out = 0; + SceKernelEvent ev; + while (IsFlipPending(_this)) { + //assert(SCE_OK == + sceKernelWaitEqueue(VData->flipQueue, &ev, 1, &out, 0); + //); // assert + } +} + +//INLINE bool GetFlipStatus(_THIS,SceVideoOutFlipStatus *status) { +// return SCE_OK == sceVideoOutGetFlipStatus(Handle(), status); +//} + +// sceVideoOutGetResolutionStatus +#if 0 +INLINE static void WaitOnFlip(size_t arg) { + int out = 0; + SceKernelEvent ev; + SceVideoOutFlipStatus status; + + while (1) { + GetFlipStatus(&status); + if (status.flipArg >= arg) + return; + (SCE_OK == sceKernelWaitEqueue(flipQueue, &ev, 1, &out, 0)); // assert + } +} +#endif + +INLINE static void SubmitFlip(_THIS) //s64 buffer = -1, u64 arg = 0) +{ +// sce::Gnm::flushGarlic(); + + //currBuffer = (buffer == -1) ? currBuffer : buffer; + sceVideoOutSubmitFlip(Handle(_this), VData->currBuffer, SCE_VIDEO_OUT_FLIP_MODE_VSYNC, 0); // !wantVsync _HSYNC + //printf("SubmitFlip() Buffer[%d] %p \n", currBuffer, (u8*)CurrentBuffer()); + + VData->currBuffer = ((VData->currBuffer + 1) % BufferCount(_this)); +} + + + + + + + + + + + + + + + + + + + + + + +static void FreeFramebuffers(_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); +} + +inline static size_t AlignUp(size_t v, size_t a) +{ + return ((v) + (a - 1)) & ~(a - 1); +} + +static int AllocFramebuffers(_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 = SCE_OK; + + if (SCE_OK != (res = sceKernelAllocateDirectMemory(0, SCE_KERNEL_MAIN_DMEM_SIZE, VData->memSize, alignTo, SCE_KERNEL_WC_GARLIC, &VData->phyAddr))) { + SDL_SetError("sceKernelAllocateDirectMemory() Failed "); // printf("Error, sceKernelAllocateDirectMemory() Failed with 0x%08X\n", (uint32_t)res); + return -1; + } + if (SCE_OK != (res = sceKernelMapDirectMemory((void**)&VData->mapAddr, VData->memSize, SCE_KERNEL_PROT_CPU_RW | SCE_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 (SCE_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(_THIS) +{ + int handle = 0; + SceVideoOutResolutionStatus res; + + handle = sceVideoOutOpen(SCE_USER_SERVICE_USER_ID_SYSTEM, SCE_VIDEO_OUT_BUS_TYPE_MAIN, 0, NULL); + if(handle <= 0) { + SDL_SetError("sceVideoOutOpen() failed"); + return -1; + } + setHandle(_this, handle); + + if (0 == sceVideoOutGetResolutionStatus(handle, &res)) { + VData->width = res.fullWidth; + VData->height = res.fullHeight; + } + + memset(&VData->attr, 0, sizeof(VData->attr)); + VData->attr.width = VData->width; + VData->attr.height = VData->height; + VData->attr.aspectRatio = SCE_VIDEO_OUT_ASPECT_RATIO_16_9; + VData->attr.pixelFormat = SCE_VIDEO_OUT_PIXEL_FORMAT_A8R8G8B8_SRGB; + VData->attr.tilingMode = SCE_VIDEO_OUT_TILING_MODE_LINEAR; // (!tile) ? : 0; // change to tiled later, GpuMode must be NEO for pro + VData->attr.pitchInPixel= VData->width; + + + if (SCE_OK != sceKernelCreateEqueue(&VData->flipQueue, "flipQueue") || + SCE_OK != sceVideoOutAddFlipEvent(VData->flipQueue, handle, NULL)) { + SDL_SetError("Failed to create/add flip queue\n"); + return -1; + } + + if (SCE_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(_THIS) { + FreeFramebuffers(_this); + sceVideoOutClose(VData->h_vout); + VData->h_vout = 0; +} + + + + + + + + + + + + + + + + + +/* unused +static SDL_bool PS4_initialized = SDL_FALSE; +*/ +static int PS4_Available(void) +{ + D_FN(); + return 1; +} + +static void PS4_Destroy(SDL_VideoDevice * device) +{ + D_FN(); + +/* SDL_VideoData *phdata = (SDL_VideoData *) device->driverdata; */ + + if (device->driverdata != NULL) { + device->driverdata = NULL; + } +} + +static SDL_VideoDevice *PS4_Create() +{ + D_FN(); + + 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 = SDL_FALSE; + device->gl_data = gldata; +#endif + + phdata->h_vout = 0; // VideoOut handle + phdata->width = 1920; + phdata->height = 1080; // defaults + + device->driverdata = 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->CreateSDLWindowFrom = PS4_CreateWindowFrom; + 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->SetWindowGrab = PS4_SetWindowGrab; + 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 */ +/*****************************************************************************/ +int PS4_VideoInit(_THIS) +{ + D_FN(); + + uint8_t *ppp = (uint8_t*)SDL_malloc(1024 * 1024 * 128); + if (ppp) SDL_free(ppp); + else { + printf("@@@ ERROR, the memory allocator is refusing to work,\n make sure you're not trying to use the GLES wrapper and try raising the libc heap limit!\n"); + return -1; + } + + SDL_VideoDisplay display; + + SDL_DisplayMode current_mode; + SDL_zero(current_mode); + + if (SCE_OK != vout_init(_this)) + return -1; + + current_mode.w = getVideoData(_this)->width; + current_mode.h = getVideoData(_this)->height; + + current_mode.refresh_rate = 60; + /* 32 bpp for default */ + current_mode.format = SDL_PIXELFORMAT_ABGR8888; + current_mode.driverdata = NULL; + + SDL_zero(display); + display.desktop_mode = current_mode; + display.current_mode = current_mode; + display.driverdata = NULL; + + SDL_AddVideoDisplay(&display); + + return 1; +} + +void PS4_VideoQuit(_THIS) +{ + D_FN(); + + vout_term(_this); +} + +void PS4_GetDisplayModes(_THIS, SDL_VideoDisplay * display) +{ + D_FN(); + +} + +int PS4_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) +{ + D_FN(); + return 0; +} + + +int PS4_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) +{ + D_FN(); + + //PS4_VideoData; // videoData * + + SDL_Surface *surface; + const Uint32 surface_format = SDL_PIXELFORMAT_BGR888; + int w, h; + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + + /* Free the old framebuffer surface */ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + surface = data->surface; + SDL_FreeSurface(surface); + + /* Create a new one */ + SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + SDL_GetWindowSize(window, &w, &h); + + surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask); + if (!surface) { + SDL_SetError("SDL_CreateRGBSurface() FAILED"); + return -1; + } + + /* Save the info and return! */ + data->surface = surface; + *format = surface_format; + *pixels = surface->pixels; + *pitch = surface->pitch; + return 0; +} + +int PS4_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects) +{ +// D_FN(); + + SDL_Surface *surface; + + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + 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 -1; + } + memset(pDst, 0, BufferSize(_this)); + + /// annoyances ... calculate actual window coords and clip + + PS4_VideoData; // videoData * + 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 0; +} + +void PS4_DestroyWindowFramebuffer(_THIS, SDL_Window * window) +{ + D_FN(); + + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + + SDL_FreeSurface(data->surface); + data->surface = NULL; +} + + + + + + + + + + + + +void PS4_PumpEvents(_THIS) +{ +// D_FN(); + + return; +} + + + +int PS4_CreateWindow(_THIS, SDL_Window * window) +{ + D_FN(); + SDL_WindowData *wdata; + + /* Allocate window internal data */ + wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); + if (wdata == NULL) { + return SDL_OutOfMemory(); + } + //PS4_VideoData; // videoData * + + + /* Setup driver data for this window */ + if (window) { + window->driverdata = wdata; + + 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; +} + +int PS4_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) +{ + D_FN(); + return SDL_Unsupported(); +} + +void PS4_SetWindowTitle(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon) +{ + D_FN(); +} +void PS4_SetWindowPosition(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_SetWindowSize(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_ShowWindow(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_HideWindow(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_RaiseWindow(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_MaximizeWindow(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_MinimizeWindow(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_RestoreWindow(_THIS, SDL_Window * window) +{ + D_FN(); +} +void PS4_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed) +{ + D_FN(); +} +void PS4_DestroyWindow(_THIS, SDL_Window * window) +{ + D_FN(); +} + +/*****************************************************************************/ +/* SDL Window Manager function */ +/*****************************************************************************/ +#if 0 +SDL_bool PS4_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) { + return SDL_TRUE; + } else { + SDL_SetError("Application not compiled with SDL %d.%d", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return SDL_FALSE; + } + + /* Failed to get window manager information */ + return SDL_FALSE; +} +#endif + + +/* TO Write Me */ +SDL_bool PS4_HasScreenKeyboardSupport(_THIS) +{ + D_FN(); + return SDL_FALSE; +} +void PS4_ShowScreenKeyboard(_THIS, SDL_Window *window) +{ + D_FN(); +} +void PS4_HideScreenKeyboard(_THIS, SDL_Window *window) +{ + D_FN(); +} +SDL_bool PS4_IsScreenKeyboardShown(_THIS, SDL_Window *window) +{ + D_FN(); + return SDL_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 0000000000..1079e4d88f --- /dev/null +++ b/src/video/ps4/SDL_ps4video.h @@ -0,0 +1,131 @@ +/* + 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. +*/ + +#ifndef SDL_ps4video_h_ +#define SDL_ps4video_h_ + + +#include "../../SDL_internal.h" +#include "../SDL_sysvideo.h" + +#include + +#define VOUT_NUM_BUFFERS 2 + +typedef struct SDL_VideoData +{ + int h_vout; // VideoOut handle + uint32_t width, height; + + SceKernelEqueue flipQueue; + SceVideoOutBufferAttribute 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 */ +/****************************************************************************/ + +void PS4_PumpEvents(_THIS); + +/* Display and window functions */ +int PS4_VideoInit(_THIS); +void PS4_VideoQuit(_THIS); +void PS4_GetDisplayModes(_THIS, SDL_VideoDisplay * display); +int PS4_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); +int PS4_CreateWindow(_THIS, SDL_Window * window); +int PS4_CreateWindowFrom(_THIS, SDL_Window * window, const void *data); +void PS4_SetWindowTitle(_THIS, SDL_Window * window); +void PS4_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon); +void PS4_SetWindowPosition(_THIS, SDL_Window * window); +void PS4_SetWindowSize(_THIS, SDL_Window * window); +void PS4_ShowWindow(_THIS, SDL_Window * window); +void PS4_HideWindow(_THIS, SDL_Window * window); +void PS4_RaiseWindow(_THIS, SDL_Window * window); +void PS4_MaximizeWindow(_THIS, SDL_Window * window); +void PS4_MinimizeWindow(_THIS, SDL_Window * window); +void PS4_RestoreWindow(_THIS, SDL_Window * window); +void PS4_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed); +void PS4_DestroyWindow(_THIS, SDL_Window * window); + +int PS4_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch); +int PS4_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects); +void PS4_DestroyWindowFramebuffer(_THIS, SDL_Window * window); + + +/* Window manager function */ +SDL_bool PS4_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info); + +#if PS4_VIDEO_GL +/* OpenGL/OpenGL ES functions */ +int PS4_GL_LoadLibrary(_THIS, const char *path); +void *PS4_GL_GetProcAddress(_THIS, const char *proc); +void PS4_GL_UnloadLibrary(_THIS); +SDL_GLContext PS4_GL_CreateContext(_THIS, SDL_Window * window); +int PS4_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); +int PS4_GL_SetSwapInterval(_THIS, int interval); +int PS4_GL_GetSwapInterval(_THIS); +int PS4_GL_SwapWindow(_THIS, SDL_Window * window); +void PS4_GL_DeleteContext(_THIS, SDL_GLContext context); +#endif + +/* PS4 on screen keyboard */ +SDL_bool PS4_HasScreenKeyboardSupport(_THIS); +void PS4_ShowScreenKeyboard(_THIS, SDL_Window *window); +void PS4_HideScreenKeyboard(_THIS, SDL_Window *window); +SDL_bool PS4_IsScreenKeyboardShown(_THIS, SDL_Window *window); + +#endif /* SDL_ps4video_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */