Add PSP support
authorCaptain Lex <kimonline@126.com>
Sun, 17 Mar 2013 20:07:02 +0800
changeset 7009 161b7b6a5303
parent 7008 e0f05e041a72
child 7010 04649ef7439b
Add PSP support
Makefile.psp
README.psp
include/SDL_config.h
include/SDL_config_psp.h
include/SDL_platform.h
include/SDL_test_common.h
src/SDL.c
src/SDL_log.c
src/audio/SDL_audio.c
src/audio/psp/SDL_pspaudio.c
src/audio/psp/SDL_pspaudio.h
src/events/SDL_gesture.c
src/joystick/psp/SDL_sysjoystick.c
src/main/psp/SDL_psp_main.c
src/power/SDL_power.c
src/power/psp/SDL_syspower.c
src/render/SDL_render.c
src/render/SDL_sysrender.h
src/render/psp/SDL_render_psp.c
src/thread/SDL_thread_c.h
src/thread/psp/SDL_syscond.c
src/thread/psp/SDL_sysmutex.c
src/thread/psp/SDL_sysmutex_c.h
src/thread/psp/SDL_syssem.c
src/thread/psp/SDL_systhread.c
src/thread/psp/SDL_systhread_c.h
src/timer/psp/SDL_systimer.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/psp/SDL_pspevents.c
src/video/psp/SDL_pspevents_c.h
src/video/psp/SDL_pspgl.c
src/video/psp/SDL_pspgl_c.h
src/video/psp/SDL_pspmouse.c
src/video/psp/SDL_pspmouse_c.h
src/video/psp/SDL_pspvideo.c
src/video/psp/SDL_pspvideo.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile.psp	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,92 @@
+TARGET_LIB = libSDL2.a
+OBJS= src/SDL.o \
+      src/SDL_assert.o \
+      src/SDL_error.o \
+      src/SDL_fatal.o \
+      src/SDL_hints.o \
+      src/SDL_log.o \
+      src/atomic/SDL_atomic.o \
+      src/atomic/SDL_spinlock.o \
+      src/audio/SDL_audio.o \
+      src/audio/SDL_audiocvt.o \
+      src/audio/SDL_audiodev.o \
+      src/audio/SDL_audiotypecvt.o \
+      src/audio/SDL_mixer.o \
+      src/audio/SDL_wave.o \
+      src/audio/psp/SDL_pspaudio.o \
+      src/cpuinfo/SDL_cpuinfo.o \
+      src/events/SDL_clipboardevents.o \
+      src/events/SDL_dropevents.o \
+      src/events/SDL_events.o \
+      src/events/SDL_gesture.o \
+      src/events/SDL_keyboard.o \
+      src/events/SDL_mouse.o \
+      src/events/SDL_quit.o \
+      src/events/SDL_touch.o \
+      src/events/SDL_windowevents.o \
+      src/file/SDL_rwops.o \
+      src/haptic/SDL_haptic.o \
+      src/haptic/dummy/SDL_syshaptic.o \
+      src/joystick/SDL_joystick.o \
+      src/joystick/SDL_gamecontroller.o \
+      src/joystick/psp/SDL_sysjoystick.o \
+      src/power/SDL_power.o \
+      src/power/psp/SDL_syspower.o \
+      src/render/SDL_render.o \
+      src/render/SDL_yuv_sw.o \
+      src/render/psp/SDL_render_psp.o \
+      src/render/software/SDL_blendfillrect.o \
+      src/render/software/SDL_blendline.o \
+      src/render/software/SDL_blendpoint.o \
+      src/render/software/SDL_drawline.o \
+      src/render/software/SDL_drawpoint.o \
+      src/render/software/SDL_render_sw.o \
+      src/render/software/SDL_rotate.o \
+      src/stdlib/SDL_getenv.o \
+      src/stdlib/SDL_iconv.o \
+      src/stdlib/SDL_malloc.o \
+      src/stdlib/SDL_qsort.o \
+      src/stdlib/SDL_stdlib.o \
+      src/stdlib/SDL_string.o \
+      src/thread/SDL_thread.o \
+      src/thread/psp/SDL_syssem.o \
+      src/thread/psp/SDL_systhread.o \
+      src/thread/psp/SDL_sysmutex.o \
+      src/thread/psp/SDL_syscond.o \
+      src/timer/SDL_timer.o \
+      src/timer/psp/SDL_systimer.o \
+      src/video/SDL_RLEaccel.o \
+      src/video/SDL_blit.o \
+      src/video/SDL_blit_0.o \
+      src/video/SDL_blit_1.o \
+      src/video/SDL_blit_A.o \
+      src/video/SDL_blit_N.o \
+      src/video/SDL_blit_auto.o \
+      src/video/SDL_blit_copy.o \
+      src/video/SDL_blit_slow.o \
+      src/video/SDL_bmp.o \
+      src/video/SDL_clipboard.o \
+      src/video/SDL_fillrect.o \
+      src/video/SDL_pixels.o \
+      src/video/SDL_rect.o \
+      src/video/SDL_stretch.o \
+      src/video/SDL_surface.o \
+      src/video/SDL_video.o \
+      src/video/psp/SDL_pspevents.o \
+      src/video/psp/SDL_pspvideo.o \
+      src/video/psp/SDL_pspgl.o \
+      src/video/psp/SDL_pspmouse.o \
+
+INCDIR = ./include
+CFLAGS = -g -O2 -G0 -Wall -D__PSP__ -DHAVE_OPENGL
+CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
+ASFLAGS = $(CFLAGS)
+
+LIBDIR  =
+LIBS = -lGL -lGLU -lglut -lz \
+         -lpspvfpu -lpsphprm -lpspsdk -lpspctrl -lpspumd -lpsprtc -lpsppower -lpspgum -lpspgu -lpspaudiolib -lpspaudio -lpsphttp -lpspssl -lpspwlan \
+         -lpspnet_adhocmatching -lpspnet_adhoc -lpspnet_adhocctl -lm -lpspvram
+
+PSPSDK=$(shell psp-config --pspsdk-path)
+include $(PSPSDK)/lib/build.mak
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.psp	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,17 @@
+SDL port for the Sony PSP contributed by 
+   Captian Lex 
+
+Credit to
+   Marcus R.Brown,Jim Paris,Matthew H for the original SDL 1.2 for PSP
+   Geecko for his PSP GU lib "Glib2d"
+
+Building
+--------
+To build for the PSP, make sure psp-config is in the path and run:
+   make -f Makefile.psp
+
+
+
+To Do
+------
+PSP Screen Keyboard
\ No newline at end of file
--- a/include/SDL_config.h	Sat Mar 16 11:00:04 2013 -0700
+++ b/include/SDL_config.h	Sun Mar 17 20:07:02 2013 +0800
@@ -39,6 +39,8 @@
 #include "SDL_config_android.h"
 #elif defined(__NINTENDODS__)
 #include "SDL_config_nintendods.h"
+#elif defined(__PSP__)
+#include "SDL_config_psp.h"
 #else
 /* This is a minimal configuration just to get SDL running on new platforms */
 #include "SDL_config_minimal.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SDL_config_psp.h	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,136 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_psp_h
+#define _SDL_config_psp_h
+
+#include "SDL_platform.h"
+
+
+
+#ifdef __GNUC__
+#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1
+#endif
+
+#define HAVE_GCC_ATOMICS	1
+
+#define HAVE_ALLOCA_H		1
+#define HAVE_SYS_TYPES_H	1
+#define HAVE_STDIO_H	1
+#define STDC_HEADERS	1
+#define HAVE_STRING_H	1
+#define HAVE_INTTYPES_H	1
+#define HAVE_STDINT_H	1
+#define HAVE_CTYPE_H	1
+#define HAVE_MATH_H	1
+#define HAVE_SIGNAL_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_STRDUP	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_SSCANF	1
+#define HAVE_SNPRINTF	1
+#define HAVE_VSNPRINTF	1
+#define HAVE_M_PI	1
+#define HAVE_ATAN	1
+#define HAVE_ATAN2	1
+#define HAVE_CEIL	1
+#define HAVE_COPYSIGN	1
+#define HAVE_COS	1
+#define HAVE_COSF	1
+#define HAVE_FABS	1
+#define HAVE_FLOOR	1
+#define HAVE_LOG	1
+#define HAVE_POW	1
+#define HAVE_SCALBN	1
+#define HAVE_SIN	1
+#define HAVE_SINF	1
+#define HAVE_SQRT	1
+#define HAVE_SETJMP	1
+#define HAVE_NANOSLEEP	1
+//#define HAVE_SYSCONF	1
+//#define HAVE_SIGACTION	1
+
+
+/* PSP isn't that sophisticated */
+#define LACKS_SYS_MMAN_H 1
+
+/* Enable the stub thread support (src/thread/psp/\*.c) */
+#define SDL_THREAD_PSP	1
+
+/* Enable the stub timer support (src/timer/psp/\*.c) */
+#define SDL_TIMERS_PSP	1
+
+/* Enable the stub joystick driver (src/joystick/psp/\*.c) */
+#define SDL_JOYSTICK_PSP		1
+
+/* Enable the stub audio driver (src/audio/psp/\*.c) */
+#define SDL_AUDIO_DRIVER_PSP	1
+
+/* PSP video dirver */
+#define SDL_VIDEO_DRIVER_PSP   1
+
+/* PSP render dirver */
+#define SDL_VIDEO_RENDER_PSP   1
+
+#define SDL_POWER_PSP          1
+
+/* PSP doesn't have haptic device (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DISABLED	   1
+
+/* PSP can't load shared object (src/loadso/dummy/\*.c) */
+#define SDL_LOADSO_DISABLED	   1
+
+
+#endif /* _SDL_config_minimal_h */
--- a/include/SDL_platform.h	Sat Mar 16 11:00:04 2013 -0700
+++ b/include/SDL_platform.h	Sun Mar 17 20:07:02 2013 +0800
@@ -124,6 +124,10 @@
 #define __NINTENDODS__	1
 #endif
 
+#if defined(__PSP__)
+#undef __PLAYSTATIONPORTABLE__
+#define __PLAYSTATIONPORTABLE__	1
+#endif
 
 #include "begin_code.h"
 /* Set up for C function definitions, even when using C++ */
--- a/include/SDL_test_common.h	Sat Mar 16 11:00:04 2013 -0700
+++ b/include/SDL_test_common.h	Sun Mar 17 20:07:02 2013 +0800
@@ -37,6 +37,9 @@
 #ifdef __NDS__
 #define DEFAULT_WINDOW_WIDTH  256
 #define DEFAULT_WINDOW_HEIGHT (2*192)
+#elif defined(__PSP__)
+#define DEFAULT_WINDOW_WIDTH  480
+#define DEFAULT_WINDOW_HEIGHT 272
 #else
 #define DEFAULT_WINDOW_WIDTH  640
 #define DEFAULT_WINDOW_HEIGHT 480
--- a/src/SDL.c	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/SDL.c	Sun Mar 17 20:07:02 2013 +0800
@@ -408,6 +408,8 @@
     return "Windows";
 #elif __IPHONEOS__
     return "iPhone OS";
+#elif __PSP__
+    return "PlayStation Portable";
 #else
     return "Unknown (see SDL_platform.h)";
 #endif
--- a/src/SDL_log.c	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/SDL_log.c	Sun Mar 17 20:07:02 2013 +0800
@@ -327,6 +327,20 @@
             return;
         }
     }
+#elif defined(__PSP__)
+//Simple Log System for PSP
+	{
+		unsigned int length;
+		char*		 output;
+		FILE*		 pFile;
+		length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
+        output = SDL_stack_alloc(char, length);
+		SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
+		pFile = fopen ("SDL_Log.txt", "a");
+		fwrite (output, strlen (output), 1, pFile);
+		SDL_stack_free(output);
+		fclose (pFile);
+	}
 #endif
 #if HAVE_STDIO_H
     fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
--- a/src/audio/SDL_audio.c	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/audio/SDL_audio.c	Sun Mar 17 20:07:02 2013 +0800
@@ -66,7 +66,7 @@
 extern AudioBootStrap NDSAUD_bootstrap;
 extern AudioBootStrap FUSIONSOUND_bootstrap;
 extern AudioBootStrap ANDROIDAUD_bootstrap;
