mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 21:52:48 +00:00
Enable FIRM file mounting
This commit is contained in:
parent
2986ce3d5c
commit
3ba8c675db
@ -38,7 +38,7 @@
|
|||||||
(((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v))
|
(((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v))
|
||||||
|
|
||||||
// GodMode9 version
|
// GodMode9 version
|
||||||
#define VERSION "0.9.0"
|
#define VERSION "0.9.1"
|
||||||
|
|
||||||
// input / output paths
|
// input / output paths
|
||||||
#define INPUT_PATHS "0:", "0:/files9", "0:/Decrypt9"
|
#define INPUT_PATHS "0:", "0:/files9", "0:/Decrypt9"
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "filetype.h"
|
#include "filetype.h"
|
||||||
#include "fsutil.h"
|
#include "fsutil.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "firm.h"
|
|
||||||
|
|
||||||
u32 IdentifyFileType(const char* path) {
|
u32 IdentifyFileType(const char* path) {
|
||||||
const u8 romfs_magic[] = { ROMFS_MAGIC };
|
const u8 romfs_magic[] = { ROMFS_MAGIC };
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#define SYS_FIRM (1<<8)
|
#define SYS_FIRM (1<<8)
|
||||||
|
|
||||||
#define FTYPE_MOUNTABLE (IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS)
|
#define FTYPE_MOUNTABLE (IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS|SYS_FIRM)
|
||||||
#define FYTPE_VERIFICABLE (GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD|SYS_FIRM)
|
#define FYTPE_VERIFICABLE (GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD|SYS_FIRM)
|
||||||
#define FYTPE_DECRYPTABLE (GAME_CIA|GAME_NCSD|GAME_NCCH|SYS_FIRM)
|
#define FYTPE_DECRYPTABLE (GAME_CIA|GAME_NCSD|GAME_NCCH|SYS_FIRM)
|
||||||
#define FTYPE_BUILDABLE (GAME_NCSD|GAME_NCCH|GAME_TMD)
|
#define FTYPE_BUILDABLE (GAME_NCSD|GAME_NCCH|GAME_TMD)
|
||||||
|
@ -79,7 +79,8 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
|
|||||||
(GetMountState() == GAME_NCSD ) ? "NCSD" :
|
(GetMountState() == GAME_NCSD ) ? "NCSD" :
|
||||||
(GetMountState() == GAME_NCCH ) ? "NCCH" :
|
(GetMountState() == GAME_NCCH ) ? "NCCH" :
|
||||||
(GetMountState() == GAME_EXEFS) ? "EXEFS" :
|
(GetMountState() == GAME_EXEFS) ? "EXEFS" :
|
||||||
(GetMountState() == GAME_ROMFS) ? "ROMFS" : "UNK", drvname[pdrv]);
|
(GetMountState() == GAME_ROMFS) ? "ROMFS" :
|
||||||
|
(GetMountState() == SYS_FIRM) ? "FIRM" : "UNK", drvname[pdrv]);
|
||||||
else snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], drvname[pdrv]);
|
else snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], drvname[pdrv]);
|
||||||
entry->name = entry->path + 4;
|
entry->name = entry->path + 4;
|
||||||
entry->size = GetTotalSpace(entry->path);
|
entry->size = GetTotalSpace(entry->path);
|
||||||
|
@ -44,8 +44,11 @@ typedef struct {
|
|||||||
|
|
||||||
u32 ValidateFirmHeader(FirmHeader* header);
|
u32 ValidateFirmHeader(FirmHeader* header);
|
||||||
u32 ValidateFirmA9LHeader(FirmA9LHeader* header);
|
u32 ValidateFirmA9LHeader(FirmA9LHeader* header);
|
||||||
FirmSectionHeader* FindFirmArm9Section(FirmHeader* firm);
|
|
||||||
|
|
||||||
|
FirmSectionHeader* FindFirmArm9Section(FirmHeader* firm);
|
||||||
|
u32 GetArm9BinarySize(FirmA9LHeader* a9l);
|
||||||
|
|
||||||
|
u32 SetupArm9BinaryCrypto(FirmA9LHeader* header);
|
||||||
u32 DecryptA9LHeader(FirmA9LHeader* header);
|
u32 DecryptA9LHeader(FirmA9LHeader* header);
|
||||||
u32 DecryptFirm(u8* data, u32 offset, u32 size, FirmHeader* firm, FirmA9LHeader* a9l);
|
u32 DecryptFirm(u8* data, u32 offset, u32 size, FirmHeader* firm, FirmA9LHeader* a9l);
|
||||||
u32 DecryptArm9Binary(u8* data, u32 offset, u32 size, FirmA9LHeader* a9l);
|
u32 DecryptArm9Binary(u8* data, u32 offset, u32 size, FirmA9LHeader* a9l);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "cia.h"
|
#include "cia.h"
|
||||||
#include "ncsd.h"
|
#include "ncsd.h"
|
||||||
#include "ncch.h"
|
#include "ncch.h"
|
||||||
#include "exefs.h"
|
#include "exefs.h"
|
||||||
#include "romfs.h"
|
#include "romfs.h"
|
||||||
|
#include "firm.h"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "gameutil.h"
|
#include "gameutil.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "firm.h"
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "fsperm.h"
|
#include "fsperm.h"
|
||||||
#include "filetype.h"
|
#include "filetype.h"
|
||||||
|
@ -111,7 +111,7 @@ bool InitNandCrypto(void)
|
|||||||
ReadNandSectors(header, 0x58980 + (offsetSection2 / 0x200), 1, 0x06, NAND_SYSNAND);
|
ReadNandSectors(header, 0x58980 + (offsetSection2 / 0x200), 1, 0x06, NAND_SYSNAND);
|
||||||
memcpy(keyY, header + 0x10, 0x10); // 0x15 keyY
|
memcpy(keyY, header + 0x10, 0x10); // 0x15 keyY
|
||||||
|
|
||||||
// try FRIM90 & FIRM81 offsets, search for the key
|
// try FIRM90 & FIRM81 offsets, search for the key
|
||||||
for (u32 fver = 0; fver < 2; fver++) {
|
for (u32 fver = 0; fver < 2; fver++) {
|
||||||
static u32 offset0x05KeyY[2] = { 0x0EB014, 0x0EB24C };
|
static u32 offset0x05KeyY[2] = { 0x0EB014, 0x0EB24C };
|
||||||
u32 offset = offset0x05KeyY[fver];
|
u32 offset = offset0x05KeyY[fver];
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
|
|
||||||
|
#define VFLAG_FIRM_ARM9 (1<<23)
|
||||||
|
#define VFLAG_FIRM (1<<24)
|
||||||
#define VFLAG_EXEFS_FILE (1<<25)
|
#define VFLAG_EXEFS_FILE (1<<25)
|
||||||
#define VFLAG_EXTHDR (1<<26)
|
#define VFLAG_EXTHDR (1<<26)
|
||||||
#define VFLAG_CIA (1<<27)
|
#define VFLAG_CIA (1<<27)
|
||||||
@ -10,9 +12,12 @@
|
|||||||
#define VFLAG_NCCH (1<<29)
|
#define VFLAG_NCCH (1<<29)
|
||||||
#define VFLAG_EXEFS (1<<30)
|
#define VFLAG_EXEFS (1<<30)
|
||||||
#define VFLAG_ROMFS (1<<31)
|
#define VFLAG_ROMFS (1<<31)
|
||||||
#define VFLAG_GAMEDIR (VFLAG_CIA|VFLAG_NCSD|VFLAG_NCCH|VFLAG_EXEFS|VFLAG_ROMFS|VFLAG_LV3)
|
#define VFLAG_GAMEDIR (VFLAG_FIRM|VFLAG_CIA|VFLAG_NCSD|VFLAG_NCCH|VFLAG_EXEFS|VFLAG_ROMFS|VFLAG_LV3)
|
||||||
|
|
||||||
#define MAX_N_TEMPLATES 2048 // this leaves us with enough room (128kB reserved)
|
#define NAME_FIRM_HEADER "header.bin"
|
||||||
|
#define NAME_FIRM_ARM9BIN "arm9dec.bin"
|
||||||
|
#define NAME_FIRM_SECTION "section%lu.%s.bin" // number.arm9/.arm11
|
||||||
|
#define NAME_FIRM_NCCH "%016llX.%.8s%s" // name.title_id(.ext)
|
||||||
|
|
||||||
#define NAME_CIA_HEADER "header.bin"
|
#define NAME_CIA_HEADER "header.bin"
|
||||||
#define NAME_CIA_CERT "cert.bin"
|
#define NAME_CIA_CERT "cert.bin"
|
||||||
@ -43,15 +48,19 @@
|
|||||||
static u32 vgame_type = 0;
|
static u32 vgame_type = 0;
|
||||||
static u32 base_vdir = 0;
|
static u32 base_vdir = 0;
|
||||||
|
|
||||||
static VirtualFile* templates_cia = (VirtualFile*) VGAME_BUFFER; // first 52kb reserved (enough for 950 entries)
|
static VirtualFile* templates_cia = (VirtualFile*) VGAME_BUFFER; // first 56kb reserved (enough for 1024 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_ncsd = (VirtualFile*) (VGAME_BUFFER + 0xE800); // 2kb reserved (enough for 36 entries)
|
||||||
static VirtualFile* templates_ncch = (VirtualFile*) (VGAME_BUFFER + 0xF000); // 2kb reserved (enough for 36 entries)
|
static VirtualFile* templates_ncch = (VirtualFile*) (VGAME_BUFFER + 0xF000); // 2kb reserved (enough for 36 entries)
|
||||||
static VirtualFile* templates_exefs = (VirtualFile*) (VGAME_BUFFER + 0xF800); // 2kb reserved (enough for 36 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_cia = -1;
|
||||||
|
static int n_templates_firm = -1;
|
||||||
static int n_templates_ncsd = -1;
|
static int n_templates_ncsd = -1;
|
||||||
static int n_templates_ncch = -1;
|
static int n_templates_ncch = -1;
|
||||||
static int n_templates_exefs = -1;
|
static int n_templates_exefs = -1;
|
||||||
|
|
||||||
|
static u64 offset_firm = (u64) -1;
|
||||||
|
static u64 offset_a9bin = (u64) -1;
|
||||||
static u64 offset_cia = (u64) -1;
|
static u64 offset_cia = (u64) -1;
|
||||||
static u64 offset_ncsd = (u64) -1;
|
static u64 offset_ncsd = (u64) -1;
|
||||||
static u64 offset_ncch = (u64) -1;
|
static u64 offset_ncch = (u64) -1;
|
||||||
@ -60,13 +69,32 @@ static u64 offset_romfs = (u64) -1;
|
|||||||
static u64 offset_lv3 = (u64) -1;
|
static u64 offset_lv3 = (u64) -1;
|
||||||
static u64 offset_lv3fd = (u64) -1;
|
static u64 offset_lv3fd = (u64) -1;
|
||||||
|
|
||||||
static CiaStub* cia = (CiaStub*) (void*) (VGAME_BUFFER + 0x10000); // 62.5kB reserved - should be enough by far
|
static CiaStub* cia = (CiaStub*) (void*) (VGAME_BUFFER + 0x10000); // 61.5kB reserved - should be enough by far
|
||||||
|
static FirmA9LHeader* a9l = (FirmA9LHeader*) (void*) (VGAME_BUFFER + 0x1F600); // 512 byte reserved
|
||||||
|
static FirmHeader* firm = (FirmHeader*) (void*) (VGAME_BUFFER + 0x1F800); // 512 byte reserved
|
||||||
static NcsdHeader* ncsd = (NcsdHeader*) (void*) (VGAME_BUFFER + 0x1FA00); // 512 byte reserved
|
static NcsdHeader* ncsd = (NcsdHeader*) (void*) (VGAME_BUFFER + 0x1FA00); // 512 byte reserved
|
||||||
static NcchHeader* ncch = (NcchHeader*) (void*) (VGAME_BUFFER + 0x1FC00); // 512 byte reserved
|
static NcchHeader* ncch = (NcchHeader*) (void*) (VGAME_BUFFER + 0x1FC00); // 512 byte reserved
|
||||||
static ExeFsHeader* exefs = (ExeFsHeader*) (void*) (VGAME_BUFFER + 0x1FE00); // 512 byte reserved
|
static ExeFsHeader* exefs = (ExeFsHeader*) (void*) (VGAME_BUFFER + 0x1FE00); // 512 byte reserved
|
||||||
static u8* romfslv3 = (u8*) (VGAME_BUFFER + 0x20000); // 1920kB reserved
|
static u8* romfslv3 = (u8*) (VGAME_BUFFER + 0x20000); // 1920kB reserved
|
||||||
static RomFsLv3Index lv3idx;
|
static RomFsLv3Index lv3idx;
|
||||||
|
|
||||||
|
int ReadFirmImageBytes(u8* buffer, u64 offset, u64 count) {
|
||||||
|
int ret = ReadImageBytes(buffer, offset, count);
|
||||||
|
if ((offset_a9bin == (u64) -1) || (ret != 0)) return ret;
|
||||||
|
if (DecryptFirm(buffer, offset, count, firm, a9l) != 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadNcchImageBytes(u8* buffer, u64 offset, u64 count) {
|
||||||
|
int ret = (offset_a9bin == (u64) - 1) ? ReadImageBytes(buffer, offset, count) :
|
||||||
|
ReadFirmImageBytes(buffer, offset, count);
|
||||||
|
if ((offset_ncch == (u64) -1) || (ret != 0)) return ret;
|
||||||
|
if (NCCH_ENCRYPTED(ncch) && (DecryptNcch(buffer, offset - offset_ncch, count, ncch,
|
||||||
|
(offset_exefs == (u64) -1) ? NULL : exefs) != 0)) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool BuildVGameExeFsDir(void) {
|
bool BuildVGameExeFsDir(void) {
|
||||||
VirtualFile* templates = templates_exefs;
|
VirtualFile* templates = templates_exefs;
|
||||||
u32 n = 0;
|
u32 n = 0;
|
||||||
@ -221,7 +249,7 @@ bool BuildVGameNcsdDir(void) {
|
|||||||
n_templates_ncsd = n;
|
n_templates_ncsd = n;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#include "ui.h"
|
|
||||||
bool BuildVGameCiaDir(void) {
|
bool BuildVGameCiaDir(void) {
|
||||||
CiaInfo info;
|
CiaInfo info;
|
||||||
VirtualFile* templates = templates_cia;
|
VirtualFile* templates = templates_cia;
|
||||||
@ -323,10 +351,100 @@ bool BuildVGameCiaDir(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BuildVGameFirmDir(void) {
|
||||||
|
VirtualFile* templates = templates_firm;
|
||||||
|
u32 n = 0;
|
||||||
|
|
||||||
|
// header
|
||||||
|
strncpy(templates[n].name, NAME_FIRM_HEADER, 32);
|
||||||
|
templates[n].offset = 0;
|
||||||
|
templates[n].size = 0x200;
|
||||||
|
templates[n].keyslot = 0xFF;
|
||||||
|
templates[n].flags = 0;
|
||||||
|
n++;
|
||||||
|
|
||||||
|
// arm9 binary (only for encrypted)
|
||||||
|
if (offset_a9bin != (u64) -1) {
|
||||||
|
strncpy(templates[n].name, NAME_FIRM_ARM9BIN, 32);
|
||||||
|
templates[n].offset = offset_a9bin;
|
||||||
|
templates[n].size = GetArm9BinarySize(a9l);
|
||||||
|
templates[n].keyslot = 0x15;
|
||||||
|
templates[n].flags = VFLAG_FIRM_ARM9;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// section binaries & NCCHs
|
||||||
|
for (u32 i = 0; i < 4; i++) {
|
||||||
|
FirmSectionHeader* section = firm->sections + i;
|
||||||
|
if (!section->size) continue;
|
||||||
|
snprintf(templates[n].name, 32, NAME_FIRM_SECTION, i, (section->type == 0) ? "arm9" : "arm11");
|
||||||
|
templates[n].offset = section->offset;
|
||||||
|
templates[n].size = section->size;
|
||||||
|
templates[n].keyslot = 0xFF;
|
||||||
|
templates[n].flags = 0;
|
||||||
|
n++;
|
||||||
|
if (section->type == 0) { // ARM9 section, search for Process9
|
||||||
|
u8* buffer = (u8*) (TEMP_BUFFER + (TEMP_BUFFER_SIZE/2));
|
||||||
|
u32 buffer_size = TEMP_BUFFER_SIZE/4;
|
||||||
|
NcchHeader* p9_ncch;
|
||||||
|
char name[8];
|
||||||
|
u32 offset_p9 = 0;
|
||||||
|
for (u32 p = 0; (p < section->size) && (!offset_p9); p += buffer_size) {
|
||||||
|
u32 btr = min(buffer_size, (section->size - p));
|
||||||
|
if (ReadFirmImageBytes(buffer, section->offset + p, btr) != 0) break;
|
||||||
|
for (u32 s = 0; (s < btr) && (!offset_p9); s += 0x10) {
|
||||||
|
p9_ncch = (NcchHeader*) (void*) (buffer + s);
|
||||||
|
if ((ValidateNcchHeader(p9_ncch) == 0) &&
|
||||||
|
(ReadFirmImageBytes((u8*) name, section->offset + p + s + 0x200, 8) == 0))
|
||||||
|
offset_p9 = section->offset + p + s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_p9) {
|
||||||
|
snprintf(templates[n].name, 32, NAME_FIRM_NCCH, p9_ncch->programId, name, ".app");
|
||||||
|
templates[n].offset = offset_p9;
|
||||||
|
templates[n].size = p9_ncch->size * NCCH_MEDIA_UNIT;
|
||||||
|
templates[n].keyslot = (offset_a9bin == (u64) -1) ? 0xFF : 0x15;
|
||||||
|
templates[n].flags = VFLAG_NCCH;
|
||||||
|
n++;
|
||||||
|
memcpy(templates + n, templates + n - 1, sizeof(VirtualFile));
|
||||||
|
snprintf(templates[n].name, 32, NAME_FIRM_NCCH, p9_ncch->programId, name, "");
|
||||||
|
templates[n].flags |= VFLAG_DIR;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
} else if (section->type == 1) { // ARM11 section, search for modules
|
||||||
|
NcchHeader firm_ncch;
|
||||||
|
for (u32 p = 0; p < section->size; p += firm_ncch.size * NCCH_MEDIA_UNIT) {
|
||||||
|
char name[8];
|
||||||
|
if ((ReadImageBytes((u8*) &firm_ncch, section->offset + p, 0x200) != 0) ||
|
||||||
|
(ReadImageBytes((u8*) name, section->offset + p + 0x200, 0x8) != 0) ||
|
||||||
|
(ValidateNcchHeader(&firm_ncch) != 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
snprintf(templates[n].name, 32, NAME_FIRM_NCCH, firm_ncch.programId, name, ".app");
|
||||||
|
templates[n].offset = section->offset + p;
|
||||||
|
templates[n].size = firm_ncch.size * NCCH_MEDIA_UNIT;
|
||||||
|
templates[n].keyslot = 0xFF;
|
||||||
|
templates[n].flags = VFLAG_NCCH;
|
||||||
|
n++;
|
||||||
|
memcpy(templates + n, templates + n - 1, sizeof(VirtualFile));
|
||||||
|
snprintf(templates[n].name, 32, NAME_FIRM_NCCH, firm_ncch.programId, name, "");
|
||||||
|
templates[n].flags |= VFLAG_DIR;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n_templates_firm = n;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
u32 InitVGameDrive(void) { // prerequisite: game file mounted as image
|
u32 InitVGameDrive(void) { // prerequisite: game file mounted as image
|
||||||
u32 type = GetMountState();
|
u32 type = GetMountState();
|
||||||
|
|
||||||
vgame_type = 0;
|
vgame_type = 0;
|
||||||
|
offset_firm = (u64) -1;
|
||||||
|
offset_a9bin = (u64) -1;
|
||||||
offset_cia = (u64) -1;
|
offset_cia = (u64) -1;
|
||||||
offset_ncsd = (u64) -1;
|
offset_ncsd = (u64) -1;
|
||||||
offset_ncch = (u64) -1;
|
offset_ncch = (u64) -1;
|
||||||
@ -336,6 +454,7 @@ u32 InitVGameDrive(void) { // prerequisite: game file mounted as image
|
|||||||
offset_lv3fd = (u64) -1;
|
offset_lv3fd = (u64) -1;
|
||||||
|
|
||||||
base_vdir =
|
base_vdir =
|
||||||
|
(type == SYS_FIRM ) ? VFLAG_FIRM :
|
||||||
(type == GAME_CIA ) ? VFLAG_CIA :
|
(type == GAME_CIA ) ? VFLAG_CIA :
|
||||||
(type == GAME_NCSD ) ? VFLAG_NCSD :
|
(type == GAME_NCSD ) ? VFLAG_NCSD :
|
||||||
(type == GAME_NCCH ) ? VFLAG_NCCH :
|
(type == GAME_NCCH ) ? VFLAG_NCCH :
|
||||||
@ -352,14 +471,6 @@ u32 CheckVGameDrive(void) {
|
|||||||
return vgame_type;
|
return vgame_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadNcchImageBytes(u8* buffer, u64 offset, u64 count) {
|
|
||||||
int ret = ReadImageBytes(buffer, offset, count);
|
|
||||||
if ((offset_ncch == (u64) -1) || (ret != 0)) return ret;
|
|
||||||
if (NCCH_ENCRYPTED(ncch) && (DecryptNcch(buffer, offset - offset_ncch, count, ncch,
|
|
||||||
(offset_exefs == (u64) -1) ? NULL : exefs) != 0)) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry) {
|
bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry) {
|
||||||
// build vdir object
|
// build vdir object
|
||||||
vdir->index = -1;
|
vdir->index = -1;
|
||||||
@ -376,7 +487,17 @@ bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build directories where required
|
// build directories where required
|
||||||
if ((vdir->flags & VFLAG_CIA) && (offset_cia != vdir->offset)) {
|
if ((vdir->flags & VFLAG_FIRM) && (offset_firm != vdir->offset)) {
|
||||||
|
if ((ReadImageBytes((u8*) firm, 0, sizeof(FirmHeader)) != 0) ||
|
||||||
|
(ValidateFirmHeader(firm) != 0)) return false;
|
||||||
|
offset_firm = vdir->offset;
|
||||||
|
FirmSectionHeader* arm9s = FindFirmArm9Section(firm);
|
||||||
|
if (arm9s && (ReadImageBytes((u8*) a9l, arm9s->offset, sizeof(FirmA9LHeader)) == 0) &&
|
||||||
|
(ValidateFirmA9LHeader(a9l) == 0) &&
|
||||||
|
(SetupArm9BinaryCrypto(a9l)))
|
||||||
|
offset_a9bin = arm9s->offset + ARM9BIN_OFFSET;
|
||||||
|
if (!BuildVGameFirmDir()) return false;
|
||||||
|
} if ((vdir->flags & VFLAG_CIA) && (offset_cia != vdir->offset)) {
|
||||||
CiaInfo info;
|
CiaInfo info;
|
||||||
if ((ReadImageBytes((u8*) cia, 0, 0x20) != 0) ||
|
if ((ReadImageBytes((u8*) cia, 0, 0x20) != 0) ||
|
||||||
(ValidateCiaHeader(&(cia->header)) != 0) ||
|
(ValidateCiaHeader(&(cia->header)) != 0) ||
|
||||||
@ -388,11 +509,12 @@ bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry) {
|
|||||||
} else if ((vdir->flags & VFLAG_NCSD) && (offset_ncsd != vdir->offset)) {
|
} else if ((vdir->flags & VFLAG_NCSD) && (offset_ncsd != vdir->offset)) {
|
||||||
if ((ReadImageBytes((u8*) ncsd, 0, sizeof(NcsdHeader)) != 0) ||
|
if ((ReadImageBytes((u8*) ncsd, 0, sizeof(NcsdHeader)) != 0) ||
|
||||||
(ValidateNcsdHeader(ncsd) != 0))
|
(ValidateNcsdHeader(ncsd) != 0))
|
||||||
return 0;
|
return false;
|
||||||
offset_ncsd = vdir->offset; // always zero(!)
|
offset_ncsd = vdir->offset; // always zero(!)
|
||||||
if (!BuildVGameNcsdDir()) return 0;
|
if (!BuildVGameNcsdDir()) return false;
|
||||||
} else if ((vdir->flags & VFLAG_NCCH) && (offset_ncch != vdir->offset)) {
|
} else if ((vdir->flags & VFLAG_NCCH) && (offset_ncch != vdir->offset)) {
|
||||||
if ((ReadImageBytes((u8*) ncch, vdir->offset, sizeof(NcchHeader)) != 0) ||
|
offset_ncch = (u64) -1;
|
||||||
|
if ((ReadNcchImageBytes((u8*) ncch, vdir->offset, sizeof(NcchHeader)) != 0) ||
|
||||||
(ValidateNcchHeader(ncch) != 0))
|
(ValidateNcchHeader(ncch) != 0))
|
||||||
return false;
|
return false;
|
||||||
offset_ncch = vdir->offset;
|
offset_ncch = vdir->offset;
|
||||||
@ -523,7 +645,10 @@ bool ReadVGameDir(VirtualFile* vfile, VirtualDir* vdir) {
|
|||||||
VirtualFile* templates;
|
VirtualFile* templates;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
if (vdir->flags & VFLAG_CIA) {
|
if (vdir->flags & VFLAG_FIRM) {
|
||||||
|
templates = templates_firm;
|
||||||
|
n = n_templates_firm;
|
||||||
|
} else if (vdir->flags & VFLAG_CIA) {
|
||||||
templates = templates_cia;
|
templates = templates_cia;
|
||||||
n = n_templates_cia;
|
n = n_templates_cia;
|
||||||
} else if (vdir->flags & VFLAG_NCSD) {
|
} else if (vdir->flags & VFLAG_NCSD) {
|
||||||
@ -556,9 +681,10 @@ int ReadVGameFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count) {
|
|||||||
lv3file = LV3_GET_FILE(vfile->offset, &lv3idx);
|
lv3file = LV3_GET_FILE(vfile->offset, &lv3idx);
|
||||||
vfoffset = offset_lv3fd + lv3file->offset_data;
|
vfoffset = offset_lv3fd + lv3file->offset_data;
|
||||||
}
|
}
|
||||||
if ((vfile->keyslot < 0x40) && (offset_ncch != (u64) -1) && NCCH_ENCRYPTED(ncch) &&
|
if (vfile->flags & (VFLAG_EXEFS_FILE|VFLAG_EXTHDR|VFLAG_EXEFS|VFLAG_ROMFS|VFLAG_LV3|VFLAG_NCCH))
|
||||||
(vfile->flags & (VFLAG_EXEFS_FILE|VFLAG_EXTHDR|VFLAG_EXEFS|VFLAG_ROMFS|VFLAG_LV3|VFLAG_NCCH)))
|
|
||||||
return ReadNcchImageBytes(buffer, vfoffset + offset, count);
|
return ReadNcchImageBytes(buffer, vfoffset + offset, count);
|
||||||
|
else if (vfile->flags & VFLAG_FIRM_ARM9)
|
||||||
|
return ReadFirmImageBytes(buffer, vfoffset + offset, count);
|
||||||
else return ReadImageBytes(buffer, vfoffset + offset, count);
|
else return ReadImageBytes(buffer, vfoffset + offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
// virtual file flag (subject to change):
|
// virtual file flag (subject to change):
|
||||||
// bits 0...9 : reserved for NAND virtual sources and info
|
// bits 0...9 : reserved for NAND virtual sources and info
|
||||||
// bits 10...15: reserved for other virtual sources
|
// bits 10...15: reserved for other virtual sources
|
||||||
// bits 16...23: reserved for external flags
|
// bits 16...21: reserved for external flags
|
||||||
// bits 24...31: reserved for internal flags (different per source)
|
// bits 22...31: reserved for internal flags (different per source)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char name[32];
|
char name[32];
|
||||||
u64 offset; // must be a multiple of 0x200 (for NAND access)
|
u64 offset; // must be a multiple of 0x200 (for NAND access)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user