SDL: Initial rebase of xerpi's port

From 2d64e37e41eb6ab4795bba90aee26269100ff770 Mon Sep 17 00:00:00 2001
From: Ivan Epifanov <[EMAIL REDACTED]>
Date: Mon, 2 Nov 2020 18:09:43 +0300
Subject: [PATCH] Initial rebase of xerpi's port

---
 Makefile.vita.dolce                 |  59 +++++
 include/SDL_config.h                |   2 +
 include/SDL_config_vita.h           | 158 +++++++++++++
 src/SDL.c                           |   2 +
 src/SDL_log.c                       |   7 +
 src/audio/SDL_audio.c               |   3 +
 src/audio/SDL_sysaudio.h            |   1 +
 src/audio/vita/SDL_vitaaudio.c      | 203 +++++++++++++++++
 src/audio/vita/SDL_vitaaudio.h      |  45 ++++
 src/cpuinfo/SDL_cpuinfo.c           |   2 +
 src/dynapi/SDL_dynapi.h             |   2 +
 src/joystick/SDL_gamecontrollerdb.h |   4 +
 src/joystick/vita/SDL_sysjoystick.c | 310 +++++++++++++++++++++++++
 src/power/SDL_power.c               |   3 +
 src/power/SDL_syspower.h            |   1 +
 src/power/vita/SDL_syspower.c       |  68 ++++++
 src/thread/SDL_thread_c.h           |   2 +
 src/thread/vita/SDL_syscond.c       | 224 ++++++++++++++++++
 src/thread/vita/SDL_sysmutex.c      | 136 +++++++++++
 src/thread/vita/SDL_sysmutex_c.h    |  22 ++
 src/thread/vita/SDL_syssem.c        | 163 +++++++++++++
 src/thread/vita/SDL_systhread.c     | 112 +++++++++
 src/thread/vita/SDL_systhread_c.h   |  24 ++
 src/timer/vita/SDL_systimer.c       |  91 ++++++++
 src/video/SDL_sysvideo.h            |   1 +
 src/video/SDL_video.c               |   3 +
 src/video/vita/SDL_vitagl.c         | 221 ++++++++++++++++++
 src/video/vita/SDL_vitagl_c.h       |  56 +++++
 src/video/vita/SDL_vitakeyboard.c   | 198 ++++++++++++++++
 src/video/vita/SDL_vitakeyboard.h   |  33 +++
 src/video/vita/SDL_vitamouse.c      |  94 ++++++++
 src/video/vita/SDL_vitamouse_c.h    |  33 +++
 src/video/vita/SDL_vitatouch.c      | 179 +++++++++++++++
 src/video/vita/SDL_vitatouch.h      |  35 +++
 src/video/vita/SDL_vitavideo.c      | 341 ++++++++++++++++++++++++++++
 src/video/vita/SDL_vitavideo.h      | 102 +++++++++
 36 files changed, 2940 insertions(+)
 create mode 100644 Makefile.vita.dolce
 create mode 100644 include/SDL_config_vita.h
 create mode 100644 src/audio/vita/SDL_vitaaudio.c
 create mode 100644 src/audio/vita/SDL_vitaaudio.h
 create mode 100644 src/joystick/vita/SDL_sysjoystick.c
 create mode 100644 src/power/vita/SDL_syspower.c
 create mode 100644 src/thread/vita/SDL_syscond.c
 create mode 100644 src/thread/vita/SDL_sysmutex.c
 create mode 100644 src/thread/vita/SDL_sysmutex_c.h
 create mode 100644 src/thread/vita/SDL_syssem.c
 create mode 100644 src/thread/vita/SDL_systhread.c
 create mode 100644 src/thread/vita/SDL_systhread_c.h
 create mode 100644 src/timer/vita/SDL_systimer.c
 create mode 100644 src/video/vita/SDL_vitagl.c
 create mode 100644 src/video/vita/SDL_vitagl_c.h
 create mode 100644 src/video/vita/SDL_vitakeyboard.c
 create mode 100644 src/video/vita/SDL_vitakeyboard.h
 create mode 100644 src/video/vita/SDL_vitamouse.c
 create mode 100644 src/video/vita/SDL_vitamouse_c.h
 create mode 100644 src/video/vita/SDL_vitatouch.c
 create mode 100644 src/video/vita/SDL_vitatouch.h
 create mode 100644 src/video/vita/SDL_vitavideo.c
 create mode 100644 src/video/vita/SDL_vitavideo.h

