From ee7060cdc172608f20898209f662f31d06b01534 Mon Sep 17 00:00:00 2001 From: Bluzume <39113159+KuromeSan@users.noreply.github.com> Date: Thu, 16 Jan 2020 07:54:36 +1300 Subject: [PATCH] Add Support for PlayStation Mobile games in "Refresh Livearea" (#557) * Add Suppot for PlayStation Mobile games in "Refresh Livearea" * Add support for PlayStation Mobile games to "Refresh Livearea" (and my credits ofc-) * Switched to vitasdk provied structs * Add files via upload --- package_installer.c | 45 +++++++++++++ package_installer.h | 1 + refresh.c | 160 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 176 insertions(+), 30 deletions(-) diff --git a/package_installer.c b/package_installer.c index 7cadb36..76f58cc 100644 --- a/package_installer.c +++ b/package_installer.c @@ -48,6 +48,51 @@ static int unloadScePaf() { return sceSysmoduleUnloadModuleInternalWithArg(SCE_SYSMODULE_INTERNAL_PAF, 0, NULL, &buf); } +int promotePsm(const char *path, const char *titleid) +{ + + ScePromoterUtilityImportParams promoteArgs; + memset(&promoteArgs,0x00,sizeof(ScePromoterUtilityImportParams)); + + strncpy(promoteArgs.path,path,0x7F); + strncpy(promoteArgs.titleid,titleid,0xB); + + promoteArgs.type = SCE_PKG_TYPE_PSM; + promoteArgs.attribute = 0x1; + + int res; + + res = loadScePaf(); + if (res < 0) + return res; + + res = sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_PROMOTER_UTIL); + if (res < 0) + return res; + + res = scePromoterUtilityInit(); + if (res < 0) + return res; + + res = scePromoterUtilityPromoteImport(&promoteArgs); + if (res < 0) + return res; + + res = scePromoterUtilityExit(); + if (res < 0) + return res; + + res = sceSysmoduleUnloadModuleInternal(SCE_SYSMODULE_INTERNAL_PROMOTER_UTIL); + if (res < 0) + return res; + + res = unloadScePaf(); + if (res < 0) + return res; + + return res; +} + int promoteApp(const char *path) { int res; diff --git a/package_installer.h b/package_installer.h index ac802f9..2a56e02 100644 --- a/package_installer.h +++ b/package_installer.h @@ -29,6 +29,7 @@ typedef struct { } InstallArguments; int promoteApp(const char *path); +int promotePsm(const char *path, const char *titleid); int deleteApp(const char *titleid); int checkAppExist(const char *titleid); diff --git a/refresh.c b/refresh.c index e38f060..72ca0d9 100644 --- a/refresh.c +++ b/refresh.c @@ -3,6 +3,7 @@ Copyright (C) 2015-2018, TheFloW Copyright (C) 2017, VitaSmith Copyright (C) 2018, TheRadziu + Copyright (C) 2020, SilicaAndPina This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,7 +37,7 @@ #define APP_TEMP "ux0:temp/app" #define DLC_TEMP "ux0:temp/addcont" #define PATCH_TEMP "ux0:temp/patch" -#define PSM_TEMP "ux0:temp/psm" +#define PSM_TEMP "ux0:temp/game" #define THEME_TEMP "ux0:temp/theme" #define MAX_DLC_PER_TITLE 1024 @@ -55,60 +56,98 @@ int isCustomHomebrew(const char* path) return 1; } + + int refreshNeeded(const char *app_path, const char* content_type) { - char sfo_path[MAX_PATH_LENGTH]; char appmeta_path[MAX_PATH_LENGTH]; char appmeta_param[MAX_PATH_LENGTH]; + char sfo_path[MAX_PATH_LENGTH]; int mounted_appmeta; - - // Read param.sfo - snprintf(sfo_path, MAX_PATH_LENGTH, "%s/sce_sys/param.sfo", app_path); - void *sfo_buffer = NULL; - int sfo_size = allocateReadFile(sfo_path, &sfo_buffer); - if (sfo_size < 0) - return sfo_size; - - // Get title and content ids char titleid[12], contentid[50], appver[8]; - getSfoString(sfo_buffer, "TITLE_ID", titleid, sizeof(titleid)); - getSfoString(sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid)); - getSfoString(sfo_buffer, "APP_VER", appver, sizeof(appver)); + if(strcmp(content_type,"psm") == 0) + { + char contentid_path[MAX_PATH_LENGTH]; + void *cidFile = NULL; + + //Initalize buffers + memset(titleid,0,12); + memset(contentid,0,50); + memset(appver,0,8); + + snprintf(contentid_path, MAX_PATH_LENGTH, "%s/RW/System/content_id", app_path); + + // Get content id + int contentid_size = allocateReadFile(contentid_path, &cidFile); + if(contentid_size < 0) + return contentid_size; + + // Get title id from content id + strncpy(titleid,cidFile+7,9); + strncpy(contentid,cidFile,49); + + + free(cidFile); + + int isExist = checkAppExist(titleid); + } + else + { + // Read param.sfo + snprintf(sfo_path, MAX_PATH_LENGTH, "%s/sce_sys/param.sfo", app_path); + + void *sfo_buffer = NULL; + int sfo_size = allocateReadFile(sfo_path, &sfo_buffer); + if (sfo_size < 0) + return sfo_size; - // Free sfo buffer - free(sfo_buffer); + // Get title and content ids + + getSfoString(sfo_buffer, "TITLE_ID", titleid, sizeof(titleid)); + getSfoString(sfo_buffer, "CONTENT_ID", contentid, sizeof(contentid)); + getSfoString(sfo_buffer, "APP_VER", appver, sizeof(appver)); + // Free sfo buffer + free(sfo_buffer); + } + + // Check if app or dlc exists - if (((strcmp(content_type, "app") == 0)||(strcmp(content_type, "dlc") == 0))&&(checkAppExist(titleid))) { + if (((strcmp(content_type, "app") == 0)||(strcmp(content_type, "dlc") == 0)||(strcmp(content_type,"psm") == 0))&&(checkAppExist(titleid))) { char rif_name[48]; - + char rif_path[MAX_PATH_LENGTH]; + uint64_t aid; sceRegMgrGetKeyBin("/CONFIG/NP", "account_id", &aid, sizeof(uint64_t)); // Check if bounded rif file exits _sceNpDrmGetRifName(rif_name, 0, aid); if (strcmp(content_type, "app") == 0) - snprintf(sfo_path, MAX_PATH_LENGTH, "ux0:license/app/%s/%s", titleid, rif_name); + snprintf(rif_path, MAX_PATH_LENGTH, "ux0:license/app/%s/%s", titleid, rif_name); else if (strcmp(content_type, "dlc") == 0) - snprintf(sfo_path, MAX_PATH_LENGTH, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name); - if (checkFileExist(sfo_path)) + snprintf(rif_path, MAX_PATH_LENGTH, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name); + if (checkFileExist(rif_path)) return 0; - + // Check if fixed rif file exits _sceNpDrmGetFixedRifName(rif_name, 0, 0); if (strcmp(content_type, "app") == 0) - snprintf(sfo_path, MAX_PATH_LENGTH, "ux0:license/app/%s/%s", titleid, rif_name); + snprintf(rif_path, MAX_PATH_LENGTH, "ux0:license/app/%s/%s", titleid, rif_name); else if (strcmp(content_type, "dlc") == 0) - snprintf(sfo_path, MAX_PATH_LENGTH, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name); - if (checkFileExist(sfo_path)) + snprintf(rif_path, MAX_PATH_LENGTH, "ux0:license/addcont/%s/%s/%s", titleid, &contentid[20], rif_name); + if (checkFileExist(rif_path)) return 0; - } + + if(strcmp(content_type,"psm") == 0) + return 0; + } // Check if patch for installed app exists else if (strcmp(content_type, "patch") == 0) { if (!checkAppExist(titleid)) return 0; if (checkFileExist(sfo_path)) { + void *sfo_buffer = NULL; snprintf(appmeta_path, MAX_PATH_LENGTH, "ux0:appmeta/%s", titleid); pfsUmount(); if(pfsMount(appmeta_path)<0) @@ -326,6 +365,57 @@ void patch_callback(void* data, const char* dir, const char* subdir) } } +void psm_callback(void* data, const char* dir, const char* subdir) +{ + refresh_data_t *refresh_data = (refresh_data_t*)data; + char path[MAX_PATH_LENGTH]; + + if (strcasecmp(subdir, vitashell_titleid) == 0) + return; + + if (refresh_data->refresh_pass) { + snprintf(path, MAX_PATH_LENGTH, "%s/%s", dir, subdir); + if (refreshNeeded(path, "psm")) { + char contentid_path[MAX_PATH_LENGTH]; + snprintf(contentid_path, MAX_PATH_LENGTH, "%s/RW/System/content_id", path); + + char titleid[12]; + void *cidFile = NULL; + + // Initalize Bufer + memset(titleid,0,12); + + // Get content id + allocateReadFile(contentid_path, &cidFile); + + // Get title id from content id + strncpy(titleid,cidFile+7,9); + + //free buffers + free(cidFile); + + + // Get promote path + char promote_path[MAX_PATH_LENGTH]; + snprintf(promote_path,MAX_PATH_LENGTH,"%s/%s",PSM_TEMP,titleid); + + // Move the directory to temp for installation + removePath(promote_path, NULL); + sceIoRename(path, promote_path); + + // Finally call promote + if (promotePsm(PSM_TEMP,titleid) == 0) + refresh_data->refreshed++; + else + // Restore folder on error + sceIoRename(promote_path, path); + } + SetProgress(++refresh_data->processed, refresh_data->count); + } else { + refresh_data->count++; + } +} + int refresh_thread(SceSize args, void *argp) { SceUID thid = -1; @@ -350,13 +440,18 @@ int refresh_thread(SceSize args, void *argp) if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:patch", patch_callback, &refresh_data) < 0) goto EXIT; + // Get the psm count + if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:psm", psm_callback, &refresh_data) < 0) + goto EXIT; + // Update thread thid = createStartUpdateThread(refresh_data.count, 0); // Make sure we have the temp directories we need sceIoMkdir("ux0:temp", 0006); - sceIoMkdir("ux0:temp/addcont", 0006); - sceIoMkdir("ux0:temp/patch", 0006); + sceIoMkdir(DLC_TEMP, 0006); + sceIoMkdir(PATCH_TEMP, 0006); + sceIoMkdir(PSM_TEMP, 0006); refresh_data.refresh_pass = 1; // Refresh apps @@ -371,8 +466,13 @@ int refresh_thread(SceSize args, void *argp) if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:patch", patch_callback, &refresh_data) < 0) goto EXIT; - sceIoRmdir("ux0:temp/addcont"); - sceIoRmdir("ux0:temp/patch"); + // Refresh psm + if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:psm", psm_callback, &refresh_data) < 0) + goto EXIT; + + sceIoRmdir(DLC_TEMP); + sceIoRmdir(PATCH_TEMP); + sceIoRmdir(PSM_TEMP); // Set progress to 100% sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100);