-
+extern AudioBootStrap PSPAUD_bootstrap;
 
 /* Available audio drivers */
 static const AudioBootStrap *const bootstrap[] = {
@@ -130,6 +130,9 @@
 #if SDL_AUDIO_DRIVER_ANDROID
     &ANDROIDAUD_bootstrap,
 #endif
+#if SDL_AUDIO_DRIVER_PSP
+    &PSPAUD_bootstrap,
+#endif
     NULL
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audio/psp/SDL_pspaudio.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,199 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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 <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_audiomem.h"
+#include "../SDL_audio_c.h"
+#include "../SDL_audiodev_c.h"
+#include "../SDL_sysaudio.h"
+#include "SDL_pspaudio.h"
+
+#include <pspaudio.h>
+#include <pspthreadman.h>
+
+/* The tag name used by PSP audio */
+#define PSPAUD_DRIVER_NAME         "psp"
+
+static int
+PSPAUD_OpenDevice(_THIS, const char *devname, int iscapture)
+{
+	int format, mixlen, i;
+    this->hidden = (struct SDL_PrivateAudioData *)
+        SDL_malloc(sizeof(*this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+	switch (this->spec.format & 0xff) {
+		case 8:
+		case 16:
+			this->spec.format = AUDIO_S16LSB;
+			break;
+		default:
+			SDL_SetError("Unsupported audio format");
+			return 0;
+	}
+
+	/* The sample count must be a multiple of 64. */
+	this->spec.samples = PSP_AUDIO_SAMPLE_ALIGN(this->spec.samples);
+	this->spec.freq = 44100;
+
+	/* 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) {
+		SDL_SetError("Couldn't allocate mixing buffer");
+		return 0;
+	}
+
+	/* Setup the hardware channel. */
+	if (this->spec.channels == 1) {
+		format = PSP_AUDIO_FORMAT_MONO;
+	} else {
+		format = PSP_AUDIO_FORMAT_STEREO;
+	}
+	this->hidden->channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, this->spec.samples, format);
+	if (this->hidden->channel < 0) {
+		SDL_SetError("Couldn't reserve hardware channel");
+		free(this->hidden->rawbuf);
+		this->hidden->rawbuf = NULL;
+		return 0;
+	}
+
+	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 1;
+}
+
+static void PSPAUD_PlayDevice(_THIS)
+{
+	Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
+
+	if (this->spec.channels == 1) {
+		sceAudioOutputBlocking(this->hidden->channel, PSP_AUDIO_VOLUME_MAX, mixbuf);
+	} else {
+		sceAudioOutputPannedBlocking(this->hidden->channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, 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 PSPAUD_WaitDevice(_THIS)
+{
+	/* Because we block when sending audio, there's no need for this function to do anything. */
+}
+static Uint8 *PSPAUD_GetDeviceBuf(_THIS)
+{
+	return this->hidden->mixbufs[this->hidden->next_buffer];
+}
+
+static void PSPAUD_CloseDevice(_THIS)
+{
+	if (this->hidden->channel >= 0) {
+		sceAudioChRelease(this->hidden->channel);
+		this->hidden->channel = -1;
+	}
+
+	if (this->hidden->rawbuf != NULL) {
+		free(this->hidden->rawbuf);
+		this->hidden->rawbuf = NULL;
+	}
+}
+static void PSPAUD_ThreadInit(_THIS)
+{
+	/* 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);
+	}
+}
+
+
+static int
+PSPAUD_Init(SDL_AudioDriverImpl * impl)
+{
+
+    // Set the function pointers 
+    impl->OpenDevice = PSPAUD_OpenDevice;
+    impl->PlayDevice = PSPAUD_PlayDevice;
+    impl->WaitDevice = PSPAUD_WaitDevice;
+    impl->GetDeviceBuf = PSPAUD_GetDeviceBuf;   
+    impl->WaitDone = PSPAUD_WaitDevice;
+    impl->CloseDevice = PSPAUD_CloseDevice;
+    impl->ThreadInit = PSPAUD_ThreadInit;
+    
+    //PSP 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 PSPAUD_bootstrap = {
+    "psp", "PSP audio driver", PSPAUD_Init, 0
+};
+
+ /* SDL_AUDI*/
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/audio/psp/SDL_pspaudio.h	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,45 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_pspaudio_h
+#define _SDL_pspaudio_h
+
+#include "../SDL_sysaudio.h"
+
+/* Hidden "this" pointer for the video 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_pspaudio_h */
+/* vim: ts=4 sw=4
+ */
--- a/src/events/SDL_gesture.c	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/events/SDL_gesture.c	Sun Mar 17 20:07:02 2013 +0800
@@ -27,7 +27,10 @@
 #include "SDL_events_c.h"
 #include "SDL_gesture_c.h"
 
+#if !defined(__PSP__)
 #include <memory.h>
+#endif
+
 #include <string.h>
 #include <stdio.h>
 #include <math.h>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/joystick/psp/SDL_sysjoystick.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,276 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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.
+*/
+
+/* This is the system specific header for the SDL joystick API */
+#include <pspctrl.h>
+#include <pspkernel.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 pad = { .Lx = 0, .Ly = 0, .Buttons = 0 };
+static SDL_sem *pad_sem = NULL;
+static SDL_Thread *thread = NULL;
+static int running = 0;
+static const enum PspCtrlButtons button_map[] = {
+	PSP_CTRL_TRIANGLE, PSP_CTRL_CIRCLE, PSP_CTRL_CROSS, PSP_CTRL_SQUARE,
+	PSP_CTRL_LTRIGGER, PSP_CTRL_RTRIGGER,
+	PSP_CTRL_DOWN, PSP_CTRL_LEFT, PSP_CTRL_UP, PSP_CTRL_RIGHT,
+	PSP_CTRL_SELECT, PSP_CTRL_START, PSP_CTRL_HOME, PSP_CTRL_HOLD };
+static int analog_map[256];  /* Map analog inputs to -32768 -> 32767 */
+
+typedef struct
+{
+  int x;
+  int y;
+} point;
+
+// 4 points define the bezier-curve.  
+static point a = { 0, 0 };
+static point b = { 50, 0  };
+static point c = { 78, 32767 };
+static point d = { 128, 32767 };
+
+// simple linear interpolation between two points
+static __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;
+}
+
+/*
+ * Collect pad data about once per frame
+ */
+int JoystickUpdate(void *data)
+{
+	while (running) {
+		SDL_SemWait(pad_sem);
+		sceCtrlPeekBufferPositive(&pad, 1); 
+		SDL_SemPost(pad_sem);
+		/* Delay 1/60th of a second */
+		sceKernelDelayThread(1000000 / 60);  
+	}
+	return 0;
+}
+
+
+
+/* Function to scan the system for joysticks.
+ * This function should set SDL_numjoysticks to the number of available
+ * 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;
+
+//	SDL_numjoysticks = 1;
+
+	/* Setup input */
+	sceCtrlSetSamplingCycle(0);
+	sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
+
+	/* Start thread to read data */
+	if((pad_sem =  SDL_CreateSemaphore(1)) == NULL) {
+		SDL_SetError("Can't create input semaphore\n");
+		return -1;
+	}
+	running = 1;
+	if((thread = SDL_CreateThread(JoystickUpdate, "JoySitckThread",NULL)) == NULL) {
+		SDL_SetError("Can't create input thread\n");
+		return -1;
+	}
+
+	/* 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];
+	}
+
+	return 1;
+}
+
+int SDL_SYS_NumJoysticks()
+{
+    return 1;
+}
+
+void SDL_SYS_JoystickDetect()
+{
+}
+
+SDL_bool SDL_SYS_JoystickNeedsPolling()
+{
+    return SDL_FALSE;
+}
+
+/* Function to get the device-dependent name of a joystick */
+const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
+{
+    return "PSP builtin joypad";
+}
+
+/* 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 "PSP 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 index field of the joystick.
+   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 = 14;
+	joystick->naxes = 2;
+	joystick->nhats = 0;
+
+	return 0;
+}
+
+/* Function to determine is 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;
+	enum PspCtrlButtons buttons;
+	enum PspCtrlButtons changed;
+	unsigned char x, y;
+	static enum PspCtrlButtons old_buttons = 0;
+	static unsigned char old_x = 0, old_y = 0;
+
+	SDL_SemWait(pad_sem);
+	buttons = pad.Buttons;
+	x = pad.Lx;
+	y = pad.Ly;
+	SDL_SemPost(pad_sem);
+
+	/* Axes */
+	if(old_x != x) {
+		SDL_PrivateJoystickAxis(joystick, 0, analog_map[x]);
+		old_x = x;
+	}
+	if(old_y != y) {
+		SDL_PrivateJoystickAxis(joystick, 1, analog_map[y]);
+		old_y = y;
+	}
+
+	/* Buttons */
+	changed = old_buttons ^ buttons;
+	old_buttons = 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);
+			}
+		}
+	}
+
+	sceKernelDelayThread(0);
+}
+
+/* Function to close a joystick after use */
+void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
+{
+	/* Do nothing. */
+}
+
+/* Function to perform any system-specific joystick related cleanup */
+void SDL_SYS_JoystickQuit(void)
+{
+	/* Cleanup Threads and Semaphore. */
+	running = 0;
+	SDL_WaitThread(thread, NULL);
+	SDL_DestroySemaphore(pad_sem);
+}
+
+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_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
+    return guid;
+}
+
+/* vim: ts=4 sw=4
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/psp/SDL_psp_main.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,80 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_main.h"
+#include <pspkernel.h>
+#include <pspdebug.h>
+#include <pspsdk.h>
+#include <pspthreadman.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* If application's main() is redefined as SDL_main, and libSDLmain is
+   linked, then this file will create the standard exit callback,
+   define the PSP_MODULE_INFO macro, and exit back to the browser when
+   the program is finished. 
+
+   You can still override other parameters in your own code if you
+   desire, such as PSP_HEAP_SIZE_KB, PSP_MAIN_THREAD_ATTR,
+   PSP_MAIN_THREAD_STACK_SIZE, etc.
+*/
+
+extern int SDL_main(int argc, char *argv[]);
+
+PSP_MODULE_INFO("SDL App", 0, 1, 1);
+
+int sdl_psp_exit_callback(int arg1, int arg2, void *common)
+{
+	exit(0);
+	return 0;
+}
+
+int sdl_psp_callback_thread(SceSize args, void *argp)
+{
+	int cbid;
+	cbid = sceKernelCreateCallback("Exit Callback", 
+				       sdl_psp_exit_callback, NULL);
+	sceKernelRegisterExitCallback(cbid);
+	sceKernelSleepThreadCB();
+	return 0;
+}
+
+int sdl_psp_setup_callbacks(void)
+{
+	int thid = 0;
+	thid = sceKernelCreateThread("update_thread", 
+				     sdl_psp_callback_thread, 0x11, 0xFA0, 0, 0);
+	if(thid >= 0)
+		sceKernelStartThread(thid, 0, 0);
+	return thid;
+}
+
+int main(int argc, char *argv[])
+{
+	pspDebugScreenInit();
+	sdl_psp_setup_callbacks();
+
+	/* Register sceKernelExitGame() to be called when we exit */
+	atexit(sceKernelExitGame);
+
+	(void)SDL_main(argc, argv);
+	return 0;
+}
--- a/src/power/SDL_power.c	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/power/SDL_power.c	Sun Mar 17 20:07:02 2013 +0800
@@ -37,6 +37,7 @@
 SDL_bool SDL_GetPowerInfo_NintendoDS(SDL_PowerState *, int *, int *);
 SDL_bool SDL_GetPowerInfo_UIKit(SDL_PowerState *, int *, int *);
 SDL_bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *);
+SDL_bool SDL_GetPowerInfo_PSP(SDL_PowerState *, int *, int *);
 
 #ifndef SDL_POWER_DISABLED
 #ifdef SDL_POWER_HARDWIRED
@@ -77,6 +78,10 @@
 #ifdef SDL_POWER_ANDROID        /* handles Android. */
     SDL_GetPowerInfo_Android,
 #endif
+#ifdef SDL_POWER_PSP        /* handles PSP. */
+    SDL_GetPowerInfo_PSP,
+#endif
+
 #ifdef SDL_POWER_HARDWIRED
     SDL_GetPowerInfo_Hardwired,
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/power/psp/SDL_syspower.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,68 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_config.h"
+
+#ifndef SDL_POWER_DISABLED
+#if SDL_POWER_PSP
+
+#include "SDL_power.h"
+#include <psppower.h> 
+
+
+SDL_bool
+SDL_GetPowerInfo_PSP(SDL_PowerState * state, int *seconds,
+                            int *percent)
+{
+    int battery = scePowerIsBatteryExist();
+    int plugged = scePowerIsPowerOnline();
+	int charging = scePowerIsBatteryCharging();
+
+    *state = SDL_POWERSTATE_UNKNOWN;
+	*seconds = -1;
+	*percent = -1;
+	
+	if (!battery) {
+		*state = SDL_POWERSTATE_NO_BATTERY;
+		*seconds = -1;
+    	*percent = -1;
+    } else if (charging) {
+        *state = SDL_POWERSTATE_CHARGING;
+    	*percent = scePowerGetBatteryLifePercent();
+		*seconds = scePowerGetBatteryLifeTime()*60;
+    } else if (plugged) {
+        *state = SDL_POWERSTATE_CHARGED;
+    	*percent = scePowerGetBatteryLifePercent();
+		*seconds = scePowerGetBatteryLifeTime()*60;        
+    } else {
+        *state = SDL_POWERSTATE_ON_BATTERY;
+    	*percent = scePowerGetBatteryLifePercent();
+		*seconds = scePowerGetBatteryLifeTime()*60;
+    }
+
+	
+    return SDL_TRUE;            /* always the definitive answer on PSP. */
+}
+
+#endif /* SDL_POWER_PSP */
+#endif /* SDL_POWER_DISABLED */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/render/SDL_render.c	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/render/SDL_render.c	Sun Mar 17 20:07:02 2013 +0800
@@ -64,6 +64,9 @@
 #if SDL_VIDEO_RENDER_NDS
     &NDS_RenderDriver,
 #endif