diff --git a/Makefile.vita.dolce b/Makefile.vita.dolce
new file mode 100644
index 000000000..c9ca1ca88
--- /dev/null
+++ b/Makefile.vita.dolce
@@ -0,0 +1,59 @@
+# Based on port by xerpi
+# Makefile to build the SDL library
+
+TARGET_LIB = libSDL2.a
+
+SOURCES = \
+	src/*.c \
+	src/atomic/*.c \
+	src/audio/*.c \
+	src/audio/vita/*.c \
+	src/cpuinfo/*.c \
+	src/events/*.c \
+	src/file/*.c \
+	src/haptic/*.c \
+	src/haptic/dummy/*.c \
+	src/joystick/*.c \
+	src/joystick/vita/*.c \
+	src/loadso/dummy/*.c \
+	src/power/*.c \
+	src/power/vita/*.c \
+	src/filesystem/dummy/*.c \
+	src/render/*.c \
+	src/render/software/*.c \
+	src/render/opengles2/SDL_render_gles2.c \
+	src/render/vita/*.c \
+	src/sensor/*.c \
+	src/sensor/dummy/*.c \
+	src/stdlib/*.c \
+	src/thread/*.c \
+	src/thread/generic/SDL_systls.c \
+	src/thread/vita/*.c \
+	src/timer/*.c \
+	src/timer/vita/*.c \
+	src/video/*.c \
+	src/video/vita/*.c \
+	src/video/yuv2rgb/*.c \
+
+OBJS = $(shell echo $(SOURCES) | sed -e 's,\.c,\.o,g')
+
+PREFIX  = arm-dolce-eabi
+CC      = $(PREFIX)-gcc
+AR      = $(PREFIX)-ar
+CFLAGS  = -g -Wl,-q -Wall -O3 -Iinclude \
+                        -D__VITA__ -D__ARM_ARCH=7 -D__ARM_ARCH_7A__ \
+                        -mfpu=neon -mcpu=cortex-a9 -mfloat-abi=hard
+ASFLAGS = $(CFLAGS)
+
+$(TARGET_LIB): $(OBJS)
+	$(AR) rcs $@ $^
+
+clean:
+	@rm -f $(TARGET_LIB) $(OBJS)
+
+install: $(TARGET_LIB)
+	@mkdir -p "$(DOLCESDK)/arm-dolce-eabi/lib"
+	@cp  $(TARGET_LIB) $(DOLCESDK)/arm-dolce-eabi/lib
+	@mkdir -p "$(DOLCESDK)/arm-dolce-eabi/include/SDL2"
+	@cp include/*.h "$(DOLCESDK)/arm-dolce-eabi/include/SDL2"
+	@echo "Installed!"
diff --git a/include/SDL_config.h b/include/SDL_config.h
index 378e180d8..0c3f56f2a 100644
--- a/include/SDL_config.h
+++ b/include/SDL_config.h
@@ -43,6 +43,8 @@
 #include "SDL_config_psp.h"
 #elif defined(__OS2__)
 #include "SDL_config_os2.h"
+#elif defined(__VITA__)
+#include "SDL_config_vita.h"
 #else
 /* This is a minimal configuration just to get SDL running on new platforms. */
 #include "SDL_config_minimal.h"
