From 2e07189a1be2cd28ba31ab3a9b420ab82f7974bd Mon Sep 17 00:00:00 2001 From: d0k3 Date: Tue, 17 Apr 2018 00:48:50 +0200 Subject: [PATCH] Allow .code extraction for .3ds files --- arm9/source/filesys/filetype.h | 2 +- arm9/source/utils/gameutil.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arm9/source/filesys/filetype.h b/arm9/source/filesys/filetype.h index ea7fffb..a6ecad1 100644 --- a/arm9/source/filesys/filetype.h +++ b/arm9/source/filesys/filetype.h @@ -55,7 +55,7 @@ #define FTYPE_RENAMABLE(tp) (tp&(GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_NDS|GAME_GBA)) #define FTYPE_TRANSFERABLE(tp) ((u64) (tp&(IMG_FAT|FLAG_CTR)) == (u64) (IMG_FAT|FLAG_CTR)) #define FTYPE_NCSDFIXABLE(tp) (tp&(HDR_NAND|NOIMG_NAND)) -#define FTYPE_HASCODE(tp) ((u64) (tp&(GAME_NCCH|FLAG_CXI)) == (u64) (GAME_NCCH|FLAG_CXI)) +#define FTYPE_HASCODE(tp) (((u64) (tp&(GAME_NCCH|FLAG_CXI)) == (u64) (GAME_NCCH|FLAG_CXI))|(tp&GAME_NCSD)) #define FTYPE_ISDISADIFF(tp) (tp&(SYS_DIFF|SYS_DISA)) #define FTYPE_RESTORABLE(tp) (tp&(IMG_NAND)) #define FTYPE_EBACKUP(tp) (tp&(IMG_NAND)) diff --git a/arm9/source/utils/gameutil.c b/arm9/source/utils/gameutil.c index 64e56c1..10cd6a3 100644 --- a/arm9/source/utils/gameutil.c +++ b/arm9/source/utils/gameutil.c @@ -1498,16 +1498,26 @@ u32 DumpCxiSrlFromTmdFile(const char* path) { } u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr) { + u64 filetype = IdentifyFileType(path); char dest[256]; if (!path_out && (fvx_rmkdir(OUTPUT_PATH) != FR_OK)) return 1; strncpy(dest, path_out ? path_out : OUTPUT_PATH, 256); if (!CheckWritePermissions(dest)) return 1; + // NCSD handling + u32 ncch_offset = 0; + if (filetype & GAME_NCSD) { + NcsdHeader ncsd; + if (LoadNcsdHeader(&ncsd, path) == 0) + ncch_offset = ncsd.partitions[0].offset * NCSD_MEDIA_UNIT; + else return 1; + } + // load all required headers NcchHeader ncch; NcchExtHeader exthdr; ExeFsHeader exefs; - if (LoadNcchHeaders(&ncch, &exthdr, &exefs, path, 0) != 0) return 1; + if (LoadNcchHeaders(&ncch, &exthdr, &exefs, path, ncch_offset) != 0) return 1; // find ".code" or ".firm" inside the ExeFS header u32 code_size = 0; @@ -1526,7 +1536,7 @@ u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr) if (exthdr.flag & 0x1) { u8 footer[8]; if (code_size < 8) return 1; - if ((fvx_qread(path, footer, code_offset + code_size - 8, 8, NULL) != FR_OK) || + if ((fvx_qread(path, footer, ncch_offset + code_offset + code_size - 8, 8, NULL) != FR_OK) || (DecryptNcch(footer, code_offset + code_size - 8, 8, &ncch, &exefs) != 0)) return 1; u32 unc_size = GetCodeLzssUncompressedSize(footer, code_size); @@ -1541,7 +1551,7 @@ u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr) } // load .code - if ((fvx_qread(path, code, code_offset, code_size, NULL) != FR_OK) || + if ((fvx_qread(path, code, ncch_offset + code_offset, code_size, NULL) != FR_OK) || (DecryptNcch(code, code_offset, code_size, &ncch, &exefs) != 0)) { free(code); return 1;