mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-02 16:59:03 +00:00
[ctrtool] Implemented --listromfs & --romfsdir to work directly with NCCH. Also implemented plainrgn extraction.
This commit is contained in:
+47
-13
@@ -31,11 +31,47 @@ void ivfc_set_file(ivfc_context* ctx, FILE* file)
|
||||
ctx->file = file;
|
||||
}
|
||||
|
||||
void ivfc_set_encrypted(ivfc_context* ctx, u32 encrypted)
|
||||
{
|
||||
ctx->encrypted = encrypted;
|
||||
}
|
||||
|
||||
void ivfc_set_key(ivfc_context* ctx, u8 key[16])
|
||||
{
|
||||
memcpy(ctx->key, key, 16);
|
||||
}
|
||||
|
||||
void ivfc_set_counter(ivfc_context* ctx, u8 counter[16])
|
||||
{
|
||||
memcpy(ctx->counter, counter, 16);
|
||||
}
|
||||
|
||||
void ivfc_fseek(ivfc_context* ctx, u64 offset)
|
||||
{
|
||||
u64 data_pos = offset - ctx->offset;
|
||||
fseeko64(ctx->file, offset, SEEK_SET);
|
||||
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
|
||||
ctr_add_counter(&ctx->aes, data_pos / 0x10);
|
||||
}
|
||||
|
||||
size_t ivfc_fread(ivfc_context* ctx, void* buffer, size_t size, size_t count)
|
||||
{
|
||||
size_t read;
|
||||
if ((read = fread(buffer, size, count, ctx->file)) != count) {
|
||||
//printf("ivfc_fread() fail\n");
|
||||
return read;
|
||||
}
|
||||
if (ctx->encrypted) {
|
||||
ctr_crypt_counter(&ctx->aes, buffer, buffer, size*read);
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
|
||||
void ivfc_process(ivfc_context* ctx, u32 actions)
|
||||
{
|
||||
fseeko64(ctx->file, ctx->offset, SEEK_SET);
|
||||
fread(&ctx->header, 1, sizeof(ivfc_header), ctx->file);
|
||||
ivfc_fseek(ctx, ctx->offset);
|
||||
ivfc_fread(ctx, &ctx->header, 1, sizeof(ivfc_header));
|
||||
|
||||
if (getle32(ctx->header.magic) != MAGIC_IVFC)
|
||||
{
|
||||
@@ -45,25 +81,23 @@ void ivfc_process(ivfc_context* ctx, u32 actions)
|
||||
|
||||
if (getle32(ctx->header.id) == 0x10000)
|
||||
{
|
||||
fread(&ctx->romfsheader, 1, sizeof(ivfc_header_romfs), ctx->file);
|
||||
|
||||
ctx->levelcount = 3;
|
||||
|
||||
ctx->level[2].hashblocksize = 1 << getle32(ctx->romfsheader.level3.blocksize);
|
||||
ctx->level[1].hashblocksize = 1 << getle32(ctx->romfsheader.level2.blocksize);
|
||||
ctx->level[0].hashblocksize = 1 << getle32(ctx->romfsheader.level1.blocksize);
|
||||
ctx->level[2].hashblocksize = 1 << getle32(ctx->header.level3.blocksize);
|
||||
ctx->level[1].hashblocksize = 1 << getle32(ctx->header.level2.blocksize);
|
||||
ctx->level[0].hashblocksize = 1 << getle32(ctx->header.level1.blocksize);
|
||||
|
||||
ctx->bodyoffset = align64(IVFC_HEADER_SIZE + getle32(ctx->romfsheader.masterhashsize), ctx->level[2].hashblocksize);
|
||||
ctx->bodysize = getle64(ctx->romfsheader.level3.hashdatasize);
|
||||
ctx->bodyoffset = align64(IVFC_HEADER_SIZE + getle32(ctx->header.masterhashsize), ctx->level[2].hashblocksize);
|
||||
ctx->bodysize = getle64(ctx->header.level3.hashdatasize);
|
||||
|
||||
ctx->level[2].dataoffset = ctx->bodyoffset;
|
||||
ctx->level[2].datasize = align64(ctx->bodysize, ctx->level[2].hashblocksize);
|
||||
|
||||
ctx->level[0].dataoffset = ctx->level[2].dataoffset + ctx->level[2].datasize;
|
||||
ctx->level[0].datasize = align64(getle64(ctx->romfsheader.level1.hashdatasize), ctx->level[0].hashblocksize);
|
||||
ctx->level[0].datasize = align64(getle64(ctx->header.level1.hashdatasize), ctx->level[0].hashblocksize);
|
||||
|
||||
ctx->level[1].dataoffset = ctx->level[0].dataoffset + ctx->level[0].datasize;
|
||||
ctx->level[1].datasize = align64(getle64(ctx->romfsheader.level2.hashdatasize), ctx->level[1].hashblocksize);
|
||||
ctx->level[1].datasize = align64(getle64(ctx->header.level2.hashdatasize), ctx->level[1].hashblocksize);
|
||||
|
||||
ctx->level[0].hashoffset = IVFC_HEADER_SIZE;
|
||||
ctx->level[1].hashoffset = ctx->level[0].dataoffset;
|
||||
@@ -125,8 +159,8 @@ void ivfc_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer)
|
||||
return;
|
||||
}
|
||||
|
||||
fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
|
||||
if (size != fread(buffer, 1, size, ctx->file))
|
||||
ivfc_fseek(ctx, ctx->offset + offset);
|
||||
if (size != ivfc_fread(ctx, buffer, 1, size))
|
||||
{
|
||||
fprintf(stderr, "Error, IVFC could not read file\n");
|
||||
return;
|
||||
|
||||
+14
-8
@@ -2,18 +2,13 @@
|
||||
#define __IVFC_H__
|
||||
|
||||
#include "types.h"
|
||||
#include "ctr.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define IVFC_HEADER_SIZE 0x60
|
||||
#define IVFC_MAX_LEVEL 4
|
||||
#define IVFC_MAX_BUFFERSIZE 0x4000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 magic[4];
|
||||
u8 id[4];
|
||||
} ivfc_header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 logicaloffset[8];
|
||||
@@ -33,13 +28,15 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 magic[4];
|
||||
u8 id[4];
|
||||
u8 masterhashsize[4];
|
||||
ivfc_levelheader level1;
|
||||
ivfc_levelheader level2;
|
||||
ivfc_levelheader level3;
|
||||
u8 reserved[4];
|
||||
u8 optionalsize[4];
|
||||
} ivfc_header_romfs;
|
||||
} ivfc_header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -47,9 +44,12 @@ typedef struct
|
||||
u64 offset;
|
||||
u64 size;
|
||||
settings* usersettings;
|
||||
u8 counter[16];
|
||||
u8 key[16];
|
||||
ctr_aes_context aes;
|
||||
int encrypted;
|
||||
|
||||
ivfc_header header;
|
||||
ivfc_header_romfs romfsheader;
|
||||
|
||||
u32 levelcount;
|
||||
ivfc_level level[IVFC_MAX_LEVEL];
|
||||
@@ -64,6 +64,12 @@ void ivfc_set_offset(ivfc_context* ctx, u64 offset);
|
||||
void ivfc_set_size(ivfc_context* ctx, u64 size);
|
||||
void ivfc_set_file(ivfc_context* ctx, FILE* file);
|
||||
void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings);
|
||||
void ivfc_set_encrypted(ivfc_context* ctx, u32 encrypted);
|
||||
void ivfc_set_key(ivfc_context* ctx, u8 key[16]);
|
||||
void ivfc_set_counter(ivfc_context* ctx, u8 counter[16]);
|
||||
void ivfc_fseek(ivfc_context* ctx, u64 offset);
|
||||
size_t ivfc_fread(ivfc_context* ctx, void* buffer, size_t size, size_t count);
|
||||
|
||||
void ivfc_verify(ivfc_context* ctx, u32 flags);
|
||||
void ivfc_print(ivfc_context* ctx);
|
||||
|
||||
|
||||
+8
-5
@@ -64,11 +64,14 @@ static void usage(const char *argv0)
|
||||
" --lzssout=file Specify lzss output file\n"
|
||||
"CXI/CCI options:\n"
|
||||
" -n, --ncch=index Specify NCCH partition index.\n"
|
||||
" --exheader=file Specify Extended Header file path.\n"
|
||||
" --logo=file Specify Logo file path.\n"
|
||||
" --plainrgn=file Specify Plain region file path"
|
||||
" --exefs=file Specify ExeFS file path.\n"
|
||||
" --exefsdir=dir Specify ExeFS directory path.\n"
|
||||
" --romfs=file Specify RomFS file path.\n"
|
||||
" --exheader=file Specify Extended Header file path.\n"
|
||||
" --logo=file Specify Logo file path.\n"
|
||||
" --romfsdir=dir Specify RomFS directory path.\n"
|
||||
" --listromfs List files in RomFS.\n"
|
||||
"CIA options:\n"
|
||||
" --certs=file Specify Certificate chain file path.\n"
|
||||
" --tik=file Specify Ticket file path.\n"
|
||||
@@ -83,9 +86,6 @@ static void usage(const char *argv0)
|
||||
"EXEFS options:\n"
|
||||
" --decompresscode Decompress .code section\n"
|
||||
" (only needed when using raw EXEFS file)\n"
|
||||
"ROMFS options:\n"
|
||||
" --romfsdir=dir Specify RomFS directory path.\n"
|
||||
" --listromfs List files in RomFS.\n"
|
||||
"\n",
|
||||
__TIME__, __DATE__, argv0);
|
||||
exit(1);
|
||||
@@ -149,6 +149,7 @@ int main(int argc, char* argv[])
|
||||
{"logo", 1, NULL, 20},
|
||||
{"decompresscode", 0, NULL, 21},
|
||||
{"titlekey", 1, NULL, 22},
|
||||
{"plainrgn", 1, NULL, 23},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
@@ -237,6 +238,7 @@ int main(int argc, char* argv[])
|
||||
case 20: settings_set_logo_path(&ctx.usersettings, optarg); break;
|
||||
case 21: ctx.actions |= DecompressCodeFlag; break;
|
||||
case 22: keyset_parse_titlekey(&tmpkeys, optarg, strlen(optarg)); break;
|
||||
case 23: settings_set_plainrgn_path(&ctx.usersettings, optarg); break;
|
||||
|
||||
default:
|
||||
usage(argv[0]);
|
||||
@@ -452,6 +454,7 @@ int main(int argc, char* argv[])
|
||||
romfs_set_file(&romfsctx, ctx.infile);
|
||||
romfs_set_size(&romfsctx, ctx.infilesize);
|
||||
romfs_set_usersettings(&romfsctx, &ctx.usersettings);
|
||||
romfs_set_encrypted(&romfsctx, 0);
|
||||
romfs_process(&romfsctx, ctx.actions);
|
||||
|
||||
break;
|
||||
|
||||
+37
-1
@@ -116,6 +116,13 @@ int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags)
|
||||
}
|
||||
break;
|
||||
|
||||
case NCCHTYPE_PLAINRGN:
|
||||
{
|
||||
offset = ncch_get_plainrgn_offset(ctx);
|
||||
size = ncch_get_plainrgn_size(ctx);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
fprintf(stderr, "Error invalid NCCH type\n");
|
||||
@@ -181,6 +188,7 @@ void ncch_save(ncch_context* ctx, u32 type, u32 flags)
|
||||
case NCCHTYPE_ROMFS: path = settings_get_romfs_path(ctx->usersettings); break;
|
||||
case NCCHTYPE_EXHEADER: path = settings_get_exheader_path(ctx->usersettings); break;
|
||||
case NCCHTYPE_LOGO: path = settings_get_logo_path(ctx->usersettings); break;
|
||||
case NCCHTYPE_PLAINRGN: path = settings_get_plainrgn_path(ctx->usersettings); break;
|
||||
}
|
||||
|
||||
if (path == 0 || path->valid == 0)
|
||||
@@ -199,13 +207,14 @@ void ncch_save(ncch_context* ctx, u32 type, u32 flags)
|
||||
case NCCHTYPE_ROMFS: fprintf(stdout, "Saving RomFS...\n"); break;
|
||||
case NCCHTYPE_EXHEADER: fprintf(stdout, "Saving Extended Header...\n"); break;
|
||||
case NCCHTYPE_LOGO: fprintf(stdout, "Saving Logo...\n"); break;
|
||||
case NCCHTYPE_PLAINRGN: fprintf(stdout, "Saving Plain Region...\n"); break;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
u32 read_len;
|
||||
|
||||
if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &read_len, type == NCCHTYPE_LOGO))
|
||||
if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &read_len, type == NCCHTYPE_LOGO || type == NCCHTYPE_PLAINRGN))
|
||||
goto clean;
|
||||
|
||||
if (read_len == 0)
|
||||
@@ -304,6 +313,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
|
||||
{
|
||||
u8 exheadercounter[16];
|
||||
u8 exefscounter[16];
|
||||
u8 romfscounter[16];
|
||||
int result = 1;
|
||||
|
||||
|
||||
@@ -320,6 +330,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
|
||||
|
||||
ncch_get_counter(ctx, exheadercounter, NCCHTYPE_EXHEADER);
|
||||
ncch_get_counter(ctx, exefscounter, NCCHTYPE_EXEFS);
|
||||
ncch_get_counter(ctx, romfscounter, NCCHTYPE_ROMFS);
|
||||
|
||||
|
||||
exheader_set_file(&ctx->exheader, ctx->file);
|
||||
@@ -342,6 +353,14 @@ void ncch_process(ncch_context* ctx, u32 actions)
|
||||
exefs_set_key(&ctx->exefs, ctx->key);
|
||||
exefs_set_encrypted(&ctx->exefs, ctx->encrypted);
|
||||
|
||||
romfs_set_file(&ctx->romfs, ctx->file);
|
||||
romfs_set_offset(&ctx->romfs, ncch_get_romfs_offset(ctx));
|
||||
romfs_set_size(&ctx->romfs, ncch_get_romfs_size(ctx));
|
||||
romfs_set_usersettings(&ctx->romfs, ctx->usersettings);
|
||||
romfs_set_counter(&ctx->romfs, romfscounter);
|
||||
romfs_set_key(&ctx->romfs, ctx->key);
|
||||
romfs_set_encrypted(&ctx->romfs, ctx->encrypted);
|
||||
|
||||
exheader_read(&ctx->exheader, actions);
|
||||
|
||||
|
||||
@@ -357,6 +376,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
|
||||
ncch_save(ctx, NCCHTYPE_ROMFS, actions);
|
||||
ncch_save(ctx, NCCHTYPE_EXHEADER, actions);
|
||||
ncch_save(ctx, NCCHTYPE_LOGO, actions);
|
||||
ncch_save(ctx, NCCHTYPE_PLAINRGN, actions);
|
||||
}
|
||||
|
||||
|
||||
@@ -374,6 +394,11 @@ void ncch_process(ncch_context* ctx, u32 actions)
|
||||
exefs_set_compressedflag(&ctx->exefs, exheader_get_compressedflag(&ctx->exheader));
|
||||
exefs_process(&ctx->exefs, actions);
|
||||
}
|
||||
|
||||
if (result && ncch_get_romfs_size(ctx))
|
||||
{
|
||||
romfs_process(&ctx->romfs, actions);
|
||||
}
|
||||
}
|
||||
|
||||
int ncch_signature_verify(ncch_context* ctx, rsakey2048* key)
|
||||
@@ -425,6 +450,17 @@ u64 ncch_get_logo_size(ncch_context* ctx)
|
||||
return getle32(ctx->header.logosize) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
u64 ncch_get_plainrgn_offset(ncch_context* ctx)
|
||||
{
|
||||
return ctx->offset + getle32(ctx->header.plainregionoffset) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
u64 ncch_get_plainrgn_size(ncch_context* ctx)
|
||||
{
|
||||
return getle32(ctx->header.plainregionsize) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
|
||||
u64 ncch_get_mediaunit_size(ncch_context* ctx)
|
||||
{
|
||||
unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "filepath.h"
|
||||
#include "ctr.h"
|
||||
#include "exefs.h"
|
||||
#include "romfs.h"
|
||||
#include "exheader.h"
|
||||
#include "settings.h"
|
||||
|
||||
@@ -16,6 +17,7 @@ typedef enum
|
||||
NCCHTYPE_EXEFS = 2,
|
||||
NCCHTYPE_ROMFS = 3,
|
||||
NCCHTYPE_LOGO = 4,
|
||||
NCCHTYPE_PLAINRGN = 5,
|
||||
} ctr_ncchtypes;
|
||||
|
||||
typedef struct
|
||||
@@ -63,6 +65,7 @@ typedef struct
|
||||
ctr_ncchheader header;
|
||||
ctr_aes_context aes;
|
||||
exefs_context exefs;
|
||||
romfs_context romfs;
|
||||
exheader_context exheader;
|
||||
int exefshashcheck;
|
||||
int romfshashcheck;
|
||||
@@ -87,6 +90,8 @@ u64 ncch_get_exheader_offset(ncch_context* ctx);
|
||||
u64 ncch_get_exheader_size(ncch_context* ctx);
|
||||
u64 ncch_get_logo_offset(ncch_context* ctx);
|
||||
u64 ncch_get_logo_size(ncch_context* ctx);
|
||||
u64 ncch_get_plainrgn_offset(ncch_context* ctx);
|
||||
u64 ncch_get_plainrgn_size(ncch_context* ctx);
|
||||
void ncch_print(ncch_context* ctx);
|
||||
int ncch_signature_verify(ncch_context* ctx, rsakey2048* key);
|
||||
void ncch_verify(ncch_context* ctx, u32 flags);
|
||||
|
||||
+55
-19
@@ -30,7 +30,41 @@ void romfs_set_usersettings(romfs_context* ctx, settings* usersettings)
|
||||
ctx->usersettings = usersettings;
|
||||
}
|
||||
|
||||
void romfs_set_encrypted(romfs_context* ctx, u32 encrypted)
|
||||
{
|
||||
ctx->encrypted = encrypted;
|
||||
}
|
||||
|
||||
void romfs_set_key(romfs_context* ctx, u8 key[16])
|
||||
{
|
||||
memcpy(ctx->key, key, 16);
|
||||
}
|
||||
|
||||
void romfs_set_counter(romfs_context* ctx, u8 counter[16])
|
||||
{
|
||||
memcpy(ctx->counter, counter, 16);
|
||||
}
|
||||
|
||||
void romfs_fseek(romfs_context* ctx, u64 offset)
|
||||
{
|
||||
u64 data_pos = offset - ctx->offset;
|
||||
fseeko64(ctx->file, offset, SEEK_SET);
|
||||
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
|
||||
ctr_add_counter(&ctx->aes, data_pos / 0x10);
|
||||
}
|
||||
|
||||
size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count)
|
||||
{
|
||||
size_t read;
|
||||
if ((read = fread(buffer, size, count, ctx->file)) != count) {
|
||||
//printf("romfs_fread() fail\n");
|
||||
return read;
|
||||
}
|
||||
if (ctx->encrypted) {
|
||||
ctr_crypt_counter(&ctx->aes, buffer, buffer, size*read);
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
void romfs_process(romfs_context* ctx, u32 actions)
|
||||
{
|
||||
@@ -39,15 +73,17 @@ void romfs_process(romfs_context* ctx, u32 actions)
|
||||
u32 fileblockoffset = 0;
|
||||
u32 fileblocksize = 0;
|
||||
|
||||
|
||||
ivfc_set_offset(&ctx->ivfc, ctx->offset);
|
||||
ivfc_set_size(&ctx->ivfc, ctx->size);
|
||||
ivfc_set_file(&ctx->ivfc, ctx->file);
|
||||
ivfc_set_usersettings(&ctx->ivfc, ctx->usersettings);
|
||||
ivfc_set_counter(&ctx->ivfc, ctx->counter);
|
||||
ivfc_set_key(&ctx->ivfc, ctx->key);
|
||||
ivfc_set_encrypted(&ctx->ivfc, ctx->encrypted);
|
||||
ivfc_process(&ctx->ivfc, actions);
|
||||
|
||||
fseeko64(ctx->file, ctx->offset, SEEK_SET);
|
||||
fread(&ctx->header, 1, sizeof(romfs_header), ctx->file);
|
||||
romfs_fseek(ctx, ctx->offset);
|
||||
romfs_fread(ctx, &ctx->header, 1, sizeof(romfs_header));
|
||||
|
||||
if (getle32(ctx->header.magic) != MAGIC_IVFC)
|
||||
{
|
||||
@@ -57,8 +93,8 @@ void romfs_process(romfs_context* ctx, u32 actions)
|
||||
|
||||
ctx->infoblockoffset = ctx->offset + 0x1000;
|
||||
|
||||
fseeko64(ctx->file, ctx->infoblockoffset, SEEK_SET);
|
||||
fread(&ctx->infoheader, 1, sizeof(romfs_infoheader), ctx->file);
|
||||
romfs_fseek(ctx, ctx->infoblockoffset);
|
||||
romfs_fread(ctx, &ctx->infoheader, 1, sizeof(romfs_infoheader));
|
||||
|
||||
if (getle32(ctx->infoheader.headersize) != sizeof(romfs_infoheader))
|
||||
{
|
||||
@@ -71,25 +107,25 @@ void romfs_process(romfs_context* ctx, u32 actions)
|
||||
fileblockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.section[3].offset);
|
||||
fileblocksize = getle32(ctx->infoheader.section[3].size);
|
||||
|
||||
u32 hdrsize = getle32(ctx->infoheader.dataoffset);
|
||||
u8 *block = malloc(hdrsize);
|
||||
romfs_fseek(ctx, ctx->infoblockoffset);
|
||||
romfs_fread(ctx, block, hdrsize, 1);
|
||||
|
||||
ctx->dirblock = malloc(dirblocksize);
|
||||
ctx->dirblocksize = dirblocksize;
|
||||
if(ctx->dirblock)
|
||||
memcpy(ctx->dirblock, block + getle32(ctx->infoheader.section[1].offset), dirblocksize);
|
||||
|
||||
ctx->fileblock = malloc(fileblocksize);
|
||||
ctx->fileblocksize = fileblocksize;
|
||||
if (ctx->fileblock)
|
||||
memcpy(ctx->fileblock, block + getle32(ctx->infoheader.section[3].offset), fileblocksize);
|
||||
|
||||
free(block);
|
||||
|
||||
ctx->datablockoffset = ctx->infoblockoffset + getle32(ctx->infoheader.dataoffset);
|
||||
|
||||
if (ctx->dirblock)
|
||||
{
|
||||
fseeko64(ctx->file, dirblockoffset, SEEK_SET);
|
||||
fread(ctx->dirblock, 1, dirblocksize, ctx->file);
|
||||
}
|
||||
|
||||
if (ctx->fileblock)
|
||||
{
|
||||
fseeko64(ctx->file, fileblockoffset, SEEK_SET);
|
||||
fread(ctx->fileblock, 1, fileblocksize, ctx->file);
|
||||
}
|
||||
|
||||
if (actions & InfoFlag)
|
||||
romfs_print(ctx);
|
||||
|
||||
@@ -315,7 +351,7 @@ void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, const osch
|
||||
|
||||
offset += ctx->datablockoffset;
|
||||
|
||||
fseeko64(ctx->file, offset, SEEK_SET);
|
||||
romfs_fseek(ctx, offset);
|
||||
outfile = os_fopen(path, OS_MODE_WRITE);
|
||||
if (outfile == NULL)
|
||||
{
|
||||
@@ -329,7 +365,7 @@ void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, const osch
|
||||
if (max > size)
|
||||
max = size;
|
||||
|
||||
if (max != fread(buffer, 1, max, ctx->file))
|
||||
if (max != romfs_fread(ctx, buffer, 1, max))
|
||||
{
|
||||
fprintf(stderr, "Error reading file\n");
|
||||
goto clean;
|
||||
|
||||
+9
-1
@@ -57,6 +57,8 @@ typedef struct
|
||||
FILE* file;
|
||||
oschar_t* extractdir;
|
||||
settings* usersettings;
|
||||
u8 counter[16];
|
||||
u8 key[16];
|
||||
u64 offset;
|
||||
u64 size;
|
||||
romfs_header header;
|
||||
@@ -70,6 +72,8 @@ typedef struct
|
||||
romfs_direntry direntry;
|
||||
romfs_fileentry fileentry;
|
||||
ivfc_context ivfc;
|
||||
ctr_aes_context aes;
|
||||
int encrypted;
|
||||
} romfs_context;
|
||||
|
||||
void romfs_init(romfs_context* ctx);
|
||||
@@ -77,7 +81,11 @@ void romfs_set_file(romfs_context* ctx, FILE* file);
|
||||
void romfs_set_offset(romfs_context* ctx, u64 offset);
|
||||
void romfs_set_size(romfs_context* ctx, u64 size);
|
||||
void romfs_set_usersettings(romfs_context* ctx, settings* usersettings);
|
||||
void romfs_test(romfs_context* ctx);
|
||||
void romfs_set_encrypted(romfs_context* ctx, u32 encrypted);
|
||||
void romfs_set_key(romfs_context* ctx, u8 key[16]);
|
||||
void romfs_set_counter(romfs_context* ctx, u8 counter[16]);
|
||||
void romfs_fseek(romfs_context* ctx, u64 offset);
|
||||
size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count);
|
||||
int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer);
|
||||
int romfs_dirblock_readentry(romfs_context* ctx, u32 diroffset, romfs_direntry* entry);
|
||||
int romfs_fileblock_read(romfs_context* ctx, u32 fileoffset, u32 filesize, void* buffer);
|
||||
|
||||
@@ -120,6 +120,14 @@ filepath* settings_get_content_path(settings* usersettings)
|
||||
return 0;
|
||||
}
|
||||
|
||||
filepath* settings_get_plainrgn_path(settings* usersettings)
|
||||
{
|
||||
if (usersettings)
|
||||
return &usersettings->plainrgnpath;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int settings_get_mediaunit_size(settings* usersettings)
|
||||
{
|
||||
if (usersettings)
|
||||
@@ -255,6 +263,11 @@ void settings_set_romfs_dir_path(settings* usersettings, const char* path)
|
||||
filepath_set(&usersettings->romfsdirpath, path);
|
||||
}
|
||||
|
||||
void settings_set_plainrgn_path(settings* usersettings, const char* path)
|
||||
{
|
||||
filepath_set(&usersettings->plainrgnpath, path);
|
||||
}
|
||||
|
||||
void settings_set_mediaunit_size(settings* usersettings, unsigned int size)
|
||||
{
|
||||
usersettings->mediaunitsize = size;
|
||||
|
||||
@@ -15,6 +15,7 @@ typedef struct
|
||||
filepath romfsdirpath;
|
||||
filepath exheaderpath;
|
||||
filepath logopath;
|
||||
filepath plainrgnpath;
|
||||
filepath certspath;
|
||||
filepath contentpath;
|
||||
filepath tikpath;
|
||||
@@ -43,6 +44,7 @@ filepath* settings_get_exefs_dir_path(settings* usersettings);
|
||||
filepath* settings_get_romfs_dir_path(settings* usersettings);
|
||||
filepath* settings_get_firm_dir_path(settings* usersettings);
|
||||
filepath* settings_get_wav_path(settings* usersettings);
|
||||
filepath* settings_get_plainrgn_path(settings* usersettings);
|
||||
unsigned int settings_get_mediaunit_size(settings* usersettings);
|
||||
unsigned char* settings_get_ncch_key(settings* usersettings);
|
||||
unsigned char* settings_get_ncch_fixedsystemkey(settings* usersettings);
|
||||
@@ -66,6 +68,7 @@ void settings_set_exefs_dir_path(settings* usersettings, const char* path);
|
||||
void settings_set_romfs_dir_path(settings* usersettings, const char* path);
|
||||
void settings_set_firm_dir_path(settings* usersettings, const char* path);
|
||||
void settings_set_wav_path(settings* usersettings, const char* path);
|
||||
void settings_set_plainrgn_path(settings* usersettings, const char* path);
|
||||
void settings_set_mediaunit_size(settings* usersettings, unsigned int size);
|
||||
void settings_set_ignore_programid(settings* usersettings, int enable);
|
||||
void settings_set_list_romfs_files(settings* usersettings, int enable);
|
||||
|
||||
@@ -84,6 +84,43 @@ void putle32(u8* p, u32 n)
|
||||
p[3] = n>>24;
|
||||
}
|
||||
|
||||
void putle64(u8* p, u64 n)
|
||||
{
|
||||
p[0] = n;
|
||||
p[1] = n >> 8;
|
||||
p[2] = n >> 16;
|
||||
p[3] = n >> 24;
|
||||
p[4] = n >> 32;
|
||||
p[5] = n >> 40;
|
||||
p[6] = n >> 48;
|
||||
p[7] = n >> 56;
|
||||
}
|
||||
|
||||
void putbe16(u8* p, u16 n)
|
||||
{
|
||||
p[1] = n;
|
||||
p[0] = n >> 8;
|
||||
}
|
||||
|
||||
void putbe32(u8* p, u32 n)
|
||||
{
|
||||
p[3] = n;
|
||||
p[2] = n >> 8;
|
||||
p[1] = n >> 16;
|
||||
p[0] = n >> 24;
|
||||
}
|
||||
|
||||
void putbe64(u8* p, u64 n)
|
||||
{
|
||||
p[7] = n;
|
||||
p[6] = n >> 8;
|
||||
p[5] = n >> 16;
|
||||
p[4] = n >> 24;
|
||||
p[3] = n >> 32;
|
||||
p[2] = n >> 40;
|
||||
p[1] = n >> 48;
|
||||
p[0] = n >> 56;
|
||||
}
|
||||
|
||||
void readkeyfile(u8* key, const char* keyfname)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,10 @@ u32 getbe32(const u8* p);
|
||||
u32 getbe16(const u8* p);
|
||||
void putle16(u8* p, u16 n);
|
||||
void putle32(u8* p, u32 n);
|
||||
void putle64(u8* p, u64 n);
|
||||
void putbe16(u8* p, u16 n);
|
||||
void putbe32(u8* p, u32 n);
|
||||
void putbe64(u8* p, u64 n);
|
||||
|
||||
void readkeyfile(u8* key, const char* keyfname);
|
||||
void memdump(FILE* fout, const char* prefix, const u8* data, u32 size);
|
||||
|
||||
Reference in New Issue
Block a user