2020-07-25 06:56:35 +01:00
/*
* title . h
*
2020-12-23 17:48:57 +00:00
* Copyright ( c ) 2020 - 2021 , DarkMatterCore < pabloacurielz @ gmail . com > .
2020-07-25 06:56:35 +01:00
*
* This file is part of nxdumptool ( https : //github.com/DarkMatterCore/nxdumptool).
*
* nxdumptool is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* nxdumptool is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# pragma once
2021-03-24 17:25:19 +00:00
# ifndef __TITLE_H__
# define __TITLE_H__
2021-03-23 14:06:52 +00:00
# ifdef __cplusplus
extern " C " {
# endif
2020-07-28 07:20:19 +01:00
# define TITLE_PATCH_TYPE_VALUE (u64)0x800
2020-07-25 06:56:35 +01:00
2020-07-28 07:20:19 +01:00
# define TITLE_ADDONCONTENT_TYPE_VALUE (u64)0x1000
2020-07-28 04:32:08 +01:00
# define TITLE_ADDONCONTENT_CONVERSION_MASK (u64)0xFFFFFFFFFFFFF000
# define TITLE_ADDONCONTENT_MAX_ENTRIES 2000
2020-07-28 07:20:19 +01:00
# define TITLE_DELTA_TYPE_VALUE (u64)0xC00
2020-07-28 04:32:08 +01:00
2021-02-22 21:30:47 +00:00
/// Generated using ns application records and/or ncm content meta keys.
2020-07-28 04:32:08 +01:00
/// Used by the UI to display title lists.
2020-07-25 06:56:35 +01:00
typedef struct {
2020-07-28 04:32:08 +01:00
u64 title_id ; ///< Title ID from the application / system title this data belongs to.
2020-07-26 05:57:12 +01:00
NacpLanguageEntry lang_entry ; ///< UTF-8 strings in the console language.
2020-07-25 06:56:35 +01:00
u32 icon_size ; ///< JPEG icon size.
2020-07-28 04:32:08 +01:00
u8 * icon ; ///< JPEG icon data.
2020-07-25 06:56:35 +01:00
} TitleApplicationMetadata ;
2021-02-22 21:30:47 +00:00
/// Generated using ncm databases.
2020-07-28 04:32:08 +01:00
typedef struct _TitleInfo {
u8 storage_id ; ///< NcmStorageId.
NcmContentMetaKey meta_key ; ///< Used with ncm calls.
2020-10-08 19:31:09 +01:00
VersionType1 version ; ///< Holds the same value from meta_key.version.
2020-07-28 04:32:08 +01:00
u32 content_count ; ///< Content info count.
NcmContentInfo * content_infos ; ///< Content info entries from this title.
2020-10-21 05:27:48 +01:00
u64 size ; ///< Total title size.
char size_str [ 32 ] ; ///< Total title size string.
2021-01-31 09:16:05 +00:00
TitleApplicationMetadata * app_metadata ; ///< User application metadata.
2020-08-13 19:12:33 +01:00
struct _TitleInfo * parent , * previous , * next ; ///< Used with TitleInfo entries from user applications, patches and add-on contents. The parent pointer is unused in user applications.
2020-07-25 06:56:35 +01:00
} TitleInfo ;
2020-07-28 04:32:08 +01:00
/// Used to deal with user applications stored in the eMMC, SD card and/or gamecard.
2020-08-13 19:12:33 +01:00
/// The parent, previous and next pointers from the TitleInfo elements are used to traverse through multiple user applications, patches and/or add-on contents.
2020-07-28 04:32:08 +01:00
typedef struct {
2020-08-13 19:12:33 +01:00
TitleInfo * app_info ; ///< Pointer to a TitleInfo element holding info for the first detected user application entry matching the provided application ID.
TitleInfo * patch_info ; ///< Pointer to a TitleInfo element holding info for the first detected patch entry matching the provided application ID.
TitleInfo * aoc_info ; ///< Pointer to a TitleInfo element holding info for the first detected add-on content entry matching the provided application ID.
2020-07-28 04:32:08 +01:00
} TitleUserApplicationData ;
2020-08-14 03:31:02 +01:00
typedef enum {
TitleFileNameConvention_Full = 0 , ///< Individual titles: "[{Name}] [{TitleId}][v{TitleVersion}][{TitleType}]".
///< Gamecards: "[{Name1}] [{TitleId1}][v{TitleVersion1}] + ... + [{NameN}] [{TitleIdN}][v{TitleVersionN}]".
TitleFileNameConvention_IdAndVersionOnly = 1 ///< Individual titles: "{TitleId}_v{TitleVersion}_{TitleType}".
///< Gamecards: "{TitleId1}_v{TitleVersion1}_{TitleType1} + ... + {TitleIdN}_v{TitleVersionN}_{TitleTypeN}".
} TitleFileNameConvention ;
typedef enum {
TitleFileNameIllegalCharReplaceType_None = 0 ,
TitleFileNameIllegalCharReplaceType_IllegalFsChars = 1 ,
TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly = 2
} TitleFileNameIllegalCharReplaceType ;
2020-07-26 05:57:12 +01:00
/// Initializes the title interface.
bool titleInitialize ( void ) ;
2020-07-25 06:56:35 +01:00
2020-07-26 05:57:12 +01:00
/// Closes the title interface.
void titleExit ( void ) ;
2020-07-25 06:56:35 +01:00
2020-07-26 05:57:12 +01:00
/// Returns a pointer to a ncm database handle using a NcmStorageId value.
NcmContentMetaDatabase * titleGetNcmDatabaseByStorageId ( u8 storage_id ) ;
/// Returns a pointer to a ncm storage handle using a NcmStorageId value.
NcmContentStorage * titleGetNcmStorageByStorageId ( u8 storage_id ) ;
2020-12-23 18:43:12 +00:00
/// Returns a pointer to a dynamically allocated array of pointers to TitleApplicationMetadata entries, as well as their count. The allocated buffer must be freed by the calling function.
2020-07-29 22:02:21 +01:00
/// If 'is_system' is true, TitleApplicationMetadata entries from available system titles (NcmStorageId_BuiltInSystem) will be returned.
2021-03-10 13:10:43 +00:00
/// Otherwise, TitleApplicationMetadata entries from user applications with available content data (NcmStorageId_BuiltInUser, NcmStorageId_SdCard, NcmStorageId_GameCard) will be returned.
2020-07-28 04:32:08 +01:00
/// Returns NULL if an error occurs.
TitleApplicationMetadata * * titleGetApplicationMetadataEntries ( bool is_system , u32 * out_count ) ;
2020-07-29 22:02:21 +01:00
/// Returns a pointer to a TitleInfo entry with a matching storage ID and title ID.
2020-07-26 05:57:12 +01:00
/// If NcmStorageId_Any is used, the first entry with a matching title ID is returned.
/// Returns NULL if an error occurs.
TitleInfo * titleGetInfoFromStorageByTitleId ( u8 storage_id , u64 title_id ) ;
2020-07-25 06:56:35 +01:00
2020-10-25 15:42:53 +00:00
/// Populates a TitleUserApplicationData element using a user application ID.
2020-07-28 04:32:08 +01:00
bool titleGetUserApplicationData ( u64 app_id , TitleUserApplicationData * out ) ;
2020-07-30 23:37:45 +01:00
/// Returns true if orphan titles are available.
2020-08-13 19:12:33 +01:00
/// Orphan titles are patches or add-on contents with no NsApplicationControlData available for their parent user application ID.
2020-07-30 23:37:45 +01:00
bool titleAreOrphanTitlesAvailable ( void ) ;
2020-12-23 18:43:12 +00:00
/// Returns a pointer to a dynamically allocated array of pointers to TitleInfo entries from orphan titles, as well as their count. The allocated buffer must be freed by the calling function.
2020-07-30 23:37:45 +01:00
/// Returns NULL if an error occurs.
TitleInfo * * titleGetInfoFromOrphanTitles ( u32 * out_count ) ;
2020-10-27 21:23:19 +00:00
/// Checks if a gamecard status update has been detected by the background gamecard title info thread (e.g. after a new gamecard has been inserted, of after the current one has been taken out).
/// If so, gamecard title info entries will be updated or freed during this call, depending on the current gamecard status.
2021-03-10 13:10:43 +00:00
/// If this function returns true and titleGetApplicationMetadataEntries() or titleGetInfoFromOrphanTitles() have been previously called:
/// 1. Their returned buffers should be freed.
/// 2. They must be called again.
2020-07-30 22:43:50 +01:00
bool titleIsGameCardInfoUpdated ( void ) ;
2020-08-14 03:31:02 +01:00
/// Returns a pointer to a dynamically allocated buffer that holds a filename string suitable for output title dumps.
/// Returns NULL if an error occurs.
char * titleGenerateFileName ( const TitleInfo * title_info , u8 name_convention , u8 illegal_char_replace_type ) ;
/// Returns a pointer to a dynamically allocated buffer that holds a filename string suitable for output gamecard dumps.
/// A valid gamecard must be inserted, and title info must have been loaded from it accordingly.
/// Returns NULL if an error occurs.
char * titleGenerateGameCardFileName ( u8 name_convention , u8 illegal_char_replace_type ) ;
2020-10-03 18:09:29 +01:00
/// Returns a pointer to a string holding the name of the provided NcmContentType value. Returns NULL if the provided value is invalid.
2020-07-29 22:02:21 +01:00
const char * titleGetNcmContentTypeName ( u8 content_type ) ;
2020-10-03 18:09:29 +01:00
/// Returns a pointer to a string holding the name of the provided NcmContentMetaType value. Returns NULL if the provided value is invalid.
2020-08-14 03:31:02 +01:00
const char * titleGetNcmContentMetaTypeName ( u8 content_meta_type ) ;
2020-07-25 06:56:35 +01:00
/// Miscellaneous functions.
2020-07-26 05:57:12 +01:00
NX_INLINE void titleConvertNcmContentSizeToU64 ( const u8 * size , u64 * out )
{
if ( ! size | | ! out ) return ;
* out = 0 ;
memcpy ( out , size , 6 ) ;
}
NX_INLINE void titleConvertU64ToNcmContentSize ( const u64 * size , u8 * out )
{
2021-03-10 01:15:40 +00:00
if ( size & & out ) memcpy ( out , size , 6 ) ;
2020-07-26 05:57:12 +01:00
}
2020-07-25 06:56:35 +01:00
NX_INLINE u64 titleGetPatchIdByApplicationId ( u64 app_id )
{
2020-07-28 07:20:19 +01:00
return ( app_id + TITLE_PATCH_TYPE_VALUE ) ;
2020-07-25 06:56:35 +01:00
}
NX_INLINE u64 titleGetApplicationIdByPatchId ( u64 patch_id )
{
2020-07-28 07:20:19 +01:00
return ( patch_id - TITLE_PATCH_TYPE_VALUE ) ;
2020-07-25 06:56:35 +01:00
}
NX_INLINE bool titleCheckIfPatchIdBelongsToApplicationId ( u64 app_id , u64 patch_id )
{
2020-07-28 04:32:08 +01:00
return ( patch_id = = titleGetPatchIdByApplicationId ( app_id ) ) ;
}
NX_INLINE u64 titleGetAddOnContentBaseIdByApplicationId ( u64 app_id )
{
2020-07-28 07:20:19 +01:00
return ( ( app_id & TITLE_ADDONCONTENT_CONVERSION_MASK ) + TITLE_ADDONCONTENT_TYPE_VALUE ) ;
2020-07-28 04:32:08 +01:00
}
NX_INLINE u64 titleGetAddOnContentIdWithIndexByApplicationId ( u64 app_id , u16 idx )
{
return ( titleGetAddOnContentBaseIdByApplicationId ( app_id ) + idx + 1 ) ;
}
NX_INLINE u64 titleGetApplicationIdByAddOnContentId ( u64 aoc_id )
{
2020-07-28 07:20:19 +01:00
return ( ( aoc_id - TITLE_ADDONCONTENT_TYPE_VALUE ) & TITLE_ADDONCONTENT_CONVERSION_MASK ) ;
2020-07-28 04:32:08 +01:00
}
NX_INLINE u64 titleGetAddOnContentMaxIdByBaseId ( u64 aoc_base_id )
{
return ( aoc_base_id + TITLE_ADDONCONTENT_MAX_ENTRIES + 1 ) ;
}
NX_INLINE bool titleIsAddOnContentIdValid ( u64 aoc_id , u64 aoc_base_id , u64 aoc_max_id )
{
return ( aoc_id > aoc_base_id & & aoc_id < aoc_max_id ) ;
2020-07-25 06:56:35 +01:00
}
NX_INLINE bool titleCheckIfAddOnContentIdBelongsToApplicationId ( u64 app_id , u64 aoc_id )
{
2020-07-28 04:32:08 +01:00
u64 aoc_base_id = titleGetAddOnContentBaseIdByApplicationId ( app_id ) ;
u64 aoc_max_id = titleGetAddOnContentMaxIdByBaseId ( aoc_base_id ) ;
return titleIsAddOnContentIdValid ( aoc_id , aoc_base_id , aoc_max_id ) ;
}
NX_INLINE bool titleCheckIfAddOnContentIdsAreSiblings ( u64 aoc_id_1 , u64 aoc_id_2 )
{
u64 app_id_1 = titleGetApplicationIdByAddOnContentId ( aoc_id_1 ) ;
u64 app_id_2 = titleGetApplicationIdByAddOnContentId ( aoc_id_2 ) ;
return ( app_id_1 = = app_id_2 & & titleCheckIfAddOnContentIdBelongsToApplicationId ( app_id_1 , aoc_id_1 ) & & titleCheckIfAddOnContentIdBelongsToApplicationId ( app_id_2 , aoc_id_2 ) ) ;
2020-07-25 06:56:35 +01:00
}
2021-01-31 09:16:05 +00:00
NX_INLINE u64 titleGetDeltaIdByApplicationId ( u64 app_id )
{
return ( app_id + TITLE_DELTA_TYPE_VALUE ) ;
}
NX_INLINE u64 titleGetApplicationIdByDeltaId ( u64 delta_id )
{
return ( delta_id - TITLE_DELTA_TYPE_VALUE ) ;
}
NX_INLINE bool titleCheckIfDeltaIdBelongsToApplicationId ( u64 app_id , u64 delta_id )
{
return ( delta_id = = titleGetDeltaIdByApplicationId ( app_id ) ) ;
}
2020-09-19 07:59:31 +01:00
NX_INLINE u32 titleGetContentCountByType ( TitleInfo * info , u8 content_type )
{
if ( ! info | | ! info - > content_count | | ! info - > content_infos | | content_type > NcmContentType_DeltaFragment ) return 0 ;
u32 cnt = 0 ;
for ( u32 i = 0 ; i < info - > content_count ; i + + )
{
if ( info - > content_infos [ i ] . content_type = = content_type ) cnt + + ;
}
return cnt ;
}
2020-07-26 05:57:12 +01:00
NX_INLINE NcmContentInfo * titleGetContentInfoByTypeAndIdOffset ( TitleInfo * info , u8 content_type , u8 id_offset )
{
if ( ! info | | ! info - > content_count | | ! info - > content_infos | | content_type > NcmContentType_DeltaFragment ) return NULL ;
for ( u32 i = 0 ; i < info - > content_count ; i + + )
{
2020-10-14 19:58:33 +01:00
NcmContentInfo * cur_content_info = & ( info - > content_infos [ i ] ) ;
if ( cur_content_info - > content_type = = content_type & & cur_content_info - > id_offset = = id_offset ) return cur_content_info ;
2020-07-26 05:57:12 +01:00
}
return NULL ;
}
2020-10-21 05:27:48 +01:00
NX_INLINE u32 titleGetCountFromInfoBlock ( TitleInfo * title_info )
{
if ( ! title_info ) return 0 ;
u32 count = 1 ;
TitleInfo * cur_info = title_info - > previous ;
while ( cur_info )
{
count + + ;
cur_info = cur_info - > previous ;
}
cur_info = title_info - > next ;
while ( cur_info )
{
count + + ;
cur_info = cur_info - > next ;
}
return count ;
}
2021-03-23 14:06:52 +00:00
# ifdef __cplusplus
}
2021-03-24 17:25:19 +00:00
# endif
# endif /* __TITLE_H__ */