From 1d52cba6c40d24ded06010fa974cf603ed572fd1 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 17 Feb 2018 22:13:42 -0800 Subject: [PATCH] Download SMDH for 3DSX from TitleDB if available, do not load file metadata when unnecessary. --- source/fbi/action/action.h | 2 +- source/fbi/action/deletecontents.c | 3 +- source/fbi/action/installcias.c | 1 + source/fbi/action/installtickets.c | 1 + source/fbi/action/installtitledb.c | 22 ++++++++++----- source/fbi/action/installurl.c | 44 +++++++++++++++--------------- source/fbi/action/pastecontents.c | 3 +- source/fbi/action/updatetitledb.c | 30 ++++++++++++++------ source/fbi/files.c | 1 + source/fbi/task/listfiles.c | 2 +- source/fbi/task/listfiles.h | 1 + 11 files changed, 69 insertions(+), 41 deletions(-) diff --git a/source/fbi/action/action.h b/source/fbi/action/action.h index 27d33c2..27874fb 100644 --- a/source/fbi/action/action.h +++ b/source/fbi/action/action.h @@ -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_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 (*finishedAll)(void* data), void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index)); diff --git a/source/fbi/action/deletecontents.c b/source/fbi/action/deletecontents.c index 1fb1e1b..0345d02 100644 --- a/source/fbi/action/deletecontents.c +++ b/source/fbi/action/deletecontents.c @@ -190,7 +190,7 @@ static void action_delete_internal(linked_list* items, list_item* selected, cons data->items = items; 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)) { 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); loadingData->popData.recursive = recursive; loadingData->popData.includeBase = includeBase; + loadingData->popData.meta = false; loadingData->popData.filter = ciasOnly ? fs_filter_cias : ticketsOnly ? fs_filter_tickets : NULL; loadingData->popData.filterData = NULL; diff --git a/source/fbi/action/installcias.c b/source/fbi/action/installcias.c index aa9d8f2..46380d7 100644 --- a/source/fbi/action/installcias.c +++ b/source/fbi/action/installcias.c @@ -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); loadingData->popData.recursive = false; loadingData->popData.includeBase = !(data->target->attributes & FS_ATTRIBUTE_DIRECTORY); + loadingData->popData.meta = true; loadingData->popData.filter = fs_filter_cias; loadingData->popData.filterData = NULL; diff --git a/source/fbi/action/installtickets.c b/source/fbi/action/installtickets.c index 10eee5a..d4103cd 100644 --- a/source/fbi/action/installtickets.c +++ b/source/fbi/action/installtickets.c @@ -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); loadingData->popData.recursive = false; loadingData->popData.includeBase = !(data->target->attributes & FS_ATTRIBUTE_DIRECTORY); + loadingData->popData.meta = true; loadingData->popData.filter = fs_filter_tickets; loadingData->popData.filterData = NULL; diff --git a/source/fbi/action/installtitledb.c b/source/fbi/action/installtitledb.c index 83a592b..25d763a 100644 --- a/source/fbi/action/installtitledb.c +++ b/source/fbi/action/installtitledb.c @@ -47,17 +47,25 @@ void action_install_titledb(linked_list* items, list_item* selected, bool cia) { titledb_info* info = (titledb_info*) selected->data; - char url[64]; - char path3dsx[FILE_PATH_MAX]; + char urls[2 * DOWNLOAD_URL_MAX]; + char paths[2 * FILE_PATH_MAX]; 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 { - snprintf(url, DOWNLOAD_URL_MAX, "https://3ds.titledb.com/v1/tdsx/%lu/download", info->tdsx.id); - char name[FILE_NAME_MAX]; 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); } \ No newline at end of file diff --git a/source/fbi/action/installurl.c b/source/fbi/action/installurl.c index d158f49..b0d334e 100644 --- a/source/fbi/action/installurl.c +++ b/source/fbi/action/installurl.c @@ -12,13 +12,13 @@ typedef enum content_type_e { CONTENT_CIA, CONTENT_TICKET, - CONTENT_3DSX + CONTENT_3DSX_SMDH } content_type; typedef struct { 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 (*finishedURL)(void* data, u32 index); @@ -34,7 +34,7 @@ typedef struct { volatile bool n3dsContinue; ticket_info ticketInfo; http_context currContext; - char curr3dsxPath[FILE_PATH_MAX]; + char currPath[FILE_PATH_MAX]; data_op_data installInfo; } install_url_data; @@ -142,7 +142,7 @@ static Result action_install_url_open_dst(void* data, u32 index, void* initialRe installData->currTitleId = 0; installData->n3dsContinue = false; 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) { 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); res = AM_InstallTicketBegin(handle); - } else if(*(u32*) initialReadBlock == 0x58534433) { - installData->contentType = CONTENT_3DSX; + } else if(*(u32*) initialReadBlock == 0x58534433 /* 3DSX */ || *(u32*) initialReadBlock == 0x48444D53 /* SMDH */) { + installData->contentType = CONTENT_3DSX_SMDH; FS_Archive sdmcArchive = 0; if(R_SUCCEEDED(res = FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")))) { char dir[FILE_PATH_MAX]; - if(strlen(installData->paths3dsx[index]) > 0) { - string_get_parent_path(dir, installData->paths3dsx[index], FILE_PATH_MAX); - strncpy(installData->curr3dsxPath, installData->paths3dsx[index], FILE_PATH_MAX); + if(strlen(installData->paths[index]) > 0) { + string_get_parent_path(dir, installData->paths[index], FILE_PATH_MAX); + strncpy(installData->currPath, installData->paths[index], FILE_PATH_MAX); } else { char 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); 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))) { - FS_Path* path = fs_make_path_utf8(installData->curr3dsxPath); + FS_Path* path = fs_make_path_utf8(installData->currPath); if(path != NULL) { 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); } } - } else if(installData->contentType == CONTENT_3DSX) { + } else if(installData->contentType == CONTENT_3DSX_SMDH) { res = FSFILE_Close(handle); } } else { @@ -272,12 +272,12 @@ static Result action_install_url_close_dst(void* data, u32 index, bool succeeded res = AM_CancelCIAInstall(handle); } else if(installData->contentType == CONTENT_TICKET) { res = AM_InstallTicketAbort(handle); - } else if(installData->contentType == CONTENT_3DSX) { + } else if(installData->contentType == CONTENT_3DSX_SMDH) { res = FSFILE_Close(handle); FS_Archive sdmcArchive = 0; 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) { 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 (*finishedAll)(void* data), 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) { - size_t pathsLen = strlen(paths3dsx); + if(paths != NULL) { + size_t pathsLen = strlen(paths); if(pathsLen > 0) { - const char* currStart = paths3dsx; - for(u32 i = 0; i < data->installInfo.total && currStart - paths3dsx < pathsLen; i++) { + const char* currStart = paths; + for(u32 i = 0; i < data->installInfo.total && currStart - paths < pathsLen; i++) { const char* currEnd = strchr(currStart, '\n'); if(currEnd == NULL) { - currEnd = paths3dsx + pathsLen; + currEnd = paths + pathsLen; } u32 len = currEnd - currStart; @@ -436,7 +436,7 @@ void action_install_url(const char* confirmMessage, const char* urls, const char len = FILE_PATH_MAX; } - strncpy(data->paths3dsx[i], currStart, len); + strncpy(data->paths[i], currStart, len); currStart = currEnd + 1; } @@ -456,7 +456,7 @@ void action_install_url(const char* confirmMessage, const char* urls, const char data->currTitleId = 0; data->n3dsContinue = false; 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; diff --git a/source/fbi/action/pastecontents.c b/source/fbi/action/pastecontents.c index 0f485dc..deba2fd 100644 --- a/source/fbi/action/pastecontents.c +++ b/source/fbi/action/pastecontents.c @@ -342,7 +342,7 @@ void action_paste_contents(linked_list* items, list_item* selected) { data->items = items; 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)) { 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); loadingData->popData.recursive = true; 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.filterData = NULL; diff --git a/source/fbi/action/updatetitledb.c b/source/fbi/action/updatetitledb.c index f2ee14c..bd20ebd 100644 --- a/source/fbi/action/updatetitledb.c +++ b/source/fbi/action/updatetitledb.c @@ -9,9 +9,10 @@ #include "../../core/core.h" typedef struct { - bool cia[INSTALL_URLS_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]; } update_titledb_data; @@ -58,29 +59,42 @@ void action_update_titledb(linked_list* items, list_item* selected) { titledb_info* info = (titledb_info*) item->data; 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; - 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; index++; } - if(info->tdsx.outdated) { + if(info->tdsx.outdated && (!info->tdsx.smdh.exists || index < INSTALL_URLS_MAX - 1)) { char name[FILE_NAME_MAX]; 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); - 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; 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) { - 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 { prompt_display_notify("Success", "All titles are up to date.", COLOR_TEXT, NULL, NULL, NULL); } diff --git a/source/fbi/files.c b/source/fbi/files.c index 788118a..8f5e2cb 100644 --- a/source/fbi/files.c +++ b/source/fbi/files.c @@ -370,6 +370,7 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) { data->populateData.recursive = false; data->populateData.includeBase = true; + data->populateData.meta = true; data->populateData.filter = files_filter; data->populateData.filterData = data; diff --git a/source/fbi/task/listfiles.c b/source/fbi/task/listfiles.c index efca4a8..486dddc 100644 --- a/source/fbi/task/listfiles.c +++ b/source/fbi/task/listfiles.c @@ -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_iterate(data->items, &iter); diff --git a/source/fbi/task/listfiles.h b/source/fbi/task/listfiles.h index 54d4c3f..1138f5e 100644 --- a/source/fbi/task/listfiles.h +++ b/source/fbi/task/listfiles.h @@ -40,6 +40,7 @@ typedef struct populate_files_data_s { bool recursive; bool includeBase; + bool meta; bool (*filter)(void* data, const char* name, u32 attributes); void* filterData;