+#if SDL_VIDEO_RENDER_PSP
+    &PSP_RenderDriver,
+#endif
     &SW_RenderDriver
 #endif /* !SDL_RENDER_DISABLED */
 };
--- a/src/render/SDL_sysrender.h	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/render/SDL_sysrender.h	Sun Mar 17 20:07:02 2013 +0800
@@ -176,6 +176,9 @@
 #if SDL_VIDEO_RENDER_NDS
 extern SDL_RenderDriver NDS_RenderDriver;
 #endif
+#if SDL_VIDEO_RENDER_PSP
+extern SDL_RenderDriver PSP_RenderDriver;
+#endif
 extern SDL_RenderDriver SW_RenderDriver;
 
 #endif /* !SDL_RENDER_DISABLED */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/render/psp/SDL_render_psp.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,1024 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_config.h"
+
+#if SDL_VIDEO_RENDER_PSP 
+
+#include "SDL_hints.h"
+#include "../SDL_sysrender.h"
+
+#include <pspkernel.h>
+#include <pspdisplay.h>
+#include <pspgu.h>
+#include <pspgum.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <pspge.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <vram.h>
+
+
+
+
+/* PSP renderer implementation, based on the PGE  */
+
+
+extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
+
+
+static SDL_Renderer *PSP_CreateRenderer(SDL_Window * window, Uint32 flags);
+static void PSP_WindowEvent(SDL_Renderer * renderer,
+                             const SDL_WindowEvent *event);
+static int PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+                              const SDL_Rect * rect, const void *pixels,
+                              int pitch);
+static int PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+                            const SDL_Rect * rect, void **pixels, int *pitch);
+static void PSP_UnlockTexture(SDL_Renderer * renderer,
+                               SDL_Texture * texture);
+static int PSP_SetRenderTarget(SDL_Renderer * renderer,
+                                 SDL_Texture * texture);
+static int PSP_UpdateViewport(SDL_Renderer * renderer);
+static int PSP_RenderClear(SDL_Renderer * renderer);
+static int PSP_RenderDrawPoints(SDL_Renderer * renderer,
+                                 const SDL_FPoint * points, int count);
+static int PSP_RenderDrawLines(SDL_Renderer * renderer,
+                                const SDL_FPoint * points, int count);
+static int PSP_RenderFillRects(SDL_Renderer * renderer,
+                                const SDL_FRect * rects, int count);
+static int PSP_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+                           const SDL_Rect * srcrect,
+                           const SDL_FRect * dstrect);
+static int PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+                    Uint32 pixel_format, void * pixels, int pitch);
+static int PSP_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
+                         const SDL_Rect * srcrect, const SDL_FRect * dstrect,
+                         const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
+static void PSP_RenderPresent(SDL_Renderer * renderer);
+static void PSP_DestroyTexture(SDL_Renderer * renderer,
+                                SDL_Texture * texture);
+static void PSP_DestroyRenderer(SDL_Renderer * renderer);
+
+/*
+SDL_RenderDriver PSP_RenderDriver = {
+    PSP_CreateRenderer,
+    {
+     "PSP",
+     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
+     1,
+     {SDL_PIXELFORMAT_ABGR8888},
+     0,
+     0}
+};
+*/
+SDL_RenderDriver PSP_RenderDriver = {
+	.CreateRenderer = PSP_CreateRenderer,
+    .info = {
+		.name = "PSP",
+		.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 = 512,
+		.max_texture_height = 512,
+     }
+};
+
+#define PSP_SCREEN_WIDTH	480
+#define PSP_SCREEN_HEIGHT	272
+
+#define PSP_FRAME_BUFFER_WIDTH	512
+#define PSP_FRAME_BUFFER_SIZE	(PSP_FRAME_BUFFER_WIDTH*PSP_SCREEN_HEIGHT)
+
+static unsigned int __attribute__((aligned(16))) DisplayList[262144];
+
+																						 	
+#define COL5650(r,g,b,a)	((r>>3) | ((g>>2)<<5) | ((b>>3)<<11))
+#define COL5551(r,g,b,a)	((r>>3) | ((g>>3)<<5) | ((b>>3)<<10) | (a>0?0x7000:0))
+#define COL4444(r,g,b,a)	((r>>4) | ((g>>4)<<4) | ((b>>4)<<8) | ((a>>4)<<12))
+#define COL8888(r,g,b,a)	((r) | ((g)<<8) | ((b)<<16) | ((a)<<24))
+	
+
+typedef struct
+{
+	void* 			frontbuffer ;
+	void* 			backbuffer ;
+	SDL_bool 		initialized ;
+	SDL_bool 		displayListAvail ;
+	unsigned int 	psm ;
+	unsigned int 	bpp ;
+	
+	SDL_bool    	vsync;	
+	unsigned int 	currentColor;
+	int				currentBlendMode;
+		
+} PSP_RenderData;
+
+
+typedef struct
+{
+	void				*data;								/**< Image data. */
+	unsigned int		size;								/**< Size of data in bytes. */
+	unsigned int		width;								/**< Image width. */
+	unsigned int		height;								/**< Image height. */
+	unsigned int		textureWidth;						/**< Texture width (power of two). */
+	unsigned int		textureHeight;						/**< Texture height (power of two). */
+	unsigned int		bits;								/**< Image bits per pixel. */
+	unsigned int		format;								/**< Image format - one of ::pgePixelFormat. */
+	unsigned int		pitch;										
+	SDL_bool			swizzled;							/**< Is image swizzled. */
+
+} PSP_TextureData;
+
+typedef struct
+{	
+	float	x, y, z;
+} VertV;
+
+
+typedef struct
+{
+	float	u, v;
+	float	x, y, z;
+	
+} VertTV;
+
+
+// Return next power of 2
+static int 
+TextureNextPow2(unsigned int w)
+{
+	if(w == 0)
+		return 0;
+
+	unsigned int n = 2;
+
+	while(w > n)
+		n <<= 1;
+
+	return n;
+}
+
+
+static int
+GetScaleQuality(void)
+{
+    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
+
+    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
+        return GU_NEAREST; // GU_NEAREST good for tile-map
+    } else {
+        return GU_LINEAR; // GU_LINEAR good for scaling
+    }
+}
+
+static int
+PixelFormatToPSPFMT(Uint32 format)
+{
+    switch (format) {
+    case SDL_PIXELFORMAT_BGR565:
+        return GU_PSM_5650;
+    case SDL_PIXELFORMAT_ABGR1555:
+        return GU_PSM_5551;
+    case SDL_PIXELFORMAT_ABGR4444:
+        return GU_PSM_4444;
+    case SDL_PIXELFORMAT_ABGR8888:
+        return GU_PSM_8888;        
+    default:    	
+        return GU_PSM_8888;
+    }
+}
+
+void 
+StartDrawing(SDL_Renderer * renderer)
+{	
+	PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
+	if(data->displayListAvail)
+		return;
+
+	sceGuStart(GU_DIRECT, DisplayList);
+	data->displayListAvail = SDL_TRUE;
+}
+
+
+int 
+TextureSwizzle(PSP_TextureData *psp_texture)
+{
+	if(psp_texture->swizzled)
+		return 1;
+	
+	int bytewidth = psp_texture->textureWidth*(psp_texture->bits>>3);
+	int height = psp_texture->size / bytewidth;
+
+	int rowblocks = (bytewidth>>4);
+	int rowblocksadd = (rowblocks-1)<<7;
+	unsigned int blockaddress = 0;
+	unsigned int *src = (unsigned int*) psp_texture->data;
+
+	unsigned char *data = NULL;	
+	data = malloc(psp_texture->size);
+
+	int j;
+
+	for(j = 0; j < height; j++, blockaddress += 16)
+	{
+		unsigned int *block;
+
+		block = (unsigned int*)&data[blockaddress];
+
+		int i;
+
+		for(i = 0; i < rowblocks; i++)
+		{
+			*block++ = *src++;
+			*block++ = *src++;
+			*block++ = *src++;
+			*block++ = *src++;
+			block += 28;
+		}
+
+		if((j & 0x7) == 0x7)
+			blockaddress += rowblocksadd;
+	}
+
+	free(psp_texture->data);	
+	psp_texture->data = data;
+	psp_texture->swizzled = SDL_TRUE;
+
+	return 1;
+}
+int TextureUnswizzle(PSP_TextureData *psp_texture)
+{
+	if(!psp_texture->swizzled)
+		return 1;
+		
+	int blockx, blocky;
+	
+	int bytewidth = psp_texture->textureWidth*(psp_texture->bits>>3);
+	int height = psp_texture->size / bytewidth;
+	
+	int widthblocks = bytewidth/16;
+	int heightblocks = height/8;
+	
+	int dstpitch = (bytewidth - 16)/4;
+	int dstrow = bytewidth * 8;
+
+	unsigned int *src = (unsigned int*) psp_texture->data;
+
+	unsigned char *data = NULL;
+	
+	data = malloc(psp_texture->size);
+
+	if(!data)
+		return 0;
+		
+	sceKernelDcacheWritebackAll();
+
+	int j;
+	
+	unsigned char *ydst = (unsigned char *)data;
+
+	for(blocky = 0; blocky < heightblocks; ++blocky)
+	{
+		unsigned char *xdst = ydst;
+		
+		for(blockx = 0; blockx < widthblocks; ++blockx)
+		{
+			unsigned int *block;
+
+			block = (unsigned int*)xdst;
+
+			for(j = 0; j < 8; ++j)
+			{
+				*(block++) = *(src++);
+				*(block++) = *(src++);
+				*(block++) = *(src++);
+				*(block++) = *(src++);
+				block += dstpitch;
+			}
+
+			xdst += 16;
+		}
+		
+		ydst += dstrow;
+	}
+
+	free(psp_texture->data);
+	
+	psp_texture->data = data;
+
+	psp_texture->swizzled = SDL_FALSE;
+
+	return 1;
+}
+
+SDL_Renderer *
+PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+
+    SDL_Renderer *renderer;
+    PSP_RenderData *data;
+		int pixelformat;
+    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+    if (!renderer) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
+    data = (PSP_RenderData *) SDL_calloc(1, sizeof(*data));
+    if (!data) {
+        PSP_DestroyRenderer(renderer);
+        SDL_OutOfMemory();
+        return NULL;
+    }
+    
+		
+    renderer->WindowEvent = PSP_WindowEvent;
+    renderer->CreateTexture = PSP_CreateTexture;
+    renderer->UpdateTexture = PSP_UpdateTexture;
+    renderer->LockTexture = PSP_LockTexture;
+    renderer->UnlockTexture = PSP_UnlockTexture;
+    renderer->SetRenderTarget = PSP_SetRenderTarget;
+    renderer->UpdateViewport = PSP_UpdateViewport;
+    renderer->RenderClear = PSP_RenderClear;
+    renderer->RenderDrawPoints = PSP_RenderDrawPoints;
+    renderer->RenderDrawLines = PSP_RenderDrawLines;
+    renderer->RenderFillRects = PSP_RenderFillRects;
+    renderer->RenderCopy = PSP_RenderCopy;
+    renderer->RenderReadPixels = PSP_RenderReadPixels;
+    renderer->RenderCopyEx = PSP_RenderCopyEx;
+    renderer->RenderPresent = PSP_RenderPresent;
+    renderer->DestroyTexture = PSP_DestroyTexture;
+    renderer->DestroyRenderer = PSP_DestroyRenderer;
+    renderer->info = PSP_RenderDriver.info;
+    renderer->info.flags = SDL_RENDERER_ACCELERATED;
+    renderer->driverdata = data;
+    renderer->window = window;
+    
+	if (data->initialized != SDL_FALSE)
+		return 0;
+	data->initialized = SDL_TRUE;
+	
+    if (flags & SDL_RENDERER_PRESENTVSYNC) {
+        data->vsync = SDL_TRUE;
+    } else {
+        data->vsync = SDL_FALSE;
+    }
+    	
+	pixelformat=PixelFormatToPSPFMT(SDL_GetWindowPixelFormat(window));
+	switch(pixelformat)
+	{
+		case GU_PSM_4444:
+		case GU_PSM_5650:
+		case GU_PSM_5551:
+			data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<1);
+			data->backbuffer =  (unsigned int *)(0);
+			data->bpp = 2;
+			data->psm = pixelformat;
+			break;
+		default:
+			data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<2);
+			data->backbuffer =  (unsigned int *)(0);
+			data->bpp = 4;
+			data->psm = GU_PSM_8888;
+			break;
+	}
+	
+	sceGuInit();
+	// setup GU
+	sceGuStart(GU_DIRECT, DisplayList);
+	sceGuDrawBuffer(data->psm, data->frontbuffer, PSP_FRAME_BUFFER_WIDTH);
+	sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, data->backbuffer, PSP_FRAME_BUFFER_WIDTH);
+
+
+	sceGuOffset(2048 - (PSP_SCREEN_WIDTH>>1), 2048 - (PSP_SCREEN_HEIGHT>>1));
+	sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
+
+    data->frontbuffer = vabsptr(data->frontbuffer);
+    data->backbuffer = vabsptr(data->backbuffer);
+    
+	// Scissoring
+	sceGuScissor(0, 0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
+	sceGuEnable(GU_SCISSOR_TEST);
+
+	// Backface culling
+	sceGuFrontFace(GU_CCW);
+	sceGuEnable(GU_CULL_FACE);
+	
+	// Texturing
+	sceGuEnable(GU_TEXTURE_2D);
+	sceGuShadeModel(GU_SMOOTH);
+	sceGuTexWrap(GU_REPEAT, GU_REPEAT);
+	
+	// Blending
+	sceGuEnable(GU_BLEND);
+	sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
+
+	sceGuTexFilter(GU_LINEAR,GU_LINEAR);
+	
+	sceGuFinish();
+	sceGuSync(0,0);	
+	sceDisplayWaitVblankStartCB();
+	sceGuDisplay(GU_TRUE);	
+		
+    return renderer;
+}
+
+static void
+PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
+{
+
+}
+
+
+static int
+PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+//		PSP_RenderData *renderdata = (PSP_RenderData *) renderer->driverdata;
+	PSP_TextureData* psp_texture = (PSP_TextureData*) SDL_calloc(1, sizeof(*psp_texture));;
+	
+	if(!psp_texture)
+		return -1;
+
+	psp_texture->swizzled = SDL_FALSE;
+	psp_texture->width = texture->w;
+	psp_texture->height = texture->h;
+	psp_texture->textureHeight = TextureNextPow2(texture->h);
+	psp_texture->textureWidth = TextureNextPow2(texture->w);
+	psp_texture->format = PixelFormatToPSPFMT(texture->format);
+
+	switch(psp_texture->format)
+	{
+		case GU_PSM_5650:
+		case GU_PSM_5551:
+		case GU_PSM_4444:
+			psp_texture->bits = 16;
+			break;
+			
+		case GU_PSM_8888:
+			psp_texture->bits = 32;
+			break;
+			
+		default:
+			return -1;
+	}
+
+	psp_texture->pitch = psp_texture->textureWidth * SDL_BYTESPERPIXEL(texture->format);	
+	psp_texture->size = psp_texture->textureHeight*psp_texture->pitch;
+	psp_texture->data = SDL_calloc(1, psp_texture->size);
+	
+	if(!psp_texture->data)
+	{
+		SDL_OutOfMemory();
+		SDL_free(psp_texture);
+		return -1;
+	}
+    texture->driverdata = psp_texture;
+    
+    return 0;
+}
+
+
+void 
+TextureActivate(SDL_Texture * texture)
+{		
+	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
+	int scaleMode = GetScaleQuality();
+	
+	// Swizzling is useless with small textures.
+    if (texture->w >= 16 || texture->h >= 16)
+    {
+		TextureSwizzle(psp_texture);	
+    }
+    
+	sceGuEnable(GU_TEXTURE_2D);
+	sceGuTexWrap(GU_REPEAT, GU_REPEAT);
+	sceGuTexMode(psp_texture->format, 0, 0, psp_texture->swizzled);
+	sceGuTexFilter(scaleMode, scaleMode); // GU_NEAREST good for tile-map
+										  // GU_LINEAR good for scaling	
+	sceGuTexImage(0, psp_texture->textureWidth, psp_texture->textureHeight, psp_texture->textureWidth, psp_texture->data);
+	sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
+}
+
+
+static int
+PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+                   const SDL_Rect * rect, const void *pixels, int pitch)
+{
+//	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
+    const Uint8 *src;
+    Uint8 *dst;
+    int row, length,dpitch;
+    src = pixels;
+    
+    PSP_LockTexture(renderer, texture,rect,(void **)&dst, &dpitch);
+    length = rect->w * SDL_BYTESPERPIXEL(texture->format);
+    if (length == pitch && length == dpitch) {
+        SDL_memcpy(dst, src, length*rect->h);
+    } else {
+        for (row = 0; row < rect->h; ++row) {
+            SDL_memcpy(dst, src, length);
+            src += pitch;
+            dst += dpitch;
+        }
+    }
+    
+	sceKernelDcacheWritebackAll();
+    return 0;
+}
+
+static int
+PSP_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
+                 const SDL_Rect * rect, void **pixels, int *pitch)
+{
+	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
+
+    *pixels =
+        (void *) ((Uint8 *) psp_texture->data + rect->y * psp_texture->pitch +
+                  rect->x * SDL_BYTESPERPIXEL(texture->format));
+    *pitch = psp_texture->pitch;
+    return 0;
+}
+
+static void
+PSP_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
+    SDL_Rect rect;
+
+    /* We do whole texture updates, at least for now */
+    rect.x = 0;
+    rect.y = 0;
+    rect.w = texture->w;
+    rect.h = texture->h;
+    PSP_UpdateTexture(renderer, texture, &rect, psp_texture->data, psp_texture->pitch);
+}
+
+static int
+PSP_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+
+    return 0;
+}
+
+static int
+PSP_UpdateViewport(SDL_Renderer * renderer)
+{
+
+    return 0;
+}
+
+
+static void
+PSP_SetBlendMode(SDL_Renderer * renderer, int blendMode)
+{
+	PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;				
+    if (blendMode != data-> currentBlendMode) {
+        switch (blendMode) {
+        case SDL_BLENDMODE_NONE:
+        		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);        
+				sceGuDisable(GU_BLEND);
+            break;
+        case SDL_BLENDMODE_BLEND:
+        		sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
+				sceGuEnable(GU_BLEND);
+				sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
+            break;
+        case SDL_BLENDMODE_ADD:
+        		sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
+				sceGuEnable(GU_BLEND);
+				sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, 0x00FFFFFF );
+            break;
+        case SDL_BLENDMODE_MOD:
+        		sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
+				sceGuEnable(GU_BLEND);
+				sceGuBlendFunc( GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);
+            break;
+        }
+        data->currentBlendMode = blendMode;
+    }
+}
+
+
+
+static int
+PSP_RenderClear(SDL_Renderer * renderer)
+{					
+		//start list
+	StartDrawing(renderer);
+	int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;		
+	sceGuClearColor(color);
+	sceGuClearDepth(0);
+	sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT|GU_FAST_CLEAR_BIT);
+
+    return 0;
+}
+
+static int
+PSP_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
+                      int count)
+{
+	int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
+	int i;
+	StartDrawing(renderer);		
+	VertV* vertices = (VertV*)sceGuGetMemory(count*sizeof(VertV)); 
+	
+ 	for (i = 0; i < count; ++i) {
+			vertices[i].x = points[i].x;
+			vertices[i].y = points[i].y;
+			vertices[i].z = 0.0f;
+	}
+	sceGuDisable(GU_TEXTURE_2D);
+	sceGuColor(color);		
+	sceGuShadeModel(GU_FLAT);
+	sceGuDrawArray(GU_POINTS, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, vertices);
+	sceGuShadeModel(GU_SMOOTH);
+	sceGuEnable(GU_TEXTURE_2D);			
+
+    return 0;
+}
+
+static int
+PSP_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
+                     int count)
+{
+	int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
+	int i;
+	StartDrawing(renderer);
+	VertV* vertices = (VertV*)sceGuGetMemory(count*sizeof(VertV)); 
+	
+	for (i = 0; i < count; ++i) {
+			vertices[i].x = points[i].x;
+			vertices[i].y = points[i].y;
+			vertices[i].z = 0.0f;
+	}
+
+	sceGuDisable(GU_TEXTURE_2D);
+	sceGuColor(color);
+	sceGuShadeModel(GU_FLAT);
+	sceGuDrawArray(GU_LINE_STRIP, GU_VERTEX_32BITF|GU_TRANSFORM_2D, count, 0, vertices);
+	sceGuShadeModel(GU_SMOOTH);
+	sceGuEnable(GU_TEXTURE_2D);
+	 
+    return 0;
+}
+
+static int
+PSP_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
+                     int count)
+{
+	int color = renderer->a << 24 | renderer->b << 16 | renderer->g << 8 | renderer->r;
+	int i;	
+	StartDrawing(renderer);
+	
+	for (i = 0; i < count; ++i) {
+    	const SDL_FRect *rect = &rects[i];
+		VertV* vertices = (VertV*)sceGuGetMemory((sizeof(VertV)<<1));
+		vertices[0].x = rect->x;
+		vertices[0].y = rect->y;
+		vertices[0].z = 0.0f;
+
+		vertices[1].x = rect->x + rect->w;
+		vertices[1].y = rect->y + rect->h;
+		vertices[1].z = 0.0f;
+		
+		sceGuDisable(GU_TEXTURE_2D);
+		sceGuColor(color);			
+		sceGuShadeModel(GU_FLAT);
+		sceGuDrawArray(GU_SPRITES, GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
+		sceGuShadeModel(GU_SMOOTH);
+		sceGuEnable(GU_TEXTURE_2D);
+    }
+		
+    return 0;
+}
+
+
+#define PI   3.14159265358979f
+
+#define radToDeg(x) ((x)*180.f/PI)
+#define degToRad(x) ((x)*PI/180.f)
+
+float MathAbs(float x)
+{
+	float result;
+
+	__asm__ volatile (
+		"mtv      %1, S000\n"
+		"vabs.s   S000, S000\n"
+		"mfv      %0, S000\n"
+	: "=r"(result) : "r"(x));
+
+	return result;
+}
+
+void MathSincos(float r, float *s, float *c)
+{
+	__asm__ volatile (
+		"mtv      %2, S002\n"
+		"vcst.s   S003, VFPU_2_PI\n"
+		"vmul.s   S002, S002, S003\n"
+		"vrot.p   C000, S002, [s, c]\n"
+		"mfv      %0, S000\n"
+		"mfv      %1, S001\n"
+	: "=r"(*s), "=r"(*c): "r"(r));
+}
+
+void Swap(float *a, float *b)
+{
+	float n=*a;
+	*a = *b;
+	*b = n;
+}
+
+static int
+PSP_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+                const SDL_Rect * srcrect, const SDL_FRect * dstrect)
+{
+	float x, y, width, height;
+	float u0, v0, u1, v1;
+	unsigned char alpha;
+	
+	x = dstrect->x;
+	y = dstrect->y;
+	width = dstrect->w;
+	height = dstrect->h;
+
+	u0 = srcrect->x;
+	v0 = srcrect->y;
+	u1 = srcrect->x + srcrect->w;
+	v1 = srcrect->y + srcrect->h;
+	
+	alpha = texture->a;
+	
+	StartDrawing(renderer);
+	TextureActivate(texture);
+	PSP_SetBlendMode(renderer, renderer->blendMode);
+	
+	if(alpha != 255)
+	{
+		sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
+		sceGuColor(GU_RGBA(255, 255, 255, alpha));
+	}else{
+		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
+		sceGuColor(0xFFFFFFFF);
+	}
+		
+	if((MathAbs(u1) - MathAbs(u0)) < 64.0f)
+	{
+		VertTV* vertices = (VertTV*)sceGuGetMemory((sizeof(VertTV))<<1);
+
+		vertices[0].u = u0;
+		vertices[0].v = v0;
+		vertices[0].x = x;
+		vertices[0].y = y; 
+		vertices[0].z = 0;
+
+		vertices[1].u = u1;
+		vertices[1].v = v1;
+		vertices[1].x = x + width;
+		vertices[1].y = y + height;
+		vertices[1].z = 0;
+
+		sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
+	}
+	else
+	{
+		float start, end;
+		float curU = u0;
+		float curX = x;
+		float endX = x + width;
+		float slice = 64.0f;
+		float ustep = (u1 - u0)/width * slice;
+	
+		if(ustep < 0.0f)
+			ustep = -ustep;
+
+		for(start = 0, end = width; start < end; start += slice)
+		{
+			VertTV* vertices = (VertTV*)sceGuGetMemory((sizeof(VertTV))<<1);
+
+			float polyWidth = ((curX + slice) > endX) ? (endX - curX) : slice;
+			float sourceWidth = ((curU + ustep) > u1) ? (u1 - curU) : ustep;
+
+			vertices[0].u = curU;
+			vertices[0].v = v0;
+			vertices[0].x = curX;
+			vertices[0].y = y; 
+			vertices[0].z = 0;
+
+			curU += sourceWidth;
+			curX += polyWidth;
+
+			vertices[1].u = curU;
+			vertices[1].v = v1;
+			vertices[1].x = curX;
+			vertices[1].y = (y + height);
+			vertices[1].z = 0;
+
+			sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices);
+		}
+	}
+	
+	if(alpha != 255)
+		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
+    return 0;
+}
+
+static int
+PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
+                    Uint32 pixel_format, void * pixels, int pitch)
+
+{
+		return 0;
+}
+
+
+static int
+PSP_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
+                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
+                const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
+{
+	float x, y, width, height;
+	float u0, v0, u1, v1;
+	unsigned char alpha;
+	float centerx, centery;
+	
+	x = dstrect->x;
+	y = dstrect->y;
+	width = dstrect->w;
+	height = dstrect->h;
+
+	u0 = srcrect->x;
+	v0 = srcrect->y;
+	u1 = srcrect->x + srcrect->w;
+	v1 = srcrect->y + srcrect->h;
+	
+    centerx = center->x;
+    centery = center->y;
+		
+	alpha = texture->a;
+	
+	StartDrawing(renderer);
+	TextureActivate(texture);
+	PSP_SetBlendMode(renderer, renderer->blendMode);
+	
+	if(alpha != 255)
+	{
+		sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
+		sceGuColor(GU_RGBA(255, 255, 255, alpha));
+	}else{
+		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
+		sceGuColor(0xFFFFFFFF);
+	}
+
+//		x += width * 0.5f;
+//		y += height * 0.5f;
+	x += centerx;
+	y += centery;		
+	
+	float c, s;
+	
+	MathSincos(degToRad(angle), &s, &c);
+	
+//		width *= 0.5f;
+//		height *= 0.5f;
+	width  -= centerx;
+	height -= centery;		
+	
+	
+	float cw = c*width;
+	float sw = s*width;
+	float ch = c*height;
+	float sh = s*height;
+
+	VertTV* vertices = (VertTV*)sceGuGetMemory(sizeof(VertTV)<<2);
+
+	vertices[0].u = u0;
+	vertices[0].v = v0;
+	vertices[0].x = x - cw + sh;
+	vertices[0].y = y - sw - ch;
+	vertices[0].z = 0;
+			
+	vertices[1].u = u0;
+	vertices[1].v = v1;
+	vertices[1].x = x - cw - sh;
+	vertices[1].y = y - sw + ch;
+	vertices[1].z = 0;
+	
+	vertices[2].u = u1;
+	vertices[2].v = v1;
+	vertices[2].x = x + cw - sh;
+	vertices[2].y = y + sw + ch;
+	vertices[2].z = 0;
+	
+	vertices[3].u = u1;
+	vertices[3].v = v0;
+	vertices[3].x = x + cw + sh;
+	vertices[3].y = y + sw - ch;
+	vertices[3].z = 0;
+	
+	if (flip & SDL_FLIP_HORIZONTAL) {
+				Swap(&vertices[0].v, &vertices[2].v);
+				Swap(&vertices[1].v, &vertices[3].v);
+	}
+	if (flip & SDL_FLIP_VERTICAL) {
+				Swap(&vertices[0].u, &vertices[2].u);
+				Swap(&vertices[1].u, &vertices[3].u);
+	}  	
+
+	sceGuDrawArray(GU_TRIANGLE_FAN, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices);
+			
+	if(alpha != 255)
+		sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
+    return 0;
+}
+
+static void
+PSP_RenderPresent(SDL_Renderer * renderer)
+{
+    PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
+	if(!data->displayListAvail)
+		return;
+	
+	data->displayListAvail = SDL_FALSE;
+	sceGuFinish();
+	sceGuSync(0,0);
+	
+//	if(data->vsync)
+		sceDisplayWaitVblankStart();
+			
+    data->backbuffer = data->frontbuffer;
+    data->frontbuffer = vabsptr(sceGuSwapBuffers());
+		
+}
+
+static void
+PSP_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+	PSP_RenderData *renderdata = (PSP_RenderData *) renderer->driverdata;
+	PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
+	
+	if (renderdata == 0)
+		return;
+
+	if(psp_texture == 0)
+		return;
+
+	if(psp_texture->data != 0)
+	{
+		free(psp_texture->data);
+	}
+	free(texture);
+	texture->driverdata = NULL;
+}
+
+static void
+PSP_DestroyRenderer(SDL_Renderer * renderer)
+{
+    PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
+    if (data) {
+		if (!data->initialized)
+			return;
+
+		StartDrawing(renderer);
+		
+		sceGuTerm();
+//		vfree(data->backbuffer);
+//		vfree(data->frontbuffer);
+		
+		data->initialized = SDL_FALSE;
+		data->displayListAvail = SDL_FALSE;
+        SDL_free(data);
+    }
+    SDL_free(renderer);
+}
+
+#endif /* SDL_VIDEO_RENDER_PSP */
+
+/* vi: set ts=4 sw=4 expandtab: */
+
--- a/src/thread/SDL_thread_c.h	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/thread/SDL_thread_c.h	Sun Mar 17 20:07:02 2013 +0800
@@ -36,6 +36,8 @@
 #include "windows/SDL_systhread_c.h"
 #elif SDL_THREAD_NDS
 #include "nds/SDL_systhread_c.h"
