From ec51cc1ce34aa33d2551481bdd681d652bd38860 Mon Sep 17 00:00:00 2001 From: TheFloW Date: Sun, 4 Sep 2016 12:55:15 +0200 Subject: [PATCH] Finished network update feature. --- Makefile | 5 +- VitaShellUpdater/main.c | 0 file.c | 8 +- file.h | 8 +- language.c | 1 + language.h | 1 + main.c | 105 +++++++------ main.h | 4 +- network_update.c | 112 +++++++++++++- network_update.h | 1 + package_installer.c | 8 +- package_installer.h | 9 ++ resources/english_us.txt | 1 + resources/updater_eboot.bin | Bin 0 -> 126816 bytes resources/updater_param.bin | Bin 0 -> 912 bytes {VitaShellUpdater => updater}/Makefile | 17 ++- updater/main.c | 199 +++++++++++++++++++++++++ utils.c | 14 ++ utils.h | 2 + 19 files changed, 426 insertions(+), 69 deletions(-) delete mode 100644 VitaShellUpdater/main.c create mode 100644 resources/updater_eboot.bin create mode 100644 resources/updater_param.bin rename {VitaShellUpdater => updater}/Makefile (62%) create mode 100644 updater/main.c diff --git a/Makefile b/Makefile index 28a323d..6434aec 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,8 @@ RESOURCES_PNG = resources/folder_icon.png resources/file_icon.png resources/arch resources/battery_bar_charge.png resources/headphone.png resources/audio_previous.png resources/audio_pause.png \ resources/audio_play.png resources/audio_next.png RESOURCES_TXT = resources/theme.txt resources/colors.txt resources/english_us.txt -OBJS += $(RESOURCES_PNG:.png=.o) $(RESOURCES_TXT:.txt=.o) +RESOURCES_BIN = resources/updater_eboot.bin resources/updater_param.bin +OBJS += $(RESOURCES_PNG:.png=.o) $(RESOURCES_TXT:.txt=.o) $(RESOURCES_BIN:.bin=.o) LIBS = -lftpvita -lvita2d -lpng -ljpeg -lz -lm -lc \ -lSceAppMgr_stub -lSceAppUtil_stub -lSceCommonDialog_stub \ @@ -59,6 +60,8 @@ $(TARGET).elf: $(OBJS) $(PREFIX)-ld -r -b binary -o $@ $^ %.o: %.txt $(PREFIX)-ld -r -b binary -o $@ $^ +%.o: %.bin + $(PREFIX)-ld -r -b binary -o $@ $^ clean: @rm -rf $(TARGET).vpk $(TARGET).velf $(TARGET).elf $(OBJS) \ diff --git a/VitaShellUpdater/main.c b/VitaShellUpdater/main.c deleted file mode 100644 index e69de29..0000000 diff --git a/file.c b/file.c index 6d55625..e5b3baa 100644 --- a/file.c +++ b/file.c @@ -356,14 +356,16 @@ typedef struct { static ExtensionType extension_types[] = { { ".BMP", FILE_TYPE_BMP }, + { ".INI", FILE_TYPE_INI }, { ".JPG", FILE_TYPE_JPEG }, { ".JPEG", FILE_TYPE_JPEG }, - { ".PNG", FILE_TYPE_PNG }, { ".MP3", FILE_TYPE_MP3 }, + { ".PNG", FILE_TYPE_PNG }, { ".SFO", FILE_TYPE_SFO }, - { ".VPK", FILE_TYPE_VPK }, - { ".ZIP", FILE_TYPE_ZIP }, { ".TXT", FILE_TYPE_TXT }, + { ".VPK", FILE_TYPE_VPK }, + { ".XML", FILE_TYPE_XML }, + { ".ZIP", FILE_TYPE_ZIP }, }; int getFileType(char *file) { diff --git a/file.h b/file.h index 8e64930..70b861b 100644 --- a/file.h +++ b/file.h @@ -32,13 +32,15 @@ enum FileTypes { FILE_TYPE_UNKNOWN, FILE_TYPE_BMP, + FILE_TYPE_INI, FILE_TYPE_JPEG, - FILE_TYPE_PNG, FILE_TYPE_MP3, + FILE_TYPE_PNG, FILE_TYPE_SFO, - FILE_TYPE_VPK, - FILE_TYPE_ZIP, FILE_TYPE_TXT, + FILE_TYPE_VPK, + FILE_TYPE_XML, + FILE_TYPE_ZIP, }; enum SortFlags { diff --git a/language.c b/language.c index 265d263..5242e3c 100644 --- a/language.c +++ b/language.c @@ -85,6 +85,7 @@ void loadLanguage(int id) { LANGUAGE_ENTRY(DELETING), LANGUAGE_ENTRY(INSTALLING), LANGUAGE_ENTRY(DOWNLOADING), + LANGUAGE_ENTRY(EXTRACTING), LANGUAGE_ENTRY(DELETE_FILE_QUESTION), LANGUAGE_ENTRY(DELETE_FOLDER_QUESTION), LANGUAGE_ENTRY(DELETE_FILES_FOLDERS_QUESTION), diff --git a/language.h b/language.h index f2c8df7..f4e3610 100644 --- a/language.h +++ b/language.h @@ -43,6 +43,7 @@ enum LanguageContainer { DELETING, INSTALLING, DOWNLOADING, + EXTRACTING, DELETE_FILE_QUESTION, DELETE_FOLDER_QUESTION, DELETE_FILES_FOLDERS_QUESTION, diff --git a/main.c b/main.c index 0ec9115..8d2d481 100644 --- a/main.c +++ b/main.c @@ -259,7 +259,9 @@ int handleFile(char *file, FileListEntry *entry) { } switch (type) { + case FILE_TYPE_INI: case FILE_TYPE_TXT: + case FILE_TYPE_XML: case FILE_TYPE_UNKNOWN: res = textViewer(file); break; @@ -758,7 +760,6 @@ int dialogSteps() { case DIALOG_STEP_COPIED: case DIALOG_STEP_DELETED: case DIALOG_STEP_INSTALLED: - case DIALOG_STEP_DOWNLOADED: if (msg_result == MESSAGE_DIALOG_RESULT_NONE || msg_result == MESSAGE_DIALOG_RESULT_FINISHED) { refresh = 1; dialog_step = DIALOG_STEP_NONE; @@ -835,47 +836,6 @@ int dialogSteps() { break; - case DIALOG_STEP_INSTALL_QUESTION: - if (msg_result == MESSAGE_DIALOG_RESULT_YES) { - initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[INSTALLING]); - dialog_step = DIALOG_STEP_INSTALL_CONFIRMED; - } else if (msg_result == MESSAGE_DIALOG_RESULT_NO) { - dialog_step = DIALOG_STEP_NONE; - } - - break; - - case DIALOG_STEP_INSTALL_CONFIRMED: - if (msg_result == MESSAGE_DIALOG_RESULT_RUNNING) { - InstallArguments args; - args.file = cur_file; - - SceUID thid = sceKernelCreateThread("install_thread", (SceKernelThreadEntry)install_thread, 0x40, 0x10000, 0, 0, NULL); - if (thid >= 0) - sceKernelStartThread(thid, sizeof(InstallArguments), &args); - - dialog_step = DIALOG_STEP_INSTALLING; - } - - break; - - case DIALOG_STEP_INSTALL_WARNING: - if (msg_result == MESSAGE_DIALOG_RESULT_YES) { - dialog_step = DIALOG_STEP_INSTALL_WARNING_AGREED; - } else if (msg_result == MESSAGE_DIALOG_RESULT_NO) { - dialog_step = DIALOG_STEP_CANCELLED; - } - - break; - - case DIALOG_STEP_UPDATE_QUESTION: - if (msg_result == MESSAGE_DIALOG_RESULT_YES) { - initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[DOWNLOADING]); - dialog_step = DIALOG_STEP_UPDATE_CONFIRMED; - } else if (msg_result == MESSAGE_DIALOG_RESULT_NO) { - dialog_step = DIALOG_STEP_NONE; - } - case DIALOG_STEP_RENAME: if (ime_result == IME_DIALOG_RESULT_FINISHED) { char *name = (char *)getImeDialogInputTextUTF8(); @@ -934,6 +894,65 @@ int dialogSteps() { } break; + + case DIALOG_STEP_INSTALL_QUESTION: + if (msg_result == MESSAGE_DIALOG_RESULT_YES) { + initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[INSTALLING]); + dialog_step = DIALOG_STEP_INSTALL_CONFIRMED; + } else if (msg_result == MESSAGE_DIALOG_RESULT_NO) { + dialog_step = DIALOG_STEP_NONE; + } + + break; + + case DIALOG_STEP_INSTALL_CONFIRMED: + if (msg_result == MESSAGE_DIALOG_RESULT_RUNNING) { + InstallArguments args; + args.file = cur_file; + + SceUID thid = sceKernelCreateThread("install_thread", (SceKernelThreadEntry)install_thread, 0x40, 0x10000, 0, 0, NULL); + if (thid >= 0) + sceKernelStartThread(thid, sizeof(InstallArguments), &args); + + dialog_step = DIALOG_STEP_INSTALLING; + } + + break; + + case DIALOG_STEP_INSTALL_WARNING: + if (msg_result == MESSAGE_DIALOG_RESULT_YES) { + dialog_step = DIALOG_STEP_INSTALL_WARNING_AGREED; + } else if (msg_result == MESSAGE_DIALOG_RESULT_NO) { + dialog_step = DIALOG_STEP_CANCELLED; + } + + break; + + case DIALOG_STEP_UPDATE_QUESTION: + if (msg_result == MESSAGE_DIALOG_RESULT_YES) { + initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[DOWNLOADING]); + dialog_step = DIALOG_STEP_DOWNLOADING; + } else if (msg_result == MESSAGE_DIALOG_RESULT_NO) { + dialog_step = DIALOG_STEP_NONE; + } + + case DIALOG_STEP_DOWNLOADED: + if (msg_result == MESSAGE_DIALOG_RESULT_FINISHED) { + initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[INSTALLING]); + + SceUID thid = sceKernelCreateThread("update_extract_thread", (SceKernelThreadEntry)update_extract_thread, 0x40, 0x10000, 0, 0, NULL); + if (thid >= 0) + sceKernelStartThread(thid, 0, NULL); + + dialog_step = DIALOG_STEP_EXTRACTING; + } + + break; + + case DIALOG_STEP_EXTRACTED: + launchAppByUriExit("VSUPDATER"); + dialog_step = DIALOG_STEP_NONE; + break; } return refresh; @@ -1166,7 +1185,7 @@ int shellMain() { } else if (file_entry->type == FILE_TYPE_SFO) { // SFO // note: specific color to be determined vita2d_draw_texture(sfo_icon, SHELL_MARGIN_X, y + 3.0f); - } else if (file_entry->type == FILE_TYPE_TXT) { // TXT + } else if (file_entry->type == FILE_TYPE_INI || file_entry->type == FILE_TYPE_TXT || file_entry->type == FILE_TYPE_XML) { // TXT // note: specific color to be determined vita2d_draw_texture(text_icon, SHELL_MARGIN_X, y + 3.0f); } else { // Other files diff --git a/main.h b/main.h index 207ba40..77fa9dd 100644 --- a/main.h +++ b/main.h @@ -175,8 +175,10 @@ enum DialogSteps { DIALOG_STEP_RENAME, DIALOG_STEP_UPDATE_QUESTION, - DIALOG_STEP_UPDATE_CONFIRMED, + DIALOG_STEP_DOWNLOADING, DIALOG_STEP_DOWNLOADED, + DIALOG_STEP_EXTRACTING, + DIALOG_STEP_EXTRACTED, }; extern vita2d_pgf *font; diff --git a/network_update.c b/network_update.c index 1d3d715..28e4c00 100644 --- a/network_update.c +++ b/network_update.c @@ -19,11 +19,21 @@ #include "main.h" #include "io_process.h" #include "network_update.h" +#include "package_installer.h" +#include "archive.h" #include "file.h" #include "message_dialog.h" #include "language.h" #include "utils.h" +#define BASE_ADDRESS "https://github.com/TheOfficialFloW/VitaShell/releases/download" +#define VITASHELL_UPDATE_FILE "ux0:VitaShell/VitaShell.vpk" + +extern unsigned char _binary_resources_updater_eboot_bin_start; +extern unsigned char _binary_resources_updater_eboot_bin_size; +extern unsigned char _binary_resources_updater_param_bin_start; +extern unsigned char _binary_resources_updater_param_bin_size; + int getDownloadFileSize(char *src, uint64_t *size) { int tpl = sceHttpCreateTemplate("VitaShell/1.00 libhttp/1.1", SCE_HTTP_VERSION_1_1, 1); if (tpl < 0) @@ -117,7 +127,7 @@ int downloadProcess(char *version_string) { // Download url char url[128]; - sprintf(url, "https://github.com/TheOfficialFloW/VitaShell/releases/download/%s/VitaShell.vpk", version_string); + sprintf(url, BASE_ADDRESS "/%s/VitaShell.vpk", version_string); // File size uint64_t size = 0; @@ -128,7 +138,7 @@ int downloadProcess(char *version_string) { // Download uint64_t value = 0; - int res = downloadFile(url, "ux0:VitaShell/Vitashell.vpk", &value, size, SetProgress, cancelHandler); + int res = downloadFile(url, VITASHELL_UPDATE_FILE, &value, size, SetProgress, cancelHandler); if (res <= 0) { closeWaitDialog(); dialog_step = DIALOG_STEP_CANCELLED; @@ -158,7 +168,7 @@ EXIT: int network_update_thread(SceSize args, void *argp) { sceHttpsDisableOption(SCE_HTTPS_FLAG_SERVER_VERIFY); - if (downloadFile("http://github.com/TheOfficialFloW/VitaShell/releases/download/0.0/version.bin", "ux0:VitaShell/version.bin", NULL, 0, NULL, NULL) > 0) { + if (downloadFile(BASE_ADDRESS "/0.0/version.bin", "ux0:VitaShell/version.bin", NULL, 0, NULL, NULL) > 0) { uint32_t version = 0; ReadFile("ux0:VitaShell/version.bin", &version, sizeof(uint32_t)); sceIoRemove("ux0:VitaShell/version.bin"); @@ -195,5 +205,101 @@ int network_update_thread(SceSize args, void *argp) { } } + return sceKernelExitDeleteThread(0); +} + +int installUpdater() { + // Recursively clean up package_temp directory + removePath(PACKAGE_PARENT, NULL, 0, NULL, NULL); + sceIoMkdir(PACKAGE_PARENT, 0777); + + sceIoMkdir("ux0:ptmp", 0777); + sceIoMkdir("ux0:ptmp/pkg", 0777); + sceIoMkdir("ux0:ptmp/pkg/sce_sys", 0777); + + WriteFile("ux0:ptmp/pkg/eboot.bin", (void *)&_binary_resources_updater_eboot_bin_start, (int)&_binary_resources_updater_eboot_bin_size); + WriteFile("ux0:ptmp/pkg/sce_sys/param.sfo", (void *)&_binary_resources_updater_param_bin_start, (int)&_binary_resources_updater_param_bin_size); + + // Make head.bin + makeHeadBin(); + + // Promote + promote(PACKAGE_DIR); +} + +int update_extract_thread(SceSize args, void *argp) { + SceUID thid = -1; + + // Lock power timers + powerLock(); + + // Set progress to 0% + sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0); + sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage + + // Install updater + installUpdater(); + + // Recursively clean up package_temp directory + removePath(PACKAGE_PARENT, NULL, 0, NULL, NULL); + sceIoMkdir(PACKAGE_PARENT, 0777); + + // Open archive + int res = archiveOpen(VITASHELL_UPDATE_FILE); + if (res < 0) { + closeWaitDialog(); + errorDialog(res); + goto EXIT; + } + + // Src path + char *src_path = VITASHELL_UPDATE_FILE "/"; + + // Get archive path info + uint64_t size = 0; + uint32_t folders = 0, files = 0; + getArchivePathInfo(src_path, &size, &folders, &files); + + // Update thread + thid = createStartUpdateThread(size + folders); + + // Extract process + uint64_t value = 0; + + res = extractArchivePath(src_path, PACKAGE_DIR "/", &value, size + folders, SetProgress, cancelHandler); + if (res <= 0) { + closeWaitDialog(); + dialog_step = DIALOG_STEP_CANCELLED; + errorDialog(res); + goto EXIT; + } + + // Remove update file + sceIoRemove(VITASHELL_UPDATE_FILE); + + // Make head.bin + res = makeHeadBin(); + if (res < 0) { + closeWaitDialog(); + errorDialog(res); + goto EXIT; + } + + // Set progress to 100% + sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100); + sceKernelDelayThread(COUNTUP_WAIT); + + // Close + sceMsgDialogClose(); + + dialog_step = DIALOG_STEP_EXTRACTED; + +EXIT: + if (thid >= 0) + sceKernelWaitThreadEnd(thid, NULL, NULL); + + // Unlock power timers + powerUnlock(); + return sceKernelExitDeleteThread(0); } \ No newline at end of file diff --git a/network_update.h b/network_update.h index 7611f27..fef701c 100644 --- a/network_update.h +++ b/network_update.h @@ -20,5 +20,6 @@ #define __NETWORK_UPDATE_H__ int network_update_thread(SceSize args, void *argp); +int update_extract_thread(SceSize args, void *argp); #endif \ No newline at end of file diff --git a/package_installer.c b/package_installer.c index 58623ce..3afe032 100644 --- a/package_installer.c +++ b/package_installer.c @@ -31,12 +31,6 @@ #include "resources/base_head_bin.h" -#define ntohl __builtin_bswap32 - -#define PACKAGE_PARENT "ux0:ptmp" -#define PACKAGE_DIR PACKAGE_PARENT "/pkg" -#define HEAD_BIN PACKAGE_DIR "/sce_sys/package/head.bin" - void loadScePaf() { uint32_t ptr[0x100] = { 0 }; ptr[0] = 0; @@ -68,7 +62,7 @@ int promote(char *path) { if (res < 0) return res; - sceKernelDelayThread(300 * 1000); + sceKernelDelayThread(100 * 1000); } while (state); int result = 0; diff --git a/package_installer.h b/package_installer.h index fe6a6a5..b45c296 100644 --- a/package_installer.h +++ b/package_installer.h @@ -19,10 +19,19 @@ #ifndef __PACKAGE_INSTALLER_H__ #define __PACKAGE_INSTALLER_H__ +#define ntohl __builtin_bswap32 + +#define PACKAGE_PARENT "ux0:ptmp" +#define PACKAGE_DIR PACKAGE_PARENT "/pkg" +#define HEAD_BIN PACKAGE_DIR "/sce_sys/package/head.bin" + typedef struct { char *file; } InstallArguments; +int promote(char *path); +int makeHeadBin(); + int install_thread(SceSize args_size, InstallArguments *args); #endif \ No newline at end of file diff --git a/resources/english_us.txt b/resources/english_us.txt index 6e9fe21..3a0d2db 100644 --- a/resources/english_us.txt +++ b/resources/english_us.txt @@ -23,6 +23,7 @@ COPYING = "Copying..." DELETING = "Deleting..." INSTALLING = "Installing..." DOWNLOADING = "Downloading..." +EXTRACTING = "Extracting..." DELETE_FILE_QUESTION = "Are you sure you want to delete this file?" DELETE_FOLDER_QUESTION = "Are you sure you want to delete this folder?" DELETE_FILES_FOLDERS_QUESTION = "Are you sure you want to delete these files/folders?" diff --git a/resources/updater_eboot.bin b/resources/updater_eboot.bin new file mode 100644 index 0000000000000000000000000000000000000000..568cda7c371bab343ef26693413eedc026669192 GIT binary patch literal 126816 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%0D78fhJzoilt7cNPK)=F_Q=2(I1 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 literal 0 HcmV?d00001 diff --git a/VitaShellUpdater/Makefile b/updater/Makefile similarity index 62% rename from VitaShellUpdater/Makefile rename to updater/Makefile index de47c87..f9c7982 100644 --- a/VitaShellUpdater/Makefile +++ b/updater/Makefile @@ -1,24 +1,25 @@ TITLE_ID = VSUPDATER -TARGET = VitaShellUpdater +TARGET = updater OBJS = main.o -LIBS = -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CFLAGS = -Wl,-q -Wall -O3 -marm -ASFLAGS = $(CFLAGS) +LIBS = -lSceAppMgr_stub ../libpromoter/libScePromoterUtil_stub.a -lSceSysmodule_stub + +PREFIX = arm-vita-eabi +CC = $(PREFIX)-gcc +CFLAGS = -Wl,-q -Wall -O3 -marm +ASFLAGS = $(CFLAGS) all: $(TARGET).vpk %.vpk: eboot.bin - vita-mksfoex -s TITLE_ID=$(TITLE_ID) "$(TARGET)" param.sfo + vita-mksfoex -s TITLE_ID=$(TITLE_ID) "VitaShell Updater" param.sfo vita-pack-vpk -s param.sfo -b eboot.bin $@ eboot.bin: $(TARGET).velf vita-make-fself $< $@ %.velf: %.elf - vita-elf-create $< $@ + vita-elf-create $< $@ ../libpromoter/promoterutil.json $(TARGET).elf: $(OBJS) $(CC) $(CFLAGS) $^ $(LIBS) -o $@ diff --git a/updater/main.c b/updater/main.c new file mode 100644 index 0000000..4c4013a --- /dev/null +++ b/updater/main.c @@ -0,0 +1,199 @@ +/* + VitaShell + Copyright (C) 2015-2016, TheFloW + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 this program. If not, see . +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "../sysmodule_internal.h" +#include "../libpromoter/promoterutil.h" + +#define TRANSFER_SIZE 64 * 1024 + +#define PACKAGE_PARENT "ux0:ptmp" +#define PACKAGE_DIR PACKAGE_PARENT "/pkg" +#define HEAD_BIN PACKAGE_DIR "/sce_sys/package/head.bin" + +typedef struct SfoHeader { + uint32_t magic; + uint32_t version; + uint32_t keyofs; + uint32_t valofs; + uint32_t count; +} __attribute__((packed)) SfoHeader; + +typedef struct SfoEntry { + uint16_t nameofs; + uint8_t alignment; + uint8_t type; + uint32_t valsize; + uint32_t totalsize; + uint32_t dataofs; +} __attribute__((packed)) SfoEntry; + +int launchAppByUriExit(char *titleid) { + char uri[32]; + sprintf(uri, "psgm:play?titleid=%s", titleid); + + sceKernelDelayThread(10000); + sceAppMgrLaunchAppByUri(0xFFFFF, uri); + sceKernelDelayThread(10000); + sceAppMgrLaunchAppByUri(0xFFFFF, uri); + + sceKernelExitProcess(0); + + return 0; +} + +int copyFile(char *src_path, char *dst_path) { + SceUID fdsrc = sceIoOpen(src_path, SCE_O_RDONLY, 0); + if (fdsrc < 0) + return fdsrc; + + SceUID fddst = sceIoOpen(dst_path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); + if (fddst < 0) { + sceIoClose(fdsrc); + return fddst; + } + + void *buf = malloc(TRANSFER_SIZE); + + int read; + while ((read = sceIoRead(fdsrc, buf, TRANSFER_SIZE)) > 0) { + sceIoWrite(fddst, buf, read); + } + + free(buf); + + sceIoClose(fddst); + sceIoClose(fdsrc); + + return 0; +} + +void loadScePaf() { + uint32_t ptr[0x100] = { 0 }; + ptr[0] = 0; + ptr[1] = (uint32_t)&ptr[0]; + uint32_t scepaf_argp[] = { 0x400000, 0xEA60, 0x40000, 0, 0 }; + sceSysmoduleLoadModuleInternalWithArg(0x80000008, sizeof(scepaf_argp), scepaf_argp, ptr); +} + +int promote(char *path) { + int res; + + loadScePaf(); + + res = sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_PROMOTER_UTIL); + if (res < 0) + return res; + + res = scePromoterUtilityInit(); + if (res < 0) + return res; + + res = scePromoterUtilityPromotePkg(path, 0); + if (res < 0) + return res; + + int state = 0; + do { + res = scePromoterUtilityGetState(&state); + if (res < 0) + return res; + + sceKernelDelayThread(100 * 1000); + } while (state); + + int result = 0; + res = scePromoterUtilityGetResult(&result); + if (res < 0) + return res; + + res = scePromoterUtilityExit(); + if (res < 0) + return res; + + res = sceSysmoduleUnloadModuleInternal(SCE_SYSMODULE_PROMOTER_UTIL); + if (res < 0) + return res; + + return result; +} + +char *get_title_id(const char *filename) { + char *res = NULL; + long size = 0; + FILE *fin = NULL; + char *buf = NULL; + int i; + + SfoHeader *header; + SfoEntry *entry; + + fin = fopen(filename, "rb"); + if (!fin) + goto cleanup; + if (fseek(fin, 0, SEEK_END) != 0) + goto cleanup; + if ((size = ftell(fin)) == -1) + goto cleanup; + if (fseek(fin, 0, SEEK_SET) != 0) + goto cleanup; + buf = calloc(1, size + 1); + if (!buf) + goto cleanup; + if (fread(buf, size, 1, fin) != 1) + goto cleanup; + + header = (SfoHeader*)buf; + entry = (SfoEntry*)(buf + sizeof(SfoHeader)); + for (i = 0; i < header->count; ++i, ++entry) { + const char *name = buf + header->keyofs + entry->nameofs; + const char *value = buf + header->valofs + entry->dataofs; + if (name >= buf + size || value >= buf + size) + break; + if (strcmp(name, "TITLE_ID") == 0) + res = strdup(value); + } + +cleanup: + if (buf) + free(buf); + if (fin) + fclose(fin); + + return res; +} + +int main(int argc, const char *argv[]) { + char *titleid = get_title_id(PACKAGE_DIR "/sce_sys/param.sfo"); + if (strcmp(titleid, "VITASHELL") == 0) { + copyFile(PACKAGE_DIR "/eboot.bin", "ux0:app/MLCL00001/eboot.bin"); + + if (promote(PACKAGE_DIR) >= 0) + launchAppByUriExit("VITASHELL"); + } + + return sceKernelExitProcess(0); +} \ No newline at end of file diff --git a/utils.c b/utils.c index f4a7c75..6a76714 100644 --- a/utils.c +++ b/utils.c @@ -299,5 +299,19 @@ int debugPrintf(char *text, ...) { #endif #endif + return 0; +} + +int launchAppByUriExit(char *titleid) { + char uri[32]; + sprintf(uri, "psgm:play?titleid=%s", titleid); + + sceKernelDelayThread(10000); + sceAppMgrLaunchAppByUri(0xFFFFF, uri); + sceKernelDelayThread(10000); + sceAppMgrLaunchAppByUri(0xFFFFF, uri); + + sceKernelExitProcess(0); + return 0; } \ No newline at end of file diff --git a/utils.h b/utils.h index dc6fc54..f96fb11 100644 --- a/utils.h +++ b/utils.h @@ -71,4 +71,6 @@ int randomNumber(int low, int high); int debugPrintf(char *text, ...); +int launchAppByUriExit(char *titleid); + #endif