mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Fix CMD & NCSD handling
This commit is contained in:
parent
b8798f2aff
commit
d8aeb056cb
@ -124,7 +124,7 @@ u64 IdentifyFileType(const char* path) {
|
||||
(memcmp(data, threedsx_magic, sizeof(threedsx_magic)) == 0)) {
|
||||
return GAME_3DSX; // 3DSX (executable) file
|
||||
} else if ((fsize > sizeof(CmdHeader)) &&
|
||||
CheckCmdSize((CmdHeader*) data, fsize) == 0) {
|
||||
(CMD_SIZE((CmdHeader*) data) == fsize)) {
|
||||
return GAME_CMD; // CMD file
|
||||
} else if ((fsize > sizeof(NcchInfoHeader)) &&
|
||||
(GetNcchInfoVersion((NcchInfoHeader*) data)) &&
|
||||
|
@ -1,50 +1,62 @@
|
||||
#include "cmd.h"
|
||||
|
||||
|
||||
u32 CheckCmdSize(CmdHeader* cmd, u64 fsize) {
|
||||
u64 cmdsize = sizeof(CmdHeader) +
|
||||
(cmd->n_entries * sizeof(u32)) +
|
||||
(cmd->n_cmacs * sizeof(u32)) +
|
||||
(cmd->n_entries * 0x10);
|
||||
|
||||
return (fsize == cmdsize) ? 0 : 1;
|
||||
}
|
||||
|
||||
u32 BuildCmdData(CmdHeader* cmd, TitleMetaData* tmd) {
|
||||
CmdHeader* BuildAllocCmdData(TitleMetaData* tmd) {
|
||||
CmdHeader proto;
|
||||
CmdHeader* cmd = NULL;
|
||||
u32 content_count = getbe16(tmd->content_count);
|
||||
u32 max_cnt_id = 0;
|
||||
|
||||
// header basic info
|
||||
cmd->cmd_id = 0x1;
|
||||
cmd->n_entries = content_count;
|
||||
cmd->n_cmacs = content_count;
|
||||
// sanity check
|
||||
if (!content_count)
|
||||
return NULL;
|
||||
|
||||
// find max content id
|
||||
TmdContentChunk* chunk = (TmdContentChunk*) (tmd + 1);
|
||||
for (u32 i = 0; (i < content_count) && (i < TMD_MAX_CONTENTS); i++, chunk++)
|
||||
if (getbe32(chunk->id) > max_cnt_id) max_cnt_id = getbe32(chunk->id);
|
||||
|
||||
// allocate memory for CMD / basic setup
|
||||
proto.cmd_id = 1;
|
||||
proto.n_entries = max_cnt_id + 1;
|
||||
proto.n_cmacs = content_count;
|
||||
proto.unknown = 1;
|
||||
cmd = (CmdHeader*) malloc(CMD_SIZE(&proto));
|
||||
if (!cmd) return NULL;
|
||||
memcpy(cmd, &proto, sizeof(CmdHeader));
|
||||
cmd->unknown = 0x0; // this means no CMACs, only valid for NAND
|
||||
|
||||
// copy content ids
|
||||
u32* cnt_id = (u32*) (cmd + 1);
|
||||
u32* cnt_id_cpy = cnt_id + content_count;
|
||||
TmdContentChunk* chunk = (TmdContentChunk*) (tmd + 1);
|
||||
u32* cnt_id_2nd = cnt_id + cmd->n_entries;
|
||||
chunk = (TmdContentChunk*) (tmd + 1);
|
||||
memset(cnt_id, 0xFF, cmd->n_entries * sizeof(u32));
|
||||
for (u32 i = 0; (i < content_count) && (i < TMD_MAX_CONTENTS); i++, chunk++) {
|
||||
cnt_id[i] = getbe32(chunk->id);
|
||||
cnt_id_cpy[i] = cnt_id[i];
|
||||
u32 chunk_id = getbe32(chunk->id);
|
||||
cnt_id[chunk_id] = chunk_id;
|
||||
*(cnt_id_2nd++) = chunk_id;
|
||||
}
|
||||
|
||||
// bubble sort the second content id list
|
||||
u32 b = 0;
|
||||
while ((b < content_count) && (b < TMD_MAX_CONTENTS)) {
|
||||
for (b = 1; (b < content_count) && (b < TMD_MAX_CONTENTS); b++) {
|
||||
if (cnt_id_cpy[b] < cnt_id_cpy[b-1]) {
|
||||
u32 swp = cnt_id_cpy[b];
|
||||
cnt_id_cpy[b] = cnt_id_cpy[b-1];
|
||||
cnt_id_cpy[b-1] = swp;
|
||||
bool bs_finished = false;
|
||||
cnt_id_2nd = cnt_id + cmd->n_entries;
|
||||
while (!bs_finished) {
|
||||
bs_finished = true;
|
||||
for (u32 b = 1; b < cmd->n_cmacs; b++) {
|
||||
if (cnt_id_2nd[b] < cnt_id_2nd[b-1]) {
|
||||
u32 swp = cnt_id_2nd[b];
|
||||
cnt_id_2nd[b] = cnt_id_2nd[b-1];
|
||||
cnt_id_2nd[b-1] = swp;
|
||||
bs_finished = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set CMACs to 0xFF
|
||||
u8* cnt_cmac = (u8*) (cnt_id + (2*cmd->n_entries));
|
||||
u8* cnt_cmac = (u8*) (cnt_id_2nd + cmd->n_cmacs);
|
||||
memset(cmd->cmac, 0xFF, 0x10);
|
||||
memset(cnt_cmac, 0xFF, 0x10 * content_count);
|
||||
memset(cnt_cmac, 0xFF, 0x10 * cmd->n_entries);
|
||||
|
||||
// we still need to fix / set the CMACs inside the CMD file!
|
||||
return 0;
|
||||
return cmd;
|
||||
}
|
||||
|
@ -3,9 +3,10 @@
|
||||
#include "common.h"
|
||||
#include "tmd.h"
|
||||
|
||||
#define CMD_SIZE_N(n) (sizeof(CmdHeader) + ((n)*(sizeof(u32)+sizeof(u32)+0x10)))
|
||||
#define CMD_SIZE_NS(n) (sizeof(CmdHeader) + ((n)*(sizeof(u32)+sizeof(u32))))
|
||||
|
||||
#define CMD_SIZE(cmd) (sizeof(CmdHeader) + \
|
||||
(((cmd)->n_entries) * sizeof(u32)) + \
|
||||
(((cmd)->n_cmacs) * sizeof(u32)) + \
|
||||
(((cmd)->unknown) ? (((cmd)->n_entries) * 0x10) : 0))
|
||||
|
||||
// from: http://3dbrew.org/wiki/Titles#Data_Structure
|
||||
typedef struct {
|
||||
@ -19,5 +20,4 @@ typedef struct {
|
||||
// followed by <n_entries> CMACs (may contain garbage)
|
||||
} __attribute__((packed, aligned(4))) CmdHeader;
|
||||
|
||||
u32 CheckCmdSize(CmdHeader* cmd, u64 fsize);
|
||||
u32 BuildCmdData(CmdHeader* cmd, TitleMetaData* tmd);
|
||||
CmdHeader* BuildAllocCmdData(TitleMetaData* tmd);
|
||||
|
@ -25,7 +25,7 @@ u32 BuildTitleInfoEntryTmd(TitleInfoEntry* tie, TitleMetaData* tmd, bool sd) {
|
||||
tie->title_size =
|
||||
(align_size * 3) + // base folder + 'content' + 'cmd'
|
||||
align(TMD_SIZE_N(content_count), align_size) + // TMD
|
||||
align(CMD_SIZE_N(content_count), align_size); // CMD
|
||||
align_size; // CMD, placeholder
|
||||
for (u32 i = 0; (i < content_count) && (i < TMD_MAX_CONTENTS); i++, chunk++) {
|
||||
if (getbe32(chunk->id) == 1) has_id1 = true; // will be useful later
|
||||
tie->title_size += align(getbe64(chunk->size), align_size);
|
||||
|
@ -1402,10 +1402,9 @@ u32 InstallCiaSystemData(CiaStub* cia, const char* drv) {
|
||||
return 1;
|
||||
|
||||
// build the cmd
|
||||
cmd = (CmdHeader*) malloc(CMD_SIZE_N(content_count));
|
||||
cmd = BuildAllocCmdData(tmd);
|
||||
if (!cmd) return 1;
|
||||
BuildCmdData(cmd, tmd);
|
||||
if (!syscmd) cmd->unknown = 0xFFFFFFFE; // mark this as custom built
|
||||
cmd->unknown = 0xFFFFFFFE; // mark this as custom built
|
||||
|
||||
// generate all the paths
|
||||
snprintf(path_titledb, 32, "%2.2s/dbs/title.db",
|
||||
@ -1423,8 +1422,7 @@ u32 InstallCiaSystemData(CiaStub* cia, const char* drv) {
|
||||
fvx_rmkpath(path_tmd);
|
||||
fvx_rmkpath(path_cmd);
|
||||
if ((fvx_qwrite(path_tmd, tmd, 0, TMD_SIZE_N(content_count), NULL) != FR_OK) ||
|
||||
(fvx_qwrite(path_cmd, cmd, 0,
|
||||
syscmd ? CMD_SIZE_NS(content_count) : CMD_SIZE_N(content_count), NULL) != FR_OK)) {
|
||||
(fvx_qwrite(path_cmd, cmd, 0, CMD_SIZE(cmd), NULL) != FR_OK)) {
|
||||
free(cmd);
|
||||
return 1;
|
||||
}
|
||||
@ -1963,7 +1961,7 @@ u32 BuildInstallFromNcsdFile(const char* path_ncsd, const char* path_dest, bool
|
||||
if ((!install && (InsertCiaContent(path_dest, path_ncsd,
|
||||
offset, size, chunk++, NULL, false, (i == 0), false) != 0)) ||
|
||||
(install && (InstallCiaContent(path_dest, path_ncsd,
|
||||
offset, size, chunk, title_id, NULL, (i == 0)) != 0))) {
|
||||
offset, size, chunk++, title_id, NULL, (i == 0)) != 0))) {
|
||||
free(cia);
|
||||
return 1;
|
||||
}
|
||||
@ -2161,9 +2159,8 @@ u32 InstallGameFile(const char* path, bool to_emunand, bool force_nand) {
|
||||
to_sd = true;
|
||||
|
||||
// does the title.db exist?
|
||||
if (to_sd && !fvx_qsize(to_emunand ? "B:/dbs/title.db" : "A:/dbs/title.db"))
|
||||
to_sd = false;
|
||||
if (!to_sd && !fvx_qsize(to_emunand ? "4:/dbs/title.db" : "1:/dbs/title.db"))
|
||||
if ((to_sd && !fvx_qsize(to_emunand ? "B:/dbs/title.db" : "A:/dbs/title.db")) ||
|
||||
(!to_sd && !fvx_qsize(to_emunand ? "4:/dbs/title.db" : "1:/dbs/title.db")))
|
||||
return 1;
|
||||
|
||||
// now we know the correct drive
|
||||
@ -2411,7 +2408,6 @@ u32 LoadSmdhFromGameFile(const char* path, Smdh* smdh) {
|
||||
if (LoadExeFsFile(smdh, path, NCSD_CNT0_OFFSET, "icon", sizeof(Smdh), NULL) == 0) return 0;
|
||||
} else if (filetype & GAME_CIA) { // CIA file
|
||||
CiaInfo info;
|
||||
|
||||
if ((fvx_qread(path, &info, 0, 0x20, NULL) != FR_OK) ||
|
||||
(GetCiaInfo(&info, (CiaHeader*) &info) != 0)) return 1;
|
||||
if ((info.offset_meta) && (fvx_qread(path, smdh, info.offset_meta + 0x400, sizeof(Smdh), NULL) == FR_OK)) return 0;
|
||||
|
@ -374,7 +374,7 @@ u32 CheckFixCmdCmac(const char* path, bool fix) {
|
||||
|
||||
// read the full file to memory and check it (we may write it back later)
|
||||
if ((fvx_qread(path, cmd_data, 0, cmd_size, NULL) != FR_OK) ||
|
||||
(CheckCmdSize(cmd, cmd_size) != 0)) {
|
||||
(CMD_SIZE(cmd) != cmd_size)) {
|
||||
free(cmd_data);
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user