From df89a6b6047bd5c2e5226053c5eb9addf570f961 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sat, 7 Aug 2021 21:59:16 +0200 Subject: [PATCH] Add support of HDD for PS2 --- Makefile.ps2 | 3 +- Makefile.ps2.salamander | 3 +- frontend/drivers/platform_ps2.c | 162 +++++++++++++++++++++++++++++++- ps2/compat_files/ps2_devices.c | 25 +++++ ps2/include/ps2_devices.h | 2 + ps2/include/ps2_irx_variables.h | 15 +++ ps2/irx/Makefile | 4 +- 7 files changed, 207 insertions(+), 7 deletions(-) diff --git a/Makefile.ps2 b/Makefile.ps2 index eae698a9b5..5dd46d0099 100644 --- a/Makefile.ps2 +++ b/Makefile.ps2 @@ -35,7 +35,7 @@ RARCH_DEFINES += -DHAVE_DSP_FILTER LDFLAGS += -L$(PS2DEV)/gsKit/lib -L$(PS2SDK)/ports/lib -L. # Lib cdvd is needed to get proper time -LIBS += -lretro_ps2 -lpatches -lgskit -ldmakit -laudsrv -lmtap -lpadx -lz -lcdvd -lelf-loader +LIBS += -lretro_ps2 -lpatches -lgskit -ldmakit -laudsrv -lmtap -lpadx -lz -lcdvd -lelf-loader -lfileXio -lpoweroff ifeq ($(SCREEN_DEBUG), 1) LIBS += -ldebug @@ -58,6 +58,7 @@ EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o EE_OBJS += $(IRX_DIR)/libsd_irx.o $(IRX_DIR)/audsrv_irx.o EE_OBJS += $(IRX_DIR)/cdfs_irx.o +EE_OBJS += $(IRX_DIR)/ps2dev9_irx.o $(IRX_DIR)/ps2atad_irx.o $(IRX_DIR)/ps2hdd_irx.o $(IRX_DIR)/ps2fs_irx.o $(IRX_DIR)/poweroff_irx.o EE_OBJS += $(IRX_DIR)/mtapman_irx.o $(IRX_DIR)/padman_irx.o # Missing objecst on the PS2SDK diff --git a/Makefile.ps2.salamander b/Makefile.ps2.salamander index eb8202b7b8..548b9f69af 100644 --- a/Makefile.ps2.salamander +++ b/Makefile.ps2.salamander @@ -31,7 +31,7 @@ RARCH_DEFINES += -DPS2 -DIS_SALAMANDER -DRARCH_CONSOLE LIBDIR = LDFLAGS = -LIBS = -lelf-loader -lpatches +LIBS = -lelf-loader -lpatches -lfileXio -lpoweroff ifeq ($(SCREEN_DEBUG), 1) LIBS += -ldebug @@ -70,6 +70,7 @@ EE_OBJS += $(IRX_DIR)/sio2man_irx.o $ $(IRX_DIR)/iomanX_irx.o $(IRX_DIR)/fileXio EE_OBJS += $(IRX_DIR)/mcman_irx.o $(IRX_DIR)/mcserv_irx.o EE_OBJS += $(IRX_DIR)/usbd_irx.o $(IRX_DIR)/bdm_irx.o $(IRX_DIR)/bdmfs_vfat_irx.o $(IRX_DIR)/usbmass_bd_irx.o EE_OBJS += $(IRX_DIR)/cdfs_irx.o +EE_OBJS += $(IRX_DIR)/ps2dev9_irx.o $(IRX_DIR)/ps2atad_irx.o $(IRX_DIR)/ps2hdd_irx.o $(IRX_DIR)/ps2fs_irx.o $(IRX_DIR)/poweroff_irx.o EE_CFLAGS = $(CFLAGS) EE_CXXFLAGS = $(CFLAGS) diff --git a/frontend/drivers/platform_ps2.c b/frontend/drivers/platform_ps2.c index 0903a5a804..b945f663d5 100644 --- a/frontend/drivers/platform_ps2.c +++ b/frontend/drivers/platform_ps2.c @@ -25,6 +25,12 @@ #include #include #include +#include + +#define NEWLIB_PORT_AWARE +#include +#include +#include #if defined(SCREEN_DEBUG) #include @@ -39,9 +45,14 @@ #include "../../verbosity.h" #include "../../paths.h" +#define DEFAULT_PARTITION "hdd0:__common:pfs" static enum frontend_fork ps2_fork_mode = FRONTEND_FORK_NONE; static char cwd[FILENAME_MAX]; +static char mountString[10]; +static char mountPoint[50]; +static int hddMounted = 0; +static int pfsModuleLoaded = 0; static void create_path_names(void) { @@ -118,12 +129,64 @@ static void reset_IOP() sbv_patch_disable_prefix_check(); } -static void load_modules() +static int hddCheck(void) +{ + int ret; + + ret = fileXioDevctl("hdd0:", HDIOC_STATUS, NULL, 0, NULL, 0); + + // 0 = HDD connected and formatted, 1 = not formatted, 2 = HDD not usable, 3 = HDD not connected. + if ((ret >= 3) || (ret < 0)) + return -1; + + return ret; +} + +static void load_hdd_modules() +{ + pfsModuleLoaded = 0; + int ret; + char hddarg[] = "-o" "\0" "4" "\0" "-n" "\0" "20"; + + ret = SifExecModuleBuffer(&ps2dev9_irx, size_ps2dev9_irx, 0, NULL, NULL); + + ret = SifExecModuleBuffer(&ps2atad_irx, size_ps2atad_irx, 0, NULL, NULL); + if (ret < 0) + { + RARCH_WARN("HDD: No HardDisk Drive detected.\n"); + return; + } + + ret = SifExecModuleBuffer(&ps2hdd_irx, size_ps2hdd_irx, sizeof(hddarg), hddarg, NULL); + if (ret < 0) + { + RARCH_WARN("HDD: No HardDisk Drive detected.\n"); + return; + } + + // Check if a HDD unit is connected + if (hddCheck() < 0) { + RARCH_WARN("HDD: No HardDisk Drive detected.\n"); + return; + } + + ret = SifExecModuleBuffer(&ps2fs_irx, size_ps2fs_irx, 0, NULL, NULL); + if (ret < 0) { + RARCH_WARN("HDD: HardDisk Drive not formatted (PFS).\n"); + return; + } + + RARCH_LOG("HDDSUPPORT modules loaded\n"); + pfsModuleLoaded = 1; +} + +static void load_modules() { /* I/O Files */ SifExecModuleBuffer(&iomanX_irx, size_iomanX_irx, 0, NULL, NULL); SifExecModuleBuffer(&fileXio_irx, size_fileXio_irx, 0, NULL, NULL); SifExecModuleBuffer(&sio2man_irx, size_sio2man_irx, 0, NULL, NULL); + fileXioInitSkipOverride(); /* Memory Card */ SifExecModuleBuffer(&mcman_irx, size_mcman_irx, 0, NULL, NULL); @@ -135,6 +198,11 @@ static void load_modules() SifExecModuleBuffer(&bdmfs_vfat_irx, size_bdmfs_vfat_irx, 0, NULL, NULL); SifExecModuleBuffer(&usbmass_bd_irx, size_usbmass_bd_irx, 0, NULL, NULL); + /* Power off */ + SifExecModuleBuffer(&poweroff_irx, size_poweroff_irx, 0, NULL, NULL); + + /* HDD */ + load_hdd_modules(); #if !defined(DEBUG) /* CDFS */ SifExecModuleBuffer(&cdfs_irx, size_cdfs_irx, 0, NULL, NULL); @@ -151,6 +219,74 @@ static void load_modules() #endif } +static int mount_hdd_partition() { + char mountPath[FILENAME_MAX]; + char newCWD[FILENAME_MAX]; + int shouldMount = 0; + + int bootDeviceID = getBootDeviceID(cwd); + /* Try to mount HDD partition, either from cwd or default one */ + if (bootDeviceID == BOOT_DEVICE_HDD || bootDeviceID == BOOT_DEVICE_HDD0) + { + shouldMount = 1; + strlcpy(mountPath, cwd, sizeof(mountPath)); + } +#if !defined(IS_SALAMANDER) + else + { + // Even if we're booting from USB, try to mount default partition + strcpy(mountPath, DEFAULT_PARTITION); + shouldMount = 1; + } +#endif + + if (!shouldMount) + return 0; + + if (getMountInfo(mountPath, mountString, mountPoint, newCWD) != 1) + { + RARCH_WARN("Partition info not readed\n"); + return 0; + } + + if (fileXioMount(mountString, mountPoint, FIO_MT_RDWR) < 0) + { + RARCH_WARN("Error mount mounting partition %s, %s\n", mountString, mountPoint); + return 0; + } + + if (bootDeviceID == BOOT_DEVICE_HDD || bootDeviceID == BOOT_DEVICE_HDD0) + { + // If we're booting from HDD, we must update the cwd variable and add : to the mount point + sprintf(cwd, "%s", newCWD); + strcat(mountPoint, ":"); + } else { + // we MUST put mountPoint as empty to avoid wrong results with LoadELFFromFileWithPartition + strcpy(mountPoint, ""); + } + + return 1; +} + +static void prepare_for_exit(void) +{ + if (hddMounted) + { + fileXioUmount(mountString); + fileXioDevctl(mountString, PDIOC_CLOSEALL, NULL, 0, NULL, 0); + fileXioDevctl("hdd0:", HDIOC_IDLEIMM, NULL, 0, NULL, 0); + } + + if (pfsModuleLoaded) + fileXioDevctl("dev9x:", DDIOC_OFF, NULL, 0, NULL, 0); +} + +static void poweroffHandler(void *arg) +{ + prepare_for_exit(); + poweroffShutdown(); +} + static void frontend_ps2_get_env(int *argc, char *argv[], void *args, void *params_data) { @@ -195,10 +331,13 @@ static void frontend_ps2_init(void *data) reset_IOP(); #if defined(SCREEN_DEBUG) init_scr(); - scr_printf("Starting RetroArch...\n"); + scr_printf("\n\nStarting RetroArch...\n"); #endif load_modules(); + poweroffInit(); + poweroffSetCallback(&poweroffHandler, NULL); + #ifndef IS_SALAMANDER /* Initializes audsrv library */ @@ -223,6 +362,8 @@ static void frontend_ps2_init(void *data) // If it is not salamander we need to go one level up for set the CWD. path_parent_dir(cwd); #endif + if (pfsModuleLoaded) + hddMounted = mount_hdd_partition(); #if !defined(DEBUG) waitUntilDeviceIsReady(cwd); @@ -232,6 +373,9 @@ static void frontend_ps2_init(void *data) static void frontend_ps2_deinit(void *data) { #ifndef IS_SALAMANDER + if (ps2_fork_mode == FRONTEND_FORK_NONE) + prepare_for_exit(); + if (audsrv_quit()) { RARCH_ERR("audsrv library not deinitalizated\n"); @@ -248,7 +392,7 @@ static void frontend_ps2_exec(const char *path, bool should_load_game) { int args = 0; static char *argv[1]; - RARCH_LOG("Attempt to load executable: [%s].\n", path); + RARCH_LOG("Attempt to load executable: [%s], partition [%s].\n", path, mountPoint); #ifndef IS_SALAMANDER if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) { @@ -256,7 +400,7 @@ static void frontend_ps2_exec(const char *path, bool should_load_game) argv[0] = (char *)path_get(RARCH_PATH_CONTENT); } #endif - LoadELFFromFile(path, args, argv); + LoadELFFromFileWithPartition(path, mountPoint, args, argv); } #ifndef IS_SALAMANDER @@ -317,6 +461,7 @@ enum frontend_architecture frontend_ps2_get_arch(void) static int frontend_ps2_parse_drive_list(void *data, bool load_content) { #ifndef IS_SALAMANDER + char hdd[10]; 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 : @@ -342,6 +487,15 @@ static int frontend_ps2_parse_drive_list(void *data, bool load_content) msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), enum_idx, FILE_TYPE_DIRECTORY, 0, 0); + if (hddMounted) + { + sprintf(hdd, "%s/", mountString); + menu_entries_append_enum(list, + hdd, + 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, rootDevicePath(BOOT_DEVICE_HOST), msg_hash_to_str(MENU_ENUM_LABEL_FILE_DETECT_CORE_LIST_PUSH_DIR), diff --git a/ps2/compat_files/ps2_devices.c b/ps2/compat_files/ps2_devices.c index 6dfe3ec9f8..77d0fba07e 100644 --- a/ps2/compat_files/ps2_devices.c +++ b/ps2/compat_files/ps2_devices.c @@ -20,6 +20,7 @@ #include #include #include +#include #define DEVICE_SLASH "/" @@ -154,6 +155,30 @@ enum BootDeviceIDs getBootDeviceID(char *path) return BOOT_DEVICE_UNKNOWN; } +/* This method returns true if it can extract needed info from path, otherwise false. + * In case of true, it also updates mountString, mountPoint and newCWD parameters + * It splits path by ":", and requires a minimum of 3 elements + * Example: if path = hdd0:__common:pfs:/retroarch/ then + * mountString = "pfs:" + * mountPoint = "hdd0:__common" + * newCWD = pfs:/retroarch/ + * return true +*/ +bool getMountInfo(char *path, char *mountString, char *mountPoint, char *newCWD) +{ + struct string_list *str_list = string_split(path, ":"); + if (str_list->size < 3 ) + { + return false; + } + + sprintf(mountPoint, "%s:%s", str_list->elems[0].data, str_list->elems[1].data); + sprintf(mountString, "%s:", str_list->elems[2].data); + sprintf(newCWD, "%s%s", mountString, str_list->size == 4 ? str_list->elems[3].data : ""); + + return true; +} + /* HACK! If booting from a USB device, keep trying to * open this program again until it succeeds. * diff --git a/ps2/include/ps2_devices.h b/ps2/include/ps2_devices.h index 5c0faa7d8e..f7c086a398 100644 --- a/ps2/include/ps2_devices.h +++ b/ps2/include/ps2_devices.h @@ -45,6 +45,8 @@ char *rootDevicePath(enum BootDeviceIDs device_id); enum BootDeviceIDs getBootDeviceID(char *path); +bool getMountInfo(char *path, char *mountString, char *mountPoint, char *newCWD); + bool waitUntilDeviceIsReady(char *path); #endif diff --git a/ps2/include/ps2_irx_variables.h b/ps2/include/ps2_irx_variables.h index 51455e0ea9..cc52452e94 100644 --- a/ps2/include/ps2_irx_variables.h +++ b/ps2/include/ps2_irx_variables.h @@ -69,4 +69,19 @@ extern unsigned int size_libsd_irx; extern unsigned char audsrv_irx; extern unsigned int size_audsrv_irx; +extern unsigned char ps2dev9_irx; +extern unsigned int size_ps2dev9_irx; + +extern unsigned char ps2atad_irx; +extern unsigned int size_ps2atad_irx; + +extern unsigned char ps2hdd_irx; +extern unsigned int size_ps2hdd_irx; + +extern unsigned char ps2fs_irx; +extern unsigned int size_ps2fs_irx; + +extern unsigned char poweroff_irx; +extern unsigned int size_poweroff_irx; + #endif /* PS2_IRX_VARIABLES_H */ diff --git a/ps2/irx/Makefile b/ps2/irx/Makefile index 916ee60f95..8e6e89ed76 100644 --- a/ps2/irx/Makefile +++ b/ps2/irx/Makefile @@ -4,8 +4,10 @@ IRX_DIR = $(PS2SDK)/iop/irx #IRX modules # IRX modules - modules have to be in IRX_DIR -IRX_FILES += iomanX.irx fileXio.irx sio2man.irx mtapman.irx padman.irx mcman.irx mcserv.irx +IRX_FILES += mtapman.irx padman.irx poweroff.irx +IRX_FILES += iomanX.irx fileXio.irx sio2man.irx mcman.irx mcserv.irx IRX_FILES += usbd.irx bdm.irx bdmfs_vfat.irx usbmass_bd.irx +IRX_FILES += ps2dev9.irx ps2atad.irx ps2hdd.irx ps2fs.irx IRX_FILES += libsd.irx audsrv.irx cdfs.irx IRX_C_FILES = $(IRX_FILES:.irx=_irx.c)