forked from Mirror/GodMode9
Sourcecode cleanup / reorganization
This commit is contained in:
parent
e510ac76c4
commit
6a5b13ea09
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user