Game installer: Misc code improvements

This commit is contained in:
d0k3 2020-08-07 13:05:10 +02:00
parent 18e6d9f0db
commit 6eb546dfab

View File

@ -262,8 +262,8 @@ u32 GetTmdContentPath(char* path_content, const char* path_tmd) {
u32 GetTieContentPath(char* path_content, const char* path_tie) { u32 GetTieContentPath(char* path_content, const char* path_tie) {
char path_tmd[64]; char path_tmd[64];
char* tid_str = path_tie + 3;
char drv[3] = { 0x00 }; char drv[3] = { 0x00 };
u64 tid64 = 0;
// this relies on: // this relies on:
// 1: titleinfo entries are only loaded from mounted [1/4/A/B]:/dbs/title.db // 1: titleinfo entries are only loaded from mounted [1/4/A/B]:/dbs/title.db
@ -272,6 +272,11 @@ u32 GetTieContentPath(char* path_content, const char* path_tie) {
// basic sanity check // basic sanity check
if (*path_tie != 'T') return 1; if (*path_tie != 'T') return 1;
// get title id
if (sscanf(path_tie, "T:/%016llx", &tid64) != 1) return 1;
u32 tid_high = (u32) ((tid64 >> 32) & 0xFFFFFFFF);
u32 tid_low = (u32) (tid64 & 0xFFFFFFFF);
// load TitleDB entry file // load TitleDB entry file
TitleInfoEntry tie; TitleInfoEntry tie;
if (fvx_qread(path_tie, &tie, 0, sizeof(TitleInfoEntry), NULL) != FR_OK) if (fvx_qread(path_tie, &tie, 0, sizeof(TitleInfoEntry), NULL) != FR_OK)
@ -281,14 +286,15 @@ u32 GetTieContentPath(char* path_content, const char* path_tie) {
const char* mntpath = GetMountPath(); const char* mntpath = GetMountPath();
if (!mntpath || !*mntpath) return 1; if (!mntpath || !*mntpath) return 1;
strncpy(drv, mntpath, 2); strncpy(drv, mntpath, 2);
if ((tid_str[3] == '4') && (tid_str[4] == '8')) { if (tid_high & 0x8000) {
if (*drv == '1') *drv = '2'; if (*drv == '1') *drv = '2';
if (*drv == '4') *drv = '5'; if (*drv == '4') *drv = '5';
tid_high = 0x00030000 | (tid_high&0xFF);
} }
// build the path // build the path
snprintf(path_tmd, 64, "%2.2s/title/%8.8s/%8.8s/content/%08lx.tmd", snprintf(path_tmd, 64, "%2.2s/title/%08lX/%08lX/content/%08lx.tmd",
drv, tid_str, tid_str + 8, tie.tmd_content_id); drv, tid_high, tid_low, tie.tmd_content_id);
// let the TMD content path function take over // let the TMD content path function take over
return GetTmdContentPath(path_content, path_tmd); return GetTmdContentPath(path_content, path_tmd);
@ -1270,11 +1276,43 @@ u32 CryptGameFile(const char* path, bool inplace, bool encrypt) {
return ret; return ret;
} }
u32 GetInstallPath(char* path, const char* drv, const u8* title_id, const u8* content_id, const char* str) { u32 GetInstallDataDrive(char* drv, u64 tid64, bool to_emunand) {
// check the title id
bool to_twl = ((tid64 >> 32) & 0x8000);
bool to_sd = (!to_twl && !((tid64 >> 32) & 0x10));
// determine the correct drive
drv[0] = to_emunand ?
(to_twl ? '5' : to_sd ? 'B' : '4') :
(to_twl ? '2' : to_sd ? 'A' : '1');
drv[1] = ':';
drv[2] = '\0';
return 0;
}
u32 GetInstallDbsPath(char* path, const char* drv, const char* str) {
bool is_ticketdb = (strncasecmp(str, "ticket.db", 10) == 0);
// fix the drive if required
if (*drv == '2') drv = "1:";
else if (*drv == '5') drv = "4:";
else if (is_ticketdb) {
if (*drv == 'A') drv = "1:";
else if (*drv == 'B') drv = "4:";
}
// build the path
snprintf(path, 256, "%2.2s/dbs/%s", drv, str);
return 0;
}
u32 GetInstallPath(char* path, const char* drv, u64 tid64, const u8* content_id, const char* str) {
static const u8 dlc_tid_high[] = { DLC_TID_HIGH }; static const u8 dlc_tid_high[] = { DLC_TID_HIGH };
bool dlc = (memcmp(title_id, dlc_tid_high, sizeof(dlc_tid_high)) == 0); u32 tid_high = (u32) ((tid64 >> 32) & 0xFFFFFFFF);
u32 tid_high = getbe32(title_id); u32 tid_low = (u32) (tid64 & 0xFFFFFFFF);
u32 tid_low = getbe32(title_id + 4); bool dlc = (tid_high == getbe32(dlc_tid_high));
if ((*drv == '2') || (*drv == '5')) // TWL titles need TWL title ID if ((*drv == '2') || (*drv == '5')) // TWL titles need TWL title ID
tid_high = 0x00030000 | (tid_high&0xFF); tid_high = 0x00030000 | (tid_high&0xFF);
@ -1293,7 +1331,7 @@ u32 GetInstallPath(char* path, const char* drv, const u8* title_id, const u8* co
return 0; return 0;
} }
u32 GetInstallSavePath(char* path, const char* drv, const u8* title_id) { u32 GetInstallSavePath(char* path, const char* drv, u64 tid64) {
// generate the save path (thanks ihaveamac for system path) // generate the save path (thanks ihaveamac for system path)
if ((*drv == '1') || (*drv == '4')) { // ooof, system save if ((*drv == '1') || (*drv == '4')) { // ooof, system save
// get the id0 // get the id0
@ -1305,13 +1343,13 @@ u32 GetInstallSavePath(char* path, const char* drv, const u8* title_id) {
memset(sd_keyy, 0x00, 16); memset(sd_keyy, 0x00, 16);
sha_quick(sha256sum, sd_keyy, 0x10, SHA256_MODE); sha_quick(sha256sum, sd_keyy, 0x10, SHA256_MODE);
// build path // build path
u32 tid_low = getbe32(title_id + 4); u32 tid_low = (u32) (tid64 & 0xFFFFFFFF);
snprintf(path, 128, "%2.2s/data/%08lx%08lx%08lx%08lx/sysdata/%08lx/00000000", snprintf(path, 128, "%2.2s/data/%08lx%08lx%08lx%08lx/sysdata/%08lx/00000000",
drv, sha256sum[0], sha256sum[1], sha256sum[2], sha256sum[3], drv, sha256sum[0], sha256sum[1], sha256sum[2], sha256sum[3],
tid_low | 0x00020000); tid_low | 0x00020000);
return 0; return 0;
} else { // SD save, simple } else { // SD save, simple
return GetInstallPath(path, drv, title_id, NULL, "data/00000001.sav"); return GetInstallPath(path, drv, tid64, NULL, "data/00000001.sav");
} }
} }
@ -1320,7 +1358,7 @@ u32 InstallCiaContent(const char* drv, const char* path_content, u32 offset, u32
char dest[256]; char dest[256];
// create destination path and ensure it exists // create destination path and ensure it exists
GetInstallPath(dest, drv, title_id, chunk->id, NULL); GetInstallPath(dest, drv, getbe64(title_id), chunk->id, NULL);
fvx_rmkpath(dest); fvx_rmkpath(dest);
// open file(s) // open file(s)
@ -1420,15 +1458,12 @@ u32 InstallCiaSystemData(CiaStub* cia, const char* drv) {
(*drv != '4') && (*drv != '5') && (*drv != 'B')) (*drv != '4') && (*drv != '5') && (*drv != 'B'))
return 1; return 1;
// progress update
if (!ShowProgress(0, 0, "TMD/CMD/TiE/Ticket/Save")) return 1;
// collect data for title info entry // collect data for title info entry
char path_cnt0[256]; char path_cnt0[256];
u8 hdr_cnt0[0x600]; // we don't need more u8 hdr_cnt0[0x600]; // we don't need more
NcchHeader* ncch = NULL; NcchHeader* ncch = NULL;
NcchExtHeader* exthdr = NULL; NcchExtHeader* exthdr = NULL;
GetInstallPath(path_cnt0, drv, title_id, content_list->id, NULL); GetInstallPath(path_cnt0, drv, getbe64(title_id), content_list->id, NULL);
if (fvx_qread(path_cnt0, hdr_cnt0, 0, 0x600, NULL) != FR_OK) if (fvx_qread(path_cnt0, hdr_cnt0, 0, 0x600, NULL) != FR_OK)
return 1; return 1;
if (ValidateNcchHeader((void*) hdr_cnt0) == 0) { if (ValidateNcchHeader((void*) hdr_cnt0) == 0) {
@ -1455,11 +1490,8 @@ u32 InstallCiaSystemData(CiaStub* cia, const char* drv) {
snprintf(path_ticketdb, 32, "%2.2s/dbs/ticket.db", snprintf(path_ticketdb, 32, "%2.2s/dbs/ticket.db",
((*drv == 'A') || (*drv == '2')) ? "1:" : ((*drv == 'A') || (*drv == '2')) ? "1:" :
((*drv == 'B') || (*drv == '5')) ? "4:" : drv); ((*drv == 'B') || (*drv == '5')) ? "4:" : drv);
GetInstallPath(path_tmd, drv, title_id, NULL, "content/00000000.tmd"); GetInstallPath(path_tmd, drv, getbe64(title_id), NULL, "content/00000000.tmd");
GetInstallPath(path_cmd, drv, title_id, NULL, "content/cmd/00000001.cmd"); GetInstallPath(path_cmd, drv, getbe64(title_id), NULL, "content/cmd/00000001.cmd");
// progress update
if (!ShowProgress(1, 5, "TMD/CMD")) return 1;
// copy tmd & cmd // copy tmd & cmd
fvx_rmkpath(path_tmd); fvx_rmkpath(path_tmd);
@ -1475,11 +1507,8 @@ u32 InstallCiaSystemData(CiaStub* cia, const char* drv) {
if (exthdr && (exthdr->savedata_size)) { if (exthdr && (exthdr->savedata_size)) {
char path_save[128]; char path_save[128];
// progress update
if (!ShowProgress(2, 5, "Savegame")) return 1;
// generate the path // generate the path
GetInstallSavePath(path_save, drv, title_id); GetInstallSavePath(path_save, drv, getbe64(title_id));
// generate the save file, first check if it already exists // generate the save file, first check if it already exists
if (fvx_qsize(path_save) != exthdr->savedata_size) { if (fvx_qsize(path_save) != exthdr->savedata_size) {
@ -1498,9 +1527,6 @@ u32 InstallCiaSystemData(CiaStub* cia, const char* drv) {
} }
} }
// progress update
if (!ShowProgress(3, 5, "TitleDB update")) return 1;
// write ticket and title databases // write ticket and title databases
// ensure remounting the old mount path // ensure remounting the old mount path
char path_store[256] = { 0 }; char path_store[256] = { 0 };
@ -1515,9 +1541,6 @@ u32 InstallCiaSystemData(CiaStub* cia, const char* drv) {
return 1; return 1;
} }
// progress update
if (!ShowProgress(4, 5, "TicketDB update")) return 1;
// ticket database // ticket database
if (!InitImgFS(path_ticketdb) || if (!InitImgFS(path_ticketdb) ||
((AddTicketToDB("D:/partitionA.bin", title_id, (Ticket*) ticket, true)) != 0)) { ((AddTicketToDB("D:/partitionA.bin", title_id, (Ticket*) ticket, true)) != 0)) {
@ -1525,9 +1548,6 @@ u32 InstallCiaSystemData(CiaStub* cia, const char* drv) {
return 1; return 1;
} }
// progress update
if (!ShowProgress(5, 5, "TMD/CMD/TiE/Ticket/Save")) return 1;
// restore old mount path // restore old mount path
InitImgFS(path_bak); InitImgFS(path_bak);
@ -2185,34 +2205,21 @@ u64 GetGameFileTitleId(const char* path) {
} }
u32 InstallGameFile(const char* path, bool to_emunand) { u32 InstallGameFile(const char* path, bool to_emunand) {
const char* drv; char drv[3];
u64 filetype = IdentifyFileType(path); u64 filetype = IdentifyFileType(path);
u32 ret = 0; u32 ret = 0;
// find out the destination // find out the destination
bool to_sd = false;
bool to_twl = false;
u64 tid64 = GetGameFileTitleId(path); u64 tid64 = GetGameFileTitleId(path);
if (!tid64) return 1; if (GetInstallDataDrive(drv, tid64, to_emunand) != 0)
if (((tid64 >> 32) & 0x8000) || (filetype & GAME_NDS))
to_twl = true;
else if (!((tid64 >> 32) & 0x10))
to_sd = true;
// does title.db & import.db exist?
if (to_sd) {
if (!fvx_qsize(to_emunand ? "B:/dbs/title.db" : "A:/dbs/title.db") ||
!fvx_qsize(to_emunand ? "B:/dbs/import.db" : "A:/dbs/import.db"))
return 1; return 1;
} else {
if (!fvx_qsize(to_emunand ? "4:/dbs/title.db" : "1:/dbs/title.db") ||
!fvx_qsize(to_emunand ? "4:/dbs/import.db" : "1:/dbs/import.db"))
return 1;
}
// now we know the correct drive // check dbs
drv = to_emunand ? (to_sd ? "B:" : to_twl ? "5:" : "4:") : char path_db[32];
(to_sd ? "A:" : to_twl ? "2:" : "1:"); if (((GetInstallDbsPath(path_db, drv, "title.db" ) != 0) || !fvx_qsize(path_db)) ||
((GetInstallDbsPath(path_db, drv, "import.db") != 0) || !fvx_qsize(path_db)) ||
((GetInstallDbsPath(path_db, drv, "ticket.db") != 0) || !fvx_qsize(path_db)))
return 1; // this needs an error prompt (!!!)
// check permissions for SysNAND (this includes everything we need) // check permissions for SysNAND (this includes everything we need)
if (!CheckWritePermissions(to_emunand ? "4:" : "1:")) return 1; if (!CheckWritePermissions(to_emunand ? "4:" : "1:")) return 1;