diff --git a/README.md b/README.md index bf3e080..f92961a 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,10 @@ This tool would not have been possible without the help of numerous people. Than * **Archshift**, for providing the base project infrastructure * **Normmatt**, for sdmmc.c / sdmmc.h * **Cha(N)**, **Kane49**, and all other FatFS contributors for FatFS -* **b1l1s**, for helping me figure out A9LH compatibility +* **SciResM** for helping me figure out RomFS +* **b1l1s** for helping me figure out A9LH compatibility * **Gelex** and **AuroraWright** for helping me figure out various things * **dark_samus** for the new 6x10 font and help on various things -* **Al3x_10m**, **Supster131** and all other fearless testers +* **Al3x_10m**, **Supster131**, **imanoob**, **Kasher_CS** and all other fearless testers * The fine folks on **freenode #Cakey** * Everyone I possibly forgot, if you think you deserve to be mentioned, just contact me! \ No newline at end of file diff --git a/source/common.h b/source/common.h index b7b1e85..28c9664 100644 --- a/source/common.h +++ b/source/common.h @@ -38,7 +38,7 @@ (((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v)) // GodMode9 version -#define VERSION "0.8.4" +#define VERSION "0.8.5" // input / output paths #define INPUT_PATHS "0:", "0:/files9", "0:/Decrypt9" diff --git a/source/filetype.c b/source/filetype.c index c224ac0..87bfbe9 100644 --- a/source/filetype.c +++ b/source/filetype.c @@ -5,6 +5,8 @@ u32 IdentifyFileType(const char* path) { u8 header[0x200] __attribute__((aligned(32))); // minimum required size + const u8 romfs_magic[] = { ROMFS_MAGIC }; + FIL file; if (fx_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) return 0; @@ -46,6 +48,10 @@ u32 IdentifyFileType(const char* path) { NcchHeader* ncch = (NcchHeader*) (void*) header; if (fsize >= (ncch->size * NCCH_MEDIA_UNIT)) return GAME_NCCH; // NCSD (".3DS") file + } else if (ValidateExeFsHeader((ExeFsHeader*) (void*) header, fsize) == 0) { + return GAME_EXEFS; // ExeFS file + } else if (memcmp(header, romfs_magic, sizeof(romfs_magic)) == 0) { + return GAME_ROMFS; // RomFS file (check could be better) } else if (strncmp(CIA_TMD_ISSUER, (char*) (header + 0x140), 0x40) == 0) { if (fsize >= CIA_TMD_SIZE_N(getbe16(header + 0x1DE))) return GAME_TMD; // TMD file diff --git a/source/filetype.h b/source/filetype.h index e8af134..9af1288 100644 --- a/source/filetype.h +++ b/source/filetype.h @@ -9,10 +9,10 @@ #define GAME_NCSD (1<<3) #define GAME_NCCH (1<<4) #define GAME_TMD (1<<5) -// #define GAME_EXEFS (1<<6) -// #define GAME_ROMFS (1<<7) +#define GAME_EXEFS (1<<6) +#define GAME_ROMFS (1<<7) -#define FTYPE_MOUNTABLE (IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH) +#define FTYPE_MOUNTABLE (IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS) #define FYTPE_VERIFICABLE (GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD) u32 IdentifyFileType(const char* path); diff --git a/source/fs.c b/source/fs.c index e736f76..042c722 100644 --- a/source/fs.c +++ b/source/fs.c @@ -1187,9 +1187,11 @@ bool GetRootDirContentsWorker(DirStruct* contents) { (GetMountState() == IMG_FAT) ? "FAT IMAGE" : "RAMDRIVE"); else if (pdrv == 10) // Game drive special handling snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[pdrv], - (GetMountState() == GAME_CIA) ? "CIA" : - (GetMountState() == GAME_NCSD) ? "NCSD" : - (GetMountState() == GAME_NCCH) ? "NCCH" : "UNK", drvname[pdrv]); + (GetMountState() == GAME_CIA ) ? "CIA" : + (GetMountState() == GAME_NCSD ) ? "NCSD" : + (GetMountState() == GAME_NCCH ) ? "NCCH" : + (GetMountState() == GAME_EXEFS) ? "EXEFS" : + (GetMountState() == GAME_ROMFS) ? "ROMFS" : "UNK", drvname[pdrv]); else snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], drvname[pdrv]); entry->name = entry->path + 4; entry->size = GetTotalSpace(entry->path); diff --git a/source/game/exefs.c b/source/game/exefs.c index 0a5e09f..27cd67b 100644 --- a/source/game/exefs.c +++ b/source/game/exefs.c @@ -1,16 +1,19 @@ #include "exefs.h" u32 ValidateExeFsHeader(ExeFsHeader* exefs, u32 size) { + u8 zeroes[32] = { 0 }; u32 data_size = 0; + u32 n_files = 0; for (u32 i = 0; i < 10; i++) { ExeFsFileHeader* file = exefs->files + i; - if ((file->offset == 0) && (file->size == 0)) - continue; - if (file->offset < data_size) - return 1; // overlapping data, failed + u8* hash = exefs->hashes[9 - i]; + if (file->size == 0) continue; + if (file->offset < data_size) return 1; // overlapping data, failed + if (memcmp(hash, zeroes, 32) == 0) return 1; // hash not set, failed data_size = file->offset + file->size; + n_files++; } if (size && (data_size > (size - sizeof(ExeFsHeader)))) // exefs header not included in table return 1; - return 0; + return (n_files) ? 0 : 1; } diff --git a/source/godmode.c b/source/godmode.c index 2ad79a2..b1ebbe8 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -692,11 +692,13 @@ u32 GodMode() { if (verificable > 0) optionstr[verificable-1] = "Verify game image"; if (injectable > 0) optionstr[injectable-1] = "Inject data @offset"; if (mountable > 0) optionstr[mountable-1] = - (filetype == IMG_NAND) ? "Mount as NAND image" : - (filetype == IMG_FAT) ? "Mount as FAT image" : - (filetype == GAME_CIA) ? "Mount as CIA image" : - (filetype == GAME_NCSD) ? "Mount as NCSD image" : - (filetype == GAME_NCCH) ? "Mount as NCCH image" : "???"; + (filetype == IMG_NAND ) ? "Mount as NAND image" : + (filetype == IMG_FAT ) ? "Mount as FAT image" : + (filetype == GAME_CIA ) ? "Mount as CIA image" : + (filetype == GAME_NCSD ) ? "Mount as NCSD image" : + (filetype == GAME_NCCH ) ? "Mount as NCCH image" : + (filetype == GAME_EXEFS) ? "Mount as EXEFS image" : + (filetype == GAME_ROMFS) ? "Mount as ROMFS image" : "???"; if (searchdrv > 0) optionstr[searchdrv-1] = "Open containing folder"; int user_select = 0; diff --git a/source/virtual/vgame.c b/source/virtual/vgame.c index ef624f1..7c64fa5 100644 --- a/source/virtual/vgame.c +++ b/source/virtual/vgame.c @@ -78,7 +78,8 @@ bool BuildVGameExeFsDir(void) { snprintf(templates[n].name, 32, "%.8s", file->name); templates[n].offset = offset_exefs + sizeof(ExeFsHeader) + file->offset; templates[n].size = file->size; - templates[n].keyslot = NCCH_ENCRYPTED(ncch) ? 0x2C : 0xFF; // actual keyslot may be different + templates[n].keyslot = ((offset_ncch != (u64) -1) && NCCH_ENCRYPTED(ncch)) ? + 0x2C : 0xFF; // actual keyslot may be different templates[n].flags = VFLAG_EXEFS_FILE; n++; } @@ -335,7 +336,12 @@ u32 InitVGameDrive(void) { // prerequisite: game file mounted as image offset_lv3 = (u64) -1; offset_lv3fd = (u64) -1; - base_vdir = (type == GAME_CIA) ? VFLAG_CIA : (type == GAME_NCSD) ? VFLAG_NCSD : (type == GAME_NCCH) ? VFLAG_NCCH : 0; + base_vdir = + (type == GAME_CIA ) ? VFLAG_CIA : + (type == GAME_NCSD ) ? VFLAG_NCSD : + (type == GAME_NCCH ) ? VFLAG_NCCH : + (type == GAME_EXEFS) ? VFLAG_EXEFS : + (type == GAME_ROMFS) ? VFLAG_ROMFS : 0; if (!base_vdir) return 0; vgame_type = type; @@ -446,7 +452,8 @@ bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry) { bool ReadVGameDirLv3(VirtualFile* vfile, VirtualDir* vdir) { BuildLv3Index(&lv3idx, romfslv3); vfile->flags = VFLAG_LV3; - vfile->keyslot = NCCH_ENCRYPTED(ncch) ? 0x2C : 0xFF; // actual keyslot may be different + vfile->keyslot = ((offset_ncch != (u64) -1) && NCCH_ENCRYPTED(ncch)) ? + 0x2C : 0xFF; // actual keyslot may be different // start from parent dir object if (vdir->index == -1) vdir->index = 0; @@ -551,7 +558,7 @@ int ReadVGameFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count) { lv3file = LV3_GET_FILE(vfile->offset, &lv3idx); vfoffset = offset_lv3fd + lv3file->offset_data; } - if (NCCH_ENCRYPTED(ncch) && (vfile->keyslot < 0x40) && + if ((vfile->keyslot < 0x40) && (offset_ncch != (u64) -1) && NCCH_ENCRYPTED(ncch) && (vfile->flags & (VFLAG_EXEFS_FILE|VFLAG_EXTHDR|VFLAG_EXEFS|VFLAG_ROMFS|VFLAG_LV3|VFLAG_NCCH))) return ReadNcchImageBytes(buffer, vfoffset + offset, count); else return ReadImageBytes(buffer, vfoffset + offset, count); @@ -560,7 +567,8 @@ int ReadVGameFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count) { bool FindVirtualFileInLv3Dir(VirtualFile* vfile, const VirtualDir* vdir, const char* name) { vfile->name[0] = '\0'; vfile->flags = vdir->flags & ~VFLAG_DIR; - vfile->keyslot = NCCH_ENCRYPTED(ncch) ? 0x2C : 0xFF; // actual keyslot may be different + vfile->keyslot = ((offset_ncch != (u64) -1) && NCCH_ENCRYPTED(ncch)) ? + 0x2C : 0xFF; // actual keyslot may be different RomFsLv3DirMeta* lv3dir = GetLv3DirMeta(name, vdir->offset, &lv3idx); if (lv3dir) {