diff --git a/include/SDL_config_vita.h b/include/SDL_config_vita.h
new file mode 100644
index 000000000..d03aae3e1
--- /dev/null
+++ b/include/SDL_config_vita.h
@@ -0,0 +1,158 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 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_config_vita_h
+#define _SDL_config_vita_h
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* include stdint.h here, needed on Vita to compile the yuv_rgb.h */
+#include <stdint.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_SIGNAL_H   1
+#define HAVE_STDINT_H   1
+#define HAVE_STDIO_H    1
+#define HAVE_STRING_H   1
+#define HAVE_SYS_TYPES_H    1
+
+/* 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_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_LOG10 1
+#define HAVE_LOG10F 1
+/* #define HAVE_SYSCONF  1 */
+/* #define HAVE_SIGACTION    1 */
+
+
+/* VITA isn't that sophisticated */
+#define LACKS_SYS_MMAN_H 1
+
+
+#define SDL_AUDIO_DRIVER_VITA  1
+#define SDL_THREAD_VITA    1
+#define SDL_JOYSTICK_VITA   1
+#define SDL_TIMERS_VITA 1
+#define SDL_POWER_VITA 1
+#define SDL_VIDEO_DRIVER_VITA  1
+
+
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+#define SDL_VIDEO_OPENGL_ES2 1
+
+
+/* !!! FIXME: what does VITA do for filesystem stuff? */
+#define SDL_FILESYSTEM_DUMMY   1
+
+/* VITA doesn't have haptic device (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DISABLED    1
+
+/* VITA can't load shared object (src/loadso/dummy/\*.c) */
+// that' not true, but oh well
+#define SDL_LOADSO_DISABLED    1
+
+#define SDL_SENSOR_DISABLED 1
+#define SDL_SENSOR_DUMMY  1
+
+#endif /* _SDL_config_vita_h */
diff --git a/src/SDL.c b/src/SDL.c
index 124aceebf..c5cf06730 100644
--- a/src/SDL.c
+++ b/src/SDL.c
@@ -527,6 +527,8 @@ SDL_GetPlatform()
     return "iOS";
 #elif __PSP__
     return "PlayStation Portable";
+#elif __VITA__
+    return "PlayStation Vita";
 #else
     return "Unknown (see SDL_platform.h)";
 #endif
diff --git a/src/SDL_log.c b/src/SDL_log.c
index 9a5d1c480..d14c3d2f0 100644
--- a/src/SDL_log.c
+++ b/src/SDL_log.c
@@ -422,6 +422,13 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
         fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
         fclose (pFile);
     }
+#elif defined(__VITA__)
+    {
+        FILE*        pFile;
+        pFile = fopen ("ux0:/data/SDL_Log.txt", "a");
+        fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message);
+        fclose (pFile);
+    }
 #endif
 #if HAVE_STDIO_H
     fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 725e169ce..00ee976c6 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_VITA
+    &VITAAUD_bootstrap,
+#endif
 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
     &EMSCRIPTENAUDIO_bootstrap,
 #endif
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
index 0c66ec657..d7fd556bd 100644
--- a/src/audio/SDL_sysaudio.h
+++ b/src/audio/SDL_sysaudio.h
@@ -208,6 +208,7 @@ extern AudioBootStrap FUSIONSOUND_bootstrap;
 extern AudioBootStrap openslES_bootstrap;
 extern AudioBootStrap ANDROIDAUDIO_bootstrap;
 extern AudioBootStrap PSPAUDIO_bootstrap;
+extern AudioBootStrap VITAAUD_bootstrap;
 extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
 extern AudioBootStrap OS2AUDIO_bootstrap;
 
