implement vdisadiff

This commit is contained in:
aspargas2 2019-09-21 10:37:14 -04:00 committed by d0k3
parent 1026a60597
commit f8b9332728
10 changed files with 53 additions and 104 deletions

View File

@ -13,7 +13,7 @@
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 diff_magic[] = { DIFF_MAGIC };
// const u8 disa_magic[] = { DISA_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 };
@ -98,6 +98,8 @@ u64 IdentifyFileType(const char* path) {
if (memcmp(header + 0x100, tickdb_magic, sizeof(tickdb_magic)) == 0) // ticket.db file if (memcmp(header + 0x100, tickdb_magic, sizeof(tickdb_magic)) == 0) // ticket.db file
return SYS_DIFF | SYS_TICKDB; // ticket.db return SYS_DIFF | SYS_TICKDB; // ticket.db
return SYS_DIFF; 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) { } 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

@ -21,7 +21,7 @@
#define GAME_TAD (1ULL<<16) #define GAME_TAD (1ULL<<16)
#define SYS_FIRM (1ULL<<17) #define SYS_FIRM (1ULL<<17)
#define SYS_DIFF (1ULL<<18) #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_AGBSAVE (1ULL<<20)
#define SYS_TICKDB (1ULL<<21) #define SYS_TICKDB (1ULL<<21)
#define BIN_NCCHNFO (1ULL<<22) #define BIN_NCCHNFO (1ULL<<22)
@ -44,7 +44,7 @@
#define FLAG_NUSCDN (1ULL<<62) #define FLAG_NUSCDN (1ULL<<62)
#define FLAG_CXI (1ULL<<63) #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_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_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)) #define FTYPE_ENCRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|BIN_KEYDB))

View File

@ -46,7 +46,7 @@ int DriveType(const char* path) {
type = DRV_VIRTUAL | DRV_SYSNAND; type = DRV_VIRTUAL | DRV_SYSNAND;
} else if (vsrc == VRT_EMUNAND) { } else if (vsrc == VRT_EMUNAND) {
type = DRV_VIRTUAL | DRV_EMUNAND; type = DRV_VIRTUAL | DRV_EMUNAND;
} else if (vsrc == VRT_IMGNAND) { } else if ((vsrc == VRT_IMGNAND) || (vsrc == VRT_DISADIFF)) {
type = DRV_VIRTUAL | DRV_IMAGE; type = DRV_VIRTUAL | DRV_IMAGE;
} else if (vsrc == VRT_XORPAD) { } else if (vsrc == VRT_XORPAD) {
type = DRV_VIRTUAL | DRV_XORPAD; type = DRV_VIRTUAL | DRV_XORPAD;

View File

@ -37,13 +37,13 @@
"EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP", "EMUNAND SD", "EMUNAND VIRTUAL", \ "EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP", "EMUNAND SD", "EMUNAND VIRTUAL", \
"IMGNAND CTRNAND", "IMGNAND TWLN", "IMGNAND TWLP", "IMGNAND VIRTUAL", \ "IMGNAND CTRNAND", "IMGNAND TWLN", "IMGNAND TWLP", "IMGNAND VIRTUAL", \
"GAMECART", \ "GAMECART", \
"GAME IMAGE", "AESKEYDB IMAGE", "TICKET.DB IMAGE", \ "GAME IMAGE", "AESKEYDB IMAGE", "TICKET.DB IMAGE", "DISA/DIFF IMAGE", \
"MEMORY VIRTUAL", \ "MEMORY VIRTUAL", \
"VRAM VIRTUAL", \ "VRAM VIRTUAL", \
"LAST SEARCH" \ "LAST SEARCH" \
#define FS_DRVNUM \ #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 **/ /** Function to identify the type of a drive **/
int DriveType(const char* path); int DriveType(const char* path);

View File

@ -47,6 +47,8 @@ bool InitImgFS(const char* path) {
snprintf(fsname, 7, "%lu:", drv_i); snprintf(fsname, 7, "%lu:", drv_i);
if (!(DriveType(fsname)&DRV_IMAGE)) break; if (!(DriveType(fsname)&DRV_IMAGE)) break;
} }
// deinit virtual filesystem
DeinitVirtualImageDrive();
// deinit image filesystem // deinit image filesystem
DismountDriveType(DRV_IMAGE); DismountDriveType(DRV_IMAGE);
// (re)mount image, done if path == NULL // (re)mount image, done if path == NULL

