Sourcecode cleanup / reorganization

This commit is contained in:
d0k3 2017-05-10 21:59:22 +02:00
parent e510ac76c4
commit 6a5b13ea09
5 changed files with 116 additions and 111 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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];