diff --git a/src/audio/vita/SDL_vitaaudio.c b/src/audio/vita/SDL_vitaaudio.c
new file mode 100644
index 000000000..5225b8033
--- /dev/null
+++ b/src/audio/vita/SDL_vitaaudio.c
@@ -0,0 +1,203 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2015 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"
+
+#if SDL_AUDIO_DRIVER_VITA
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+#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_vitaaudio.h"
+
+#include <psp2/kernel/threadmgr.h>
+#include <psp2/audioout.h>
+
+#define SCE_AUDIO_SAMPLE_ALIGN(s)   (((s) + 63) & ~63)
+#define SCE_AUDIO_MAX_VOLUME      0x8000
+
+/* The tag name used by VITA audio */
+#define VITAAUD_DRIVER_NAME         "vita"
+
+static int
+VITAAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+{
+    int format, mixlen, i, port = SCE_AUDIO_OUT_PORT_TYPE_MAIN;
+
+    this->hidden = (struct SDL_PrivateAudioData *)
+        SDL_malloc(sizeof(*this->hidden));
+    if (this->hidden == NULL) {
+        return SDL_OutOfMemory();
+    }
+    SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+    switch (this->spec.format & 0xff) {
+        case 8:
+        case 16:
+            this->spec.format = AUDIO_S16LSB;
+            break;
+        default:
+            return SDL_SetError("Unsupported audio format");
+    }
+
+    /* The sample count must be a multiple of 64. */
+    this->spec.samples = SCE_AUDIO_SAMPLE_ALIGN(this->spec.samples);
+
+    /* Update the fragment size as size in bytes. */
+/*  SDL_CalculateAudioSpec(this->spec); MOD */
+    switch (this->spec.format) {
+    case AUDIO_U8:
+        this->spec.silence = 0x80;
+        break;
+    default:
+        this->spec.silence = 0x00;
+        break;
+    }
+    this->spec.size = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
+    this->spec.size *= this->spec.channels;
+    this->spec.size *= this->spec.samples;
+
+/* ========================================== */
+
+    /* 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");
+    }
+
+    /* Setup the hardware channel. */
+    if (this->spec.channels == 1) {
+        format = SCE_AUDIO_OUT_MODE_MONO;
+    } else {
+        format = SCE_AUDIO_OUT_MODE_STEREO;
+    }
+
+    if(this->spec.freq < 48000) {
+		port = SCE_AUDIO_OUT_PORT_TYPE_BGM;
+	}
+
+    this->hidden->channel = sceAudioOutOpenPort(port, this->spec.samples, this->spec.freq, format);
+    if (this->hidden->channel < 0) {
+        free(this->hidden->rawbuf);
+        this->hidden->rawbuf = NULL;
+        return SDL_SetError("Couldn't reserve hardware channel");
+    }
+
+    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 VITAAUD_PlayDevice(_THIS)
+{
+    Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
+
+    int vols[2] = {SCE_AUDIO_MAX_VOLUME, SCE_AUDIO_MAX_VOLUME};
+    sceAudioOutSetVolume(this->hidden->channel, SCE_AUDIO_VOLUME_FLAG_L_CH|SCE_AUDIO_VOLUME_FLAG_R_CH, vols);
+    sceAudioOutOutput(this->hidden->channel, mixbuf);
+
+    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 VITAAUD_WaitDevice(_THIS)
+{
+    /* Because we block when sending audio, there's no need for this function to do anything. */
+}
+static Uint8 *VITAAUD_GetDeviceBuf(_THIS)
+{
+    return this->hidden->mixbufs[this->hidden->next_buffer];
+}
+
+static void VITAAUD_CloseDevice(_THIS)
+{
+    if (this->hidden->channel >= 0) {
+        sceAudioOutReleasePort(this->hidden->channel);
+        this->hidden->channel = -1;
+    }
+
+    if (this->hidden->rawbuf != NULL) {
+        free(this->hidden->rawbuf);
+        this->hidden->rawbuf = NULL;
+    }
+}
+static void VITAAUD_ThreadInit(_THIS)
+{
+    /* Increase the priority of this audio thread by 1 to put it
+       ahead of other SDL threads. */
+    SceUID thid;
+    SceKernelThreadInfo info;
+    thid = sceKernelGetThreadId();
+    info.size = sizeof(SceKernelThreadInfo);
+    if (sceKernelGetThreadInfo(thid, &info) == 0) {
+        sceKernelChangeThreadPriority(thid, info.currentPriority - 1);
+    }
+}
+
+
+static int
+VITAAUD_Init(SDL_AudioDriverImpl * impl)
+{
+
+    /* Set the function pointers */
+    impl->OpenDevice = VITAAUD_OpenDevice;
+    impl->PlayDevice = VITAAUD_PlayDevice;
+    impl->WaitDevice = VITAAUD_WaitDevice;
+    impl->GetDeviceBuf = VITAAUD_GetDeviceBuf;
+    impl->CloseDevice = VITAAUD_CloseDevice;
+    impl->ThreadInit = VITAAUD_ThreadInit;
+
+    /* VITA audio device */
+    impl->OnlyHasDefaultOutputDevice = 1;
+/*
+    impl->HasCaptureSupport = 1;
+
+    impl->OnlyHasDefaultInputDevice = 1;
+*/
+    /*
+    impl->DetectDevices = DSOUND_DetectDevices;
+    impl->Deinitialize = DSOUND_Deinitialize;
+    */
+    return 1;   /* this audio target is available. */
+}
+
+AudioBootStrap VITAAUD_bootstrap = {
+    "vita", "VITA audio driver", VITAAUD_Init, 0
+};
+
+ /* SDL_AUDI */
+
+#endif /* SDL_AUDIO_DRIVER_VITA */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/audio/vita/SDL_vitaaudio.h b/src/audio/vita/SDL_vitaaudio.h
new file mode 100644
index 000000000..0c1ad523b
--- /dev/null
+++ b/src/audio/vita/SDL_vitaaudio.h
@@ -0,0 +1,45 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2015 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_vitaaudio_h
+#define _SDL_vitaaudio_h
+
+#include "../SDL_sysaudio.h"
+
+/* Hidden "this" pointer for the audio functions */
+#define _THIS   SDL_AudioDevice *this
+
+#define NUM_BUFFERS 2
+
+struct SDL_PrivateAudioData {
+    /* The hardware output channel. */
+    int     channel;
+    /* 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_vitaaudio_h */
+/* vim: ts=4 sw=4
+ */
diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c
index 1f134e11b..1668e701c 100644
--- a/src/cpuinfo/SDL_cpuinfo.c
+++ b/src/cpuinfo/SDL_cpuinfo.c
@@ -450,6 +450,8 @@ CPU_haveNEON(void)
     return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) != 0;
 #elif (defined(__ARM_ARCH) && (__ARM_ARCH >= 8)) || defined(__aarch64__)
     return 1;  /* ARMv8 always has non-optional NEON support. */
+#elif __VITA__
+    return 1;
 #elif defined(__APPLE__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7)
     /* (note that sysctlbyname("hw.optional.neon") doesn't work!) */
     return 1;  /* all Apple ARMv7 chips and later have NEON. */
diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h
index e8acb7f78..2619ff761 100644
--- a/src/dynapi/SDL_dynapi.h
+++ b/src/dynapi/SDL_dynapi.h
@@ -57,6 +57,8 @@
 #define SDL_DYNAMIC_API 0
 #elif defined(__clang_analyzer__)
 #define SDL_DYNAMIC_API 0  /* Turn off for static analysis, so reports are more clear. */
+#elif defined(__VITA__)
+#define SDL_DYNAMIC_API 0  /* vitasdk doesn't support dynamic linking */
 #endif
 
 /* everyone else. This is where we turn on the API if nothing forced it off. */
diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h
index 9ee4d458a..87d3c560b 100644
--- a/src/joystick/SDL_gamecontrollerdb.h
+++ b/src/joystick/SDL_gamecontrollerdb.h
@@ -856,6 +856,10 @@ static const char *s_ControllerMappings [] =
 #if defined(SDL_JOYSTICK_EMSCRIPTEN)
     "default,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
 #endif
+#if defined(SDL_JOYSTICK_VITA)
+    "50535669746120436f6e74726f6c6c65,PSVita Controller,y:b0,b:b1,a:b2,x:b3,leftshoulder:b4,rightshoulder:b5,dpdown:b6,dpleft:b7,dpup:b8,dpright:b9,back:b10,start:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
+#endif
+    "hidapi,*,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
     NULL
 };
 
diff --git a/src/joystick/vita/SDL_sysjoystick.c b/src/joystick/vita/SDL_sysjoystick.c
new file mode 100644
index 000000000..151e3f86c
--- /dev/null
+++ b/src/joystick/vita/SDL_sysjoystick.c
@@ -0,0 +1,310 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2015 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"
+
+#if SDL_JOYSTICK_VITA
+
+/* This is the PSVita implementation of the SDL joystick API */
+#include <psp2/types.h>
+#include <psp2/ctrl.h>
+#include <psp2/kernel/threadmgr.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_thread.h"
+#include "SDL_mutex.h"
+#include "SDL_timer.h"
+
+/* Current pad state */
+static SceCtrlData pad0 = { .lx = 0, .ly = 0, .rx = 0, .ry = 0, .buttons = 0 };
+static SceCtrlData pad1 = { .lx = 0, .ly = 0, .rx = 0, .ry = 0, .buttons = 0 };
+static SceCtrlData pad2 = { .lx = 0, .ly = 0, .rx = 0, .ry = 0, .buttons = 0 };
+static SceCtrlData pad3 = { .lx = 0, .ly = 0, .rx = 0, .ry = 0, .buttons = 0 };
+static int port_map[4]= { 0, 2, 3, 4 }; //index: SDL joy number, entry: Vita port number
+static int SDL_numjoysticks = 1;
+static const unsigned int button_map[] = {
+    SCE_CTRL_TRIANGLE, SCE_CTRL_CIRCLE, SCE_CTRL_CROSS, SCE_CTRL_SQUARE,
+    SCE_CTRL_LTRIGGER, SCE_CTRL_RTRIGGER,
+    SCE_CTRL_DOWN, SCE_CTRL_LEFT, SCE_CTRL_UP, SCE_CTRL_RIGHT,
+    SCE_CTRL_SELECT, SCE_CTRL_START};
+static int analog_map[256];  /* Map analog inputs to -32768 -> 32767 */
+
+typedef struct
+{
+  int x;
+  int y;
+} point;
+
+/* 4 points define the bezier-curve. */
+/* The Vita has a good amount of analog travel, so use a linear curve */
+static point a = { 0, 0 };
+static point b = { 0, 0  };
+static point c = { 128, 32767 };
+static point d = { 128, 32767 };
+
+/* simple linear interpolation between two points */
+static SDL_INLINE void lerp (point *dest, point *a, point *b, float t)
+{
+    dest->x = a->x + (b->x - a->x)*t;
+    dest->y = a->y + (b->y - a->y)*t;
+}
+
+/* evaluate a point on a bezier-curve. t goes from 0 to 1.0 */
+static int calc_bezier_y(float t)
+{
+    point ab, bc, cd, abbc, bccd, dest;
+    lerp (&ab, &a, &b, t);           /* point between a and b */
+    lerp (&bc, &b, &c, t);           /* point between b and c */
+    lerp (&cd, &c, &d, t);           /* point between c and d */
+    lerp (&abbc, &ab, &bc, t);       /* point between ab and bc */
+    lerp (&bccd, &bc, &cd, t);       /* point between bc and cd */
+    lerp (&dest, &abbc, &bccd, t);   /* point on the bezier-curve */
+    return dest.y;
+}
+
+/* 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 SDL_SYS_JoystickInit(void)
+{
+    int i;
+
+    /* Setup input */
+    sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE);
+
+    /* Create an accurate map from analog inputs (0 to 255)
+       to SDL joystick positions (-32768 to 32767) */
+    for (i = 0; i < 128; i++)
+    {
+        float t = (float)i/127.0f;
+        analog_map[i+128] = calc_bezier_y(t);
+        analog_map[127-i] = -1 * analog_map[i+128];
+    }
+
+	SceCtrlPortInfo myPortInfo;
+
+	// Assume we have at least one controller, even when nothing is paired
+	// This way the user can jump in, pair a controller
+	// and control things immediately even if it is paired
+	// after the app has already started.
+
+	SDL_numjoysticks = 1;
+
+	//How many additional paired controllers are there?
+	sceCtrlGetControllerPortInfo(&myPortInfo);
+	//On Vita TV, port 0 and 1 are the same controller
+	//and that is the first one, so start at port 2
+	for (i=2; i<=4; i++)
+	{
+		if (myPortInfo.port[i]!=SCE_CTRL_TYPE_UNPAIRED)
+		{
+			SDL_numjoysticks++;
+		}
+	}
+  return SDL_numjoysticks;
+}
+
+int SDL_SYS_NumJoysticks()
+{
+    return SDL_numjoysticks;
+}
+
+void SDL_SYS_JoystickDetect()
+{
+}
+
+/* Function to get the device-dependent name of a joystick */
+const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
+{
+   if (device_index == 1)
+		return "PSVita Controller";
+
+	if (device_index == 2)
+		return "PSVita Controller";
+
+	if (device_index == 3)
+		return "PSVita Controller";
+
+   return "PSVita Controller";
+}
+
+/* Function to perform the mapping from device index to the instance id for this index */
+SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
+{
+    return device_index;
+}
+
+/* Function to get the device-dependent name of a joystick */
+const char *SDL_SYS_JoystickName(int index)
+{
+	if (index == 0)
+   	return "PSVita Controller";
+
+	if (index == 1)
+   	return "PSVita Controller";
+
+	if (index == 2)
+   	return "PSVita Controller";
+
+	if (index == 3)
+   	return "PSVita Controller";
+
+    SDL_SetError("No joystick available with that index");
+    return(NULL);
+}
+
+/* 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 SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
+{
+    joystick->nbuttons = sizeof(button_map)/sizeof(*button_map);
+    joystick->naxes = 4;
+    joystick->nhats = 0;
+    joystick->instance_id = device_index;
+
+    return 0;
+}
+
+/* Function to determine if this joystick is attached to the system right now */
+SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
+{
+    return SDL_TRUE;
+}
+
+/* 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 SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
+{
+    int i;
+    unsigned int buttons;
+    unsigned int changed;
+    unsigned char lx, ly, rx, ry;
+    static unsigned int old_buttons[] = { 0, 0, 0, 0 };
+    static unsigned char old_lx[] = { 0, 0, 0, 0 };
+    static unsigned char old_ly[] = { 0, 0, 0, 0 };
+    static unsigned char old_rx[] = { 0, 0, 0, 0 };
+    static unsigned char old_ry[] = { 0, 0, 0, 0 };
+    SceCtrlData *pad = NULL;
+
+	  int index = (int) SDL_JoystickInstanceID(joystick);
+
+    if (index == 0) pad = &pad0;
+    else if (index == 1) pad = &pad1;
+	  else if (index == 2) pad = &pad2;
+    else if (index == 3) pad = &pad3;
+    else return;
+
+    sceCtrlPeekBufferPositive(port_map[index], pad, 1);
+
+    buttons = pad->buttons;
+    lx = pad->lx;
+    ly = pad->ly;
+    rx = pad->rx;
+    ry = pad->ry;
+/*
+    for(i=0; i<sizeof(button_map)/sizeof(button_map[0]); i++) {
+        SDL_PrivateJoystickButton(
+            joystick, i,
+            (buttons & button_map[i]) ?
+            SDL_PRESSED : SDL_RELEASED);
+}
+*/
+    // Axes
+
+    if(old_lx[index] != lx) {
+        SDL_PrivateJoystickAxis(joystick, 0, analog_map[lx]);
+        old_lx[index] = lx;
+    }
+    if(old_ly[index] != ly) {
+        SDL_PrivateJoystickAxis(joystick, 1, analog_map[ly]);
+        old_ly[index] = ly;
+    }
+    if(old_rx[index] != rx) {
+        SDL_PrivateJoystickAxis(joystick, 2, analog_map[rx]);
+        old_rx[index] = rx;
+    }
+    if(old_ry[index] != ry) {
+        SDL_PrivateJoystickAxis(joystick, 3, analog_map[ry]);
+        old_ry[index] = ry;
+    }
+
+    // Buttons
+    changed = old_buttons[index] ^ buttons;
+    old_buttons[index] = buttons;
+    if(changed) {
+        for(i=0; i<sizeof(button_map)/sizeof(button_map[0]); i++) {
+            if(changed & button_map[i]) {
+                SDL_PrivateJoystickButton(
+                    joystick, i,
+                    (buttons & button_map[i]) ?
+                    SDL_PRESSED : SDL_RELEASED);
+            }
+        }
+     }
+}
+
+/* Function to close a joystick after use */
+void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
+{
+}
+
+/* Function to perform any system-specific joystick related cleanup */
+void SDL_SYS_JoystickQuit(void)
+{
+}
+
+SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
+{
+    SDL_JoystickGUID guid;
+    /* the GUID is just the first 16 chars of the name for now */
+    const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index );
+    SDL_zero( guid );
+    SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
+    return guid;
+}
+
+SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
+{
+    SDL_JoystickGUID guid;
+    /* the GUID is just the first 16 chars of the name for now */
+    const char *name = joystick->name;
+    SDL_zero( guid );
+    SDL_memc

(Patch may be truncated, please check the link at the top of this post.)