From 6a5b13ea0953c5e844b55f5f8f8c574a7d4fea94 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Wed, 10 May 2017 21:59:22 +0200 Subject: [PATCH] Sourcecode cleanup / reorganization --- source/game/gameutil.c | 182 ++++++++++++++++++----------------------- source/game/gameutil.h | 2 +- source/game/nds.c | 10 ++- source/game/nds.h | 24 ++++-- source/game/smdh.h | 9 ++ 5 files changed, 116 insertions(+), 111 deletions(-) diff --git a/source/game/gameutil.c b/source/game/gameutil.c index cb5cd66..ab452ad 100644 --- a/source/game/gameutil.c +++ b/source/game/gameutil.c @@ -13,29 +13,6 @@ #define CRYPTO_DECRYPT NCCH_NOCRYPTO #define CRYPTO_ENCRYPT NCCH_STDCRYPTO -u64 GetTitleId(const char* path) { - u32 filetype = IdentifyFileType(path); - UINT br; - if (filetype & GAME_TMD) { - TitleMetaData* tmd = (TitleMetaData*) (void*) TEMP_BUFFER; - if ((fvx_qread(path, tmd, 0, TMD_SIZE_MIN, &br) == FR_OK) && - (br == TMD_SIZE_MIN)) return getbe64(tmd->title_id); - } else if (filetype & GAME_NCCH) { - NcchHeader* ncch = (NcchHeader*) (void*) TEMP_BUFFER; - if ((fvx_qread(path, ncch, 0, sizeof(NcchHeader), &br) == FR_OK) && - (br == sizeof(NcchHeader))) return ncch->programId; - } else if (filetype & GAME_NCSD) { - NcsdHeader* ncsd = (NcsdHeader*) (void*) TEMP_BUFFER; - if ((fvx_qread(path, ncsd, 0, sizeof(NcsdHeader), &br) == FR_OK) && - (br == sizeof(NcsdHeader))) return ncsd->mediaId; - } else if (filetype & GAME_NDS) { - TwlHeader* twl = (TwlHeader*) (void*) TEMP_BUFFER; - if ((fvx_qread(path, twl, 0, sizeof(TwlHeader), &br) == FR_OK) && - (br == sizeof(TwlHeader))) return twl->title_id; - } // ignored: CIA, ticket - return 0; -} - u32 GetNcchHeaders(NcchHeader* ncch, NcchExtHeader* exthdr, ExeFsHeader* exefs, FIL* file) { u32 offset_ncch = fvx_tell(file); UINT btr; @@ -1372,6 +1349,50 @@ u32 BuildCiaFromGameFile(const char* path, bool force_legit) { return ret; } +u32 LoadSmdhFromGameFile(const char* path, Smdh* smdh) { + u32 filetype = IdentifyFileType(path); + + if (filetype & GAME_SMDH) { // SMDH file + UINT btr; + if ((fvx_qread(path, smdh, 0, sizeof(Smdh), &btr) == FR_OK) || (btr == sizeof(Smdh))) return 0; + } else if (filetype & GAME_NCCH) { // NCCH file + if (LoadExeFsFile(smdh, path, 0, "icon", sizeof(Smdh)) == 0) return 0; + } else if (filetype & GAME_NCSD) { // NCSD file + if (LoadExeFsFile(smdh, path, NCSD_CNT0_OFFSET, "icon", sizeof(Smdh)) == 0) return 0; + } else if (filetype & GAME_CIA) { // CIA file + CiaInfo info; + UINT btr; + + if ((fvx_qread(path, &info, 0, 0x20, &btr) != FR_OK) || (btr != 0x20) || + (GetCiaInfo(&info, (CiaHeader*) &info) != 0)) return 1; + if ((info.offset_meta) && (fvx_qread(path, smdh, info.offset_meta + 0x400, sizeof(Smdh), &btr) == FR_OK) && + (btr == sizeof(Smdh))) return 0; + else if (LoadExeFsFile(smdh, path, info.offset_content, "icon", sizeof(Smdh)) == 0) return 0; + } else if (filetype & GAME_TMD) { + const u8 dlc_tid_high[] = { DLC_TID_HIGH }; + TitleMetaData* tmd = (TitleMetaData*) TEMP_BUFFER; + TmdContentChunk* chunk = (TmdContentChunk*) (tmd + 1); + + // content path string + char path_content[256]; + char* name_content; + strncpy(path_content, path, 256); + name_content = strrchr(path_content, '/'); + if (!name_content) return 1; // will not happen + name_content++; + + // load TMD file + if ((LoadTmdFile(tmd, path) != 0) || !getbe16(tmd->content_count)) + return 1; + snprintf(name_content, 256 - (name_content - path_content), + (memcmp(tmd->title_id, dlc_tid_high, sizeof(dlc_tid_high)) == 0) ? "00000000/%08lx.app" : "%08lx.app", getbe32(chunk->id)); + + return LoadSmdhFromGameFile(path_content, smdh); + } + + return 1; +} + u32 ShowSmdhTitleInfo(Smdh* smdh) { const u32 lwrap = 24; u8* icon = (u8*) (TEMP_BUFFER + sizeof(Smdh)); @@ -1392,71 +1413,12 @@ u32 ShowSmdhTitleInfo(Smdh* smdh) { return 0; } -u32 ShowSmdhFileTitleInfo(const char* path) { - Smdh* smdh = (Smdh*) (void*) TEMP_BUFFER; - UINT btr; - if ((fvx_qread(path, smdh, 0, sizeof(Smdh), &btr) != FR_OK) || (btr != sizeof(Smdh))) - return 1; - return ShowSmdhTitleInfo(smdh); -} - -u32 ShowNcchFileTitleInfo(const char* path) { - Smdh* smdh = (Smdh*) (void*) TEMP_BUFFER; - if (LoadExeFsFile(smdh, path, 0, "icon", sizeof(Smdh)) != 0) - return 1; - return ShowSmdhTitleInfo(smdh); -} - -u32 ShowNcsdFileTitleInfo(const char* path) { - Smdh* smdh = (Smdh*) (void*) TEMP_BUFFER; - if (LoadExeFsFile(smdh, path, NCSD_CNT0_OFFSET, "icon", sizeof(Smdh)) != 0) - return 1; - return ShowSmdhTitleInfo(smdh); -} - -u32 ShowCiaFileTitleInfo(const char* path) { - Smdh* smdh = (Smdh*) (void*) TEMP_BUFFER; - CiaInfo info; - UINT btr; - - if ((fvx_qread(path, &info, 0, 0x20, &btr) != FR_OK) || (btr != 0x20) || - (GetCiaInfo(&info, (CiaHeader*) &info) != 0)) - return 1; - if ((info.offset_meta) && ((fvx_qread(path, smdh, info.offset_meta + 0x400, sizeof(Smdh), &btr) != FR_OK) || - (btr != sizeof(Smdh)))) return 1; - else if (LoadExeFsFile(smdh, path, info.offset_content, "icon", sizeof(Smdh)) != 0) return 1; - - return ShowSmdhTitleInfo(smdh); -} - -u32 ShowTmdFileTitleInfo(const char* path) { - const u8 dlc_tid_high[] = { DLC_TID_HIGH }; - TitleMetaData* tmd = (TitleMetaData*) TEMP_BUFFER; - TmdContentChunk* chunk = (TmdContentChunk*) (tmd + 1); - - // content path string - char path_content[256]; - char* name_content; - strncpy(path_content, path, 256); - name_content = strrchr(path_content, '/'); - if (!name_content) return 1; // will not happen - name_content++; - - // load TMD file - if ((LoadTmdFile(tmd, path) != 0) || !getbe16(tmd->content_count)) - return 1; - snprintf(name_content, 256 - (name_content - path_content), - (memcmp(tmd->title_id, dlc_tid_high, sizeof(dlc_tid_high)) == 0) ? "00000000/%08lx.app" : "%08lx.app", getbe32(chunk->id)); - - return ShowGameFileTitleInfo(path_content); -} - u32 ShowNdsFileTitleInfo(const char* path) { const u32 lwrap = 24; TwlIconData* twl_icon = (TwlIconData*) TEMP_BUFFER; u8* icon = (u8*) (TEMP_BUFFER + sizeof(TwlIconData)); char* desc = (char*) icon + TWLICON_SIZE_ICON; - if ((LoadTwlIconData(path, twl_icon) != 0) || + if ((LoadTwlMetaData(path, NULL, twl_icon) != 0) || (GetTwlIcon(icon, twl_icon) != 0) || (GetTwlTitle(desc, twl_icon) != 0)) return 1; @@ -1469,25 +1431,12 @@ u32 ShowNdsFileTitleInfo(const char* path) { } u32 ShowGameFileTitleInfo(const char* path) { - u32 filetype = IdentifyFileType(path); - u32 ret = 1; + Smdh* smdh = (Smdh*) (void*) TEMP_BUFFER; - // build CIA from game file - if (filetype & GAME_SMDH) { - ret = ShowSmdhFileTitleInfo(path); - } else if (filetype & GAME_NCCH) { - ret = ShowNcchFileTitleInfo(path); - } else if (filetype & GAME_NCSD) { - ret = ShowNcsdFileTitleInfo(path); - } else if (filetype & GAME_CIA) { - ret = ShowCiaFileTitleInfo(path); - } else if (filetype & GAME_TMD) { - ret = ShowTmdFileTitleInfo(path); - } else if (filetype & GAME_NDS) { - ret = ShowNdsFileTitleInfo(path); - } - - return ret; + // try loading SMDH, then try NDS + if (LoadSmdhFromGameFile(path, smdh) == 0) + return ShowSmdhTitleInfo(smdh); + else return ShowNdsFileTitleInfo(path); } u32 BuildNcchInfoXorpads(const char* destdir, const char* path) { @@ -1816,3 +1765,34 @@ u32 BuildSeedInfo(const char* path, bool dump) { return 0; } + +u64 GetTitleId(const char* path) { + u32 filetype = IdentifyFileType(path); + UINT br; + + if (filetype & GAME_TMD) { + TitleMetaData* tmd = (TitleMetaData*) (void*) TEMP_BUFFER; + if ((fvx_qread(path, tmd, 0, TMD_SIZE_MIN, &br) == FR_OK) && + (br == TMD_SIZE_MIN) && (ValidateTmd(tmd) == 0)) return getbe64(tmd->title_id); + } else if (filetype & GAME_NCCH) { + NcchHeader* ncch = (NcchHeader*) (void*) TEMP_BUFFER; + if ((fvx_qread(path, ncch, 0, sizeof(NcchHeader), &br) == FR_OK) && + (br == sizeof(NcchHeader)) && (ValidateNcchHeader(ncch) == 0)) return ncch->programId; + } else if (filetype & GAME_NCSD) { + NcsdHeader* ncsd = (NcsdHeader*) (void*) TEMP_BUFFER; + if ((fvx_qread(path, ncsd, 0, sizeof(NcsdHeader), &br) == FR_OK) && + (br == sizeof(NcsdHeader)) && (ValidateNcsdHeader(ncsd) == 0)) return ncsd->mediaId; + } else if (filetype & GAME_NDS) { + TwlHeader* twl = (TwlHeader*) (void*) TEMP_BUFFER; + if ((twl->unit_code & 0x02) && (fvx_qread(path, twl, 0, sizeof(TwlHeader), &br) == FR_OK) && + (br == sizeof(TwlHeader))) return twl->title_id; + } else if (filetype & GAME_CIA) { + TitleMetaData* tmd = (TitleMetaData*) (void*) TEMP_BUFFER; + CiaInfo info; + if ((fvx_qread(path, &info, 0, 0x20, &br) == FR_OK) && (br == 0x20) && + (GetCiaInfo(&info, (CiaHeader*) &info) == 0) && (fvx_qread(path, tmd, info.offset_tmd, TMD_SIZE_MIN, &br) == FR_OK) && + (br == TMD_SIZE_MIN) && (ValidateTmd(tmd) == 0)) return getbe64(tmd->title_id); + } + + return 0; +} diff --git a/source/game/gameutil.h b/source/game/gameutil.h index 6f32aee..1f5d1df 100644 --- a/source/game/gameutil.h +++ b/source/game/gameutil.h @@ -12,4 +12,4 @@ 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); -u64 GetTitleId(const char* path); +u64 GetTitleIdFromGameFile(const char* path); diff --git a/source/game/nds.c b/source/game/nds.c index 036eac1..d5a8156 100644 --- a/source/game/nds.c +++ b/source/game/nds.c @@ -28,14 +28,16 @@ u32 ValidateTwlHeader(TwlHeader* twl) { return (crc16_quick(twl->logo, sizeof(twl->logo)) == NDS_LOGO_CRC16) ? 0 : 1; } -u32 LoadTwlIconData(const char* path, TwlIconData* icon) { +u32 LoadTwlMetaData(const char* path, TwlHeader* hdr, TwlIconData* icon) { u8 ntr_header[0x200]; // we only need the NTR header (ignore TWL stuff) - TwlHeader* twl = (TwlHeader*) ntr_header; + TwlHeader* twl = hdr ? hdr : (TwlHeader*) ntr_header; + u32 hdr_size = hdr ? sizeof(TwlHeader) : 0x200; // load full header if bufefr provided UINT br; - if ((fvx_qread(path, ntr_header, 0, 0x200, &br) != FR_OK) || (br != 0x200) || + if ((fvx_qread(path, ntr_header, 0, hdr_size, &br) != FR_OK) || (br != hdr_size) || (ValidateTwlHeader(twl) != 0)) return 1; - // we also don't need anything beyond the v0x0001 icon, so ignore this, too + if (!icon) return 0; // done if icon data is not required + // we don't need anything beyond the v0x0001 icon, so ignore the remainder if ((fvx_qread(path, icon, twl->icon_offset, TWLICON_SIZE_DATA(0x0001), &br) != FR_OK) || (br != TWLICON_SIZE_DATA(0x0001)) || (!TWLICON_SIZE_DATA(icon->version)) || (crc16_quick(((u8*) icon) + 0x20, TWLICON_SIZE_DATA(0x0001) - 0x20) != icon->crc_0x0020_0x0840)) return 1; diff --git a/source/game/nds.h b/source/game/nds.h index 87919e7..5940720 100644 --- a/source/game/nds.h +++ b/source/game/nds.h @@ -15,6 +15,18 @@ #define TWLICON_SIZE_ICON (TWLICON_DIM_ICON * TWLICON_DIM_ICON * 3) // w * h * bpp (rgb888) #define NDS_LOGO_CRC16 0xCF56 +#define TWL_UNITCODE_NTR 0x00 +#define TWL_UNITCODE_TWLNTR 0x02 +#define TWL_UNITCODE_TWL 0x03 + +#define TWL_REGION_JAP 0x01 +#define TWL_REGION_USA 0x02 +#define TWL_REGION_EUR 0x04 +#define TWL_REGION_AUS 0x08 +#define TWL_REGION_CHN 0x10 +#define TWL_REGION_KOR 0x20 +#define TWL_REGION_FREE 0xFFFFFFFF + // see: http://problemkaputt.de/gbatek.htm#dscartridgeicontitle typedef struct { u16 version; @@ -88,7 +100,9 @@ typedef struct { u16 header_crc; u8 debugger_reserved[0x20]; // extended mode stuff (DSi only) - u8 ignored0[0x40]; // ignored + u8 ignored0[0x30]; // ignored + u32 region_flags; + u8 ignored1[0xC]; // ignored u32 arm9i_rom_offset; u32 reserved2; u32 arm9i_load_adress; @@ -97,19 +111,19 @@ typedef struct { u32 unknown1; u32 arm7i_load_adress; u32 arm7i_size; - u8 ignored1[0x30]; // ignored + u8 ignored2[0x30]; // ignored u32 ntr_twl_rom_size; u8 unknown2[12]; - u8 ignored2[0x10]; // ignored + u8 ignored3[0x10]; // ignored u64 title_id; u32 pubsav_size; u32 prvsav_size; u8 reserved3[176]; u8 unknown3[0x10]; - u8 ignored3[0xD00]; // ignored + u8 ignored4[0xD00]; // ignored } __attribute__((packed)) TwlHeader; u32 ValidateTwlHeader(TwlHeader* twl); -u32 LoadTwlIconData(const char* path, TwlIconData* icon); +u32 LoadTwlMetaData(const char* path, TwlHeader* hdr, TwlIconData* icon); u32 GetTwlTitle(char* desc, const TwlIconData* twl_icon); u32 GetTwlIcon(u8* icon, const TwlIconData* twl_icon); diff --git a/source/game/smdh.h b/source/game/smdh.h index 82899a7..536375e 100644 --- a/source/game/smdh.h +++ b/source/game/smdh.h @@ -11,6 +11,15 @@ #define SMDH_SIZE_ICON_SMALL (SMDH_DIM_ICON_SMALL * SMDH_DIM_ICON_SMALL * 3) // w * h * bpp (rgb888) #define SMDH_SIZE_ICON_BIG (SMDH_DIM_ICON_BIG * SMDH_DIM_ICON_BIG * 3) // w * h * bpp (rgb888) +#define SMDH_REGION_JAP 0x01 +#define SMDH_REGION_USA 0x02 +#define SMDH_REGION_EUR 0x04 +#define SMDH_REGION_AUS 0x08 +#define SMDH_REGION_CHN 0x10 +#define SMDH_REGION_KOR 0x20 +#define SMDH_REGION_TWN 0x40 +#define SMDH_REGION_FREE 0x7FFFFFFF + // see: https://www.3dbrew.org/wiki/SMDH#Application_Titles typedef struct { u16 short_desc[0x40];