Added ability to extract data from DIFF files

This commit is contained in:
d0k3 2018-02-22 01:47:29 +01:00
parent bba90f14ad
commit 2f739ab130
6 changed files with 106 additions and 22 deletions

View File

@ -3,6 +3,7 @@
#include "fatmbr.h" #include "fatmbr.h"
#include "nand.h" #include "nand.h"
#include "game.h" #include "game.h"
#include "disadiff.h"
#include "keydb.h" #include "keydb.h"
#include "ctrtransfer.h" #include "ctrtransfer.h"
#include "scripting.h" #include "scripting.h"
@ -11,6 +12,8 @@
u64 IdentifyFileType(const char* path) { u64 IdentifyFileType(const char* path) {
const u8 romfs_magic[] = { ROMFS_MAGIC }; const u8 romfs_magic[] = { ROMFS_MAGIC };
const u8 diff_magic[] = { DIFF_MAGIC };
// const u8 disa_magic[] = { DISA_MAGIC };
const u8 tickdb_magic[] = { TICKDB_MAGIC }; const u8 tickdb_magic[] = { TICKDB_MAGIC };
const u8 smdh_magic[] = { SMDH_MAGIC }; const u8 smdh_magic[] = { SMDH_MAGIC };
const u8 threedsx_magic[] = { THREEDSX_EXT_MAGIC }; const u8 threedsx_magic[] = { THREEDSX_EXT_MAGIC };
@ -88,8 +91,10 @@ u64 IdentifyFileType(const char* path) {
return SYS_FIRM; // FIRM file return SYS_FIRM; // FIRM file
} else if ((ValidateAgbSaveHeader((AgbSaveHeader*) data) == 0) && (fsize >= AGBSAVE_MAX_SIZE)) { } else if ((ValidateAgbSaveHeader((AgbSaveHeader*) data) == 0) && (fsize >= AGBSAVE_MAX_SIZE)) {
return SYS_AGBSAVE; // AGBSAVE file return SYS_AGBSAVE; // AGBSAVE file
} else if (memcmp(header + 0x100, tickdb_magic, sizeof(tickdb_magic)) == 0) { } else if (memcmp(header + 0x100, diff_magic, sizeof(diff_magic)) == 0) { // DIFF file
return SYS_TICKDB; // ticket.db if (memcmp(header + 0x100, tickdb_magic, sizeof(tickdb_magic)) == 0) // ticket.db file
return SYS_DIFF | SYS_TICKDB; // ticket.db
return SYS_DIFF;
} else if (memcmp(header, smdh_magic, sizeof(smdh_magic)) == 0) { } else if (memcmp(header, smdh_magic, sizeof(smdh_magic)) == 0) {
return GAME_SMDH; // SMDH file return GAME_SMDH; // SMDH file
} else if (ValidateTwlHeader((TwlHeader*) data) == 0) { } else if (ValidateTwlHeader((TwlHeader*) data) == 0) {

View File

@ -19,18 +19,20 @@
#define GAME_GBA (1ULL<<14) #define GAME_GBA (1ULL<<14)
#define GAME_TAD (1ULL<<15) #define GAME_TAD (1ULL<<15)
#define SYS_FIRM (1ULL<<16) #define SYS_FIRM (1ULL<<16)
#define SYS_AGBSAVE (1ULL<<17) #define SYS_DIFF (1ULL<<17)
#define SYS_TICKDB (1ULL<<18) #define SYS_DISA (1ULL<<18) // not yet used
#define BIN_NCCHNFO (1ULL<<19) #define SYS_AGBSAVE (1ULL<<19)
#define BIN_TIKDB (1ULL<<20) #define SYS_TICKDB (1ULL<<20)
#define BIN_KEYDB (1ULL<<21) #define BIN_NCCHNFO (1ULL<<21)
#define BIN_LEGKEY (1ULL<<22) #define BIN_TIKDB (1ULL<<22)
#define TXT_SCRIPT (1ULL<<23) #define BIN_KEYDB (1ULL<<23)
#define TXT_GENERIC (1ULL<<24) #define BIN_LEGKEY (1ULL<<24)
#define GFX_PCX (1ULL<<25) #define TXT_SCRIPT (1ULL<<25)
#define FONT_PBM (1ULL<<26) #define TXT_GENERIC (1ULL<<26)
#define NOIMG_NAND (1ULL<<27) #define GFX_PCX (1ULL<<27)
#define HDR_NAND (1ULL<<28) #define FONT_PBM (1ULL<<28)
#define NOIMG_NAND (1ULL<<29)
#define HDR_NAND (1ULL<<30)
#define TYPE_BASE 0xFFFFFFFFULL // 32 bit reserved for base types #define TYPE_BASE 0xFFFFFFFFULL // 32 bit reserved for base types
// #define FLAG_FIRM (1ULL<<58) // <--- for CXIs containing FIRMs // #define FLAG_FIRM (1ULL<<58) // <--- for CXIs containing FIRMs
@ -54,6 +56,7 @@
#define FTYPE_TRANSFERABLE(tp) ((u64) (tp&(IMG_FAT|FLAG_CTR)) == (u64) (IMG_FAT|FLAG_CTR)) #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_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))
#define FTYPE_ISDISADIFF(tp) (tp&(SYS_DIFF|SYS_DISA))
#define FTYPE_RESTORABLE(tp) (tp&(IMG_NAND)) #define FTYPE_RESTORABLE(tp) (tp&(IMG_NAND))
#define FTYPE_EBACKUP(tp) (tp&(IMG_NAND)) #define FTYPE_EBACKUP(tp) (tp&(IMG_NAND))
// #define FTYPE_XORPAD(tp) (tp&(BIN_NCCHNFO)) // deprecated // #define FTYPE_XORPAD(tp) (tp&(BIN_NCCHNFO)) // deprecated

View File

@ -9,6 +9,7 @@
#include "virtual.h" #include "virtual.h"
#include "vcart.h" #include "vcart.h"
#include "game.h" #include "game.h"
#include "disadiff.h"
#include "unittype.h" #include "unittype.h"
#include "entrypoints.h" #include "entrypoints.h"
#include "bootfirm.h" #include "bootfirm.h"
@ -1015,6 +1016,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
bool transferable = (FTYPE_TRANSFERABLE(filetype) && IS_A9LH && (drvtype & DRV_FAT)); bool transferable = (FTYPE_TRANSFERABLE(filetype) && IS_A9LH && (drvtype & DRV_FAT));
bool hsinjectable = (FTYPE_HASCODE(filetype)); bool hsinjectable = (FTYPE_HASCODE(filetype));
bool extrcodeable = (FTYPE_HASCODE(filetype)); bool extrcodeable = (FTYPE_HASCODE(filetype));
bool extrdiffable = (FTYPE_ISDISADIFF(filetype));
bool restorable = (FTYPE_RESTORABLE(filetype) && IS_A9LH && !(drvtype & DRV_SYSNAND)); bool restorable = (FTYPE_RESTORABLE(filetype) && IS_A9LH && !(drvtype & DRV_SYSNAND));
bool ebackupable = (FTYPE_EBACKUP(filetype)); bool ebackupable = (FTYPE_EBACKUP(filetype));
bool ncsdfixable = (FTYPE_NCSDFIXABLE(filetype)); bool ncsdfixable = (FTYPE_NCSDFIXABLE(filetype));
@ -1038,7 +1040,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
extrcodeable = (FTYPE_HASCODE(filetype_cxi)); extrcodeable = (FTYPE_HASCODE(filetype_cxi));
} }
bool special_opt = mountable || verificable || decryptable || encryptable || cia_buildable || cia_buildable_legit || cxi_dumpable || tik_buildable || key_buildable || titleinfo || renamable || transferable || hsinjectable || restorable || xorpadable || ebackupable || ncsdfixable || extrcodeable || keyinitable || keyinstallable || bootable || scriptable || fontable || viewable || installable || agbexportable || agbimportable; bool special_opt = mountable || verificable || decryptable || encryptable || cia_buildable || cia_buildable_legit || cxi_dumpable || tik_buildable || key_buildable || titleinfo || renamable || transferable || hsinjectable || restorable || xorpadable || ebackupable || ncsdfixable || extrcodeable || extrdiffable || keyinitable || keyinstallable || bootable || scriptable || fontable || viewable || installable || agbexportable || agbimportable;
char pathstr[32+1]; char pathstr[32+1];
TruncateString(pathstr, file_path, 32, 8); TruncateString(pathstr, file_path, 32, 8);
@ -1082,7 +1084,8 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
(filetype & GAME_3DSX) ? "Show 3DSX title info" : (filetype & GAME_3DSX) ? "Show 3DSX title info" :
(filetype & SYS_FIRM ) ? "FIRM image options..." : (filetype & SYS_FIRM ) ? "FIRM image options..." :
(filetype & SYS_AGBSAVE)? (agbimportable) ? "AGBSAVE options..." : "Dump GBA VC save" : (filetype & SYS_AGBSAVE)? (agbimportable) ? "AGBSAVE options..." : "Dump GBA VC save" :
(filetype & SYS_TICKDB) ? (tik_buildable) ? "Ticket.db options..." : "Mount as ticket.db" : (filetype & SYS_TICKDB) ? "Ticket.db options..." :
(filetype & SYS_DIFF) ? "Extract DIFF data" :
(filetype & BIN_TIKDB) ? "Titlekey options..." : (filetype & BIN_TIKDB) ? "Titlekey options..." :
(filetype & BIN_KEYDB) ? "AESkeydb options..." : (filetype & BIN_KEYDB) ? "AESkeydb options..." :
(filetype & BIN_LEGKEY) ? "Build " KEYDB_NAME : (filetype & BIN_LEGKEY) ? "Build " KEYDB_NAME :
@ -1224,6 +1227,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
int ctrtransfer = (transferable) ? ++n_opt : -1; int ctrtransfer = (transferable) ? ++n_opt : -1;
int hsinject = (hsinjectable) ? ++n_opt : -1; int hsinject = (hsinjectable) ? ++n_opt : -1;
int extrcode = (extrcodeable) ? ++n_opt : -1; int extrcode = (extrcodeable) ? ++n_opt : -1;
int extrdiff = (extrdiffable) ? ++n_opt : -1;
int rename = (renamable) ? ++n_opt : -1; int rename = (renamable) ? ++n_opt : -1;
int xorpad = (xorpadable) ? ++n_opt : -1; int xorpad = (xorpadable) ? ++n_opt : -1;
int xorpad_inplace = (xorpadable) ? ++n_opt : -1; int xorpad_inplace = (xorpadable) ? ++n_opt : -1;
@ -1256,6 +1260,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
if (xorpad > 0) optionstr[xorpad-1] = "Build XORpads (SD output)"; if (xorpad > 0) optionstr[xorpad-1] = "Build XORpads (SD output)";
if (xorpad_inplace > 0) optionstr[xorpad_inplace-1] = "Build XORpads (inplace)"; if (xorpad_inplace > 0) optionstr[xorpad_inplace-1] = "Build XORpads (inplace)";
if (extrcode > 0) optionstr[extrcode-1] = "Extract " EXEFS_CODE_NAME; if (extrcode > 0) optionstr[extrcode-1] = "Extract " EXEFS_CODE_NAME;
if (extrdiff > 0) optionstr[extrdiff-1] = "Extract DIFF data";
if (keyinit > 0) optionstr[keyinit-1] = "Init " KEYDB_NAME; if (keyinit > 0) optionstr[keyinit-1] = "Init " KEYDB_NAME;
if (keyinstall > 0) optionstr[keyinstall-1] = "Install " KEYDB_NAME; if (keyinstall > 0) optionstr[keyinstall-1] = "Install " KEYDB_NAME;
if (install > 0) optionstr[install-1] = "Install FIRM"; if (install > 0) optionstr[install-1] = "Install FIRM";
@ -1576,7 +1581,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
} }
return 0; return 0;
} }
else if (user_select == extrcode) { // -> Extract code else if ((user_select == extrcode) || (user_select == extrdiff)) { // -> Extract .code or DIFF partition
if ((n_marked > 1) && ShowPrompt(true, "Try to extract all %lu selected files?", n_marked)) { if ((n_marked > 1) && ShowPrompt(true, "Try to extract all %lu selected files?", n_marked)) {
u32 n_success = 0; u32 n_success = 0;
u32 n_other = 0; u32 n_other = 0;
@ -1591,19 +1596,29 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
continue; continue;
} }
DrawDirContents(current_dir, (*cursor = i), scroll); DrawDirContents(current_dir, (*cursor = i), scroll);
if (filetype & GAME_TMD) { if (filetype & SYS_DIFF) {
if (ExtractDataFromDisaDiff(path) == 0) n_success++;
else continue;
} else if (filetype & GAME_TMD) {
char cxi_pathl[256] = { 0 }; char cxi_pathl[256] = { 0 };
if ((GetTmdContentPath(cxi_pathl, path) == 0) && PathExist(cxi_pathl) && if ((GetTmdContentPath(cxi_pathl, path) == 0) && PathExist(cxi_pathl) &&
(ExtractCodeFromCxiFile(cxi_pathl, NULL, NULL) == 0)) { (ExtractCodeFromCxiFile(cxi_pathl, NULL, NULL) == 0)) {
n_success++; n_success++;
} } else continue;
} else if (ExtractCodeFromCxiFile(path, NULL, NULL) == 0) n_success++; } else {
if (ExtractCodeFromCxiFile(path, NULL, NULL) == 0) n_success++;
else continue; else continue;
}
current_dir->entry[i].marked = false; current_dir->entry[i].marked = false;
} }
if (n_other) ShowPrompt(false, "%lu/%lu files extracted ok\n%lu/%lu not of same type", if (n_other) ShowPrompt(false, "%lu/%lu files extracted ok\n%lu/%lu not of same type",
n_success, n_marked, n_other, n_marked); n_success, n_marked, n_other, n_marked);
else ShowPrompt(false, "%lu/%lu files extracted ok", n_success, n_marked); else ShowPrompt(false, "%lu/%lu files extracted ok", n_success, n_marked);
} else if (filetype & SYS_DIFF) {
ShowString("%s\nExtracting data, please wait...", pathstr);
if (ExtractDataFromDisaDiff(file_path) == 0) {
ShowPrompt(false, "%s\ndata extracted to " OUTPUT_PATH, pathstr);
} else ShowPrompt(false, "%s\ndata extract failed", pathstr);
} else { } else {
char extstr[8] = { 0 }; char extstr[8] = { 0 };
ShowString("%s\nExtracting .code, please wait...", pathstr); ShowString("%s\nExtracting .code, please wait...", pathstr);

View File

@ -1574,6 +1574,66 @@ u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr)
return 0; return 0;
} }
u32 ExtractDataFromDisaDiff(const char* path) {
char dest[256];
u32 ret = 0;
// build output name
char* name = strrchr(path, '/');
if (!name) return 1;
snprintf(dest, 256, "%s/%s", OUTPUT_PATH, ++name);
// replace extension
char* dot = strrchr(dest, '.');
if (!dot || (dot < strrchr(dest, '/')))
dot = dest + strnlen(dest, 256);
snprintf(dot, 16, ".%s", "bin");
if (!CheckWritePermissions(dest)) return 1;
// prepare DISA / DIFF read
DisaDiffReaderInfo info;
u8* lvl2_cache = NULL;
if ((GetDisaDiffReaderInfo(path, &info, false) != 0) ||
!(lvl2_cache = (u8*) malloc(info.size_dpfs_lvl2)) ||
(BuildDisaDiffDpfsLvl2Cache(path, &info, lvl2_cache, info.size_dpfs_lvl2) != 0)) {
if (lvl2_cache) free(lvl2_cache);
return 1;
}
// prepare buffer
u8* buffer = (u8*) malloc(STD_BUFFER_SIZE);
if (!buffer) {
free(lvl2_cache);
return 1;
}
// open output file
FIL file;
if (fvx_open(&file, dest, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) {
free(buffer);
free(lvl2_cache);
return 1;
}
// actually extract the partition
u32 total_size = 0;
for (u32 i = 0; ret == 0; i += STD_BUFFER_SIZE) {
UINT btr;
u32 add_size = ReadDisaDiffIvfcLvl4(path, &info, i, STD_BUFFER_SIZE, buffer);
if (!add_size) break;
if ((fvx_write(&file, buffer, add_size, &btr) != FR_OK) || (btr != add_size)) ret = 1;
total_size += add_size;
}
// wrap it up
if (!total_size) ret = 1;
free(buffer);
free(lvl2_cache);
fvx_close(&file);
return ret;
}
u32 LoadSmdhFromGameFile(const char* path, Smdh* smdh) { u32 LoadSmdhFromGameFile(const char* path, Smdh* smdh) {
u64 filetype = IdentifyFileType(path); u64 filetype = IdentifyFileType(path);

View File

@ -8,6 +8,7 @@ u32 CryptGameFile(const char* path, bool inplace, bool encrypt);
u32 BuildCiaFromGameFile(const char* path, bool force_legit); u32 BuildCiaFromGameFile(const char* path, bool force_legit);
u32 DumpCxiSrlFromTmdFile(const char* path); u32 DumpCxiSrlFromTmdFile(const char* path);
u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr); u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr);
u32 ExtractDataFromDisaDiff(const char* path);
u32 ShowGameFileTitleInfo(const char* path); u32 ShowGameFileTitleInfo(const char* path);
u32 GetTmdContentPath(char* path_content, const char* path_tmd); u32 GetTmdContentPath(char* path_content, const char* path_tmd);
u32 BuildNcchInfoXorpads(const char* destdir, const char* path); u32 BuildNcchInfoXorpads(const char* destdir, const char* path);