Download SMDH for 3DSX from TitleDB if available, do not load file metadata when unnecessary.

This commit is contained in:
Steven Smith 2018-02-17 22:13:42 -08:00
parent 599c631b11
commit 1d52cba6c4
11 changed files with 69 additions and 41 deletions

View File

@ -52,7 +52,7 @@ void action_import_secure_value(linked_list* items, list_item* selected);
void action_export_secure_value(linked_list* items, list_item* selected); void action_export_secure_value(linked_list* items, list_item* selected);
void action_delete_secure_value(linked_list* items, list_item* selected); void action_delete_secure_value(linked_list* items, list_item* selected);
void action_install_url(const char* confirmMessage, const char* urls, const char* path3dsx, void* userData, void action_install_url(const char* confirmMessage, const char* urls, const char* paths, void* userData,
void (*finishedURL)(void* data, u32 index), void (*finishedURL)(void* data, u32 index),
void (*finishedAll)(void* data), void (*finishedAll)(void* data),
void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index)); void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index));

View File

@ -190,7 +190,7 @@ static void action_delete_internal(linked_list* items, list_item* selected, cons
data->items = items; data->items = items;
file_info* targetInfo = (file_info*) selected->data; file_info* targetInfo = (file_info*) selected->data;
Result targetCreateRes = task_create_file_item(&data->targetItem, targetInfo->archive, targetInfo->path, targetInfo->attributes, true); Result targetCreateRes = task_create_file_item(&data->targetItem, targetInfo->archive, targetInfo->path, targetInfo->attributes, false);
if(R_FAILED(targetCreateRes)) { if(R_FAILED(targetCreateRes)) {
error_display_res(NULL, NULL, targetCreateRes, "Failed to create target file item."); error_display_res(NULL, NULL, targetCreateRes, "Failed to create target file item.");
@ -231,6 +231,7 @@ static void action_delete_internal(linked_list* items, list_item* selected, cons
strncpy(loadingData->popData.path, data->target->path, FILE_PATH_MAX); strncpy(loadingData->popData.path, data->target->path, FILE_PATH_MAX);
loadingData->popData.recursive = recursive; loadingData->popData.recursive = recursive;
loadingData->popData.includeBase = includeBase; loadingData->popData.includeBase = includeBase;
loadingData->popData.meta = false;
loadingData->popData.filter = ciasOnly ? fs_filter_cias : ticketsOnly ? fs_filter_tickets : NULL; loadingData->popData.filter = ciasOnly ? fs_filter_cias : ticketsOnly ? fs_filter_tickets : NULL;
loadingData->popData.filterData = NULL; loadingData->popData.filterData = NULL;

View File

@ -370,6 +370,7 @@ static void action_install_cias_internal(linked_list* items, list_item* selected
strncpy(loadingData->popData.path, data->target->path, FILE_PATH_MAX); strncpy(loadingData->popData.path, data->target->path, FILE_PATH_MAX);
loadingData->popData.recursive = false; loadingData->popData.recursive = false;
loadingData->popData.includeBase = !(data->target->attributes & FS_ATTRIBUTE_DIRECTORY); loadingData->popData.includeBase = !(data->target->attributes & FS_ATTRIBUTE_DIRECTORY);
loadingData->popData.meta = true;
loadingData->popData.filter = fs_filter_cias; loadingData->popData.filter = fs_filter_cias;
loadingData->popData.filterData = NULL; loadingData->popData.filterData = NULL;

View File

@ -344,6 +344,7 @@ static void action_install_tickets_internal(linked_list* items, list_item* selec
strncpy(loadingData->popData.path, data->target->path, FILE_PATH_MAX); strncpy(loadingData->popData.path, data->target->path, FILE_PATH_MAX);
loadingData->popData.recursive = false; loadingData->popData.recursive = false;
loadingData->popData.includeBase = !(data->target->attributes & FS_ATTRIBUTE_DIRECTORY); loadingData->popData.includeBase = !(data->target->attributes & FS_ATTRIBUTE_DIRECTORY);
loadingData->popData.meta = true;
loadingData->popData.filter = fs_filter_tickets; loadingData->popData.filter = fs_filter_tickets;
loadingData->popData.filterData = NULL; loadingData->popData.filterData = NULL;

View File

@ -47,17 +47,25 @@ void action_install_titledb(linked_list* items, list_item* selected, bool cia) {
titledb_info* info = (titledb_info*) selected->data; titledb_info* info = (titledb_info*) selected->data;
char url[64]; char urls[2 * DOWNLOAD_URL_MAX];
char path3dsx[FILE_PATH_MAX]; char paths[2 * FILE_PATH_MAX];
if(data->cia) { if(data->cia) {
snprintf(url, DOWNLOAD_URL_MAX, "https://3ds.titledb.com/v1/cia/%lu/download", info->cia.id); snprintf(urls, sizeof(urls), "https://3ds.titledb.com/v1/cia/%lu/download", info->cia.id);
} else { } else {
snprintf(url, DOWNLOAD_URL_MAX, "https://3ds.titledb.com/v1/tdsx/%lu/download", info->tdsx.id);
char name[FILE_NAME_MAX]; char name[FILE_NAME_MAX];
string_escape_file_name(name, info->meta.shortDescription, sizeof(name)); string_escape_file_name(name, info->meta.shortDescription, sizeof(name));
snprintf(path3dsx, sizeof(path3dsx), "/3ds/%s/%s.3dsx", name, name);
u32 urlsPos = 0;
u32 pathsPos = 0;
urlsPos += snprintf(urls + urlsPos, sizeof(urls) - urlsPos, "https://3ds.titledb.com/v1/tdsx/%lu/download\n", info->tdsx.id);
pathsPos += snprintf(paths + pathsPos, sizeof(paths) - pathsPos, "/3ds/%s/%s.3dsx\n", name, name);
if(info->tdsx.smdh.exists) {
snprintf(urls + urlsPos, sizeof(urls) - urlsPos, "https://3ds.titledb.com/v1/smdh/%lu/download\n", info->tdsx.smdh.id);
snprintf(paths + pathsPos, sizeof(paths) - pathsPos, "/3ds/%s/%s.smdh\n", name, name);
}
} }
action_install_url("Install the selected title from TitleDB?", url, path3dsx, data, action_install_titledb_finished_url, action_install_titledb_finished_all, action_install_titledb_draw_top); action_install_url("Install the selected title from TitleDB?", urls, paths, data, action_install_titledb_finished_url, action_install_titledb_finished_all, action_install_titledb_draw_top);
} }

View File

@ -12,13 +12,13 @@
typedef enum content_type_e { typedef enum content_type_e {
CONTENT_CIA, CONTENT_CIA,
CONTENT_TICKET, CONTENT_TICKET,
CONTENT_3DSX CONTENT_3DSX_SMDH
} content_type; } content_type;
typedef struct { typedef struct {
char urls[INSTALL_URLS_MAX][DOWNLOAD_URL_MAX]; char urls[INSTALL_URLS_MAX][DOWNLOAD_URL_MAX];
char paths3dsx[INSTALL_URLS_MAX][FILE_PATH_MAX]; char paths[INSTALL_URLS_MAX][FILE_PATH_MAX];
void* userData; void* userData;
void (*finishedURL)(void* data, u32 index); void (*finishedURL)(void* data, u32 index);
@ -34,7 +34,7 @@ typedef struct {
volatile bool n3dsContinue; volatile bool n3dsContinue;
ticket_info ticketInfo; ticket_info ticketInfo;
http_context currContext; http_context currContext;
char curr3dsxPath[FILE_PATH_MAX]; char currPath[FILE_PATH_MAX];
data_op_data installInfo; data_op_data installInfo;
} install_url_data; } install_url_data;
@ -142,7 +142,7 @@ static Result action_install_url_open_dst(void* data, u32 index, void* initialRe
installData->currTitleId = 0; installData->currTitleId = 0;
installData->n3dsContinue = false; installData->n3dsContinue = false;
memset(&installData->ticketInfo, 0, sizeof(installData->ticketInfo)); memset(&installData->ticketInfo, 0, sizeof(installData->ticketInfo));
memset(&installData->curr3dsxPath, 0, sizeof(installData->curr3dsxPath)); memset(&installData->currPath, 0, sizeof(installData->currPath));
if(*(u16*) initialReadBlock == 0x2020) { if(*(u16*) initialReadBlock == 0x2020) {
installData->contentType = CONTENT_CIA; installData->contentType = CONTENT_CIA;
@ -197,15 +197,15 @@ static Result action_install_url_open_dst(void* data, u32 index, void* initialRe
AM_DeleteTicket(installData->ticketInfo.titleId); AM_DeleteTicket(installData->ticketInfo.titleId);
res = AM_InstallTicketBegin(handle); res = AM_InstallTicketBegin(handle);
} else if(*(u32*) initialReadBlock == 0x58534433) { } else if(*(u32*) initialReadBlock == 0x58534433 /* 3DSX */ || *(u32*) initialReadBlock == 0x48444D53 /* SMDH */) {
installData->contentType = CONTENT_3DSX; installData->contentType = CONTENT_3DSX_SMDH;
FS_Archive sdmcArchive = 0; FS_Archive sdmcArchive = 0;
if(R_SUCCEEDED(res = FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")))) { if(R_SUCCEEDED(res = FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")))) {
char dir[FILE_PATH_MAX]; char dir[FILE_PATH_MAX];
if(strlen(installData->paths3dsx[index]) > 0) { if(strlen(installData->paths[index]) > 0) {
string_get_parent_path(dir, installData->paths3dsx[index], FILE_PATH_MAX); string_get_parent_path(dir, installData->paths[index], FILE_PATH_MAX);
strncpy(installData->curr3dsxPath, installData->paths3dsx[index], FILE_PATH_MAX); strncpy(installData->currPath, installData->paths[index], FILE_PATH_MAX);
} else { } else {
char filename[FILE_NAME_MAX]; char filename[FILE_NAME_MAX];
if(R_FAILED(http_get_file_name(installData->currContext, filename, FILE_NAME_MAX))) { if(R_FAILED(http_get_file_name(installData->currContext, filename, FILE_NAME_MAX))) {
@ -216,11 +216,11 @@ static Result action_install_url_open_dst(void* data, u32 index, void* initialRe
string_get_file_name(name, filename, FILE_NAME_MAX); string_get_file_name(name, filename, FILE_NAME_MAX);
snprintf(dir, FILE_PATH_MAX, "/3ds/%s/", name); snprintf(dir, FILE_PATH_MAX, "/3ds/%s/", name);
snprintf(installData->curr3dsxPath, FILE_PATH_MAX, "/3ds/%s/%s.3dsx", name, name); snprintf(installData->currPath, FILE_PATH_MAX, "/3ds/%s/%s", name, filename);
} }
if(R_SUCCEEDED(res = fs_ensure_dir(sdmcArchive, "/3ds/")) && R_SUCCEEDED(res = fs_ensure_dir(sdmcArchive, dir))) { if(R_SUCCEEDED(res = fs_ensure_dir(sdmcArchive, "/3ds/")) && R_SUCCEEDED(res = fs_ensure_dir(sdmcArchive, dir))) {
FS_Path* path = fs_make_path_utf8(installData->curr3dsxPath); FS_Path* path = fs_make_path_utf8(installData->currPath);
if(path != NULL) { if(path != NULL) {
res = FSUSER_OpenFileDirectly(handle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), *path, FS_OPEN_WRITE | FS_OPEN_CREATE, 0); res = FSUSER_OpenFileDirectly(handle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), *path, FS_OPEN_WRITE | FS_OPEN_CREATE, 0);
@ -264,7 +264,7 @@ static Result action_install_url_close_dst(void* data, u32 index, bool succeeded
svcSleepThread(100000000); svcSleepThread(100000000);
} }
} }
} else if(installData->contentType == CONTENT_3DSX) { } else if(installData->contentType == CONTENT_3DSX_SMDH) {
res = FSFILE_Close(handle); res = FSFILE_Close(handle);
} }
} else { } else {
@ -272,12 +272,12 @@ static Result action_install_url_close_dst(void* data, u32 index, bool succeeded
res = AM_CancelCIAInstall(handle); res = AM_CancelCIAInstall(handle);
} else if(installData->contentType == CONTENT_TICKET) { } else if(installData->contentType == CONTENT_TICKET) {
res = AM_InstallTicketAbort(handle); res = AM_InstallTicketAbort(handle);
} else if(installData->contentType == CONTENT_3DSX) { } else if(installData->contentType == CONTENT_3DSX_SMDH) {
res = FSFILE_Close(handle); res = FSFILE_Close(handle);
FS_Archive sdmcArchive = 0; FS_Archive sdmcArchive = 0;
if(R_SUCCEEDED(FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")))) { if(R_SUCCEEDED(FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")))) {
FS_Path* path = fs_make_path_utf8(installData->curr3dsxPath); FS_Path* path = fs_make_path_utf8(installData->currPath);
if(path != NULL) { if(path != NULL) {
FSUSER_DeleteFile(sdmcArchive, *path); FSUSER_DeleteFile(sdmcArchive, *path);
@ -377,7 +377,7 @@ static void action_install_url_confirm_onresponse(ui_view* view, void* data, u32
} }
} }
void action_install_url(const char* confirmMessage, const char* urls, const char* paths3dsx, void* userData, void action_install_url(const char* confirmMessage, const char* urls, const char* paths, void* userData,
void (*finishedURL)(void* data, u32 index), void (*finishedURL)(void* data, u32 index),
void (*finishedAll)(void* data), void (*finishedAll)(void* data),
void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index)) { void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index)) {
@ -421,14 +421,14 @@ void action_install_url(const char* confirmMessage, const char* urls, const char
} }
} }
if(paths3dsx != NULL) { if(paths != NULL) {
size_t pathsLen = strlen(paths3dsx); size_t pathsLen = strlen(paths);
if(pathsLen > 0) { if(pathsLen > 0) {
const char* currStart = paths3dsx; const char* currStart = paths;
for(u32 i = 0; i < data->installInfo.total && currStart - paths3dsx < pathsLen; i++) { for(u32 i = 0; i < data->installInfo.total && currStart - paths < pathsLen; i++) {
const char* currEnd = strchr(currStart, '\n'); const char* currEnd = strchr(currStart, '\n');
if(currEnd == NULL) { if(currEnd == NULL) {
currEnd = paths3dsx + pathsLen; currEnd = paths + pathsLen;
} }
u32 len = currEnd - currStart; u32 len = currEnd - currStart;
@ -436,7 +436,7 @@ void action_install_url(const char* confirmMessage, const char* urls, const char
len = FILE_PATH_MAX; len = FILE_PATH_MAX;
} }
strncpy(data->paths3dsx[i], currStart, len); strncpy(data->paths[i], currStart, len);
currStart = currEnd + 1; currStart = currEnd + 1;
} }
@ -456,7 +456,7 @@ void action_install_url(const char* confirmMessage, const char* urls, const char
data->currTitleId = 0; data->currTitleId = 0;
data->n3dsContinue = false; data->n3dsContinue = false;
memset(&data->ticketInfo, 0, sizeof(data->ticketInfo)); memset(&data->ticketInfo, 0, sizeof(data->ticketInfo));
memset(&data->curr3dsxPath, 0, sizeof(data->curr3dsxPath)); memset(&data->currPath, 0, sizeof(data->currPath));
data->installInfo.data = data; data->installInfo.data = data;

View File

@ -342,7 +342,7 @@ void action_paste_contents(linked_list* items, list_item* selected) {
data->items = items; data->items = items;
file_info* targetInfo = (file_info*) selected->data; file_info* targetInfo = (file_info*) selected->data;
Result targetCreateRes = task_create_file_item(&data->targetItem, targetInfo->archive, targetInfo->path, targetInfo->attributes, true); Result targetCreateRes = task_create_file_item(&data->targetItem, targetInfo->archive, targetInfo->path, targetInfo->attributes, false);
if(R_FAILED(targetCreateRes)) { if(R_FAILED(targetCreateRes)) {
error_display_res(NULL, NULL, targetCreateRes, "Failed to create target file item."); error_display_res(NULL, NULL, targetCreateRes, "Failed to create target file item.");
@ -398,6 +398,7 @@ void action_paste_contents(linked_list* items, list_item* selected) {
strncpy(loadingData->popData.path, clipboard_get_path(), FILE_PATH_MAX); strncpy(loadingData->popData.path, clipboard_get_path(), FILE_PATH_MAX);
loadingData->popData.recursive = true; loadingData->popData.recursive = true;
loadingData->popData.includeBase = !clipboard_is_contents_only() || !fs_is_dir(clipboard_get_archive(), clipboard_get_path()); loadingData->popData.includeBase = !clipboard_is_contents_only() || !fs_is_dir(clipboard_get_archive(), clipboard_get_path());
loadingData->popData.meta = false;
loadingData->popData.filter = NULL; loadingData->popData.filter = NULL;
loadingData->popData.filterData = NULL; loadingData->popData.filterData = NULL;

View File

@ -9,9 +9,10 @@
#include "../../core/core.h" #include "../../core/core.h"
typedef struct { typedef struct {
bool cia[INSTALL_URLS_MAX];
char urls[INSTALL_URLS_MAX * DOWNLOAD_URL_MAX]; char urls[INSTALL_URLS_MAX * DOWNLOAD_URL_MAX];
char paths3dsx[INSTALL_URLS_MAX * FILE_PATH_MAX]; char paths[INSTALL_URLS_MAX * FILE_PATH_MAX];
bool cia[INSTALL_URLS_MAX];
list_item* items[INSTALL_URLS_MAX]; list_item* items[INSTALL_URLS_MAX];
} update_titledb_data; } update_titledb_data;
@ -58,29 +59,42 @@ void action_update_titledb(linked_list* items, list_item* selected) {
titledb_info* info = (titledb_info*) item->data; titledb_info* info = (titledb_info*) item->data;
if(info->cia.outdated) { if(info->cia.outdated) {
urlsPos += snprintf(data->urls + urlsPos, INSTALL_URLS_MAX * DOWNLOAD_URL_MAX - urlsPos,
"https://3ds.titledb.com/v1/cia/%lu/download\n",
info->cia.id);
pathsPos += snprintf(data->paths + pathsPos, INSTALL_URLS_MAX * FILE_PATH_MAX - pathsPos,
"\n");
data->cia[index] = true; data->cia[index] = true;
urlsPos += snprintf(data->urls + urlsPos, INSTALL_URLS_MAX * DOWNLOAD_URL_MAX - urlsPos, "https://3ds.titledb.com/v1/cia/%lu/download\n", info->cia.id);
pathsPos += snprintf(data->paths3dsx + pathsPos, INSTALL_URLS_MAX * FILE_PATH_MAX - pathsPos, "\n");
data->items[index] = item; data->items[index] = item;
index++; index++;
} }
if(info->tdsx.outdated) { if(info->tdsx.outdated && (!info->tdsx.smdh.exists || index < INSTALL_URLS_MAX - 1)) {
char name[FILE_NAME_MAX]; char name[FILE_NAME_MAX];
string_escape_file_name(name, info->meta.shortDescription, sizeof(name)); string_escape_file_name(name, info->meta.shortDescription, sizeof(name));
data->cia[index] = false;
urlsPos += snprintf(data->urls + urlsPos, INSTALL_URLS_MAX * DOWNLOAD_URL_MAX - urlsPos, "https://3ds.titledb.com/v1/tdsx/%lu/download\n", info->tdsx.id); urlsPos += snprintf(data->urls + urlsPos, INSTALL_URLS_MAX * DOWNLOAD_URL_MAX - urlsPos, "https://3ds.titledb.com/v1/tdsx/%lu/download\n", info->tdsx.id);
pathsPos += snprintf(data->paths3dsx + pathsPos, INSTALL_URLS_MAX * FILE_PATH_MAX - pathsPos, "/3ds/%s/%s.3dsx\n", name, name); pathsPos += snprintf(data->paths + pathsPos, INSTALL_URLS_MAX * FILE_PATH_MAX - pathsPos, "/3ds/%s/%s.3dsx\n", name, name);
data->cia[index] = false;
data->items[index] = item; data->items[index] = item;
index++; index++;
if(info->tdsx.smdh.exists) {
urlsPos += snprintf(data->urls + urlsPos, INSTALL_URLS_MAX * DOWNLOAD_URL_MAX - urlsPos, "https://3ds.titledb.com/v1/smdh/%lu/download\n", info->tdsx.smdh.id);
pathsPos += snprintf(data->paths + pathsPos, INSTALL_URLS_MAX * FILE_PATH_MAX - pathsPos, "/3ds/%s/%s.smdh\n", name, name);
data->cia[index] = false;
data->items[index] = item;
index++;
}
} }
} }
if(index > 0) { if(index > 0) {
action_install_url("Install all updates from TitleDB?", data->urls, data->paths3dsx, data, action_update_titledb_finished_url, action_update_titledb_finished_all, action_update_titledb_draw_top); action_install_url("Install all updates from TitleDB?", data->urls, data->paths, data, action_update_titledb_finished_url, action_update_titledb_finished_all, action_update_titledb_draw_top);
} else { } else {
prompt_display_notify("Success", "All titles are up to date.", COLOR_TEXT, NULL, NULL, NULL); prompt_display_notify("Success", "All titles are up to date.", COLOR_TEXT, NULL, NULL, NULL);
} }

View File

@ -370,6 +370,7 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
data->populateData.recursive = false; data->populateData.recursive = false;
data->populateData.includeBase = true; data->populateData.includeBase = true;
data->populateData.meta = true;
data->populateData.filter = files_filter; data->populateData.filter = files_filter;
data->populateData.filterData = data; data->populateData.filterData = data;

View File

@ -279,7 +279,7 @@ static void task_populate_files_thread(void* arg) {
} }
} }
if(R_SUCCEEDED(res)) { if(R_SUCCEEDED(res) && data->meta) {
linked_list_iter iter; linked_list_iter iter;
linked_list_iterate(data->items, &iter); linked_list_iterate(data->items, &iter);

View File

@ -40,6 +40,7 @@ typedef struct populate_files_data_s {
bool recursive; bool recursive;
bool includeBase; bool includeBase;
bool meta;
bool (*filter)(void* data, const char* name, u32 attributes); bool (*filter)(void* data, const char* name, u32 attributes);
void* filterData; void* filterData;