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". */
-
-