diff --git a/code_templates/sd_romfs_dumper.c b/code_templates/sd_romfs_dumper.c index 4bf6bbd..0ee2238 100644 --- a/code_templates/sd_romfs_dumper.c +++ b/code_templates/sd_romfs_dumper.c @@ -20,7 +20,7 @@ */ #include "nxdt_utils.h" -#include "bktr.h" +#include "romfs.h" #include "gamecard.h" #include "title.h" @@ -37,7 +37,6 @@ typedef struct { FILE *fd; RomFileSystemContext *romfs_ctx; - BktrContext *bktr_ctx; void *data; size_t data_size; size_t data_written; @@ -87,7 +86,7 @@ static void consolePrint(const char *text, ...) static void read_thread_func(void *arg) { ThreadSharedData *shared_data = (ThreadSharedData*)arg; - if (!shared_data || shared_data->fd || !shared_data->data || !shared_data->total_size || (!shared_data->romfs_ctx && !shared_data->bktr_ctx)) + if (!shared_data || shared_data->fd || !shared_data->data || !shared_data->total_size || !shared_data->romfs_ctx) { shared_data->read_error = true; goto end; @@ -101,7 +100,7 @@ static void read_thread_func(void *arg) } u64 file_table_offset = 0; - u64 file_table_size = (shared_data->bktr_ctx ? shared_data->bktr_ctx->patch_romfs_ctx.file_table_size : shared_data->romfs_ctx->file_table_size); + u64 file_table_size = shared_data->romfs_ctx->file_table_size; RomFileSystemFileEntry *file_entry = NULL; char path[FS_MAX_PATH] = {0}; @@ -130,15 +129,8 @@ static void read_thread_func(void *arg) } /* Retrieve RomFS file entry information. */ - if (shared_data->bktr_ctx) - { - shared_data->read_error = (!(file_entry = bktrGetFileEntryByOffset(shared_data->bktr_ctx, file_table_offset)) || \ - !bktrGeneratePathFromFileEntry(shared_data->bktr_ctx, file_entry, path + 11, FS_MAX_PATH - 11, RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly)); - } else { - shared_data->read_error = (!(file_entry = romfsGetFileEntryByOffset(shared_data->romfs_ctx, file_table_offset)) || \ - !romfsGeneratePathFromFileEntry(shared_data->romfs_ctx, file_entry, path + 11, FS_MAX_PATH - 11, RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly)); - } - + shared_data->read_error = (!(file_entry = romfsGetFileEntryByOffset(shared_data->romfs_ctx, file_table_offset)) || \ + !romfsGeneratePathFromFileEntry(shared_data->romfs_ctx, file_entry, path + 11, FS_MAX_PATH - 11, RomFileSystemPathIllegalCharReplaceType_KeepAsciiCharsOnly)); if (shared_data->read_error) { condvarWakeAll(&g_writeCondvar); @@ -168,8 +160,7 @@ static void read_thread_func(void *arg) } /* Read current file data chunk. */ - shared_data->read_error = (shared_data->bktr_ctx ? !bktrReadFileEntryData(shared_data->bktr_ctx, file_entry, buf, blksize, offset) : \ - !romfsReadFileEntryData(shared_data->romfs_ctx, file_entry, buf, blksize, offset)); + shared_data->read_error = !romfsReadFileEntryData(shared_data->romfs_ctx, file_entry, buf, blksize, offset); if (shared_data->read_error) { condvarWakeAll(&g_writeCondvar); @@ -406,7 +397,6 @@ int main(int argc, char *argv[]) NcaContext *base_nca_ctx = NULL, *update_nca_ctx = NULL; RomFileSystemContext romfs_ctx = {0}; - BktrContext bktr_ctx = {0}; ThreadSharedData shared_data = {0}; Thread read_thread = {0}, write_thread = {0}; @@ -586,9 +576,18 @@ int main(int argc, char *argv[]) goto out2; } - if (user_app_data.patch_info) + TitleInfo *latest_patch = NULL; + if (user_app_data.patch_info) latest_patch = get_latest_patch_info(user_app_data.patch_info); + + if (base_nca_ctx->fs_ctx[1].has_sparse_layer && (!latest_patch || latest_patch->version.value < user_app_data.app_info->version.value)) { - TitleInfo *latest_patch = get_latest_patch_info(user_app_data.patch_info); + consolePrint("base app is a sparse title and no v%u or greater update could be found\n", user_app_data.app_info->version.value); + goto out2; + } + + if (latest_patch) + { + consolePrint("using patch romfs with update v%u\n", latest_patch->version.value); if (!ncaInitializeContext(update_nca_ctx, latest_patch->storage_id, (latest_patch->storage_id == NcmStorageId_GameCard ? GameCardHashFileSystemPartitionType_Secure : 0), \ titleGetContentInfoByTypeAndIdOffset(latest_patch, NcmContentType_Program, program_id_offset), latest_patch->version.value, NULL)) @@ -597,29 +596,26 @@ int main(int argc, char *argv[]) goto out2; } - if (!bktrInitializeContext(&bktr_ctx, &(base_nca_ctx->fs_ctx[1]), &(update_nca_ctx->fs_ctx[1]))) + if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]), &(update_nca_ctx->fs_ctx[1]))) { - consolePrint("bktr initialize ctx failed\n"); + consolePrint("romfs initialize ctx failed (update)\n"); goto out2; } - - shared_data.bktr_ctx = &bktr_ctx; - bktrGetTotalDataSize(&bktr_ctx, &(shared_data.total_size)); - - consolePrint("bktr initialize ctx succeeded\n"); } else { - if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]))) + consolePrint("using base romfs only\n"); + + if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]), NULL)) { - consolePrint("romfs initialize ctx failed\n"); + consolePrint("romfs initialize ctx failed (base)\n"); goto out2; } - - shared_data.romfs_ctx = &romfs_ctx; - romfsGetTotalDataSize(&romfs_ctx, &(shared_data.total_size)); - - consolePrint("romfs initialize ctx succeeded\n"); } + shared_data.romfs_ctx = &romfs_ctx; + romfsGetTotalDataSize(&romfs_ctx, &(shared_data.total_size)); + + consolePrint("romfs initialize ctx succeeded\n"); + shared_data.fd = NULL; shared_data.data = buf; shared_data.data_size = 0; @@ -718,7 +714,6 @@ out2: } romfsFreeContext(&romfs_ctx); - bktrFreeContext(&bktr_ctx); if (update_nca_ctx) free(update_nca_ctx); diff --git a/code_templates/system_title_dumper.c b/code_templates/system_title_dumper.c index 6b1b127..d0a4814 100644 --- a/code_templates/system_title_dumper.c +++ b/code_templates/system_title_dumper.c @@ -167,7 +167,7 @@ static void dumpRomFs(TitleInfo *info, NcaFsSectionContext *nca_fs_ctx) size_t path_len = 0; *path = '\0'; - if (!romfsInitializeContext(&romfs_ctx, nca_fs_ctx)) + if (!romfsInitializeContext(&romfs_ctx, nca_fs_ctx, NULL)) { consolePrint("romfs initialize ctx failed!\n"); goto end; diff --git a/code_templates/usb_romfs_dumper.c b/code_templates/usb_romfs_dumper.c index 2b24db0..49fa00a 100644 --- a/code_templates/usb_romfs_dumper.c +++ b/code_templates/usb_romfs_dumper.c @@ -20,7 +20,7 @@ */ #include "nxdt_utils.h" -#include "bktr.h" +#include "romfs.h" #include "gamecard.h" #include "usb.h" #include "title.h" @@ -38,7 +38,6 @@ typedef struct { //FILE *fileobj; RomFileSystemContext *romfs_ctx; - BktrContext *bktr_ctx; void *data; size_t data_size; size_t data_written; @@ -88,7 +87,7 @@ static void consolePrint(const char *text, ...) static void read_thread_func(void *arg) { ThreadSharedData *shared_data = (ThreadSharedData*)arg; - if (!shared_data || !shared_data->data || !shared_data->total_size || (!shared_data->romfs_ctx && !shared_data->bktr_ctx)) + if (!shared_data || !shared_data->data || !shared_data->total_size || !shared_data->romfs_ctx) { shared_data->read_error = true; goto end; @@ -102,7 +101,7 @@ static void read_thread_func(void *arg) } u64 file_table_offset = 0; - u64 file_table_size = (shared_data->bktr_ctx ? shared_data->bktr_ctx->patch_romfs_ctx.file_table_size : shared_data->romfs_ctx->file_table_size); + u64 file_table_size = shared_data->romfs_ctx->file_table_size; RomFileSystemFileEntry *file_entry = NULL; char path[FS_MAX_PATH] = {0}; @@ -116,15 +115,8 @@ static void read_thread_func(void *arg) } /* Retrieve RomFS file entry information */ - if (shared_data->bktr_ctx) - { - shared_data->read_error = (!(file_entry = bktrGetFileEntryByOffset(shared_data->bktr_ctx, file_table_offset)) || \ - !bktrGeneratePathFromFileEntry(shared_data->bktr_ctx, file_entry, path, FS_MAX_PATH, RomFileSystemPathIllegalCharReplaceType_IllegalFsChars)); - } else { - shared_data->read_error = (!(file_entry = romfsGetFileEntryByOffset(shared_data->romfs_ctx, file_table_offset)) || \ - !romfsGeneratePathFromFileEntry(shared_data->romfs_ctx, file_entry, path, FS_MAX_PATH, RomFileSystemPathIllegalCharReplaceType_IllegalFsChars)); - } - + shared_data->read_error = (!(file_entry = romfsGetFileEntryByOffset(shared_data->romfs_ctx, file_table_offset)) || \ + !romfsGeneratePathFromFileEntry(shared_data->romfs_ctx, file_entry, path, FS_MAX_PATH, RomFileSystemPathIllegalCharReplaceType_IllegalFsChars)); if (shared_data->read_error) { condvarWakeAll(&g_writeCondvar); @@ -157,8 +149,7 @@ static void read_thread_func(void *arg) } /* Read current file data chunk */ - shared_data->read_error = (shared_data->bktr_ctx ? !bktrReadFileEntryData(shared_data->bktr_ctx, file_entry, buf, blksize, offset) : \ - !romfsReadFileEntryData(shared_data->romfs_ctx, file_entry, buf, blksize, offset)); + shared_data->read_error = !romfsReadFileEntryData(shared_data->romfs_ctx, file_entry, buf, blksize, offset); if (shared_data->read_error) { condvarWakeAll(&g_writeCondvar); @@ -385,7 +376,6 @@ int main(int argc, char *argv[]) NcaContext *base_nca_ctx = NULL, *update_nca_ctx = NULL; RomFileSystemContext romfs_ctx = {0}; - BktrContext bktr_ctx = {0}; ThreadSharedData shared_data = {0}; Thread read_thread = {0}, write_thread = {0}; @@ -559,9 +549,18 @@ int main(int argc, char *argv[]) goto out2; } - if (user_app_data.patch_info) + TitleInfo *latest_patch = NULL; + if (user_app_data.patch_info) latest_patch = get_latest_patch_info(user_app_data.patch_info); + + if (base_nca_ctx->fs_ctx[1].has_sparse_layer && (!latest_patch || latest_patch->version.value < user_app_data.app_info->version.value)) { - TitleInfo *latest_patch = get_latest_patch_info(user_app_data.patch_info); + consolePrint("base app is a sparse title and no v%u or greater update could be found\n", user_app_data.app_info->version.value); + goto out2; + } + + if (latest_patch) + { + consolePrint("using patch romfs with update v%u\n", latest_patch->version.value); if (!ncaInitializeContext(update_nca_ctx, latest_patch->storage_id, (latest_patch->storage_id == NcmStorageId_GameCard ? GameCardHashFileSystemPartitionType_Secure : 0), \ titleGetContentInfoByTypeAndIdOffset(latest_patch, NcmContentType_Program, program_id_offset), latest_patch->version.value, NULL)) @@ -570,29 +569,26 @@ int main(int argc, char *argv[]) goto out2; } - if (!bktrInitializeContext(&bktr_ctx, &(base_nca_ctx->fs_ctx[1]), &(update_nca_ctx->fs_ctx[1]))) + if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]), &(update_nca_ctx->fs_ctx[1]))) { - consolePrint("bktr initialize ctx failed\n"); + consolePrint("romfs initialize ctx failed (update)\n"); goto out2; } - - shared_data.bktr_ctx = &bktr_ctx; - bktrGetTotalDataSize(&bktr_ctx, &(shared_data.total_size)); - - consolePrint("bktr initialize ctx succeeded\n"); } else { - if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]))) + consolePrint("using base romfs only\n"); + + if (!romfsInitializeContext(&romfs_ctx, &(base_nca_ctx->fs_ctx[1]), NULL)) { - consolePrint("romfs initialize ctx failed\n"); + consolePrint("romfs initialize ctx failed (base)\n"); goto out2; } - - shared_data.romfs_ctx = &romfs_ctx; - romfsGetTotalDataSize(&romfs_ctx, &(shared_data.total_size)); - - consolePrint("romfs initialize ctx succeeded\n"); } + shared_data.romfs_ctx = &romfs_ctx; + romfsGetTotalDataSize(&romfs_ctx, &(shared_data.total_size)); + + consolePrint("romfs initialize ctx succeeded\n"); + shared_data.data = buf; shared_data.data_size = 0; shared_data.data_written = 0; @@ -719,7 +715,6 @@ out2: } romfsFreeContext(&romfs_ctx); - bktrFreeContext(&bktr_ctx); if (update_nca_ctx) free(update_nca_ctx); diff --git a/include/core/legal_info.h b/include/core/legal_info.h index a28a9cc..2b93ab4 100644 --- a/include/core/legal_info.h +++ b/include/core/legal_info.h @@ -24,7 +24,7 @@ #ifndef __LEGAL_INFO_H__ #define __LEGAL_INFO_H__ -#include "nca.h" +#include "romfs.h" #ifdef __cplusplus extern "C" { diff --git a/source/core/bktr.c b/source/core/bktr.c index 1374b7e..17dcc05 100644 --- a/source/core/bktr.c +++ b/source/core/bktr.c @@ -123,7 +123,7 @@ NX_INLINE bool bktrIsExistOffsetL2OnL1(BucketTreeContext *ctx); static void bktrInitializeStorageNode(BucketTreeStorageNode *out, u64 entry_size, u32 entry_count); static void bktrStorageNodeFind(BucketTreeStorageNode *storage_node, const BucketTreeNodeHeader *node_header, u64 virtual_offset); NX_INLINE BucketTreeStorageNodeOffset bktrStorageNodeOffsetAdd(BucketTreeStorageNodeOffset *ofs, u64 value); -NX_INLINE u64 bktrStorageNodeOffsetSubstract(BucketTreeStorageNodeOffset *ofs1, BucketTreeStorageNodeOffset *ofs2); +NX_INLINE const u64 bktrStorageNodeOffsetGetEntryVirtualOffset(const BucketTreeNodeHeader *node_header, const BucketTreeStorageNodeOffset *ofs); NX_INLINE bool bktrVisitorIsValid(BucketTreeVisitor *visitor); NX_INLINE bool bktrVisitorCanMoveNext(BucketTreeVisitor *visitor); @@ -1104,21 +1104,27 @@ static bool bktrGetTreeNodeEntryIndex(const u64 *start_ptr, const u64 *end_ptr, } u64 *pos = (u64*)start_ptr; - bool found = false; + u32 index = 0; while(pos < end_ptr) { - if (start_ptr < pos && *pos > virtual_offset) + if (start_ptr < pos) { - *out_index = ((u32)(pos - start_ptr) - 1); - found = true; - break; + /* Stop looking if we have found the right offset node. */ + if (*pos > virtual_offset) break; + + /* Increment index. */ + index++; } + /* Increment offset node pointer. */ pos++; } - return found; + /* Update output index. */ + *out_index = index; + + return true; } static bool bktrGetEntryNodeEntryIndex(const BucketTreeNodeHeader *node_header, u64 entry_size, u64 virtual_offset, u32 *out_index) @@ -1299,25 +1305,41 @@ static void bktrInitializeStorageNode(BucketTreeStorageNode *out, u64 entry_size static void bktrStorageNodeFind(BucketTreeStorageNode *storage_node, const BucketTreeNodeHeader *node_header, u64 virtual_offset) { - u32 end = storage_node->count; - BucketTreeStorageNodeOffset pos = storage_node->start; - - while(end > 0) + /* Check for edge case, short circuit. */ + if (storage_node->count == 1) { - u32 half = (end / 2); - BucketTreeStorageNodeOffset mid = bktrStorageNodeOffsetAdd(&pos, half); - - const u64 offset = *((const u64*)((const u8*)node_header + mid.offset)); - if (offset <= virtual_offset) - { - pos = bktrStorageNodeOffsetAdd(&mid, 1); - end -= (half + 1); - } else { - end = half; - } + storage_node->index = 0; + return; } - storage_node->index = ((u32)bktrStorageNodeOffsetSubstract(&pos, &(storage_node->start)) - 1); + /* Perform a binary search. */ + u32 entry_count = storage_node->count, low = 0, high = (entry_count - 1); + BucketTreeStorageNodeOffset *start = &(storage_node->start); + + while(low <= high) + { + /* Get the offset to the middle entry within our current lookup range. */ + u32 half = ((low + high) / 2); + BucketTreeStorageNodeOffset mid = bktrStorageNodeOffsetAdd(start, half); + + /* Check middle entry's virtual offset. */ + if (bktrStorageNodeOffsetGetEntryVirtualOffset(node_header, &mid) > virtual_offset) + { + /* Update our upper limit. */ + high = (half - 1); + } else { + /* Check for success. */ + BucketTreeStorageNodeOffset pos = bktrStorageNodeOffsetAdd(&mid, 1); + if (half == (entry_count - 1) || bktrStorageNodeOffsetGetEntryVirtualOffset(node_header, &pos) > virtual_offset) + { + storage_node->index = half; + break; + } + + /* Update our lower limit. */ + low = (half + 1); + } + } } NX_INLINE BucketTreeStorageNodeOffset bktrStorageNodeOffsetAdd(BucketTreeStorageNodeOffset *ofs, u64 value) @@ -1326,9 +1348,9 @@ NX_INLINE BucketTreeStorageNodeOffset bktrStorageNodeOffsetAdd(BucketTreeStorage return out; } -NX_INLINE u64 bktrStorageNodeOffsetSubstract(BucketTreeStorageNodeOffset *ofs1, BucketTreeStorageNodeOffset *ofs2) +NX_INLINE const u64 bktrStorageNodeOffsetGetEntryVirtualOffset(const BucketTreeNodeHeader *node_header, const BucketTreeStorageNodeOffset *ofs) { - return (u64)((ofs1->offset - ofs2->offset) / ofs1->stride); + return *((const u64*)((const u8*)node_header + ofs->offset)); } NX_INLINE bool bktrVisitorIsValid(BucketTreeVisitor *visitor) @@ -1356,12 +1378,12 @@ static bool bktrVisitorMoveNext(BucketTreeVisitor *visitor) BucketTreeContext *ctx = visitor->bktr_ctx; BucketTreeEntrySetHeader *entry_set = &(visitor->entry_set); + u32 entry_index = (visitor->entry_index + 1); bool success = false; /* Invalidate index. */ visitor->entry_index = UINT32_MAX; - u32 entry_index = (visitor->entry_index + 1); if (entry_index == entry_set->header.count) { /* We have reached the end of this entry node. Let's try to retrieve the first entry from the next one. */ @@ -1428,12 +1450,12 @@ static bool bktrVisitorMovePrevious(BucketTreeVisitor *visitor) BucketTreeContext *ctx = visitor->bktr_ctx; BucketTreeEntrySetHeader *entry_set = &(visitor->entry_set); + u32 entry_index = visitor->entry_index; bool success = false; /* Invalidate index. */ visitor->entry_index = UINT32_MAX; - u32 entry_index = visitor->entry_index; if (entry_index == 0) { /* We have reached the start of this entry node. Let's try to retrieve the last entry from the previous one. */ diff --git a/source/core/legal_info.c b/source/core/legal_info.c index a66fced..45d882f 100644 --- a/source/core/legal_info.c +++ b/source/core/legal_info.c @@ -21,7 +21,6 @@ #include "nxdt_utils.h" #include "legal_info.h" -#include "romfs.h" bool legalInfoInitializeContext(LegalInfoContext *out, NcaContext *nca_ctx) { diff --git a/source/core/nca_storage.c b/source/core/nca_storage.c index 7b619ca..5a10e54 100644 --- a/source/core/nca_storage.c +++ b/source/core/nca_storage.c @@ -119,7 +119,7 @@ bool ncaStorageSetPatchOriginalSubStorage(NcaStorageContext *patch_ctx, NcaStora !(patch_nca_ctx = (NcaContext*)patch_ctx->nca_fs_ctx->nca_ctx) || !(base_nca_ctx = (NcaContext*)base_ctx->nca_fs_ctx->nca_ctx) || \ patch_ctx->nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || base_ctx->nca_fs_ctx->section_type != NcaFsSectionType_RomFs || \ patch_nca_ctx->header.program_id != base_nca_ctx->header.program_id || patch_nca_ctx->header.content_type != base_nca_ctx->header.content_type || \ - patch_nca_ctx->id_offset != base_nca_ctx->id_offset || patch_nca_ctx->title_version <= base_nca_ctx->title_version || !patch_ctx->indirect_storage) + patch_nca_ctx->id_offset != base_nca_ctx->id_offset || patch_nca_ctx->title_version < base_nca_ctx->title_version || !patch_ctx->indirect_storage) { LOG_MSG("Invalid parameters!"); return false; @@ -170,26 +170,19 @@ bool ncaStorageGetHashTargetExtents(NcaStorageContext *ctx, u64 *out_offset, u64 switch(ctx->base_storage_type) { case NcaStorageBaseStorageType_Regular: + case NcaStorageBaseStorageType_Sparse: + case NcaStorageBaseStorageType_Indirect: { - /* Just provide the NCA FS section hash target extents. */ + /* Regular: just provide the NCA FS section hash target extents -- they already represent physical information. */ + /* Sparse/Indirect: the base storage's virtual section encompasses the hash layers, too. The NCA FS section hash target extents represent valid virtual information. */ if (out_offset) *out_offset = hash_target_offset; if (out_size) *out_size = hash_target_size; break; } - case NcaStorageBaseStorageType_Sparse: - case NcaStorageBaseStorageType_Indirect: - { - /* Sparse/Indirect storages encompass the entire virtual section. */ - /* Let's substract the NCA FS section hash target offset from the storage's virtual end offset. */ - BucketTreeContext *bktr_ctx = (ctx->base_storage_type == NcaStorageBaseStorageType_Sparse ? ctx->sparse_storage : ctx->indirect_storage); - if (out_offset) *out_offset = hash_target_offset; - if (out_size) *out_size = (bktr_ctx->end_offset - hash_target_offset); - break; - } case NcaStorageBaseStorageType_Compressed: { - /* Compressed sections already reference the hash target section, so there's no need calculate the full size. */ - if (out_offset) *out_offset = 0; + /* Compressed sections already point to the hash target layer. */ + if (out_offset) *out_offset = ctx->compressed_storage->start_offset; if (out_size) *out_size = ctx->compressed_storage->end_offset; break; } @@ -232,7 +225,7 @@ bool ncaStorageRead(NcaStorageContext *ctx, void *out, u64 read_size, u64 offset break; } - if (!success) LOG_MSG("Failed to read 0x%lX-byte long block from offset 0x%lX in base storage! (%u).", read_size, offset, ctx->base_storage_type); + if (!success) LOG_MSG("Failed to read 0x%lX-byte long block from offset 0x%lX in base storage! (type: %u).", read_size, offset, ctx->base_storage_type); return success; } diff --git a/source/core/romfs.c b/source/core/romfs.c index e50c4f0..aad8d28 100644 --- a/source/core/romfs.c +++ b/source/core/romfs.c @@ -31,14 +31,14 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base { u64 dir_table_offset = 0, file_table_offset = 0; NcaContext *base_nca_ctx = NULL, *patch_nca_ctx = NULL; - bool dump_fs_header = false, is_patch = (patch_nca_fs_ctx != NULL), success = false; + bool dump_fs_header = false, success = false; - if (!out || !base_nca_fs_ctx || !base_nca_fs_ctx->enabled || (base_nca_fs_ctx->has_sparse_layer && !is_patch) || !(base_nca_ctx = (NcaContext*)base_nca_fs_ctx->nca_ctx) || \ + if (!out || !base_nca_fs_ctx || !base_nca_fs_ctx->enabled || (base_nca_fs_ctx->has_sparse_layer && !patch_nca_fs_ctx) || !(base_nca_ctx = (NcaContext*)base_nca_fs_ctx->nca_ctx) || \ (base_nca_ctx->format_version == NcaVersion_Nca0 && (base_nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs || \ base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalSha256)) || (base_nca_ctx->format_version != NcaVersion_Nca0 && \ (base_nca_fs_ctx->section_type != NcaFsSectionType_RomFs || (base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegrity && \ base_nca_fs_ctx->hash_type != NcaHashType_HierarchicalIntegritySha3))) || (base_nca_ctx->rights_id_available && !base_nca_ctx->titlekey_retrieved) || \ - (is_patch && (!patch_nca_fs_ctx->enabled || !(patch_nca_ctx = (NcaContext*)patch_nca_fs_ctx->nca_ctx) || patch_nca_ctx->format_version != base_nca_ctx->format_version || \ + (patch_nca_fs_ctx && (!patch_nca_fs_ctx->enabled || !(patch_nca_ctx = (NcaContext*)patch_nca_fs_ctx->nca_ctx) || patch_nca_ctx->format_version != base_nca_ctx->format_version || \ patch_nca_fs_ctx->section_type != NcaFsSectionType_PatchRomFs || (patch_nca_ctx->rights_id_available && !patch_nca_ctx->titlekey_retrieved)))) { LOG_MSG("Invalid parameters!"); @@ -58,9 +58,7 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base goto end; } - out->is_patch = is_patch; - - if (is_patch) + if (patch_nca_fs_ctx) { /* Initialize base NCA storage context. */ if (!ncaStorageInitializeContext(patch_storage_ctx, patch_nca_fs_ctx)) @@ -77,9 +75,11 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base } /* Set default NCA FS storage context. */ + out->is_patch = true; out->default_storage_ctx = patch_storage_ctx; } else { /* Set default NCA FS storage context. */ + out->is_patch = false; out->default_storage_ctx = base_storage_ctx; } diff --git a/todo.txt b/todo.txt index ba52f5e..d5e5cce 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,7 @@ todo: - nca: support for sparse sections - nca: support for compressed fs sections + nca / nca_storage / bktr: re-test support for all section types + nca: add function to retrieve a pointer to a nca fs ctx based on section type? (e.g. like titleGetContentInfoByTypeAndIdOffset) log: verbosity levels log: nxlink output for advanced users @@ -18,8 +18,6 @@ todo: romfs: functions to display filelist - bktr: functions to display filelist (wrappers for romfs functions tbh) - usb: change buffer size? usb: change chunk size? usb: improve abi (make it rest-like?)