diff --git a/code_templates/dump_title_infos.c b/code_templates/dump_title_infos.c index 2e3cffa..9e968f2 100644 --- a/code_templates/dump_title_infos.c +++ b/code_templates/dump_title_infos.c @@ -12,9 +12,9 @@ { fprintf(title_infos_txt, "Storage ID: 0x%02X\r\n", g_titleInfo[i].storage_id); fprintf(title_infos_txt, "Title ID: %016lX\r\n", g_titleInfo[i].meta_key.id); - fprintf(title_infos_txt, "Version: %u (%u.%u.%u-%u.%u)\r\n", g_titleInfo[i].meta_key.version, g_titleInfo[i].version.TitleVersion_Major, \ - g_titleInfo[i].version.TitleVersion_Minor, g_titleInfo[i].version.TitleVersion_Micro, g_titleInfo[i].version.TitleVersion_MajorRelstep, \ - g_titleInfo[i].version.TitleVersion_MinorRelstep); + fprintf(title_infos_txt, "Version: %u (%u.%u.%u-%u.%u)\r\n", g_titleInfo[i].meta_key.version, g_titleInfo[i].version.major, \ + g_titleInfo[i].version.minor, g_titleInfo[i].version.micro, g_titleInfo[i].version.major_relstep, \ + g_titleInfo[i].version.minor_relstep); fprintf(title_infos_txt, "Type: 0x%02X\r\n", g_titleInfo[i].meta_key.type); fprintf(title_infos_txt, "Install Type: 0x%02X\r\n", g_titleInfo[i].meta_key.install_type); fprintf(title_infos_txt, "Title Size: %s (0x%lX)\r\n", g_titleInfo[i].title_size_str, g_titleInfo[i].title_size); diff --git a/code_templates/xml_generator.c b/code_templates/xml_generator.c index 3809468..9d0dd6c 100644 --- a/code_templates/xml_generator.c +++ b/code_templates/xml_generator.c @@ -262,7 +262,7 @@ int main(int argc, char *argv[]) consolePrint("nacp initialize ctx succeeded\n"); - if (nacpGenerateAuthoringToolXml(&nacp_ctx, titleGetVersionInteger(&(user_app_data.app_info->version)), cnmtGetRequiredTitleVersion(&cnmt_ctx))) + if (nacpGenerateAuthoringToolXml(&nacp_ctx, user_app_data.app_info->version.value, cnmtGetRequiredTitleVersion(&cnmt_ctx))) { consolePrint("nacp xml succeeded\n"); @@ -311,6 +311,8 @@ out2: utilsWaitForButtonPress(KEY_NONE); } + nacpFreeContext(&nacp_ctx); + cnmtFreeContext(&cnmt_ctx); if (nca_ctx) free(nca_ctx); diff --git a/source/cnmt.c b/source/cnmt.c index 0ba6273..9ec0b3c 100644 --- a/source/cnmt.c +++ b/source/cnmt.c @@ -261,8 +261,8 @@ bool cnmtGenerateAuthoringToolXml(ContentMetaContext *cnmt_ctx, NcaContext *nca_ " %u\n", \ titleGetNcmContentMetaTypeName(cnmt_ctx->packaged_header->content_meta_type), \ cnmt_ctx->packaged_header->title_id, \ - cnmtGetVersionInteger(&(cnmt_ctx->packaged_header->version)), \ - cnmtGetVersionInteger(&(cnmt_ctx->packaged_header->required_download_system_version)))) goto end; + cnmt_ctx->packaged_header->version.value, + cnmt_ctx->packaged_header->required_download_system_version.value)) goto end; for(i = 0; i < nca_ctx_count; i++) { @@ -336,7 +336,7 @@ bool cnmtGenerateAuthoringToolXml(ContentMetaContext *cnmt_ctx, NcaContext *nca_ { if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ " %u\n", \ - cnmtGetVersionInteger((ContentMetaVersion*)(cnmt_ctx->extended_header + sizeof(u64) + sizeof(u32))))) goto end; + ((VersionType1*)(cnmt_ctx->extended_header + sizeof(u64) + sizeof(u32)))->value)) goto end; } if (!(success = utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, ""))) goto end; diff --git a/source/cnmt.h b/source/cnmt.h index 3a66388..fad6295 100644 --- a/source/cnmt.h +++ b/source/cnmt.h @@ -27,15 +27,6 @@ #define CNMT_DIGEST_SIZE SHA256_HASH_SIZE -/// Used to display version numbers in dot notation: "{Major}.{Minor}.{Micro}-{MajorRelstep}.{MinorRelstep}". -typedef struct { - u32 ContentMetaVersion_MinorRelstep : 8; - u32 ContentMetaVersion_MajorRelstep : 8; - u32 ContentMetaVersion_Micro : 4; - u32 ContentMetaVersion_Minor : 6; - u32 ContentMetaVersion_Major : 6; -} ContentMetaVersion; - /// Equivalent to NcmContentMetaAttribute. typedef enum { ContentMetaAttribute_IncludesExFatDriver = BIT(0), @@ -43,9 +34,8 @@ typedef enum { ContentMetaAttribute_Compacted = BIT(2) } ContentMetaAttribute; -typedef struct { - u8 ContentMetaInstallState_Committed : 1; - u8 ContentMetaInstallState_Reserved : 7; +typedef enum { + ContentMetaInstallState_Committed = BIT(0) } ContentMetaInstallState; /// Extended variation of NcmContentMetaHeader. This is essentially the start of every CNMT file. @@ -55,7 +45,7 @@ typedef struct { /// Finally, a 0x20 byte long digest is appended to the EOF. typedef struct { u64 title_id; - ContentMetaVersion version; + VersionType1 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). @@ -64,8 +54,8 @@ typedef struct { u8 content_meta_attribute; ///< ContentMetaAttribute. u8 storage_id; ///< NcmStorageId. u8 content_install_type; ///< NcmContentInstallType. - ContentMetaInstallState install_state; - ContentMetaVersion required_download_system_version; + u8 install_state; ///< ContentMetaInstallState. + VersionType1 required_download_system_version; u8 reserved_2[0x4]; } ContentMetaPackagedContentMetaHeader; @@ -76,27 +66,27 @@ typedef struct { } ContentMetaSystemUpdateMetaExtendedHeader; /// Extended header for Application titles. -/// Equivalent to NcmApplicationMetaExtendedHeader, but using ContentMetaVersion structs. +/// Equivalent to NcmApplicationMetaExtendedHeader, but using VersionType1 structs. typedef struct { u64 patch_id; - ContentMetaVersion required_system_version; - ContentMetaVersion required_application_version; + VersionType1 required_system_version; + VersionType1 required_application_version; } ContentMetaApplicationMetaExtendedHeader; /// Extended header for Patch titles. -/// Equivalent to NcmPatchMetaExtendedHeader, but using a ContentMetaVersion struct. +/// Equivalent to NcmPatchMetaExtendedHeader, but using a VersionType1 struct. typedef struct { u64 application_id; - ContentMetaVersion required_system_version; + VersionType1 required_system_version; u32 extended_data_size; u8 reserved[0x8]; } ContentMetaPatchMetaExtendedHeader; /// Extended header for AddOnContent titles. -/// Equivalent to NcmAddOnContentMetaExtendedHeader, but using a ContentMetaVersion struct. +/// Equivalent to NcmAddOnContentMetaExtendedHeader, but using a VersionType1 struct. typedef struct { u64 application_id; - ContentMetaVersion required_application_version; + VersionType1 required_application_version; u8 reserved[0x4]; } ContentMetaAddOnContentMetaExtendedHeader; @@ -168,8 +158,8 @@ typedef struct { typedef struct { u64 source_patch_id; u64 destination_patch_id; - ContentMetaVersion source_version; - ContentMetaVersion destination_version; + VersionType1 source_version; + VersionType1 destination_version; u64 download_size; u8 reserved[0x8]; } ContentMetaPatchDeltaHistory; @@ -177,8 +167,8 @@ typedef struct { typedef struct { u64 source_patch_id; u64 destination_patch_id; - ContentMetaVersion source_version; - ContentMetaVersion destination_version; + VersionType1 source_version; + VersionType1 destination_version; u16 fragment_set_count; u8 reserved_1[0x6]; u16 content_info_count; @@ -191,6 +181,7 @@ typedef enum { ContentMetaUpdateType_Create = 2 } ContentMetaUpdateType; +#pragma pack(push, 1) typedef struct { NcmContentId source_content_id; NcmContentId destination_content_id; @@ -199,10 +190,11 @@ typedef struct { u32 destination_size_low; u16 destination_size_high; u16 fragment_count; - NcmContentType fragment_target_content_type; + u8 fragment_target_content_type; ///< NcmContentType. u8 update_type; ///< ContentMetaUpdateType. u8 reserved[0x4]; } ContentMetaFragmentSet; +#pragma pack(pop) typedef struct { u16 content_info_index; @@ -216,8 +208,8 @@ typedef struct { typedef struct { u64 source_patch_id; u64 destination_patch_id; - ContentMetaVersion source_version; - ContentMetaVersion destination_version; + VersionType1 source_version; + VersionType1 destination_version; u16 fragment_set_count; u8 reserved[0x6]; } ContentMetaDeltaMetaExtendedDataHeader; @@ -285,11 +277,6 @@ NX_INLINE bool cnmtGenerateNcaPatch(ContentMetaContext *cnmt_ctx) return (cnmtIsValidContext(cnmt_ctx) && pfsGenerateEntryPatch(&(cnmt_ctx->pfs_ctx), cnmt_ctx->pfs_entry, cnmt_ctx->raw_data, cnmt_ctx->raw_data_size, 0, &(cnmt_ctx->nca_patch))); } -NX_INLINE u32 cnmtGetVersionInteger(ContentMetaVersion *version) -{ - return (version ? *((u32*)version) : 0); -} - NX_INLINE u64 cnmtGetRequiredTitleId(ContentMetaContext *cnmt_ctx) { return ((cnmtIsValidContext(cnmt_ctx) && (cnmt_ctx->packaged_header->content_meta_type == NcmContentMetaType_Application || \ @@ -301,7 +288,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)) ? \ - cnmtGetVersionInteger((ContentMetaVersion*)(cnmt_ctx->extended_header + sizeof(u64))) : 0); + ((VersionType1*)(cnmt_ctx->extended_header + sizeof(u64)))->value : 0); } #endif /* __CNMT_H__ */ diff --git a/source/common.h b/source/common.h new file mode 100644 index 0000000..741ae90 --- /dev/null +++ b/source/common.h @@ -0,0 +1,55 @@ +/* + * common.h + * + * Copyright (c) 2020, DarkMatterCore . + * + * 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 . + */ + +#pragma once + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +/// Used to store version numbers expressed in dot notation: "{major}.{minor}.{micro}-{major_relstep}.{minor_relstep}". +/// Referenced by multiple header files. +typedef struct { + union { + struct { + u32 minor_relstep : 8; + u32 major_relstep : 8; + u32 micro : 4; + u32 minor : 6; + u32 major : 6; + }; + u32 value; + }; +} VersionType1; + +/// Used to store version numbers expressed in dot notation: "{major}.{minor}.{micro}-{relstep}". +/// Only used by GameCardFwMode and NcaSdkAddOnVersion. +typedef struct { + union { + struct { + u32 relstep : 8; + u32 micro : 8; + u32 minor : 8; + u32 major : 8; + }; + u32 value; + }; +} VersionType2; + +#endif /* __COMMON_H__ */ diff --git a/source/fs_ext.h b/source/fs_ext.h index 0140090..78914ba 100644 --- a/source/fs_ext.h +++ b/source/fs_ext.h @@ -27,7 +27,7 @@ /// Located at offset 0x7000 in the gamecard image. typedef struct { - u8 signature[0x100]; ///< RSA-2048 PKCS #1 signature over the rest of the data. + u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the data. u32 magic; ///< "CERT". u8 reserved_1[0x4]; u8 kek_index; diff --git a/source/gamecard.h b/source/gamecard.h index fb65586..3cccaa4 100644 --- a/source/gamecard.h +++ b/source/gamecard.h @@ -118,21 +118,6 @@ typedef enum { GameCardCompatibilityType_Terra = 1 } GameCardCompatibilityType; -typedef struct { - u32 GameCardFwMode_Relstep : 8; - u32 GameCardFwMode_Micro : 8; - u32 GameCardFwMode_Minor : 8; - u32 GameCardFwMode_Major : 8; -} GameCardFwMode; - -typedef struct { - u32 GameCardCupVersion_MinorRelstep : 8; - u32 GameCardCupVersion_MajorRelstep : 8; - u32 GameCardCupVersion_Micro : 4; - u32 GameCardCupVersion_Minor : 6; - u32 GameCardCupVersion_Major : 6; -} GameCardCupVersion; - /// Encrypted using AES-128-CBC with the XCI header key (found in FS program memory under newer versions of HOS) and the IV from `GameCardHeader`. /// Key hashes for documentation purposes: /// Production XCI header key hash: 2E36CC55157A351090A73E7AE77CF581F69B0B6E48FB066C984879A6ED7D2E96 @@ -144,8 +129,8 @@ typedef struct { u32 wait_2_time_read; ///< Always 0. u32 wait_1_time_write; ///< Always 0. u32 wait_2_time_write; ///< Always 0. - GameCardFwMode fw_mode; - GameCardCupVersion cup_version; + VersionType2 fw_mode; + VersionType1 cup_version; u8 compatibility_type; ///< GameCardCompatibilityType. u8 reserved_1[0x3]; u64 cup_hash; @@ -155,7 +140,7 @@ typedef struct { /// Placed after the `GameCardKeyArea` section. typedef struct { - u8 signature[0x100]; ///< RSA-2048 PKCS #1 signature over the rest of the header. + u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the header. u32 magic; ///< "HEAD". u32 secure_area_start_address; ///< Expressed in GAMECARD_MEDIA_UNIT_SIZE blocks. u32 backup_area_start_address; ///< Always 0xFFFFFFFF. diff --git a/source/nacp.c b/source/nacp.c index d2df0cb..fbb355c 100644 --- a/source/nacp.c +++ b/source/nacp.c @@ -30,158 +30,158 @@ typedef const char *(*NacpStringFunction)(u8 value); /* Used while adding fie static const char *g_unknownString = "Unknown"; -static const char *g_nacpLanguageStrings[] = { - [NacpLanguage_AmericanEnglish] = "AmericanEnglish", - [NacpLanguage_BritishEnglish] = "BritishEnglish", - [NacpLanguage_Japanese] = "Japanese", - [NacpLanguage_French] = "French", - [NacpLanguage_German] = "German", - [NacpLanguage_LatinAmericanSpanish] = "LatinAmericanSpanish", - [NacpLanguage_Spanish] = "Spanish", - [NacpLanguage_Italian] = "Italian", - [NacpLanguage_Dutch] = "Dutch", - [NacpLanguage_CanadianFrench] = "CanadianFrench", - [NacpLanguage_Portuguese] = "Portuguese", - [NacpLanguage_Russian] = "Russian", - [NacpLanguage_Korean] = "Korean", - [NacpLanguage_TraditionalChinese] = "TraditionalChinese", - [NacpLanguage_SimplifiedChinese] = "SimplifiedChinese", - [NacpLanguage_BrazilianPortuguese] = "BrazilianPortuguese" +static const char *g_nacpLanguageStrings[NacpLanguage_Count] = { + "AmericanEnglish", + "BritishEnglish", + "Japanese", + "French", + "German", + "LatinAmericanSpanish", + "Spanish", + "Italian", + "Dutch", + "CanadianFrench", + "Portuguese", + "Russian", + "Korean", + "TraditionalChinese", + "SimplifiedChinese", + "BrazilianPortuguese" }; -static const char *g_nacpStartupUserAccountStrings[] = { - [NacpStartupUserAccount_None] = "None", - [NacpStartupUserAccount_Required] = "Required", - [NacpStartupUserAccount_RequiredWithNetworkServiceAccountAvailable] = "RequiredWithNetworkServiceAccountAvailable" +static const char *g_nacpStartupUserAccountStrings[NacpStartupUserAccount_Count] = { + "None", + "Required", + "RequiredWithNetworkServiceAccountAvailable" }; -static const char *g_nacpUserAccountSwitchLockStrings[] = { - [NacpUserAccountSwitchLock_Disable] = "Disable", - [NacpUserAccountSwitchLock_Enable] = "Enable" +static const char *g_nacpUserAccountSwitchLockStrings[NacpUserAccountSwitchLock_Count] = { + "Disable", + "Enable" }; -static const char *g_nacpAddOnContentRegistrationTypeStrings[] = { - [NacpAddOnContentRegistrationType_AllOnLaunch] = "AllOnLaunch", - [NacpAddOnContentRegistrationType_OnDemand] = "OnDemand" +static const char *g_nacpAddOnContentRegistrationTypeStrings[NacpAddOnContentRegistrationType_Count] = { + "AllOnLaunch", + "OnDemand" }; -static const char *g_nacpAttributeStrings[] = { - [NacpAttribute_Demo] = "Demo", - [NacpAttribute_RetailInteractiveDisplay] = "RetailInteractiveDisplay" +static const char *g_nacpAttributeStrings[NacpAttribute_Count] = { + "Demo", + "RetailInteractiveDisplay" }; -static const char *g_nacpParentalControlStrings[] = { - [NacpParentalControl_FreeCommunication] = "FreeCommunication" +static const char *g_nacpParentalControlStrings[NacpParentalControl_Count] = { + "FreeCommunication" }; -static const char *g_nacpScreenshotStrings[] = { - [NacpScreenshot_Allow] = "Allow", - [NacpScreenshot_Deny] = "Deny" +static const char *g_nacpScreenshotStrings[NacpScreenshot_Count] = { + "Allow", + "Deny" }; -static const char *g_nacpVideoCaptureStrings[] = { - [NacpVideoCapture_Disable] = "Disable", - [NacpVideoCapture_Manual] = "Manual", - [NacpVideoCapture_Enable] = "Enable" +static const char *g_nacpVideoCaptureStrings[NacpVideoCapture_Count] = { + "Disable", + "Manual", + "Enable" }; -static const char *g_nacpDataLossConfirmationStrings[] = { - [NacpDataLossConfirmation_None] = "None", - [NacpDataLossConfirmation_Required] = "Required" +static const char *g_nacpDataLossConfirmationStrings[NacpDataLossConfirmation_Count] = { + "None", + "Required" }; -static const char *g_nacpPlayLogPolicyStrings[] = { - [NacpPlayLogPolicy_Open] = "Open", - [NacpPlayLogPolicy_LogOnly] = "LogOnly", - [NacpPlayLogPolicy_None] = "None", - [NacpPlayLogPolicy_Closed] = "Closed" +static const char *g_nacpPlayLogPolicyStrings[NacpPlayLogPolicy_Count] = { + "Open", + "LogOnly", + "None", + "Closed" }; -static const char *g_nacpRatingAgeOrganizationStrings[] = { - [NacpRatingAgeOrganization_CERO] = "CERO", - [NacpRatingAgeOrganization_GRACGCRB] = "GRACGCRB", - [NacpRatingAgeOrganization_GSRMR] = "GSRMR", - [NacpRatingAgeOrganization_ESRB] = "ESRB", - [NacpRatingAgeOrganization_ClassInd] = "ClassInd", - [NacpRatingAgeOrganization_USK] = "USK", - [NacpRatingAgeOrganization_PEGI] = "PEGI", - [NacpRatingAgeOrganization_PEGIPortugal] = "PEGIPortugal", - [NacpRatingAgeOrganization_PEGIBBFC] = "PEGIBBFC", - [NacpRatingAgeOrganization_Russian] = "Russian", - [NacpRatingAgeOrganization_ACB] = "ACB", - [NacpRatingAgeOrganization_OFLC] = "OFLC", - [NacpRatingAgeOrganization_IARCGeneric] = "IARCGeneric" +static const char *g_nacpRatingAgeOrganizationStrings[NacpRatingAgeOrganization_Count] = { + "CERO", + "GRACGCRB", + "GSRMR", + "ESRB", + "ClassInd", + "USK", + "PEGI", + "PEGIPortugal", + "PEGIBBFC", + "Russian", + "ACB", + "OFLC", + "IARCGeneric" }; -static const char *g_nacpLogoTypeStrings[] = { - [NacpLogoType_LicensedByNintendo] = "LicensedByNintendo", - [NacpLogoType_DistributedByNintendo] = "DistributedByNintendo", - [NacpLogoType_Nintendo] = "Nintendo" +static const char *g_nacpLogoTypeStrings[NacpLogoType_Count] = { + "LicensedByNintendo", + "DistributedByNintendo", + "Nintendo" }; -static const char *g_nacpLogoHandlingStrings[] = { - [NacpLogoHandling_Auto] = "Auto", - [NacpLogoHandling_Manual] = "Manual" +static const char *g_nacpLogoHandlingStrings[NacpLogoHandling_Count] = { + "Auto", + "Manual" }; -static const char *g_nacpRuntimeAddOnContentInstallStrings[] = { - [NacpRuntimeAddOnContentInstall_Deny] = "Deny", - [NacpRuntimeAddOnContentInstall_AllowAppend] = "AllowAppend", - [NacpRuntimeAddOnContentInstall_AllowAppendButDontDownloadWhenUsingNetwork] = "AllowAppendButDontDownloadWhenUsingNetwork" +static const char *g_nacpRuntimeAddOnContentInstallStrings[NacpRuntimeAddOnContentInstall_Count] = { + "Deny", + "AllowAppend", + "AllowAppendButDontDownloadWhenUsingNetwork" }; -static const char *g_nacpNacpRuntimeParameterDeliveryStrings[] = { - [NacpRuntimeParameterDelivery_Always] = "Always", - [NacpRuntimeParameterDelivery_AlwaysIfUserStateMatched] = "AlwaysIfUserStateMatched", - [NacpRuntimeParameterDelivery_OnRestart] = "OnRestart" +static const char *g_nacpNacpRuntimeParameterDeliveryStrings[NacpRuntimeParameterDelivery_Count] = { + "Always", + "AlwaysIfUserStateMatched", + "OnRestart" }; -static const char *g_nacpCrashReportStrings[] = { - [NacpCrashReport_Deny] = "Deny", - [NacpCrashReport_Allow] = "Allow" +static const char *g_nacpCrashReportStrings[NacpCrashReport_Count] = { + "Deny", + "Allow" }; -static const char *g_nacpHdcpStrings[] = { - [NacpHdcp_None] = "None", - [NacpHdcp_Required] = "Required" +static const char *g_nacpHdcpStrings[NacpHdcp_Count] = { + "None", + "Required" }; -static const char *g_nacpStartupUserAccountOptionStrings[] = { - [NacpStartupUserAccountOption_IsOptional] = "IsOptional" +static const char *g_nacpStartupUserAccountOptionStrings[NacpStartupUserAccountOption_Count] = { + "IsOptional" }; -static const char *g_nacpPlayLogQueryCapabilityStrings[] = { - [NacpPlayLogQueryCapability_None] = "None", - [NacpPlayLogQueryCapability_WhiteList] = "WhiteList", - [NacpPlayLogQueryCapability_All] = "All" +static const char *g_nacpPlayLogQueryCapabilityStrings[NacpPlayLogQueryCapability_Count] = { + "None", + "WhiteList", + "All" }; -static const char *g_nacpRepairStrings[] = { - [NacpRepair_SuppressGameCardAccess] = "SuppressGameCardAccess" +static const char *g_nacpRepairStrings[NacpRepair_Count] = { + "SuppressGameCardAccess" }; -static const char *g_nacpRequiredNetworkServiceLicenseOnLaunchStrings[] = { - [NacpRequiredNetworkServiceLicenseOnLaunch_Common] = "RequiredNetworkServiceLicenseOnLaunch" +static const char *g_nacpRequiredNetworkServiceLicenseOnLaunchStrings[NacpRequiredNetworkServiceLicenseOnLaunch_Count] = { + "Common" }; -static const char *g_nacpJitConfigurationFlagStrings[] = { - [NacpJitConfigurationFlag_None] = "None", - [NacpJitConfigurationFlag_Enabled] = "Enabled" +static const char *g_nacpJitConfigurationFlagStrings[NacpJitConfigurationFlag_Count] = { + "None", + "Enabled" }; -static const char *g_nacpPlayReportPermissionStrings[] = { - [NacpPlayReportPermission_None] = "None", - [NacpPlayReportPermission_TargetMarketing] = "TargetMarketing" +static const char *g_nacpPlayReportPermissionStrings[NacpPlayReportPermission_Count] = { + "None", + "TargetMarketing" }; -static const char *g_nacpCrashScreenshotForProdStrings[] = { - [NacpCrashScreenshotForProd_Deny] = "Deny", - [NacpCrashScreenshotForProd_Allow] = "Allow" +static const char *g_nacpCrashScreenshotForProdStrings[NacpCrashScreenshotForProd_Count] = { + "Deny", + "Allow" }; -static const char *g_nacpCrashScreenshotForDevStrings[] = { - [NacpCrashScreenshotForDev_Deny] = "Deny", - [NacpCrashScreenshotForDev_Allow] = "Allow" +static const char *g_nacpCrashScreenshotForDevStrings[NacpCrashScreenshotForDev_Count] = { + "Deny", + "Allow" }; /* Function prototypes. */ @@ -260,12 +260,12 @@ bool nacpInitializeContext(NacpContext *out, NcaContext *nca_ctx) out->nca_ctx = nca_ctx; /* Retrieve NACP icon data. */ - for(u8 i = 0; i < NacpLanguage_Count; i++) + for(u8 i = 0; i < NacpSupportedLanguage_Count; i++) { NacpIconContext *icon_ctx = NULL; /* Check if the current language is supported. */ - if (!nacpCheckBitflagField(&(out->data->supported_language_flag), sizeof(out->data->supported_language_flag) * 8, i)) continue; + if (!nacpCheckBitflagField(&(out->data->supported_language), sizeof(out->data->supported_language) * 8, i)) continue; /* Get language string. */ language_str = nacpGetLanguageString(i); @@ -388,21 +388,21 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "StartupUserAccount", nacp->startup_user_account, &nacpGetStartupUserAccountString)) goto end; /* StartupUserAccountOption. */ - if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "StartupUserAccountOption", &(nacp->startup_user_account_option_flag), sizeof(nacp->startup_user_account_option_flag), \ + if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "StartupUserAccountOption", &(nacp->startup_user_account_option), sizeof(nacp->startup_user_account_option), \ NacpStartupUserAccountOption_Count, &nacpGetStartupUserAccountOptionString)) goto end; /* UserAccountSwitchLock. */ if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSwitchLock", nacp->user_account_switch_lock, &nacpGetUserAccountSwitchLockString)) goto end; /* Attribute. */ - if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Attribute", &(nacp->attribute_flag), sizeof(nacp->attribute_flag), NacpAttribute_Count, &nacpGetAttributeString)) goto end; + if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Attribute", &(nacp->attribute), sizeof(nacp->attribute), NacpAttribute_Count, &nacpGetAttributeString)) goto end; /* ParentalControl. */ - if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ParentalControl", &(nacp->parental_control_flag), sizeof(nacp->parental_control_flag), NacpParentalControl_Count, \ + if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ParentalControl", &(nacp->parental_control), sizeof(nacp->parental_control), NacpParentalControl_Count, \ &nacpGetParentalControlString)) goto end; /* SupportedLanguage. */ - if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SupportedLanguage", &(nacp->supported_language_flag), sizeof(nacp->supported_language_flag), NacpLanguage_Count, \ + if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SupportedLanguage", &(nacp->supported_language), sizeof(nacp->supported_language), NacpSupportedLanguage_Count, \ &nacpGetLanguageString)) goto end; /* Screenshot. */ @@ -586,14 +586,14 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "PlayLogQueryCapability", nacp->play_log_query_capability, &nacpGetPlayLogQueryCapabilityString)) goto end; /* Repair. */ - if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Repair", &(nacp->repair_flag), sizeof(nacp->repair_flag), NacpRepair_Count, &nacpGetRepairString)) goto end; + if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Repair", &(nacp->repair), sizeof(nacp->repair), NacpRepair_Count, &nacpGetRepairString)) goto end; /* ProgramIndex. */ if (!nacpAddU16FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ProgramIndex", nacp->program_index, false)) goto end; /* RequiredNetworkServiceLicenseOnLaunch. */ - if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RequiredNetworkServiceLicenseOnLaunch", &(nacp->required_network_service_license_on_launch_flag), \ - sizeof(nacp->required_network_service_license_on_launch_flag), NacpRequiredNetworkServiceLicenseOnLaunch_Count, &nacpGetRequiredNetworkServiceLicenseOnLaunchString)) goto end; + if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RequiredNetworkServiceLicenseOnLaunch", &(nacp->required_network_service_license_on_launch), \ + sizeof(nacp->required_network_service_license_on_launch), NacpRequiredNetworkServiceLicenseOnLaunch_Count, &nacpGetRequiredNetworkServiceLicenseOnLaunchString)) goto end; /* NeighborDetectionClientConfiguration. */ ndcc_sgc_available = (ndcc->send_group_configuration.group_id && memcmp(ndcc->send_group_configuration.key, null_key, sizeof(null_key))); @@ -650,13 +650,13 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir /* RequiredAddOnContentsSet. */ for(i = 0, count = 0; i < 0x20; i++) { - if (!raocsbd->descriptors[i].NacpDescriptors_Index || !raocsbd->descriptors[i].NacpDescriptors_ContinueSet) continue; + if (!raocsbd->descriptors[i].index || !raocsbd->descriptors[i].continue_set) continue; if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ " \n" \ " %u\n" \ " \n", - raocsbd->descriptors[i].NacpDescriptors_Index)) goto end; + raocsbd->descriptors[i].index)) goto end; count++; } diff --git a/source/nacp.h b/source/nacp.h index b7bc0d5..e4cb439 100644 --- a/source/nacp.h +++ b/source/nacp.h @@ -36,35 +36,28 @@ typedef enum { NacpStartupUserAccount_None = 0, NacpStartupUserAccount_Required = 1, NacpStartupUserAccount_RequiredWithNetworkServiceAccountAvailable = 2, - NacpStartupUserAccount_Count = 3 ///< Not a real value. + NacpStartupUserAccount_Count = 3 ///< Total values supported by this enum. } NacpStartupUserAccount; typedef enum { NacpUserAccountSwitchLock_Disable = 0, NacpUserAccountSwitchLock_Enable = 1, - NacpUserAccountSwitchLock_Count = 2 ///< Not a real value. + NacpUserAccountSwitchLock_Count = 2 ///< Total values supported by this enum. } NacpUserAccountSwitchLock; typedef enum { NacpAddOnContentRegistrationType_AllOnLaunch = 0, NacpAddOnContentRegistrationType_OnDemand = 1, - NacpAddOnContentRegistrationType_Count = 2 ///< Not a real value. + NacpAddOnContentRegistrationType_Count = 2 ///< Total values supported by this enum. } NacpAddOnContentRegistrationType; -/// Indexes used to access NACP attribute info. typedef enum { - NacpAttribute_Demo = 0, - NacpAttribute_RetailInteractiveDisplay = 1, - NacpAttribute_Count = 2 ///< Not a real value. + NacpAttribute_Demo = BIT(0), + NacpAttribute_RetailInteractiveDisplay = BIT(1), + NacpAttribute_Count = 2 ///< Total values supported by this enum. } NacpAttribute; -typedef struct { - u32 NacpAttributeFlag_Demo : 1; - u32 NacpAttributeFlag_RetailInteractiveDisplay : 1; - u32 NacpAttributeFlag_Reserved : 30; -} NacpAttributeFlag; - -/// Indexes used to access NACP language info. +/// Indexes used to access NACP Title structs. typedef enum { NacpLanguage_AmericanEnglish = 0, NacpLanguage_BritishEnglish = 1, @@ -82,51 +75,45 @@ typedef enum { NacpLanguage_TraditionalChinese = 13, NacpLanguage_SimplifiedChinese = 14, NacpLanguage_BrazilianPortuguese = 15, - NacpLanguage_Count = 16 ///< Not a real value. + NacpLanguage_Count = 16 ///< Total values supported by this enum. } NacpLanguage; -typedef struct { - u32 NacpSupportedLanguageFlag_AmericanEnglish : 1; - u32 NacpSupportedLanguageFlag_BritishEnglish : 1; - u32 NacpSupportedLanguageFlag_Japanese : 1; - u32 NacpSupportedLanguageFlag_French : 1; - u32 NacpSupportedLanguageFlag_German : 1; - u32 NacpSupportedLanguageFlag_LatinAmericanSpanish : 1; - u32 NacpSupportedLanguageFlag_Spanish : 1; - u32 NacpSupportedLanguageFlag_Italian : 1; - u32 NacpSupportedLanguageFlag_Dutch : 1; - u32 NacpSupportedLanguageFlag_CanadianFrench : 1; - u32 NacpSupportedLanguageFlag_Portuguese : 1; - u32 NacpSupportedLanguageFlag_Russian : 1; - u32 NacpSupportedLanguageFlag_Korean : 1; - u32 NacpSupportedLanguageFlag_TraditionalChinese : 1; ///< Old: NacpSupportedLanguageFlag_Taiwanese. - u32 NacpSupportedLanguageFlag_SimplifiedChinese : 1; ///< Old: NacpSupportedLanguageFlag_Chinese. - u32 NacpSupportedLanguageFlag_BrazilianPortuguese : 1; - u32 NacpSupportedLanguageFlag_Reserved : 16; -} NacpSupportedLanguageFlag; - -/// Indexes used to access NACP parental control info. typedef enum { - NacpParentalControl_FreeCommunication = 0, - NacpParentalControl_Count = 1 ///< Not a real value. -} NacpParentalControl; + NacpSupportedLanguage_AmericanEnglish = BIT(0), + NacpSupportedLanguage_BritishEnglish = BIT(1), + NacpSupportedLanguage_Japanese = BIT(2), + NacpSupportedLanguage_French = BIT(3), + NacpSupportedLanguage_German = BIT(4), + NacpSupportedLanguage_LatinAmericanSpanish = BIT(5), + NacpSupportedLanguage_Spanish = BIT(6), + NacpSupportedLanguage_Italian = BIT(7), + NacpSupportedLanguage_Dutch = BIT(8), + NacpSupportedLanguage_CanadianFrench = BIT(9), + NacpSupportedLanguage_Portuguese = BIT(10), + NacpSupportedLanguage_Russian = BIT(11), + NacpSupportedLanguage_Korean = BIT(12), + NacpSupportedLanguage_TraditionalChinese = BIT(13), ///< Old: NacpSupportedLanguage_Taiwanese. + NacpSupportedLanguage_SimplifiedChinese = BIT(14), ///< Old: NacpSupportedLanguage_Chinese. + NacpSupportedLanguage_BrazilianPortuguese = BIT(15), + NacpSupportedLanguage_Count = 16 ///< Total values supported by this enum. Should always match NacpLanguage_Count. +} NacpSupportedLanguage; -typedef struct { - u32 NacpParentalControlFlag_FreeCommunication : 1; - u32 NacpParentalControlFlag_Reserved : 31; -} NacpParentalControlFlag; +typedef enum { + NacpParentalControl_FreeCommunication = BIT(0), + NacpParentalControl_Count = 1 ///< Total values supported by this enum. +} NacpParentalControl; typedef enum { NacpScreenshot_Allow = 0, NacpScreenshot_Deny = 1, - NacpScreenshot_Count = 2 ///< Not a real value. + NacpScreenshot_Count = 2 ///< Total values supported by this enum. } NacpScreenshot; typedef enum { NacpVideoCapture_Disable = 0, NacpVideoCapture_Manual = 1, NacpVideoCapture_Enable = 2, - NacpVideoCapture_Count = 3, ///< Not a real value. + NacpVideoCapture_Count = 3, ///< Total values supported by this enum. /// Old. NacpVideoCapture_Deny = NacpVideoCapture_Disable, @@ -136,7 +123,7 @@ typedef enum { typedef enum { NacpDataLossConfirmation_None = 0, NacpDataLossConfirmation_Required = 1, - NacpDataLossConfirmation_Count = 2 ///< Not a real value. + NacpDataLossConfirmation_Count = 2 ///< Total values supported by this enum. } NacpDataLossConfirmation; typedef enum { @@ -144,13 +131,13 @@ typedef enum { NacpPlayLogPolicy_LogOnly = 1, NacpPlayLogPolicy_None = 2, NacpPlayLogPolicy_Closed = 3, - NacpPlayLogPolicy_Count = 4, ///< Not a real value. + NacpPlayLogPolicy_Count = 4, ///< Total values supported by this enum. /// Old. NacpPlayLogPolicy_All = NacpPlayLogPolicy_Open } NacpPlayLogPolicy; -/// Indexes used to access NACP rating age info. +/// Indexes used to access NACP RatingAge info. typedef enum { NacpRatingAgeOrganization_CERO = 0, NacpRatingAgeOrganization_GRACGCRB = 1, @@ -165,7 +152,7 @@ typedef enum { NacpRatingAgeOrganization_ACB = 10, NacpRatingAgeOrganization_OFLC = 11, NacpRatingAgeOrganization_IARCGeneric = 12, - NacpRatingAgeOrganization_Count = 13 ///< Not a real value. + NacpRatingAgeOrganization_Count = 13 ///< Total values supported by this enum. } NacpRatingAgeOrganization; typedef struct { @@ -189,85 +176,67 @@ typedef enum { NacpLogoType_LicensedByNintendo = 0, NacpLogoType_DistributedByNintendo = 1, ///< Removed. NacpLogoType_Nintendo = 2, - NacpLogoType_Count = 3 ///< Not a real value. + NacpLogoType_Count = 3 ///< Total values supported by this enum. } NacpLogoType; typedef enum { NacpLogoHandling_Auto = 0, NacpLogoHandling_Manual = 1, - NacpLogoHandling_Count = 2 ///< Not a real value. + NacpLogoHandling_Count = 2 ///< Total values supported by this enum. } NacpLogoHandling; typedef enum { NacpRuntimeAddOnContentInstall_Deny = 0, NacpRuntimeAddOnContentInstall_AllowAppend = 1, NacpRuntimeAddOnContentInstall_AllowAppendButDontDownloadWhenUsingNetwork = 2, - NacpRuntimeAddOnContentInstall_Count = 3 ///< Not a real value. + NacpRuntimeAddOnContentInstall_Count = 3 ///< Total values supported by this enum. } NacpRuntimeAddOnContentInstall; typedef enum { NacpRuntimeParameterDelivery_Always = 0, NacpRuntimeParameterDelivery_AlwaysIfUserStateMatched = 1, NacpRuntimeParameterDelivery_OnRestart = 2, - NacpRuntimeParameterDelivery_Count = 3 ///< Not a real value. + NacpRuntimeParameterDelivery_Count = 3 ///< Total values supported by this enum. } NacpRuntimeParameterDelivery; typedef enum { NacpCrashReport_Deny = 0, NacpCrashReport_Allow = 1, - NacpCrashReport_Count = 2 ///< Not a real value. + NacpCrashReport_Count = 2 ///< Total values supported by this enum. } NacpCrashReport; typedef enum { NacpHdcp_None = 0, NacpHdcp_Required = 1, - NacpHdcp_Count = 2 ///< Not a real value. + NacpHdcp_Count = 2 ///< Total values supported by this enum. } NacpHdcp; -/// Indexes used to access NACP startup user account option info. typedef enum { - NacpStartupUserAccountOption_IsOptional = 0, - NacpStartupUserAccountOption_Count = 1 ///< Not a real value. + NacpStartupUserAccountOption_IsOptional = BIT(0), + NacpStartupUserAccountOption_Count = 1 ///< Total values supported by this enum. } NacpStartupUserAccountOption; -typedef struct { - u8 NacpStartupUserAccountOptionFlag_IsOptional : 1; - u8 NacpStartupUserAccountOptionFlag_Reserved : 7; -} NacpStartupUserAccountOptionFlag; - typedef enum { NacpPlayLogQueryCapability_None = 0, NacpPlayLogQueryCapability_WhiteList = 1, NacpPlayLogQueryCapability_All = 2, - NacpPlayLogQueryCapability_Count = 3 ///< Not a real value. + NacpPlayLogQueryCapability_Count = 3 ///< Total values supported by this enum. } NacpPlayLogQueryCapability; -/// Indexes used to access NACP repair info. typedef enum { - NacpRepair_SuppressGameCardAccess = 0, - NacpRepair_Count = 1 ///< Not a real value. + NacpRepair_SuppressGameCardAccess = BIT(0), + NacpRepair_Count = 1 ///< Total values supported by this enum. } NacpRepair; -typedef struct { - u8 NacpRepairFlag_SuppressGameCardAccess : 1; - u8 NacpRepairFlag_Reserved : 7; -} NacpRepairFlag; - -/// Indexes used to access NACP required network service license on launch info. typedef enum { - NacpRequiredNetworkServiceLicenseOnLaunch_Common = 0, - NacpRequiredNetworkServiceLicenseOnLaunch_Count = 1 ///< Not a real value. + NacpRequiredNetworkServiceLicenseOnLaunch_Common = BIT(0), + NacpRequiredNetworkServiceLicenseOnLaunch_Count = 1 ///< Total values supported by this enum. } NacpRequiredNetworkServiceLicenseOnLaunch; -typedef struct { - u8 NacpRequiredNetworkServiceLicenseOnLaunchFlag_Common : 1; - u8 NacpRequiredNetworkServiceLicenseOnLaunchFlag_Reserved : 7; -} NacpRequiredNetworkServiceLicenseOnLaunchFlag; - typedef enum { NacpJitConfigurationFlag_None = 0, NacpJitConfigurationFlag_Enabled = 1, - NacpJitConfigurationFlag_Count = 2 ///< Not a real value. + NacpJitConfigurationFlag_Count = 2 ///< Total values supported by this enum. } NacpJitConfigurationFlag; typedef struct { @@ -276,8 +245,8 @@ typedef struct { } NacpJitConfiguration; typedef struct { - u16 NacpDescriptors_Index : 15; - u16 NacpDescriptors_ContinueSet : 1; ///< Called "flag" by Nintendo, which isn't really great... + u16 index : 15; + u16 continue_set : 1; ///< Called "flag" by Nintendo, which isn't really great... } NacpDescriptors; typedef struct { @@ -287,19 +256,19 @@ typedef struct { typedef enum { NacpPlayReportPermission_None = 0, NacpPlayReportPermission_TargetMarketing = 1, - NacpPlayReportPermission_Count = 2 ///< Not a real value. + NacpPlayReportPermission_Count = 2 ///< Total values supported by this enum. } NacpPlayReportPermission; typedef enum { NacpCrashScreenshotForProd_Deny = 0, NacpCrashScreenshotForProd_Allow = 1, - NacpCrashScreenshotForProd_Count = 2 ///< Not a real value. + NacpCrashScreenshotForProd_Count = 2 ///< Total values supported by this enum. } NacpCrashScreenshotForProd; typedef enum { NacpCrashScreenshotForDev_Deny = 0, NacpCrashScreenshotForDev_Allow = 1, - NacpCrashScreenshotForDev_Count = 2 ///< Not a real value. + NacpCrashScreenshotForDev_Count = 2 ///< Total values supported by this enum. } NacpCrashScreenshotForDev; typedef struct { @@ -312,9 +281,9 @@ typedef struct { u8 startup_user_account; ///< NacpStartupUserAccount. u8 user_account_switch_lock; ///< NacpUserAccountSwitchLock. Old: touch_screen_usage (None, Supported, Required). u8 add_on_content_registration_type; ///< NacpAddOnContentRegistrationType. - NacpAttributeFlag attribute_flag; - NacpSupportedLanguageFlag supported_language_flag; - NacpParentalControlFlag parental_control_flag; + u32 attribute; ///< NacpAttribute. + u32 supported_language; ///< NacpSupportedLanguage. + u32 parental_control; ///< NacpParentalControl. u8 screenshot; ///< NacpScreenshot. u8 video_capture; ///< NacpVideoCapture. u8 data_loss_confirmation; ///< NacpDataLossConfirmation. @@ -340,7 +309,7 @@ typedef struct { u8 hdcp; ///< NacpHdcp. u64 seed_for_pseudo_device_id; char bcat_passphrase[0x41]; - NacpStartupUserAccountOptionFlag startup_user_account_option_flag; + u8 startup_user_account_option; ///< NacpStartupUserAccountOption. u8 reserved_2[0x6]; u64 user_account_save_data_size_max; u64 user_account_save_data_journal_size_max; @@ -354,9 +323,9 @@ typedef struct { u8 reserved_3[0x6]; u64 play_log_queryable_application_id[0x10]; u8 play_log_query_capability; ///< NacpPlayLogQueryCapability. - NacpRepairFlag repair_flag; + u8 repair; ///< NacpRepair. u8 program_index; - NacpRequiredNetworkServiceLicenseOnLaunchFlag required_network_service_license_on_launch_flag; + u8 required_network_service_license_on_launch; ///< NacpRequiredNetworkServiceLicenseOnLaunch. u8 reserved_4[0x4]; NacpNeighborDetectionClientConfiguration neighbor_detection_client_configuration; NacpJitConfiguration jit_configuration; @@ -398,9 +367,11 @@ bool nacpInitializeContext(NacpContext *out, NcaContext *nca_ctx); /// If the function succeeds, XML data and size will get saved to the 'authoring_tool_xml' and 'authoring_tool_xml_size' members from the NacpContext. bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 required_system_version); -/// These functions return pointers to string representations of the input value. -/// If the provided value is invalid, "Unknown" is returned. -const char *nacpGetLanguageString(u8 language); +/// These functions return pointers to string representations of the input flag/value index (e.g. nacpGetLanguageString(NacpLanguage_AmericanEnglish) -> "AmericanEnglish"). +/// If the input flag/value index is invalid, "Unknown" will be returned. +/// If dealing with a bitflag field such as NacpAttribute, NacpSupportedLanguage, etc., the provided value must be a 0-based index to the desired flag and not a bitmask from its enum. +/// (e.g. NacpAttribute_RetailInteractiveDisplay -> Use 1 instead). +const char *nacpGetLanguageString(u8 language); ///< Can also be used for NacpSupportedLanguage flags with values from the NacpLanguage enum. const char *nacpGetStartupUserAccountString(u8 startup_user_account); const char *nacpGetUserAccountSwitchLockString(u8 user_account_switch_lock); const char *nacpGetAddOnContentRegistrationTypeString(u8 add_on_content_registration_type); @@ -421,7 +392,7 @@ const char *nacpGetStartupUserAccountOptionString(u8 startup_user_account_option const char *nacpGetPlayLogQueryCapabilityString(u8 play_log_query_capability); const char *nacpGetRepairString(u8 repair); const char *nacpGetRequiredNetworkServiceLicenseOnLaunchString(u8 required_network_service_license_on_launch); -const char *nacpGetJitConfigurationFlagString(u64 jig_configuration_flag); +const char *nacpGetJitConfigurationFlagString(u64 jig_configuration_flag); ///< Uses an input u64 value. const char *nacpGetPlayReportPermissionString(u8 play_report_permission); const char *nacpGetCrashScreenshotForProdString(u8 crash_screenshot_for_prod); const char *nacpGetCrashScreenshotForDevString(u8 crash_screenshot_for_dev); diff --git a/source/nca.h b/source/nca.h index 700747a..1452c8c 100644 --- a/source/nca.h +++ b/source/nca.h @@ -73,13 +73,6 @@ typedef enum { NcaKeyAreaEncryptionKeyIndex_System = 2 } NcaKeyAreaEncryptionKeyIndex; -typedef struct { - u32 NcaSdkAddOnVersion_Relstep : 8; - u32 NcaSdkAddOnVersion_Micro : 8; - u32 NcaSdkAddOnVersion_Minor : 8; - u32 NcaSdkAddOnVersion_Major : 8; -} NcaSdkAddOnVersion; - /// 'NcaKeyGeneration_Current' will always point to the last known key generation value. typedef enum { NcaKeyGeneration_301_302 = 3, @@ -119,8 +112,8 @@ typedef struct { /// First 0x400 bytes from every NCA. typedef struct { - u8 main_signature[0x100]; ///< RSA-PSS signature over header with fixed key. - u8 acid_signature[0x100]; ///< RSA-PSS signature over header with key in NPDM. + u8 main_signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over header using a fixed key. + u8 acid_signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over header using the ACID public key from the NPDM in ExeFS. Only used in Program NCAs. u32 magic; ///< "NCA0" / "NCA2" / "NCA3". u8 distribution_type; ///< NcaDistributionType. u8 content_type; ///< NcaContentType. @@ -129,7 +122,7 @@ typedef struct { u64 content_size; u64 program_id; u32 content_index; - NcaSdkAddOnVersion sdk_addon_version; + VersionType2 sdk_addon_version; u8 key_generation; ///< NcaKeyGeneration. u8 main_signature_key_generation; u8 reserved[0xE]; diff --git a/source/pfs.c b/source/pfs.c index 15a4b0f..2b20153 100644 --- a/source/pfs.c +++ b/source/pfs.c @@ -20,6 +20,9 @@ #include "utils.h" #include "pfs.h" +//#include "npdm.h" + +#define NPDM_META_MAGIC 0x4D455441 /* "META". */ bool pfsInitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext *nca_fs_ctx) { @@ -56,7 +59,7 @@ bool pfsInitializeContext(PartitionFileSystemContext *out, NcaFsSectionContext * out->offset = hash_region->offset; out->size = hash_region->size; - /* Read partial PFS header. */ + /* Read partial Partition FS header. */ if (!ncaReadFsSection(nca_fs_ctx, &pfs_header, sizeof(PartitionFileSystemHeader), out->offset)) { LOGFILE("Failed to read partial Partition FS header!"); @@ -167,7 +170,8 @@ bool pfsGetEntryIndexByName(PartitionFileSystemContext *ctx, const char *name, u } } - //LOGFILE("Unable to find Partition FS entry \"%s\"!", name); + /* Only log error if we're not dealing with a NPDM. */ + if (name_len != 9 || strcmp(name, "main.npdm") != 0) LOGFILE("Unable to find Partition FS entry \"%s\"!", name); return false; } diff --git a/source/rsa.c b/source/rsa.c index 66dfa3f..192c88c 100644 --- a/source/rsa.c +++ b/source/rsa.c @@ -32,7 +32,7 @@ /* Global variables. */ /// Self-generated private key. -static const char g_rsa2048CustomAcidPrivateKey[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" +static const char g_rsa2048CustomPrivateKey[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" "MIIEowIBAAKCAQEAvVRzt+8mE7oE4RkmSh3ws4CGlBj7uhHkfwCpPFsn4TNVdLRo\r\n" "YYY17jQYWTtcOYPMcHxwUpgJyspGN8QGXEkJqY8jILv2eO0jBGtg7Br2afUBp6/x\r\n" "BOMT2RlYVX6H4a1UA19Hzmcn+T1hdDwS6oBYpi8rJSm0+q+yB34dueNkVsk4eKbj\r\n" @@ -61,7 +61,8 @@ static const char g_rsa2048CustomAcidPrivateKey[] = "-----BEGIN RSA PRIVATE KEY- "-----END RSA PRIVATE KEY-----\r\n"; /// Self-generated public key. -static const u8 g_rsa2048CustomAcidPublicKey[] = { +/// Used to verify signatures generated with g_rsa2048CustomPrivateKey. +static const u8 g_rsa2048CustomPublicKey[] = { 0xBD, 0x54, 0x73, 0xB7, 0xEF, 0x26, 0x13, 0xBA, 0x04, 0xE1, 0x19, 0x26, 0x4A, 0x1D, 0xF0, 0xB3, 0x80, 0x86, 0x94, 0x18, 0xFB, 0xBA, 0x11, 0xE4, 0x7F, 0x00, 0xA9, 0x3C, 0x5B, 0x27, 0xE1, 0x33, 0x55, 0x74, 0xB4, 0x68, 0x61, 0x86, 0x35, 0xEE, 0x34, 0x18, 0x59, 0x3B, 0x5C, 0x39, 0x83, 0xCC, @@ -84,7 +85,7 @@ static const u8 g_rsa2048CustomAcidPublicKey[] = { static void rsaCalculateMgf1AndXor(void *data, size_t data_size, const void *h_src, size_t h_src_size); -bool rsa2048GenerateSha256BasedCustomAcidSignature(void *dst, const void *src, size_t size) +bool rsa2048GenerateSha256BasedPssSignature(void *dst, const void *src, size_t size) { if (!dst || !src || !size) { @@ -121,7 +122,7 @@ bool rsa2048GenerateSha256BasedCustomAcidSignature(void *dst, const void *src, s } /* Parse private key. */ - ret = mbedtls_pk_parse_key(&pk, (u8*)g_rsa2048CustomAcidPrivateKey, strlen(g_rsa2048CustomAcidPrivateKey) + 1, NULL, 0); + ret = mbedtls_pk_parse_key(&pk, (const u8*)g_rsa2048CustomPrivateKey, strlen(g_rsa2048CustomPrivateKey) + 1, NULL, 0); if (ret != 0) { LOGFILE("mbedtls_pk_parse_key failed! (%d).", ret); @@ -151,9 +152,9 @@ end: return success; } -const u8 *rsa2048GetCustomAcidPublicKey(void) +const u8 *rsa2048GetCustomPublicKey(void) { - return g_rsa2048CustomAcidPublicKey; + return g_rsa2048CustomPublicKey; } bool rsa2048OaepDecryptAndVerify(void *dst, size_t dst_size, const void *signature, const void *modulus, const void *exponent, size_t exponent_size, const void *label_hash, size_t *out_size) diff --git a/source/rsa.h b/source/rsa.h index 62581b8..68bbc3a 100644 --- a/source/rsa.h +++ b/source/rsa.h @@ -27,12 +27,14 @@ #define RSA2048_SIG_SIZE 0x100 -/// Generates a SHA-256 based RSA-2048 signature, suitable to replace the ACID signature in NCA headers. -bool rsa2048GenerateSha256BasedCustomAcidSignature(void *dst, const void *src, size_t size); +/// Generates a RSA-2048-PSS with SHA-256 signature using a custom RSA-2048 private key. +/// Suitable to replace the ACID signature in a Program NCA header. +/// Destination buffer size should be at least RSA2048_SIG_SIZE. +bool rsa2048GenerateSha256BasedPssSignature(void *dst, const void *src, size_t size); -/// Returns the custom ACID public key that can be used to verify the signature generated by rsa2048GenerateSha256BasedCustomAcidSignature(). -/// Suitable to replace the ACID public key in main.npdm files. -const u8 *rsa2048GetCustomAcidPublicKey(void); +/// Returns a pointer to the RSA-2048 public key that can be used to verify signatures generated by rsa2048GenerateSha256BasedPssSignature(). +/// Suitable to replace the ACID public key in a NPDM. +const u8 *rsa2048GetCustomPublicKey(void); /// Performs RSA-2048-OAEP decryption and verification. Used to decrypt the titlekey block from tickets with personalized crypto. bool rsa2048OaepDecryptAndVerify(void *dst, size_t dst_size, const void *signature, const void *modulus, const void *exponent, size_t exponent_size, const void *label_hash, size_t *out_size); diff --git a/source/title.c b/source/title.c index 605e901..bb78246 100644 --- a/source/title.c +++ b/source/title.c @@ -1358,7 +1358,7 @@ static bool titleRetrieveContentMetaKeysFromDatabase(u8 storage_id) /* Fill information. */ cur_title_info->storage_id = storage_id; memcpy(&(cur_title_info->meta_key), &(meta_keys[i]), sizeof(NcmContentMetaKey)); - memcpy(&(cur_title_info->version), &(meta_keys[i].version), sizeof(u32)); + cur_title_info->version.value = meta_keys[i].version; if (cur_title_info->meta_key.type <= NcmContentMetaType_Application) cur_title_info->app_metadata = titleFindApplicationMetadataByTitleId(meta_keys[i].id); diff --git a/source/title.h b/source/title.h index d57afd6..7704c2d 100644 --- a/source/title.h +++ b/source/title.h @@ -31,15 +31,6 @@ #define TITLE_DELTA_TYPE_VALUE (u64)0xC00 -/// Used to display version numbers in dot notation: "{Major}.{Minor}.{Micro}-{MajorRelstep}.{MinorRelstep}". -typedef struct { - u32 TitleVersion_MinorRelstep : 8; - u32 TitleVersion_MajorRelstep : 8; - u32 TitleVersion_Micro : 4; - u32 TitleVersion_Minor : 6; - u32 TitleVersion_Major : 6; -} TitleVersion; - /// Retrieved using ns application records and/or ncm content meta keys. /// Used by the UI to display title lists. typedef struct { @@ -53,7 +44,7 @@ typedef struct { typedef struct _TitleInfo { u8 storage_id; ///< NcmStorageId. NcmContentMetaKey meta_key; ///< Used with ncm calls. - TitleVersion version; ///< Holds the same value from meta_key.version. + VersionType1 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 title_size; ///< Total title size. @@ -230,9 +221,4 @@ NX_INLINE NcmContentInfo *titleGetContentInfoByTypeAndIdOffset(TitleInfo *info, return NULL; } -NX_INLINE u32 titleGetVersionInteger(TitleVersion *version) -{ - return (version ? *((u32*)version) : 0); -} - #endif /* __TITLE_H__ */ diff --git a/source/utils.c b/source/utils.c index 67ed8a5..cdf6787 100644 --- a/source/utils.c +++ b/source/utils.c @@ -51,6 +51,8 @@ static u8 g_customFirmwareType = UtilsCustomFirmwareType_Unknown; static AppletHookCookie g_systemOverclockCookie = {0}; static Mutex g_logfileMutex = 0; +static const char *g_logfileTimestampFormat = "%d-%02d-%02d %02d:%02d:%02d -> %s: "; +static const char *g_logfileLineBreak = "\r\n"; static const char *g_sizeSuffixes[] = { "B", "KiB", "MiB", "GiB" }; static const u32 g_sizeSuffixesCount = MAX_ELEMENTS(g_sizeSuffixes); @@ -389,13 +391,13 @@ void utilsWriteMessageToLogFile(const char *func_name, const char *fmt, ...) time_t now = time(NULL); struct tm *ts = localtime(&now); - fprintf(logfile, "%d-%02d-%02d %02d:%02d:%02d -> %s: ", ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec, func_name); + fprintf(logfile, g_logfileTimestampFormat, ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec, func_name); va_start(args, fmt); vfprintf(logfile, fmt, args); va_end(args); - fprintf(logfile, "\r\n"); + fprintf(logfile, g_logfileLineBreak); fclose(logfile); utilsCommitSdCardFileSystemChanges(); @@ -423,7 +425,7 @@ void utilsWriteMessageToLogBuffer(char **dst, size_t *dst_size, const char *func dst_str_len = 0; } - timestamp_len = snprintf(NULL, 0, "%d-%02d-%02d %02d:%02d:%02d -> %s: ", ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec, func_name); + timestamp_len = snprintf(NULL, 0, g_logfileTimestampFormat, ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec, func_name); if (timestamp_len <= 0) goto end; formatted_str_len = vsnprintf(NULL, 0, fmt, args); @@ -443,9 +445,9 @@ void utilsWriteMessageToLogBuffer(char **dst, size_t *dst_size, const char *func *dst_size = required_dst_size; } - sprintf(*dst + dst_str_len, "%d-%02d-%02d %02d:%02d:%02d -> %s: ", ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec, func_name); + sprintf(*dst + dst_str_len, g_logfileTimestampFormat, ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec, func_name); vsprintf(*dst + dst_str_len + (size_t)timestamp_len, fmt, args); - sprintf(*dst + dst_str_len + (size_t)timestamp_len + (size_t)formatted_str_len, "\r\n"); + sprintf(*dst + dst_str_len + (size_t)timestamp_len + (size_t)formatted_str_len, g_logfileLineBreak); end: va_end(args); diff --git a/source/utils.h b/source/utils.h index 4d9dff5..271f2e8 100644 --- a/source/utils.h +++ b/source/utils.h @@ -38,6 +38,8 @@ #include #include +#include "common.h" + #define APP_BASE_PATH "sdmc:/switch/" APP_TITLE "/" #define MEMBER_SIZE(type, member) sizeof(((type*)NULL)->member) @@ -58,10 +60,6 @@ -/// Need to move this to npdm.c/h eventually. -#define NPDM_META_MAGIC 0x4D455441 /* "META". */ - -