mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-26 04:02:11 +00:00
romfs: reintroduce support for missing base RomFS.
Also added a free space check and concatenation file creation to sd_romfs_dumper.
This commit is contained in:
parent
942a407247
commit
c910fe6c0a
4 changed files with 64 additions and 19 deletions
|
@ -126,6 +126,7 @@ static void read_thread_func(void *arg)
|
|||
{
|
||||
fclose(shared_data->fd);
|
||||
shared_data->fd = NULL;
|
||||
utilsCommitSdCardFileSystemChanges();
|
||||
}
|
||||
|
||||
/* Retrieve RomFS file entry information. */
|
||||
|
@ -141,6 +142,13 @@ static void read_thread_func(void *arg)
|
|||
utilsCreateDirectoryTree(path, false);
|
||||
|
||||
/* Create file. */
|
||||
if (file_entry->size > FAT32_FILESIZE_LIMIT && !utilsCreateConcatenationFile(path))
|
||||
{
|
||||
shared_data->read_error = true;
|
||||
condvarWakeAll(&g_writeCondvar);
|
||||
break;
|
||||
}
|
||||
|
||||
shared_data->read_error = ((shared_data->fd = fopen(path, "wb")) == NULL);
|
||||
if (shared_data->read_error)
|
||||
{
|
||||
|
@ -201,10 +209,10 @@ static void read_thread_func(void *arg)
|
|||
{
|
||||
fclose(shared_data->fd);
|
||||
shared_data->fd = NULL;
|
||||
if (shared_data->read_error || shared_data->write_error || shared_data->transfer_cancelled) utilsRemoveConcatenationFile(path);
|
||||
utilsCommitSdCardFileSystemChanges();
|
||||
}
|
||||
|
||||
if ((shared_data->read_error || shared_data->write_error || shared_data->transfer_cancelled) && *path) remove(path);
|
||||
|
||||
free(buf);
|
||||
|
||||
end:
|
||||
|
@ -579,6 +587,12 @@ int main(int argc, char *argv[])
|
|||
TitleInfo *latest_patch = NULL;
|
||||
if (user_app_data.patch_info) latest_patch = get_latest_patch_info(user_app_data.patch_info);
|
||||
|
||||
if (!latest_patch && (!base_nca_ctx->fs_ctx[1].enabled || (base_nca_ctx->fs_ctx[1].section_type != NcaFsSectionType_RomFs && base_nca_ctx->fs_ctx[1].section_type != NcaFsSectionType_Nca0RomFs)))
|
||||
{
|
||||
consolePrint("base app has no valid romfs and no updates could be found\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if (base_nca_ctx->fs_ctx[1].has_sparse_layer && (!latest_patch || latest_patch->version.value < user_app_data.app_info->version.value))
|
||||
{
|
||||
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);
|
||||
|
@ -616,6 +630,20 @@ int main(int argc, char *argv[])
|
|||
|
||||
consolePrint("romfs initialize ctx succeeded\n");
|
||||
|
||||
// check free space
|
||||
u64 free_space = 0;
|
||||
if (!utilsGetFileSystemStatsByPath("sdmc:/", NULL, &free_space))
|
||||
{
|
||||
consolePrint("failed to retrieve free sd card space\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if (free_space <= shared_data.total_size)
|
||||
{
|
||||
consolePrint("extracted romfs size (0x%lX) exceeds free sd card space (0x%lX)\n", shared_data.total_size, free_space);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
shared_data.fd = NULL;
|
||||
shared_data.data = buf;
|
||||
shared_data.data_size = 0;
|
||||
|
|
|
@ -552,6 +552,12 @@ int main(int argc, char *argv[])
|
|||
TitleInfo *latest_patch = NULL;
|
||||
if (user_app_data.patch_info) latest_patch = get_latest_patch_info(user_app_data.patch_info);
|
||||
|
||||
if (!latest_patch && (!base_nca_ctx->fs_ctx[1].enabled || (base_nca_ctx->fs_ctx[1].section_type != NcaFsSectionType_RomFs && base_nca_ctx->fs_ctx[1].section_type != NcaFsSectionType_Nca0RomFs)))
|
||||
{
|
||||
consolePrint("base app has no valid romfs and no updates could be found\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if (base_nca_ctx->fs_ctx[1].has_sparse_layer && (!latest_patch || latest_patch->version.value < user_app_data.app_info->version.value))
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -363,11 +363,12 @@ static bool bktrReadIndirectStorage(BucketTreeVisitor *visitor, void *out, u64 r
|
|||
{
|
||||
BucketTreeContext *ctx = visitor->bktr_ctx;
|
||||
bool is_sparse = (ctx->storage_type == BucketTreeStorageType_Sparse);
|
||||
bool missing_original_storage = !bktrIsValidSubstorage(&(ctx->substorages[0]));
|
||||
|
||||
if (!out || !bktrIsValidSubstorage(&(ctx->substorages[0])) || (!is_sparse && !bktrIsValidSubstorage(&(ctx->substorages[1]))) || \
|
||||
(!is_sparse && ((ctx->substorages[0].type != BucketTreeSubStorageType_Regular && ctx->substorages[0].type != BucketTreeStorageType_Compressed && \
|
||||
ctx->substorages[0].type != BucketTreeSubStorageType_Sparse) || ctx->substorages[1].type != BucketTreeSubStorageType_AesCtrEx)) || \
|
||||
(is_sparse && ctx->substorages[0].type != BucketTreeSubStorageType_Regular))
|
||||
if (!out || (is_sparse && (missing_original_storage || ctx->substorages[0].type != BucketTreeSubStorageType_Regular)) || \
|
||||
(!is_sparse && (!bktrIsValidSubstorage(&(ctx->substorages[1])) || ctx->substorages[1].type != BucketTreeSubStorageType_AesCtrEx || \
|
||||
(!missing_original_storage && ((ctx->substorages[0].type != BucketTreeSubStorageType_Regular && \
|
||||
ctx->substorages[0].type != BucketTreeStorageType_Compressed && ctx->substorages[0].type != BucketTreeSubStorageType_Sparse))))))
|
||||
{
|
||||
LOG_MSG("Invalid parameters!");
|
||||
return false;
|
||||
|
@ -438,10 +439,15 @@ static bool bktrReadIndirectStorage(BucketTreeVisitor *visitor, void *out, u64 r
|
|||
|
||||
if (cur_entry.storage_index == BucketTreeIndirectStorageIndex_Original)
|
||||
{
|
||||
/* Retrieve data from the original data storage. */
|
||||
/* This may either be a Regular/Sparse/Compressed storage from the base NCA (Indirect) or a Regular storage from this very same NCA (Sparse). */
|
||||
success = bktrReadSubStorage(&(ctx->substorages[0]), ¶ms);
|
||||
if (!success) LOG_MSG("Failed to read 0x%lX-byte long chunk from offset 0x%lX in original data storage!", read_size, data_offset);
|
||||
if (!missing_original_storage)
|
||||
{
|
||||
/* Retrieve data from the original data storage. */
|
||||
/* This may either be a Regular/Sparse/Compressed storage from the base NCA (Indirect) or a Regular storage from this very same NCA (Sparse). */
|
||||
success = bktrReadSubStorage(&(ctx->substorages[0]), ¶ms);
|
||||
if (!success) LOG_MSG("Failed to read 0x%lX-byte long chunk from offset 0x%lX in original data storage!", read_size, data_offset);
|
||||
} else {
|
||||
LOG_MSG("Error: attempting to read 0x%lX-byte long chunk from missing original data storage at offset 0x%lX!", read_size, data_offset);
|
||||
}
|
||||
} else {
|
||||
if (!is_sparse)
|
||||
{
|
||||
|
|
|
@ -33,12 +33,17 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base
|
|||
NcaContext *base_nca_ctx = NULL, *patch_nca_ctx = NULL;
|
||||
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 && !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) || \
|
||||
(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 || \
|
||||
/* Check if the base RomFS is missing (e.g. Fortnite, World of Tanks Blitz, etc.). */
|
||||
bool missing_base_romfs = (base_nca_fs_ctx && (!base_nca_fs_ctx->enabled || (base_nca_fs_ctx->section_type != NcaFsSectionType_RomFs && \
|
||||
base_nca_fs_ctx->section_type != NcaFsSectionType_Nca0RomFs)));
|
||||
|
||||
if (!out || !base_nca_fs_ctx || (!patch_nca_fs_ctx && (missing_base_romfs || base_nca_fs_ctx->has_sparse_layer)) || \
|
||||
(!missing_base_romfs && (!(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))) || (patch_nca_fs_ctx && (!patch_nca_fs_ctx->enabled || \
|
||||
!(patch_nca_ctx = (NcaContext*)patch_nca_fs_ctx->nca_ctx) || (!missing_base_romfs && 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!");
|
||||
|
@ -52,7 +57,7 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base
|
|||
bool is_nca0_romfs = (base_nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs);
|
||||
|
||||
/* Initialize base NCA storage context. */
|
||||
if (!ncaStorageInitializeContext(base_storage_ctx, base_nca_fs_ctx))
|
||||
if (!missing_base_romfs && !ncaStorageInitializeContext(base_storage_ctx, base_nca_fs_ctx))
|
||||
{
|
||||
LOG_MSG("Failed to initialize base NCA storage context!");
|
||||
goto end;
|
||||
|
@ -67,8 +72,8 @@ bool romfsInitializeContext(RomFileSystemContext *out, NcaFsSectionContext *base
|
|||
goto end;
|
||||
}
|
||||
|
||||
/* Set patch NCA storage original substorage. */
|
||||
if (!ncaStorageSetPatchOriginalSubStorage(patch_storage_ctx, base_storage_ctx))
|
||||
/* Set patch NCA storage original substorage, if available. */
|
||||
if (!missing_base_romfs && !ncaStorageSetPatchOriginalSubStorage(patch_storage_ctx, base_storage_ctx))
|
||||
{
|
||||
LOG_MSG("Failed to set patch NCA storage context's original substorage!");
|
||||
goto end;
|
||||
|
|
Loading…
Reference in a new issue