diff --git a/Makefile.ps2 b/Makefile.ps2
new file mode 100644
index 0000000000..cbd9a5c556
--- /dev/null
+++ b/Makefile.ps2
@@ -0,0 +1,105 @@
+BUILD_PRX = 0
+DEBUG = 1
+HAVE_KERNEL_PRX = 0
+HAVE_LOGGER = 0
+HAVE_FILE_LOGGER = 0
+HAVE_THREADS = 0
+BIG_STACK = 0
+WHOLE_ARCHIVE_LINK = 0
+PS2_IP = 192.168.1.150
+
+#Configuration for IRX
+EE_BIN2O = bin2o
+IRX_DIR = $(PS2SDK)/iop/irx
+
+TARGET = retroarchps2.elf
+
+ifeq ($(DEBUG), 1)
+ OPTIMIZE_LV := -O0 -g
+ RARCH_DEFINES += -DDEBUG
+else
+ OPTIMIZE_LV := -O2
+endif
+
+ifeq ($(WHOLE_ARCHIVE_LINK), 1)
+ WHOLE_START := -Wl,--whole-archive
+ WHOLE_END := -Wl,--no-whole-archive
+endif
+
+INCDIR = -I$(PS2SDK)/ports/include -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/iop/include -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include
+INCDIR += -Ips2 -Ips2/include -Ilibretro-common/include
+INCDIR += -Ideps -Ideps/stb -Ideps/libz -Ideps/7zip -Ideps/pthreads -Ideps/pthreads/platform/ps2 -Ideps/pthreads/platform/helper
+GPVAL = -G0
+CFLAGS = $(OPTIMIZE_LV) -ffast-math -fsingle-precision-constant
+ASFLAGS = $(CFLAGS)
+
+RARCH_DEFINES += -DPS2 -DUSE_IOP_CTYPE_MACRO -D_MIPS_ARCH_R5900 -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DWANT_ZLIB
+RARCH_DEFINES += -DHAVE_GRIFFIN=1 -DRARCH_INTERNAL -DRARCH_CONSOLE -DHAVE_MENU -DHAVE_RGUI -DHAVE_FILTERS_BUILTIN -DHAVE_7ZIP -DHAVE_CC_RESAMPLER
+
+LIBDIR =
+LDFLAGS = -L$(PS2SDK)/ports/lib -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ee/lib -L.
+#LIBS = $(WHOLE_START) -lretro_ps2 $(WHOLE_END) -lstdc++ -lm -lz -lgskit -ldmakit -lpng -laudsrv -lpad -lcdvd -lmad -lfileXio -lpatches
+LIBS += $(WHOLE_START) -lretro_ps2 $(WHOLE_END)
+LIBS += -lm -lg -lz -ldebug -lfileXio -laudsrv -lpatches -lpoweroff -ldma -lgskit -ldmakit -lpad -lsdl
+
+#IRX modules
+# IRX modules - modules have to be in IRX_DIR
+IRX = iomanX.irx fileXio.irx usbd.irx usbhdfsd.irx freesd.irx audsrv.irx poweroff.irx ps2dev9.irx ps2atad.irx ps2hdd.irx ps2fs.irx
+IRX_OBJ = $(IRX:.irx=.o)
+EE_OBJS += $(IRX_OBJ)
+
+ifeq ($(HAVE_THREADS), 1)
+RARCH_DEFINES += -DHAVE_THREADS
+endif
+
+ifeq ($(HAVE_FILE_LOGGER), 1)
+CFLAGS += -DHAVE_FILE_LOGGER
+endif
+
+ifeq ($(HAVE_KERNEL_PRX), 1)
+CFLAGS += -DHAVE_KERNEL_PRX
+endif
+
+ifeq ($(BIG_STACK), 1)
+CFLAGS += -DBIG_STACK
+endif
+
+CFLAGS += $(RARCH_DEFINES)
+
+# Missing objecst on the PS2SDK
+EE_OBJS += ps2/compat_ctype.o
+
+#EE_OBJS = griffin/griffin.o bootstrap/ps2/kernel_functions.o
+EE_OBJS += griffin/griffin.o
+
+EE_CFLAGS = $(CFLAGS)
+EE_LDFLAGS = $(LDFLAGS)
+EE_LIBS = $(LIBS)
+EE_ASFLAGS = $(ASFLAGS)
+EE_INCS = $(INCDIR)
+EE_IRX_OBJ = $(IRX_OBJ)
+EE_BIN = $(TARGET)
+EE_GPVAL = $(GPVAL)
+
+all: $(EE_IRX_OBJ) $(EE_BIN)
+
+clean:
+ rm -f $(EE_BIN) $(EE_OBJS)
+
+prepare:
+ ps2client -h $(PS2_IP) reset
+ ps2client -h $(PS2_IP) netdump
+
+run:
+ ps2client -h $(PS2_IP) execee host:$(EE_BIN)
+
+debug: clean prepare all run
+
+#Specific file name and output per IRX Module
+$(EE_IRX_OBJ):
+ $(EE_BIN2O) $(EE_GPVAL) $(IRX_DIR)/$(@:.o=.irx) $@ $(@:.o=_irx)
+
+#Include preferences
+include $(PS2SDK)/samples/Makefile.pref
+include $(PS2SDK)/samples/Makefile.eeglobal
+
\ No newline at end of file
diff --git a/audio/audio_driver.h b/audio/audio_driver.h
index 1d67fa0768..c90db9873c 100644
--- a/audio/audio_driver.h
+++ b/audio/audio_driver.h
@@ -335,6 +335,7 @@ extern audio_driver_t audio_ps3;
extern audio_driver_t audio_gx;
extern audio_driver_t audio_ax;
extern audio_driver_t audio_psp;
+extern audio_driver_t audio_ps2;
extern audio_driver_t audio_ctr_csnd;
extern audio_driver_t audio_ctr_dsp;
extern audio_driver_t audio_switch;
diff --git a/config.def.h b/config.def.h
index 80a10a7f61..2791384be9 100644
--- a/config.def.h
+++ b/config.def.h
@@ -188,7 +188,7 @@ static const bool video_threaded = false;
#endif
#if defined(HAVE_THREADS)
-#if defined(GEKKO) || defined(PSP)
+#if defined(GEKKO) || defined(PSP) || defined(PS2)
/* For single-core consoles right now it's better to have this be disabled. */
static const bool threaded_data_runloop_enable = false;
#else
@@ -731,7 +731,7 @@ static const bool desktop_menu_enable = true;
#if defined(__QNX__) || defined(_XBOX1) || defined(_XBOX360) || defined(__CELLOS_LV2__) || (defined(__MACH__) && defined(IOS)) || defined(ANDROID) || defined(WIIU) || defined(HAVE_NEON) || defined(GEKKO) || defined(__ARM_NEON__)
static enum resampler_quality audio_resampler_quality_level = RESAMPLER_QUALITY_LOWER;
-#elif defined(PSP) || defined(_3DS) || defined(VITA)
+#elif defined(PSP) || defined(_3DS) || defined(VITA) || defined(PS2)
static enum resampler_quality audio_resampler_quality_level = RESAMPLER_QUALITY_LOWEST;
#else
static enum resampler_quality audio_resampler_quality_level = RESAMPLER_QUALITY_NORMAL;
diff --git a/configuration.c b/configuration.c
index 0329a77778..65f6a70b7c 100644
--- a/configuration.c
+++ b/configuration.c
@@ -148,6 +148,7 @@ enum video_driver_enum
VIDEO_XENON360,
VIDEO_PSP1,
VIDEO_VITA2D,
+ VIDEO_PS2,
VIDEO_CTR,
VIDEO_SWITCH,
VIDEO_D3D8,
@@ -191,6 +192,7 @@ enum audio_driver_enum
AUDIO_WIIU,
AUDIO_RWEBAUDIO,
AUDIO_PSP,
+ AUDIO_PS2,
AUDIO_CTR,
AUDIO_SWITCH,
AUDIO_NULL
@@ -214,6 +216,7 @@ enum input_driver_enum
INPUT_DINPUT,
INPUT_PS3,
INPUT_PSP,
+ INPUT_PS2,
INPUT_CTR,
INPUT_SWITCH,
INPUT_XENON360,
@@ -237,6 +240,7 @@ enum joypad_driver_enum
JOYPAD_WIIU,
JOYPAD_XDK,
JOYPAD_PSP,
+ JOYPAD_PS2,
JOYPAD_CTR,
JOYPAD_SWITCH,
JOYPAD_DINPUT,
@@ -325,6 +329,8 @@ static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VG;
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VITA2D;
#elif defined(PSP)
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PSP1;
+#elif defined(PS2)
+static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PS2;
#elif defined(_3DS)
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_CTR;
#elif defined(SWITCH)
@@ -355,6 +361,8 @@ static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WII;
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WIIU;
#elif defined(PSP) || defined(VITA)
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PSP;
+#elif defined(PS2)
+static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PS2;
#elif defined(_3DS)
static enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_CTR;
#elif defined(SWITCH)
@@ -435,6 +443,8 @@ static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_DINPUT;
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS3;
#elif defined(PSP) || defined(VITA)
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PSP;
+#elif defined(PS2)
+static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS2;
#elif defined(_3DS)
static enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_CTR;
#elif defined(SWITCH)
@@ -477,6 +487,8 @@ static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_WIIU;
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_XDK;
#elif defined(PSP) || defined(VITA)
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PSP;
+#elif defined(PS2)
+static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS2;
#elif defined(_3DS)
static enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_CTR;
#elif defined(SWITCH)
@@ -663,6 +675,8 @@ const char *config_get_default_audio(void)
#else
return "psp";
#endif
+ case AUDIO_PS2:
+ return "ps2";
case AUDIO_CTR:
return "csnd";
case AUDIO_SWITCH:
@@ -758,6 +772,8 @@ const char *config_get_default_video(void)
return "d3d12";
case VIDEO_PSP1:
return "psp1";
+ case VIDEO_PS2:
+ return "ps2";
case VIDEO_VITA2D:
return "vita2d";
case VIDEO_CTR:
@@ -818,6 +834,8 @@ const char *config_get_default_input(void)
#else
return "psp";
#endif
+ case INPUT_PS2:
+ return "ps2";
case INPUT_CTR:
return "ctr";
case INPUT_SWITCH:
@@ -888,6 +906,8 @@ const char *config_get_default_joypad(void)
#else
return "psp";
#endif
+ case JOYPAD_PS2:
+ return "ps2";
case JOYPAD_CTR:
return "ctr";
case JOYPAD_SWITCH:
diff --git a/core_info.c b/core_info.c
index 18c8caf448..d7ea70ed91 100644
--- a/core_info.c
+++ b/core_info.c
@@ -205,7 +205,7 @@ static bool core_info_list_iterate(
current_path,
info_path_base_size);
-#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS) && !defined(VITA) && !defined(HW_WUP))
+#if defined(RARCH_MOBILE) || (defined(RARCH_CONSOLE) && !defined(PSP) && !defined(_3DS) && !defined(VITA) && !defined(PS2) && !defined(HW_WUP))
substr = strrchr(info_path_base, '_');
if (substr)
*substr = '\0';
diff --git a/frontend/drivers/platform_ps2.c b/frontend/drivers/platform_ps2.c
new file mode 100644
index 0000000000..93d389d889
--- /dev/null
+++ b/frontend/drivers/platform_ps2.c
@@ -0,0 +1,514 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ * * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+
+#include "../frontend_driver.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+enum BootDeviceIDs{
+ BOOT_DEVICE_UNKNOWN = -1,
+ BOOT_DEVICE_MC0 = 0,
+ BOOT_DEVICE_MC1,
+ BOOT_DEVICE_CDROM,
+ BOOT_DEVICE_MASS,
+ BOOT_DEVICE_HDD,
+ BOOT_DEVICE_HOST,
+
+ BOOT_DEVICE_COUNT,
+};
+
+extern unsigned char poweroff_irx_start[];
+extern unsigned int poweroff_irx_size;
+
+extern unsigned char ps2dev9_irx_start[];
+extern unsigned int ps2dev9_irx_size;
+
+extern unsigned char ps2atad_irx_start[];
+extern unsigned int ps2atad_irx_size;
+
+extern unsigned char ps2hdd_irx_start[];
+extern unsigned int ps2hdd_irx_size;
+
+extern unsigned char ps2fs_irx_start[];
+extern unsigned int ps2fs_irx_size;
+
+extern unsigned char iomanX_irx_start[];
+extern unsigned int iomanX_irx_size;
+
+extern unsigned char fileXio_irx_start[];
+extern unsigned int fileXio_irx_size;
+
+extern unsigned char freesd_irx_start[];
+extern unsigned int freesd_irx_size;
+
+extern unsigned char audsrv_irx_start[];
+extern unsigned int audsrv_irx_size;
+
+extern unsigned char usbd_irx_start[];
+extern unsigned int usbd_irx_size;
+
+extern unsigned char usbhdfsd_irx_start[];
+extern unsigned int usbhdfsd_irx_size;
+
+static unsigned char HDDModulesLoaded=0;
+
+char eboot_path[512];
+char user_path[512];
+
+static enum frontend_fork ps2_fork_mode = FRONTEND_FORK_NONE;
+
+//Only paths residing on "basic" devices (devices that don't require mounting)
+//can be specified here, since this system doesn't perform mounting based on the path.
+#define DEFAULT_PATH "mass:"
+
+static int getBootDeviceID(char *path) {
+ int result = BOOT_DEVICE_HOST;
+
+ if(!strncmp(path, "mc0:", 4)) result=BOOT_DEVICE_MC0;
+ else if(!strncmp(path, "mc1:", 4)) result=BOOT_DEVICE_MC1;
+ else if(!strncmp(path, "cdrom0:", 7)) result=BOOT_DEVICE_CDROM;
+ else if(!strncmp(path, "mass:", 5) || !strncmp(path, "mass0:", 6)) result=BOOT_DEVICE_MASS;
+ else if(!strncmp(path, "hdd:", 4) || !strncmp(path, "hdd0:", 5)) result=BOOT_DEVICE_HDD;
+ else if(!strncmp(path, "host", 4) && ((path[4]>='0' && path[4]<='9') || path[4]==':')) result=BOOT_DEVICE_HOST;
+ else result=BOOT_DEVICE_UNKNOWN;
+
+ return result;
+}
+
+//HACK! If booting from a USB device, keep trying to open this program again until it succeeds. This will ensure that the emulator will be able to load its files.
+static void waitUntilDeviceIsReady(const char *path) {
+ FILE *file;
+
+ while((file=fopen(path, "rb"))==NULL){
+ //Wait for a while first, or the IOP will get swamped by requests from the EE.
+ nopdelay();
+ nopdelay();
+ nopdelay();
+ nopdelay();
+ nopdelay();
+ nopdelay();
+ nopdelay();
+ nopdelay();
+ };
+
+ fclose(file);
+}
+
+void setPWDOnPFS(const char *FullCWD_path) {
+ int i;
+ char *path;
+
+ path=NULL;
+ for(i=strlen(FullCWD_path); i>=0; i--){ /* Try to seperate the CWD from the path to this ELF. */
+ if(FullCWD_path[i]==':'){
+ if((path=malloc(i+6+2))!=NULL){
+ strcpy(path, "pfs0:/");
+ strncat(path, FullCWD_path, i+1);
+ path[i+1+6]='\0';
+ }
+ break;
+ }
+ else if((FullCWD_path[i]=='\\')||(FullCWD_path[i]=='/')){
+ if((path=malloc(i+6+1))!=NULL){
+ strcpy(path, "pfs0:/");
+ strncat(path, FullCWD_path, i);
+ path[i+6]='\0';
+ }
+ break;
+ }
+ }
+
+ if(path!=NULL){
+ chdir(path);
+ free(path);
+ }
+}
+
+static const char *getMountParams(const char *command, char *BlockDevice) {
+ const char *MountPath;
+ int BlockDeviceNameLen;
+
+ MountPath=NULL;
+ if(strlen(command)>6 && (MountPath=strchr(&command[5], ':'))!=NULL){
+ BlockDeviceNameLen=(unsigned int)MountPath-(unsigned int)command;
+ strncpy(BlockDevice, command, BlockDeviceNameLen);
+ BlockDevice[BlockDeviceNameLen]='\0';
+
+ MountPath++; //This is the location of the mount path;
+ }
+
+ return MountPath;
+}
+
+static void create_path_names(void)
+{
+#ifndef IS_SALAMANDER
+#if defined(HAVE_LOGGER)
+
+#elif defined(HAVE_FILE_LOGGER)
+ retro_main_log_file_init("ux0:/temp/retroarch-log.txt"); // It really depend from where we are executing this
+#endif
+#endif
+
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE], g_defaults.dirs[DEFAULT_DIR_PORT],
+ "CORES", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE_INFO], g_defaults.dirs[DEFAULT_DIR_PORT],
+ "INFO", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE_INFO]));
+
+ /* user data */
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CHEATS], user_path,
+ "CHEATS", sizeof(g_defaults.dirs[DEFAULT_DIR_CHEATS]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG], user_path,
+ "CONFIG", sizeof(g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS], user_path,
+ "DOWNLOADS", sizeof(g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_PLAYLIST], user_path,
+ "PLAYLISTS", sizeof(g_defaults.dirs[DEFAULT_DIR_PLAYLIST]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_REMAP], g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG],
+ "REMAPS", sizeof(g_defaults.dirs[DEFAULT_DIR_REMAP]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SRAM], user_path,
+ "SAVEFILES", sizeof(g_defaults.dirs[DEFAULT_DIR_SRAM]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SAVESTATE], user_path,
+ "SAVESTATES", sizeof(g_defaults.dirs[DEFAULT_DIR_SAVESTATE]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SCREENSHOT], user_path,
+ "SCREENSHOTS", sizeof(g_defaults.dirs[DEFAULT_DIR_SCREENSHOT]));
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SYSTEM], user_path,
+ "SYSTEM", sizeof(g_defaults.dirs[DEFAULT_DIR_SYSTEM]));
+
+ /* cache dir */
+ fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_CACHE], user_path,
+ "TEMP", sizeof(g_defaults.dirs[DEFAULT_DIR_CACHE]));
+
+ /* history and main config */
+ strlcpy(g_defaults.dirs[DEFAULT_DIR_CONTENT_HISTORY],
+ user_path, sizeof(g_defaults.dirs[DEFAULT_DIR_CONTENT_HISTORY]));
+ fill_pathname_join(g_defaults.path.config, user_path,
+ file_path_str(FILE_PATH_MAIN_CONFIG), sizeof(g_defaults.path.config));
+}
+
+static void poweroffCallback(void *arg)
+{
+ //Close all files and unmount all partitions.
+ //close(fd);
+
+ //If you use PFS, close all files and unmount all partitions.
+ //fileXioDevctl("pfs:", PDIOC_CLOSEALL, NULL, 0, NULL, 0)
+
+ //Shut down DEV9, if you used it.
+ //while(fileXioDevctl("dev9x:", DDIOC_OFF, NULL, 0, NULL, 0) < 0){};
+
+ printf("Shutdown!");
+ poweroffShutdown();
+}
+
+static void frontend_ps2_get_environment_settings(int *argc, char *argv[],
+ void *args, void *params_data)
+{
+ char cwd[FILENAME_MAX], blockDevice[16];
+ const char *mountPoint;
+ int bootDeviceID;
+
+ //TODO: I DONT KNOW YET, WHY IT CRASHES IF UNCOMENT THIS PART
+ getcwd(cwd, sizeof(cwd));
+ bootDeviceID=getBootDeviceID(cwd);
+ //Mount the HDD partition, if required.
+ if(bootDeviceID==BOOT_DEVICE_HDD){
+ /* Try not to adjust this unless you know what you are doing. The tricky part i keeping the NULL character in the middle of that argument list separated from the number 4. */
+ static const char PS2HDD_args[]="-o\0""2";
+ static const char PS2FS_args[]="-o\0""8";
+
+ if(!HDDModulesLoaded){
+ SifExecModuleBuffer(poweroff_irx_start, poweroff_irx_size, 0, NULL, NULL);
+ SifExecModuleBuffer(ps2dev9_irx_start, ps2dev9_irx_size, 0, NULL, NULL);
+ SifExecModuleBuffer(ps2atad_irx_start, ps2atad_irx_size, 0, NULL, NULL);
+ SifExecModuleBuffer(ps2hdd_irx_start, ps2hdd_irx_size, sizeof(PS2HDD_args), PS2HDD_args, NULL);
+ SifExecModuleBuffer(ps2fs_irx_start, ps2fs_irx_size, sizeof(PS2FS_args), PS2FS_args, NULL);
+ HDDModulesLoaded=1;
+ }
+
+ //Attempt to mount the partition.
+ if((mountPoint=getMountParams(cwd, blockDevice))!=NULL && !strncmp(mountPoint, "pfs:", 4)){
+ fileXioMount("pfs0:", blockDevice, FIO_MT_RDWR);
+
+ setPWDOnPFS(&mountPoint[4]);
+ }
+ } else if(bootDeviceID==BOOT_DEVICE_CDROM){
+ chdir(DEFAULT_PATH);
+ } else if(bootDeviceID==BOOT_DEVICE_MASS){
+ waitUntilDeviceIsReady(argv[0]);
+ } else if (bootDeviceID==BOOT_DEVICE_UNKNOWN) {
+
+ }
+
+ create_path_names();
+
+#ifndef IS_SALAMANDER
+ if (!string_is_empty(argv[1]))
+ {
+ static char path[PATH_MAX_LENGTH] = {0};
+ struct rarch_main_wrap *args =
+ (struct rarch_main_wrap*)params_data;
+
+ if (args)
+ {
+ strlcpy(path, argv[1], sizeof(path));
+
+ args->touched = true;
+ args->no_content = false;
+ args->verbose = false;
+ args->config_path = NULL;
+ args->sram_path = NULL;
+ args->state_path = NULL;
+ args->content_path = path;
+ args->libretro_path = NULL;
+
+ RARCH_LOG("argv[0]: %s\n", argv[0]);
+ RARCH_LOG("argv[1]: %s\n", argv[1]);
+ RARCH_LOG("argv[2]: %s\n", argv[2]);
+
+ RARCH_LOG("Auto-start game %s.\n", argv[1]);
+ }
+ }
+#endif
+ int i;
+ for (i = 0; i < DEFAULT_DIR_LAST; i++)
+ {
+ const char *dir_path = g_defaults.dirs[i];
+ if (!string_is_empty(dir_path))
+ path_mkdir(dir_path);
+ }
+
+}
+
+static void frontend_ps2_init(void *data)
+{
+ SifInitRpc(0);
+#if !defined(DEBUG)
+ while(!SifIopReset(NULL, 0)){}; // Comment this line if you don't wanna debug the output
+#endif
+
+ while(!SifIopSync()){};
+ SifInitRpc(0);
+ sbv_patch_enable_lmb();
+
+ SifExecModuleBuffer(iomanX_irx_start, iomanX_irx_size, 0, NULL, NULL);
+ SifExecModuleBuffer(fileXio_irx_start, fileXio_irx_size, 0, NULL, NULL);
+
+ SifLoadModule("rom0:SIO2MAN", 0, NULL);
+ SifLoadModule("rom0:MCMAN", 0, NULL);
+ SifLoadModule("rom0:MCSERV", 0, NULL);
+ SifLoadModule("rom0:PADMAN", 0, NULL);
+
+ SifExecModuleBuffer(usbd_irx_start, usbd_irx_size, 0, NULL, NULL);
+ SifExecModuleBuffer(usbhdfsd_irx_start, usbhdfsd_irx_size, 0, NULL, NULL);
+ SifExecModuleBuffer(freesd_irx_start, freesd_irx_size, 0, NULL, NULL);
+ SifExecModuleBuffer(audsrv_irx_start, audsrv_irx_size, 0, NULL, NULL);
+
+ fileXioInit();
+ audsrv_init();
+
+ SDL_Init(SDL_INIT_TIMER);
+}
+
+static void frontend_ps2_deinit(void *data)
+{
+ (void)data;
+#ifndef IS_SALAMANDER
+ verbosity_disable();
+#ifdef HAVE_FILE_LOGGER
+ command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL);
+#endif
+
+#endif
+ fileXioUmount("pfs0:");
+ fileXioExit();
+
+ SifExitRpc();
+}
+
+static void frontend_ps2_exec(const char *path, bool should_load_game)
+{
+#if defined(IS_SALAMANDER)
+ char argp[512] = {0};
+ SceSize args = 0;
+
+ strlcpy(argp, eboot_path, sizeof(argp));
+ args = strlen(argp) + 1;
+
+#ifndef IS_SALAMANDER
+ if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT))
+ {
+ argp[args] = '\0';
+ strlcat(argp + args, path_get(RARCH_PATH_CONTENT), sizeof(argp) - args);
+ args += strlen(argp + args) + 1;
+ }
+#endif
+
+ RARCH_LOG("Attempt to load executable: [%s].\n", path);
+ // exitspawn_kernel(path, args, argp); // I don't know what this is doing
+#endif
+}
+
+#ifndef IS_SALAMANDER
+static bool frontend_ps2_set_fork(enum frontend_fork fork_mode)
+{
+ switch (fork_mode)
+ {
+ case FRONTEND_FORK_CORE:
+ RARCH_LOG("FRONTEND_FORK_CORE\n");
+ ps2_fork_mode = fork_mode;
+ break;
+ case FRONTEND_FORK_CORE_WITH_ARGS:
+ RARCH_LOG("FRONTEND_FORK_CORE_WITH_ARGS\n");
+ ps2_fork_mode = fork_mode;
+ break;
+ case FRONTEND_FORK_RESTART:
+ RARCH_LOG("FRONTEND_FORK_RESTART\n");
+ /* NOTE: We don't implement Salamander, so just turn
+ * this into FRONTEND_FORK_CORE. */
+ ps2_fork_mode = FRONTEND_FORK_CORE;
+ break;
+ case FRONTEND_FORK_NONE:
+ default:
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+static void frontend_ps2_exitspawn(char *core_path, size_t core_path_size)
+{
+ bool should_load_game = false;
+#ifndef IS_SALAMANDER
+ if (ps2_fork_mode == FRONTEND_FORK_NONE)
+ return;
+
+ switch (ps2_fork_mode)
+ {
+ case FRONTEND_FORK_CORE_WITH_ARGS:
+ should_load_game = true;
+ break;
+ case FRONTEND_FORK_NONE:
+ default:
+ break;
+ }
+#endif
+ frontend_ps2_exec(core_path, should_load_game);
+}
+
+static void frontend_ps2_shutdown(bool unused)
+{
+ poweroffInit();
+ //Set callback function
+ poweroffSetCallback(&poweroffCallback, NULL);
+}
+
+static int frontend_ps2_get_rating(void)
+{
+ return 10;
+}
+
+enum frontend_architecture frontend_ps2_get_architecture(void)
+{
+ return FRONTEND_ARCH_MIPS;
+}
+
+static int frontend_ps2_parse_drive_list(void *data, bool load_content)
+{
+#ifndef IS_SALAMANDER
+ file_list_t *list = (file_list_t*)data;
+ enum msg_hash_enums enum_idx = load_content ?
+ MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR :
+ MSG_UNKNOWN;
+
+ menu_entries_append_enum(list,
+ "mc0:/",
+ msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR),
+ enum_idx,
+ FILE_TYPE_DIRECTORY, 0, 0);
+ menu_entries_append_enum(list,
+ "mc1:/",
+ msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR),
+ enum_idx,
+ FILE_TYPE_DIRECTORY, 0, 0);
+ menu_entries_append_enum(list,
+ "mass:/",
+ msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR),
+ enum_idx,
+ FILE_TYPE_DIRECTORY, 0, 0);
+ menu_entries_append_enum(list,
+ "hdd0:/",
+ msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR),
+ enum_idx,
+ FILE_TYPE_DIRECTORY, 0, 0);
+ menu_entries_append_enum(list,
+ "host:/",
+ msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR),
+ enum_idx,
+ FILE_TYPE_DIRECTORY, 0, 0);
+#endif
+
+ return 0;
+}
+
+frontend_ctx_driver_t frontend_ctx_ps2 = {
+ frontend_ps2_get_environment_settings, /* environment_get */
+ frontend_ps2_init, /* init */
+ frontend_ps2_deinit, /* deinit */
+ frontend_ps2_exitspawn, /* exitspawn */
+ NULL, /* process_args */
+ frontend_ps2_exec, /* exec */
+ #ifdef IS_SALAMANDER
+ NULL, /* set_fork */
+#else
+ frontend_ps2_set_fork, /* set_fork */
+#endif
+ frontend_ps2_shutdown, /* shutdown */
+ NULL, /* get_name */
+ NULL, /* get_os */
+ frontend_ps2_get_rating, /* get_rating */
+ NULL, /* load_content */
+ frontend_ps2_get_architecture, /* get_architecture */
+ NULL, /* get_powerstate */
+ frontend_ps2_parse_drive_list, /* parse_drive_list */
+ NULL, /* get_mem_total */
+ NULL, /* get_mem_free */
+ NULL, /* install_signal_handler */
+ NULL, /* get_sighandler_state */
+ NULL, /* set_sighandler_state */
+ NULL, /* destroy_sighandler_state */
+ NULL, /* attach_console */
+ NULL, /* detach_console */
+#ifdef HAVE_LAKKA
+ NULL, /* get_lakka_version */
+#endif
+ NULL, /* watch_path_for_changes */
+ NULL, /* check_for_path_changes */
+ NULL, /* set_sustained_performance_mode */
+ "null",
+};
diff --git a/frontend/frontend_driver.c b/frontend/frontend_driver.c
index d846ed5928..b8ff69a442 100644
--- a/frontend/frontend_driver.c
+++ b/frontend/frontend_driver.c
@@ -56,6 +56,9 @@ static frontend_ctx_driver_t *frontend_ctx_drivers[] = {
#if defined(PSP) || defined(VITA)
&frontend_ctx_psp,
#endif
+#if defined(PS2)
+ &frontend_ctx_ps2,
+#endif
#if defined(_3DS)
&frontend_ctx_ctr,
#endif
@@ -141,6 +144,9 @@ bool frontend_driver_get_core_extension(char *s, size_t len)
#elif defined(VITA)
strlcpy(s, "self|bin", len);
return true;
+#elif defined(PS2)
+ strlcpy(s, "elf", len);
+ return true;
#elif defined(_XBOX1)
strlcpy(s, "xbe", len);
return true;
@@ -187,6 +193,9 @@ bool frontend_driver_get_salamander_basename(char *s, size_t len)
#elif defined(VITA)
strlcpy(s, "eboot.bin", len);
return true;
+#elif defined(PS2)
+ strlcpy(s, "eboot.elf", len);
+ return true;
#elif defined(_XBOX1)
strlcpy(s, "default.xbe", len);
return true;
diff --git a/frontend/frontend_driver.h b/frontend/frontend_driver.h
index c6092ad7ef..f5de976563 100644
--- a/frontend/frontend_driver.h
+++ b/frontend/frontend_driver.h
@@ -120,6 +120,7 @@ extern frontend_ctx_driver_t frontend_ctx_qnx;
extern frontend_ctx_driver_t frontend_ctx_darwin;
extern frontend_ctx_driver_t frontend_ctx_unix;
extern frontend_ctx_driver_t frontend_ctx_psp;
+extern frontend_ctx_driver_t frontend_ctx_ps2;
extern frontend_ctx_driver_t frontend_ctx_ctr;
extern frontend_ctx_driver_t frontend_ctx_switch;
extern frontend_ctx_driver_t frontend_ctx_win32;
diff --git a/gfx/drivers/ps2_gfx.c b/gfx/drivers/ps2_gfx.c
new file mode 100644
index 0000000000..cb921bbc68
--- /dev/null
+++ b/gfx/drivers/ps2_gfx.c
@@ -0,0 +1,424 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2018 - Francisco Javier Trujillo Mata
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include "../video_driver.h"
+
+#include "../../driver.h"
+#include "../../verbosity.h"
+
+#include
+#include
+#include
+#include
+
+#define GS_TEXT GS_SETREG_RGBAQ(0x80,0x80,0x80,0x80,0x00) // turn white GS Screen
+#define GS_BLACK GS_SETREG_RGBAQ(0x00,0x00,0x00,0x00,0x00) // turn white GS Screen
+
+typedef struct ps2_video
+{
+ GSGLOBAL *gsGlobal;
+ GSTEXTURE *menuTexture;
+ GSTEXTURE *coreTexture;
+
+ bool menuVisible;
+ bool fullscreen;
+
+ bool rgb32;
+ bool force_aspect;
+ int menu_filter;
+ int core_filter;
+} ps2_video_t;
+
+// PRIVATE METHODS
+static GSGLOBAL *init_GSGlobal(void) {
+ GSGLOBAL *gsGlobal = gsKit_init_global();
+
+ gsGlobal->PSM = GS_PSM_CT16;
+ gsGlobal->PSMZ = GS_PSMZ_16S;
+ gsGlobal->DoubleBuffering = GS_SETTING_OFF;
+ gsGlobal->ZBuffering = GS_SETTING_OFF;
+ gsGlobal->PrimAlphaEnable = GS_SETTING_OFF;
+
+ dmaKit_init(D_CTRL_RELE_OFF,D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC,
+ D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF);
+
+ // Initialize the DMAC
+ dmaKit_chan_init(DMA_CHANNEL_GIF);
+
+ gsKit_init_screen(gsGlobal);
+ gsKit_mode_switch(gsGlobal, GS_ONESHOT);
+
+ gsKit_clear(gsGlobal, GS_BLACK);
+
+ return gsGlobal;
+}
+
+static GSTEXTURE * prepare_new_texture(void) {
+ GSTEXTURE *texture = malloc(sizeof *texture);
+ texture->Width = 0;
+ texture->Height = 0;
+ texture->Mem = NULL;
+ return texture;
+}
+
+static void init_ps2_video(ps2_video_t *ps2) {
+ ps2->gsGlobal = init_GSGlobal();
+ ps2->menuTexture = prepare_new_texture();
+ ps2->coreTexture = prepare_new_texture();
+}
+
+static void deinitTexture(GSTEXTURE *texture) {
+ free(texture->Mem);
+ free(texture->Clut);
+ texture->Mem = NULL;
+ texture->Clut = NULL;
+}
+
+static void color_correction32(uint32_t *buffer, uint32_t dimensions)
+{
+ uint32_t i;
+ uint32_t x32;
+ for (i = 0; i < dimensions; i++) {
+ x32 = buffer[i];
+ buffer[i] = ((x32 >> 16) & 0xFF) | ((x32 << 16) & 0xFF0000) | (x32 & 0xFF00FF00);
+ }
+}
+
+static void color_correction16(uint16_t *buffer, uint32_t dimensions)
+{
+ uint32_t i;
+ uint16_t x16;
+ for (i = 0; i < dimensions; i++) {
+ x16 = buffer[i];
+ buffer[i] = (x16 & 0x8000) | ((x16 << 10) & 0x7C00) | (x16 & 0x3E0) | ((x16 >> 10) & 0x1F);
+ }
+}
+
+static void transfer_texture(GSTEXTURE *texture, const void *frame,
+ int width, int height, bool rgb32, int filter, bool color_correction) {
+
+ int PSM = rgb32 ? GS_PSM_CT32 : GS_PSM_CT16;
+ size_t size = gsKit_texture_size_ee(width, height, PSM);
+ if ( !texture->Mem ||
+ texture->Width != width ||
+ texture->Height != height ||
+ texture->PSM != PSM ) {
+ texture->Width = width;
+ texture->Height = height;
+ texture->PSM = PSM;
+ texture->Filter = filter;
+ free(texture->Mem);
+ texture->Mem = memalign(128, size);
+}
+
+if (color_correction) {
+ int pixels = width * height;
+ if (rgb32) {
+ uint32_t *buffer = (uint32_t *)frame;
+ color_correction32(buffer, pixels);
+ } else {
+ uint16_t *buffer = (uint16_t *)frame;
+ color_correction16(buffer, pixels);
+ }
+}
+
+ memcpy(texture->Mem, frame, size);
+}
+
+static void vram_alloc(GSGLOBAL *gsGlobal, GSTEXTURE *texture) {
+ uint32_t size = gsKit_texture_size(texture->Width, texture->Height, texture->PSM);
+ texture->Vram=gsKit_vram_alloc(gsGlobal, size, GSKIT_ALLOC_USERBUFFER);
+ if(texture->Vram == GSKIT_ALLOC_ERROR) {
+ printf("VRAM Allocation Failed. Will not upload texture.\n");
+ }
+}
+
+static void prim_texture(GSGLOBAL *gsGlobal, GSTEXTURE *texture, int zPosition, bool force_aspect) {
+ float x1, y1, x2, y2;
+ if (force_aspect) {
+ float delta = 1.0f;
+ float texture_aspect_ratio = texture->Width / texture->Height;
+ float gsGlobal_aspect_ratio = gsGlobal->Width / gsGlobal->Height;
+ if (texture_aspect_ratio < gsGlobal_aspect_ratio) {
+ //height
+ delta = gsGlobal->Height / texture->Height;
+ } else {
+ //width
+ delta = gsGlobal->Width / texture->Width;
+ }
+ float newWidth = texture->Width * delta;
+ float newHeight = texture->Height * delta;
+
+ x1 = (gsGlobal->Width - newWidth) / 2.0f;
+ y1 = (gsGlobal->Height - newHeight) / 2.0f;
+ x2 = newWidth + x1;
+ y2 = newHeight + y1;
+
+ } else {
+ x1 = 0.0f;
+ y1 = 0.0f;
+ x2 = gsGlobal->Width;
+ y2 = gsGlobal->Height;
+ }
+
+ gsKit_prim_sprite_texture( gsGlobal, texture,
+ x1, //X1
+ y1, // Y1
+ 0.0f, // U1
+ 0.0f, // V1
+ x2, // X2
+ y2, // Y2
+ texture->Width, // U2
+ texture->Height, // V2
+ zPosition,
+ GS_TEXT);
+}
+
+
+static void *ps2_gfx_init(const video_info_t *video,
+ const input_driver_t **input, void **input_data)
+{
+ void *ps2input = NULL;
+ *input_data = NULL;
+ (void)video;
+
+ ps2_video_t *ps2 = (ps2_video_t*)calloc(1, sizeof(ps2_video_t));
+
+ if (!ps2)
+ return NULL;
+
+ init_ps2_video(ps2);
+ ps2->rgb32 = video->rgb32;
+ ps2->fullscreen = video->fullscreen;
+ ps2->core_filter = video->smooth ? GS_FILTER_LINEAR : GS_FILTER_NEAREST;
+ ps2->force_aspect = video->force_aspect;
+
+ if (input && input_data)
+ {
+ settings_t *settings = config_get_ptr();
+ ps2input = input_ps2.init(settings->arrays.input_joypad_driver);
+ *input = ps2input ? &input_ps2 : NULL;
+ *input_data = ps2input;
+ }
+
+ return ps2;
+}
+
+static bool ps2_gfx_frame(void *data, const void *frame,
+ unsigned width, unsigned height, uint64_t frame_count,
+ unsigned pitch, const char *msg, video_frame_info_t *video_info)
+{
+#ifdef DISPLAY_FPS
+ uint32_t diff;
+ static uint64_t currentTick,lastTick;
+ static int frames;
+ static float fps = 0.0;
+#endif
+ ps2_video_t *ps2 = (ps2_video_t*)data;
+
+ if (!width || !height)
+ return false;
+
+ if (frame_count%120==0) {
+ printf("ps2_gfx_frame %i\n", frame_count);
+ }
+ gsKit_vram_clear(ps2->gsGlobal);
+
+ if (frame) {
+ transfer_texture(ps2->coreTexture, frame, width, height, ps2->rgb32, ps2->core_filter, 1);
+ vram_alloc(ps2->gsGlobal, ps2->coreTexture);
+ gsKit_texture_upload(ps2->gsGlobal, ps2->coreTexture);
+ prim_texture(ps2->gsGlobal, ps2->coreTexture, 1, ps2->force_aspect);
+ }
+
+ bool texture_empty = !ps2->menuTexture->Width || !ps2->menuTexture->Height;
+ if (ps2->menuVisible && !texture_empty) {
+ vram_alloc(ps2->gsGlobal, ps2->menuTexture);
+ gsKit_texture_upload(ps2->gsGlobal, ps2->menuTexture);
+ prim_texture(ps2->gsGlobal, ps2->menuTexture, 2, ps2->fullscreen);
+ }
+
+ gsKit_sync_flip(ps2->gsGlobal);
+ gsKit_queue_exec(ps2->gsGlobal);
+
+ return true;
+}
+
+static void ps2_gfx_set_nonblock_state(void *data, bool toggle)
+{
+ (void)data;
+ (void)toggle;
+}
+
+static bool ps2_gfx_alive(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static bool ps2_gfx_focus(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static bool ps2_gfx_suppress_screensaver(void *data, bool enable)
+{
+ (void)data;
+ (void)enable;
+ return false;
+}
+
+static bool ps2_gfx_has_windowed(void *data)
+{
+ (void)data;
+ return true;
+}
+
+static void ps2_gfx_free(void *data)
+{
+ ps2_video_t *ps2 = (ps2_video_t*)data;
+
+ gsKit_clear(ps2->gsGlobal, GS_BLACK);
+ gsKit_vram_clear(ps2->gsGlobal);
+
+ deinitTexture(ps2->menuTexture);
+ deinitTexture(ps2->coreTexture);
+
+ gsKit_deinit_global(ps2->gsGlobal);
+
+ free(data);
+}
+
+static bool ps2_gfx_set_shader(void *data,
+ enum rarch_shader_type type, const char *path)
+{
+ (void)data;
+ (void)type;
+ (void)path;
+
+ return false;
+}
+
+static void ps2_gfx_set_rotation(void *data,
+ unsigned rotation)
+{
+ (void)data;
+ (void)rotation;
+}
+
+static void ps2_gfx_viewport_info(void *data,
+ struct video_viewport *vp)
+{
+ (void)data;
+ (void)vp;
+}
+
+static bool ps2_gfx_read_viewport(void *data, uint8_t *buffer, bool is_idle)
+{
+ (void)data;
+ (void)buffer;
+
+ return true;
+}
+
+static void ps2_set_filtering(void *data, unsigned index, bool smooth)
+{
+ ps2_video_t *ps2 = (ps2_video_t*)data;
+
+ ps2->menu_filter = smooth ? GS_FILTER_LINEAR : GS_FILTER_NEAREST;
+}
+
+static void ps2_set_aspect_ratio(void *data, unsigned aspect_ratio_idx)
+{
+ ps2_video_t *ps2 = (ps2_video_t*)data;
+}
+
+static void ps2_apply_state_changes(void *data)
+{
+ ps2_video_t *ps2 = (ps2_video_t*)data;
+}
+
+static void ps2_set_texture_frame(void *data, const void *frame, bool rgb32,
+ unsigned width, unsigned height, float alpha)
+{
+ ps2_video_t *ps2 = (ps2_video_t*)data;
+
+ transfer_texture(ps2->menuTexture, frame, width, height, rgb32, ps2->menu_filter, 0);
+}
+
+static void ps2_set_texture_enable(void *data, bool enable, bool fullscreen)
+{
+ ps2_video_t *ps2 = (ps2_video_t*)data;
+ ps2->menuVisible = enable;
+ ps2->fullscreen = fullscreen;
+}
+
+static const video_poke_interface_t ps2_poke_interface = {
+ NULL, /* get_flags */
+ NULL, /* set_coords */
+ NULL, /* set_mvp */
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* get_refresh_rate */
+ ps2_set_filtering,
+ NULL, /* get_video_output_size */
+ NULL, /* get_video_output_prev */
+ NULL, /* get_video_output_next */
+ NULL, /* get_current_framebuffer */
+ NULL, /* get_proc_address */
+ ps2_set_aspect_ratio,
+ ps2_apply_state_changes,
+ ps2_set_texture_frame,
+ ps2_set_texture_enable,
+ NULL, /* set_osd_msg */
+ NULL, /* show_mouse */
+ NULL, /* grab_mouse_toggle */
+ NULL, /* get_current_shader */
+ NULL, /* get_current_software_framebuffer */
+ NULL /* get_hw_render_interface */
+};
+
+
+static void ps2_gfx_get_poke_interface(void *data,
+ const video_poke_interface_t **iface)
+{
+ (void)data;
+ *iface = &ps2_poke_interface;
+}
+
+video_driver_t video_ps2 = {
+ ps2_gfx_init,
+ ps2_gfx_frame,
+ ps2_gfx_set_nonblock_state,
+ ps2_gfx_alive,
+ ps2_gfx_focus,
+ ps2_gfx_suppress_screensaver,
+ ps2_gfx_has_windowed,
+ ps2_gfx_set_shader,
+ ps2_gfx_free,
+ "ps2",
+ NULL, /* set_viewport */
+ ps2_gfx_set_rotation,
+ ps2_gfx_viewport_info,
+ ps2_gfx_read_viewport,
+ NULL, /* read_frame_raw */
+
+#ifdef HAVE_OVERLAY
+ NULL, /* overlay_interface */
+#endif
+ ps2_gfx_get_poke_interface,
+};
diff --git a/gfx/video_driver.c b/gfx/video_driver.c
index 07d6ffea55..75f2f46bfb 100644
--- a/gfx/video_driver.c
+++ b/gfx/video_driver.c
@@ -295,6 +295,9 @@ static const video_driver_t *video_drivers[] = {
#ifdef PSP
&video_psp1,
#endif
+#ifdef PS2
+ &video_ps2,
+#endif
#ifdef _3DS
&video_ctr,
#endif
diff --git a/gfx/video_driver.h b/gfx/video_driver.h
index 4c151afbbb..3a261ebdb8 100644
--- a/gfx/video_driver.h
+++ b/gfx/video_driver.h
@@ -1251,6 +1251,7 @@ extern video_driver_t video_vulkan;
extern video_driver_t video_metal;
extern video_driver_t video_psp1;
extern video_driver_t video_vita2d;
+extern video_driver_t video_ps2;
extern video_driver_t video_ctr;
extern video_driver_t video_switch;
extern video_driver_t video_d3d8;
diff --git a/griffin/griffin.c b/griffin/griffin.c
index f84450d833..d2b8b5dedc 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -438,6 +438,8 @@ VIDEO DRIVER
#include "../gfx/drivers/gx_gfx.c"
#elif defined(PSP)
#include "../gfx/drivers/psp1_gfx.c"
+#elif defined(PS2)
+#include "../gfx/drivers/ps2_gfx.c"
#elif defined(HAVE_VITA2D)
#include "../deps/libvita2d/source/vita2d.c"
#include "../deps/libvita2d/source/vita2d_texture.c"
@@ -567,6 +569,9 @@ INPUT
#elif defined(SN_TARGET_PSP2) || defined(PSP) || defined(VITA)
#include "../input/drivers/psp_input.c"
#include "../input/drivers_joypad/psp_joypad.c"
+#elif defined(PS2)
+#include "../input/drivers/ps2_input.c"
+#include "../input/drivers_joypad/ps2_joypad.c"
#elif defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL)
#include "../input/drivers/cocoa_input.c"
#elif defined(_3DS)
@@ -764,6 +769,8 @@ AUDIO
#include "../audio/drivers/rwebaudio.c"
#elif defined(PSP) || defined(VITA)
#include "../audio/drivers/psp_audio.c"
+#elif defined(PS2)
+// #include "../audio/drivers/ps2_audio.c"
#elif defined(_3DS)
#include "../audio/drivers/ctr_csnd_audio.c"
#include "../audio/drivers/ctr_dsp_audio.c"
@@ -959,6 +966,8 @@ FRONTEND
#include "../frontend/drivers/platform_wiiu.c"
#elif defined(PSP) || defined(VITA)
#include "../frontend/drivers/platform_psp.c"
+#elif defined(PS2)
+#include "../frontend/drivers/platform_ps2.c"
#elif defined(_3DS)
#include "../frontend/drivers/platform_ctr.c"
#elif defined(SWITCH) && defined(HAVE_LIBNX)
diff --git a/input/drivers/ps2_input.c b/input/drivers/ps2_input.c
new file mode 100644
index 0000000000..6942c700f9
--- /dev/null
+++ b/input/drivers/ps2_input.c
@@ -0,0 +1,152 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+#include
+
+#ifdef HAVE_CONFIG_H
+#include "../../config.h"
+#endif
+
+#include
+
+#include
+#include
+#include
+
+#include "../input_driver.h"
+
+typedef struct ps2_input
+{
+ bool blocked;
+ const input_device_driver_t *joypad;
+} ps2_input_t;
+
+static void ps2_input_poll(void *data)
+{
+ ps2_input_t *ps2 = (ps2_input_t*)data;
+
+ if (ps2 && ps2->joypad)
+ ps2->joypad->poll();
+}
+
+static int16_t ps2_input_state(void *data,
+ rarch_joypad_info_t joypad_info,
+ const struct retro_keybind **binds,
+ unsigned port, unsigned device,
+ unsigned idx, unsigned id)
+{
+ ps2_input_t *ps2 = (ps2_input_t*)data;
+
+ switch (device)
+ {
+ case RETRO_DEVICE_JOYPAD:
+ return input_joypad_pressed(ps2->joypad, joypad_info, port, binds[port], id);
+ case RETRO_DEVICE_ANALOG:
+ if (binds[port])
+ return input_joypad_analog(ps2->joypad, joypad_info, port, idx, id, binds[port]);
+ break;
+ }
+
+ return 0;
+}
+
+static void ps2_input_free_input(void *data)
+{
+ ps2_input_t *ps2 = (ps2_input_t*)data;
+
+ if (ps2 && ps2->joypad)
+ ps2->joypad->destroy();
+
+ free(data);
+}
+
+static void* ps2_input_initialize(const char *joypad_driver)
+{
+ ps2_input_t *ps2 = (ps2_input_t*)calloc(1, sizeof(*ps2));
+ if (!ps2)
+ return NULL;
+
+ ps2->joypad = input_joypad_init_driver(joypad_driver, ps2);
+
+ return ps2;
+}
+
+static uint64_t ps2_input_get_capabilities(void *data)
+{
+ (void)data;
+
+ return (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG);
+}
+
+static const input_device_driver_t *ps2_input_get_joypad_driver(void *data)
+{
+ ps2_input_t *ps2 = (ps2_input_t*)data;
+ if (ps2)
+ return ps2->joypad;
+ return NULL;
+}
+
+static void ps2_input_grab_mouse(void *data, bool state)
+{
+ (void)data;
+ (void)state;
+}
+
+static bool ps2_input_set_rumble(void *data, unsigned port,
+ enum retro_rumble_effect effect, uint16_t strength)
+{
+ ps2_input_t *ps2 = (ps2_input_t*)data;
+
+ if (ps2 && ps2->joypad)
+ return input_joypad_set_rumble(ps2->joypad,
+ port, effect, strength);
+ return false;
+}
+
+static bool ps2_input_keyboard_mapping_is_blocked(void *data)
+{
+ ps2_input_t *ps2 = (ps2_input_t*)data;
+ if (!ps2)
+ return false;
+ return ps2->blocked;
+}
+
+static void ps2_input_keyboard_mapping_set_block(void *data, bool value)
+{
+ ps2_input_t *ps2 = (ps2_input_t*)data;
+ if (!ps2)
+ return;
+ ps2->blocked = value;
+}
+
+input_driver_t input_ps2 = {
+ ps2_input_initialize,
+ ps2_input_poll,
+ ps2_input_state,
+ ps2_input_free_input,
+ NULL,
+ NULL,
+ ps2_input_get_capabilities,
+ "ps2",
+ ps2_input_grab_mouse,
+ NULL,
+ ps2_input_set_rumble,
+ ps2_input_get_joypad_driver,
+ NULL,
+ ps2_input_keyboard_mapping_is_blocked,
+ ps2_input_keyboard_mapping_set_block,
+};
diff --git a/input/drivers_joypad/ps2_joypad.c b/input/drivers_joypad/ps2_joypad.c
new file mode 100644
index 0000000000..969c075ebe
--- /dev/null
+++ b/input/drivers_joypad/ps2_joypad.c
@@ -0,0 +1,167 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ * Copyright (C) 2013-2014 - CatalystG
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include
+#include
+#include
+
+#include "../input_driver.h"
+
+#include "libpad.h"
+
+#define PS2_MAX_PADS 1
+
+/*
+ * Global var's
+ */
+// pad_dma_buf is provided by the user, one buf for each pad
+// contains the pad's current state
+static char padBuf[256] __attribute__((aligned(64)));
+
+static uint64_t pad_state[PS2_MAX_PADS];
+
+
+static const char *ps2_joypad_name(unsigned pad)
+{
+ return "PS2 Controller";
+}
+
+static bool ps2_joypad_init(void *data)
+{
+ unsigned i;
+ unsigned players_count = PS2_MAX_PADS;
+
+ for (i = 0; i < players_count; i++)
+ {
+ bool auto_configure = input_autoconfigure_connect( ps2_joypad_name(i),
+ NULL,
+ ps2_joypad.ident,
+ i,
+ 0,
+ 0);
+ if (!auto_configure) {
+ input_config_set_device_name(i, ps2_joypad_name(i));
+ }
+
+ padInit(i);
+
+ int ret;
+ int port, slot;
+
+ port = 0; // 0 -> Connector 1, 1 -> Connector 2
+ slot = 0; // Always zero if not using multitap
+
+ printf("PortMax: %d\n", padGetPortMax());
+ printf("SlotMax: %d\n", padGetSlotMax(port));
+
+
+ if((ret = padPortOpen(port, slot, padBuf)) == 0) {
+ printf("padOpenPort failed: %d\n", ret);
+ }
+
+
+ }
+
+ return true;
+}
+
+static bool ps2_joypad_button(unsigned port_num, uint16_t joykey)
+{
+ if (port_num >= PS2_MAX_PADS)
+ return false;
+
+ return (pad_state[port_num] & (UINT64_C(1) << joykey));
+}
+
+static void ps2_joypad_get_buttons(unsigned port_num, input_bits_t *state)
+{
+ BIT256_CLEAR_ALL_PTR(state);
+}
+
+static int16_t ps2_joypad_axis(unsigned port_num, uint32_t joyaxis)
+{
+ return 0;
+}
+
+static void ps2_joypad_poll(void)
+{
+ unsigned player;
+ unsigned players_count = PS2_MAX_PADS;
+ struct padButtonStatus buttons;
+
+ for (player = 0; player < players_count; player++)
+ {
+ unsigned j, k;
+ unsigned i = player;
+ unsigned p = player;
+
+ int ret = padRead(player, player, &buttons); // port, slot, buttons
+ if (ret != 0)
+ {
+ int32_t state_tmp = 0xffff ^ buttons.btns;
+
+ pad_state[i] = 0;
+
+ pad_state[i] |= (state_tmp & PAD_LEFT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
+ pad_state[i] |= (state_tmp & PAD_DOWN) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
+ pad_state[i] |= (state_tmp & PAD_RIGHT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
+ pad_state[i] |= (state_tmp & PAD_UP) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
+ pad_state[i] |= (state_tmp & PAD_START) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START) : 0;
+ pad_state[i] |= (state_tmp & PAD_SELECT) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0;
+ pad_state[i] |= (state_tmp & PAD_TRIANGLE) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_X) : 0;
+ pad_state[i] |= (state_tmp & PAD_SQUARE) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y) : 0;
+ pad_state[i] |= (state_tmp & PAD_CROSS) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B) : 0;
+ pad_state[i] |= (state_tmp & PAD_CIRCLE) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A) : 0;
+ pad_state[i] |= (state_tmp & PAD_R1) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R) : 0;
+ pad_state[i] |= (state_tmp & PAD_L1) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L) : 0;
+ pad_state[i] |= (state_tmp & PAD_R2) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R2) : 0;
+ pad_state[i] |= (state_tmp & PAD_L2) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L2) : 0;
+ pad_state[i] |= (state_tmp & PAD_R3) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R3) : 0;
+ pad_state[i] |= (state_tmp & PAD_L3) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L3) : 0;
+ }
+ }
+
+}
+
+static bool ps2_joypad_query_pad(unsigned pad)
+{
+ return pad < PS2_MAX_PADS && pad_state[pad];
+}
+
+static bool ps2_joypad_rumble(unsigned pad,
+ enum retro_rumble_effect effect, uint16_t strength)
+{
+ return false;
+}
+
+
+static void ps2_joypad_destroy(void)
+{
+}
+
+input_device_driver_t ps2_joypad = {
+ ps2_joypad_init,
+ ps2_joypad_query_pad,
+ ps2_joypad_destroy,
+ ps2_joypad_button,
+ ps2_joypad_get_buttons,
+ ps2_joypad_axis,
+ ps2_joypad_poll,
+ ps2_joypad_rumble,
+ ps2_joypad_name,
+ "ps2",
+};
diff --git a/input/drivers_joypad/ps2_joypad_copy.c b/input/drivers_joypad/ps2_joypad_copy.c
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c
index df74a8627f..98d9e3405d 100644
--- a/input/input_autodetect_builtin.c
+++ b/input/input_autodetect_builtin.c
@@ -178,6 +178,32 @@ DECL_AXIS_EX(r_x_minus, -2, "R-Stick left") \
DECL_AXIS_EX(r_y_plus, +3, "R-Stick down") \
DECL_AXIS_EX(r_y_minus, -3, "R-Stick up")
+#define PS2INPUT_DEFAULT_BINDS \
+DECL_BTN_EX(a, 8, "Circle") \
+DECL_BTN_EX(b, 0, "Cross") \
+DECL_BTN_EX(x, 9, "Triangle") \
+DECL_BTN_EX(y, 1, "Square") \
+DECL_BTN_EX(start, 3, "Start") \
+DECL_BTN_EX(select, 2, "Select") \
+DECL_BTN_EX(up, 4, "D-Pad up") \
+DECL_BTN_EX(down, 5, "D-Pad down") \
+DECL_BTN_EX(left, 6, "D-Pad left") \
+DECL_BTN_EX(right, 7, "D-Pad right") \
+DECL_BTN_EX(l, 10, "L1") \
+DECL_BTN_EX(r, 11, "R1") \
+DECL_BTN_EX(l2, 12, "L2") \
+DECL_BTN_EX(r2, 13, "R2") \
+DECL_BTN_EX(l3, 14, "L3") \
+DECL_BTN_EX(r3, 15, "R3") \
+DECL_AXIS_EX(l_x_plus, +0, "L-Stick right") \
+DECL_AXIS_EX(l_x_minus, -0, "L-Stick left") \
+DECL_AXIS_EX(l_y_plus, +1, "L-Stick down") \
+DECL_AXIS_EX(l_y_minus, -1, "L-Stick up") \
+DECL_AXIS_EX(r_x_plus, +2, "R-Stick right") \
+DECL_AXIS_EX(r_x_minus, -2, "R-Stick left") \
+DECL_AXIS_EX(r_y_plus, +3, "R-Stick down") \
+DECL_AXIS_EX(r_y_minus, -3, "R-Stick up")
+
#define CTRINPUT_DEFAULT_BINDS \
DECL_BTN(a, 8) \
DECL_BTN(b, 0) \
@@ -641,6 +667,9 @@ const char* const input_builtin_autoconfs[] =
#elif defined(PSP)
DECL_AUTOCONF_DEVICE("PSP Controller", "psp", PSPINPUT_DEFAULT_BINDS),
#endif
+#if defined(PS2)
+ DECL_AUTOCONF_DEVICE("PS2 Controller", "ps2", PS2INPUT_DEFAULT_BINDS),
+#endif
#ifdef _3DS
DECL_AUTOCONF_DEVICE("3DS Controller", "ctr", CTRINPUT_DEFAULT_BINDS),
#endif
diff --git a/input/input_driver.c b/input/input_driver.c
index 4a6a6fb8b5..2e264c7159 100644
--- a/input/input_driver.c
+++ b/input/input_driver.c
@@ -86,6 +86,9 @@ static const input_driver_t *input_drivers[] = {
#if defined(SN_TARGET_PSP2) || defined(PSP) || defined(VITA)
&input_psp,
#endif
+#if defined(PS2)
+ &input_ps2,
+#endif
#if defined(_3DS)
&input_ctr,
#endif
@@ -161,6 +164,9 @@ static input_device_driver_t *joypad_drivers[] = {
#if defined(PSP) || defined(VITA)
&psp_joypad,
#endif
+#if defined(PS2)
+ &ps2_joypad,
+#endif
#ifdef _3DS
&ctr_joypad,
#endif
diff --git a/input/input_driver.h b/input/input_driver.h
index 6c5b4f1a0f..b3169021ec 100644
--- a/input/input_driver.h
+++ b/input/input_driver.h
@@ -806,6 +806,7 @@ extern input_device_driver_t xinput_joypad;
extern input_device_driver_t sdl_joypad;
extern input_device_driver_t ps3_joypad;
extern input_device_driver_t psp_joypad;
+extern input_device_driver_t ps2_joypad;
extern input_device_driver_t ctr_joypad;
extern input_device_driver_t switch_joypad;
extern input_device_driver_t xdk_joypad;
@@ -825,6 +826,7 @@ extern input_driver_t input_dinput;
extern input_driver_t input_x;
extern input_driver_t input_ps3;
extern input_driver_t input_psp;
+extern input_driver_t input_ps2;
extern input_driver_t input_ctr;
extern input_driver_t input_switch;
extern input_driver_t input_xenon360;
diff --git a/libretro-common/features/features_cpu.c b/libretro-common/features/features_cpu.c
index fdefe92714..1a04ce07c5 100644
--- a/libretro-common/features/features_cpu.c
+++ b/libretro-common/features/features_cpu.c
@@ -65,6 +65,12 @@
#include
#endif
+#if defined(PS2)
+#include
+#include
+#include
+#endif
+
#if defined(__PSL1GHT__)
#include
#elif defined(__CELLOS_LV2__)
@@ -184,6 +190,8 @@ retro_perf_tick_t cpu_features_get_perf_counter(void)
sceRtcGetCurrentTick((uint64_t*)&time_ticks);
#elif defined(VITA)
sceRtcGetCurrentTick((SceRtcTick*)&time_ticks);
+#elif defined(PS2)
+ time_ticks = SDL_GetTicks()*294912; // 294,912MHZ / 1000 msecs
#elif defined(_3DS)
time_ticks = svcGetSystemTick();
#elif defined(WIIU)
@@ -232,6 +240,8 @@ retro_time_t cpu_features_get_time_usec(void)
return tv.tv_sec * INT64_C(1000000) + (tv.tv_nsec + 500) / 1000;
#elif defined(EMSCRIPTEN)
return emscripten_get_now() * 1000;
+#elif defined(PS2)
+ return SDL_GetTicks()*1000;
#elif defined(__mips__) || defined(DJGPP)
struct timeval tv;
gettimeofday(&tv,NULL);
@@ -479,7 +489,7 @@ unsigned cpu_features_get_core_amount(void)
return sysinfo.dwNumberOfProcessors;
#elif defined(GEKKO)
return 1;
-#elif defined(PSP)
+#elif defined(PSP) || defined(PS2)
return 1;
#elif defined(VITA)
return 4;
@@ -787,7 +797,7 @@ uint64_t cpu_features_get(void)
cpu |= RETRO_SIMD_VMX;
#elif defined(XBOX360)
cpu |= RETRO_SIMD_VMX128;
-#elif defined(PSP)
+#elif defined(PSP) || defined(PS2)
cpu |= RETRO_SIMD_VFPU;
#elif defined(GEKKO)
cpu |= RETRO_SIMD_PS;
diff --git a/libretro-common/file/file_path.c b/libretro-common/file/file_path.c
index 2e90537210..1e910f4ec1 100644
--- a/libretro-common/file/file_path.c
+++ b/libretro-common/file/file_path.c
@@ -79,6 +79,11 @@
#include
#endif
+#if defined(PS2)
+#include
+#include
+#endif
+
#if defined(__CELLOS_LV2__)
#include
#endif
@@ -122,7 +127,19 @@ static bool path_stat(const char *path, enum stat_mode mode, int32_t *size)
return false;
}
free(tmp);
+#elif defined(PS2)
+ iox_stat_t buf;
+ char *tmp = strdup(path);
+ size_t len = strlen(tmp);
+ if (tmp[len-1] == '/')
+ tmp[len-1]='\0';
+ if (fileXioGetStat(tmp, &buf) < 0)
+ {
+ free(tmp);
+ return false;
+ }
+ free(tmp);
#elif defined(__CELLOS_LV2__)
CellFsStat buf;
if (cellFsStat(path, &buf) < 0)
@@ -167,13 +184,18 @@ static bool path_stat(const char *path, enum stat_mode mode, int32_t *size)
#endif
if (size)
+#if defined(PS2)
+ *size = (int32_t)buf.size;
+#else
*size = (int32_t)buf.st_size;
-
+#endif
switch (mode)
{
case IS_DIRECTORY:
#if defined(VITA) || defined(PSP)
return FIO_S_ISDIR(buf.st_mode);
+#elif defined(PS2)
+ return FIO_S_ISDIR(buf.mode);
#elif defined(__CELLOS_LV2__)
return ((buf.st_mode & S_IFMT) == S_IFDIR);
#elif defined(_WIN32)
@@ -182,7 +204,7 @@ static bool path_stat(const char *path, enum stat_mode mode, int32_t *size)
return S_ISDIR(buf.st_mode);
#endif
case IS_CHARACTER_SPECIAL:
-#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(_WIN32)
+#if defined(VITA) || defined(PSP) || defined(PS2) || defined(__CELLOS_LV2__) || defined(_WIN32)
return false;
#else
return S_ISCHR(buf.st_mode);
@@ -230,7 +252,7 @@ static bool path_mkdir_error(int ret)
{
#if defined(VITA)
return (ret == SCE_ERROR_ERRNO_EEXIST);
-#elif defined(PSP) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
+#elif defined(PSP) || defined(PS2) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
return (ret == -1);
#else
return (ret < 0 && errno == EEXIST);
@@ -299,6 +321,8 @@ bool path_mkdir(const char *dir)
int ret = mkdir(dir, 0755);
#elif defined(VITA) || defined(PSP)
int ret = sceIoMkdir(dir, 0777);
+#elif defined(PS2)
+ int ret =fileXioMkdir(dir, 0777);
#elif defined(__QNX__)
int ret = mkdir(dir, 0777);
#else
diff --git a/libretro-common/file/retro_dirent.c b/libretro-common/file/retro_dirent.c
index 0b6ecad246..561c1b055a 100644
--- a/libretro-common/file/retro_dirent.c
+++ b/libretro-common/file/retro_dirent.c
@@ -49,11 +49,14 @@
#elif defined(VITA)
# include
# include
-#include
+# include
#else
# if defined(PSP)
# include
# endif
+# if defined(PS2)
+# include
+# endif
# include
# include
# include
@@ -64,7 +67,7 @@
#include
#endif
-#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP)
+#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) || defined(PS2)
#include /* stat() is defined here */
#endif
@@ -88,6 +91,9 @@ struct RDIR
#elif defined(VITA) || defined(PSP)
SceUID directory;
SceIoDirent entry;
+#elif defined(PS2)
+ int directory;
+ iox_dirent_t entry;
#elif defined(__CELLOS_LV2__)
CellFsErrno error;
int directory;
@@ -146,6 +152,8 @@ struct RDIR *retro_opendir(const char *name)
#elif defined(VITA) || defined(PSP)
rdir->directory = sceIoDopen(name);
+#elif defined(PS2)
+ rdir->directory = fileXioDopen(name);
#elif defined(_3DS)
rdir->directory = !string_is_empty(name) ? opendir(name) : NULL;
rdir->entry = NULL;
@@ -167,7 +175,7 @@ bool retro_dirent_error(struct RDIR *rdir)
{
#if defined(_WIN32)
return (rdir->directory == INVALID_HANDLE_VALUE);
-#elif defined(VITA) || defined(PSP)
+#elif defined(VITA) || defined(PSP) || defined(PS2)
return (rdir->directory < 0);
#elif defined(__CELLOS_LV2__)
return (rdir->error != CELL_FS_SUCCEEDED);
@@ -190,6 +198,11 @@ int retro_readdir(struct RDIR *rdir)
return (rdir->directory != INVALID_HANDLE_VALUE);
#elif defined(VITA) || defined(PSP)
return (sceIoDread(rdir->directory, &rdir->entry) > 0);
+#elif defined(PS2)
+ iox_dirent_t record;
+ int ret = fileXioDread(rdir->directory, &record);
+ rdir->entry = record;
+ return ( ret > 0);
#elif defined(__CELLOS_LV2__)
uint64_t nread;
rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread);
@@ -220,6 +233,8 @@ const char *retro_dirent_get_name(struct RDIR *rdir)
return (char*)rdir->entry.cFileName;
#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__)
return rdir->entry.d_name;
+#elif defined(PS2)
+ return rdir->entry.name;
#else
return rdir->entry->d_name;
@@ -249,6 +264,9 @@ bool retro_dirent_is_dir(struct RDIR *rdir, const char *path)
#elif defined(VITA)
return SCE_S_ISDIR(entry->d_stat.st_mode);
#endif
+#elif defined(PS2)
+ const iox_dirent_t *entry = (const iox_dirent_t*)&rdir->entry;
+ return FIO_S_ISDIR(entry->stat.mode);
#elif defined(__CELLOS_LV2__)
CellFsDirent *entry = (CellFsDirent*)&rdir->entry;
return (entry->d_type == CELL_FS_TYPE_DIRECTORY);
@@ -289,6 +307,8 @@ void retro_closedir(struct RDIR *rdir)
FindClose(rdir->directory);
#elif defined(VITA) || defined(PSP)
sceIoDclose(rdir->directory);
+#elif defined(PS2)
+ fileXioDclose(rdir->directory);
#elif defined(__CELLOS_LV2__)
rdir->error = cellFsClosedir(rdir->directory);
#else
diff --git a/libretro-common/include/compat/intrinsics.h b/libretro-common/include/compat/intrinsics.h
index 3fc7d92918..f9e39dd97b 100644
--- a/libretro-common/include/compat/intrinsics.h
+++ b/libretro-common/include/compat/intrinsics.h
@@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS
/* Count Leading Zero, unsigned 16bit input value */
static INLINE unsigned compat_clz_u16(uint16_t val)
{
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(PS2)
return __builtin_clz(val << 16 | 0x8000);
#else
unsigned ret = 0;
diff --git a/libretro-common/include/compat/posix_string.h b/libretro-common/include/compat/posix_string.h
index 9f56322ab9..46c14413c5 100644
--- a/libretro-common/include/compat/posix_string.h
+++ b/libretro-common/include/compat/posix_string.h
@@ -29,6 +29,10 @@
#include
#endif
+#if defined(PS2)
+#include
+#endif
+
RETRO_BEGIN_DECLS
#ifdef _WIN32
diff --git a/libretro-common/include/compat/strcasestr.h b/libretro-common/include/compat/strcasestr.h
index f849593b0f..02f28d0192 100644
--- a/libretro-common/include/compat/strcasestr.h
+++ b/libretro-common/include/compat/strcasestr.h
@@ -25,6 +25,10 @@
#include
+#if defined(PS2)
+#include
+#endif
+
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif
diff --git a/libretro-common/include/memmap.h b/libretro-common/include/memmap.h
index 2bedd5c926..e1d75c39fc 100644
--- a/libretro-common/include/memmap.h
+++ b/libretro-common/include/memmap.h
@@ -26,7 +26,7 @@
#include
#include
-#if defined(__CELLOS_LV2__) || defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
+#if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
/* No mman available */
#elif defined(_WIN32) && !defined(_XBOX)
#include
diff --git a/libretro-common/include/retro_environment.h b/libretro-common/include/retro_environment.h
index 0a40593e31..e220c1529b 100644
--- a/libretro-common/include/retro_environment.h
+++ b/libretro-common/include/retro_environment.h
@@ -103,4 +103,4 @@ printf("This is C++, version %d.\n", __cplusplus);
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/libretro-common/include/retro_miscellaneous.h b/libretro-common/include/retro_miscellaneous.h
index 2fd97d54c1..5972c1796f 100644
--- a/libretro-common/include/retro_miscellaneous.h
+++ b/libretro-common/include/retro_miscellaneous.h
@@ -77,7 +77,7 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
#ifndef PATH_MAX_LENGTH
#if defined(__CELLOS_LV2__)
#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
-#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)|| defined(WIIU)
+#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU)
#define PATH_MAX_LENGTH 512
#else
#define PATH_MAX_LENGTH 4096
diff --git a/libretro-common/include/retro_timers.h b/libretro-common/include/retro_timers.h
index 6c164e65d0..d11e67e7c2 100644
--- a/libretro-common/include/retro_timers.h
+++ b/libretro-common/include/retro_timers.h
@@ -37,6 +37,8 @@
#include
#elif defined(VITA)
#include
+#elif defined(PS2)
+#include
#elif defined(_3DS)
#include <3ds.h>
#else
@@ -89,6 +91,8 @@ static INLINE void retro_sleep(unsigned msec)
sys_timer_usleep(1000 * msec);
#elif defined(PSP) || defined(VITA)
sceKernelDelayThread(1000 * msec);
+#elif defined(PS2)
+ SDL_Delay(msec);
#elif defined(_3DS)
svcSleepThread(1000000 * (s64)msec);
#elif defined(__WINRT__)
diff --git a/libretro-common/rthreads/rthreads.c b/libretro-common/rthreads/rthreads.c
index b5db30d788..085952b9ef 100644
--- a/libretro-common/rthreads/rthreads.c
+++ b/libretro-common/rthreads/rthreads.c
@@ -852,6 +852,10 @@ bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us)
sys_time_get_current_time(&s, &n);
now.tv_sec = s;
now.tv_nsec = n;
+#elif defined(PS2)
+ int tickUS = cpu_ticks()/295.0;
+ now.tv_sec = tickUS/1000000;
+ now.tv_nsec = tickUS * 1000;
#elif defined(__mips__) || defined(VITA) || defined(_3DS)
struct timeval tm;
diff --git a/libretro-common/vfs/vfs_implementation.c b/libretro-common/vfs/vfs_implementation.c
index 3443381bc7..0213c06091 100644
--- a/libretro-common/vfs/vfs_implementation.c
+++ b/libretro-common/vfs/vfs_implementation.c
@@ -47,6 +47,9 @@
# if defined(PSP)
# include
# endif
+# if defined(PS2)
+# include
+# endif
# include
# include
# if !defined(VITA)
@@ -125,6 +128,8 @@ int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, i
return _fseeki64(stream->fp, offset, whence);
#elif defined(__CELLOS_LV2__) || defined(_MSC_VER) && _MSC_VER <= 1310
return fseek(stream->fp, (long)offset, whence);
+#elif defined(PS2)
+ return fioLseek(fileno(stream->fp), (off_t)offset, whence);
#else
return fseeko(stream->fp, (off_t)offset, whence);
#endif
@@ -231,7 +236,9 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
mode_str = "wb";
flags = O_WRONLY | O_CREAT | O_TRUNC;
-#ifndef _WIN32
+#if defined(PS2)
+ flags |= FIO_S_IRUSR | FIO_S_IWUSR;
+#elif !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
@@ -242,7 +249,9 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
mode_str = "w+b";
flags = O_RDWR | O_CREAT | O_TRUNC;
-#ifndef _WIN32
+#if defined(PS2)
+ flags |= FIO_S_IRUSR | FIO_S_IWUSR;
+#elif !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
@@ -254,7 +263,9 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, uns
mode_str = "r+b";
flags = O_RDWR;
-#ifndef _WIN32
+#if defined(PS2)
+ flags |= FIO_S_IRUSR | FIO_S_IWUSR;
+#elif !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
@@ -391,7 +402,7 @@ int64_t retro_vfs_file_truncate_impl(libretro_vfs_implementation_file *stream, i
#ifdef _WIN32
if(_chsize(_fileno(stream->fp), length) != 0)
return -1;
-#elif !defined(VITA) && !defined(PSP) && (!defined(SWITCH) || defined(HAVE_LIBNX))
+#elif !defined(VITA) && !defined(PSP) && !defined(PS2) && (!defined(SWITCH) || defined(HAVE_LIBNX))
if(ftruncate(fileno(stream->fp), length) != 0)
return -1;
#endif
diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c
index 346be1ab5d..16e2996a9f 100644
--- a/menu/drivers/rgui.c
+++ b/menu/drivers/rgui.c
@@ -73,6 +73,10 @@ static uint16_t *rgui_framebuf_data = NULL;
#define HOVER_COLOR(settings) ((3 << 0) | (10 << 4) | (3 << 8) | (7 << 12))
#define NORMAL_COLOR(settings) 0x7FFF
#define TITLE_COLOR(settings) HOVER_COLOR(settings)
+#elif defined(PS2)
+#define HOVER_COLOR(settings) 0x03E0
+#define NORMAL_COLOR(settings) 0x7FFF
+#define TITLE_COLOR(settings) HOVER_COLOR(settings)
#else
#define HOVER_COLOR(settings) (argb32_to_rgba4444(settings->uints.menu_entry_hover_color))
#define NORMAL_COLOR(settings) (argb32_to_rgba4444(settings->uints.menu_entry_normal_color))
@@ -94,7 +98,9 @@ static uint16_t rgui_gray_filler(rgui_t *rgui, unsigned x, unsigned y)
unsigned shft = (rgui->bg_thickness ? 1 : 0);
unsigned col = (((x >> shft) + (y >> shft)) & 1) + 1;
#if defined(GEKKO) || defined(PSP)
- return (6 << 12) | (col << 8) | (col << 4) | (col << 0);
+ return (6 << 12) | (col << 8) | (col << 4) | (col << 0);
+#elif defined(PS2)
+ return (0 << 15) | (col << 12) | (col << 7) | (col << 2);
#elif defined(HAVE_LIBNX) && !defined(HAVE_OPENGL)
return (((31 * (54)) / 255) << 11) |
(((63 * (54)) / 255) << 5) |
@@ -110,6 +116,8 @@ static uint16_t rgui_green_filler(rgui_t *rgui, unsigned x, unsigned y)
unsigned col = (((x >> shft) + (y >> shft)) & 1) + 1;
#if defined(GEKKO) || defined(PSP)
return (6 << 12) | (col << 8) | (col << 5) | (col << 0);
+#elif defined(PS2)
+ return (0 << 15) | (col << 12) | (col << 8) | (col << 2);
#elif defined(HAVE_LIBNX) && !defined(HAVE_OPENGL)
return (((31 * (54)) / 255) << 11) |
(((63 * (109)) / 255) << 5) |
diff --git a/ps2/compat_ctype.c b/ps2/compat_ctype.c
new file mode 100644
index 0000000000..0c5dba835d
--- /dev/null
+++ b/ps2/compat_ctype.c
@@ -0,0 +1,427 @@
+#include
+#include
+#include
+#include
+#include
+
+#define ULLONG_MAX UINT64_C(0xffffffffffffffff)
+
+/* Do not link from libc */
+
+int islower(int c)
+{
+ if ((c < 'a') || (c > 'z'))
+ return 0;
+
+ // passed both criteria, so it
+ // is a lower case alpha char
+ return 1;
+}
+
+int tolower(int ch)
+{
+ if(ch >= 'A' && ch <= 'Z')
+ return ('a' + ch - 'A');
+ else
+ return ch;
+}
+
+int toupper(int c)
+{
+ if (islower(c))
+ c -= 32;
+
+ return c;
+}
+
+int memcmp(const void *s1, const void *s2, unsigned int length)
+{
+ const char *a = s1;
+ const char *b = s2;
+
+ while (length--) {
+ if (*a++ != *b++)
+ return 1;
+ }
+
+ return 0;
+}
+
+void * memcpy (void *dest, const void *src, size_t len)
+{
+ char *d = dest;
+ const char *s = src;
+ while (len--)
+ *d++ = *s++;
+ return dest;
+}
+
+void * memset (void *dest, int val, size_t len)
+{
+ unsigned char *ptr = dest;
+ while (len-- > 0)
+ *ptr++ = val;
+ return dest;
+}
+
+int sprintf (char *s, const char *format, ...)
+{
+ va_list arg;
+ int done;
+ va_start (arg, format);
+ done = vsprintf (s, format, arg);
+ va_end (arg);
+ return done;
+}
+
+char * strcat(char *dest, const char *src)
+{
+ size_t i,j;
+ for (i = 0; dest[i] != '\0'; i++)
+ ;
+ for (j = 0; src[j] != '\0'; j++)
+ dest[i+j] = src[j];
+ dest[i+j] = '\0';
+ return dest;
+}
+
+char *strchr(const char *string, int c)
+{
+ while (*string) {
+ if (*string == c)
+ return (char *)string;
+ string++;
+ }
+
+ if (*string == c)
+ return (char *)string;
+
+ return NULL;
+}
+
+int strcmp(const char *s1, const char *s2)
+{
+ while (*s1 == *s2++)
+ if (*s1++ == 0)
+ return (0);
+ return (*(unsigned char *)s1 - *(unsigned char *)--s2);
+}
+
+char * strcpy(char *to, const char *from)
+{
+ char *save = to;
+
+ for (; (*to = *from) != '\0'; ++from, ++to);
+ return(save);
+}
+
+size_t strcspn(const char *s1, const char *s2)
+{
+ const char *p, *spanp;
+ char c, sc;
+
+ /*
+ * Stop as soon as we find any character from s2. Note that there
+ * must be a NUL in s2; it suffices to stop when we find that, too.
+ */
+ for (p = s1;;) {
+ c = *p++;
+ spanp = s2;
+ do {
+ if ((sc = *spanp++) == c)
+ return (p - 1 - s1);
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+
+size_t strlen(const char *str)
+{
+ const char *s;
+
+ for (s = str; *s; ++s)
+ ;
+ return (s - str);
+}
+
+char * strncat(char *dst, const char *src, size_t n)
+{
+ if (n != 0) {
+ char *d = dst;
+ const char *s = src;
+
+ while (*d != 0)
+ d++;
+ do {
+ if ((*d = *s++) == 0)
+ break;
+ d++;
+ } while (--n != 0);
+ *d = 0;
+ }
+ return (dst);
+}
+
+int strncmp(const char *s1, const char *s2, size_t n)
+{
+ if (n == 0)
+ return (0);
+ do {
+ if (*s1 != *s2++)
+ return (*(unsigned char *)s1 - *(unsigned char *)--s2);
+ if (*s1++ == 0)
+ break;
+ } while (--n != 0);
+ return (0);
+}
+
+char * strncpy(char *dst, const char *src, size_t n)
+{
+ if (n != 0) {
+ char *d = dst;
+ const char *s = src;
+
+ do {
+ if ((*d++ = *s++) == 0) {
+ /* NUL pad the remaining n-1 bytes */
+ while (--n != 0)
+ *d++ = 0;
+ break;
+ }
+ } while (--n != 0);
+ }
+ return (dst);
+}
+
+char * strpbrk(const char *s1, const char *s2)
+{
+ const char *scanp;
+ int c, sc;
+
+ while ((c = *s1++) != 0) {
+ for (scanp = s2; (sc = *scanp++) != 0;)
+ if (sc == c)
+ return ((char *)(s1 - 1));
+ }
+ return (NULL);
+}
+
+/* Do not link to strrchr() from libc */
+char * strrchr(const char *p, int ch)
+{
+ char *save;
+
+ for (save = NULL;; ++p) {
+ if (*p == (char) ch)
+ save = (char *)p;
+ if (!*p)
+ return(save);
+ }
+ /* NOTREACHED */
+}
+
+size_t strspn(const char *s1, const char *s2)
+{
+ const char *p = s1, *spanp;
+ char c, sc;
+
+ /*
+ * Skip any characters in s2, excluding the terminating \0.
+ */
+cont:
+ c = *p++;
+ for (spanp = s2; (sc = *spanp++) != 0;)
+ if (sc == c)
+ goto cont;
+ return (p - 1 - s1);
+}
+
+char *strstr(const char *string, const char *substring)
+{
+ char *strpos;
+
+ if (string == 0)
+ return 0;
+
+ if (strlen(substring) == 0)
+ return (char *)string;
+
+ strpos = (char *)string;
+
+ while (*strpos != 0) {
+ if (strncmp(strpos, substring, strlen(substring)) == 0)
+ return strpos;
+
+ strpos++;
+ }
+
+ return 0;
+}
+
+size_t strnlen(const char *str, size_t maxlen)
+{
+ const char *cp;
+
+ for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
+ ;
+
+ return (size_t)(cp - str);
+}
+
+char *strtok(char *strToken, const char *strDelimit)
+{
+ static char *start;
+ static char *end;
+
+ if (strToken != NULL)
+ start = strToken;
+ else {
+ if (*end == 0)
+ return 0;
+
+ start = end;
+ }
+
+ if (*start == 0)
+ return 0;
+
+ // Strip out any leading delimiters
+ while (strchr(strDelimit, *start)) {
+ // If a character from the delimiting string
+ // then skip past it
+
+ start++;
+
+ if (*start == 0)
+ return 0;
+ }
+
+ if (*start == 0)
+ return 0;
+
+ end = start;
+
+ while (*end != 0) {
+ if (strchr(strDelimit, *end)) {
+ // if we find a delimiting character
+ // before the end of the string, then
+ // terminate the token and move the end
+ // pointer to the next character
+ *end = 0;
+ end++;
+ return start;
+ }
+ end++;
+ }
+
+ // reached the end of the string before finding a delimiter
+ // so dont move on to the next character
+ return start;
+}
+
+char * strtok_r (char *s, const char *delim, char **save_ptr)
+{
+ char *end;
+ if (s == NULL)
+ s = *save_ptr;
+ if (*s == '\0')
+ {
+ *save_ptr = s;
+ return NULL;
+ }
+ /* Scan leading delimiters. */
+ s += strspn (s, delim);
+ if (*s == '\0')
+ {
+ *save_ptr = s;
+ return NULL;
+ }
+ /* Find the end of the token. */
+ end = s + strcspn (s, delim);
+ if (*end == '\0')
+ {
+ *save_ptr = end;
+ return s;
+ }
+ /* Terminate the token and make *SAVE_PTR point past it. */
+ *end = '\0';
+ *save_ptr = end + 1;
+ return s;
+}
+
+unsigned long long strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+ const char *s;
+ unsigned long long acc;
+ char c;
+ unsigned long long cutoff;
+ int neg, any, cutlim;
+
+ /*
+ * See strtoq for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace((unsigned char)c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = ULLONG_MAX / base;
+ cutlim = ULLONG_MAX % base;
+ for ( ; ; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULLONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+
+//long strtol(const char *s, char **endptr, int base); FJTRUJY MISSING
+//unsigned long strtoul(const char *s, char **endptr, int base); FJTRUJY MISSING
+
+int link(const char *oldpath, const char *newpath)
+{
+ return fileXioSymlink(oldpath, newpath);
+}
diff --git a/ps2/include/compat_ctype.h b/ps2/include/compat_ctype.h
new file mode 100644
index 0000000000..1d80025c28
--- /dev/null
+++ b/ps2/include/compat_ctype.h
@@ -0,0 +1,10 @@
+#ifndef COMPAT_CTYPE_H
+#define COMPAT_CTYPE_H
+
+char *strtok_r(char *str, const char *delim, char **saveptr);
+
+unsigned long long strtoull(const char * __restrict nptr, char ** __restrict endptr, int base);
+
+int link(const char *oldpath, const char *newpath);
+
+#endif
diff --git a/ps2/include/inttypes.h b/ps2/include/inttypes.h
new file mode 100644
index 0000000000..3049fbdbba
--- /dev/null
+++ b/ps2/include/inttypes.h
@@ -0,0 +1,8 @@
+#ifndef INTTYPES_H
+#define INTTYPES_H
+
+#define PRId64 "ld"
+#define PRIu64 "lu"
+#define PRIuPTR "lu"
+
+#endif //INTTYPES_H
diff --git a/ps2/include/math.h b/ps2/include/math.h
new file mode 100644
index 0000000000..bf0071edb1
--- /dev/null
+++ b/ps2/include/math.h
@@ -0,0 +1,21 @@
+#ifndef MATH_H
+#define MATH_H
+
+#include
+#define roundf(in) (in >= 0.0f ? floorf(in + 0.5f) : ceilf(in - 0.5f))
+
+#define cos(x) ((double)cosf((float)x))
+#define pow(x, y) ((double)powf((float)x, (float)y))
+#define sin(x) ((double)sinf((float)x))
+#define ceil(x) ((double)ceilf((float)x))
+#define floor(x) ((double)floorf((float)x))
+#define sqrt(x) ((double)sqrtf((float)x))
+#define fabs(x) ((double)fabsf((float)(x)))
+
+#define fmaxf(a, b) (((a) > (b)) ? (a) : (b))
+#define fminf(a, b) (((a) < (b)) ? (a) : (b))
+
+#define exp(a) ((double)expf((float)a))
+#define log(a) ((double)logf((float)a))
+
+#endif //MATH_H
diff --git a/ps2/include/pte_types.h b/ps2/include/pte_types.h
new file mode 100644
index 0000000000..7e81156684
--- /dev/null
+++ b/ps2/include/pte_types.h
@@ -0,0 +1,26 @@
+/* pte_types.h */
+
+#ifndef PTE_TYPES_H
+#define PTE_TYPES_H
+
+#include
+#include
+#include
+#include
+
+/** UIDs are used to describe many different kernel objects. */
+typedef int SceUID;
+
+/* Misc. kernel types. */
+typedef unsigned int SceSize;
+typedef int SceSSize;
+
+typedef unsigned char SceUChar;
+typedef unsigned int SceUInt;
+
+/* File I/O types. */
+typedef int SceMode;
+typedef long SceOff;
+typedef long SceIores;
+
+#endif /* PTE_TYPES_H */
diff --git a/ps2/include/stdint.h b/ps2/include/stdint.h
new file mode 100644
index 0000000000..813efd21f8
--- /dev/null
+++ b/ps2/include/stdint.h
@@ -0,0 +1,30 @@
+#ifndef STDINT_H
+#define STDINT_H
+
+typedef unsigned long uintptr_t;
+typedef signed long intptr_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long int64_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long uint64_t;
+
+#define STDIN_FILENO 0 /* standard input file descriptor */
+#define STDOUT_FILENO 1 /* standard output file descriptor */
+#define STDERR_FILENO 2 /* standard error file descriptor */
+
+#define INT8_C(val) val##c
+#define INT16_C(val) val##h
+#define INT32_C(val) val##i
+#define INT64_C(val) val##l
+
+#define UINT8_C(val) val##uc
+#define UINT16_C(val) val##uh
+#define UINT32_C(val) val##ui
+#define UINT64_C(val) val##ul
+
+#endif //STDINT_H
diff --git a/tasks/task_content.c b/tasks/task_content.c
index 5747236df6..af28c4fcac 100644
--- a/tasks/task_content.c
+++ b/tasks/task_content.c
@@ -1654,7 +1654,7 @@ bool task_push_start_builtin_core(
/* Preliminary stuff that has to be done before we
* load the actual content. Can differ per mode. */
retroarch_set_current_core_type(type, true);
-
+ printf("Step 1\n");
/* Load content */
if (!task_load_content_callback(content_info, true, false))
{
| |