Show title info for 3DSX files

This commit is contained in:
d0k3 2017-10-29 15:32:25 +01:00
parent a9eaf45a8e
commit d413e71c01
6 changed files with 54 additions and 18 deletions

View File

@ -11,6 +11,8 @@ u64 IdentifyFileType(const char* path) {
const u8 romfs_magic[] = { ROMFS_MAGIC }; const u8 romfs_magic[] = { ROMFS_MAGIC };
const u8 tickdb_magic[] = { TICKDB_MAGIC }; const u8 tickdb_magic[] = { TICKDB_MAGIC };
const u8 smdh_magic[] = { SMDH_MAGIC }; const u8 smdh_magic[] = { SMDH_MAGIC };
const u8 threedsx_magic[] = { THREEDSX_EXT_MAGIC };
if (!path) return 0; // safety if (!path) return 0; // safety
u8 header[0x200] __attribute__((aligned(32))); // minimum required size u8 header[0x200] __attribute__((aligned(32))); // minimum required size
void* data = (void*) header; void* data = (void*) header;
@ -95,6 +97,9 @@ u64 IdentifyFileType(const char* path) {
} else if ((fsize > sizeof(BossHeader)) && } else if ((fsize > sizeof(BossHeader)) &&
(ValidateBossHeader((BossHeader*) data, fsize) == 0)) { (ValidateBossHeader((BossHeader*) data, fsize) == 0)) {
return GAME_BOSS; // BOSS (SpotPass) file return GAME_BOSS; // BOSS (SpotPass) file
} else if ((fsize > sizeof(ThreedsxHeader)) &&
(memcmp(data, threedsx_magic, sizeof(threedsx_magic)) == 0)) {
return GAME_3DSX; // 3DSX (executable) file
} else if ((fsize > sizeof(NcchInfoHeader)) && } else if ((fsize > sizeof(NcchInfoHeader)) &&
(GetNcchInfoVersion((NcchInfoHeader*) data)) && (GetNcchInfoVersion((NcchInfoHeader*) data)) &&
fname && (strncasecmp(fname, NCCHINFO_NAME, 32) == 0)) { fname && (strncasecmp(fname, NCCHINFO_NAME, 32) == 0)) {

View File

@ -14,19 +14,20 @@
#define GAME_NUSCDN (1ULL<<9) #define GAME_NUSCDN (1ULL<<9)
#define GAME_TICKET (1ULL<<10) #define GAME_TICKET (1ULL<<10)
#define GAME_SMDH (1ULL<<11) #define GAME_SMDH (1ULL<<11)
#define GAME_NDS (1ULL<<12) #define GAME_3DSX (1ULL<<12)
#define GAME_GBA (1ULL<<13) #define GAME_NDS (1ULL<<13)
#define SYS_FIRM (1ULL<<14) #define GAME_GBA (1ULL<<14)
#define SYS_AGBSAVE (1ULL<<15) #define SYS_FIRM (1ULL<<15)
#define SYS_TICKDB (1ULL<<16) #define SYS_AGBSAVE (1ULL<<16)
#define BIN_NCCHNFO (1ULL<<17) #define SYS_TICKDB (1ULL<<17)
#define BIN_TIKDB (1ULL<<18) #define BIN_NCCHNFO (1ULL<<18)
#define BIN_KEYDB (1ULL<<19) #define BIN_TIKDB (1ULL<<19)
#define BIN_LEGKEY (1ULL<<20) #define BIN_KEYDB (1ULL<<20)
#define TXT_SCRIPT (1ULL<<21) #define BIN_LEGKEY (1ULL<<21)
#define TXT_GENERIC (1ULL<<22) #define TXT_SCRIPT (1ULL<<22)
#define NOIMG_NAND (1ULL<<23) #define TXT_GENERIC (1ULL<<23)
#define HDR_NAND (1ULL<<24) #define NOIMG_NAND (1ULL<<24)
#define HDR_NAND (1ULL<<25)
#define TYPE_BASE 0xFFFFFFFFULL // 32 bit reserved for base types #define TYPE_BASE 0xFFFFFFFFULL // 32 bit reserved for base types
#define FLAG_GBAVC (1ULL<<59) #define FLAG_GBAVC (1ULL<<59)
@ -44,7 +45,7 @@
#define FTYPE_CXIDUMP(tp) (tp&(GAME_TMD)) #define FTYPE_CXIDUMP(tp) (tp&(GAME_TMD))
#define FTYPE_TIKBUILD(tp) (tp&(GAME_TICKET|SYS_TICKDB|BIN_TIKDB)) #define FTYPE_TIKBUILD(tp) (tp&(GAME_TICKET|SYS_TICKDB|BIN_TIKDB))
#define FTYPE_KEYBUILD(tp) (tp&(BIN_KEYDB|BIN_LEGKEY)) #define FTYPE_KEYBUILD(tp) (tp&(BIN_KEYDB|BIN_LEGKEY))
#define FTYPE_TITLEINFO(tp) (tp&(GAME_SMDH|GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_TMD|GAME_NDS|GAME_GBA)) #define FTYPE_TITLEINFO(tp) (tp&(GAME_SMDH|GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_TMD|GAME_NDS|GAME_GBA|GAME_3DSX))
#define FTYPE_RENAMABLE(tp) (tp&(GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_NDS|GAME_GBA)) #define FTYPE_RENAMABLE(tp) (tp&(GAME_NCCH|GAME_NCSD|GAME_CIA|GAME_NDS|GAME_GBA))
#define FTYPE_TRANSFERABLE(tp) ((u64) (tp&(IMG_FAT|FLAG_CTR)) == (u64) (IMG_FAT|FLAG_CTR)) #define FTYPE_TRANSFERABLE(tp) ((u64) (tp&(IMG_FAT|FLAG_CTR)) == (u64) (IMG_FAT|FLAG_CTR))
#define FTYPE_NCSDFIXABLE(tp) (tp&(HDR_NAND|NOIMG_NAND)) #define FTYPE_NCSDFIXABLE(tp) (tp&(HDR_NAND|NOIMG_NAND))

23
source/game/3dsx.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include "common.h"
#define THREEDSX_MAGIC '3', 'D', 'S', 'X'
#define THREEDSX_EXT_MAGIC THREEDSX_MAGIC, 0x2C, 0x00
// see: http://3dbrew.org/wiki/3DSX_Format
typedef struct {
u8 magic[4]; // "3DSX"
u16 size_hdr; // 0x2C with extended header
u16 size_reloc_hdr; // 0x08 if existing
u32 version; // should be zero
u32 flags; // should be zero, too
u32 size_code;
u32 size_rodata;
u32 size_data_bss;
u32 size_bss;
u32 offset_smdh;
u32 size_smdh;
u32 size_romfs_lv3;
} __attribute__((packed)) ThreedsxHeader;

View File

@ -11,4 +11,5 @@
#include "codelzss.h" #include "codelzss.h"
#include "nds.h" #include "nds.h"
#include "gba.h" #include "gba.h"
#include "3dsx.h"
#include "ncchinfo.h" #include "ncchinfo.h"

View File

@ -924,6 +924,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
(filetype & GAME_NDS) ? "NDS image options..." : (filetype & GAME_NDS) ? "NDS image options..." :
(filetype & GAME_GBA) ? "GBA image options..." : (filetype & GAME_GBA) ? "GBA image options..." :
(filetype & GAME_TICKET)? "Ticket options..." : (filetype & GAME_TICKET)? "Ticket options..." :
(filetype & GAME_3DSX) ? "Show 3DSX title info" :
(filetype & SYS_FIRM ) ? "FIRM image options..." : (filetype & SYS_FIRM ) ? "FIRM image options..." :
(filetype & SYS_AGBSAVE)? (agbimportable) ? "AGBSAVE options..." : "Dump GBA VC save" : (filetype & SYS_AGBSAVE)? (agbimportable) ? "AGBSAVE options..." : "Dump GBA VC save" :
(filetype & SYS_TICKDB) ? (tik_buildable) ? "Ticket.db options..." : "Mount as ticket.db" : (filetype & SYS_TICKDB) ? (tik_buildable) ? "Ticket.db options..." : "Mount as ticket.db" :

View File

@ -1469,17 +1469,22 @@ u32 LoadSmdhFromGameFile(const char* path, Smdh* smdh) {
if (LoadExeFsFile(smdh, path, NCSD_CNT0_OFFSET, "icon", sizeof(Smdh), NULL) == 0) return 0; if (LoadExeFsFile(smdh, path, NCSD_CNT0_OFFSET, "icon", sizeof(Smdh), NULL) == 0) return 0;
} else if (filetype & GAME_CIA) { // CIA file } else if (filetype & GAME_CIA) { // CIA file
CiaInfo info; CiaInfo info;
UINT btr;
if ((fvx_qread(path, &info, 0, 0x20, &btr) != FR_OK) || (btr != 0x20) || if ((fvx_qread(path, &info, 0, 0x20, NULL) != FR_OK) ||
(GetCiaInfo(&info, (CiaHeader*) &info) != 0)) return 1; (GetCiaInfo(&info, (CiaHeader*) &info) != 0)) return 1;
if ((info.offset_meta) && (fvx_qread(path, smdh, info.offset_meta + 0x400, sizeof(Smdh), &btr) == FR_OK) && if ((info.offset_meta) && (fvx_qread(path, smdh, info.offset_meta + 0x400, sizeof(Smdh), NULL) == FR_OK)) return 0;
(btr == sizeof(Smdh))) return 0;
else if (LoadExeFsFile(smdh, path, info.offset_content, "icon", sizeof(Smdh), NULL) == 0) return 0; else if (LoadExeFsFile(smdh, path, info.offset_content, "icon", sizeof(Smdh), NULL) == 0) return 0;
} else if (filetype & GAME_TMD) { } else if (filetype & GAME_TMD) {
char path_content[256]; char path_content[256];
if (GetTmdContentPath(path_content, path) != 0) return 1; if (GetTmdContentPath(path_content, path) != 0) return 1;
return LoadSmdhFromGameFile(path_content, smdh); return LoadSmdhFromGameFile(path_content, smdh);
} else if (filetype & GAME_3DSX) {
ThreedsxHeader threedsx;
if ((fvx_qread(path, &threedsx, 0, sizeof(ThreedsxHeader), NULL) != FR_OK) ||
(!threedsx.offset_smdh || (threedsx.size_smdh != sizeof(Smdh))) ||
(fvx_qread(path, smdh, threedsx.offset_smdh, sizeof(Smdh), NULL) != FR_OK))
return 1;
return 0;
} }
return 1; return 1;