From f8b9332728012bb2ff5491566f53a6b09880d6b2 Mon Sep 17 00:00:00 2001 From: aspargas2 Date: Sat, 21 Sep 2019 10:37:14 -0400 Subject: [PATCH] implement vdisadiff --- arm9/source/filesys/filetype.c | 4 ++- arm9/source/filesys/filetype.h | 4 +-- arm9/source/filesys/fsdrive.c | 2 +- arm9/source/filesys/fsdrive.h | 4 +-- arm9/source/filesys/fsinit.c | 2 ++ arm9/source/godmode.c | 22 ++++--------- arm9/source/utils/gameutil.c | 60 ---------------------------------- arm9/source/utils/gameutil.h | 1 - arm9/source/virtual/virtual.c | 18 ++++++++-- arm9/source/virtual/virtual.h | 40 ++++++++++++----------- 10 files changed, 53 insertions(+), 104 deletions(-) diff --git a/arm9/source/filesys/filetype.c b/arm9/source/filesys/filetype.c index 9347c81..65c822e 100644 --- a/arm9/source/filesys/filetype.c +++ b/arm9/source/filesys/filetype.c @@ -13,7 +13,7 @@ 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 disa_magic[] = { DISA_MAGIC }; const u8 tickdb_magic[] = { TICKDB_MAGIC }; const u8 smdh_magic[] = { SMDH_MAGIC }; const u8 threedsx_magic[] = { THREEDSX_EXT_MAGIC }; @@ -98,6 +98,8 @@ u64 IdentifyFileType(const char* path) { 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 + 0x100, disa_magic, sizeof(disa_magic)) == 0) { // DISA file + return SYS_DISA; } else if (memcmp(header, smdh_magic, sizeof(smdh_magic)) == 0) { return GAME_SMDH; // SMDH file } else if (ValidateTwlHeader((TwlHeader*) data) == 0) { diff --git a/arm9/source/filesys/filetype.h b/arm9/source/filesys/filetype.h index f04170a..77d09db 100644 --- a/arm9/source/filesys/filetype.h +++ b/arm9/source/filesys/filetype.h @@ -21,7 +21,7 @@ #define GAME_TAD (1ULL<<16) #define SYS_FIRM (1ULL<<17) #define SYS_DIFF (1ULL<<18) -#define SYS_DISA (1ULL<<19) // not yet used +#define SYS_DISA (1ULL<<19) #define SYS_AGBSAVE (1ULL<<20) #define SYS_TICKDB (1ULL<<21) #define BIN_NCCHNFO (1ULL<<22) @@ -44,7 +44,7 @@ #define FLAG_NUSCDN (1ULL<<62) #define FLAG_CXI (1ULL<<63) -#define FTYPE_MOUNTABLE(tp) (tp&(IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS|GAME_NDS|GAME_TAD|SYS_FIRM|SYS_TICKDB|BIN_KEYDB)) +#define FTYPE_MOUNTABLE(tp) (tp&(IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS|GAME_NDS|GAME_TAD|SYS_FIRM|SYS_DIFF|SYS_DISA|SYS_TICKDB|BIN_KEYDB)) #define FTYPE_VERIFICABLE(tp) (tp&(IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD|GAME_BOSS|SYS_FIRM)) #define FTYPE_DECRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|GAME_NUSCDN|SYS_FIRM|BIN_KEYDB)) #define FTYPE_ENCRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|BIN_KEYDB)) diff --git a/arm9/source/filesys/fsdrive.c b/arm9/source/filesys/fsdrive.c index f852f2e..a03feaf 100644 --- a/arm9/source/filesys/fsdrive.c +++ b/arm9/source/filesys/fsdrive.c @@ -46,7 +46,7 @@ int DriveType(const char* path) { type = DRV_VIRTUAL | DRV_SYSNAND; } else if (vsrc == VRT_EMUNAND) { type = DRV_VIRTUAL | DRV_EMUNAND; - } else if (vsrc == VRT_IMGNAND) { + } else if ((vsrc == VRT_IMGNAND) || (vsrc == VRT_DISADIFF)) { type = DRV_VIRTUAL | DRV_IMAGE; } else if (vsrc == VRT_XORPAD) { type = DRV_VIRTUAL | DRV_XORPAD; diff --git a/arm9/source/filesys/fsdrive.h b/arm9/source/filesys/fsdrive.h index 7e7b104..f11b518 100644 --- a/arm9/source/filesys/fsdrive.h +++ b/arm9/source/filesys/fsdrive.h @@ -37,13 +37,13 @@ "EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP", "EMUNAND SD", "EMUNAND VIRTUAL", \ "IMGNAND CTRNAND", "IMGNAND TWLN", "IMGNAND TWLP", "IMGNAND VIRTUAL", \ "GAMECART", \ - "GAME IMAGE", "AESKEYDB IMAGE", "TICKET.DB IMAGE", \ + "GAME IMAGE", "AESKEYDB IMAGE", "TICKET.DB IMAGE", "DISA/DIFF IMAGE", \ "MEMORY VIRTUAL", \ "VRAM VIRTUAL", \ "LAST SEARCH" \ #define FS_DRVNUM \ - "0:", "1:", "2:", "3:", "A:", "S:", "4:", "5:", "6:", "B:", "E:", "7:", "8:", "9:", "I:", "C:", "G:", "K:", "T:", "M:", "V:", "Z:" + "0:", "1:", "2:", "3:", "A:", "S:", "4:", "5:", "6:", "B:", "E:", "7:", "8:", "9:", "I:", "C:", "G:", "K:", "T:", "D:", "M:", "V:", "Z:" /** Function to identify the type of a drive **/ int DriveType(const char* path); diff --git a/arm9/source/filesys/fsinit.c b/arm9/source/filesys/fsinit.c index 4082afe..c4bdb19 100644 --- a/arm9/source/filesys/fsinit.c +++ b/arm9/source/filesys/fsinit.c @@ -47,6 +47,8 @@ bool InitImgFS(const char* path) { snprintf(fsname, 7, "%lu:", drv_i); if (!(DriveType(fsname)&DRV_IMAGE)) break; } + // deinit virtual filesystem + DeinitVirtualImageDrive(); // deinit image filesystem DismountDriveType(DRV_IMAGE); // (re)mount image, done if path == NULL diff --git a/arm9/source/godmode.c b/arm9/source/godmode.c index 60fe653..d66ca78 100644 --- a/arm9/source/godmode.c +++ b/arm9/source/godmode.c @@ -1103,7 +1103,6 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan bool transferable = (FTYPE_TRANSFERABLE(filetype) && IS_UNLOCKED && (drvtype & DRV_FAT)); bool hsinjectable = (FTYPE_HASCODE(filetype)); bool extrcodeable = (FTYPE_HASCODE(filetype)); - bool extrdiffable = (FTYPE_ISDISADIFF(filetype)); bool restorable = (FTYPE_RESTORABLE(filetype) && IS_UNLOCKED && !(drvtype & DRV_SYSNAND)); bool ebackupable = (FTYPE_EBACKUP(filetype)); bool ncsdfixable = (FTYPE_NCSDFIXABLE(filetype)); @@ -1128,7 +1127,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 || trimable || transferable || hsinjectable || restorable || xorpadable || ebackupable || ncsdfixable || extrcodeable || extrdiffable || 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 || trimable || transferable || hsinjectable || restorable || xorpadable || ebackupable || ncsdfixable || extrcodeable || keyinitable || keyinstallable || bootable || scriptable || fontable || viewable || installable || agbexportable || agbimportable; char pathstr[32+1]; TruncateString(pathstr, file_path, 32, 8); @@ -1173,7 +1172,8 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan (filetype & SYS_FIRM ) ? "FIRM image options..." : (filetype & SYS_AGBSAVE)? (agbimportable) ? "AGBSAVE options..." : "Dump GBA VC save" : (filetype & SYS_TICKDB) ? "Ticket.db options..." : - (filetype & SYS_DIFF) ? "Extract DIFF data" : + (filetype & SYS_DIFF) ? "Mount as DIFF image" : + (filetype & SYS_DISA) ? "Mount as DISA image" : (filetype & BIN_TIKDB) ? "Titlekey options..." : (filetype & BIN_KEYDB) ? "AESkeydb options..." : (filetype & BIN_LEGKEY) ? "Build " KEYDB_NAME : @@ -1316,7 +1316,6 @@ 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 trim = (trimable) ? ++n_opt : -1; int rename = (renamable) ? ++n_opt : -1; int xorpad = (xorpadable) ? ++n_opt : -1; @@ -1353,7 +1352,6 @@ 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"; @@ -1369,7 +1367,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan user_select = (n_opt <= 1) ? n_opt : (int) ShowSelectPrompt(n_opt, optionstr, (n_marked > 1) ? "%s\n%(%lu files selected)" : "%s", pathstr, n_marked); if (user_select == mount) { // -> mount file as image - const char* mnt_drv_paths[] = { "7:", "G:", "K:", "T:", "I:" }; // maybe move that to fsdrive.h + const char* mnt_drv_paths[] = { "7:", "G:", "K:", "T:", "I:", "D:" }; // maybe move that to fsdrive.h if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE)) clipboard->n_entries = 0; // remove last mounted image clipboard entries InitImgFS((filetype & GAME_TMD) ? cxi_path : file_path); @@ -1741,7 +1739,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan } return 0; } - else if ((user_select == extrcode) || (user_select == extrdiff)) { // -> Extract .code or DIFF partition + else if (user_select == extrcode) { // -> Extract .code if ((n_marked > 1) && ShowPrompt(true, "Try to extract all %lu selected files?", n_marked)) { u32 n_success = 0; u32 n_other = 0; @@ -1756,10 +1754,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan continue; } DrawDirContents(current_dir, (*cursor = i), scroll); - if (filetype & SYS_DIFF) { - if (ExtractDataFromDisaDiff(path) == 0) n_success++; - else continue; - } else if (filetype & GAME_TMD) { + if (filetype & GAME_TMD) { char cxi_pathl[256] = { 0 }; if ((GetTmdContentPath(cxi_pathl, path) == 0) && PathExist(cxi_pathl) && (ExtractCodeFromCxiFile(cxi_pathl, NULL, NULL) == 0)) { @@ -1774,11 +1769,6 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan 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); diff --git a/arm9/source/utils/gameutil.c b/arm9/source/utils/gameutil.c index fdd0e9c..671e6f0 100644 --- a/arm9/source/utils/gameutil.c +++ b/arm9/source/utils/gameutil.c @@ -1825,66 +1825,6 @@ u32 CompressCode(const char* path, const char* path_out) { 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 - DisaDiffRWInfo info; - u8* lvl2_cache = NULL; - if ((GetDisaDiffRWInfo(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; -} - u64 GetGameFileTrimmedSize(const char* path) { u64 filetype = IdentifyFileType(path); u64 trimsize = 0; diff --git a/arm9/source/utils/gameutil.h b/arm9/source/utils/gameutil.h index 5d5bef4..8b1ae72 100644 --- a/arm9/source/utils/gameutil.h +++ b/arm9/source/utils/gameutil.h @@ -9,7 +9,6 @@ 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 CompressCode(const char* path, const char* path_out); -u32 ExtractDataFromDisaDiff(const char* path); u64 GetGameFileTrimmedSize(const char* path); u32 TrimGameFile(const char* path); u32 ShowGameFileTitleInfo(const char* path); diff --git a/arm9/source/virtual/virtual.c b/arm9/source/virtual/virtual.c index 23d474e..c80e2d7 100644 --- a/arm9/source/virtual/virtual.c +++ b/arm9/source/virtual/virtual.c @@ -6,6 +6,7 @@ #include "vkeydb.h" #include "vcart.h" #include "vvram.h" +#include "vdisadiff.h" typedef struct { char drv_letter; @@ -24,11 +25,16 @@ u32 GetVirtualSource(const char* path) { return 0; } -bool InitVirtualImageDrive(void) { +void DeinitVirtualImageDrive(void) { DeinitVGameDrive(); DeinitVTickDbDrive(); DeinitVKeyDbDrive(); - return InitVGameDrive() || InitVTickDbDrive() || InitVKeyDbDrive(); + DeinitVDisaDiffDrive(); +} + +bool InitVirtualImageDrive(void) { + DeinitVirtualImageDrive(); + return InitVGameDrive() || InitVDisaDiffDrive() || InitVKeyDbDrive(); } bool CheckVirtualDrive(const char* path) { @@ -43,6 +49,8 @@ bool CheckVirtualDrive(const char* path) { return CheckVTickDbDrive(); else if (virtual_src & VRT_KEYDB) return CheckVKeyDbDrive(); + else if (virtual_src & VRT_DISADIFF) + return CheckVDisaDiffDrive(); return virtual_src; // this is safe for SysNAND & memory } @@ -63,6 +71,8 @@ bool ReadVirtualDir(VirtualFile* vfile, VirtualDir* vdir) { ret = ReadVCartDir(vfile, vdir); } else if (virtual_src & VRT_VRAM) { ret = ReadVVramDir(vfile, vdir); + } else if (virtual_src & VRT_DISADIFF) { + ret = ReadVDisaDiffDir(vfile, vdir); } vfile->flags |= virtual_src; // add source flag return ret; @@ -171,6 +181,8 @@ int ReadVirtualFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 coun return ReadVCartFile(vfile, buffer, offset, count); } else if (vfile->flags & VRT_VRAM) { return ReadVVramFile(vfile, buffer, offset, count); + } else if (vfile->flags & VRT_DISADIFF) { + return ReadVDisaDiffFile(vfile, buffer, offset, count); } return -1; @@ -190,6 +202,8 @@ int WriteVirtualFile(const VirtualFile* vfile, const void* buffer, u64 offset, u return WriteVNandFile(vfile, buffer, offset, count); } else if (vfile->flags & VRT_MEMORY) { return WriteVMemFile(vfile, buffer, offset, count); + } else if (vfile->flags & VRT_DISADIFF) { + return WriteVDisaDiffFile(vfile, buffer, offset, count); } // no write support for virtual game / tickdb / keydb / cart / vram files return -1; diff --git a/arm9/source/virtual/virtual.h b/arm9/source/virtual/virtual.h index 5829153..fbb85c8 100644 --- a/arm9/source/virtual/virtual.h +++ b/arm9/source/virtual/virtual.h @@ -3,33 +3,34 @@ #include "common.h" #include "nand.h" -#define VRT_SYSNAND NAND_SYSNAND -#define VRT_EMUNAND NAND_EMUNAND -#define VRT_IMGNAND NAND_IMGNAND -#define VRT_XORPAD NAND_ZERONAND -#define VRT_MEMORY (1UL<<4) -#define VRT_GAME (1UL<<5) -#define VRT_TICKDB (1UL<<6) -#define VRT_KEYDB (1UL<<7) -#define VRT_CART (1UL<<8) -#define VRT_VRAM (1UL<<9) +#define VRT_SYSNAND NAND_SYSNAND +#define VRT_EMUNAND NAND_EMUNAND +#define VRT_IMGNAND NAND_IMGNAND +#define VRT_XORPAD NAND_ZERONAND +#define VRT_MEMORY (1UL<<4) +#define VRT_GAME (1UL<<5) +#define VRT_TICKDB (1UL<<6) +#define VRT_KEYDB (1UL<<7) +#define VRT_CART (1UL<<8) +#define VRT_VRAM (1UL<<9) +#define VRT_DISADIFF (1UL<<10) -#define VRT_SOURCE (VRT_SYSNAND|VRT_EMUNAND|VRT_IMGNAND|VRT_XORPAD|VRT_MEMORY|VRT_GAME|VRT_TICKDB|VRT_KEYDB|VRT_CART|VRT_VRAM) +#define VRT_SOURCE (VRT_SYSNAND|VRT_EMUNAND|VRT_IMGNAND|VRT_XORPAD|VRT_MEMORY|VRT_GAME|VRT_TICKDB|VRT_KEYDB|VRT_CART|VRT_VRAM|VRT_DISADIFF) -#define VFLAG_DIR (1UL<<10) -#define VFLAG_ROOT (1UL<<11) -#define VFLAG_READONLY (1UL<<12) -#define VFLAG_DELETABLE (1UL<<13) -#define VFLAG_LV3 (1UL<<14) +#define VFLAG_DIR (1UL<<11) +#define VFLAG_ROOT (1UL<<12) +#define VFLAG_READONLY (1UL<<13) +#define VFLAG_DELETABLE (1UL<<14) +#define VFLAG_LV3 (1UL<<15) #define VRT_DRIVES {'S', VRT_SYSNAND}, {'E', VRT_EMUNAND}, {'I', VRT_IMGNAND}, {'X', VRT_XORPAD }, \ - {'M', VRT_MEMORY}, {'G', VRT_GAME}, {'K', VRT_KEYDB}, {'T', VRT_TICKDB}, {'C', VRT_CART}, {'V', VRT_VRAM} + {'M', VRT_MEMORY}, {'G', VRT_GAME}, {'K', VRT_KEYDB}, {'T', VRT_TICKDB}, {'C', VRT_CART}, {'V', VRT_VRAM}, {'D', VRT_DISADIFF} // virtual file flag (subject to change): // bits 0...3 : reserved for NAND virtual sources and info -// bits 4...9 : reserved for other virtual sources -// bits 10...15: reserved for external flags +// bits 4...10 : reserved for other virtual sources +// bits 11...15: reserved for external flags // bits 16...31: reserved for internal flags (different per source, see vgame.c) typedef struct { char name[32]; @@ -48,6 +49,7 @@ typedef struct { } VirtualDir; u32 GetVirtualSource(const char* path); +void DeinitVirtualImageDrive(void); bool InitVirtualImageDrive(void); bool CheckVirtualDrive(const char* path);