mirror of
https://github.com/SciresM/hactool
synced 2024-11-10 06:34:14 +00:00
Add more options for Update RomFS
This commit is contained in:
parent
8311740694
commit
5271b3ae00
6 changed files with 96 additions and 19 deletions
|
@ -40,6 +40,8 @@ NCA options:
|
|||
--listromfs List files in RomFS.
|
||||
--baseromfs Set Base RomFS to use with update partitions.
|
||||
--basenca Set Base NCA to use with update partitions.
|
||||
--basefake Use a fake Base RomFS with update partitions (all reads will return 0xCC).
|
||||
--onlyupdated Ignore non-updated files in update partitions.
|
||||
PFS0 options:
|
||||
--pfs0dir=dir Specify PFS0 directory path.
|
||||
--outdir=dir Specify PFS0 directory path. Overrides previous path, if present.
|
||||
|
|
|
@ -38,6 +38,14 @@ int os_makedir(const oschar_t *dir) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int os_rmdir(const oschar_t *dir) {
|
||||
#ifdef _WIN32
|
||||
return _wrmdir(dir);
|
||||
#else
|
||||
return remove(dir);
|
||||
#endif
|
||||
}
|
||||
|
||||
void filepath_update(filepath_t *fpath) {
|
||||
memset(fpath->os_path, 0, MAX_PATH * sizeof(oschar_t));
|
||||
os_strcpy(fpath->os_path, fpath->char_path);
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct filepath {
|
|||
|
||||
void os_strcpy(oschar_t *dst, const char *src);
|
||||
int os_makedir(const oschar_t *dir);
|
||||
int os_rmdir(const oschar_t *dir);
|
||||
|
||||
void filepath_init(filepath_t *fpath);
|
||||
void filepath_copy(filepath_t *fpath, filepath_t *copy);
|
||||
|
|
21
main.c
21
main.c
|
@ -50,7 +50,9 @@ static void usage(void) {
|
|||
" --romfsdir=dir Specify RomFS directory path. Overrides appropriate section directory path.\n"
|
||||
" --listromfs List files in RomFS.\n"
|
||||
" --baseromfs Set Base RomFS to use with update partitions.\n"
|
||||
" --basenca Set Base NCA to use with update partitions.\n"
|
||||
" --basenca Set Base NCA to use with update partitions.\n"
|
||||
" --basefake Use a fake Base RomFS with update partitions (all reads will return 0xCC).\n"
|
||||
" --onlyupdated Ignore non-updated files in update partitions.\n"
|
||||
"PFS0 options:\n"
|
||||
" --pfs0dir=dir Specify PFS0 directory path.\n"
|
||||
" --outdir=dir Specify PFS0 directory path. Overrides previous path, if present.\n"
|
||||
|
@ -148,6 +150,8 @@ int main(int argc, char **argv) {
|
|||
{"package2dir", 1, NULL, 27},
|
||||
{"ini1dir", 1, NULL, 28},
|
||||
{"extractini1", 0, NULL, 29},
|
||||
{"basefake", 0, NULL, 30},
|
||||
{"onlyupdated", 0, NULL, 31},
|
||||
{NULL, 0, NULL, 0},
|
||||
};
|
||||
|
||||
|
@ -304,6 +308,17 @@ int main(int argc, char **argv) {
|
|||
case 29:
|
||||
tool_ctx.action |= ACTION_EXTRACTINI1;
|
||||
break;
|
||||
case 30:
|
||||
if (nca_ctx.tool_ctx->base_file != NULL) {
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
nca_ctx.tool_ctx->base_file_type = BASEFILE_FAKE;
|
||||
nca_ctx.tool_ctx->base_file++; /* Guarantees base_file != NULL. I'm so sorry. */
|
||||
break;
|
||||
case 31:
|
||||
tool_ctx.action |= ACTION_ONLYUPDATEDROMFS;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
|
@ -371,6 +386,10 @@ int main(int argc, char **argv) {
|
|||
nca_process(&nca_ctx);
|
||||
nca_free_section_contexts(&nca_ctx);
|
||||
|
||||
if (nca_ctx.tool_ctx->base_file_type == BASEFILE_FAKE) {
|
||||
nca_ctx.tool_ctx->base_file = NULL;
|
||||
}
|
||||
|
||||
if (nca_ctx.tool_ctx->base_file != NULL) {
|
||||
fclose(nca_ctx.tool_ctx->base_file);
|
||||
if (nca_ctx.tool_ctx->base_file_type == BASEFILE_NCA) {
|
||||
|
|
79
nca.c
79
nca.c
|
@ -215,7 +215,7 @@ size_t nca_section_fread(nca_section_ctx_t *ctx, void *buffer, size_t count) {
|
|||
if ((read = fread(buffer, 1, count, ctx->tool_ctx->base_file)) != count) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
} else if (ctx->tool_ctx->base_file_type == BASEFILE_NCA) {
|
||||
nca_ctx_t *base_ctx = ctx->tool_ctx->base_nca_ctx;
|
||||
unsigned int romfs_section_num;
|
||||
for (romfs_section_num = 0; romfs_section_num < 4; romfs_section_num++) {
|
||||
|
@ -228,6 +228,13 @@ size_t nca_section_fread(nca_section_ctx_t *ctx, void *buffer, size_t count) {
|
|||
fprintf(stderr, "Failed to read from Base NCA RomFS!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (ctx->tool_ctx->base_file_type == BASEFILE_FAKE) {
|
||||
/* Fake reads. */
|
||||
memset(buffer, 0xCC, count);
|
||||
read = count;
|
||||
} else {
|
||||
fprintf(stderr, "Unknown Base File Type!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1190,7 +1197,28 @@ void nca_save_pfs0_section(nca_section_ctx_t *ctx) {
|
|||
}
|
||||
|
||||
/* RomFS functions... */
|
||||
void nca_visit_romfs_file(nca_section_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) {
|
||||
int nca_is_romfs_file_updated(nca_section_ctx_t *ctx, uint64_t file_offset, uint64_t file_size) {
|
||||
/* All files in a Base RomFS are "updated". */
|
||||
if (ctx->type == ROMFS) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bktr_relocation_entry_t *first_reloc = bktr_get_relocation(ctx->bktr_ctx.relocation_block, file_offset);
|
||||
bktr_relocation_entry_t *last_reloc = first_reloc;
|
||||
while (last_reloc->virt_offset < file_offset + file_size) {
|
||||
last_reloc++;
|
||||
}
|
||||
|
||||
for (bktr_relocation_entry_t *cur_reloc = first_reloc; cur_reloc < last_reloc; cur_reloc++) {
|
||||
if (cur_reloc->is_patch) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nca_visit_romfs_file(nca_section_ctx_t *ctx, uint32_t file_offset, filepath_t *dir_path) {
|
||||
romfs_fentry_t *entry;
|
||||
if (ctx->type == ROMFS) {
|
||||
entry = romfs_get_fentry(ctx->romfs_ctx.files, file_offset);
|
||||
|
@ -1207,29 +1235,37 @@ void nca_visit_romfs_file(nca_section_ctx_t *ctx, uint32_t file_offset, filepath
|
|||
if (entry->name_size) {
|
||||
filepath_append_n(cur_path, entry->name_size, "%s", entry->name);
|
||||
}
|
||||
|
||||
int found_file = 1;
|
||||
|
||||
/* If we're extracting... */
|
||||
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) {
|
||||
printf("Saving %s...\n", cur_path->char_path);
|
||||
uint64_t phys_offset;
|
||||
if (ctx->type == ROMFS) {
|
||||
phys_offset = ctx->romfs_ctx.romfs_offset + ctx->romfs_ctx.header.data_offset + entry->offset;
|
||||
} else {
|
||||
phys_offset = ctx->bktr_ctx.romfs_offset + ctx->bktr_ctx.header.data_offset + entry->offset;
|
||||
}
|
||||
nca_save_section_file(ctx, phys_offset, entry->size, cur_path);
|
||||
uint64_t phys_offset;
|
||||
if (ctx->type == ROMFS) {
|
||||
phys_offset = ctx->romfs_ctx.romfs_offset + ctx->romfs_ctx.header.data_offset + entry->offset;
|
||||
} else {
|
||||
printf("rom:%s\n", cur_path->char_path);
|
||||
phys_offset = ctx->bktr_ctx.romfs_offset + ctx->bktr_ctx.header.data_offset + entry->offset;
|
||||
}
|
||||
if ((ctx->tool_ctx->action & ACTION_ONLYUPDATEDROMFS) == 0 || nca_is_romfs_file_updated(ctx, phys_offset, entry->size)) {
|
||||
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) {
|
||||
printf("Saving %s...\n", cur_path->char_path);
|
||||
nca_save_section_file(ctx, phys_offset, entry->size, cur_path);
|
||||
} else {
|
||||
printf("rom:%s\n", cur_path->char_path);
|
||||
}
|
||||
} else {
|
||||
found_file = 0;
|
||||
}
|
||||
|
||||
free(cur_path);
|
||||
|
||||
if (entry->sibling != ROMFS_ENTRY_EMPTY) {
|
||||
nca_visit_romfs_file(ctx, entry->sibling, dir_path);
|
||||
return found_file | nca_visit_romfs_file(ctx, entry->sibling, dir_path);
|
||||
}
|
||||
|
||||
return found_file;
|
||||
}
|
||||
|
||||
void nca_visit_romfs_dir(nca_section_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) {
|
||||
int nca_visit_romfs_dir(nca_section_ctx_t *ctx, uint32_t dir_offset, filepath_t *parent_path) {
|
||||
romfs_direntry_t *entry;
|
||||
if (ctx->type == ROMFS) {
|
||||
entry = romfs_get_direntry(ctx->romfs_ctx.directories, dir_offset);
|
||||
|
@ -1251,18 +1287,27 @@ void nca_visit_romfs_dir(nca_section_ctx_t *ctx, uint32_t dir_offset, filepath_t
|
|||
if ((ctx->tool_ctx->action & ACTION_LISTROMFS) == 0) {
|
||||
os_makedir(cur_path->os_path);
|
||||
}
|
||||
|
||||
int any_files = 0;
|
||||
|
||||
if (entry->file != ROMFS_ENTRY_EMPTY) {
|
||||
nca_visit_romfs_file(ctx, entry->file, cur_path);
|
||||
any_files |= nca_visit_romfs_file(ctx, entry->file, cur_path);
|
||||
}
|
||||
if (entry->child != ROMFS_ENTRY_EMPTY) {
|
||||
nca_visit_romfs_dir(ctx, entry->child, cur_path);
|
||||
any_files |= nca_visit_romfs_dir(ctx, entry->child, cur_path);
|
||||
}
|
||||
|
||||
if (any_files == 0 && ctx->type == BKTR && (ctx->tool_ctx->action & ACTION_ONLYUPDATEDROMFS)) {
|
||||
os_rmdir(cur_path->os_path);
|
||||
}
|
||||
|
||||
|
||||
if (entry->sibling != ROMFS_ENTRY_EMPTY) {
|
||||
nca_visit_romfs_dir(ctx, entry->sibling, parent_path);
|
||||
}
|
||||
|
||||
|
||||
free(cur_path);
|
||||
return any_files;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
BASEFILE_ROMFS,
|
||||
BASEFILE_NCA
|
||||
BASEFILE_NCA,
|
||||
BASEFILE_FAKE
|
||||
} hactool_basefile_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -88,6 +89,7 @@ enum hactool_file_type
|
|||
#define ACTION_LISTROMFS (1<<4)
|
||||
#define ACTION_DEV (1<<5)
|
||||
#define ACTION_EXTRACTINI1 (1<<6)
|
||||
#define ACTION_ONLYUPDATEDROMFS (1<<7)
|
||||
|
||||
struct nca_ctx; /* This will get re-defined by nca.h. */
|
||||
|
||||
|
|
Loading…
Reference in a new issue