mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
Added ability to build seeddb.bin
... plus new entry in HOME more... menu
This commit is contained in:
parent
1c14730f8f
commit
89b6946789
@ -53,51 +53,13 @@ u32 GetArm9BinarySize(FirmA9LHeader* a9l) {
|
||||
}
|
||||
|
||||
u32 SetupSecretKey(u32 keynum) {
|
||||
const char* base[] = { INPUT_PATHS };
|
||||
// from: https://github.com/AuroraWright/SafeA9LHInstaller/blob/master/source/installer.c#L9-L17
|
||||
const u8 sectorHash[0x20] = {
|
||||
0x82, 0xF2, 0x73, 0x0D, 0x2C, 0x2D, 0xA3, 0xF3, 0x01, 0x65, 0xF9, 0x87, 0xFD, 0xCC, 0xAC, 0x5C,
|
||||
0xBA, 0xB2, 0x4B, 0x4E, 0x5F, 0x65, 0xC9, 0x81, 0xCD, 0x7B, 0xE6, 0xF4, 0x38, 0xE6, 0xD9, 0xD3
|
||||
};
|
||||
static u8 __attribute__((aligned(32))) sector[0x200];
|
||||
u8 hash[0x20];
|
||||
|
||||
// safety check
|
||||
if (keynum >= 0x200/0x10) return 1;
|
||||
|
||||
// secret sector already loaded?
|
||||
sha_quick(hash, sector, 0x200, SHA256_MODE);
|
||||
if (memcmp(hash, sectorHash, 0x20) == 0) {
|
||||
setup_aeskey(0x11, sector + (keynum*0x10));
|
||||
use_aeskey(0x11);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// search for valid secret sector in SysNAND / EmuNAND
|
||||
const u32 nand_src[] = { NAND_SYSNAND, NAND_EMUNAND };
|
||||
for (u32 i = 0; i < sizeof(nand_src) / sizeof(u32); i++) {
|
||||
ReadNandSectors(sector, 0x96, 1, 0x11, nand_src[i]);
|
||||
sha_quick(hash, sector, 0x200, SHA256_MODE);
|
||||
if (memcmp(hash, sectorHash, 0x20) != 0) continue;
|
||||
setup_aeskey(0x11, sector + (keynum*0x10));
|
||||
use_aeskey(0x11);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no luck? try searching for a file
|
||||
for (u32 i = 0; i < (sizeof(base)/sizeof(char*)); i++) {
|
||||
char path[64];
|
||||
FIL fp;
|
||||
UINT btr;
|
||||
snprintf(path, 64, "%s/%s", base[i], SECTOR_NAME);
|
||||
if (f_open(&fp, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) {
|
||||
snprintf(path, 64, "%s/%s", base[i], SECRET_NAME);
|
||||
if (f_open(&fp, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) continue;
|
||||
}
|
||||
f_read(&fp, sector, 0x200, &btr);
|
||||
f_close(&fp);
|
||||
sha_quick(hash, sector, 0x200, SHA256_MODE);
|
||||
if (memcmp(hash, sectorHash, 0x20) != 0) continue;
|
||||
// seach for secret sector data...
|
||||
if (GetLegitSector0x96(sector) == 0) {
|
||||
setup_aeskey(0x11, sector + (keynum*0x10));
|
||||
use_aeskey(0x11);
|
||||
return 0;
|
||||
|
@ -4,9 +4,6 @@
|
||||
|
||||
#define FIRM_MAGIC 'F', 'I', 'R', 'M'
|
||||
|
||||
#define SECTOR_NAME "sector0x96.bin"
|
||||
#define SECRET_NAME "secret_sector.bin"
|
||||
|
||||
#define FIRM_MAX_SIZE 0x400000 // 4MB, due to FIRM partition size
|
||||
#define ARM11NCCH_OFFSET 0, 0x2A000, 0x2B000, 0x2C000
|
||||
#define ARM9BIN_OFFSET 0x800
|
||||
|
@ -1729,3 +1729,78 @@ u32 BuildTitleKeyInfo(const char* path, bool dec, bool dump) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 BuildSeedInfo(const char* path, bool dump) {
|
||||
SeedInfo* seed_info = (SeedInfo*) MAIN_BUFFER;
|
||||
const char* path_out = OUTPUT_PATH "/" SEEDDB_NAME;
|
||||
const char* path_in = path;
|
||||
u32 inputtype = 0; // 0 -> none, 1 -> seeddb.bin, 2 -> seed system save
|
||||
UINT br;
|
||||
|
||||
if (!path_in && !dump) { // no input path given - initialize
|
||||
memset(seed_info, 0, 16);
|
||||
if ((fvx_stat(path_out, NULL) == FR_OK) &&
|
||||
(ShowPrompt(true, "%s\nOutput file already exists.\nUpdate this?", path_out))) {
|
||||
path_in = path_out;
|
||||
inputtype = 1;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
char path_str[128];
|
||||
if (path_in && (strnlen(path_in, 16) == 2)) { // when only a drive is given...
|
||||
// grab the key Y from movable.sed
|
||||
u8 movable_keyy[16];
|
||||
snprintf(path_str, 128, "%s/private/movable.sed", path_in);
|
||||
if ((fvx_qread(path_str, movable_keyy, 0x110, 0x10, &br) != FR_OK) || (br != 0x10))
|
||||
return 1;
|
||||
// build the seed save path
|
||||
u32 sha256sum[8];
|
||||
sha_quick(sha256sum, movable_keyy, 0x10, SHA256_MODE);
|
||||
snprintf(path_str, 128, "%s/data/%08lX%08lX%08lX%08lX/sysdata/0001000F/00000000",
|
||||
path_in, sha256sum[0], sha256sum[1], sha256sum[2], sha256sum[3]);
|
||||
path_in = path_str;
|
||||
inputtype = 2;
|
||||
}
|
||||
|
||||
if (inputtype == 1) { // seeddb.bin input
|
||||
SeedInfo* seed_info_merge = (SeedInfo*) TEMP_BUFFER;
|
||||
if ((fvx_qread(path_in, seed_info_merge, 0, TEMP_BUFFER_SIZE, &br) != FR_OK) ||
|
||||
(SEEDDB_SIZE(seed_info_merge) != br)) return 1;
|
||||
// merge and rebuild SeedInfo
|
||||
u32 n_entries = seed_info_merge->n_entries;
|
||||
SeedInfoEntry* seed = seed_info_merge->entries;
|
||||
for (u32 i = 0; i < n_entries; i++, seed++) {
|
||||
if (SEEDDB_SIZE(seed_info) + 32 > MAIN_BUFFER_SIZE) return 1;
|
||||
AddSeedToDb(seed_info, seed); // ignore result
|
||||
}
|
||||
} else if (inputtype == 2) { // seed system save input
|
||||
static const u32 seed_offset[2] = {SEEDSAVE_AREA_OFFSETS};
|
||||
u8* seedsave = (u8*) TEMP_BUFFER;
|
||||
if ((fvx_qread(path_in, seedsave, 0, 0x200, &br) != FR_OK) || (br != 0x200))
|
||||
return 1;
|
||||
u32 p_active = (getle32(seedsave + 0x168)) ? 1 : 0;
|
||||
for (u32 p = 0; p < 2; p++) {
|
||||
SeedInfoEntry seed = { 0 };
|
||||
if ((fvx_qread(path_in, seedsave, seed_offset[(p + p_active) % 2], SEEDSAVE_MAX_ENTRIES*(8+16), &br) != FR_OK) ||
|
||||
(br != SEEDSAVE_MAX_ENTRIES*(8+16)))
|
||||
return 1;
|
||||
for (u32 s = 0; s < SEEDSAVE_MAX_ENTRIES; s++) {
|
||||
seed.titleId = getle64(seedsave + (s*8));
|
||||
memcpy(seed.seed, seedsave + (SEEDSAVE_MAX_ENTRIES*8) + (s*16), 16);
|
||||
if (((seed.titleId >> 32) != 0x00040000) ||
|
||||
(!getle64(seed.seed) && !getle64(seed.seed + 8))) continue;
|
||||
if (SEEDDB_SIZE(seed_info) + 32 > MAIN_BUFFER_SIZE) return 1;
|
||||
AddSeedToDb(seed_info, &seed); // ignore result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dump) {
|
||||
u32 dump_size = SEEDDB_SIZE(seed_info);
|
||||
f_unlink(path_out);
|
||||
if ((dump_size <= 16) || (fvx_qwrite(path_out, seed_info, 0, dump_size, &br) != FR_OK) || (br != dump_size))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -11,3 +11,4 @@ u32 BuildNcchInfoXorpads(const char* destdir, const char* path);
|
||||
u32 CheckHealthAndSafetyInject(const char* hsdrv);
|
||||
u32 InjectHealthAndSafety(const char* path, const char* destdrv);
|
||||
u32 BuildTitleKeyInfo(const char* path, bool dec, bool dump);
|
||||
u32 BuildSeedInfo(const char* path, bool dump);
|
||||
|
@ -4,21 +4,8 @@
|
||||
#include "sha.h"
|
||||
#include "ff.h"
|
||||
|
||||
#define SEEDDB_NAME "seeddb.bin"
|
||||
#define EXEFS_KEYID(name) (((strncmp(name, "banner", 8) == 0) || (strncmp(name, "icon", 8) == 0)) ? 0 : 1)
|
||||
|
||||
typedef struct {
|
||||
u64 titleId;
|
||||
u8 seed[16];
|
||||
u8 reserved[8];
|
||||
} __attribute__((packed)) SeedInfoEntry;
|
||||
|
||||
typedef struct {
|
||||
u32 n_entries;
|
||||
u8 padding[12];
|
||||
SeedInfoEntry entries[256]; // this number is only a placeholder
|
||||
} __attribute__((packed)) SeedInfo;
|
||||
|
||||
u32 ValidateNcchHeader(NcchHeader* header) {
|
||||
if (memcmp(header->magic, "NCCH", 4) != 0) // check magic number
|
||||
return 1;
|
||||
@ -102,14 +89,13 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
|
||||
continue;
|
||||
f_read(&file, seedsave, 0x200, &btr);
|
||||
u32 p_active = (getle32(seedsave + 0x168)) ? 1 : 0;
|
||||
static const u32 seed_offset[2] = {0x7000, 0x5C000};
|
||||
static const u32 seed_offset[2] = {SEEDSAVE_AREA_OFFSETS};
|
||||
for (u32 p = 0; p < 2; p++) {
|
||||
f_lseek(&file, seed_offset[(p + p_active) % 2]);
|
||||
f_read(&file, seedsave, 2000*(8+16), &btr);
|
||||
for (u32 s = 0; s < 2000; s++) {
|
||||
if (titleId != getle64(seedsave + (s*8)))
|
||||
continue;
|
||||
memcpy(lseed, seedsave + (2000*8) + (s*16), 16);
|
||||
f_read(&file, seedsave, SEEDSAVE_MAX_ENTRIES*(8+16), &btr);
|
||||
for (u32 s = 0; s < SEEDSAVE_MAX_ENTRIES; s++) {
|
||||
if (titleId != getle64(seedsave + (s*8))) continue;
|
||||
memcpy(lseed, seedsave + (SEEDSAVE_MAX_ENTRIES*8) + (s*16), 16);
|
||||
sha_quick(sha256sum, lseed, 16 + 8, SHA256_MODE);
|
||||
if (hash_seed == sha256sum[0]) {
|
||||
memcpy(seed, lseed, 16);
|
||||
@ -148,6 +134,22 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 AddSeedToDb(SeedInfo* seed_info, SeedInfoEntry* seed_entry) {
|
||||
if (!seed_entry) { // no seed entry -> reset database
|
||||
memset(seed_info, 0, 16);
|
||||
return 0;
|
||||
}
|
||||
// check if entry already in DB
|
||||
u32 n_entries = seed_info->n_entries;
|
||||
SeedInfoEntry* seed = seed_info->entries;
|
||||
for (u32 i = 0; i < n_entries; i++, seed++)
|
||||
if (seed->titleId == seed_entry->titleId) return 0;
|
||||
// actually a new seed entry
|
||||
memcpy(seed, seed_entry, sizeof(SeedInfoEntry));
|
||||
seed_info->n_entries++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 SetNcchKey(NcchHeader* ncch, u16 crypto, u32 keyid) {
|
||||
u8 flags3 = (crypto >> 8) & 0xFF;
|
||||
u8 flags7 = crypto & 0xFF;
|
||||
|
@ -15,6 +15,12 @@
|
||||
#define NCCH_STDCRYPTO 0x0000
|
||||
#define NCCH_GET_CRYPTO(ncch) (!NCCH_ENCRYPTED(ncch) ? NCCH_NOCRYPTO : (((ncch)->flags[3] << 8) | ((ncch)->flags[7]&(0x01|0x20))))
|
||||
|
||||
#define SEEDDB_NAME "seeddb.bin"
|
||||
#define SEEDDB_SIZE(sdb) (16 + ((sdb)->n_entries * sizeof(SeedInfoEntry)))
|
||||
|
||||
#define SEEDSAVE_AREA_OFFSETS 0x7000, 0x5C000
|
||||
#define SEEDSAVE_MAX_ENTRIES 2000
|
||||
|
||||
// wrapper defines
|
||||
#define DecryptNcch(data, offset, size, ncch, exefs) CryptNcch(data, offset, size, ncch, exefs, NCCH_NOCRYPTO)
|
||||
#define EncryptNcch(data, offset, size, ncch, exefs, crypto) CryptNcch(data, offset, size, ncch, exefs, crypto)
|
||||
@ -70,9 +76,23 @@ typedef struct {
|
||||
u8 hash_romfs[0x20];
|
||||
} __attribute__((packed, aligned(16))) NcchHeader;
|
||||
|
||||
typedef struct {
|
||||
u64 titleId;
|
||||
u8 seed[16];
|
||||
u8 reserved[8];
|
||||
} __attribute__((packed)) SeedInfoEntry;
|
||||
|
||||
typedef struct {
|
||||
u32 n_entries;
|
||||
u8 padding[12];
|
||||
SeedInfoEntry entries[256]; // this number is only a placeholder
|
||||
} __attribute__((packed)) SeedInfo;
|
||||
|
||||
u32 ValidateNcchHeader(NcchHeader* header);
|
||||
u32 SetNcchKey(NcchHeader* ncch, u16 crypto, u32 keyid);
|
||||
u32 SetupNcchCrypto(NcchHeader* ncch, u16 crypt_to);
|
||||
u32 CryptNcch(u8* data, u32 offset, u32 size, NcchHeader* ncch, ExeFsHeader* exefs, u16 crypto);
|
||||
u32 CryptNcchSequential(u8* data, u32 offset, u32 size, u16 crypto);
|
||||
u32 SetNcchSdFlag(u8* data);
|
||||
|
||||
u32 AddSeedToDb(SeedInfo* seed_info, SeedInfoEntry* seed_entry);
|
||||
|
@ -1120,12 +1120,14 @@ u32 HomeMoreMenu(char* current_path, DirStruct* current_dir, DirStruct* clipboar
|
||||
int sdformat = ++n_opt;
|
||||
int bonus = (GetNandUnusedSectors(NAND_SYSNAND) > 0x2000) ? (int) ++n_opt : -1; // 4MB minsize
|
||||
int multi = (CheckMultiEmuNand()) ? (int) ++n_opt : -1;
|
||||
int bsupport = ++n_opt;
|
||||
int hsrestore = ((CheckHealthAndSafetyInject("1:") == 0) || (CheckHealthAndSafetyInject("4:") == 0)) ? (int) ++n_opt : -1;
|
||||
int nandbak = ++n_opt;
|
||||
|
||||
if (sdformat > 0) optionstr[sdformat - 1] = "SD format menu";
|
||||
if (bonus > 0) optionstr[bonus - 1] = "Bonus drive setup";
|
||||
if (multi > 0) optionstr[multi - 1] = "Switch EmuNAND";
|
||||
if (bsupport > 0) optionstr[bsupport - 1] = "Build support files";
|
||||
if (hsrestore > 0) optionstr[hsrestore - 1] = "Restore H&S";
|
||||
if (nandbak > 0) optionstr[nandbak - 1] = "Backup NAND";
|
||||
|
||||
@ -1162,6 +1164,48 @@ u32 HomeMoreMenu(char* current_path, DirStruct* current_dir, DirStruct* clipboar
|
||||
}
|
||||
GetDirContents(current_dir, current_path);
|
||||
return 0;
|
||||
} else if (user_select == bsupport) { // build support files
|
||||
bool tik_enc_sys = false;
|
||||
bool tik_enc_emu = false;
|
||||
if (BuildTitleKeyInfo(NULL, false, false) == 0) {
|
||||
ShowString("Building " TIKDB_NAME_ENC "...");
|
||||
tik_enc_sys = (BuildTitleKeyInfo("1:/dbs/ticket.db", false, false) == 0);
|
||||
tik_enc_emu = (BuildTitleKeyInfo("4:/dbs/ticket.db", false, false) == 0);
|
||||
if (BuildTitleKeyInfo(NULL, false, true) != 0)
|
||||
tik_enc_sys = tik_enc_emu = false;
|
||||
}
|
||||
bool tik_dec_sys = false;
|
||||
bool tik_dec_emu = false;
|
||||
if (BuildTitleKeyInfo(NULL, true, false) == 0) {
|
||||
ShowString("Building " TIKDB_NAME_DEC "...");
|
||||
tik_dec_sys = (BuildTitleKeyInfo("1:/dbs/ticket.db", true, false) == 0);
|
||||
tik_dec_emu = (BuildTitleKeyInfo("4:/dbs/ticket.db", true, false) == 0);
|
||||
if (!tik_dec_sys || BuildTitleKeyInfo(NULL, true, true) != 0)
|
||||
tik_dec_sys = tik_dec_emu = false;
|
||||
}
|
||||
bool seed_sys = false;
|
||||
bool seed_emu = false;
|
||||
if (BuildSeedInfo(NULL, false) == 0) {
|
||||
ShowString("Building " SEEDDB_NAME "...");
|
||||
seed_sys = (BuildSeedInfo("1:", false) == 0);
|
||||
seed_emu = (BuildSeedInfo("4:", false) == 0);
|
||||
if (!seed_sys || BuildSeedInfo(NULL, true) != 0)
|
||||
seed_sys = seed_emu = false;
|
||||
}
|
||||
bool lsector = false;
|
||||
u8 legit_sector[0x200];
|
||||
if (GetLegitSector0x96(legit_sector) == 0) {
|
||||
ShowString("Searching secret sector...");
|
||||
const char* path_sector = OUTPUT_PATH "/" SECRET_NAME;
|
||||
lsector = FileSetData(path_sector, legit_sector, 0x200, 0, true);
|
||||
}
|
||||
ShowPrompt(false, "Built in " OUTPUT_PATH ":\n \n%18.18-s %s\n%18.18-s %s\n%18.18-s %s\n%18.18-s %s",
|
||||
TIKDB_NAME_ENC, tik_enc_sys ? tik_enc_emu ? "OK (Sys&Emu)" : "OK (Sys)" : "Failed",
|
||||
TIKDB_NAME_DEC, tik_dec_sys ? tik_dec_emu ? "OK (Sys&Emu)" : "OK (Sys)" : "Failed",
|
||||
SEEDDB_NAME, seed_sys ? seed_emu ? "OK (Sys&Emu)" : "OK (Sys)" : "Failed",
|
||||
SECRET_NAME, lsector ? "OK (legit)" : "Failed");
|
||||
GetDirContents(current_dir, current_path);
|
||||
return 0;
|
||||
} else if (user_select == hsrestore) { // restore Health & Safety
|
||||
n_opt = 0;
|
||||
int sys = (CheckHealthAndSafetyInject("1:") == 0) ? (int) ++n_opt : -1;
|
||||
|
@ -24,6 +24,12 @@ static const u8 slot0x11Key95_sha256[0x20] = { // slot0x11Key95 hash (first 16 b
|
||||
0xBA, 0xC1, 0x40, 0x9C, 0x6E, 0xE4, 0x1F, 0x04, 0xAA, 0xC4, 0xE2, 0x09, 0x5C, 0xE9, 0x4F, 0x78,
|
||||
0x6C, 0x78, 0x5F, 0xAC, 0xEC, 0x7E, 0xC0, 0x11, 0x26, 0x9D, 0x4E, 0x47, 0xB3, 0x64, 0xC4, 0xA5
|
||||
};
|
||||
|
||||
// from: https://github.com/AuroraWright/SafeA9LHInstaller/blob/master/source/installer.c#L9-L17
|
||||
static const u8 sector0x96_sha256[0x20] = { // hash for legit sector 0x96 (different on A9LH)
|
||||
0x82, 0xF2, 0x73, 0x0D, 0x2C, 0x2D, 0xA3, 0xF3, 0x01, 0x65, 0xF9, 0x87, 0xFD, 0xCC, 0xAC, 0x5C,
|
||||
0xBA, 0xB2, 0x4B, 0x4E, 0x5F, 0x65, 0xC9, 0x81, 0xCD, 0x7B, 0xE6, 0xF4, 0x38, 0xE6, 0xD9, 0xD3
|
||||
};
|
||||
|
||||
static const u8 nand_magic_n3ds[0x60] = { // NCSD NAND header N3DS magic
|
||||
0x4E, 0x43, 0x53, 0x44, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
@ -438,6 +444,38 @@ u64 GetNandUnusedSectors(u32 nand_src)
|
||||
return GetNandSizeSectors(nand_src) - NAND_MIN_SECTORS;
|
||||
}
|
||||
|
||||
u32 GetLegitSector0x96(u8* sector)
|
||||
{
|
||||
// secret sector already in buffer?
|
||||
if (sha_cmp(sector0x96_sha256, sector, 0x200, SHA256_MODE) == 0)
|
||||
return 0;
|
||||
|
||||
// search for valid secret sector in SysNAND / EmuNAND
|
||||
const u32 nand_src[] = { NAND_SYSNAND, NAND_EMUNAND };
|
||||
for (u32 i = 0; i < sizeof(nand_src) / sizeof(u32); i++) {
|
||||
ReadNandSectors(sector, 0x96, 1, 0x11, nand_src[i]);
|
||||
if (sha_cmp(sector0x96_sha256, sector, 0x200, SHA256_MODE) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no luck? try searching for a file
|
||||
const char* base[] = { INPUT_PATHS };
|
||||
for (u32 i = 0; i < (sizeof(base)/sizeof(char*)); i++) {
|
||||
char path[64];
|
||||
snprintf(path, 64, "%s/%s", base[i], SECTOR_NAME);
|
||||
if ((FileGetData(path, sector, 0x200, 0) == 0x200) &&
|
||||
(sha_cmp(sector0x96_sha256, sector, 0x200, SHA256_MODE) == 0))
|
||||
return 0;
|
||||
snprintf(path, 64, "%s/%s", base[i], SECRET_NAME);
|
||||
if ((FileGetData(path, sector, 0x200, 0) == 0x200) &&
|
||||
(sha_cmp(sector0x96_sha256, sector, 0x200, SHA256_MODE) == 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
// failed if we arrive here
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool CheckMultiEmuNand(void)
|
||||
{
|
||||
// this only checks for the theoretical possibility
|
||||
|
@ -35,6 +35,10 @@
|
||||
#define SIZE_CTR_O3DS 0x17AE80
|
||||
#define SIZE_CTR_N3DS 0x20F680
|
||||
|
||||
// filenames for sector 0x96
|
||||
#define SECTOR_NAME "sector0x96.bin"
|
||||
#define SECRET_NAME "secret_sector.bin"
|
||||
|
||||
bool InitNandCrypto(void);
|
||||
bool CheckSlot0x05Crypto(void);
|
||||
bool CheckSector0x96Crypto(void);
|
||||
@ -52,6 +56,8 @@ u32 CheckNandMbr(u8* mbr);
|
||||
u32 CheckNandHeader(u8* header);
|
||||
u32 CheckNandType(u32 src);
|
||||
|
||||
u32 GetLegitSector0x96(u8* sector);
|
||||
|
||||
bool CheckMultiEmuNand(void);
|
||||
u32 InitEmuNandBase(bool reset);
|
||||
u32 GetEmuNandBase(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user