+#elif SDL_THREAD_PSP
+#include "psp/SDL_systhread_c.h"
 #else
 #error Need thread implementation for this platform
 #include "generic/SDL_systhread_c.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/psp/SDL_syscond.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,223 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_config.h"
+
+/* An implementation of condition variables using semaphores and mutexes */
+/*
+   This implementation borrows heavily from the BeOS condition variable
+   implementation, written by Christopher Tate and Owen Smith.  Thanks!
+ */
+
+#include "SDL_thread.h"
+
+struct SDL_cond
+{
+    SDL_mutex *lock;
+    int waiting;
+    int signals;
+    SDL_sem *wait_sem;
+    SDL_sem *wait_done;
+};
+
+/* Create a condition variable */
+SDL_cond *
+SDL_CreateCond(void)
+{
+    SDL_cond *cond;
+
+    cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
+    if (cond) {
+        cond->lock = SDL_CreateMutex();
+        cond->wait_sem = SDL_CreateSemaphore(0);
+        cond->wait_done = SDL_CreateSemaphore(0);
+        cond->waiting = cond->signals = 0;
+        if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
+            SDL_DestroyCond(cond);
+            cond = NULL;
+        }
+    } else {
+        SDL_OutOfMemory();
+    }
+    return (cond);
+}
+
+/* Destroy a condition variable */
+void
+SDL_DestroyCond(SDL_cond * cond)
+{
+    if (cond) {
+        if (cond->wait_sem) {
+            SDL_DestroySemaphore(cond->wait_sem);
+        }
+        if (cond->wait_done) {
+            SDL_DestroySemaphore(cond->wait_done);
+        }
+        if (cond->lock) {
+            SDL_DestroyMutex(cond->lock);
+        }
+        SDL_free(cond);
+    }
+}
+
+/* Restart one of the threads that are waiting on the condition variable */
+int
+SDL_CondSignal(SDL_cond * cond)
+{
+    if (!cond) {
+        SDL_SetError("Passed a NULL condition variable");
+        return -1;
+    }
+
+    /* If there are waiting threads not already signalled, then
+       signal the condition and wait for the thread to respond.
+     */
+    SDL_LockMutex(cond->lock);
+    if (cond->waiting > cond->signals) {
+        ++cond->signals;
+        SDL_SemPost(cond->wait_sem);
+        SDL_UnlockMutex(cond->lock);
+        SDL_SemWait(cond->wait_done);
+    } else {
+        SDL_UnlockMutex(cond->lock);
+    }
+
+    return 0;
+}
+
+/* Restart all threads that are waiting on the condition variable */
+int
+SDL_CondBroadcast(SDL_cond * cond)
+{
+    if (!cond) {
+        SDL_SetError("Passed a NULL condition variable");
+        return -1;
+    }
+
+    /* If there are waiting threads not already signalled, then
+       signal the condition and wait for the thread to respond.
+     */
+    SDL_LockMutex(cond->lock);
+    if (cond->waiting > cond->signals) {
+        int i, num_waiting;
+
+        num_waiting = (cond->waiting - cond->signals);
+        cond->signals = cond->waiting;
+        for (i = 0; i < num_waiting; ++i) {
+            SDL_SemPost(cond->wait_sem);
+        }
+        /* Now all released threads are blocked here, waiting for us.
+           Collect them all (and win fabulous prizes!) :-)
+         */
+        SDL_UnlockMutex(cond->lock);
+        for (i = 0; i < num_waiting; ++i) {
+            SDL_SemWait(cond->wait_done);
+        }
+    } else {
+        SDL_UnlockMutex(cond->lock);
+    }
+
+    return 0;
+}
+
+/* Wait on the condition variable for at most 'ms' milliseconds.
+   The mutex must be locked before entering this function!
+   The mutex is unlocked during the wait, and locked again after the wait.
+
+Typical use:
+
+Thread A:
+    SDL_LockMutex(lock);
+    while ( ! condition ) {
+        SDL_CondWait(cond, lock);
+    }
+    SDL_UnlockMutex(lock);
+
+Thread B:
+    SDL_LockMutex(lock);
+    ...
+    condition = true;
+    ...
+    SDL_CondSignal(cond);
+    SDL_UnlockMutex(lock);
+ */
+int
+SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
+{
+    int retval;
+
+    if (!cond) {
+        SDL_SetError("Passed a NULL condition variable");
+        return -1;
+    }
+
+    /* Obtain the protection mutex, and increment the number of waiters.
+       This allows the signal mechanism to only perform a signal if there
+       are waiting threads.
+     */
+    SDL_LockMutex(cond->lock);
+    ++cond->waiting;
+    SDL_UnlockMutex(cond->lock);
+
+    /* Unlock the mutex, as is required by condition variable semantics */
+    SDL_UnlockMutex(mutex);
+
+    /* Wait for a signal */
+    if (ms == SDL_MUTEX_MAXWAIT) {
+        retval = SDL_SemWait(cond->wait_sem);
+    } else {
+        retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
+    }
+
+    /* Let the signaler know we have completed the wait, otherwise
+       the signaler can race ahead and get the condition semaphore
+       if we are stopped between the mutex unlock and semaphore wait,
+       giving a deadlock.  See the following URL for details:
+       http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
+     */
+    SDL_LockMutex(cond->lock);
+    if (cond->signals > 0) {
+        /* If we timed out, we need to eat a condition signal */
+        if (retval > 0) {
+            SDL_SemWait(cond->wait_sem);
+        }
+        /* We always notify the signal thread that we are done */
+        SDL_SemPost(cond->wait_done);
+
+        /* Signal handshake complete */
+        --cond->signals;
+    }
+    --cond->waiting;
+    SDL_UnlockMutex(cond->lock);
+
+    /* Lock the mutex, as is required by condition variable semantics */
+    SDL_LockMutex(mutex);
+
+    return retval;
+}
+
+/* Wait on the condition variable forever */
+int
+SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
+{
+    return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/psp/SDL_sysmutex.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,135 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_config.h"
+
+/* An implementation of mutexes using semaphores */
+
+#include "SDL_thread.h"
+#include "SDL_systhread_c.h"
+
+
+struct SDL_mutex
+{
+    int recursive;
+    SDL_threadID owner;
+    SDL_sem *sem;
+};
+
+/* Create a mutex */
+SDL_mutex *
+SDL_CreateMutex(void)
+{
+    SDL_mutex *mutex;
+
+    /* Allocate mutex memory */
+    mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
+    if (mutex) {
+        /* Create the mutex semaphore, with initial value 1 */
+        mutex->sem = SDL_CreateSemaphore(1);
+        mutex->recursive = 0;
+        mutex->owner = 0;
+        if (!mutex->sem) {
+            SDL_free(mutex);
+            mutex = NULL;
+        }
+    } else {
+        SDL_OutOfMemory();
+    }
+    return mutex;
+}
+
+/* Free the mutex */
+void
+SDL_DestroyMutex(SDL_mutex * mutex)
+{
+    if (mutex) {
+        if (mutex->sem) {
+            SDL_DestroySemaphore(mutex->sem);
+        }
+        SDL_free(mutex);
+    }
+}
+
+/* Lock the semaphore */
+int
+SDL_mutexP(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+    return 0;
+#else
+    SDL_threadID this_thread;
+
+    if (mutex == NULL) {
+        SDL_SetError("Passed a NULL mutex");
+        return -1;
+    }
+
+    this_thread = SDL_ThreadID();
+    if (mutex->owner == this_thread) {
+        ++mutex->recursive;
+    } else {
+        /* The order of operations is important.
+           We set the locking thread id after we obtain the lock
+           so unlocks from other threads will fail.
+         */
+        SDL_SemWait(mutex->sem);
+        mutex->owner = this_thread;
+        mutex->recursive = 0;
+    }
+
+    return 0;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+/* Unlock the mutex */
+int
+SDL_mutexV(SDL_mutex * mutex)
+{
+#if SDL_THREADS_DISABLED
+    return 0;
+#else
+    if (mutex == NULL) {
+        SDL_SetError("Passed a NULL mutex");
+        return -1;
+    }
+
+    /* If we don't own the mutex, we can't unlock it */
+    if (SDL_ThreadID() != mutex->owner) {
+        SDL_SetError("mutex not owned by this thread");
+        return -1;
+    }
+
+    if (mutex->recursive) {
+        --mutex->recursive;
+    } else {
+        /* The order of operations is important.
+           First reset the owner so another thread doesn't lock
+           the mutex and set the ownership before we reset it,
+           then release the lock semaphore.
+         */
+        mutex->owner = 0;
+        SDL_SemPost(mutex->sem);
+    }
+    return 0;
+#endif /* SDL_THREADS_DISABLED */
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/psp/SDL_sysmutex_c.h	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,22 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_config.h"
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/psp/SDL_syssem.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,159 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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.
+*/
+
+/* Semaphore functions for the PSP. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "SDL_error.h"
+#include "SDL_thread.h"
+
+#include <pspthreadman.h>
+#include <pspkerror.h>
+
+struct SDL_semaphore {
+	SceUID	semid;
+};
+
+
+/* Create a semaphore */
+SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
+{
+	SDL_sem *sem;
+
+	sem = (SDL_sem *) malloc(sizeof(*sem));
+	if (sem != NULL) {
+		/* TODO: Figure out the limit on the maximum value. */
+		sem->semid = sceKernelCreateSema("SDL sema", 0, initial_value, 255, NULL);
+		if (sem->semid < 0) {
+			SDL_SetError("Couldn't create semaphore");
+			free(sem);
+			sem = NULL;
+		}
+	} else {
+		SDL_OutOfMemory();
+	}
+
+	return sem;
+}
+
+/* Free the semaphore */
+void SDL_DestroySemaphore(SDL_sem *sem)
+{
+	if (sem != NULL) {
+		if (sem->semid > 0) {
+			sceKernelDeleteSema(sem->semid);
+			sem->semid = 0;
+		}
+
+		free(sem);
+	}
+}
+
+/* TODO: This routine is a bit overloaded.
+ * If the timeout is 0 then just poll the semaphore; if it's SDL_MUTEX_MAXWAIT, pass
+ * NULL to sceKernelWaitSema() so that it waits indefinitely; and if the timeout
+ * is specified, convert it to microseconds. */
+int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
+{
+	Uint32 *pTimeout;
+       unsigned int res;
+
+	if (sem == NULL) {
+		SDL_SetError("Passed a NULL sem");
+		return 0;
+	}
+
+	if (timeout == 0) {
+		res = sceKernelPollSema(sem->semid, 1);
+		if (res < 0) {
+			return SDL_MUTEX_TIMEDOUT;
+		}
+		return 0;
+	}
+
+	if (timeout == SDL_MUTEX_MAXWAIT) {
+		pTimeout = NULL;
+	} else {
+		timeout *= 1000;  /* Convert to microseconds. */
+		pTimeout = &timeout;
+	}
+
+	res = sceKernelWaitSema(sem->semid, 1, pTimeout);
+       switch (res) {
+               case SCE_KERNEL_ERROR_OK:
+                       return 0;
+               case SCE_KERNEL_ERROR_WAIT_TIMEOUT:
+                       return SDL_MUTEX_TIMEDOUT;
+               default:
+                       SDL_SetError("WaitForSingleObject() failed");
+                       return -1;
+	}
+}
+
+int SDL_SemTryWait(SDL_sem *sem)
+{
+	return SDL_SemWaitTimeout(sem, 0);
+}
+
+int SDL_SemWait(SDL_sem *sem)
+{
+	return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
+}
+
+/* Returns the current count of the semaphore */
+Uint32 SDL_SemValue(SDL_sem *sem)
+{
+	SceKernelSemaInfo info;
+
+	if (sem == NULL) {
+		SDL_SetError("Passed a NULL sem");
+		return 0;
+	}
+
+	if (sceKernelReferSemaStatus(sem->semid, &info) >= 0) {
+		return info.currentCount;
+	}
+
+	return 0;
+}
+
+int SDL_SemPost(SDL_sem *sem)
+{
+	int res;
+
+	if (sem == NULL) {
+		SDL_SetError("Passed a NULL sem");
+		return -1;
+	}
+
+	res = sceKernelSignalSema(sem->semid, 1);
+	if (res < 0) {
+		SDL_SetError("sceKernelSignalSema() failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+/* vim: ts=4 sw=4
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/psp/SDL_systhread.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,103 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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.
+*/
+
+
+/* PSP thread management routines for SDL */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "SDL_error.h"
+#include "SDL_thread.h"
+#include "../SDL_systhread.h"
+#include "../SDL_thread_c.h"
+#include <pspkerneltypes.h>
+#include <pspthreadman.h>
+
+
+static int ThreadEntry(SceSize args, void *argp)
+{
+	SDL_RunThread(*(void **) argp);
+	return 0;
+}
+
+int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
+{
+	SceKernelThreadInfo status;
+	int priority = 32;
+
+	/* Set priority of new thread to the same as the current thread */
+	status.size = sizeof(SceKernelThreadInfo);
+	if (sceKernelReferThreadStatus(sceKernelGetThreadId(), &status) == 0) {
+		priority = status.currentPriority;
+	}
+
+	thread->handle = sceKernelCreateThread("SDL thread", ThreadEntry, 
+					       priority, 0x8000, 
+					       PSP_THREAD_ATTR_VFPU, NULL);
+	if (thread->handle < 0) {
+		SDL_SetError("sceKernelCreateThread() failed");
+		return -1;
+	}
+
+	sceKernelStartThread(thread->handle, 4, &args);
+	return 0;
+}
+
+void SDL_SYS_SetupThread(const char *name)
+{
+	/* Do nothing. */
+}
+
+SDL_threadID SDL_ThreadID(void)
+{
+	return (SDL_threadID) sceKernelGetThreadId();
+}
+
+void SDL_SYS_WaitThread(SDL_Thread *thread)
+{
+	sceKernelWaitThreadEnd(thread->handle, NULL);
+	sceKernelDeleteThread(thread->handle);
+}
+
+void SDL_SYS_KillThread(SDL_Thread *thread)
+{ 
+	sceKernelTerminateDeleteThread(thread->handle);
+}
+
+int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
+{    
+    int value;
+    
+    if (priority == SDL_THREAD_PRIORITY_LOW) {
+        value = 19;
+    } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
+        value = -20;
+    } else {
+        value = 0;
+    }
+    
+    return sceKernelChangeThreadPriority(sceKernelGetThreadId(),value);
+
+}
+
+/* vim: ts=4 sw=4
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/psp/SDL_systhread_c.h	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,24 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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 <pspkerneltypes.h>
+
+typedef SceUID SYS_ThreadHandle;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/timer/psp/SDL_systimer.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,69 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_thread.h"
+#include "SDL_timer.h"
+#include "SDL_error.h"
+#include "../SDL_timer_c.h"
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <pspthreadman.h>
+
+static struct timeval start;
+
+void SDL_StartTicks(void)
+{
+	gettimeofday(&start, NULL);
+}
+
+Uint32 SDL_GetTicks(void)
+{
+	struct timeval now;
+	Uint32 ticks;
+
+	gettimeofday(&now, NULL);
+	ticks=(now.tv_sec-start.tv_sec)*1000+(now.tv_usec-start.tv_usec)/1000;
+	return(ticks);
+}
+
+Uint64
+SDL_GetPerformanceCounter(void)
+{
+    return SDL_GetTicks();
+}
+
+Uint64
+SDL_GetPerformanceFrequency(void)
+{
+    return 1000;
+}
+
+void SDL_Delay(Uint32 ms)
+{
+	const Uint32 max_delay = 0xffffffffUL / 1000;
+	if(ms > max_delay)
+		ms = max_delay;
+	sceKernelDelayThreadCB(ms * 1000);
+}
+
+/* vim: ts=4 sw=4
+ */
--- a/src/video/SDL_sysvideo.h	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/video/SDL_sysvideo.h	Sun Mar 17 20:07:02 2013 +0800
@@ -350,6 +350,9 @@
 #if SDL_VIDEO_DRIVER_ANDROID
 extern VideoBootStrap Android_bootstrap;
 #endif
+#if SDL_VIDEO_DRIVER_PSP
+extern VideoBootStrap PSP_bootstrap;
+#endif
 #if SDL_VIDEO_DRIVER_DUMMY
 extern VideoBootStrap DUMMY_bootstrap;
 #endif
--- a/src/video/SDL_video.c	Sat Mar 16 11:00:04 2013 -0700
+++ b/src/video/SDL_video.c	Sun Mar 17 20:07:02 2013 +0800
@@ -78,6 +78,9 @@
 #if SDL_VIDEO_DRIVER_ANDROID
     &Android_bootstrap,
 #endif
+#if SDL_VIDEO_DRIVER_PSP
+    &PSP_bootstrap,
+#endif
 #if SDL_VIDEO_DRIVER_DUMMY
     &DUMMY_bootstrap,
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/psp/SDL_pspevents.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,284 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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.
+*/
+
+/* Being a null driver, there's no event stream. We just define stubs for
+   most of the API. */
+
+#include "SDL.h"
+#include "../../events/SDL_sysevents.h"
+#include "../../events/SDL_events_c.h"
+#include "../../events/SDL_keyboard_c.h"
+#include "SDL_pspvideo.h"
+#include "SDL_pspevents_c.h"
+#include "SDL_thread.h"
+#include "SDL_keyboard.h"
+#include <psphprm.h>
+
+#ifdef PSPIRKEYB
+#include <pspirkeyb.h>
+#include <pspirkeyb_rawkeys.h>
+
+#define IRKBD_CONFIG_FILE     NULL    /* this will take ms0:/seplugins/pspirkeyb.ini */
+
+static int irkbd_ready = 0;
+static SDLKey keymap[256];
+#endif
+
+static enum PspHprmKeys hprm = 0;
+static SDL_sem *event_sem = NULL;
+static SDL_Thread *thread = NULL;
+static int running = 0;
+static struct {
+	enum PspHprmKeys id;
+	SDL_Keycode sym;
+} keymap_psp[] = {
+	{ PSP_HPRM_PLAYPAUSE, SDLK_F10 },
+	{ PSP_HPRM_FORWARD,   SDLK_F11 },
+	{ PSP_HPRM_BACK,      SDLK_F12 },
+	{ PSP_HPRM_VOL_UP,    SDLK_F13 },
+	{ PSP_HPRM_VOL_DOWN,  SDLK_F14 },
+	{ PSP_HPRM_HOLD,      SDLK_F15 }
+};
+
+int EventUpdate(void *data)
+{
+	while (running) {
+                SDL_SemWait(event_sem);
+								sceHprmPeekCurrentKey(&hprm);
+                SDL_SemPost(event_sem);
+                /* Delay 1/60th of a second */
+                sceKernelDelayThread(1000000 / 60);  
+        }
+        return 0;
+}
+
+void PSP_PumpEvents(_THIS)
+{
+	int i;
+	enum PspHprmKeys keys;
+	enum PspHprmKeys changed;
+	static enum PspHprmKeys old_keys = 0;
+	SDL_Keysym sym;
+
+	SDL_SemWait(event_sem);
+	keys = hprm;
+	SDL_SemPost(event_sem);
+
+	/* HPRM Keyboard */
+	changed = old_keys ^ keys;
+	old_keys = keys;
+	if(changed) {
+		for(i=0; i<sizeof(keymap_psp)/sizeof(keymap_psp[0]); i++) {
+			if(changed & keymap_psp[i].id) {
+				sym.scancode = keymap_psp[i].id;
+				sym.sym = keymap_psp[i].sym;	
+							
+				/* out of date
+				SDL_PrivateKeyboard((keys & keymap_psp[i].id) ? 
+						    SDL_PRESSED : SDL_RELEASED, 
+						    &sym);
+        */
+        		SDL_SendKeyboardKey((keys & keymap_psp[i].id) ? 
+						    		SDL_PRESSED : SDL_RELEASED, SDL_GetScancodeFromKey(keymap_psp[i].sym));
+			}
+		}
+	}
+
+#ifdef PSPIRKEYB
+	if (irkbd_ready) {
+    	    unsigned char buffer[255];
+	    int i, length, count;
+	    SIrKeybScanCodeData *scanData;
+	    
+    	    if(pspIrKeybReadinput(buffer, &length) >= 0) {
+        	    if((length % sizeof(SIrKeybScanCodeData)) == 0){
+        		    count = length / sizeof(SIrKeybScanCodeData);
+        		    for( i=0; i < count; i++ ) {
+				unsigned char raw, pressed;
+            			scanData=(SIrKeybScanCodeData*) buffer+i;
+            			raw = scanData->raw;
+            			pressed = scanData->pressed;
+				sym.scancode = raw;
+				sym.sym = keymap[raw];
+				/* not tested*/
+				//SDL_PrivateKeyboard(pressed?SDL_PRESSED:SDL_RELEASED, &sym);
+        		SDL_SendKeyboardKey((keys & keymap_psp[i].id) ? 
+						    		SDL_PRESSED : SDL_RELEASED, SDL_GetScancodeFromKey(keymap[raw]);
+						    	
+			    }
+		    }
+	    }
+	}
+#endif
+	sceKernelDelayThread(0);
+
+	return;
+}
+
+void PSP_InitOSKeymap(_THIS)
+{
+#ifdef PSPIRKEYB
+	int i;
+	for (i=0; i<SDL_TABLESIZE(keymap); ++i)
+	    keymap[i] = SDLK_UNKNOWN;
+	    
+	keymap[KEY_ESC] = SDLK_ESCAPE;
+
+	keymap[KEY_F1] = SDLK_F1;
+	keymap[KEY_F2] = SDLK_F2;
+	keymap[KEY_F3] = SDLK_F3;
+	keymap[KEY_F4] = SDLK_F4;
+	keymap[KEY_F5] = SDLK_F5;
+	keymap[KEY_F6] = SDLK_F6;
+	keymap[KEY_F7] = SDLK_F7;
+	keymap[KEY_F8] = SDLK_F8;
+	keymap[KEY_F9] = SDLK_F9;
+	keymap[KEY_F10] = SDLK_F10;
+	keymap[KEY_F11] = SDLK_F11;
+	keymap[KEY_F12] = SDLK_F12;
+	keymap[KEY_F13] = SDLK_PRINT;
+	keymap[KEY_F14] = SDLK_PAUSE;
+
+	keymap[KEY_GRAVE] = SDLK_BACKQUOTE;
+	keymap[KEY_1] = SDLK_1;
+	keymap[KEY_2] = SDLK_2;
+	keymap[KEY_3] = SDLK_3;
+	keymap[KEY_4] = SDLK_4;
+	keymap[KEY_5] = SDLK_5;
+	keymap[KEY_6] = SDLK_6;
+	keymap[KEY_7] = SDLK_7;
+	keymap[KEY_8] = SDLK_8;
+	keymap[KEY_9] = SDLK_9;
+	keymap[KEY_0] = SDLK_0;
+	keymap[KEY_MINUS] = SDLK_MINUS;
+	keymap[KEY_EQUAL] = SDLK_EQUALS;
+	keymap[KEY_BACKSPACE] = SDLK_BACKSPACE;
+
+	keymap[KEY_TAB] = SDLK_TAB;
+	keymap[KEY_Q] = SDLK_q;
+	keymap[KEY_W] = SDLK_w;
+	keymap[KEY_E] = SDLK_e;
+	keymap[KEY_R] = SDLK_r;
+	keymap[KEY_T] = SDLK_t;
+	keymap[KEY_Y] = SDLK_y;
+	keymap[KEY_U] = SDLK_u;
+	keymap[KEY_I] = SDLK_i;
+	keymap[KEY_O] = SDLK_o;
+	keymap[KEY_P] = SDLK_p;
+	keymap[KEY_LEFTBRACE] = SDLK_LEFTBRACKET;
+	keymap[KEY_RIGHTBRACE] = SDLK_RIGHTBRACKET;
+	keymap[KEY_ENTER] = SDLK_RETURN;
+	
+	keymap[KEY_CAPSLOCK] = SDLK_CAPSLOCK;
+	keymap[KEY_A] = SDLK_a;
+	keymap[KEY_S] = SDLK_s;
+	keymap[KEY_D] = SDLK_d;
+	keymap[KEY_F] = SDLK_f;
+	keymap[KEY_G] = SDLK_g;
+	keymap[KEY_H] = SDLK_h;
+	keymap[KEY_J] = SDLK_j;
+	keymap[KEY_K] = SDLK_k;
+	keymap[KEY_L] = SDLK_l;
+	keymap[KEY_SEMICOLON] = SDLK_SEMICOLON;
+	keymap[KEY_APOSTROPHE] = SDLK_QUOTE;
+	keymap[KEY_BACKSLASH] = SDLK_BACKSLASH;
+		
+	keymap[KEY_Z] = SDLK_z;
+	keymap[KEY_X] = SDLK_x;
+	keymap[KEY_C] = SDLK_c;
+	keymap[KEY_V] = SDLK_v;
+	keymap[KEY_B] = SDLK_b;
+	keymap[KEY_N] = SDLK_n;
+	keymap[KEY_M] = SDLK_m;	
+	keymap[KEY_COMMA] = SDLK_COMMA;
+	keymap[KEY_DOT] = SDLK_PERIOD;
+	keymap[KEY_SLASH] = SDLK_SLASH;
+	
+	keymap[KEY_SPACE] = SDLK_SPACE;
+	
+	keymap[KEY_UP] = SDLK_UP;
+	keymap[KEY_DOWN] = SDLK_DOWN;
+	keymap[KEY_LEFT] = SDLK_LEFT;
+	keymap[KEY_RIGHT] = SDLK_RIGHT;
+	
+	keymap[KEY_HOME] = SDLK_HOME;
+	keymap[KEY_END] = SDLK_END;
+	keymap[KEY_INSERT] = SDLK_INSERT;
+	keymap[KEY_DELETE] = SDLK_DELETE;
+
+	keymap[KEY_NUMLOCK] = SDLK_NUMLOCK;
+	keymap[KEY_LEFTMETA] = SDLK_LSUPER;
+	
+	keymap[KEY_KPSLASH] = SDLK_KP_DIVIDE;
+	keymap[KEY_KPASTERISK] = SDLK_KP_MULTIPLY;
+	keymap[KEY_KPMINUS] = SDLK_KP_MINUS;
+	keymap[KEY_KPPLUS] = SDLK_KP_PLUS;
+	keymap[KEY_KPDOT] = SDLK_KP_PERIOD;
+	keymap[KEY_KPEQUAL] = SDLK_KP_EQUALS;
+
+	keymap[KEY_LEFTCTRL] = SDLK_LCTRL;
+	keymap[KEY_RIGHTCTRL] = SDLK_RCTRL;
+	keymap[KEY_LEFTALT] = SDLK_LALT;
+	keymap[KEY_RIGHTALT] = SDLK_RALT;
+	keymap[KEY_LEFTSHIFT] = SDLK_LSHIFT;
+	keymap[KEY_RIGHTSHIFT] = SDLK_RSHIFT;
+#endif
+}
+
+void PSP_EventInit(_THIS)
+{
+#ifdef PSPIRKEYB
+	int outputmode = PSP_IRKBD_OUTPUT_MODE_SCANCODE;
+	int ret = pspIrKeybInit(IRKBD_CONFIG_FILE, 0);
+	if (ret == PSP_IRKBD_RESULT_OK) {
+    		pspIrKeybOutputMode(outputmode);
+		irkbd_ready = 1;
+	} else {
+		irkbd_ready = 0;
+	}
+#endif
+	/* Start thread to read data */
+	if((event_sem =  SDL_CreateSemaphore(1)) == NULL) {
+		SDL_SetError("Can't create input semaphore\n");
+		return;
+	}
+	running = 1;
+	if((thread = SDL_CreateThread(EventUpdate, "PSPInputThread",NULL)) == NULL) {
+		SDL_SetError("Can't create input thread\n");
+		return;
+	}
+}
+
+void PSP_EventQuit(_THIS)
+{
+	running = 0;
+	SDL_WaitThread(thread, NULL);
+	SDL_DestroySemaphore(event_sem);
+#ifdef PSPIRKEYB
+	if (irkbd_ready) {
+    		pspIrKeybFinish();
+		irkbd_ready = 0;
+	}
+#endif
+}
+
+/* end of SDL_pspevents.c ... */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/psp/SDL_pspevents_c.h	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,31 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_pspvideo.h"
+
+/* Variables and functions exported by SDL_sysevents.c to other parts 
+   of the native video subsystem (SDL_sysvideo.c)
+*/
+extern void PSP_InitOSKeymap(_THIS);
+extern void PSP_PumpEvents(_THIS);
+
+/* end of SDL_pspevents_c.h ... */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/psp/SDL_pspgl.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,207 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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 <stdlib.h>
+#include <string.h>
+
+#include "SDL_error.h"
+#include "SDL_pspvideo.h"
+#include "SDL_pspgl_c.h"
+
+/*****************************************************************************/
+/* SDL OpenGL/OpenGL ES functions                                            */
+/*****************************************************************************/
+#define EGLCHK(stmt)							\
+	do {										\
+		EGLint err;								\
+												\
+		stmt;									\
+		err = eglGetError();					\
+		if (err != EGL_SUCCESS) {				\
+			SDL_SetError("EGL error %d", err);	\
+			return 0;							\
+		}										\
+	} while (0)
+
+int
+PSP_GL_LoadLibrary(_THIS, const char *path)
+{
+  if (!_this->gl_config.driver_loaded) {
+		_this->gl_config.driver_loaded = 1;
+  }
+
+  return 0;
+}
+
+/* pspgl doesn't provide this call, so stub it out since SDL requires it. 
+#define GLSTUB(func,params) void func params {}
+  		 
+GLSTUB(glOrtho,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top,
+          			GLdouble zNear, GLdouble zFar))
+*/
+void *
+PSP_GL_GetProcAddress(_THIS, const char *proc)
+{
+		return eglGetProcAddress(proc);
+}
+
+void
+PSP_GL_UnloadLibrary(_THIS)
+{
+		eglTerminate(_this->gl_data->display);
+}
+
+static EGLint width = 480;
+static EGLint height = 272;
+
+SDL_GLContext
+PSP_GL_CreateContext(_THIS, SDL_Window * window)
+{
+
+    SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
+
+		EGLint attribs[32];
+		EGLDisplay display;
+		EGLContext context;
+		EGLSurface surface;
+		EGLConfig config;
+		EGLint num_configs;
+		int i;
+	
+
+	/* EGL init taken from glutCreateWindow() in PSPGL's glut.c. */
+		EGLCHK(display = eglGetDisplay(0));
+		EGLCHK(eglInitialize(display, NULL, NULL));
+    wdata->uses_gles = SDL_TRUE;   
+		window->flags |= SDL_WINDOW_FULLSCREEN;
+    	
+		/* Setup the config based on SDL's current values. */
+		i = 0;
+		attribs[i++] = EGL_RED_SIZE;
+		attribs[i++] = _this->gl_config.red_size;
+		attribs[i++] = EGL_GREEN_SIZE;
+		attribs[i++] = _this->gl_config.green_size;
+		attribs[i++] = EGL_BLUE_SIZE;
+		attribs[i++] = _this->gl_config.blue_size;
+		attribs[i++] = EGL_DEPTH_SIZE;
+		attribs[i++] = _this->gl_config.depth_size;
+	
+		if (_this->gl_config.alpha_size)
+		{
+			attribs[i++] = EGL_ALPHA_SIZE;
+			attribs[i++] = _this->gl_config.alpha_size;
+		}
+		if (_this->gl_config.stencil_size)
+		{
+			attribs[i++] = EGL_STENCIL_SIZE;
+			attribs[i++] = _this->gl_config.stencil_size;
+		}
+	
+		attribs[i++] = EGL_NONE;
+		
+		EGLCHK(eglChooseConfig(display, attribs, &config, 1, &num_configs));
+	
+		if (num_configs == 0)
+		{
+			SDL_SetError("No valid EGL configs for requested mode");
+			return 0;
+		}
+		
+		EGLCHK(eglGetConfigAttrib(display, config, EGL_WIDTH, &width));
+		EGLCHK(eglGetConfigAttrib(display, config, EGL_HEIGHT, &height));
+
+		EGLCHK(context = eglCreateContext(display, config, NULL, NULL));
+		EGLCHK(surface = eglCreateWindowSurface(display, config, 0, NULL));
+		EGLCHK(eglMakeCurrent(display, surface, surface, context));	
+		
+		_this->gl_data->display = display;
+		_this->gl_data->context = context;
+		_this->gl_data->surface = surface;
+	
+
+    return context;
+}
+
+int
+PSP_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
+{
+		if (!eglMakeCurrent(_this->gl_data->display, _this->gl_data->surface,
+	                      _this->gl_data->surface, _this->gl_data->context))
+		{
+			SDL_SetError("Unable to make EGL context current");
+			return -1;
+		}
+    return 0;
+}
+
+int
+PSP_GL_SetSwapInterval(_THIS, int interval)
+{
+    EGLBoolean status;    
+    status = eglSwapInterval(_this->gl_data->display, interval);
+    if (status == EGL_TRUE) {
+        /* Return success to upper level */
+        _this->gl_data->swapinterval = interval;
+        return 0;
+    }
+    /* Failed to set swap interval */
+    SDL_SetError("Unable to set the EGL swap interval");
+    return -1;
+}
+
+int
+PSP_GL_GetSwapInterval(_THIS)
+{
+    return _this->gl_data->swapinterval;
+}
+
+void
+PSP_GL_SwapWindow(_THIS, SDL_Window * window)
+{
+    eglSwapBuffers(_this->gl_data->display, _this->gl_data->surface);
+}
+
+void
+PSP_GL_DeleteContext(_THIS, SDL_GLContext context)
+{
+    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
+    EGLBoolean status;
+
+    if (phdata->egl_initialized != SDL_TRUE) {
+        SDL_SetError("PSP: GLES initialization failed, no OpenGL ES support");
+        return;
+    }
+
+    /* Check if OpenGL ES connection has been initialized */
+    if (_this->gl_data->display != EGL_NO_DISPLAY) {
+        if (context != EGL_NO_CONTEXT) {
+            status = eglDestroyContext(_this->gl_data->display, context);
+            if (status != EGL_TRUE) {
+                /* Error during OpenGL ES context destroying */
+                SDL_SetError("PSP: OpenGL ES context destroy error");
+                return;
+            }
+        }
+    }
+
+    return;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/psp/SDL_pspgl_c.h	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,52 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_pspgl_c_h
+#define _SDL_pspgl_c_h
+
+
+#include <GLES/egl.h>
+#include <GLES/gl.h>
+
+#include "SDL_pspvideo.h"
+
+
+typedef struct SDL_GLDriverData {
+		EGLDisplay display;
+		EGLContext context;
+		EGLSurface surface;
+    uint32_t swapinterval;
+}SDL_GLDriverData;
+
+extern void * PSP_GL_GetProcAddress(_THIS, const char *proc);
+extern int PSP_GL_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
+extern void PSP_GL_SwapBuffers(_THIS);
+
+extern void PSP_GL_SwapWindow(_THIS, SDL_Window * window);
+extern SDL_GLContext PSP_GL_CreateContext(_THIS, SDL_Window * window);
+
+extern int PSP_GL_LoadLibrary(_THIS, const char *path);
+extern void PSP_GL_UnloadLibrary(_THIS);
+extern int PSP_GL_SetSwapInterval(_THIS, int interval);
+extern int PSP_GL_GetSwapInterval(_THIS);
+
+
+#endif /* _SDL_pspgl_c_h */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/psp/SDL_pspmouse.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,35 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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 <stdio.h>
+
+#include "SDL_error.h"
+#include "SDL_mouse.h"
+#include "../../events/SDL_events_c.h"
+
+#include "SDL_pspmouse_c.h"
+
+
+/* The implementation dependent data for the window manager cursor */
+struct WMcursor {
+	int unused;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/psp/SDL_pspmouse_c.h	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,24 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_pspvideo.h"
+
+/* Functions to be exported */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/psp/SDL_pspvideo.c	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,334 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_config.h"
+
+#if SDL_VIDEO_DRIVER_PSP
+
+/* SDL internals */
+#include "../SDL_sysvideo.h"
+#include "SDL_version.h"
+#include "SDL_syswm.h"
+#include "SDL_loadso.h"
+#include "SDL_events.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_keyboard_c.h"
+
+
+
+/* PSP declarations */
+#include "SDL_pspvideo.h"
+#include "SDL_pspevents_c.h"
+#include "SDL_pspgl_c.h"
+
+/* unused
+static SDL_bool PSP_initialized = SDL_FALSE;
+*/
+static int
+PSP_Available(void)
+{
+    return 1;
+}
+
+static void
+PSP_Destroy(SDL_VideoDevice * device)
+{
+//    SDL_VideoData *phdata = (SDL_VideoData *) device->driverdata;
+
+    if (device->driverdata != NULL) {
+        device->driverdata = NULL;
+    }
+}
+
+static SDL_VideoDevice *
+PSP_Create()
+{
+    SDL_VideoDevice *device;
+    SDL_VideoData *phdata;
+    SDL_GLDriverData *gldata;
+    int status;
+
+    /* Check if pandora could be initialized */
+    status = PSP_Available();
+    if (status == 0) {
+        /* PSP 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 Pandora specific data */
+    phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
+    if (phdata == NULL) {
+        SDL_OutOfMemory();
+        SDL_free(device);
+        return NULL;
+    }
+        
+		gldata = (SDL_GLDriverData *) SDL_calloc(1, sizeof(SDL_GLDriverData));
+    if (gldata == NULL) {
+        SDL_OutOfMemory();
+        SDL_free(device);
+        return NULL;
+    }	
+    device->gl_data = gldata;
+    
+    device->driverdata = phdata;
+
+    phdata->egl_initialized = SDL_TRUE;
+
+
+    /* Setup amount of available displays and current display */
+    device->num_displays = 0;
+
+    /* Set device free function */
+    device->free = PSP_Destroy;
+
+    /* Setup all functions which we can handle */
+    device->VideoInit = PSP_VideoInit;
+    device->VideoQuit = PSP_VideoQuit;
+    device->GetDisplayModes = PSP_GetDisplayModes;
+    device->SetDisplayMode = PSP_SetDisplayMode;
+    device->CreateWindow = PSP_CreateWindow;
+    device->CreateWindowFrom = PSP_CreateWindowFrom;
+    device->SetWindowTitle = PSP_SetWindowTitle;
+    device->SetWindowIcon = PSP_SetWindowIcon;
+    device->SetWindowPosition = PSP_SetWindowPosition;
+    device->SetWindowSize = PSP_SetWindowSize;
+    device->ShowWindow = PSP_ShowWindow;
+    device->HideWindow = PSP_HideWindow;
+    device->RaiseWindow = PSP_RaiseWindow;
+    device->MaximizeWindow = PSP_MaximizeWindow;
+    device->MinimizeWindow = PSP_MinimizeWindow;
+    device->RestoreWindow = PSP_RestoreWindow;
+    device->SetWindowGrab = PSP_SetWindowGrab;
+    device->DestroyWindow = PSP_DestroyWindow;
+    device->GetWindowWMInfo = PSP_GetWindowWMInfo;
+    device->GL_LoadLibrary = PSP_GL_LoadLibrary;
+    device->GL_GetProcAddress = PSP_GL_GetProcAddress;
+    device->GL_UnloadLibrary = PSP_GL_UnloadLibrary;
+    device->GL_CreateContext = PSP_GL_CreateContext;
+    device->GL_MakeCurrent = PSP_GL_MakeCurrent;
+    device->GL_SetSwapInterval = PSP_GL_SetSwapInterval;
+    device->GL_GetSwapInterval = PSP_GL_GetSwapInterval;
+    device->GL_SwapWindow = PSP_GL_SwapWindow;
+    device->GL_DeleteContext = PSP_GL_DeleteContext;
+	device->SDL_HasScreenKeyboardSupport = PSP_SDL_HasScreenKeyboardSupport;
+	device->SDL_ShowScreenKeyboard = PSP_SDL_ShowScreenKeyboard;
+	device->SDL_HideScreenKeyboard = PSP_SDL_HideScreenKeyboard;
+	device->SDL_IsScreenKeyboardShown = PSP_SDL_IsScreenKeyboardShown;    
+    
+    device->PumpEvents = PSP_PumpEvents;
+
+    return device;
+}
+
+VideoBootStrap PSP_bootstrap = {
+    "PSP",
+    "PSP Video Driver",
+    PSP_Available,
+    PSP_Create
+};
+
+/*****************************************************************************/
+/* SDL Video and Display initialization/handling functions                   */
+/*****************************************************************************/
+int
+PSP_VideoInit(_THIS)
+{
+    SDL_VideoDisplay display;
+    SDL_DisplayMode current_mode;
+
+    SDL_zero(current_mode);
+    
+    current_mode.w = 480;
+    current_mode.h = 272;
+    
+    current_mode.refresh_rate = 60;
+    // 32 bpp for default 
+   // current_mode.format = SDL_PIXELFORMAT_RGBA8888;
+    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
+PSP_VideoQuit(_THIS)
+{
+
+}
+
+void
+PSP_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
+{
+
+}
+
+int
+PSP_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
+{
+    return 0;
+}
+#define EGLCHK(stmt)							\
+	do {										\
+		EGLint err;								\
+												\
+		stmt;									\
+		err = eglGetError();					\
+		if (err != EGL_SUCCESS) {				\
+			SDL_SetError("EGL error %d", err);	\
+			return 0;							\
+		}										\
+	} while (0)
+	
+int
+PSP_CreateWindow(_THIS, SDL_Window * window)
+{
+//    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
+
+    SDL_WindowData *wdata;
+
+    /* Allocate window internal data */
+    wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
+    if (wdata == NULL) {
+        SDL_OutOfMemory();
+        return -1;
+    }
+
+    /* Setup driver data for this window */
+    window->driverdata = wdata;
+
+
+    /* Window has been successfully created */
+    return 0;
+}
+
+int
+PSP_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
+{
+    return -1;
+}
+
+void
+PSP_SetWindowTitle(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
+{
+}
+void
+PSP_SetWindowPosition(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_SetWindowSize(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_ShowWindow(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_HideWindow(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_RaiseWindow(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_MaximizeWindow(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_MinimizeWindow(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_RestoreWindow(_THIS, SDL_Window * window)
+{
+}
+void
+PSP_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
+{
+
+}
+void
+PSP_DestroyWindow(_THIS, SDL_Window * window)
+{
+	
+//    eglTerminate(_this->gl_data->display);
+}
+
+/*****************************************************************************/
+/* SDL Window Manager function                                               */
+/*****************************************************************************/
+SDL_bool
+PSP_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\n",
+                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
+        return SDL_FALSE;
+    }
+
+    /* Failed to get window manager information */
+    return SDL_FALSE;
+}
+
+
+/* TO Write Me*/
+SDL_bool PSP_SDL_HasScreenKeyboardSupport(_THIS)
+{
+	return SDL_TRUE;
+}
+void PSP_SDL_ShowScreenKeyboard(_THIS, SDL_Window *window)
+{
+}
+void PSP_SDL_HideScreenKeyboard(_THIS, SDL_Window *window)
+{
+}
+SDL_bool PSP_SDL_IsScreenKeyboardShown(_THIS, SDL_Window *window)
+{
+	return SDL_FALSE;
+}
+
+
+#endif /* SDL_VIDEO_DRIVER_PSP */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/psp/SDL_pspvideo.h	Sun Mar 17 20:07:02 2013 +0800
@@ -0,0 +1,102 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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_PANDORA_H__
+#define __SDL_PANDORA_H__
+
+#include <GLES/egl.h>
+
+#include "SDL_config.h"
+#include "../SDL_sysvideo.h"
+
+typedef struct SDL_VideoData
+{
+    SDL_bool egl_initialized;   /* OpenGL ES device initialization status */
+    uint32_t egl_refcount;      /* OpenGL ES reference count              */
+    
+
+
+} SDL_VideoData;
+
+
+typedef struct SDL_DisplayData
+{
+
+} SDL_DisplayData;
+
+
+typedef struct SDL_WindowData
+{
+    SDL_bool uses_gles;         /* if true window must support OpenGL ES */
+    
+} SDL_WindowData;
+
+
+
+
+/****************************************************************************/
+/* SDL_VideoDevice functions declaration                                    */
+/****************************************************************************/
+
+/* Display and window functions */
+int PSP_VideoInit(_THIS);
+void PSP_VideoQuit(_THIS);
+void PSP_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
+int PSP_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
+int PSP_CreateWindow(_THIS, SDL_Window * window);
+int PSP_CreateWindowFrom(_THIS, SDL_Window * window, const void *data);
+void PSP_SetWindowTitle(_THIS, SDL_Window * window);
+void PSP_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
+void PSP_SetWindowPosition(_THIS, SDL_Window * window);
+void PSP_SetWindowSize(_THIS, SDL_Window * window);
+void PSP_ShowWindow(_THIS, SDL_Window * window);
+void PSP_HideWindow(_THIS, SDL_Window * window);
+void PSP_RaiseWindow(_THIS, SDL_Window * window);
+void PSP_MaximizeWindow(_THIS, SDL_Window * window);
+void PSP_MinimizeWindow(_THIS, SDL_Window * window);
+void PSP_RestoreWindow(_THIS, SDL_Window * window);
+void PSP_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
+void PSP_DestroyWindow(_THIS, SDL_Window * window);
+
+/* Window manager function */
+SDL_bool PSP_GetWindowWMInfo(_THIS, SDL_Window * window,
+                             struct SDL_SysWMinfo *info);
+
+/* OpenGL/OpenGL ES functions */
+int PSP_GL_LoadLibrary(_THIS, const char *path);
+void *PSP_GL_GetProcAddress(_THIS, const char *proc);
+void PSP_GL_UnloadLibrary(_THIS);
+SDL_GLContext PSP_GL_CreateContext(_THIS, SDL_Window * window);
+int PSP_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
+int PSP_GL_SetSwapInterval(_THIS, int interval);
+int PSP_GL_GetSwapInterval(_THIS);
+void PSP_GL_SwapWindow(_THIS, SDL_Window * window);
+void PSP_GL_DeleteContext(_THIS, SDL_GLContext context);
+
+/*PSP on screen keyboard */
+SDL_bool PSP_SDL_HasScreenKeyboardSupport(_THIS);
+void PSP_SDL_ShowScreenKeyboard(_THIS, SDL_Window *window);
+void PSP_SDL_HideScreenKeyboard(_THIS, SDL_Window *window);
+SDL_bool PSP_SDL_IsScreenKeyboardShown(_THIS, SDL_Window *window);
+    
+#endif /* __SDL_PANDORA_H__ */
+
+/* vi: set ts=4 sw=4 expandtab: */