diff --git a/ctrtool/ctrtool.vcxproj b/ctrtool/ctrtool.vcxproj
new file mode 100644
index 0000000..75b7288
--- /dev/null
+++ b/ctrtool/ctrtool.vcxproj
@@ -0,0 +1,159 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {96F5CA15-30DA-4DF5-9DFF-523D58D38001}
+ ctrtooltje
+ Win32Proj
+
+
+
+ Application
+ v110
+ Unicode
+ true
+
+
+ Application
+ v110
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>11.0.50727.1
+
+
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ true
+
+
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+ false
+
+
+
+ Disabled
+ windows;.;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+
+ Level3
+ EditAndContinue
+ 4996;%(DisableSpecificWarnings)
+ false
+
+
+ true
+ Console
+ MachineX86
+
+
+
+
+ MaxSpeed
+ true
+ windows;.;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ true
+
+ Level3
+ ProgramDatabase
+
+
+ c:\dev\tools\bin\ctrtool.exe
+ true
+ Console
+ true
+ true
+ MachineX86
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ctrtool/ctrtool.vcxproj.filters b/ctrtool/ctrtool.vcxproj.filters
new file mode 100644
index 0000000..c51e94e
--- /dev/null
+++ b/ctrtool/ctrtool.vcxproj.filters
@@ -0,0 +1,207 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {dfec7c2d-ac92-481f-a1eb-732b0669b7d1}
+
+
+ {dd509a5e-b804-4879-b0b7-876718c9621a}
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {d16b9918-7159-4a81-a0b7-521c2b2f8a30}
+
+
+ {492dc50f-e790-426b-b991-86306ad69fd4}
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files\polarssl
+
+
+ Source Files\polarssl
+
+
+ Source Files\polarssl
+
+
+ Source Files\polarssl
+
+
+ Source Files\tinyxml
+
+
+ Source Files\tinyxml
+
+
+ Source Files\tinyxml
+
+
+ Source Files\tinyxml
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files\polarssl
+
+
+ Header Files\polarssl
+
+
+ Header Files\polarssl
+
+
+ Header Files\polarssl
+
+
+ Header Files\polarssl
+
+
+ Header Files\polarssl
+
+
+ Header Files\tinyxml
+
+
+ Header Files\tinyxml
+
+
+
\ No newline at end of file
diff --git a/ctrtool/exheader.c b/ctrtool/exheader.c
index 1fe0347..d96c571 100644
--- a/ctrtool/exheader.c
+++ b/ctrtool/exheader.c
@@ -299,6 +299,114 @@ void exheader_print_arm11kernelcapabilities(exheader_context* ctx)
}
}
+void exheader_print_arm11accessinfo(exheader_context* ctx)
+{
+ u32 accessinfo = getle32(ctx->header.arm11systemlocalcaps.storageinfo.accessinfo);
+ if((accessinfo & (1 << 0) )== (1 << 0))
+ fprintf(stdout, " > Category System Application\n");
+ if((accessinfo & (1 << 1) )== (1 << 1))
+ fprintf(stdout, " > Category Hardware Check\n");
+ if((accessinfo & (1 << 2) )== (1 << 2))
+ fprintf(stdout, " > Category File System Tool\n");
+ if((accessinfo & (1 << 3) )== (1 << 3))
+ fprintf(stdout, " > Debug\n");
+ if((accessinfo & (1 << 4) )== (1 << 4))
+ fprintf(stdout, " > TWL Card Backup\n");
+ if((accessinfo & (1 << 5) )== (1 << 5))
+ fprintf(stdout, " > TWL Nand Data\n");
+ if((accessinfo & (1 << 6) )== (1 << 6))
+ fprintf(stdout, " > BOSS\n");
+ if((accessinfo & (1 << 7) )== (1 << 7))
+ fprintf(stdout, " > Direct SDMC\n");
+ if((accessinfo & (1 << 8) )== (1 << 8))
+ fprintf(stdout, " > Core\n");
+ if((accessinfo & (1 << 9) )== (1 << 9))
+ fprintf(stdout, " > CTR NAND RO\n");
+ if((accessinfo & (1 << 10) )== (1 << 10))
+ fprintf(stdout, " > CTR NAND RW\n");
+ if((accessinfo & (1 << 11) )== (1 << 11))
+ fprintf(stdout, " > CTR NAND RO (Write Access)\n");
+ if((accessinfo & (1 << 12) )== (1 << 12))
+ fprintf(stdout, " > Category System Settings\n");
+ if((accessinfo & (1 << 13) )== (1 << 13))
+ fprintf(stdout, " > CARD BOARD\n");
+ if((accessinfo & (1 << 14) )== (1 << 14))
+ fprintf(stdout, " > Export Import IVS\n");
+ if((accessinfo & (1 << 15) )== (1 << 15))
+ fprintf(stdout, " > Direct SDMC (Write Only)\n");
+ if((accessinfo & (1 << 16) )== (1 << 16))
+ fprintf(stdout, " > Switch Cleanup\n");
+ if((accessinfo & (1 << 17) )== (1 << 17))
+ fprintf(stdout, " > Save Data Move\n");
+ if((accessinfo & (1 << 18) )== (1 << 18))
+ fprintf(stdout, " > Shop\n");
+ if((accessinfo & (1 << 19) )== (1 << 19))
+ fprintf(stdout, " > Shell\n");
+ if((accessinfo & (1 << 20) )== (1 << 20))
+ fprintf(stdout, " > Category HomeMenu\n");
+}
+
+void exheader_print_arm11storageinfo(exheader_context* ctx)
+{
+ u32 i;
+ // Storage Info
+ u32 systemsaveID[2];
+ u64 extdataID;
+ u32 otherusersaveID[3];
+ u32 accessiblesaveID[6];
+
+ u8 otherattibutes = ctx->header.arm11systemlocalcaps.storageinfo.otherattributes;
+ u8 accessOtherVariationSavedata = (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) & 0x1000000000000000) == 0x1000000000000000;
+
+ systemsaveID[0] = getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid);
+ systemsaveID[1] = getle32(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid+4);
+
+ extdataID = getle64(ctx->header.arm11systemlocalcaps.storageinfo.extsavedataid);
+
+ for(i = 0; i < 3; i++)
+ {
+ accessiblesaveID[i] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) >> 20*(2-i));
+ otherusersaveID[i] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.accessibleuniqueids) >> 20*(2-i));
+ }
+
+ for(i = 0; i < 3; i++)
+ {
+ accessiblesaveID[i+3] = 0xfffff & (getle64(ctx->header.arm11systemlocalcaps.storageinfo.extsavedataid) >> 20*(2-i));
+ }
+
+ if(otherattibutes & 2)
+ {
+ extdataID = 0;
+ for(i = 0; i < 3; i++)
+ otherusersaveID[i] = 0;
+ }
+ else
+ {
+ for(i = 0; i < 6; i++)
+ accessiblesaveID[i] = 0;
+ }
+
+ fprintf(stdout, "Ext savedata id: 0x%llX\n",extdataID);
+ for(i = 0; i < 2; i++)
+ fprintf(stdout, "System savedata id %d: 0x%08x\n",i+1,systemsaveID[i]);
+ for(i = 0; i < 3; i++)
+ fprintf(stdout, "OtherUserSaveDataId%d: 0x%05x\n",i+1,otherusersaveID[i]);
+ fprintf(stdout, "Accessible Savedata Ids:\n");
+ for(i = 0; i < 6; i++)
+ fprintf(stdout, " > 0x%05x\n",accessiblesaveID[i]);
+
+ fprintf(stdout, "Other Variation Saves: %s\n", accessOtherVariationSavedata ? "Accessible" : "Inaccessible");
+ memdump(stdout, "Access info: ", ctx->header.arm11systemlocalcaps.storageinfo.accessinfo, 7);
+ exheader_print_arm11accessinfo(ctx);
+
+ fprintf(stdout, "Other attributes: %02X", ctx->header.arm11systemlocalcaps.storageinfo.otherattributes);
+ if(otherattibutes & 1)
+ fprintf(stdout," [no use romfs]");
+ if(otherattibutes & 2)
+ fprintf(stdout," [use extended savedata access control]");
+ printf("\n");
+}
+
int exheader_signature_verify(exheader_context* ctx, rsakey2048* key)
{
u8 hash[0x20];
@@ -368,6 +476,8 @@ void exheader_print(exheader_context* ctx)
fprintf(stdout, "Flag: %02X ", codesetinfo->flags.flag);
if (codesetinfo->flags.flag & 1)
fprintf(stdout, "[compressed]");
+ if (codesetinfo->flags.flag & 2)
+ fprintf(stdout, "[sd application]");
fprintf(stdout, "\n");
fprintf(stdout, "Remaster version: %04X\n", getle16(codesetinfo->flags.remasterversion));
@@ -389,7 +499,7 @@ void exheader_print(exheader_context* ctx)
fprintf(stdout, "Dependency: %016llX\n", getle64(ctx->header.deplist.programid[i]));
}
- fprintf(stdout, "Savedata size: 0x%08X\n", getle32(ctx->header.systeminfo.savedatasize));
+ fprintf(stdout, "Savedata size: 0x%016X\n", getle64(ctx->header.systeminfo.savedatasize));
fprintf(stdout, "Jump id: %016llX\n", getle64(ctx->header.systeminfo.jumpid));
fprintf(stdout, "Program id: %016llX %s\n", getle64(ctx->header.arm11systemlocalcaps.programid), exheader_getvalidstring(ctx->validprogramid));
@@ -400,11 +510,7 @@ void exheader_print(exheader_context* ctx)
fprintf(stdout, "Affinity mask: %d %s\n", (ctx->header.arm11systemlocalcaps.flags[6]>>2)&0x3, exheader_getvalidstring(ctx->validaffinitymask));
fprintf(stdout, "Main thread priority: %d %s\n", ctx->header.arm11systemlocalcaps.flags[7], exheader_getvalidstring(ctx->validpriority));
// print resource limit descriptor too? currently mostly zeroes...
- fprintf(stdout, "Ext savedata id: %016llX\n", getle64(ctx->header.arm11systemlocalcaps.storageinfo.extsavedataid));
- fprintf(stdout, "System savedata id: %016llX\n", getle64(ctx->header.arm11systemlocalcaps.storageinfo.systemsavedataid));
- memdump(stdout, "Access info: ", ctx->header.arm11systemlocalcaps.storageinfo.accessinfo, 7);
- fprintf(stdout, "Other attributes: %02X\n", ctx->header.arm11systemlocalcaps.storageinfo.otherattributes);
-
+ exheader_print_arm11storageinfo(ctx);
exheader_print_arm11kernelcapabilities(ctx);
exheader_print_arm9accesscontrol(ctx);
diff --git a/ctrtool/exheader.h b/ctrtool/exheader.h
index 2673918..12fc66d 100644
--- a/ctrtool/exheader.h
+++ b/ctrtool/exheader.h
@@ -39,8 +39,7 @@ typedef struct
typedef struct
{
- u8 savedatasize[4];
- u8 reserved[4];
+ u8 savedatasize[8];
u8 jumpid[8];
u8 reserved2[0x30];
} exheader_systeminfo;
@@ -49,7 +48,7 @@ typedef struct
{
u8 extsavedataid[8];
u8 systemsavedataid[8];
- u8 reserved[8];
+ u8 accessibleuniqueids[8];
u8 accessinfo[7];
u8 otherattributes;
} exheader_storageinfo;
diff --git a/ctrtool/main.c b/ctrtool/main.c
index a432aa3..07ad779 100644
--- a/ctrtool/main.c
+++ b/ctrtool/main.c
@@ -66,6 +66,7 @@ static void usage(const char *argv0)
" --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"
"CIA options:\n"
" --certs=file Specify Certificate chain file path.\n"
" --tik=file Specify Ticket file path.\n"
@@ -140,6 +141,7 @@ int main(int argc, char* argv[])
{"romfsdir", 1, NULL, 17},
{"listromfs", 0, NULL, 18},
{"wavloops", 1, NULL, 19},
+ {"logo", 1, NULL, 20},
{NULL},
};
@@ -223,7 +225,7 @@ int main(int argc, char* argv[])
case 17: settings_set_romfs_dir_path(&ctx.usersettings, optarg); break;
case 18: settings_set_list_romfs_files(&ctx.usersettings, 1); break;
case 19: settings_set_cwav_loopcount(&ctx.usersettings, strtoul(optarg, 0, 0)); break;
-
+ case 20: settings_set_logo_path(&ctx.usersettings, optarg); break;
default:
usage(argv[0]);
diff --git a/ctrtool/ncch.c b/ctrtool/ncch.c
index a36a7d6..1a0f974 100644
--- a/ctrtool/ncch.c
+++ b/ctrtool/ncch.c
@@ -108,6 +108,13 @@ int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags)
}
break;
+ case NCCHTYPE_LOGO:
+ {
+ offset = ncch_get_logo_offset(ctx);
+ size = ncch_get_logo_size(ctx);
+ }
+ break;
+
default:
{
fprintf(stderr, "Error invalid NCCH type\n");
@@ -128,7 +135,7 @@ clean:
return 0;
}
-int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize)
+int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize, u8 nocrypto)
{
u32 max = buffersize;
@@ -145,7 +152,7 @@ int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outs
goto clean;
}
- if (ctx->encrypted)
+ if (ctx->encrypted && !nocrypto)
ctr_crypt_counter(&ctx->aes, buffer, buffer, max);
ctx->extractsize -= max;
@@ -172,6 +179,7 @@ void ncch_save(ncch_context* ctx, u32 type, u32 flags)
case NCCHTYPE_EXEFS: path = settings_get_exefs_path(ctx->usersettings); break;
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;
}
if (path == 0 || path->valid == 0)
@@ -189,13 +197,14 @@ void ncch_save(ncch_context* ctx, u32 type, u32 flags)
case NCCHTYPE_EXEFS: fprintf(stdout, "Saving ExeFS...\n"); break;
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;
}
while(1)
{
u32 max;
- if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &max))
+ if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &max, type == NCCHTYPE_LOGO))
goto clean;
if (max == 0)
@@ -219,17 +228,21 @@ void ncch_verify(ncch_context* ctx, u32 flags)
u32 exefshashregionsize = getle32(ctx->header.exefshashregionsize) * mediaunitsize;
u32 romfshashregionsize = getle32(ctx->header.romfshashregionsize) * mediaunitsize;
u32 exheaderhashregionsize = getle32(ctx->header.extendedheadersize);
+ u32 logohashregionsize = getle32(ctx->header.logosize) * mediaunitsize;
u8* exefshashregion = 0;
u8* romfshashregion = 0;
u8* exheaderhashregion = 0;
+ u8* logohashregion = 0;
+ u8* tmphash = 0;
rsakey2048 ncchrsakey;
- if (exefshashregionsize >= SIZE_128MB || romfshashregionsize >= SIZE_128MB || exheaderhashregionsize >= SIZE_128MB)
+ if (exefshashregionsize >= SIZE_128MB || romfshashregionsize >= SIZE_128MB || exheaderhashregionsize >= SIZE_128MB || logohashregionsize >= SIZE_128MB)
goto clean;
exefshashregion = malloc(exefshashregionsize);
romfshashregion = malloc(romfshashregionsize);
exheaderhashregion = malloc(exheaderhashregionsize);
+ logohashregion = malloc(logohashregionsize);
if (ctx->usersettings)
@@ -247,7 +260,7 @@ void ncch_verify(ncch_context* ctx, u32 flags)
{
if (0 == ncch_extract_prepare(ctx, NCCHTYPE_EXEFS, flags))
goto clean;
- if (0 == ncch_extract_buffer(ctx, exefshashregion, exefshashregionsize, &exefshashregionsize))
+ if (0 == ncch_extract_buffer(ctx, exefshashregion, exefshashregionsize, &exefshashregionsize,0))
goto clean;
ctx->exefshashcheck = ctr_sha_256_verify(exefshashregion, exefshashregionsize, ctx->header.exefssuperblockhash);
}
@@ -255,7 +268,7 @@ void ncch_verify(ncch_context* ctx, u32 flags)
{
if (0 == ncch_extract_prepare(ctx, NCCHTYPE_ROMFS, flags))
goto clean;
- if (0 == ncch_extract_buffer(ctx, romfshashregion, romfshashregionsize, &romfshashregionsize))
+ if (0 == ncch_extract_buffer(ctx, romfshashregion, romfshashregionsize, &romfshashregionsize,0))
goto clean;
ctx->romfshashcheck = ctr_sha_256_verify(romfshashregion, romfshashregionsize, ctx->header.romfssuperblockhash);
}
@@ -263,14 +276,24 @@ void ncch_verify(ncch_context* ctx, u32 flags)
{
if (0 == ncch_extract_prepare(ctx, NCCHTYPE_EXHEADER, flags))
goto clean;
- if (0 == ncch_extract_buffer(ctx, exheaderhashregion, exheaderhashregionsize, &exheaderhashregionsize))
+ if (0 == ncch_extract_buffer(ctx, exheaderhashregion, exheaderhashregionsize, &exheaderhashregionsize,0))
goto clean;
ctx->exheaderhashcheck = ctr_sha_256_verify(exheaderhashregion, exheaderhashregionsize, ctx->header.extendedheaderhash);
}
+ if (logohashregionsize)
+ {
+ if (0 == ncch_extract_prepare(ctx, NCCHTYPE_LOGO, flags))
+ goto clean;
+ if (0 == ncch_extract_buffer(ctx, logohashregion, logohashregionsize, &logohashregionsize,1))
+ goto clean;
+ ctx->logohashcheck = ctr_sha_256_verify(logohashregion, logohashregionsize, ctx->header.logohash);
+ }
+
free(exefshashregion);
free(romfshashregion);
free(exheaderhashregion);
+ free(logohashregion);
clean:
return;
}
@@ -331,6 +354,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
ncch_save(ctx, NCCHTYPE_EXEFS, actions);
ncch_save(ctx, NCCHTYPE_ROMFS, actions);
ncch_save(ctx, NCCHTYPE_EXHEADER, actions);
+ ncch_save(ctx, NCCHTYPE_LOGO, actions);
}
@@ -392,6 +416,18 @@ u32 ncch_get_exheader_size(ncch_context* ctx)
return getle32(ctx->header.extendedheadersize);
}
+u32 ncch_get_logo_offset(ncch_context* ctx)
+{
+ u32 mediaunitsize = ncch_get_mediaunit_size(ctx);
+ return ctx->offset + getle32(ctx->header.logooffset) * mediaunitsize;
+}
+
+u32 ncch_get_logo_size(ncch_context* ctx)
+{
+ u32 mediaunitsize = ncch_get_mediaunit_size(ctx);
+ return getle32(ctx->header.logosize) * mediaunitsize;
+}
+
u32 ncch_get_mediaunit_size(ncch_context* ctx)
{
unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings);
@@ -534,7 +570,12 @@ void ncch_print(ncch_context* ctx)
fprintf(stdout, "Maker code: %04x\n", getle16(header->makercode));
fprintf(stdout, "Version: %04x\n", getle16(header->version));
fprintf(stdout, "Program id: %016llx\n", getle64(header->programid));
- fprintf(stdout, "Temp flag: %02x\n", header->tempflag);
+ if(ctx->logohashcheck == Unchecked)
+ memdump(stdout, "Logo hash: ", header->logohash, 0x20);
+ else if(ctx->logohashcheck == Good)
+ memdump(stdout, "Logo hash (GOOD): ", header->logohash, 0x20);
+ else
+ memdump(stdout, "Logo hash (FAIL): ", header->logohash, 0x20);
fprintf(stdout, "Product code: %s\n", productcode);
fprintf(stdout, "Exheader size: %08x\n", getle32(header->extendedheadersize));
if (ctx->exheaderhashcheck == Unchecked)
@@ -549,6 +590,8 @@ void ncch_print(ncch_context* ctx)
fprintf(stdout, " > Crypto key: None\n");
else if (header->flags[7] & 1)
fprintf(stdout, " > Crypto key: %s\n", programid_is_system(header->programid)? "Fixed":"Zeros");
+ else if (header->flags[3] & 1)
+ fprintf(stdout, " > Crypto key: Secure2\n");
else
fprintf(stdout, " > Crypto key: Secure\n");
fprintf(stdout, " > Form type: %s\n", formtypetostring(header->flags[5]));
@@ -561,6 +604,8 @@ void ncch_print(ncch_context* ctx)
fprintf(stdout, "Plain region offset: 0x%08x\n", getle32(header->plainregionsize)? offset+getle32(header->plainregionoffset)*mediaunitsize : 0);
fprintf(stdout, "Plain region size: 0x%08x\n", getle32(header->plainregionsize)*mediaunitsize);
+ fprintf(stdout, "Logo offset: 0x%08x\n", getle32(header->logosize)? offset+getle32(header->logooffset)*mediaunitsize : 0);
+ fprintf(stdout, "Logo size: 0x%08x\n", getle32(header->logosize)*mediaunitsize);
fprintf(stdout, "ExeFS offset: 0x%08x\n", getle32(header->exefssize)? offset+getle32(header->exefsoffset)*mediaunitsize : 0);
fprintf(stdout, "ExeFS size: 0x%08x\n", getle32(header->exefssize)*mediaunitsize);
fprintf(stdout, "ExeFS hash region size: 0x%08x\n", getle32(header->exefshashregionsize)*mediaunitsize);
diff --git a/ctrtool/ncch.h b/ctrtool/ncch.h
index 3d15dbf..b6539e0 100644
--- a/ctrtool/ncch.h
+++ b/ctrtool/ncch.h
@@ -15,6 +15,7 @@ typedef enum
NCCHTYPE_EXHEADER = 1,
NCCHTYPE_EXEFS = 2,
NCCHTYPE_ROMFS = 3,
+ NCCHTYPE_LOGO = 4,
} ctr_ncchtypes;
typedef struct
@@ -27,8 +28,8 @@ typedef struct
u8 version[2];
u8 reserved0[4];
u8 programid[8];
- u8 tempflag;
- u8 reserved1[0x2f];
+ u8 reserved1[0x10];
+ u8 logohash[0x20];
u8 productcode[0x10];
u8 extendedheaderhash[0x20];
u8 extendedheadersize[4];
@@ -36,7 +37,8 @@ typedef struct
u8 flags[8];
u8 plainregionoffset[4];
u8 plainregionsize[4];
- u8 reserved3[8];
+ u8 logooffset[4];
+ u8 logosize[4];
u8 exefsoffset[4];
u8 exefssize[4];
u8 exefshashregionsize[4];
@@ -65,6 +67,7 @@ typedef struct
int exefshashcheck;
int romfshashcheck;
int exheaderhashcheck;
+ int logohashcheck;
int headersigcheck;
u32 extractsize;
u32 extractflags;
@@ -82,12 +85,14 @@ u32 ncch_get_romfs_offset(ncch_context* ctx);
u32 ncch_get_romfs_size(ncch_context* ctx);
u32 ncch_get_exheader_offset(ncch_context* ctx);
u32 ncch_get_exheader_size(ncch_context* ctx);
+u32 ncch_get_logo_offset(ncch_context* ctx);
+u32 ncch_get_logo_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);
void ncch_save(ncch_context* ctx, u32 type, u32 flags);
int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags);
-int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize);
+int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize, u8 nocrypto);
u32 ncch_get_mediaunit_size(ncch_context* ctx);
void ncch_get_counter(ncch_context* ctx, u8 counter[16], u8 type);
void ncch_determine_key(ncch_context* ctx, u32 actions);
diff --git a/ctrtool/settings.c b/ctrtool/settings.c
index cd3f9bf..888bdc9 100644
--- a/ctrtool/settings.c
+++ b/ctrtool/settings.c
@@ -47,6 +47,14 @@ filepath* settings_get_exheader_path(settings* usersettings)
return 0;
}
+filepath* settings_get_logo_path(settings* usersettings)
+{
+ if (usersettings)
+ return &usersettings->logopath;
+ else
+ return 0;
+}
+
filepath* settings_get_exefs_dir_path(settings* usersettings)
{
if (usersettings)
@@ -200,6 +208,11 @@ void settings_set_exheader_path(settings* usersettings, const char* path)
filepath_set(&usersettings->exheaderpath, path);
}
+void settings_set_logo_path(settings* usersettings, const char* path)
+{
+ filepath_set(&usersettings->logopath, path);
+}
+
void settings_set_certs_path(settings* usersettings, const char* path)
{
filepath_set(&usersettings->certspath, path);
diff --git a/ctrtool/settings.h b/ctrtool/settings.h
index f45bdc6..39d3c2d 100644
--- a/ctrtool/settings.h
+++ b/ctrtool/settings.h
@@ -14,6 +14,7 @@ typedef struct
filepath romfspath;
filepath romfsdirpath;
filepath exheaderpath;
+ filepath logopath;
filepath certspath;
filepath contentpath;
filepath tikpath;
@@ -32,6 +33,7 @@ filepath* settings_get_lzss_path(settings* usersettings);
filepath* settings_get_exefs_path(settings* usersettings);
filepath* settings_get_romfs_path(settings* usersettings);
filepath* settings_get_exheader_path(settings* usersettings);
+filepath* settings_get_logo_path(settings* usersettings);
filepath* settings_get_certs_path(settings* usersettings);
filepath* settings_get_tik_path(settings* usersettings);
filepath* settings_get_tmd_path(settings* usersettings);
@@ -53,6 +55,7 @@ void settings_set_lzss_path(settings* usersettings, const char* path);
void settings_set_exefs_path(settings* usersettings, const char* path);
void settings_set_romfs_path(settings* usersettings, const char* path);
void settings_set_exheader_path(settings* usersettings, const char* path);
+void settings_set_logo_path(settings* usersettings, const char* path);
void settings_set_certs_path(settings* usersettings, const char* path);
void settings_set_tik_path(settings* usersettings, const char* path);
void settings_set_tmd_path(settings* usersettings, const char* path);