mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Added title info / mount support for DSiWare Exports
This commit is contained in:
parent
fc97df6466
commit
ec861a7bf7
@ -127,10 +127,13 @@ u64 IdentifyFileType(const char* path) {
|
||||
type |= TXT_SCRIPT; // should be a script (which is also generic text)
|
||||
if (fsize < TEMP_BUFFER_SIZE) type |= TXT_GENERIC;
|
||||
return type;
|
||||
} else if ((strncmp(path + 2, "/Nintendo DSiWare/", 18) == 0) &&
|
||||
(sscanf(fname, "%08lx.bin", &id) == 1) && (strncasecmp(ext, "bin", 4) == 0)) {
|
||||
DsiWareExpHeader hdr;
|
||||
if ((FileGetData(path, &hdr, DSIWEXP_HEADER_LEN, DSIWEXP_HEADER_OFFSET) == DSIWEXP_HEADER_LEN) &&
|
||||
(strncmp(hdr.magic, DSIWEXP_HEADER_MAGIC, strlen(DSIWEXP_HEADER_MAGIC)) == 0))
|
||||
return GAME_TAD;
|
||||
} else if ((strnlen(fname, 16) == 8) && (sscanf(fname, "%08lx", &id) == 1)) {
|
||||
if (strncmp(path + 2, "/Nintendo DSiWare/", 18) == 0)
|
||||
return GAME_DSIWE;
|
||||
|
||||
char path_cdn[256];
|
||||
char* name_cdn = path_cdn + (fname - path);
|
||||
strncpy(path_cdn, path, 256);
|
||||
|
@ -17,7 +17,7 @@
|
||||
#define GAME_3DSX (1ULL<<12)
|
||||
#define GAME_NDS (1ULL<<13)
|
||||
#define GAME_GBA (1ULL<<14)
|
||||
#define GAME_DSIWE (1ULL<<15)
|
||||
#define GAME_TAD (1ULL<<15)
|
||||
#define SYS_FIRM (1ULL<<16)
|
||||
#define SYS_AGBSAVE (1ULL<<17)
|
||||
#define SYS_TICKDB (1ULL<<18)
|
||||
@ -38,7 +38,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|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_TICKDB|BIN_KEYDB))
|
||||
#define FYTPE_VERIFICABLE(tp) (tp&(IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD|GAME_BOSS|SYS_FIRM))
|
||||
#define FYTPE_DECRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|GAME_NUSCDN|SYS_FIRM|BIN_KEYDB))
|
||||
#define FYTPE_ENCRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|BIN_KEYDB))
|
||||
@ -47,7 +47,7 @@
|
||||
#define FTYPE_CXIDUMP(tp) (tp&(GAME_TMD))
|
||||
#define FTYPE_TIKBUILD(tp) (tp&(GAME_TICKET|SYS_TICKDB|BIN_TIKDB))
|
||||
#define FTYPE_KEYBUILD(tp) (tp&(BIN_KEYDB|BIN_LEGKEY))
|
||||
#define FTYPE_TITLEINFO(tp) (tp&(GAME_SMDH|GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_TMD|GAME_NDS|GAME_GBA|GAME_3DSX))
|
||||
#define FTYPE_TITLEINFO(tp) (tp&(GAME_SMDH|GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_TMD|GAME_NDS|GAME_GBA|GAME_TAD|GAME_3DSX))
|
||||
#define FTYPE_RENAMABLE(tp) (tp&(GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_NDS|GAME_GBA))
|
||||
#define FTYPE_TRANSFERABLE(tp) ((u64) (tp&(IMG_FAT|FLAG_CTR)) == (u64) (IMG_FAT|FLAG_CTR))
|
||||
#define FTYPE_NCSDFIXABLE(tp) (tp&(HDR_NAND|NOIMG_NAND))
|
||||
|
@ -95,7 +95,8 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
|
||||
(GetMountState() & GAME_EXEFS) ? "EXEFS" :
|
||||
(GetMountState() & GAME_ROMFS) ? "ROMFS" :
|
||||
(GetMountState() & GAME_NDS ) ? "NDS" :
|
||||
(GetMountState() & SYS_FIRM) ? "FIRM" : "UNK", drvname[i]);
|
||||
(GetMountState() & SYS_FIRM ) ? "FIRM" :
|
||||
(GetMountState() & GAME_TAD ) ? "DSIWARE" : "UNK", drvname[i]);
|
||||
else snprintf(entry->path + 4, 32, "[%s] %s", drvnum[i], drvname[i]);
|
||||
entry->name = entry->path + 4;
|
||||
entry->size = GetTotalSpace(entry->path);
|
||||
|
@ -898,6 +898,9 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
|
||||
bool in_output_path = (strncmp(current_path, OUTPUT_PATH, 256) == 0);
|
||||
|
||||
// don't handle TMDs inside the game drive, won't work properly anyways
|
||||
if ((filetype & GAME_TMD) && (drvtype & DRV_GAME)) filetype &= ~GAME_TMD;
|
||||
|
||||
// special stuff, only available for known filetypes (see int special below)
|
||||
bool mountable = (FTYPE_MOUNTABLE(filetype) && !(drvtype & DRV_IMAGE) &&
|
||||
!((drvtype & (DRV_SYSNAND|DRV_EMUNAND)) && (drvtype & DRV_VIRTUAL) && (filetype & IMG_FAT)));
|
||||
@ -975,6 +978,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
(filetype & GAME_NDS) ? "NDS image options..." :
|
||||
(filetype & GAME_GBA) ? "GBA image options..." :
|
||||
(filetype & GAME_TICKET)? "Ticket options..." :
|
||||
(filetype & GAME_TAD) ? "TAD image options..." :
|
||||
(filetype & GAME_3DSX) ? "Show 3DSX title info" :
|
||||
(filetype & SYS_FIRM ) ? "FIRM image options..." :
|
||||
(filetype & SYS_AGBSAVE)? (agbimportable) ? "AGBSAVE options..." : "Dump GBA VC save" :
|
||||
|
@ -1508,6 +1508,20 @@ u32 ShowSmdhTitleInfo(Smdh* smdh) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 ShowTwlIconTitleInfo(TwlIconData* twl_icon) {
|
||||
const u32 lwrap = 24;
|
||||
u8* icon = (u8*) (TEMP_BUFFER + sizeof(TwlIconData));
|
||||
char* desc = (char*) icon + TWLICON_SIZE_ICON;
|
||||
if ((GetTwlIcon(icon, twl_icon) != 0) ||
|
||||
(GetTwlTitle(desc, twl_icon) != 0))
|
||||
return 1;
|
||||
WordWrapString(desc, lwrap);
|
||||
ShowIconString(icon, TWLICON_DIM_ICON, TWLICON_DIM_ICON, "%s", desc);
|
||||
InputWait(0);
|
||||
ClearScreenF(true, false, COLOR_STD_BG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 ShowGbaFileTitleInfo(const char* path) {
|
||||
AgbHeader agb;
|
||||
if ((fvx_qread(path, &agb, 0, sizeof(AgbHeader), NULL) != FR_OK) ||
|
||||
@ -1519,28 +1533,13 @@ u32 ShowGbaFileTitleInfo(const char* path) {
|
||||
|
||||
}
|
||||
|
||||
u32 ShowNdsFileTitleInfo(const char* path) {
|
||||
const u32 lwrap = 24;
|
||||
TwlIconData* twl_icon = (TwlIconData*) TEMP_BUFFER;
|
||||
u8* icon = (u8*) (TEMP_BUFFER + sizeof(TwlIconData));
|
||||
char* desc = (char*) icon + TWLICON_SIZE_ICON;
|
||||
if ((LoadTwlMetaData(path, NULL, twl_icon) != 0) ||
|
||||
(GetTwlIcon(icon, twl_icon) != 0) ||
|
||||
(GetTwlTitle(desc, twl_icon) != 0))
|
||||
return 1;
|
||||
WordWrapString(desc, lwrap);
|
||||
ShowIconString(icon, TWLICON_DIM_ICON, TWLICON_DIM_ICON, "%s", desc);
|
||||
InputWait(0);
|
||||
ClearScreenF(true, false, COLOR_STD_BG);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
u32 ShowGameFileTitleInfo(const char* path) {
|
||||
Smdh* smdh = (Smdh*) (void*) TEMP_BUFFER;
|
||||
TwlIconData* twl_icon = (TwlIconData*) (void*) TEMP_BUFFER;
|
||||
|
||||
char path_content[256];
|
||||
if (IdentifyFileType(path) & GAME_TMD) {
|
||||
u64 itype = IdentifyFileType(path); // initial type
|
||||
if (itype & GAME_TMD) {
|
||||
if (GetTmdContentPath(path_content, path) != 0) return 1;
|
||||
path = path_content;
|
||||
}
|
||||
@ -1548,7 +1547,9 @@ u32 ShowGameFileTitleInfo(const char* path) {
|
||||
// try loading SMDH, then try NDS / GBA
|
||||
if (LoadSmdhFromGameFile(path, smdh) == 0)
|
||||
return ShowSmdhTitleInfo(smdh);
|
||||
else if (ShowNdsFileTitleInfo(path) == 0) return 0;
|
||||
else if ((LoadTwlMetaData(path, NULL, twl_icon) == 0) ||
|
||||
((itype & GAME_TAD) && (fvx_qread(path, twl_icon, DSIWEXP_BANNER_OFFSET, sizeof(TwlIconData), NULL) == FR_OK)))
|
||||
return ShowTwlIconTitleInfo(twl_icon);
|
||||
else return ShowGbaFileTitleInfo(path);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
#include "game.h"
|
||||
#include "aes.h"
|
||||
|
||||
#define VFLAG_NO_CRYPTO (1UL<<19)
|
||||
#define VFLAG_NO_CRYPTO (1UL<<18)
|
||||
#define VFLAG_DSIWARE (1UL<<19)
|
||||
#define VFLAG_CIA_CONTENT (1UL<<20)
|
||||
#define VFLAG_NDS (1UL<<21)
|
||||
#define VFLAG_NITRO_DIR (1UL<<22)
|
||||
@ -16,7 +17,7 @@
|
||||
#define VFLAG_NCCH (1UL<<29)
|
||||
#define VFLAG_EXEFS (1UL<<30)
|
||||
#define VFLAG_ROMFS (1UL<<31)
|
||||
#define VFLAG_GAMEDIR (VFLAG_FIRM|VFLAG_CIA|VFLAG_NCSD|VFLAG_NCCH|VFLAG_EXEFS|VFLAG_ROMFS|VFLAG_LV3|VFLAG_NDS|VFLAG_NITRO_DIR|VFLAG_NITRO)
|
||||
#define VFLAG_GAMEDIR (VFLAG_FIRM|VFLAG_CIA|VFLAG_NCSD|VFLAG_NCCH|VFLAG_EXEFS|VFLAG_ROMFS|VFLAG_LV3|VFLAG_NDS|VFLAG_NITRO_DIR|VFLAG_NITRO|VFLAG_DSIWARE)
|
||||
#define VFLAG_NCCH_CRYPTO (VFLAG_EXEFS_FILE|VFLAG_EXTHDR|VFLAG_EXEFS|VFLAG_ROMFS|VFLAG_LV3|VFLAG_NCCH)
|
||||
|
||||
#define NAME_FIRM_HEADER "header.bin"
|
||||
@ -60,17 +61,28 @@
|
||||
#define NAME_NDS_BANNER "banner.bin"
|
||||
#define NAME_NDS_DATADIR "data"
|
||||
|
||||
#define NAME_DSIWE_BANNER "banner.bin"
|
||||
#define NAME_DSIWE_HEADER "header.bin"
|
||||
#define NAME_DSIWE_FOOTER "footer.bin"
|
||||
#define NAME_DSIWE_TYPES "tmd", "srl", "02.unk", \
|
||||
"03.unk", "04.unk", "05.unk", \
|
||||
"06.unk", "07.unk", "08.unk", \
|
||||
"public.sav", "banner.sav", "11.unk"
|
||||
#define NAME_DSIWE_CONTENT "%016llX.%s" // titleid.type
|
||||
|
||||
|
||||
static u64 vgame_type = 0;
|
||||
static u32 base_vdir = 0;
|
||||
|
||||
static VirtualFile* templates_cia = (VirtualFile*) VGAME_BUFFER; // first 56kb reserved (enough for 1024 entries)
|
||||
static VirtualFile* templates_dsiwe = (VirtualFile*) (VGAME_BUFFER + 0xDC00); // 1kb reserved (enough for 18 entries)
|
||||
static VirtualFile* templates_firm = (VirtualFile*) (VGAME_BUFFER + 0xE000); // 2kb reserved (enough for 36 entries)
|
||||
static VirtualFile* templates_ncsd = (VirtualFile*) (VGAME_BUFFER + 0xE800); // 2kb reserved (enough for 36 entries)
|
||||
static VirtualFile* templates_ncch = (VirtualFile*) (VGAME_BUFFER + 0xF000); // 1kb reserved (enough for 18 entries)
|
||||
static VirtualFile* templates_nds = (VirtualFile*) (VGAME_BUFFER + 0xF400); // 1kb reserved (enough for 18 entries)
|
||||
static VirtualFile* templates_exefs = (VirtualFile*) (VGAME_BUFFER + 0xF800); // 2kb reserved (enough for 36 entries)
|
||||
static int n_templates_cia = -1;
|
||||
static int n_templates_dsiwe = -1;
|
||||
static int n_templates_firm = -1;
|
||||
static int n_templates_ncsd = -1;
|
||||
static int n_templates_ncch = -1;
|
||||
@ -89,6 +101,7 @@ static u64 offset_lv3fd = (u64) -1;
|
||||
static u64 offset_nds = (u64) -1;
|
||||
static u64 offset_nitro = (u64) -1;
|
||||
static u64 offset_ccnt = (u64) -1;
|
||||
static u64 offset_dsiwe = (u64) -1;
|
||||
static u32 index_ccnt = (u32) -1;
|
||||
|
||||
static CiaStub* cia = (CiaStub*) (void*) (VGAME_BUFFER + 0x10000); // 61kB reserved - should be enough by far
|
||||
@ -648,6 +661,64 @@ bool BuildVGameFirmDir(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BuildVGameDsiWareDir(void) {
|
||||
const char* name_type[] = { NAME_DSIWE_TYPES };
|
||||
VirtualFile* templates = templates_dsiwe;
|
||||
u32 content_offset = 0;
|
||||
u32 n = 0;
|
||||
|
||||
// read header, setup table
|
||||
DsiWareExpContentTable tbl;
|
||||
DsiWareExpHeader hdr;
|
||||
ReadGameImageBytes(&hdr, DSIWEXP_HEADER_OFFSET, DSIWEXP_HEADER_LEN);
|
||||
if (BuildDsiWareExportContentTable(&tbl, &hdr) != 0) {
|
||||
n_templates_dsiwe = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// banner
|
||||
strncpy(templates[n].name, NAME_DSIWE_BANNER, 32);
|
||||
templates[n].offset = content_offset;
|
||||
templates[n].size = tbl.banner_end - content_offset - sizeof(DsiWareExpBlockMetaData);
|
||||
templates[n].keyslot = 0xFF;
|
||||
templates[n].flags = 0;
|
||||
content_offset = tbl.banner_end;
|
||||
n++;
|
||||
|
||||
// header
|
||||
strncpy(templates[n].name, NAME_DSIWE_HEADER, 32);
|
||||
templates[n].offset = content_offset;
|
||||
templates[n].size = tbl.header_end - content_offset - sizeof(DsiWareExpBlockMetaData);
|
||||
templates[n].keyslot = 0xFF;
|
||||
templates[n].flags = 0;
|
||||
content_offset = tbl.header_end;
|
||||
n++;
|
||||
|
||||
// footer
|
||||
strncpy(templates[n].name, NAME_DSIWE_FOOTER, 32);
|
||||
templates[n].offset = content_offset;
|
||||
templates[n].size = tbl.footer_end - content_offset - sizeof(DsiWareExpBlockMetaData);
|
||||
templates[n].keyslot = 0xFF;
|
||||
templates[n].flags = 0;
|
||||
content_offset = tbl.footer_end;
|
||||
n++;
|
||||
|
||||
// contents
|
||||
for (u32 i = 0; i < DSIWEXP_NUM_CONTENT; content_offset = tbl.content_end[i++]) {
|
||||
if (!hdr.content_size[i]) continue; // nothing in section
|
||||
// use proper names, fix TMD handling
|
||||
snprintf(templates[n].name, 32, NAME_DSIWE_CONTENT, hdr.title_id, name_type[i]);
|
||||
templates[n].offset = content_offset;
|
||||
templates[n].size = hdr.content_size[i];
|
||||
templates[n].keyslot = 0xFF;
|
||||
templates[n].flags = 0;
|
||||
n++;
|
||||
}
|
||||
|
||||
n_templates_dsiwe = n;
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 InitVGameDrive(void) { // prerequisite: game file mounted as image
|
||||
u64 type = GetMountState();
|
||||
|
||||
@ -671,7 +742,8 @@ u64 InitVGameDrive(void) { // prerequisite: game file mounted as image
|
||||
(type & GAME_NCCH ) ? VFLAG_NCCH :
|
||||
(type & GAME_EXEFS) ? VFLAG_EXEFS :
|
||||
(type & GAME_ROMFS) ? VFLAG_ROMFS :
|
||||
(type & GAME_NDS ) ? VFLAG_NDS : 0;
|
||||
(type & GAME_NDS ) ? VFLAG_NDS :
|
||||
(type & GAME_TAD ) ? VFLAG_DSIWARE : 0;
|
||||
if (!base_vdir) return 0;
|
||||
|
||||
vgame_type = type;
|
||||
@ -718,6 +790,9 @@ bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry) {
|
||||
((SetupArm9BinaryCrypto(a9l)) == 0))
|
||||
offset_a9bin = arm9s->offset + ARM9BIN_OFFSET;
|
||||
if (!BuildVGameFirmDir()) return false;
|
||||
} else if ((vdir->flags & VFLAG_DSIWARE) && (offset_dsiwe != vdir->offset)) {
|
||||
offset_dsiwe = vdir->offset; // always zero(!)
|
||||
if (!BuildVGameDsiWareDir()) return false;
|
||||
} else if ((vdir->flags & VFLAG_CIA) && (offset_cia != vdir->offset)) {
|
||||
CiaInfo info;
|
||||
if ((ReadImageBytes((u8*) cia, 0, 0x20) != 0) ||
|
||||
@ -943,6 +1018,9 @@ bool ReadVGameDir(VirtualFile* vfile, VirtualDir* vdir) {
|
||||
} else if (vdir->flags & VFLAG_NDS) {
|
||||
templates = templates_nds;
|
||||
n = n_templates_nds;
|
||||
} else if (vdir->flags & VFLAG_DSIWARE) {
|
||||
templates = templates_dsiwe;
|
||||
n = n_templates_dsiwe;
|
||||
} else if (vdir->flags & VFLAG_LV3) {
|
||||
return ReadVGameDirLv3(vfile, vdir);
|
||||
} else if (vdir->flags & VFLAG_NITRO) {
|
||||
|
@ -29,8 +29,8 @@
|
||||
// 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...17: reserved for external flags
|
||||
// bits 18...31: reserved for internal flags (different per source, see vgame.c)
|
||||
// bits 10...15: reserved for external flags
|
||||
// bits 16...31: reserved for internal flags (different per source, see vgame.c)
|
||||
typedef struct {
|
||||
char name[32];
|
||||
u64 offset; // must be a multiple of 0x200 (for NAND access)
|
||||
|
Loading…
x
Reference in New Issue
Block a user