mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Handle incomplete DLCs when building CIA from TMD
This commit is contained in:
parent
d6df1efad3
commit
6a8b97c3e5
@ -1124,8 +1124,7 @@ u32 BuildCiaFromTmdFile(const char* path_tmd, const char* path_cia, bool force_l
|
|||||||
(LoadTmdFile(&(cia->tmd), path_tmd) != 0) ||
|
(LoadTmdFile(&(cia->tmd), path_tmd) != 0) ||
|
||||||
(FixCiaHeaderForTmd(&(cia->header), &(cia->tmd)) != 0) ||
|
(FixCiaHeaderForTmd(&(cia->header), &(cia->tmd)) != 0) ||
|
||||||
(BuildCiaCert(cia->cert) != 0) ||
|
(BuildCiaCert(cia->cert) != 0) ||
|
||||||
(BuildFakeTicket(&(cia->ticket), cia->tmd.title_id) != 0) ||
|
(BuildFakeTicket(&(cia->ticket), cia->tmd.title_id) != 0)) {
|
||||||
(WriteCiaStub(cia, path_cia) != 0)) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1134,7 +1133,7 @@ u32 BuildCiaFromTmdFile(const char* path_tmd, const char* path_cia, bool force_l
|
|||||||
TmdContentChunk* content_list = cia->content_list;
|
TmdContentChunk* content_list = cia->content_list;
|
||||||
u32 content_count = getbe16(tmd->content_count);
|
u32 content_count = getbe16(tmd->content_count);
|
||||||
u8* title_id = tmd->title_id;
|
u8* title_id = tmd->title_id;
|
||||||
bool dlc = !cdn && (memcmp(tmd->title_id, dlc_tid_high, sizeof(dlc_tid_high)) == 0);
|
bool dlc = (memcmp(tmd->title_id, dlc_tid_high, sizeof(dlc_tid_high)) == 0);
|
||||||
if (!content_count) return 1;
|
if (!content_count) return 1;
|
||||||
|
|
||||||
// get (legit) ticket
|
// get (legit) ticket
|
||||||
@ -1171,13 +1170,34 @@ u32 BuildCiaFromTmdFile(const char* path_tmd, const char* path_cia, bool force_l
|
|||||||
if (!name_content) return 1; // will not happen
|
if (!name_content) return 1; // will not happen
|
||||||
name_content++;
|
name_content++;
|
||||||
|
|
||||||
|
// DLC? Check for missing contents first!
|
||||||
|
if (dlc) for (u32 i = 0; (i < content_count) && (i < TMD_MAX_CONTENTS);) {
|
||||||
|
FILINFO fno;
|
||||||
|
TmdContentChunk* chunk = &(content_list[i]);
|
||||||
|
snprintf(name_content, 256 - (name_content - path_content),
|
||||||
|
(cdn) ? "%08lx" : (dlc && !cdn) ? "00000000/%08lx.app" : "%08lx.app", getbe32(chunk->id));
|
||||||
|
if ((fvx_stat(path_content, &fno) != FR_OK) || (fno.fsize != (u32) getbe64(chunk->size)))
|
||||||
|
memmove(chunk, chunk + 1, ((--content_count) - i) * sizeof(TmdContentChunk));
|
||||||
|
else i++;
|
||||||
|
}
|
||||||
|
if (!content_count) return 1;
|
||||||
|
if (content_count < (u16) getbe16(tmd->content_count)) {
|
||||||
|
if (!ShowPrompt(true, "ID %016llX\nIncomplete DLC (%u missing)\nContinue?",
|
||||||
|
getbe64(title_id), getbe16(tmd->content_count) - content_count)) return 1;
|
||||||
|
tmd->content_count[0] = (content_count >> 8) & 0xFF;
|
||||||
|
tmd->content_count[1] = content_count & 0xFF;
|
||||||
|
memcpy(tmd->contentinfo[0].cmd_count, tmd->content_count, 2);
|
||||||
|
if (FixCiaHeaderForTmd(&(cia->header), tmd) != 0) return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// insert contents
|
// insert contents
|
||||||
u8 titlekey[16] = { 0xFF };
|
u8 titlekey[16] = { 0xFF };
|
||||||
if ((GetTitleKey(titlekey, &(cia->ticket)) != 0) && force_legit) return 1;
|
if ((GetTitleKey(titlekey, &(cia->ticket)) != 0) && force_legit) return 1;
|
||||||
|
if (WriteCiaStub(cia, path_cia) != 0) return 1;
|
||||||
for (u32 i = 0; (i < content_count) && (i < TMD_MAX_CONTENTS); i++) {
|
for (u32 i = 0; (i < content_count) && (i < TMD_MAX_CONTENTS); i++) {
|
||||||
TmdContentChunk* chunk = &(content_list[i]);
|
TmdContentChunk* chunk = &(content_list[i]);
|
||||||
snprintf(name_content, 256 - (name_content - path_content),
|
snprintf(name_content, 256 - (name_content - path_content),
|
||||||
(cdn) ? "%08lx" : (dlc) ? "00000000/%08lx.app" : "%08lx.app", getbe32(chunk->id));
|
(cdn) ? "%08lx" : (dlc && !cdn) ? "00000000/%08lx.app" : "%08lx.app", getbe32(chunk->id));
|
||||||
if (InsertCiaContent(path_cia, path_content, 0, (u32) getbe64(chunk->size), chunk, titlekey, force_legit, false, cdn) != 0) {
|
if (InsertCiaContent(path_cia, path_content, 0, (u32) getbe64(chunk->size), chunk, titlekey, force_legit, false, cdn) != 0) {
|
||||||
ShowPrompt(false, "ID %016llX.%08lX\nInsert content failed", getbe64(title_id), getbe32(chunk->id));
|
ShowPrompt(false, "ID %016llX.%08lX\nInsert content failed", getbe64(title_id), getbe32(chunk->id));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -66,6 +66,19 @@ FRESULT fvx_sync (FIL* fp) {
|
|||||||
return f_sync( fp );
|
return f_sync( fp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FRESULT fvx_stat (const TCHAR* path, FILINFO* fno) {
|
||||||
|
if (GetVirtualSource(path)) {
|
||||||
|
VirtualFile vfile;
|
||||||
|
if (!GetVirtualFile(&vfile, path)) return FR_NO_PATH;
|
||||||
|
fno->fsize = vfile.size;
|
||||||
|
fno->fdate = fno->ftime = 0;
|
||||||
|
fno->fattrib = (vfile.flags & VFLAG_DIR) ? AM_DIR : 0;
|
||||||
|
// could be better...
|
||||||
|
if (_USE_LFN != 0) GetVirtualFilename(fno->fname, &vfile, _MAX_LFN + 1);
|
||||||
|
return FR_OK;
|
||||||
|
} else return fa_stat(path, fno);
|
||||||
|
}
|
||||||
|
|
||||||
FRESULT fvx_qread (const TCHAR* path, void* buff, FSIZE_t ofs, UINT btr, UINT* br) {
|
FRESULT fvx_qread (const TCHAR* path, void* buff, FSIZE_t ofs, UINT btr, UINT* br) {
|
||||||
FIL fp;
|
FIL fp;
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
@ -14,6 +14,7 @@ FRESULT fvx_write (FIL* fp, const void* buff, UINT btw, UINT* bw);
|
|||||||
FRESULT fvx_close (FIL* fp);
|
FRESULT fvx_close (FIL* fp);
|
||||||
FRESULT fvx_lseek (FIL* fp, FSIZE_t ofs);
|
FRESULT fvx_lseek (FIL* fp, FSIZE_t ofs);
|
||||||
FRESULT fvx_sync (FIL* fp);
|
FRESULT fvx_sync (FIL* fp);
|
||||||
|
FRESULT fvx_stat (const TCHAR* path, FILINFO* fno);
|
||||||
|
|
||||||
// additional quick read / write functions
|
// additional quick read / write functions
|
||||||
FRESULT fvx_qread (const TCHAR* path, void* buff, FSIZE_t ofs, UINT btr, UINT* br);
|
FRESULT fvx_qread (const TCHAR* path, void* buff, FSIZE_t ofs, UINT btr, UINT* br);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user