forked from SciresM/hactool
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix XTS/NCA2 support. Add NCA0 support.
- Loading branch information
Showing
14 changed files
with
730 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
#include <stdio.h> | ||
#include "types.h" | ||
#include "utils.h" | ||
#include "nca0_romfs.h" | ||
|
||
/* NCA0 RomFS functions... */ | ||
void nca0_romfs_visit_file(nca0_romfs_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) { | ||
romfs_fentry_t *entry = romfs_get_fentry(ctx->files, file_offset); | ||
filepath_t *cur_path = calloc(1, sizeof(filepath_t)); | ||
if (cur_path == NULL) { | ||
fprintf(stderr, "Failed to allocate filepath!\n"); | ||
exit(EXIT_FAILURE); | ||
} | ||
|
||
filepath_copy(cur_path, dir_path); | ||
if (entry->name_size) { | ||
filepath_append_n(cur_path, entry->name_size, "%s", entry->name); | ||
} | ||
|
||
/* If we're extracting... */ | ||
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) { | ||
printf("Saving %s...\n", cur_path->char_path); | ||
save_file_section(ctx->file, ctx->romfs_offset + ctx->header.data_offset + entry->offset, entry->size, cur_path); | ||
} else { | ||
printf("rom:%s\n", cur_path->char_path); | ||
} | ||
|
||
free(cur_path); | ||
|
||
if (entry->sibling != ROMFS_ENTRY_EMPTY) { | ||
nca0_romfs_visit_file(ctx, entry->sibling, dir_path); | ||
} | ||
} | ||
|
||
void nca0_romfs_visit_dir(nca0_romfs_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) { | ||
romfs_direntry_t *entry = romfs_get_direntry(ctx->directories, dir_offset); | ||
filepath_t *cur_path = calloc(1, sizeof(filepath_t)); | ||
if (cur_path == NULL) { | ||
fprintf(stderr, "Failed to allocate filepath!\n"); | ||
exit(EXIT_FAILURE); | ||
} | ||
|
||
filepath_copy(cur_path, parent_path); | ||
if (entry->name_size) { | ||
filepath_append_n(cur_path, entry->name_size, "%s", entry->name); | ||
} | ||
|
||
/* If we're actually extracting the romfs, make directory. */ | ||
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) { | ||
os_makedir(cur_path->os_path); | ||
} | ||
|
||
if (entry->file != ROMFS_ENTRY_EMPTY) { | ||
nca0_romfs_visit_file(ctx, entry->file, cur_path); | ||
} | ||
if (entry->child != ROMFS_ENTRY_EMPTY) { | ||
nca0_romfs_visit_dir(ctx, entry->child, cur_path); | ||
} | ||
if (entry->sibling != ROMFS_ENTRY_EMPTY) { | ||
nca0_romfs_visit_dir(ctx, entry->sibling, parent_path); | ||
} | ||
|
||
free(cur_path); | ||
} | ||
|
||
void nca0_romfs_process(nca0_romfs_ctx_t *ctx) { | ||
ctx->romfs_offset = 0; | ||
fseeko64(ctx->file, ctx->romfs_offset, SEEK_SET); | ||
if (fread(&ctx->header, 1, sizeof(nca0_romfs_hdr_t), ctx->file) != sizeof(nca0_romfs_hdr_t)) { | ||
fprintf(stderr, "Failed to read NCA0 RomFS header!\n"); | ||
return; | ||
} | ||
|
||
if ((ctx->tool_ctx->action & (ACTION_EXTRACT | ACTION_LISTROMFS)) && ctx->header.header_size == NCA0_ROMFS_HEADER_SIZE) { | ||
/* Pre-load the file/data entry caches. */ | ||
ctx->directories = calloc(1, ctx->header.dir_meta_table_size); | ||
if (ctx->directories == NULL) { | ||
fprintf(stderr, "Failed to allocate NCA0 RomFS directory cache!\n"); | ||
exit(EXIT_FAILURE); | ||
} | ||
|
||
fseeko64(ctx->file, ctx->romfs_offset + ctx->header.dir_meta_table_offset, SEEK_SET); | ||
if (fread(ctx->directories, 1, ctx->header.dir_meta_table_size, ctx->file) != ctx->header.dir_meta_table_size) { | ||
fprintf(stderr, "Failed to read NCA0 RomFS directory cache!\n"); | ||
exit(EXIT_FAILURE); | ||
} | ||
|
||
ctx->files = calloc(1, ctx->header.file_meta_table_size); | ||
if (ctx->files == NULL) { | ||
fprintf(stderr, "Failed to allocate NCA0 RomFS file cache!\n"); | ||
exit(EXIT_FAILURE); | ||
} | ||
fseeko64(ctx->file, ctx->romfs_offset + ctx->header.file_meta_table_offset, SEEK_SET); | ||
if (fread(ctx->files, 1, ctx->header.file_meta_table_size, ctx->file) != ctx->header.file_meta_table_size) { | ||
fprintf(stderr, "Failed to read NCA0 RomFS file cache!\n"); | ||
exit(EXIT_FAILURE); | ||
} | ||
} else { | ||
fprintf(stderr, "NCA0 RomFS is corrupt?\n"); | ||
return; | ||
} | ||
|
||
/* If there's ever anything meaningful to print about RomFS, uncomment and implement. | ||
* | ||
* if (ctx->tool_ctx->action & ACTION_INFO) { | ||
* nca0_romfs_print(ctx); | ||
* } | ||
*/ | ||
|
||
if (ctx->tool_ctx->action & ACTION_EXTRACT) { | ||
nca0_romfs_save(ctx); | ||
} | ||
|
||
} | ||
|
||
void nca0_romfs_save(nca0_romfs_ctx_t *ctx) { | ||
if (ctx->tool_ctx->action & ACTION_LISTROMFS) { | ||
filepath_t fakepath; | ||
filepath_init(&fakepath); | ||
filepath_set(&fakepath, ""); | ||
|
||
nca0_romfs_visit_dir(ctx, 0, &fakepath); | ||
} else { | ||
/* Extract to directory. */ | ||
filepath_t *dirpath = NULL; | ||
if (ctx->tool_ctx->settings.romfs_dir_path.enabled) { | ||
dirpath = &ctx->tool_ctx->settings.romfs_dir_path.path; | ||
} | ||
if ((dirpath == NULL || dirpath->valid != VALIDITY_VALID) && (ctx->tool_ctx->file_type == FILETYPE_NCA0_ROMFS && ctx->tool_ctx->settings.out_dir_path.enabled)) { | ||
dirpath = &ctx->tool_ctx->settings.out_dir_path.path; | ||
} | ||
if (dirpath != NULL && dirpath->valid == VALIDITY_VALID) { | ||
os_makedir(dirpath->os_path); | ||
nca0_romfs_visit_dir(ctx, 0, dirpath); | ||
} | ||
} | ||
|
||
} | ||
|
||
void nca0_romfs_print(nca0_romfs_ctx_t *ctx) { | ||
/* Is there anything meaningful to print here? */ | ||
fprintf(stderr, "Error: NCA0 RomFS printing not implemented.\n"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#ifndef HACTOOL_NCA0_ROMFS_H | ||
#define HACTOOL_NCA0_ROMFS_H | ||
|
||
#include "types.h" | ||
#include "utils.h" | ||
#include "ivfc.h" | ||
#include "settings.h" | ||
|
||
/* RomFS structs. */ | ||
#define NCA0_ROMFS_HEADER_SIZE 0x00000028 | ||
|
||
typedef struct { | ||
uint32_t header_size; | ||
uint32_t dir_hash_table_offset; | ||
uint32_t dir_hash_table_size; | ||
uint32_t dir_meta_table_offset; | ||
uint32_t dir_meta_table_size; | ||
uint32_t file_hash_table_offset; | ||
uint32_t file_hash_table_size; | ||
uint32_t file_meta_table_offset; | ||
uint32_t file_meta_table_size; | ||
uint32_t data_offset; | ||
} nca0_romfs_hdr_t; | ||
|
||
typedef struct { | ||
uint8_t master_hash[0x20]; /* SHA-256 hash of the hash table. */ | ||
uint32_t block_size; /* In bytes. */ | ||
uint32_t always_2; | ||
uint64_t hash_table_offset; /* Normally zero. */ | ||
uint64_t hash_table_size; | ||
uint64_t romfs_offset; | ||
uint64_t romfs_size; | ||
uint8_t _0x48[0xF0]; | ||
} nca0_romfs_superblock_t; | ||
|
||
typedef struct { | ||
nca0_romfs_superblock_t *superblock; | ||
FILE *file; | ||
hactool_ctx_t *tool_ctx; | ||
validity_t superblock_hash_validity; | ||
validity_t hash_table_validity; | ||
uint64_t romfs_offset; | ||
nca0_romfs_hdr_t header; | ||
romfs_direntry_t *directories; | ||
romfs_fentry_t *files; | ||
} nca0_romfs_ctx_t; | ||
|
||
void nca0_romfs_process(nca0_romfs_ctx_t *ctx); | ||
void nca0_romfs_save(nca0_romfs_ctx_t *ctx); | ||
void nca0_romfs_print(nca0_romfs_ctx_t *ctx); | ||
|
||
|
||
#endif |
Oops, something went wrong.