View File

@ -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 transferable = (FTYPE_TRANSFERABLE(filetype) && IS_UNLOCKED && (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_UNLOCKED && !(drvtype & DRV_SYSNAND)); bool restorable = (FTYPE_RESTORABLE(filetype) && IS_UNLOCKED && !(drvtype & DRV_SYSNAND));
bool ebackupable = (FTYPE_EBACKUP(filetype)); bool ebackupable = (FTYPE_EBACKUP(filetype));
bool ncsdfixable = (FTYPE_NCSDFIXABLE(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)); 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]; char pathstr[32+1];
TruncateString(pathstr, file_path, 32, 8); 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_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) ? "Ticket.db options..." : (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_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 :
@ -1316,7 +1316,6 @@ 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 trim = (trimable) ? ++n_opt : -1; int trim = (trimable) ? ++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;
@ -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 > 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";
@ -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) ? user_select = (n_opt <= 1) ? n_opt : (int) ShowSelectPrompt(n_opt, optionstr, (n_marked > 1) ?
"%s\n%(%lu files selected)" : "%s", pathstr, n_marked); "%s\n%(%lu files selected)" : "%s", pathstr, n_marked);
if (user_select == mount) { // -> mount file as image 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)) if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE))
clipboard->n_entries = 0; // remove last mounted image clipboard entries clipboard->n_entries = 0; // remove last mounted image clipboard entries
InitImgFS((filetype & GAME_TMD) ? cxi_path : file_path); 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; 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)) { 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;
@ -1756,10 +1754,7 @@ 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 & SYS_DIFF) { if (filetype & GAME_TMD) {
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)) {
@ -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", 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

@ -1825,66 +1825,6 @@ u32 CompressCode(const char* path, const char* path_out) {
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
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 GetGameFileTrimmedSize(const char* path) {
u64 filetype = IdentifyFileType(path); u64 filetype = IdentifyFileType(path);
u64 trimsize = 0; u64 trimsize = 0;

View File

@ -9,7 +9,6 @@ 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 CompressCode(const char* path, const char* path_out); u32 CompressCode(const char* path, const char* path_out);
u32 ExtractDataFromDisaDiff(const char* path);
u64 GetGameFileTrimmedSize(const char* path); u64 GetGameFileTrimmedSize(const char* path);
u32 TrimGameFile(const char* path); u32 TrimGameFile(const char* path);
u32 ShowGameFileTitleInfo(const char* path); u32 ShowGameFileTitleInfo(const char* path);

View File

@ -6,6 +6,7 @@
#include "vkeydb.h" #include "vkeydb.h"
#include "vcart.h" #include "vcart.h"
#include "vvram.h" #include "vvram.h"
#include "vdisadiff.h"
typedef struct { typedef struct {
char drv_letter; char drv_letter;
@ -24,11 +25,16 @@ u32 GetVirtualSource(const char* path) {
return 0; return 0;
} }
bool InitVirtualImageDrive(void) { void DeinitVirtualImageDrive(void) {
DeinitVGameDrive(); DeinitVGameDrive();
DeinitVTickDbDrive(); DeinitVTickDbDrive();
DeinitVKeyDbDrive(); DeinitVKeyDbDrive();
return InitVGameDrive() || InitVTickDbDrive() || InitVKeyDbDrive(); DeinitVDisaDiffDrive();
}
bool InitVirtualImageDrive(void) {
DeinitVirtualImageDrive();
return InitVGameDrive() || InitVDisaDiffDrive() || InitVKeyDbDrive();
} }
bool CheckVirtualDrive(const char* path) { bool CheckVirtualDrive(const char* path) {
@ -43,6 +49,8 @@ bool CheckVirtualDrive(const char* path) {
return CheckVTickDbDrive(); return CheckVTickDbDrive();
else if (virtual_src & VRT_KEYDB) else if (virtual_src & VRT_KEYDB)
return CheckVKeyDbDrive(); return CheckVKeyDbDrive();
else if (virtual_src & VRT_DISADIFF)
return CheckVDisaDiffDrive();
return virtual_src; // this is safe for SysNAND & memory return virtual_src; // this is safe for SysNAND & memory
} }
@ -63,6 +71,8 @@ bool ReadVirtualDir(VirtualFile* vfile, VirtualDir* vdir) {
ret = ReadVCartDir(vfile, vdir); ret = ReadVCartDir(vfile, vdir);
} else if (virtual_src & VRT_VRAM) { } else if (virtual_src & VRT_VRAM) {
ret = ReadVVramDir(vfile, vdir); ret = ReadVVramDir(vfile, vdir);
} else if (virtual_src & VRT_DISADIFF) {
ret = ReadVDisaDiffDir(vfile, vdir);
} }
vfile->flags |= virtual_src; // add source flag vfile->flags |= virtual_src; // add source flag
return ret; return ret;
@ -171,6 +181,8 @@ int ReadVirtualFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 coun
return ReadVCartFile(vfile, buffer, offset, count); return ReadVCartFile(vfile, buffer, offset, count);
} else if (vfile->flags & VRT_VRAM) { } else if (vfile->flags & VRT_VRAM) {
return ReadVVramFile(vfile, buffer, offset, count); return ReadVVramFile(vfile, buffer, offset, count);
} else if (vfile->flags & VRT_DISADIFF) {
return ReadVDisaDiffFile(vfile, buffer, offset, count);
} }
return -1; return -1;
@ -190,6 +202,8 @@ int WriteVirtualFile(const VirtualFile* vfile, const void* buffer, u64 offset, u
return WriteVNandFile(vfile, buffer, offset, count); return WriteVNandFile(vfile, buffer, offset, count);
} else if (vfile->flags & VRT_MEMORY) { } else if (vfile->flags & VRT_MEMORY) {
return WriteVMemFile(vfile, buffer, offset, count); 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 } // no write support for virtual game / tickdb / keydb / cart / vram files
return -1; return -1;

View File

@ -3,33 +3,34 @@
#include "common.h" #include "common.h"
#include "nand.h" #include "nand.h"
#define VRT_SYSNAND NAND_SYSNAND #define VRT_SYSNAND NAND_SYSNAND
#define VRT_EMUNAND NAND_EMUNAND #define VRT_EMUNAND NAND_EMUNAND
#define VRT_IMGNAND NAND_IMGNAND #define VRT_IMGNAND NAND_IMGNAND
#define VRT_XORPAD NAND_ZERONAND #define VRT_XORPAD NAND_ZERONAND
#define VRT_MEMORY (1UL<<4) #define VRT_MEMORY (1UL<<4)
#define VRT_GAME (1UL<<5) #define VRT_GAME (1UL<<5)
#define VRT_TICKDB (1UL<<6) #define VRT_TICKDB (1UL<<6)
#define VRT_KEYDB (1UL<<7) #define VRT_KEYDB (1UL<<7)
#define VRT_CART (1UL<<8) #define VRT_CART (1UL<<8)
#define VRT_VRAM (1UL<<9) #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_DIR (1UL<<11)
#define VFLAG_ROOT (1UL<<11) #define VFLAG_ROOT (1UL<<12)
#define VFLAG_READONLY (1UL<<12) #define VFLAG_READONLY (1UL<<13)
#define VFLAG_DELETABLE (1UL<<13) #define VFLAG_DELETABLE (1UL<<14)
#define VFLAG_LV3 (1UL<<14) #define VFLAG_LV3 (1UL<<15)
#define VRT_DRIVES {'S', VRT_SYSNAND}, {'E', VRT_EMUNAND}, {'I', VRT_IMGNAND}, {'X', VRT_XORPAD }, \ #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): // virtual file flag (subject to change):
// bits 0...3 : reserved for NAND virtual sources and info // bits 0...3 : reserved for NAND virtual sources and info
// bits 4...9 : reserved for other virtual sources // bits 4...10 : reserved for other virtual sources
// bits 10...15: reserved for external flags // bits 11...15: reserved for external flags
// bits 16...31: reserved for internal flags (different per source, see vgame.c) // bits 16...31: reserved for internal flags (different per source, see vgame.c)
typedef struct { typedef struct {
char name[32]; char name[32];
@ -48,6 +49,7 @@ typedef struct {
} VirtualDir; } VirtualDir;
u32 GetVirtualSource(const char* path); u32 GetVirtualSource(const char* path);
void DeinitVirtualImageDrive(void);
bool InitVirtualImageDrive(void); bool InitVirtualImageDrive(void);
bool CheckVirtualDrive(const char* path); bool CheckVirtualDrive(const char* path);