mirror of
https://github.com/joel16/VitaShell.git
synced 2024-11-23 11:49:40 +00:00
Added ability to open savedatas and trophys decrypted.
This commit is contained in:
parent
6717abf9c6
commit
61b7b03194
@ -14,7 +14,7 @@ project(VitaShell)
|
||||
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
||||
set(VITA_APP_NAME "VitaShell")
|
||||
set(VITA_TITLEID "VITASHELL")
|
||||
set(VITA_VERSION "01.83")
|
||||
set(VITA_VERSION "01.90")
|
||||
|
||||
# Flags and includes
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-format-truncation -fno-lto")
|
||||
|
@ -107,6 +107,10 @@ Credits
|
||||
Changelog
|
||||
---------
|
||||
|
||||
### Changelog 1.9
|
||||
- Added ability to open decrypted trophys, savedatas and appmetas.
|
||||
- Moved `Open Decrypted` entry to main context menu for faster access.
|
||||
|
||||
### Changelog 1.83
|
||||
- Fixed automatic network update by using rawgit. This was needed because github removed support for TLS 1.0/1.1.
|
||||
- Removed changelog support, because the files at ux0:patch must now be pfs encrypted.
|
||||
|
1
init.c
1
init.c
@ -329,6 +329,7 @@ void initVitaShell() {
|
||||
|
||||
// Allow writing to ux0:app/VITASHELL
|
||||
sceAppMgrUmount("app0:");
|
||||
sceAppMgrUmount("savedata0:");
|
||||
|
||||
// Is safe mode
|
||||
if (sceIoDevctl("ux0:", 0x3001, NULL, 0, NULL, 0) == 0x80010030)
|
||||
|
14
main.c
14
main.c
@ -137,7 +137,7 @@ static void dirUp() {
|
||||
strcmp(file_list.path, pfs_mounted_path) == 0 && // we're about to leave the pfs path
|
||||
!strstr(copy_list.path, pfs_mounted_path)) { // nothing has been copied from pfs path
|
||||
// Then umount
|
||||
gameDataUmount();
|
||||
pfsUmount();
|
||||
}
|
||||
|
||||
removeEndSlash(file_list.path);
|
||||
@ -611,8 +611,10 @@ static int dialogSteps() {
|
||||
fileListEmpty(©_list);
|
||||
|
||||
// Umount and remove from clipboard after pasting
|
||||
if (pfs_mounted_path[0] && strstr(copy_list.path, pfs_mounted_path)) {
|
||||
gameDataUmount();
|
||||
if (pfs_mounted_path[0] &&
|
||||
!strstr(file_list.path, pfs_mounted_path) &&
|
||||
strstr(copy_list.path, pfs_mounted_path)) {
|
||||
pfsUmount();
|
||||
fileListEmpty(©_list);
|
||||
}
|
||||
|
||||
@ -1713,7 +1715,7 @@ static int shellMain() {
|
||||
// Refresh on app resume
|
||||
if (event.systemEvent == SCE_APPMGR_SYSTEMEVENT_ON_RESUME) {
|
||||
sceShellUtilLock(SCE_SHELL_UTIL_LOCK_TYPE_USB_CONNECTION);
|
||||
gameDataUmount(); // umount game data at resume
|
||||
pfsUmount(); // umount game data at resume
|
||||
refresh = REFRESH_MODE_NORMAL;
|
||||
}
|
||||
|
||||
@ -1931,7 +1933,7 @@ int main(int argc, const char *argv[]) {
|
||||
readPad();
|
||||
if (current_pad[PAD_LTRIGGER])
|
||||
use_custom_config = 0;
|
||||
|
||||
|
||||
// Load settings
|
||||
loadSettingsConfig();
|
||||
|
||||
@ -1944,7 +1946,7 @@ int main(int argc, const char *argv[]) {
|
||||
// Init context menu width
|
||||
initContextMenuWidth();
|
||||
initTextContextMenuWidth();
|
||||
|
||||
|
||||
// Automatic network update
|
||||
if (!vitashell_config.disable_autoupdate) {
|
||||
SceUID thid = sceKernelCreateThread("network_update_thread", (SceKernelThreadEntry)network_update_thread, 0x10000100, 0x100000, 0, 0, NULL);
|
||||
|
2
main.h
2
main.h
@ -53,7 +53,7 @@
|
||||
|
||||
// VitaShell version major.minor
|
||||
#define VITASHELL_VERSION_MAJOR 0x01
|
||||
#define VITASHELL_VERSION_MINOR 0x83
|
||||
#define VITASHELL_VERSION_MINOR 0x90
|
||||
|
||||
#define VITASHELL_VERSION ((VITASHELL_VERSION_MAJOR << 0x18) | (VITASHELL_VERSION_MINOR << 0x10))
|
||||
|
||||
|
225
main_context.c
225
main_context.c
@ -31,6 +31,7 @@
|
||||
|
||||
char pfs_mounted_path[MAX_PATH_LENGTH];
|
||||
char pfs_mount_point[MAX_MOUNT_POINT_LENGTH];
|
||||
int read_only = 0;
|
||||
|
||||
enum MenuHomeEntrys {
|
||||
MENU_HOME_ENTRY_REFRESH_LIVEAREA,
|
||||
@ -53,6 +54,7 @@ MenuEntry menu_home_entries[] = {
|
||||
#define N_MENU_HOME_ENTRIES (sizeof(menu_home_entries) / sizeof(MenuEntry))
|
||||
|
||||
enum MenuMainEntrys {
|
||||
MENU_MAIN_ENTRY_OPEN_DECRYPTED,
|
||||
MENU_MAIN_ENTRY_MARK_UNMARK_ALL,
|
||||
MENU_MAIN_ENTRY_MOVE,
|
||||
MENU_MAIN_ENTRY_COPY,
|
||||
@ -68,18 +70,19 @@ enum MenuMainEntrys {
|
||||
};
|
||||
|
||||
MenuEntry menu_main_entries[] = {
|
||||
{ MARK_ALL, 0, 0, CTX_INVISIBLE },
|
||||
{ MOVE, 2, 0, CTX_INVISIBLE },
|
||||
{ COPY, 3, 0, CTX_INVISIBLE },
|
||||
{ PASTE, 4, 0, CTX_INVISIBLE },
|
||||
{ DELETE, 6, 0, CTX_INVISIBLE },
|
||||
{ RENAME, 7, 0, CTX_INVISIBLE },
|
||||
{ NEW_FOLDER, 9, 0, CTX_INVISIBLE },
|
||||
{ PROPERTIES, 10, 0, CTX_INVISIBLE },
|
||||
{ SORT_BY, 12, CTX_FLAG_MORE, CTX_VISIBLE },
|
||||
{ MORE, 13, CTX_FLAG_MORE, CTX_INVISIBLE },
|
||||
{ SEND, 17, 0, CTX_INVISIBLE }, // CTX_FLAG_BARRIER
|
||||
{ RECEIVE, 18, 0, CTX_INVISIBLE },
|
||||
{ OPEN_DECRYPTED, 0, 0, CTX_INVISIBLE },
|
||||
{ MARK_ALL, 1, 0, CTX_INVISIBLE },
|
||||
{ MOVE, 3, 0, CTX_INVISIBLE },
|
||||
{ COPY, 4, 0, CTX_INVISIBLE },
|
||||
{ PASTE, 5, 0, CTX_INVISIBLE },
|
||||
{ DELETE, 7, 0, CTX_INVISIBLE },
|
||||
{ RENAME, 8, 0, CTX_INVISIBLE },
|
||||
{ NEW_FOLDER, 10, 0, CTX_INVISIBLE },
|
||||
{ PROPERTIES, 11, 0, CTX_INVISIBLE },
|
||||
{ SORT_BY, 13, CTX_FLAG_MORE, CTX_VISIBLE },
|
||||
{ MORE, 14, CTX_FLAG_MORE, CTX_INVISIBLE },
|
||||
{ SEND, 17, 0, CTX_INVISIBLE }, // CTX_FLAG_BARRIER
|
||||
{ RECEIVE, 18, 0, CTX_INVISIBLE },
|
||||
};
|
||||
|
||||
#define N_MENU_MAIN_ENTRIES (sizeof(menu_main_entries) / sizeof(MenuEntry))
|
||||
@ -104,7 +107,6 @@ enum MenuMoreEntrys {
|
||||
MENU_MORE_ENTRY_INSTALL_FOLDER,
|
||||
MENU_MORE_ENTRY_EXPORT_MEDIA,
|
||||
MENU_MORE_ENTRY_CALCULATE_SHA1,
|
||||
MENU_MORE_ENTRY_OPEN_DECRYPTED,
|
||||
};
|
||||
|
||||
MenuEntry menu_more_entries[] = {
|
||||
@ -113,7 +115,6 @@ MenuEntry menu_more_entries[] = {
|
||||
{ INSTALL_FOLDER, 14, 0, CTX_INVISIBLE },
|
||||
{ EXPORT_MEDIA, 15, 0, CTX_INVISIBLE },
|
||||
{ CALCULATE_SHA1, 16, 0, CTX_INVISIBLE },
|
||||
{ OPEN_DECRYPTED, 17, 0, CTX_INVISIBLE },
|
||||
};
|
||||
|
||||
#define N_MENU_MORE_ENTRIES (sizeof(menu_more_entries) / sizeof(MenuEntry))
|
||||
@ -159,13 +160,73 @@ ContextMenu context_menu_more = {
|
||||
.sel = -1,
|
||||
};
|
||||
|
||||
int gameDataMount(const char *path) {
|
||||
int res = sceAppMgrGameDataMount(path, 0, 0, pfs_mount_point);
|
||||
debugPrintf("res: 0x%08X, %s\n", res, pfs_mount_point);
|
||||
return res;
|
||||
/*
|
||||
SceAppMgr mount IDs:
|
||||
0x64: ux0:picture
|
||||
0x65: ur0:user/00/psnfriend
|
||||
0x66: ur0:user/00/psnmsg
|
||||
0x69: ux0:music
|
||||
0x6E: ux0:appmeta
|
||||
0xC8: ur0:temp/sqlite
|
||||
0xCD: ux0:cache
|
||||
0x12E: ur0:user/00/trophy/data/sce_trop
|
||||
0x12F: ur0:user/00/trophy/data
|
||||
0x3E8: ux0:app, vs0:app, gro0:app
|
||||
0x3E9: ux0:patch
|
||||
0x3EB: ?
|
||||
0x3EA: ux0:addcont
|
||||
0x3EC: ux0:theme
|
||||
0x3ED: ux0:user/00/savedata
|
||||
0x3EE: ur0:user/00/savedata
|
||||
0x3EF: vs0:sys/external
|
||||
0x3F0: vs0:data/external
|
||||
*/
|
||||
|
||||
int known_pfs_ids[] = {
|
||||
0x6E,
|
||||
0x12E,
|
||||
0x12F,
|
||||
0x3ED,
|
||||
};
|
||||
|
||||
int pfsMount(const char *path) {
|
||||
int res;
|
||||
char work_path[MAX_PATH_LENGTH];
|
||||
char klicensee[0x10];
|
||||
char license_buf[0x200];
|
||||
ShellMountIdArgs args;
|
||||
|
||||
memset(klicensee, 0, sizeof(klicensee));
|
||||
|
||||
/*
|
||||
snprintf(work_path, MAX_PATH_LENGTH - 1, "%ssce_sys/package/work.bin", path);
|
||||
if (ReadFile(work_path, license_buf, sizeof(license_buf)) == sizeof(license_buf)) {
|
||||
int res = shellUserGetRifVitaKey(license_buf, klicensee);
|
||||
debugPrintf("read license: 0x%08X\n", res);
|
||||
}
|
||||
*/
|
||||
args.process_titleid = VITASHELL_TITLEID;
|
||||
args.path = path;
|
||||
args.desired_mount_point = NULL;
|
||||
args.klicensee = klicensee;
|
||||
args.mount_point = pfs_mount_point;
|
||||
|
||||
read_only = 0;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < sizeof(known_pfs_ids) / sizeof(int); i++) {
|
||||
args.id = known_pfs_ids[i];
|
||||
|
||||
res = shellUserMountById(&args);
|
||||
if (res >= 0)
|
||||
return res;
|
||||
}
|
||||
|
||||
read_only = 1;
|
||||
return sceAppMgrGameDataMount(path, 0, 0, pfs_mount_point);
|
||||
}
|
||||
|
||||
int gameDataUmount() {
|
||||
int pfsUmount() {
|
||||
if (pfs_mount_point[0] == 0)
|
||||
return -1;
|
||||
|
||||
@ -275,6 +336,7 @@ void setContextMenuMainVisibilities() {
|
||||
|
||||
// Invisble entries when on '..'
|
||||
if (strcmp(file_entry->name, DIR_UP) == 0) {
|
||||
menu_main_entries[MENU_MAIN_ENTRY_OPEN_DECRYPTED].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_MARK_UNMARK_ALL].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_MOVE].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_COPY].visibility = CTX_INVISIBLE;
|
||||
@ -309,9 +371,10 @@ void setContextMenuMainVisibilities() {
|
||||
}
|
||||
}
|
||||
|
||||
// Invisible write operations in archives or pfs mounted paths
|
||||
// Invisible write operations in archives
|
||||
// TODO: read-only mount points
|
||||
if (isInArchive() || (pfs_mounted_path[0] && strstr(file_list.path, pfs_mounted_path))) {
|
||||
if (isInArchive() || (pfs_mounted_path[0] && strstr(file_list.path, pfs_mounted_path) && read_only)) {
|
||||
menu_main_entries[MENU_MAIN_ENTRY_OPEN_DECRYPTED].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_MOVE].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_PASTE].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_DELETE].visibility = CTX_INVISIBLE;
|
||||
@ -333,6 +396,17 @@ void setContextMenuMainVisibilities() {
|
||||
}
|
||||
}
|
||||
|
||||
// Invisible if it's not folder or sce_pfs does not exist
|
||||
if (!file_entry->is_folder) {
|
||||
menu_main_entries[MENU_MAIN_ENTRY_OPEN_DECRYPTED].visibility = CTX_INVISIBLE;
|
||||
} else {
|
||||
char path[MAX_PATH_LENGTH];
|
||||
snprintf(path, MAX_PATH_LENGTH - 1, "%s%ssce_pfs", file_list.path, file_entry->name);
|
||||
|
||||
if (!checkFolderExist(path))
|
||||
menu_main_entries[MENU_MAIN_ENTRY_OPEN_DECRYPTED].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
// Go to first entry
|
||||
for (i = 0; i < N_MENU_MAIN_ENTRIES; i++) {
|
||||
if (menu_main_entries[i].visibility == CTX_VISIBLE) {
|
||||
@ -394,17 +468,15 @@ void setContextMenuMoreVisibilities() {
|
||||
menu_more_entries[MENU_MORE_ENTRY_INSTALL_FOLDER].visibility = CTX_INVISIBLE;
|
||||
menu_more_entries[MENU_MORE_ENTRY_EXPORT_MEDIA].visibility = CTX_INVISIBLE;
|
||||
menu_more_entries[MENU_MORE_ENTRY_CALCULATE_SHA1].visibility = CTX_INVISIBLE;
|
||||
menu_more_entries[MENU_MORE_ENTRY_OPEN_DECRYPTED].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
// Invisble operations in archives
|
||||
if (isInArchive()) {
|
||||
if (isInArchive() || (pfs_mounted_path[0] && strstr(file_list.path, pfs_mounted_path) && read_only)) {
|
||||
menu_more_entries[MENU_MORE_ENTRY_COMPRESS].visibility = CTX_INVISIBLE;
|
||||
menu_more_entries[MENU_MORE_ENTRY_INSTALL_ALL].visibility = CTX_INVISIBLE;
|
||||
menu_more_entries[MENU_MORE_ENTRY_INSTALL_FOLDER].visibility = CTX_INVISIBLE;
|
||||
menu_more_entries[MENU_MORE_ENTRY_EXPORT_MEDIA].visibility = CTX_INVISIBLE;
|
||||
menu_more_entries[MENU_MORE_ENTRY_CALCULATE_SHA1].visibility = CTX_INVISIBLE;
|
||||
menu_more_entries[MENU_MORE_ENTRY_OPEN_DECRYPTED].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
if (file_entry->is_folder) {
|
||||
@ -447,17 +519,6 @@ void setContextMenuMoreVisibilities() {
|
||||
menu_more_entries[MENU_MORE_ENTRY_EXPORT_MEDIA].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
// Invisible if it's not folder or sce_pfs does not exist
|
||||
if (!file_entry->is_folder) {
|
||||
menu_more_entries[MENU_MORE_ENTRY_OPEN_DECRYPTED].visibility = CTX_INVISIBLE;
|
||||
} else {
|
||||
char path[MAX_PATH_LENGTH];
|
||||
snprintf(path, MAX_PATH_LENGTH - 1, "%s%ssce_pfs", file_list.path, file_entry->name);
|
||||
|
||||
if (!checkFolderExist(path))
|
||||
menu_more_entries[MENU_MORE_ENTRY_OPEN_DECRYPTED].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
// Go to first entry
|
||||
for (i = 0; i < N_MENU_MORE_ENTRIES; i++) {
|
||||
if (menu_more_entries[i].visibility == CTX_VISIBLE) {
|
||||
@ -557,6 +618,57 @@ static int contextMenuHomeEnterCallback(int sel, void *context) {
|
||||
|
||||
static int contextMenuMainEnterCallback(int sel, void *context) {
|
||||
switch (sel) {
|
||||
|
||||
case MENU_MAIN_ENTRY_OPEN_DECRYPTED:
|
||||
{
|
||||
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
|
||||
if (file_entry) {
|
||||
char path[MAX_PATH_LENGTH];
|
||||
int res;
|
||||
|
||||
pfsUmount();
|
||||
|
||||
snprintf(path, MAX_PATH_LENGTH - 1, "%s%s", file_list.path, file_entry->name);
|
||||
res = pfsMount(path);
|
||||
|
||||
// In case we're at ux0:patch or grw0:patch we need to apply the mounting at ux0:app or gro0:app
|
||||
if (res < 0) {
|
||||
if (strncasecmp(file_list.path, "ux0:patch", 9) == 0 ||
|
||||
strncasecmp(file_list.path, "grw0:patch", 10) == 0) {
|
||||
snprintf(path, MAX_PATH_LENGTH - 1, "ux0:app/%s", file_entry->name);
|
||||
res = pfsMount(path);
|
||||
|
||||
if (res < 0) {
|
||||
snprintf(path, MAX_PATH_LENGTH - 1, "gro0:app/%s", file_entry->name);
|
||||
res = pfsMount(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
errorDialog(res);
|
||||
|
||||
if (res >= 0) {
|
||||
addEndSlash(file_list.path);
|
||||
strcat(file_list.path, file_entry->name);
|
||||
strcpy(pfs_mounted_path, file_list.path);
|
||||
dirLevelUp();
|
||||
|
||||
// Save last dir
|
||||
WriteFile(VITASHELL_LASTDIR, file_list.path, strlen(file_list.path) + 1);
|
||||
|
||||
// Open folder
|
||||
int res = refreshFileList();
|
||||
if (res < 0)
|
||||
errorDialog(res);
|
||||
} else {
|
||||
errorDialog(res);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MENU_MAIN_ENTRY_MARK_UNMARK_ALL:
|
||||
{
|
||||
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
|
||||
@ -596,7 +708,7 @@ static int contextMenuMainEnterCallback(int sel, void *context) {
|
||||
if (pfs_mounted_path[0] &&
|
||||
!strstr(file_list.path, pfs_mounted_path) &&
|
||||
strstr(copy_list.path, pfs_mounted_path)) {
|
||||
gameDataUmount();
|
||||
pfsUmount();
|
||||
}
|
||||
|
||||
// Mode
|
||||
@ -907,47 +1019,6 @@ static int contextMenuMoreEnterCallback(int sel, void *context) {
|
||||
setDialogStep(DIALOG_STEP_HASH_QUESTION);
|
||||
break;
|
||||
}
|
||||
|
||||
case MENU_MORE_ENTRY_OPEN_DECRYPTED:
|
||||
{
|
||||
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
|
||||
if (file_entry) {
|
||||
char path[MAX_PATH_LENGTH];
|
||||
int res;
|
||||
|
||||
gameDataUmount();
|
||||
|
||||
snprintf(path, MAX_PATH_LENGTH - 1, "%s%s", file_list.path, file_entry->name);
|
||||
res = gameDataMount(path);
|
||||
|
||||
// In case we're at ux0:patch or grw0:patch we need to apply the mounting at ux0:app or gro0:app
|
||||
snprintf(path, MAX_PATH_LENGTH - 1, "ux0:app/%s", file_entry->name);
|
||||
if (res < 0)
|
||||
res = gameDataMount(path);
|
||||
snprintf(path, MAX_PATH_LENGTH - 1, "gro:app/%s", file_entry->name);
|
||||
if (res < 0)
|
||||
res = gameDataMount(path);
|
||||
|
||||
if (res >= 0) {
|
||||
addEndSlash(file_list.path);
|
||||
strcat(file_list.path, file_entry->name);
|
||||
strcpy(pfs_mounted_path, file_list.path);
|
||||
dirLevelUp();
|
||||
|
||||
// Save last dir
|
||||
WriteFile(VITASHELL_LASTDIR, file_list.path, strlen(file_list.path) + 1);
|
||||
|
||||
// Open folder
|
||||
int res = refreshFileList();
|
||||
if (res < 0)
|
||||
errorDialog(res);
|
||||
} else {
|
||||
errorDialog(res);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CONTEXT_MENU_CLOSING;
|
||||
|
@ -28,8 +28,8 @@ extern ContextMenu context_menu_main;
|
||||
extern ContextMenu context_menu_sort;
|
||||
extern ContextMenu context_menu_more;
|
||||
|
||||
int gameDataMount(const char *path);
|
||||
int gameDataUmount();
|
||||
int pfsMount(const char *path);
|
||||
int pfsUmount();
|
||||
|
||||
void initContextMenuWidth();
|
||||
void setContextMenuHomeVisibilities();
|
||||
|
@ -22,9 +22,10 @@ target_link_libraries(kernel
|
||||
SceIofilemgrForDriver_stub
|
||||
SceSysclibForDriver_stub
|
||||
SceSysmemForDriver_stub
|
||||
SceModulemgrForKernel_stub
|
||||
SceModulemgrForDriver_stub
|
||||
SceThreadmgrForDriver_stub
|
||||
SceProcessmgrForDriver_stub
|
||||
SceNpDrmForDriver_stub
|
||||
taihenForKernel_stub
|
||||
taihenModuleUtils_stub
|
||||
)
|
||||
|
@ -12,4 +12,6 @@ VitaShellKernel2:
|
||||
functions:
|
||||
- shellKernelIsUx0Redirected
|
||||
- shellKernelRedirectUx0
|
||||
- shellKernelUnredirectUx0
|
||||
- shellKernelUnredirectUx0
|
||||
- shellKernelMountById
|
||||
- shellKernelGetRifVitaKey
|
@ -19,6 +19,7 @@
|
||||
#include <psp2kern/kernel/cpu.h>
|
||||
#include <psp2kern/kernel/modulemgr.h>
|
||||
#include <psp2kern/kernel/sysmem.h>
|
||||
#include <psp2kern/kernel/threadmgr.h>
|
||||
#include <psp2kern/io/fcntl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@ -26,8 +27,11 @@
|
||||
|
||||
#include <taihen.h>
|
||||
|
||||
#include "vitashell_kernel.h"
|
||||
|
||||
#define MOUNT_POINT_ID 0x800
|
||||
|
||||
int module_get_export_func(SceUID pid, const char *modname, uint32_t libnid, uint32_t funcnid, uintptr_t *func);
|
||||
int module_get_offset(SceUID pid, SceUID modid, int segidx, size_t offset, uintptr_t *addr);
|
||||
|
||||
typedef struct {
|
||||
@ -138,6 +142,113 @@ int shellKernelUnredirectUx0() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _shellKernelMountById(ShellMountIdArgs *args) {
|
||||
int res;
|
||||
|
||||
void *(* sceAppMgrFindProcessInfoByPid)(void *data, SceUID pid);
|
||||
int (* sceAppMgrMountById)(SceUID pid, void *info, int id, const char *titleid, const char *path, const char *desired_mount_point, const void *klicensee, char *mount_point);
|
||||
int (* _ksceKernelGetModuleInfo)(SceUID pid, SceUID modid, SceKernelModuleInfo *info);
|
||||
|
||||
// Get tai module info
|
||||
tai_module_info_t tai_info;
|
||||
tai_info.size = sizeof(tai_module_info_t);
|
||||
if (taiGetModuleInfoForKernel(KERNEL_PID, "SceAppMgr", &tai_info) < 0)
|
||||
return SCE_KERNEL_START_SUCCESS;
|
||||
|
||||
switch (tai_info.module_nid) {
|
||||
case 0xDBB29DB7: // 3.60 retail
|
||||
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
|
||||
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19B51, (uintptr_t *)&sceAppMgrMountById);
|
||||
break;
|
||||
|
||||
case 0x1C9879D6: // 3.65 retail
|
||||
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
|
||||
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E61, (uintptr_t *)&sceAppMgrMountById);
|
||||
break;
|
||||
|
||||
case 0x54E2E984: // 3.67 retail
|
||||
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x2DE1, (uintptr_t *)&sceAppMgrFindProcessInfoByPid);
|
||||
module_get_offset(KERNEL_PID, tai_info.modid, 0, 0x19E6D, (uintptr_t *)&sceAppMgrMountById);
|
||||
break;
|
||||
}
|
||||
|
||||
res = module_get_export_func(KERNEL_PID, "SceKernelModulemgr", 0xC445FA63, 0xD269F915, (uintptr_t *)&_ksceKernelGetModuleInfo);
|
||||
if (res < 0)
|
||||
res = module_get_export_func(KERNEL_PID, "SceKernelModulemgr", 0x92C9FFC2, 0xDAA90093, (uintptr_t *)&_ksceKernelGetModuleInfo);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
// Module info
|
||||
SceKernelModuleInfo mod_info;
|
||||
mod_info.size = sizeof(SceKernelModuleInfo);
|
||||
res = _ksceKernelGetModuleInfo(KERNEL_PID, tai_info.modid, &mod_info);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
uint32_t appmgr_data_addr = (uint32_t)mod_info.segments[1].vaddr;
|
||||
|
||||
SceUID process_id = ksceKernelGetProcessId();
|
||||
|
||||
void *info = sceAppMgrFindProcessInfoByPid((void *)(appmgr_data_addr + 0x500), process_id);
|
||||
if (!info)
|
||||
return -1;
|
||||
|
||||
char process_titleid[12];
|
||||
char path[256];
|
||||
char desired_mount_point[16];
|
||||
char mount_point[16];
|
||||
char klicensee[16];
|
||||
|
||||
memset(mount_point, 0, sizeof(mount_point));
|
||||
|
||||
if (args->process_titleid)
|
||||
ksceKernelStrncpyUserToKernel(process_titleid, (uintptr_t)args->process_titleid, 11);
|
||||
if (args->path)
|
||||
ksceKernelStrncpyUserToKernel(path, (uintptr_t)args->path, 255);
|
||||
if (args->desired_mount_point)
|
||||
ksceKernelStrncpyUserToKernel(desired_mount_point, (uintptr_t)args->desired_mount_point, 15);
|
||||
if (args->klicensee)
|
||||
ksceKernelMemcpyUserToKernel(klicensee, (uintptr_t)args->klicensee, 0x10);
|
||||
|
||||
res = sceAppMgrMountById(process_id, info + 0x580, args->id, args->process_titleid ? process_titleid : NULL, args->path ? path : NULL,
|
||||
args->desired_mount_point ? desired_mount_point : NULL, args->klicensee ? klicensee : NULL, mount_point);
|
||||
|
||||
if (args->mount_point)
|
||||
ksceKernelStrncpyKernelToUser((uintptr_t)args->mount_point, mount_point, 15);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int shellKernelMountById(ShellMountIdArgs *args) {
|
||||
uint32_t state;
|
||||
ENTER_SYSCALL(state);
|
||||
|
||||
ShellMountIdArgs k_args;
|
||||
ksceKernelMemcpyUserToKernel(&k_args, (uintptr_t)args, sizeof(ShellMountIdArgs));
|
||||
|
||||
int res = ksceKernelRunWithStack(0x2000, (void *)_shellKernelMountById, &k_args);
|
||||
|
||||
EXIT_SYSCALL(state);
|
||||
return res;
|
||||
}
|
||||
|
||||
int shellKernelGetRifVitaKey(const void *license_buf, void *klicensee) {
|
||||
char k_license_buf[0x200];
|
||||
char k_klicensee[0x10];
|
||||
|
||||
memset(k_klicensee, 0, sizeof(k_klicensee));
|
||||
|
||||
if (license_buf)
|
||||
ksceKernelMemcpyUserToKernel(k_license_buf, license_buf, sizeof(k_license_buf));
|
||||
|
||||
int res = ksceNpDrmGetRifVitaKey(k_license_buf, k_klicensee, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (klicensee)
|
||||
ksceKernelMemcpyKernelToUser(klicensee, k_klicensee, sizeof(k_klicensee));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void _start() __attribute__ ((weak, alias("module_start")));
|
||||
int module_start(SceSize args, void *argp) {
|
||||
SceUID tmp1, tmp2;
|
||||
|
@ -19,8 +19,19 @@
|
||||
#ifndef __VITASHELL_KERNEL_H__
|
||||
#define __VITASHELL_KERNEL_H__
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
const char *process_titleid;
|
||||
const char *path;
|
||||
const char *desired_mount_point;
|
||||
const void *klicensee;
|
||||
char *mount_point;
|
||||
} ShellMountIdArgs;
|
||||
|
||||
int shellKernelIsUx0Redirected();
|
||||
int shellKernelRedirectUx0();
|
||||
int shellKernelUnredirectUx0();
|
||||
int shellKernelMountById(ShellMountIdArgs *args);
|
||||
int shellKernelGetRifVitaKey(const void *license_buf, void *klicensee);
|
||||
|
||||
#endif
|
@ -12,4 +12,6 @@ VitaShellUser:
|
||||
functions:
|
||||
- shellUserIsUx0Redirected
|
||||
- shellUserRedirectUx0
|
||||
- shellUserUnredirectUx0
|
||||
- shellUserUnredirectUx0
|
||||
- shellUserMountById
|
||||
- shellUserGetRifVitaKey
|
@ -24,7 +24,7 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <vitashell_kernel.h>
|
||||
#include "vitashell_user.h"
|
||||
|
||||
int shellUserIsUx0Redirected() {
|
||||
return shellKernelIsUx0Redirected();
|
||||
@ -38,6 +38,14 @@ int shellUserUnredirectUx0() {
|
||||
return shellKernelUnredirectUx0();
|
||||
}
|
||||
|
||||
int shellUserMountById(ShellMountIdArgs *args) {
|
||||
return shellKernelMountById(args);
|
||||
}
|
||||
|
||||
int shellUserGetRifVitaKey(const void *license_buf, void *klicensee) {
|
||||
return shellKernelGetRifVitaKey(license_buf, klicensee);
|
||||
}
|
||||
|
||||
void _start() __attribute__ ((weak, alias("module_start")));
|
||||
int module_start(SceSize args, void *argp) {
|
||||
return SCE_KERNEL_START_SUCCESS;
|
||||
|
@ -19,8 +19,12 @@
|
||||
#ifndef __VITASHELL_USER_H__
|
||||
#define __VITASHELL_USER_H__
|
||||
|
||||
#include <vitashell_kernel.h>
|
||||
|
||||
int shellUserIsUx0Redirected();
|
||||
int shellUserRedirectUx0();
|
||||
int shellUserUnredirectUx0();
|
||||
int shellUserMountById(ShellMountIdArgs *args);
|
||||
int shellUserGetRifVitaKey(const void *license_buf, void *klicensee);
|
||||
|
||||
#endif
|
@ -28,7 +28,7 @@
|
||||
<frame id="frame4">
|
||||
<liveitem>
|
||||
<text align="left" text-align="left" word-wrap="off" ellipsis="on">
|
||||
<str size="18" color="#ffffff" shadow="on">v1.83</str>
|
||||
<str size="18" color="#ffffff" shadow="on">v1.9</str>
|
||||
</text>
|
||||
</liveitem>
|
||||
</frame>
|
||||
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user