diff --git a/main.h b/main.h index 280e656..b080e65 100644 --- a/main.h +++ b/main.h @@ -54,7 +54,7 @@ // VitaShell version major.minor #define VITASHELL_VERSION_MAJOR 0x02 -#define VITASHELL_VERSION_MINOR 0x02 +#define VITASHELL_VERSION_MINOR 0x00 #define VITASHELL_VERSION ((VITASHELL_VERSION_MAJOR << 0x18) | (VITASHELL_VERSION_MINOR << 0x10)) diff --git a/package_installer.c b/package_installer.c index 7cadb36..c07de09 100644 --- a/package_installer.c +++ b/package_installer.c @@ -48,6 +48,47 @@ static int unloadScePaf() { return sceSysmoduleUnloadModuleInternalWithArg(SCE_SYSMODULE_INTERNAL_PAF, 0, NULL, &buf); } +int promotePsm(const char *path, const char *titleid) { + int res; + + 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; + + 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..56373a6 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,13 +37,12 @@ #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 -int isCustomHomebrew(const char* path) -{ +int isCustomHomebrew(const char* path) { uint32_t work[RIF_SIZE/4]; if (ReadFile(path, work, sizeof(work)) != sizeof(work)) @@ -55,82 +55,115 @@ int isCustomHomebrew(const char* path) return 1; } -int refreshNeeded(const char *app_path, const char* content_type) -{ - char sfo_path[MAX_PATH_LENGTH]; + + +int refreshNeeded(const char *app_path, const char* content_type) { 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 != 48) //Check if valid contentid file + return 0; + + // Get title id from content id + strncpy(titleid,cidFile+7,9); + strncpy(contentid,cidFile,49); + + + free(cidFile); + } + 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 0; - // 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)) { + if (checkFileExist(sfo_path)) { + void *sfo_buffer = NULL; snprintf(appmeta_path, MAX_PATH_LENGTH, "ux0:appmeta/%s", titleid); pfsUmount(); if(pfsMount(appmeta_path)<0) return 0; //Now read it - snprintf(appmeta_param, MAX_PATH_LENGTH, "ux0:appmeta/%s/param.sfo", titleid); + snprintf(appmeta_param, MAX_PATH_LENGTH, "ux0:appmeta/%s/param.sfo", titleid); int sfo_size = allocateReadFile(appmeta_param, &sfo_buffer); if (sfo_size < 0) return sfo_size; char promoted_appver[8]; getSfoString(sfo_buffer, "APP_VER", promoted_appver, sizeof(promoted_appver)); pfsUmount(); - //Finally compare it - if (strcmp(appver, promoted_appver) == 0) - return 0; + //Finally compare it + if (strcmp(appver, promoted_appver) == 0) + return 0; } } return 1; } -int refreshApp(const char *app_path) -{ +int refreshApp(const char *app_path) { char work_bin_path[MAX_PATH_LENGTH]; int res; @@ -166,8 +199,7 @@ int refreshApp(const char *app_path) } // target_type should be either SCE_S_IFREG for files or SCE_S_IFDIR for directories -int parse_dir_with_callback(int target_type, const char* path, void(*callback)(void*, const char*, const char*), void* data) -{ +int parse_dir_with_callback(int target_type, const char* path, void(*callback)(void*, const char*, const char*), void* data) { SceUID dfd = sceIoDopen(path); if (dfd >= 0) { int res = 0; @@ -216,8 +248,7 @@ typedef struct { uint8_t* rif; } license_data_t; -void app_callback(void* data, const char* dir, const char* subdir) -{ +void app_callback(void* data, const char* dir, const char* subdir) { refresh_data_t *refresh_data = (refresh_data_t*)data; char path[MAX_PATH_LENGTH]; @@ -242,8 +273,7 @@ void app_callback(void* data, const char* dir, const char* subdir) } } -void dlc_callback_inner(void* data, const char* dir, const char* subdir) -{ +void dlc_callback_inner(void* data, const char* dir, const char* subdir) { dlc_data_t *dlc_data = (dlc_data_t*)data; char path[MAX_PATH_LENGTH]; @@ -260,8 +290,7 @@ void dlc_callback_inner(void* data, const char* dir, const char* subdir) } } -void dlc_callback_outer(void* data, const char* dir, const char* subdir) -{ +void dlc_callback_outer(void* data, const char* dir, const char* subdir) { refresh_data_t *refresh_data = (refresh_data_t*)data; dlc_data_t dlc_data; dlc_data.refresh_data = refresh_data; @@ -303,8 +332,7 @@ void dlc_callback_outer(void* data, const char* dir, const char* subdir) } } -void patch_callback(void* data, const char* dir, const char* subdir) -{ +void patch_callback(void* data, const char* dir, const char* subdir) { refresh_data_t *refresh_data = (refresh_data_t*)data; char path[MAX_PATH_LENGTH]; @@ -326,8 +354,56 @@ void patch_callback(void* data, const char* dir, const char* subdir) } } -int refresh_thread(SceSize args, void *argp) -{ +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 + sceIoRename(promote_path, path); // Restore folder on error + } + SetProgress(++refresh_data->processed, refresh_data->count); + } else { + refresh_data->count++; + } +} + +int refresh_thread(SceSize args, void *argp) { SceUID thid = -1; refresh_data_t refresh_data = { 0, 0, 0, 0 }; @@ -350,13 +426,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 @@ -366,13 +447,18 @@ int refresh_thread(SceSize args, void *argp) // Refresh dlc if (parse_dir_with_callback(SCE_S_IFDIR, "ux0:addcont", dlc_callback_outer, &refresh_data) < 0) goto EXIT; - + // Refresh patch 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); @@ -396,8 +482,7 @@ EXIT: // Note: This is currently not optimized AT ALL. // Ultimately, we want to use a single transaction and avoid trying to // re-insert rifs that are already present. -void license_file_callback(void* data, const char* dir, const char* file) -{ +void license_file_callback(void* data, const char* dir, const char* file) { license_data_t *license_data = (license_data_t*)data; char path[MAX_PATH_LENGTH]; @@ -421,8 +506,7 @@ void license_file_callback(void* data, const char* dir, const char* file) } } -void license_dir_callback(void* data, const char* dir, const char* subdir) -{ +void license_dir_callback(void* data, const char* dir, const char* subdir) { license_data_t *license_data = (license_data_t*)data; char path[MAX_PATH_LENGTH]; @@ -434,8 +518,7 @@ void license_dir_callback(void* data, const char* dir, const char* subdir) license_data->cur_depth--; } -int license_thread(SceSize args, void *argp) -{ +int license_thread(SceSize args, void *argp) { SceUID thid = -1; license_data_t license_data = { 0, 0, 0, 0, 0, 1, malloc(RIF_SIZE) };