mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Added ability to extract data from DIFF files
This commit is contained in:
parent
bba90f14ad
commit
2f739ab130
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
else continue;
|
if (ExtractCodeFromCxiFile(path, NULL, NULL) == 0) n_success++;
|
||||||
|
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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -121,7 +121,7 @@ void DeinitVTickDbDrive(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u64 InitVTickDbDrive(void) { // prerequisite: ticket.db mounted as image
|
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
|
// set up drive buffer / internal db
|
||||||
DeinitVTickDbDrive();
|
DeinitVTickDbDrive();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user