mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-12-22 16:42:11 +00:00
Some changes.
* nxdt_includes: renamed VersionType1 to Version and tweaked it to add the application_version struct, renamed VersionType2 to SdkAddOnVersion. * gc_dumper: use utilsGeneratePath() to truncate generated filenames to safe filesystem limits. Thanks to n0tw0rk for reporting the issue and testing the changes! * nxdt_host.py: fixed a string formatting issue that made it impossible to unpack data from the SendFileProperties command block under certain circumstances. * gamecard: modified GameCardKeySource to add a value field, added GameCardFlags_HasCa10Certificate flag. * utils: utilsGeneratePath() no longer adds a dot on its own if it's not part of the provided extension string.
This commit is contained in:
parent
b9018a7df0
commit
278cb5c72a
14 changed files with 149 additions and 106 deletions
|
@ -80,6 +80,8 @@ static bool waitForUsb(void);
|
|||
static void generateDumpTxt(void);
|
||||
static bool saveDumpTxt(void);
|
||||
|
||||
static char *generateOutputFileName(const char *extension);
|
||||
|
||||
static bool saveGameCardSpecificData(void);
|
||||
static bool saveGameCardCertificate(void);
|
||||
static bool saveGameCardInitialData(void);
|
||||
|
@ -557,6 +559,29 @@ static bool saveDumpTxt(void)
|
|||
return saveFileData(path, txt_info, strlen(txt_info));
|
||||
}
|
||||
|
||||
static char *generateOutputFileName(const char *extension)
|
||||
{
|
||||
char *filename = NULL, *output = NULL;
|
||||
|
||||
if (!extension || !*extension || !(filename = titleGenerateGameCardFileName(TitleNamingConvention_Full, g_useUsbHost ? TitleFileNameIllegalCharReplaceType_IllegalFsChars : TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly)))
|
||||
{
|
||||
consolePrint("failed to get gamecard filename!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
output = utilsGeneratePath(NULL, filename, extension);
|
||||
free(filename);
|
||||
|
||||
if (output)
|
||||
{
|
||||
snprintf(path, MAX_ELEMENTS(path), "%s", output);
|
||||
} else {
|
||||
consolePrint("failed to generate output filename!\n");
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static bool dumpGameCardSecurityInformation(GameCardSecurityInformation *out)
|
||||
{
|
||||
if (!out)
|
||||
|
@ -580,16 +605,19 @@ static bool saveGameCardSpecificData(void)
|
|||
GameCardSecurityInformation gc_security_information = {0};
|
||||
bool success = false;
|
||||
u32 crc = 0;
|
||||
char *filename = titleGenerateGameCardFileName(TitleNamingConvention_Full, g_useUsbHost ? TitleFileNameIllegalCharReplaceType_IllegalFsChars : TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly);
|
||||
char *filename = NULL;
|
||||
|
||||
if (!dumpGameCardSecurityInformation(&gc_security_information) || !filename) goto end;
|
||||
if (!dumpGameCardSecurityInformation(&gc_security_information)) goto end;
|
||||
|
||||
crc = crc32Calculate(&(gc_security_information.specific_data), sizeof(GameCardSpecificData));
|
||||
snprintf(path, MAX_ELEMENTS(path), "%s (Specific Data) (%08X).bin", filename, crc);
|
||||
snprintf(path, MAX_ELEMENTS(path), " (Specific Data) (%08X).bin", crc);
|
||||
|
||||
if (!saveFileData(path, &(gc_security_information.specific_data), sizeof(GameCardSpecificData))) goto end;
|
||||
filename = generateOutputFileName(path);
|
||||
if (!filename) goto end;
|
||||
|
||||
printf("successfully saved specific data as \"%s\"\n", path);
|
||||
if (!saveFileData(filename, &(gc_security_information.specific_data), sizeof(GameCardSpecificData))) goto end;
|
||||
|
||||
printf("successfully saved specific data as \"%s\"\n", filename);
|
||||
success = true;
|
||||
|
||||
end:
|
||||
|
@ -603,9 +631,9 @@ static bool saveGameCardCertificate(void)
|
|||
FsGameCardCertificate gc_cert = {0};
|
||||
bool success = false;
|
||||
u32 crc = 0;
|
||||
char *filename = titleGenerateGameCardFileName(TitleNamingConvention_Full, g_useUsbHost ? TitleFileNameIllegalCharReplaceType_IllegalFsChars : TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly);
|
||||
char *filename = NULL;
|
||||
|
||||
if (!gamecardGetCertificate(&gc_cert) || !filename)
|
||||
if (!gamecardGetCertificate(&gc_cert))
|
||||
{
|
||||
consolePrint("failed to get gamecard certificate\n");
|
||||
goto end;
|
||||
|
@ -614,11 +642,14 @@ static bool saveGameCardCertificate(void)
|
|||
consolePrint("get gamecard certificate ok\n");
|
||||
|
||||
crc = crc32Calculate(&gc_cert, sizeof(FsGameCardCertificate));
|
||||
snprintf(path, MAX_ELEMENTS(path), "%s (Certificate) (%08X).bin", filename, crc);
|
||||
snprintf(path, MAX_ELEMENTS(path), " (Certificate) (%08X).bin", crc);
|
||||
|
||||
if (!saveFileData(path, &gc_cert, sizeof(FsGameCardCertificate))) goto end;
|
||||
filename = generateOutputFileName(path);
|
||||
if (!filename) goto end;
|
||||
|
||||
printf("successfully saved certificate as \"%s\"\n", path);
|
||||
if (!saveFileData(filename, &gc_cert, sizeof(FsGameCardCertificate))) goto end;
|
||||
|
||||
printf("successfully saved certificate as \"%s\"\n", filename);
|
||||
success = true;
|
||||
|
||||
end:
|
||||
|
@ -632,16 +663,19 @@ static bool saveGameCardInitialData(void)
|
|||
GameCardSecurityInformation gc_security_information = {0};
|
||||
bool success = false;
|
||||
u32 crc = 0;
|
||||
char *filename = titleGenerateGameCardFileName(TitleNamingConvention_Full, g_useUsbHost ? TitleFileNameIllegalCharReplaceType_IllegalFsChars : TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly);
|
||||
char *filename = NULL;
|
||||
|
||||
if (!dumpGameCardSecurityInformation(&gc_security_information) || !filename) goto end;
|
||||
if (!dumpGameCardSecurityInformation(&gc_security_information)) goto end;
|
||||
|
||||
crc = crc32Calculate(&(gc_security_information.initial_data), sizeof(GameCardInitialData));
|
||||
snprintf(path, MAX_ELEMENTS(path), "%s (Initial Data) (%08X).bin", filename, crc);
|
||||
snprintf(path, MAX_ELEMENTS(path), " (Initial Data) (%08X).bin", crc);
|
||||
|
||||
if (!saveFileData(path, &(gc_security_information.initial_data), sizeof(GameCardInitialData))) goto end;
|
||||
filename = generateOutputFileName(path);
|
||||
if (!filename) goto end;
|
||||
|
||||
printf("successfully saved initial data as \"%s\"\n", path);
|
||||
if (!saveFileData(filename, &(gc_security_information.initial_data), sizeof(GameCardInitialData))) goto end;
|
||||
|
||||
printf("successfully saved initial data as \"%s\"\n", filename);
|
||||
success = true;
|
||||
|
||||
end:
|
||||
|
@ -655,16 +689,19 @@ static bool saveGameCardIdSet(void)
|
|||
FsGameCardIdSet id_set = {0};
|
||||
bool success = false;
|
||||
u32 crc = 0;
|
||||
char *filename = titleGenerateGameCardFileName(TitleNamingConvention_Full, g_useUsbHost ? TitleFileNameIllegalCharReplaceType_IllegalFsChars : TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly);
|
||||
char *filename = NULL;
|
||||
|
||||
if (!gamecardGetIdSet(&id_set) || !filename) goto end;
|
||||
if (!gamecardGetIdSet(&id_set)) goto end;
|
||||
|
||||
crc = crc32Calculate(&id_set, sizeof(FsGameCardIdSet));
|
||||
snprintf(path, MAX_ELEMENTS(path), "%s (Card ID Set) (%08X).bin", filename, crc);
|
||||
snprintf(path, MAX_ELEMENTS(path), " (Card ID Set) (%08X).bin", crc);
|
||||
|
||||
if (!saveFileData(path, &id_set, sizeof(FsGameCardIdSet))) goto end;
|
||||
if (!saveFileData(filename, &id_set, sizeof(FsGameCardIdSet))) goto end;
|
||||
|
||||
printf("successfully saved gamecard id set as \"%s\"\n", path);
|
||||
filename = generateOutputFileName(path);
|
||||
if (!filename) goto end;
|
||||
|
||||
printf("successfully saved gamecard id set as \"%s\"\n", filename);
|
||||
success = true;
|
||||
|
||||
end:
|
||||
|
@ -686,12 +723,9 @@ static bool saveGameCardImage(void)
|
|||
|
||||
consolePrint("gamecard image dump\nkeep certificate: %s | trim dump: %s | calculate crc32: %s\n\n", g_keepCertificate ? "yes" : "no", g_trimDump ? "yes" : "no", g_calcCrc ? "yes" : "no");
|
||||
|
||||
filename = titleGenerateGameCardFileName(TitleNamingConvention_Full, g_useUsbHost ? TitleFileNameIllegalCharReplaceType_IllegalFsChars : TitleFileNameIllegalCharReplaceType_KeepAsciiCharsOnly);
|
||||
if (!filename)
|
||||
{
|
||||
consolePrint("failed to generate gamecard filename!\n");
|
||||
goto end;
|
||||
}
|
||||
snprintf(path, MAX_ELEMENTS(path), " (%s) (%s).xci", g_keepCertificate ? "cert" : "certless", g_trimDump ? "trimmed" : "untrimmed");
|
||||
filename = generateOutputFileName(path);
|
||||
if (!filename) goto end;
|
||||
|
||||
shared_data.data = usbAllocatePageAlignedBuffer(BLOCK_SIZE);
|
||||
if (!shared_data.data)
|
||||
|
@ -710,25 +744,23 @@ static bool saveGameCardImage(void)
|
|||
|
||||
consolePrint("gamecard size: 0x%lX\n", gc_size);
|
||||
|
||||
snprintf(path, MAX_ELEMENTS(path), "%s (%s) (%s).xci", filename, g_keepCertificate ? "cert" : "certless", g_trimDump ? "trimmed" : "untrimmed");
|
||||
|
||||
if (g_useUsbHost && !usbSendFilePropertiesCommon(gc_size, path))
|
||||
if (g_useUsbHost && !usbSendFilePropertiesCommon(gc_size, filename))
|
||||
{
|
||||
consolePrint("failed to send file properties for \"%s\"!\n", path);
|
||||
consolePrint("failed to send file properties for \"%s\"!\n", filename);
|
||||
goto end;
|
||||
} else
|
||||
if (!g_useUsbHost)
|
||||
{
|
||||
if (gc_size > FAT32_FILESIZE_LIMIT && !utilsCreateConcatenationFile(path))
|
||||
if (gc_size > FAT32_FILESIZE_LIMIT && !utilsCreateConcatenationFile(filename))
|
||||
{
|
||||
consolePrint("failed to create concatenation file for \"%s\"!\n", path);
|
||||
consolePrint("failed to create concatenation file for \"%s\"!\n", filename);
|
||||
goto end;
|
||||
}
|
||||
|
||||
shared_data.fp = fopen(path, "wb");
|
||||
shared_data.fp = fopen(filename, "wb");
|
||||
if (!shared_data.fp)
|
||||
{
|
||||
consolePrint("failed to open \"%s\" for writing!\n", path);
|
||||
consolePrint("failed to open \"%s\" for writing!\n", filename);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
@ -824,7 +856,7 @@ end:
|
|||
shared_data.fp = NULL;
|
||||
}
|
||||
|
||||
if (!success && !g_useUsbHost) utilsRemoveConcatenationFile(path);
|
||||
if (!success && !g_useUsbHost) utilsRemoveConcatenationFile(filename);
|
||||
|
||||
if (shared_data.data) free(shared_data.data);
|
||||
|
||||
|
|
|
@ -123,8 +123,8 @@ static void nspDump(TitleInfo *title_info, u64 free_space)
|
|||
|
||||
printf("source storage: %s\n", title_info->storage_id == NcmStorageId_GameCard ? "gamecard" : (title_info->storage_id == NcmStorageId_BuiltInUser ? "emmc" : "sd card"));
|
||||
printf("title id: %016lX\n", title_info->meta_key.id);
|
||||
printf("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.major, title_info->version.minor, title_info->version.micro, title_info->version.major_relstep, \
|
||||
title_info->version.minor_relstep);
|
||||
printf("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.system_version.major, title_info->version.system_version.minor, title_info->version.system_version.micro, title_info->version.system_version.major_relstep, \
|
||||
title_info->version.system_version.minor_relstep);
|
||||
printf("content count: %u\n", title_info->content_count);
|
||||
printf("size: %s\n", title_info->size_str);
|
||||
printf("______________________________\n\n");
|
||||
|
@ -895,8 +895,8 @@ int main(int argc, char *argv[])
|
|||
(title_info->meta_key.type == NcmContentMetaType_Patch ? "update" : "dlc"));
|
||||
printf("source storage: %s\n", title_info->storage_id == NcmStorageId_GameCard ? "gamecard" : (title_info->storage_id == NcmStorageId_BuiltInUser ? "emmc" : "sd card"));
|
||||
if (title_info->meta_key.type != NcmContentMetaType_Application) printf("title id: %016lX\n", title_info->meta_key.id);
|
||||
printf("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.major, title_info->version.minor, title_info->version.micro, title_info->version.major_relstep, \
|
||||
title_info->version.minor_relstep);
|
||||
printf("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.system_version.major, title_info->version.system_version.minor, title_info->version.system_version.micro, title_info->version.system_version.major_relstep, \
|
||||
title_info->version.system_version.minor_relstep);
|
||||
printf("content count: %u\n", title_info->content_count);
|
||||
printf("size: %s\n", title_info->size_str);
|
||||
}
|
||||
|
|
|
@ -859,8 +859,8 @@ static void nspDump(TitleInfo *title_info)
|
|||
|
||||
consolePrint("source storage: %s\n", title_info->storage_id == NcmStorageId_GameCard ? "gamecard" : (title_info->storage_id == NcmStorageId_BuiltInUser ? "emmc" : "sd card"));
|
||||
consolePrint("title id: %016lX\n", title_info->meta_key.id);
|
||||
consolePrint("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.major, title_info->version.minor, title_info->version.micro, title_info->version.major_relstep, \
|
||||
title_info->version.minor_relstep);
|
||||
consolePrint("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.system_version.major, title_info->version.system_version.minor, title_info->version.system_version.micro, title_info->version.system_version.major_relstep, \
|
||||
title_info->version.system_version.minor_relstep);
|
||||
consolePrint("content count: %u\n", title_info->content_count);
|
||||
consolePrint("size: %s\n", title_info->size_str);
|
||||
consolePrint("______________________________\n\n");
|
||||
|
@ -1046,8 +1046,8 @@ int main(int argc, char *argv[])
|
|||
(title_info->meta_key.type == NcmContentMetaType_Patch ? "update" : "dlc"));
|
||||
consolePrint("source storage: %s\n", title_info->storage_id == NcmStorageId_GameCard ? "gamecard" : (title_info->storage_id == NcmStorageId_BuiltInUser ? "emmc" : "sd card"));
|
||||
if (title_info->meta_key.type != NcmContentMetaType_Application) consolePrint("title id: %016lX\n", title_info->meta_key.id);
|
||||
consolePrint("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.major, title_info->version.minor, title_info->version.micro, title_info->version.major_relstep, \
|
||||
title_info->version.minor_relstep);
|
||||
consolePrint("version: %u (%u.%u.%u-%u.%u)\n", title_info->version.value, title_info->version.system_version.major, title_info->version.system_version.minor, title_info->version.system_version.micro, title_info->version.system_version.major_relstep, \
|
||||
title_info->version.system_version.minor_relstep);
|
||||
consolePrint("content count: %u\n", title_info->content_count);
|
||||
consolePrint("size: %s\n", title_info->size_str);
|
||||
}
|
||||
|
|
|
@ -629,7 +629,7 @@ def usbHandleSendFileProperties(cmd_block):
|
|||
g_logger.debug('Received SendFileProperties (%02X) command.' % (USB_CMD_SEND_FILE_PROPERTIES))
|
||||
|
||||
# Parse command block.
|
||||
(file_size, filename_length, nsp_header_size, raw_filename) = struct.unpack_from('<QII{}s'.format(USB_FILE_PROPERTIES_MAX_NAME_LENGTH), cmd_block, 0)
|
||||
(file_size, filename_length, nsp_header_size, raw_filename) = struct.unpack_from('<QII%ds' % (USB_FILE_PROPERTIES_MAX_NAME_LENGTH), cmd_block, 0)
|
||||
filename = raw_filename.decode('utf-8').strip('\x00')
|
||||
|
||||
# Print info.
|
||||
|
|
|
@ -51,7 +51,7 @@ typedef enum {
|
|||
/// Finally, a 0x20 byte long digest is appended to the EOF.
|
||||
typedef struct {
|
||||
u64 title_id;
|
||||
VersionType1 version;
|
||||
Version version;
|
||||
u8 content_meta_type; ///< NcmContentMetaType.
|
||||
u8 reserved_1;
|
||||
u16 extended_header_size; ///< Must match the size from the extended header struct for this content meta type (SystemUpdate, Application, Patch, AddOnContent, Delta).
|
||||
|
@ -61,7 +61,7 @@ typedef struct {
|
|||
u8 storage_id; ///< NcmStorageId.
|
||||
u8 content_install_type; ///< NcmContentInstallType.
|
||||
u8 install_state; ///< ContentMetaInstallState.
|
||||
VersionType1 required_download_system_version;
|
||||
Version required_download_system_version;
|
||||
u8 reserved_2[0x4];
|
||||
} ContentMetaPackagedContentMetaHeader;
|
||||
|
||||
|
@ -76,20 +76,20 @@ typedef struct {
|
|||
NXDT_ASSERT(ContentMetaSystemUpdateMetaExtendedHeader, 0x4);
|
||||
|
||||
/// Extended header for Application titles.
|
||||
/// Equivalent to NcmApplicationMetaExtendedHeader, but using VersionType1 structs.
|
||||
/// Equivalent to NcmApplicationMetaExtendedHeader, but using Version structs.
|
||||
typedef struct {
|
||||
u64 patch_id;
|
||||
VersionType1 required_system_version;
|
||||
VersionType1 required_application_version;
|
||||
Version required_system_version;
|
||||
Version required_application_version;
|
||||
} ContentMetaApplicationMetaExtendedHeader;
|
||||
|
||||
NXDT_ASSERT(ContentMetaApplicationMetaExtendedHeader, 0x10);
|
||||
|
||||
/// Extended header for Patch titles.
|
||||
/// Equivalent to NcmPatchMetaExtendedHeader, but using a VersionType1 struct.
|
||||
/// Equivalent to NcmPatchMetaExtendedHeader, but using a Version struct.
|
||||
typedef struct {
|
||||
u64 application_id;
|
||||
VersionType1 required_system_version;
|
||||
Version required_system_version;
|
||||
u32 extended_data_size;
|
||||
u8 reserved[0x8];
|
||||
} ContentMetaPatchMetaExtendedHeader;
|
||||
|
@ -97,10 +97,10 @@ typedef struct {
|
|||
NXDT_ASSERT(ContentMetaPatchMetaExtendedHeader, 0x18);
|
||||
|
||||
/// Extended header for AddOnContent titles.
|
||||
/// Equivalent to NcmAddOnContentMetaExtendedHeader, but using a VersionType1 struct.
|
||||
/// Equivalent to NcmAddOnContentMetaExtendedHeader, but using a Version struct.
|
||||
typedef struct {
|
||||
u64 application_id;
|
||||
VersionType1 required_application_version;
|
||||
Version required_application_version;
|
||||
u8 reserved[0x4];
|
||||
} ContentMetaAddOnContentMetaExtendedHeader;
|
||||
|
||||
|
@ -186,8 +186,8 @@ NXDT_ASSERT(ContentMetaPatchHistoryHeader, 0x38);
|
|||
typedef struct {
|
||||
u64 source_patch_id;
|
||||
u64 destination_patch_id;
|
||||
VersionType1 source_version;
|
||||
VersionType1 destination_version;
|
||||
Version source_version;
|
||||
Version destination_version;
|
||||
u64 download_size;
|
||||
u8 reserved[0x8];
|
||||
} ContentMetaPatchDeltaHistory;
|
||||
|
@ -197,8 +197,8 @@ NXDT_ASSERT(ContentMetaPatchDeltaHistory, 0x28);
|
|||
typedef struct {
|
||||
u64 source_patch_id;
|
||||
u64 destination_patch_id;
|
||||
VersionType1 source_version;
|
||||
VersionType1 destination_version;
|
||||
Version source_version;
|
||||
Version destination_version;
|
||||
u16 fragment_set_count;
|
||||
u8 reserved_1[0x6];
|
||||
u16 content_info_count;
|
||||
|
@ -244,8 +244,8 @@ NXDT_ASSERT(ContentMetaFragmentIndicator, 0x4);
|
|||
typedef struct {
|
||||
u64 source_patch_id;
|
||||
u64 destination_patch_id;
|
||||
VersionType1 source_version;
|
||||
VersionType1 destination_version;
|
||||
Version source_version;
|
||||
Version destination_version;
|
||||
u16 fragment_set_count;
|
||||
u8 reserved[0x6];
|
||||
} ContentMetaDeltaMetaExtendedDataHeader;
|
||||
|
@ -323,7 +323,7 @@ NX_INLINE u32 cnmtGetRequiredTitleVersion(ContentMetaContext *cnmt_ctx)
|
|||
{
|
||||
return ((cnmtIsValidContext(cnmt_ctx) && (cnmt_ctx->packaged_header->content_meta_type == NcmContentMetaType_Application || \
|
||||
cnmt_ctx->packaged_header->content_meta_type == NcmContentMetaType_Patch || cnmt_ctx->packaged_header->content_meta_type == NcmContentMetaType_AddOnContent)) ? \
|
||||
((VersionType1*)(cnmt_ctx->extended_header + sizeof(u64)))->value : 0);
|
||||
((Version*)(cnmt_ctx->extended_header + sizeof(u64)))->value : 0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -56,8 +56,13 @@ NXDT_ASSERT(GameCardSpecificData, 0x200);
|
|||
|
||||
/// Encrypted using AES-128-ECB with the common titlekek generator key (stored in the .rodata segment from the Lotus firmware).
|
||||
typedef struct {
|
||||
u64 package_id; ///< Matches package_id from GameCardHeader.
|
||||
u8 reserved[0x8]; ///< Just zeroes.
|
||||
union {
|
||||
u8 value[0x10];
|
||||
struct {
|
||||
u64 package_id; ///< Matches package_id from GameCardHeader.
|
||||
u8 reserved[0x8]; ///< Just zeroes.
|
||||
};
|
||||
};
|
||||
} GameCardKeySource;
|
||||
|
||||
NXDT_ASSERT(GameCardKeySource, 0x10);
|
||||
|
@ -138,7 +143,8 @@ typedef enum {
|
|||
GameCardFlags_HistoryErase = BIT(1),
|
||||
GameCardFlags_RepairTool = BIT(2),
|
||||
GameCardFlags_DifferentRegionCupToTerraDevice = BIT(3),
|
||||
GameCardFlags_DifferentRegionCupToGlobalDevice = BIT(4)
|
||||
GameCardFlags_DifferentRegionCupToGlobalDevice = BIT(4),
|
||||
GameCardFlags_HasCa10Certificate = BIT(7)
|
||||
} GameCardFlags;
|
||||
|
||||
typedef enum {
|
||||
|
@ -172,18 +178,18 @@ typedef enum {
|
|||
/// Production XCI header key hash: 2E36CC55157A351090A73E7AE77CF581F69B0B6E48FB066C984879A6ED7D2E96
|
||||
/// Development XCI header key hash: 61D5C02244188810E2E3DE69341AC0F3C7653D370C6D3F77CA82B0B7E59F39AD
|
||||
typedef struct {
|
||||
u64 fw_version; ///< GameCardFwVersion.
|
||||
u32 acc_ctrl_1; ///< GameCardAccCtrl1.
|
||||
u32 wait_1_time_read; ///< Always 0x1388.
|
||||
u32 wait_2_time_read; ///< Always 0.
|
||||
u32 wait_1_time_write; ///< Always 0.
|
||||
u32 wait_2_time_write; ///< Always 0.
|
||||
VersionType2 fw_mode; ///< Current SdkAddonVersion.
|
||||
VersionType1 upp_version; ///< Bundled system update version.
|
||||
u8 compatibility_type; ///< GameCardCompatibilityType.
|
||||
u64 fw_version; ///< GameCardFwVersion.
|
||||
u32 acc_ctrl_1; ///< GameCardAccCtrl1.
|
||||
u32 wait_1_time_read; ///< Always 0x1388.
|
||||
u32 wait_2_time_read; ///< Always 0.
|
||||
u32 wait_1_time_write; ///< Always 0.
|
||||
u32 wait_2_time_write; ///< Always 0.
|
||||
SdkAddOnVersion fw_mode; ///< Current SdkAddOnVersion.
|
||||
Version upp_version; ///< Bundled system update version.
|
||||
u8 compatibility_type; ///< GameCardCompatibilityType.
|
||||
u8 reserved_1[0x3];
|
||||
u64 upp_hash; ///< SHA-256 checksum for the update partition.
|
||||
u64 upp_id; ///< Must match GAMECARD_UPDATE_TID.
|
||||
u64 upp_hash; ///< SHA-256 (?) checksum for the update partition. The exact way it's calculated is currently unknown.
|
||||
u64 upp_id; ///< Must match GAMECARD_UPDATE_TID.
|
||||
u8 reserved_2[0x38];
|
||||
} GameCardInfo;
|
||||
|
||||
|
@ -325,8 +331,8 @@ bool gamecardGetTrimmedSize(u64 *out);
|
|||
/// Fills the provided u64 pointer with the gamecard ROM capacity, based on the GameCardRomSize value from the header. Not the same as gamecardGetTotalSize().
|
||||
bool gamecardGetRomCapacity(u64 *out);
|
||||
|
||||
/// Fills the provided VersionType1 pointer with the bundled firmware update version in the inserted gamecard.
|
||||
bool gamecardGetBundledFirmwareUpdateVersion(VersionType1 *out);
|
||||
/// Fills the provided Version pointer with the bundled firmware update version in the inserted gamecard.
|
||||
bool gamecardGetBundledFirmwareUpdateVersion(Version *out);
|
||||
|
||||
/// Fills the provided HashFileSystemContext pointer using information from the requested Hash FS partition.
|
||||
/// Hash FS functions can be used on the retrieved HashFileSystemContext. hfsFreeContext() must be used to free the underlying data from the filled context.
|
||||
|
|
|
@ -144,7 +144,7 @@ typedef struct {
|
|||
u64 content_size;
|
||||
u64 program_id;
|
||||
u32 content_index;
|
||||
VersionType2 sdk_addon_version;
|
||||
SdkAddOnVersion sdk_addon_version;
|
||||
u8 key_generation; ///< NcaKeyGeneration. Uses NcaKeyGeneration_Since301NUP or greater values.
|
||||
u8 main_signature_key_generation; ///< NcaMainSignatureKeyGeneration.
|
||||
u8 reserved[0xE];
|
||||
|
|
|
@ -76,7 +76,7 @@ typedef struct {
|
|||
u8 main_thread_core_number; ///< Must not exceed NPDM_MAIN_THREAD_MAX_CORE_NUMBER.
|
||||
u8 reserved_3[0x4];
|
||||
u32 system_resource_size; ///< Must not exceed NPDM_SYSTEM_RESOURCE_MAX_SIZE.
|
||||
VersionType1 version;
|
||||
Version version;
|
||||
u32 main_thread_stack_size; ///< Must be aligned to NPDM_MAIN_THREAD_STACK_SIZE_ALIGNMENT.
|
||||
char name[0x10]; ///< Usually set to "Application".
|
||||
char product_code[0x10]; ///< Usually zeroed out.
|
||||
|
|
|
@ -65,37 +65,43 @@
|
|||
/* USB Mass Storage support. */
|
||||
#include "ums.h"
|
||||
|
||||
/// Used to store version numbers expressed in dot notation: "{major}.{minor}.{micro}-{major_relstep}.{minor_relstep}".
|
||||
/// Used to store version numbers expressed in dot notation:
|
||||
/// * System version: "{major}.{minor}.{micro}-{major_relstep}.{minor_relstep}".
|
||||
/// * Application version: "{release}.{private}".
|
||||
/// Referenced by multiple header files.
|
||||
typedef struct {
|
||||
union {
|
||||
u32 value;
|
||||
struct {
|
||||
u32 minor_relstep : 8;
|
||||
u32 major_relstep : 8;
|
||||
u32 micro : 4;
|
||||
u32 minor : 6;
|
||||
u32 major : 6;
|
||||
};
|
||||
u32 value;
|
||||
} system_version;
|
||||
struct {
|
||||
u32 private_ver : 16;
|
||||
u32 release_ver : 16;
|
||||
} application_version;
|
||||
};
|
||||
} VersionType1;
|
||||
} Version;
|
||||
|
||||
NXDT_ASSERT(VersionType1, 0x4);
|
||||
NXDT_ASSERT(Version, 0x4);
|
||||
|
||||
/// Used to store version numbers expressed in dot notation: "{major}.{minor}.{micro}-{relstep}".
|
||||
/// Only used by GameCardFwMode and NcaSdkAddOnVersion.
|
||||
typedef struct {
|
||||
union {
|
||||
u32 value;
|
||||
struct {
|
||||
u32 relstep : 8;
|
||||
u32 micro : 8;
|
||||
u32 minor : 8;
|
||||
u32 major : 8;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
} VersionType2;
|
||||
} SdkAddOnVersion;
|
||||
|
||||
NXDT_ASSERT(VersionType2, 0x4);
|
||||
NXDT_ASSERT(SdkAddOnVersion, 0x4);
|
||||
|
||||
#endif /* __NXDT_INCLUDES_H__ */
|
||||
|
|
|
@ -148,6 +148,8 @@ void utilsCreateDirectoryTree(const char *path, bool create_last_element);
|
|||
/// Returns a pointer to a dynamically allocated string that holds the full path formed by the provided arguments. Both path prefix and file extension are optional.
|
||||
/// If any elements from the generated path exceed safe filesystem limits, each exceeding element will be truncated. Truncations, if needed, are performed on a per-codepoint basis (UTF-8).
|
||||
/// If an extension is provided, it will always be preserved, regardless of any possible truncations being carried out.
|
||||
/// A path separator is automatically placed between the provided prefix and the filename if the prefix doesn't end with one.
|
||||
/// A dot *isn't* automatically placed between the filename and the provided extension -- if required, it must be provided as part of the extension string.
|
||||
/// Furthermore, if the full length for the generated path is >= FS_MAX_PATH, NULL will be returned.
|
||||
char *utilsGeneratePath(const char *prefix, const char *filename, const char *extension);
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ typedef struct {
|
|||
typedef struct _TitleInfo {
|
||||
u8 storage_id; ///< NcmStorageId.
|
||||
NcmContentMetaKey meta_key; ///< Used with ncm calls.
|
||||
VersionType1 version; ///< Holds the same value from meta_key.version.
|
||||
Version version; ///< Holds the same value from meta_key.version.
|
||||
u32 content_count; ///< Content info count.
|
||||
NcmContentInfo *content_infos; ///< Content info entries from this title.
|
||||
u64 size; ///< Total title size.
|
||||
|
|
|
@ -435,7 +435,7 @@ bool gamecardGetRomCapacity(u64 *out)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool gamecardGetBundledFirmwareUpdateVersion(VersionType1 *out)
|
||||
bool gamecardGetBundledFirmwareUpdateVersion(Version *out)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
|
|
|
@ -759,11 +759,9 @@ char *utilsGeneratePath(const char *prefix, const char *filename, const char *ex
|
|||
|
||||
bool use_extension = (extension && *extension);
|
||||
size_t extension_len = (use_extension ? strlen(extension) : 0);
|
||||
bool append_dot = (use_extension && *extension != '.');
|
||||
|
||||
size_t path_len = (prefix_len + strlen(filename) + extension_len);
|
||||
if (append_path_sep) path_len++;
|
||||
if (append_dot) path_len++;
|
||||
|
||||
char *path = NULL, *ptr1 = NULL, *ptr2 = NULL;
|
||||
bool filename_only = false, success = false;
|
||||
|
@ -779,7 +777,6 @@ char *utilsGeneratePath(const char *prefix, const char *filename, const char *ex
|
|||
if (use_prefix) strcat(path, prefix);
|
||||
if (append_path_sep) strcat(path, "/");
|
||||
strcat(path, filename);
|
||||
if (append_dot) strcat(path, ".");
|
||||
if (use_extension) strcat(path, extension);
|
||||
|
||||
/* Retrieve pointer to the first path separator. */
|
||||
|
@ -793,11 +790,14 @@ char *utilsGeneratePath(const char *prefix, const char *filename, const char *ex
|
|||
/* Make sure each path element doesn't exceed NT_MAX_FILENAME_LENGTH. */
|
||||
while(ptr1)
|
||||
{
|
||||
/* End loop if we find a NULL terminator. */
|
||||
if (!filename_only && !*ptr1++) break;
|
||||
|
||||
/* Get pointer to next path separator. */
|
||||
ptr2 = strchr(ptr1, '/');
|
||||
if (!filename_only)
|
||||
{
|
||||
/* End loop if we find a NULL terminator. */
|
||||
if (!*ptr1++) break;
|
||||
|
||||
/* Get pointer to next path separator. */
|
||||
ptr2 = strchr(ptr1, '/');
|
||||
}
|
||||
|
||||
/* Get current path element size. */
|
||||
size_t element_size = (ptr2 ? (size_t)(ptr2 - ptr1) : (path_len - (size_t)(ptr1 - path)));
|
||||
|
@ -819,16 +819,13 @@ char *utilsGeneratePath(const char *prefix, const char *filename, const char *ex
|
|||
if (use_extension)
|
||||
{
|
||||
/* Truncate last element. Make sure to preserve the provided file extension. */
|
||||
size_t diff = extension_len;
|
||||
if (append_dot) diff++;
|
||||
|
||||
if (diff >= last_cp_pos)
|
||||
if (extension_len >= last_cp_pos)
|
||||
{
|
||||
LOG_MSG("File extension length is >= truncated filename length! (0x%lX >= 0x%lX) (#1).", diff, last_cp_pos);
|
||||
LOG_MSG("File extension length is >= truncated filename length! (0x%lX >= 0x%lX).", extension_len, last_cp_pos);
|
||||
goto end;
|
||||
}
|
||||
|
||||
memmove(ptr1 + last_cp_pos - diff, ptr1 + element_size - diff, diff);
|
||||
memmove(ptr1 + last_cp_pos - extension_len, ptr1 + element_size - extension_len, extension_len);
|
||||
}
|
||||
|
||||
path_len -= (element_size - last_cp_pos);
|
||||
|
|
|
@ -104,14 +104,14 @@ namespace nxdt::views
|
|||
this->total_size->setValue(this->GetFormattedSizeString(&gamecardGetTotalSize));
|
||||
this->trimmed_size->setValue(this->GetFormattedSizeString(&gamecardGetTrimmedSize));
|
||||
|
||||
const VersionType1 *upp_version = &(card_info.upp_version);
|
||||
this->update_version->setValue(fmt::format("{}.{}.{}-{}.{} (v{})", upp_version->major, upp_version->minor, upp_version->micro, upp_version->major_relstep, \
|
||||
upp_version->minor_relstep, upp_version->value));
|
||||
const Version *upp_version = &(card_info.upp_version);
|
||||
this->update_version->setValue(fmt::format("{}.{}.{}-{}.{} (v{})", upp_version->system_version.major, upp_version->system_version.minor, upp_version->system_version.micro, \
|
||||
upp_version->system_version.major_relstep, upp_version->system_version.minor_relstep, upp_version->value));
|
||||
|
||||
u64 fw_version = card_info.fw_version;
|
||||
this->lafw_version->setValue(fmt::format("{} ({})", fw_version, fw_version >= GameCardFwVersion_Count ? "generic/unknown"_i18n : gamecardGetRequiredHosVersionString(fw_version)));
|
||||
|
||||
const VersionType2 *fw_mode = &(card_info.fw_mode);
|
||||
const SdkAddOnVersion *fw_mode = &(card_info.fw_mode);
|
||||
this->sdk_version->setValue(fmt::format("{}.{}.{}-{} (v{})", fw_mode->major, fw_mode->minor, fw_mode->micro, fw_mode->relstep, fw_mode->value));
|
||||
|
||||
u8 compatibility_type = card_info.compatibility_type;
|
||||
|
|
Loading…
Reference in a new issue