diff --git a/code_templates/gc_dumper.c b/code_templates/gc_dumper.c index 10420f2..a76fdb7 100644 --- a/code_templates/gc_dumper.c +++ b/code_templates/gc_dumper.c @@ -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); diff --git a/code_templates/nsp_dumper_stor.c b/code_templates/nsp_dumper_stor.c index c38959a..2f249c8 100644 --- a/code_templates/nsp_dumper_stor.c +++ b/code_templates/nsp_dumper_stor.c @@ -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); } diff --git a/code_templates/nsp_dumper_usb.c b/code_templates/nsp_dumper_usb.c index 6b27923..0c7011f 100644 --- a/code_templates/nsp_dumper_usb.c +++ b/code_templates/nsp_dumper_usb.c @@ -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); } diff --git a/host/nxdt_host.py b/host/nxdt_host.py index e745221..7a52b2e 100644 --- a/host/nxdt_host.py +++ b/host/nxdt_host.py @@ -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('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 diff --git a/include/core/gamecard.h b/include/core/gamecard.h index 7904589..2685bd9 100644 --- a/include/core/gamecard.h +++ b/include/core/gamecard.h @@ -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. diff --git a/include/core/nca.h b/include/core/nca.h index 765140f..b72fbf3 100644 --- a/include/core/nca.h +++ b/include/core/nca.h @@ -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]; diff --git a/include/core/npdm.h b/include/core/npdm.h index 7a1248b..efd7065 100644 --- a/include/core/npdm.h +++ b/include/core/npdm.h @@ -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. diff --git a/include/core/nxdt_includes.h b/include/core/nxdt_includes.h index b773873..85f71dc 100644 --- a/include/core/nxdt_includes.h +++ b/include/core/nxdt_includes.h @@ -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__ */ diff --git a/include/core/nxdt_utils.h b/include/core/nxdt_utils.h index d1a387b..b7ccc40 100644 --- a/include/core/nxdt_utils.h +++ b/include/core/nxdt_utils.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); diff --git a/include/core/title.h b/include/core/title.h index 4814b4e..b5a6c80 100644 --- a/include/core/title.h +++ b/include/core/title.h @@ -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. diff --git a/source/core/gamecard.c b/source/core/gamecard.c index cf229a5..4f1197b 100644 --- a/source/core/gamecard.c +++ b/source/core/gamecard.c @@ -435,7 +435,7 @@ bool gamecardGetRomCapacity(u64 *out) return ret; } -bool gamecardGetBundledFirmwareUpdateVersion(VersionType1 *out) +bool gamecardGetBundledFirmwareUpdateVersion(Version *out) { bool ret = false; diff --git a/source/core/nxdt_utils.c b/source/core/nxdt_utils.c index 22038e7..b554194 100644 --- a/source/core/nxdt_utils.c +++ b/source/core/nxdt_utils.c @@ -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); diff --git a/source/gamecard_tab.cpp b/source/gamecard_tab.cpp index 64850c9..b78bc5e 100644 --- a/source/gamecard_tab.cpp +++ b/source/gamecard_tab.cpp @@ -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;