mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 21:52:48 +00:00
Added installer for cifinish.bin files
This commit is contained in:
parent
07cb94d99a
commit
25bf8b3f93
@ -156,6 +156,9 @@ u64 IdentifyFileType(const char* path) {
|
||||
return BIN_KEYDB; // key database
|
||||
} else if ((sscanf(fname, "slot%02lXKey", &id) == 1) && (strncasecmp(ext, "bin", 4) == 0) && (fsize = 16) && (id < 0x40)) {
|
||||
return BIN_LEGKEY; // legacy key file
|
||||
} else if ((strncmp((char*) data, CIFINISH_MAGIC, strlen(CIFINISH_MAGIC)) == 0) &&
|
||||
(fsize == CIFINISH_SIZE((void*) data)) && (fsize > sizeof(CifinishHeader))) {
|
||||
return BIN_CIFNSH;
|
||||
} else if (ValidateText((char*) data, (fsize > 0x200) ? 0x200 : fsize)) {
|
||||
u64 type = 0;
|
||||
if ((fsize < SCRIPT_MAX_SIZE) && (strncasecmp(ext, SCRIPT_EXT, strnlen(SCRIPT_EXT, 16) + 1) == 0))
|
||||
|
@ -27,17 +27,18 @@
|
||||
#define SYS_DISA (1ULL<<22)
|
||||
#define SYS_AGBSAVE (1ULL<<23)
|
||||
#define SYS_TICKDB (1ULL<<24)
|
||||
#define BIN_NCCHNFO (1ULL<<25)
|
||||
#define BIN_TIKDB (1ULL<<26)
|
||||
#define BIN_KEYDB (1ULL<<27)
|
||||
#define BIN_LEGKEY (1ULL<<28)
|
||||
#define TXT_SCRIPT (1ULL<<29)
|
||||
#define TXT_GENERIC (1ULL<<30)
|
||||
#define GFX_PNG (1ULL<<31)
|
||||
#define FONT_PBM (1ULL<<32)
|
||||
#define FONT_RIFF (1ULL<<33)
|
||||
#define NOIMG_NAND (1ULL<<34)
|
||||
#define HDR_NAND (1ULL<<35)
|
||||
#define BIN_CIFNSH (1ULL<<25)
|
||||
#define BIN_NCCHNFO (1ULL<<26)
|
||||
#define BIN_TIKDB (1ULL<<27)
|
||||
#define BIN_KEYDB (1ULL<<28)
|
||||
#define BIN_LEGKEY (1ULL<<29)
|
||||
#define TXT_SCRIPT (1ULL<<30)
|
||||
#define TXT_GENERIC (1ULL<<31)
|
||||
#define GFX_PNG (1ULL<<32)
|
||||
#define FONT_PBM (1ULL<<33)
|
||||
#define FONT_RIFF (1ULL<<34)
|
||||
#define NOIMG_NAND (1ULL<<35)
|
||||
#define HDR_NAND (1ULL<<36)
|
||||
#define TYPE_BASE 0xFFFFFFFFFFULL // 40 bit reserved for base types
|
||||
|
||||
// #define FLAG_FIRM (1ULL<<58) // <--- for CXIs containing FIRMs
|
||||
@ -55,6 +56,7 @@
|
||||
#define FTYPE_CIABUILD_L(tp) (tp&(GAME_TMD|GAME_CDNTMD|GAME_TIE|GAME_TAD))
|
||||
#define FTYPE_CIAINSTALL(tp) ((tp&(GAME_NCSD|GAME_NCCH|GAME_CIA|GAME_CDNTMD|GAME_TWLTMD)) || ((tp&GAME_NDS)&&(tp&(FLAG_DSIW))))
|
||||
#define FTYPE_TIKINSTALL(tp) (tp&(GAME_TICKET))
|
||||
#define FTYPE_CIFINSTALL(tp) (tp&(BIN_CIFNSH))
|
||||
#define FTYPE_TIKDUMP(tp) (tp&(GAME_TIE))
|
||||
#define FTYPE_CXIDUMP(tp) (tp&(GAME_TMD|GAME_TIE))
|
||||
#define FTYPE_UNINSTALL(tp) (tp&(GAME_TIE))
|
||||
|
23
arm9/source/game/cifinish.h
Normal file
23
arm9/source/game/cifinish.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define CIFINISH_MAGIC "CIFINISH"
|
||||
#define CIFINISH_TITLE_MAGIC "TITLE"
|
||||
#define CIFINISH_SIZE(c) (sizeof(CifinishHeader) + ((((CifinishHeader*)(c))->n_entries) * sizeof(CifinishTitle)))
|
||||
|
||||
// see: https://github.com/ihaveamac/custom-install/blob/ac0be9d61d7ebef9356df23036dc53e8e862011a/custominstall.py#L163
|
||||
typedef struct {
|
||||
char magic[8];
|
||||
u32 version;
|
||||
u32 n_entries;
|
||||
} __attribute__((packed, aligned(4))) CifinishHeader;
|
||||
|
||||
typedef struct {
|
||||
char magic[5];
|
||||
u8 padding0;
|
||||
u8 has_seed; // 1 if it does, otherwise 0
|
||||
u8 padding1;
|
||||
u64 title_id;
|
||||
u8 seed[16];
|
||||
} __attribute__((packed, aligned(4))) CifinishTitle;
|
@ -20,3 +20,4 @@
|
||||
#include "bdri.h"
|
||||
#include "ticketdb.h"
|
||||
#include "ncchinfo.h"
|
||||
#include "cifinish.h"
|
||||
|
@ -74,7 +74,7 @@ u32 BuildVariableFakeTicket(Ticket** ticket, u32* ticket_size, const u8* title_i
|
||||
memset(_ticket->ecdsa, 0xFF, 0x3C);
|
||||
_ticket->version = 0x01;
|
||||
memset(_ticket->titlekey, 0xFF, 16);
|
||||
memcpy(_ticket->title_id, title_id, 8);
|
||||
if (title_id) memcpy(_ticket->title_id, title_id, 8);
|
||||
_ticket->commonkey_idx = 0x00; // eshop
|
||||
_ticket->audit = 0x01; // whatever
|
||||
|
||||
|
@ -1107,6 +1107,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
!(drvtype & DRV_TWLNAND) && !(drvtype & DRV_ALIAS) && !(drvtype & DRV_IMAGE);
|
||||
bool tik_installable = (FTYPE_TIKINSTALL(filetype)) && !(drvtype & DRV_IMAGE);
|
||||
bool tik_dumpable = (FTYPE_TIKDUMP(filetype));
|
||||
bool cif_installable = (FTYPE_CIFINSTALL(filetype)) && !(drvtype & DRV_IMAGE);
|
||||
bool uninstallable = (FTYPE_UNINSTALL(filetype));
|
||||
bool cxi_dumpable = (FTYPE_CXIDUMP(filetype));
|
||||
bool tik_buildable = (FTYPE_TIKBUILD(filetype)) && !in_output_path;
|
||||
@ -1149,7 +1150,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
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 || cia_installable || tik_installable || tik_dumpable;
|
||||
agbimportable || cia_installable || tik_installable || tik_dumpable || cif_installable;
|
||||
|
||||
char pathstr[UTF_BUFFER_BYTESIZE(32)];
|
||||
TruncateString(pathstr, file_path, 32, 8);
|
||||
@ -1211,6 +1212,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
(filetype & SYS_TICKDB) ? "Ticket.db options..." :
|
||||
(filetype & SYS_DIFF) ? "Mount as DIFF image" :
|
||||
(filetype & SYS_DISA) ? "Mount as DISA image" :
|
||||
(filetype & BIN_CIFNSH) ? "Install cifinish.bin" :
|
||||
(filetype & BIN_TIKDB) ? "Titlekey options..." :
|
||||
(filetype & BIN_KEYDB) ? "AESkeydb options..." :
|
||||
(filetype & BIN_LEGKEY) ? "Build " KEYDB_NAME :
|
||||
@ -1359,6 +1361,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
int cia_install = (cia_installable) ? ++n_opt : -1;
|
||||
int tik_install = (tik_installable) ? ++n_opt : -1;
|
||||
int tik_dump = (tik_dumpable) ? ++n_opt : -1;
|
||||
int cif_install = (cif_installable) ? ++n_opt : -1;
|
||||
int uninstall = (uninstallable) ? ++n_opt : -1;
|
||||
int tik_build_enc = (tik_buildable) ? ++n_opt : -1;
|
||||
int tik_build_dec = (tik_buildable) ? ++n_opt : -1;
|
||||
@ -1394,6 +1397,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
if (cia_install > 0) optionstr[cia_install-1] = "Install game image";
|
||||
if (tik_install > 0) optionstr[tik_install-1] = "Install ticket";
|
||||
if (tik_dump > 0) optionstr[tik_dump-1] = "Dump ticket file";
|
||||
if (cif_install > 0) optionstr[cif_install-1] = "Install cifinish.bin";
|
||||
if (uninstall > 0) optionstr[uninstall-1] = "Uninstall title";
|
||||
if (tik_build_enc > 0) optionstr[tik_build_enc-1] = "Build " TIKDB_NAME_ENC;
|
||||
if (tik_build_dec > 0) optionstr[tik_build_dec-1] = "Build " TIKDB_NAME_DEC;
|
||||
@ -1602,8 +1606,11 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if ((user_select == cia_install) || (user_select == tik_install)) { // -> install game/ticket file
|
||||
bool install_tik = (user_select == tik_install);
|
||||
else if ((user_select == cia_install) || (user_select == tik_install) ||
|
||||
(user_select == cif_install)) { // -> install game/ticket/cifinish file
|
||||
u32 (*InstallFunction)(const char*, bool) =
|
||||
(user_select == cia_install) ? &InstallGameFile :
|
||||
(user_select == tik_install) ? &InstallTicketFile : &InstallCifinishFile;
|
||||
bool to_emunand = false;
|
||||
if (CheckVirtualDrive("E:")) {
|
||||
optionstr[0] = "Install to SysNAND";
|
||||
@ -1626,8 +1633,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
continue;
|
||||
}
|
||||
DrawDirContents(current_dir, (*cursor = i), scroll);
|
||||
if ((!install_tik && (InstallGameFile(path, to_emunand) == 0)) ||
|
||||
(install_tik && (InstallTicketFile(path, to_emunand) == 0)))
|
||||
if ((*InstallFunction)(path, to_emunand) == 0)
|
||||
n_success++;
|
||||
else { // on failure: show error, continue
|
||||
char lpathstr[UTF_BUFFER_BYTESIZE(32)];
|
||||
@ -1642,8 +1648,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
||||
n_success, n_marked, n_other, n_marked);
|
||||
} else ShowPrompt(false, "%lu/%lu files installed ok", n_success, n_marked);
|
||||
} else {
|
||||
u32 ret = install_tik ? InstallTicketFile(file_path, to_emunand) :
|
||||
InstallGameFile(file_path, to_emunand);
|
||||
u32 ret = (*InstallFunction)(file_path, to_emunand);
|
||||
ShowPrompt(false, "%s\nInstall %s", pathstr, (ret == 0) ? "success" : "failed");
|
||||
if ((ret != 0) && (filetype & (GAME_NCCH|GAME_NCSD)) &&
|
||||
ShowPrompt(true, "%s\nfile failed install.\n \nVerify now?", pathstr)) {
|
||||
|
@ -2891,6 +2891,82 @@ u32 InstallGameFile(const char* path, bool to_emunand) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 InstallCifinishFile(const char* path, bool to_emunand) {
|
||||
u8 ALIGN(4) seeddb_storage[sizeof(SeedInfo) + sizeof(SeedInfoEntry)];
|
||||
SeedInfo* seeddb = (SeedInfo*) (void*) seeddb_storage;
|
||||
TicketCommon ticket;
|
||||
u32 ret = 0;
|
||||
|
||||
// sanity check / preparations
|
||||
if (!(IdentifyFileType(path) & BIN_CIFNSH)) return 1;
|
||||
if (BuildFakeTicket((Ticket*) &ticket, NULL) != 0) return 1;
|
||||
seeddb->n_entries = 1;
|
||||
|
||||
// check ticket db
|
||||
char path_ticketdb[32];
|
||||
if ((GetInstallDbsPath(path_ticketdb, to_emunand ? "4:" : "1:", "ticket.db") != 0) || !fvx_qsize(path_ticketdb)) {
|
||||
ShowPrompt(false, "Install error:\nThis system is missing the\nticket.db file.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check permissions for SysNAND (this includes everything we need)
|
||||
if (!CheckWritePermissions(to_emunand ? "4:" : "1:")) return 1;
|
||||
|
||||
// store mount path
|
||||
char path_store[256] = { 0 };
|
||||
char* path_bak = NULL;
|
||||
strncpy(path_store, GetMountPath(), 256);
|
||||
if (*path_store) path_bak = path_store;
|
||||
|
||||
// load the entire cifinish file into memory
|
||||
CifinishHeader* cifinish = (CifinishHeader*) malloc(fvx_qsize(path));
|
||||
CifinishTitle* cftitle = (CifinishTitle*) (cifinish+1);
|
||||
if (!cifinish) return 1;
|
||||
if (fvx_qread(path, cifinish, 0, fvx_qsize(path), NULL) != FR_OK) {
|
||||
free(cifinish);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// process tickets for the entire cifinish file
|
||||
if (!ShowProgress(0, 0, path)) ret = 1;
|
||||
if (!InitImgFS(path_ticketdb)) ret = 1;
|
||||
for (u32 i = 0; !ret && (i < cifinish->n_entries); i++) {
|
||||
// sanity
|
||||
if (strncmp(cftitle[i].magic, CIFINISH_TITLE_MAGIC, strlen(CIFINISH_TITLE_MAGIC)) != 0) {
|
||||
ret = 1;
|
||||
continue;
|
||||
}
|
||||
// check for forbidden title id (the "too large dlc")
|
||||
if ((TITLE_MAX_CONTENTS <= 1024) && (cftitle[i].title_id == 0x0004008C000CBD00)) {
|
||||
ShowPrompt(false, "Skipped title:\nTitle with id 0004008C000CBD00\nneeds special compiler flags.");
|
||||
ShowProgress(0, 0, path);
|
||||
continue;
|
||||
}
|
||||
if (!ShowProgress(i, cifinish->n_entries, path)) ret = 1;
|
||||
// insert ticket with correct title id
|
||||
for (u32 t = 0; t < 8; t++)
|
||||
ticket.title_id[7-t] = (cftitle[i].title_id >> (8*t)) & 0xFF;
|
||||
AddTicketToDB(PART_PATH, ticket.title_id, (Ticket*) &ticket, false);
|
||||
}
|
||||
|
||||
// process seeds for the entire cifinish file
|
||||
if (!ShowProgress(0, 0, path)) ret = 1;
|
||||
for (u32 i = 0; !ret && (i < cifinish->n_entries); i++) {
|
||||
if (!ShowProgress(i, cifinish->n_entries, path)) ret = 1;
|
||||
if ((TITLE_MAX_CONTENTS <= 1024) && (cftitle[i].title_id == 0x0004008C000CBD00)) continue;
|
||||
if (!cftitle[i].has_seed) continue;
|
||||
seeddb->entries[0].titleId = cftitle[i].title_id;
|
||||
memcpy(&(seeddb->entries[0].seed), cftitle[i].seed, sizeof(Seed));
|
||||
ret = InstallSeedDbToSystem(seeddb, to_emunand);
|
||||
}
|
||||
|
||||
// cleanup
|
||||
InitImgFS(path_bak);
|
||||
free(cifinish);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 InstallTicketFile(const char* path, bool to_emunand) {
|
||||
// sanity check
|
||||
if (!(IdentifyFileType(path) & GAME_TICKET))
|
||||
|
@ -7,6 +7,7 @@ u32 CheckEncryptedGameFile(const char* path);
|
||||
u32 CryptGameFile(const char* path, bool inplace, bool encrypt);
|
||||
u32 BuildCiaFromGameFile(const char* path, bool force_legit);
|
||||
u32 InstallGameFile(const char* path, bool to_emunand);
|
||||
u32 InstallCifinishFile(const char* path, bool to_emunand);
|
||||
u32 InstallTicketFile(const char* path, bool to_emunand);
|
||||
u32 DumpTicketForGameFile(const char* path, bool force_legit);
|
||||
u32 DumpCxiSrlFromGameFile(const char* path);
|
||||
|
Loading…
x
Reference in New Issue
Block a user