13
13
#define CRYPTO_DECRYPT NCCH_NOCRYPTO
14
14
#define CRYPTO_ENCRYPT NCCH_STDCRYPTO
15
15
16
- u32 GetNcchHeaders (NcchHeader * ncch , NcchExtHeader * exthdr , ExeFsHeader * exefs , FIL * file ) {
16
+ u32 GetNcchHeaders (NcchHeader * ncch , NcchExtHeader * exthdr , ExeFsHeader * exefs , FIL * file , bool nocrypto ) {
17
17
u32 offset_ncch = fvx_tell (file );
18
18
UINT btr ;
19
-
20
- if ((fvx_read (file , ncch , sizeof (NcchHeader ), & btr ) != FR_OK ) ||
21
- (ValidateNcchHeader (ncch ) != 0 ))
22
- return 1 ;
19
+
20
+ if (fvx_read (file , ncch , sizeof (NcchHeader ), & btr ) != FR_OK ) return 1 ;
21
+ if (nocrypto ) {
22
+ ncch -> flags [3 ] = 0x00 ;
23
+ ncch -> flags [7 ] = (ncch -> flags [7 ] & ~0x21 ) | 0x04 ;
24
+ }
25
+ if (ValidateNcchHeader (ncch ) != 0 ) return 1 ;
23
26
24
27
if (exthdr ) {
25
28
if (!ncch -> size_exthdr ) return 1 ;
@@ -71,7 +74,7 @@ u32 LoadNcchHeaders(NcchHeader* ncch, NcchExtHeader* exthdr, ExeFsHeader* exefs,
71
74
if (fvx_open (& file , path , FA_READ | FA_OPEN_EXISTING ) != FR_OK )
72
75
return 1 ;
73
76
fvx_lseek (& file , offset );
74
- if (GetNcchHeaders (ncch , exthdr , exefs , & file ) != 0 ) {
77
+ if (GetNcchHeaders (ncch , exthdr , exefs , & file , false ) != 0 ) {
75
78
fvx_close (& file );
76
79
return 1 ;
77
80
}
@@ -137,7 +140,7 @@ u32 LoadExeFsFile(void* data, const char* path, u32 offset, const char* name, u3
137
140
if (fvx_open (& file , path , FA_READ | FA_OPEN_EXISTING ) != FR_OK )
138
141
return 1 ;
139
142
fvx_lseek (& file , offset );
140
- if ((GetNcchHeaders (& ncch , NULL , & exefs , & file ) != 0 ) ||
143
+ if ((GetNcchHeaders (& ncch , NULL , & exefs , & file , false ) != 0 ) ||
141
144
(!ncch .size_exefs )) {
142
145
fvx_close (& file );
143
146
return 1 ;
@@ -304,6 +307,7 @@ u32 VerifyTmdContent(const char* path, u64 offset, TmdContentChunk* chunk, const
304
307
}
305
308
306
309
u32 VerifyNcchFile (const char * path , u32 offset , u32 size ) {
310
+ bool cryptofix = false;
307
311
NcchHeader ncch ;
308
312
NcchExtHeader exthdr ;
309
313
ExeFsHeader exefs ;
@@ -316,35 +320,49 @@ u32 VerifyNcchFile(const char* path, u32 offset, u32 size) {
316
320
if (fvx_open (& file , path , FA_READ | FA_OPEN_EXISTING ) != FR_OK )
317
321
return 1 ;
318
322
323
+ // fetch and check NCCH header
319
324
fvx_lseek (& file , offset );
320
- if (GetNcchHeaders (& ncch , NULL , NULL , & file ) != 0 ) {
325
+ if (GetNcchHeaders (& ncch , NULL , NULL , & file , cryptofix ) != 0 ) {
321
326
if (!offset ) ShowPrompt (false, "%s\nError: Not a NCCH file" , pathstr );
322
327
fvx_close (& file );
323
328
return 1 ;
324
329
}
325
-
326
- fvx_lseek (& file , offset );
327
- if (ncch .size_exthdr && (GetNcchHeaders (& ncch , & exthdr , NULL , & file ) != 0 )) {
328
- if (!offset ) ShowPrompt (false, "%s\nError: Missing ExtHeader" , pathstr );
330
+
331
+ // check NCCH size
332
+ if (!size ) size = fvx_size (& file ) - offset ;
333
+ if ((fvx_size (& file ) < offset ) || (size < ncch .size * NCCH_MEDIA_UNIT )) {
334
+ if (!offset ) ShowPrompt (false, "%s\nError: File is too small" , pathstr );
329
335
fvx_close (& file );
330
336
return 1 ;
331
337
}
332
338
339
+ // fetch and check ExeFS header
333
340
fvx_lseek (& file , offset );
334
- if (ncch .size_exefs && (GetNcchHeaders (& ncch , NULL , & exefs , & file ) != 0 )) {
335
- if (!offset ) ShowPrompt (false, "%s\nError: Bad ExeFS header" , pathstr );
336
- fvx_close (& file );
337
- return 1 ;
341
+ if (ncch .size_exefs && (GetNcchHeaders (& ncch , NULL , & exefs , & file , cryptofix ) != 0 )) {
342
+ bool borkedflags = false;
343
+ if (ncch .size_exefs && NCCH_ENCRYPTED (& ncch )) {
344
+ // disable crypto, try again
345
+ cryptofix = true;
346
+ fvx_lseek (& file , offset );
347
+ if ((GetNcchHeaders (& ncch , NULL , & exefs , & file , cryptofix ) == 0 ) &&
348
+ ShowPrompt (true, "%s\nError: Bad crypto flags\n \nAttempt to fix?" , pathstr ))
349
+ borkedflags = true;
350
+ }
351
+ if (!borkedflags ) {
352
+ if (!offset ) ShowPrompt (false, "%s\nError: Bad ExeFS header" , pathstr );
353
+ fvx_close (& file );
354
+ return 1 ;
355
+ }
338
356
}
339
-
340
- // size checks
341
- if (! size ) size = fvx_size ( & file ) - offset ;
342
- if (( fvx_size ( & file ) < offset ) || ( size < ncch . size * NCCH_MEDIA_UNIT )) {
343
- if (!offset ) ShowPrompt (false, "%s\nError: File is too small " , pathstr );
357
+
358
+ // fetch and check ExtHeader
359
+ fvx_lseek ( & file , offset ) ;
360
+ if (ncch . size_exthdr && ( GetNcchHeaders ( & ncch , & exthdr , NULL , & file , cryptofix ) != 0 )) {
361
+ if (!offset ) ShowPrompt (false, "%s\nError: Missing ExtHeader " , pathstr );
344
362
fvx_close (& file );
345
363
return 1 ;
346
364
}
347
-
365
+
348
366
// check / setup crypto
349
367
if (SetupNcchCrypto (& ncch , NCCH_NOCRYPTO ) != 0 ) {
350
368
if (!offset ) ShowPrompt (false, "%s\nError: Crypto not set up" , pathstr );
@@ -481,6 +499,7 @@ u32 VerifyNcchFile(const char* path, u32 offset, u32 size) {
481
499
}
482
500
483
501
fvx_close (& file );
502
+ if (cryptofix ) fvx_qwrite (path , & ncch , offset , sizeof (NcchHeader ), NULL );
484
503
return ver_exthdr |ver_exefs |ver_romfs ;
485
504
}
486
505
0 commit comments