Skip to content

Commit

Permalink
Added ability to extract data from DIFF files
Browse files Browse the repository at this point in the history
  • Loading branch information
d0k3 committed Feb 22, 2018
1 parent bba90f1 commit 2f739ab
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 22 deletions.
9 changes: 7 additions & 2 deletions arm9/source/filesys/filetype.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "fatmbr.h"
#include "nand.h"
#include "game.h"
#include "disadiff.h"
#include "keydb.h"
#include "ctrtransfer.h"
#include "scripting.h"
Expand All @@ -11,6 +12,8 @@

u64 IdentifyFileType(const char* path) {
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 smdh_magic[] = { SMDH_MAGIC };
const u8 threedsx_magic[] = { THREEDSX_EXT_MAGIC };
Expand Down Expand Up @@ -88,8 +91,10 @@ u64 IdentifyFileType(const char* path) {
return SYS_FIRM; // FIRM file
} else if ((ValidateAgbSaveHeader((AgbSaveHeader*) data) == 0) && (fsize >= AGBSAVE_MAX_SIZE)) {
return SYS_AGBSAVE; // AGBSAVE file
} else if (memcmp(header + 0x100, tickdb_magic, sizeof(tickdb_magic)) == 0) {
return SYS_TICKDB; // ticket.db
} else if (memcmp(header + 0x100, diff_magic, sizeof(diff_magic)) == 0) { // DIFF file
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) {
return GAME_SMDH; // SMDH file
} else if (ValidateTwlHeader((TwlHeader*) data) == 0) {
Expand Down
27 changes: 15 additions & 12 deletions arm9/source/filesys/filetype.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,20 @@
#define GAME_GBA (1ULL<<14)
#define GAME_TAD (1ULL<<15)
#define SYS_FIRM (1ULL<<16)
#define SYS_AGBSAVE (1ULL<<17)
#define SYS_TICKDB (1ULL<<18)
#define BIN_NCCHNFO (1ULL<<19)
#define BIN_TIKDB (1ULL<<20)
#define BIN_KEYDB (1ULL<<21)
#define BIN_LEGKEY (1ULL<<22)
#define TXT_SCRIPT (1ULL<<23)
#define TXT_GENERIC (1ULL<<24)
#define GFX_PCX (1ULL<<25)
#define FONT_PBM (1ULL<<26)
#define NOIMG_NAND (1ULL<<27)
#define HDR_NAND (1ULL<<28)
#define SYS_DIFF (1ULL<<17)
#define SYS_DISA (1ULL<<18) // not yet used
#define SYS_AGBSAVE (1ULL<<19)
#define SYS_TICKDB (1ULL<<20)
#define BIN_NCCHNFO (1ULL<<21)
#define BIN_TIKDB (1ULL<<22)
#define BIN_KEYDB (1ULL<<23)
#define BIN_LEGKEY (1ULL<<24)
#define TXT_SCRIPT (1ULL<<25)
#define TXT_GENERIC (1ULL<<26)
#define GFX_PCX (1ULL<<27)
#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 FLAG_FIRM (1ULL<<58) // <--- for CXIs containing FIRMs
Expand All @@ -54,6 +56,7 @@
#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_ISDISADIFF(tp) (tp&(SYS_DIFF|SYS_DISA))
#define FTYPE_RESTORABLE(tp) (tp&(IMG_NAND))
#define FTYPE_EBACKUP(tp) (tp&(IMG_NAND))
// #define FTYPE_XORPAD(tp) (tp&(BIN_NCCHNFO)) // deprecated
Expand Down
29 changes: 22 additions & 7 deletions arm9/source/godmode.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "virtual.h"
#include "vcart.h"
#include "game.h"
#include "disadiff.h"
#include "unittype.h"
#include "entrypoints.h"
#include "bootfirm.h"
Expand Down Expand Up @@ -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 hsinjectable = (FTYPE_HASCODE(filetype));
bool extrcodeable = (FTYPE_HASCODE(filetype));
bool extrdiffable = (FTYPE_ISDISADIFF(filetype));
bool restorable = (FTYPE_RESTORABLE(filetype) && IS_A9LH && !(drvtype & DRV_SYSNAND));
bool ebackupable = (FTYPE_EBACKUP(filetype));
bool ncsdfixable = (FTYPE_NCSDFIXABLE(filetype));
Expand All @@ -1038,7 +1040,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
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];
TruncateString(pathstr, file_path, 32, 8);
Expand Down Expand Up @@ -1082,7 +1084,8 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
(filetype & GAME_3DSX) ? "Show 3DSX title info" :
(filetype & SYS_FIRM ) ? "FIRM image options..." :
(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_KEYDB) ? "AESkeydb options..." :
(filetype & BIN_LEGKEY) ? "Build " KEYDB_NAME :
Expand Down Expand Up @@ -1224,6 +1227,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
int ctrtransfer = (transferable) ? ++n_opt : -1;
int hsinject = (hsinjectable) ? ++n_opt : -1;
int extrcode = (extrcodeable) ? ++n_opt : -1;
int extrdiff = (extrdiffable) ? ++n_opt : -1;
int rename = (renamable) ? ++n_opt : -1;
int xorpad = (xorpadable) ? ++n_opt : -1;
int xorpad_inplace = (xorpadable) ? ++n_opt : -1;
Expand Down Expand Up @@ -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_inplace > 0) optionstr[xorpad_inplace-1] = "Build XORpads (inplace)";
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 (keyinstall > 0) optionstr[keyinstall-1] = "Install " KEYDB_NAME;
if (install > 0) optionstr[install-1] = "Install FIRM";
Expand Down Expand Up @@ -1576,7 +1581,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
}
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)) {
u32 n_success = 0;
u32 n_other = 0;
Expand All @@ -1591,19 +1596,29 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
continue;
}
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 };
if ((GetTmdContentPath(cxi_pathl, path) == 0) && PathExist(cxi_pathl) &&
(ExtractCodeFromCxiFile(cxi_pathl, NULL, NULL) == 0)) {
n_success++;
}
} else if (ExtractCodeFromCxiFile(path, NULL, NULL) == 0) n_success++;
else continue;
} else continue;
} else {
if (ExtractCodeFromCxiFile(path, NULL, NULL) == 0) n_success++;
else continue;
}
current_dir->entry[i].marked = false;
}
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);
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 {
char extstr[8] = { 0 };
ShowString("%s\nExtracting .code, please wait...", pathstr);
Expand Down
60 changes: 60 additions & 0 deletions arm9/source/utils/gameutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,66 @@ u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr)
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) {
u64 filetype = IdentifyFileType(path);

Expand Down
1 change: 1 addition & 0 deletions arm9/source/utils/gameutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ u32 CryptGameFile(const char* path, bool inplace, bool encrypt);
u32 BuildCiaFromGameFile(const char* path, bool force_legit);
u32 DumpCxiSrlFromTmdFile(const char* path);
u32 ExtractCodeFromCxiFile(const char* path, const char* path_out, char* extstr);
u32 ExtractDataFromDisaDiff(const char* path);
u32 ShowGameFileTitleInfo(const char* path);
u32 GetTmdContentPath(char* path_content, const char* path_tmd);
u32 BuildNcchInfoXorpads(const char* destdir, const char* path);
Expand Down
2 changes: 1 addition & 1 deletion arm9/source/virtual/vtickdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void DeinitVTickDbDrive(void) {
}

u64 InitVTickDbDrive(void) { // prerequisite: ticket.db mounted as image
if (!(GetMountState() & SYS_TICKDB)) return 0;
if (!(GetMountState() & SYS_TICKDB)) return 0;

// set up drive buffer / internal db
DeinitVTickDbDrive();
Expand Down

0 comments on commit 2f739ab

Please sign in to comment.