diff --git a/README.md b/README.md index 346680115..91c5bdab5 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,11 @@ USB modes: | "LNG" | for translation support | all | | "CHT" | for cheats files | all | -OPL will automatically create the above directory structure the first time -you launch it and enable your favourite device. For HDD users, a 128Mb +OPL -partition will be created (you can enlarge it using uLaunchELF if you need to). +OPL will automatically create the above directory structure the first time you launch it and enable your favourite device. + +For HDD users, OPL will read hdd0:__common/OPL/conf_hdd.cfg for the config entry "hdd_partition" to use as your OPL partition. +If not found a config file and a 128Mb +OPL partition will be created, you can edit the config if you wish to use/create a different partition. +All partitions created by OPL will be 128Mb (it is not recommended to enlarge partitions as it will break LBAs, instead remove and recreate manually with uLaunchELF at a larger size if needed). ## USB diff --git a/elfldr/elfldr.c b/elfldr/elfldr.c index 1a81f2f5b..a663071e7 100644 --- a/elfldr/elfldr.c +++ b/elfldr/elfldr.c @@ -14,7 +14,7 @@ #include #include -static inline void _strcpy(char *dst, const char *src) +/*static inline void _strcpy(char *dst, const char *src) { memcpy(dst, src, strlen(src) + 1); } @@ -38,7 +38,7 @@ static int _strncmp(const char *s1, const char *s2, int length) } return 0; -} +}*/ static inline void BootError(char *filename) { @@ -101,14 +101,6 @@ int main(int argc, char *argv[]) SifLoadFileExit(); SifExitRpc(); - if (_strncmp(argv[0], "pfs", 3) == 0) { - static char _argv[256]; - _strcpy(_argv, "hdd0:+OPL:"); - _strcat(_argv, argv[0]); - - argv[0] = _argv; - } - ExecPS2((void *)exd.epc, (void *)exd.gp, argc, argv); } else { SifExitRpc(); diff --git a/include/hddsupport.h b/include/hddsupport.h index 01b7c3df9..060af99ec 100644 --- a/include/hddsupport.h +++ b/include/hddsupport.h @@ -63,4 +63,6 @@ void hddInit(); item_list_t *hddGetObject(int initOnly); void hddLoadModules(void); +extern char gOPLPart[128]; + #endif diff --git a/include/opl.h b/include/opl.h index 547feba8e..6cc9c3ea0 100644 --- a/include/opl.h +++ b/include/opl.h @@ -164,6 +164,7 @@ extern int gDefaultDevice; extern int gEnableWrite; +extern char *gHDDPrefix; //These prefixes are relative to the device's name (meaning that they do not include the device name). extern char gBDMPrefix[32]; extern char gETHPrefix[32]; diff --git a/src/hddsupport.c b/src/hddsupport.c index 8f21f105b..5924e9780 100644 --- a/src/hddsupport.c +++ b/src/hddsupport.c @@ -28,7 +28,7 @@ static unsigned char hddModulesLoaded = 0; static char *hddPrefix = "pfs0:"; static hdl_games_list_t hddGames; -const char *oplPart = "hdd0:+OPL"; +char gOPLPart[128]; // forward declaration static item_list_t hddGameList; @@ -42,13 +42,13 @@ static void hddInitModules(void) // update Themes char path[256]; - sprintf(path, "%sTHM", hddPrefix); + sprintf(path, "%sTHM", gHDDPrefix); thmAddElements(path, "/", 1); - sprintf(path, "%sLNG", hddPrefix); + sprintf(path, "%sLNG", gHDDPrefix); lngAddLanguages(path, "/", hddGameList.mode); - sbCreateFolders(hddPrefix, 0); + sbCreateFolders(gHDDPrefix, 0); } // HD Pro Kit is mapping the 1st word in ROM0 seg as a main ATA controller, @@ -93,16 +93,76 @@ static int hddCheckHDProKit(void) #define PFS_ZONE_SIZE 8192 #define PFS_FRAGMENT 0x00000000 -static int CreateOPLPartition(const char *oplPart, const char *mountpoint) +static void hddCheckOPLFolder(const char *mountPoint) +{ + DIR *dir; + char path[32]; + + sprintf(path, "%sOPL", mountPoint); + + dir = opendir(path); + if (dir == NULL) + mkdir(path, 0777); + else + closedir(dir); +} + +static void hddFindOPLPartition(void) +{ + static config_set_t *config; + char name[64]; + int fd, ret = 0; + + fileXioUmount(hddPrefix); + + ret = fileXioMount("pfs0:", "hdd0:__common", FIO_MT_RDWR); + if (ret == 0) { + fd = open("pfs0:OPL/conf_hdd.cfg", O_RDONLY); + if (fd >= 0) { + config = configAlloc(0, NULL, "pfs0:OPL/conf_hdd.cfg"); + configRead(config); + + configGetStrCopy(config, "hdd_partition", name, sizeof(name)); + snprintf(gOPLPart, sizeof(gOPLPart), "hdd0:%s", name); + + configFree(config); + close(fd); + + fileXioUmount(hddPrefix); + return; + } + + hddCheckOPLFolder(hddPrefix); + + fd = open("pfs0:OPL/conf_hdd.cfg", O_CREAT | O_TRUNC | O_WRONLY); + if (fd >= 0) { + config = configAlloc(0, NULL, "pfs0:OPL/conf_hdd.cfg"); + configRead(config); + + configSetStr(config, "hdd_partition", "+OPL"); + configWrite(config); + + configFree(config); + close(fd); + } + } + + snprintf(gOPLPart, sizeof(gOPLPart), "hdd0:+OPL"); + fileXioUmount(hddPrefix); + + return; +} + +static int hddCreateOPLPartition(const char *name) { int formatArg[3] = {PFS_ZONE_SIZE, 0x2d66, PFS_FRAGMENT}; int fd, result; - char cmd[43]; + char cmd[140]; - sprintf(cmd, "%s,,,128M,PFS", oplPart); + sprintf(cmd, "%s,,,128M,PFS", name); if ((fd = open(cmd, O_CREAT | O_TRUNC | O_WRONLY)) >= 0) { close(fd); - result = fileXioFormat(mountpoint, oplPart, (const char *)&formatArg, sizeof(formatArg)); + result = fileXioFormat(hddPrefix, name, (const char *)&formatArg, sizeof(formatArg)); } else { result = fd; } @@ -168,11 +228,18 @@ void hddLoadModules(void) LOG("HDDSUPPORT modules loaded\n"); - ret = fileXioMount(hddPrefix, oplPart, FIO_MT_RDWR); + hddFindOPLPartition(); + + ret = fileXioMount(hddPrefix, gOPLPart, FIO_MT_RDWR); if (ret == -ENOENT) { //Attempt to create the partition. - if ((CreateOPLPartition(oplPart, hddPrefix)) >= 0) - fileXioMount(hddPrefix, oplPart, FIO_MT_RDWR); + if ((hddCreateOPLPartition(gOPLPart)) >= 0) + fileXioMount(hddPrefix, gOPLPart, FIO_MT_RDWR); + } + + if (gOPLPart[5] != '+') { + hddCheckOPLFolder(hddPrefix); + gHDDPrefix = "pfs0:OPL/"; } } } @@ -279,7 +346,7 @@ static void hddLaunchGame(int id, config_set_t *configSet) configGetVMC(configSet, vmc_name[1], sizeof(vmc_name[1]), 1); if (vmc_name[0][0] || vmc_name[1][0]) { - nparts = hddGetPartitionInfo(oplPart, parts); + nparts = hddGetPartitionInfo(gOPLPart, parts); if (nparts > 0 && nparts <= 5) { for (i = 0; i < nparts; i++) { hdd_vmc_infos.parts[i].start = parts[i].start; @@ -301,7 +368,7 @@ static void hddLaunchGame(int id, config_set_t *configSet) if (vmc_name[vmc_id][0]) { have_error = 1; hdd_vmc_infos.active = 0; - if (sysCheckVMC(hddPrefix, "/", vmc_name[vmc_id], 0, &vmc_superblock) > 0) { + if (sysCheckVMC(gHDDPrefix, "/", vmc_name[vmc_id], 0, &vmc_superblock) > 0) { hdd_vmc_infos.flags = vmc_superblock.mc_flag & 0xFF; hdd_vmc_infos.flags |= 0x100; hdd_vmc_infos.specs.page_size = vmc_superblock.page_size; @@ -309,7 +376,7 @@ static void hddLaunchGame(int id, config_set_t *configSet) hdd_vmc_infos.specs.card_size = vmc_superblock.pages_per_cluster * vmc_superblock.clusters_per_card; // Check vmc inode block chain (write operation can cause damage) - snprintf(vmc_path, sizeof(vmc_path), "%sVMC/%s.bin", hddPrefix, vmc_name[vmc_id]); + snprintf(vmc_path, sizeof(vmc_path), "%sVMC/%s.bin", gHDDPrefix, vmc_name[vmc_id]); if ((nparts = hddGetFileBlockInfo(vmc_path, parts, blocks, 11)) > 0) { have_error = 0; hdd_vmc_infos.active = 1; @@ -380,7 +447,7 @@ static void hddLaunchGame(int id, config_set_t *configSet) sbPrepare(NULL, configSet, size_irx, irx, &i); - if ((result = sbLoadCheats(hddPrefix, game->startup)) < 0) { + if ((result = sbLoadCheats(gHDDPrefix, game->startup)) < 0) { switch (result) { case -ENOENT: guiWarning(_l(_STR_NO_CHEATS_FOUND), 10); @@ -414,7 +481,7 @@ static config_set_t *hddGetConfig(int id) char path[256]; hdl_game_info_t *game = &hddGames.games[id]; - snprintf(path, sizeof(path), "%sCFG/%s.cfg", hddPrefix, game->startup); + snprintf(path, sizeof(path), "%sCFG/%s.cfg", gHDDPrefix, game->startup); config_set_t *config = configAlloc(0, NULL, path); configRead(config); //Does not matter if the config file exists or not. @@ -431,7 +498,7 @@ static int hddGetImage(char *folder, int isRelative, char *value, char *suffix, { char path[256]; if (isRelative) - snprintf(path, sizeof(path), "%s%s/%s_%s", hddPrefix, folder, value, suffix); + snprintf(path, sizeof(path), "%s%s/%s_%s", gHDDPrefix, folder, value, suffix); else snprintf(path, sizeof(path), "%s%s_%s", folder, value, suffix); return texDiscoverLoad(resultTex, path, -1, psm); @@ -459,7 +526,7 @@ static void hddCleanUp(int exception) static int hddCheckVMC(char *name, int createSize) { - return sysCheckVMC(hddPrefix, "/", name, createSize, NULL); + return sysCheckVMC(gHDDPrefix, "/", name, createSize, NULL); } //This may be called, even if hddInit() was not. @@ -500,7 +567,7 @@ static int hddLoadGameListCache(hdl_games_list_t *cache) hddFreeHDLGamelist(cache); - sprintf(filename, "%s/games.bin", hddPrefix); + sprintf(filename, "%sgames.bin", gHDDPrefix); file = fopen(filename, "rb"); if (file != NULL) { fseek(file, 0, SEEK_END); @@ -573,7 +640,7 @@ static int hddUpdateGameListCache(hdl_games_list_t *cache, hdl_games_list_t *gam return 0; LOG("hddUpdateGameListCache: caching new game list.\n"); - sprintf(filename, "%s/games.bin", hddPrefix); + sprintf(filename, "%sgames.bin", gHDDPrefix); if (game_list->count > 0) { file = fopen(filename, "wb"); if (file != NULL) { @@ -593,17 +660,17 @@ static int hddUpdateGameListCache(hdl_games_list_t *cache, hdl_games_list_t *gam static void hddGetAppsPath(char *path, int max) { - snprintf(path, max, "%s/APPS", hddPrefix); + snprintf(path, max, "%sAPPS", gHDDPrefix); } static void hddGetLegacyAppsPath(char *path, int max) { - snprintf(path, max, "%sconf_apps.cfg", hddPrefix); + snprintf(path, max, "%sconf_apps.cfg", gHDDPrefix); } static void hddGetLegacyAppsInfo(char *path, int max, char *name) { - snprintf(path, max, "%sCFG/%s.cfg", hddPrefix, name); + snprintf(path, max, "%sCFG/%s.cfg", gHDDPrefix, name); } static item_list_t hddGameList = { diff --git a/src/opl.c b/src/opl.c index f225b0cb2..8ef82e238 100644 --- a/src/opl.c +++ b/src/opl.c @@ -125,6 +125,7 @@ static opl_io_module_t list_support[MODE_COUNT]; // Global data char *gBaseMCDir; +char *gHDDPrefix; int ps2_ip_use_dhcp; int ps2_ip[4]; int ps2_netmask[4]; @@ -723,13 +724,16 @@ static int checkLoadConfigBDM(int types) static int checkLoadConfigHDD(int types) { int value; + char path[64]; hddLoadModules(); - value = open("pfs0:conf_opl.cfg", O_RDONLY); + + snprintf(path, sizeof(path), "%sconf_opl.cfg", gHDDPrefix); + value = open(path, O_RDONLY); if (value >= 0) { close(value); configEnd(); - configInit("pfs0:"); + configInit(gHDDPrefix); value = configReadMulti(types); config_set_t *configOPL = configGetByType(CONFIG_OPL); configSetInt(configOPL, CONFIG_OPL_HDD_MODE, START_MODE_AUTO); @@ -781,11 +785,11 @@ static int tryAlternateDevice(int types) configInit("mass0:"); } else { // No? Check if the save location on the HDD is available. - dir = opendir("pfs0:"); + dir = opendir(gHDDPrefix); if (dir != NULL) { closedir(dir); configEnd(); - configInit("pfs0:"); + configInit(gHDDPrefix); } } showCfgPopup = 0; @@ -912,7 +916,7 @@ static int trySaveConfigHDD(int types) hddLoadModules(); //Check that the formatted & usable HDD is connected. if (hddCheck() == 0) { - configSetMove("pfs0:"); + configSetMove(gHDDPrefix); return configWriteMulti(types); } @@ -1525,6 +1529,7 @@ static void setDefaults(void) clearIOModuleT(&list_support[APP_MODE]); gBaseMCDir = "mc?:OPL"; + gHDDPrefix = "pfs0:"; ps2_ip_use_dhcp = 1; gETHOpMode = ETH_OP_MODE_AUTO; diff --git a/src/system.c b/src/system.c index e65090ac6..7253af2e6 100644 --- a/src/system.c +++ b/src/system.c @@ -11,6 +11,7 @@ #include "include/opl.h" #include "include/gui.h" #include "include/ethsupport.h" +#include "include/hddsupport.h" #include "include/util.h" #include "include/pad.h" #include "include/system.h" @@ -858,7 +859,9 @@ int sysExecElf(const char *path) elf_pheader_t *eph; void *pdata; int i; - char *elf_argv[1]; + char *elf_argv[2]; + char argv[256]; + int elf_argc = 1; // NB: ELFLDR.ELF is embedded boot_elf = (u8 *)&elfldr_elf; @@ -888,10 +891,16 @@ int sysExecElf(const char *path) elf_argv[0] = (char *)path; + if (strncmp(path, "pfs", 3) == 0) { + snprintf(argv, sizeof(argv), "%s:%s", gOPLPart, elf_argv[0]); + elf_argv[1] = argv; + elf_argc++; + } + FlushCache(0); FlushCache(2); - ExecPS2((void *)eh->entry, NULL, 1, elf_argv); + ExecPS2((void *)eh->entry, NULL, elf_argc, elf_argv); return 0; }