diff --git a/code_templates/gc_dumper.c b/code_templates/gc_dumper.c
index a76fdb7..45db0e6 100644
--- a/code_templates/gc_dumper.c
+++ b/code_templates/gc_dumper.c
@@ -696,11 +696,11 @@ static bool saveGameCardIdSet(void)
crc = crc32Calculate(&id_set, sizeof(FsGameCardIdSet));
snprintf(path, MAX_ELEMENTS(path), " (Card ID Set) (%08X).bin", crc);
- if (!saveFileData(filename, &id_set, sizeof(FsGameCardIdSet))) goto end;
-
filename = generateOutputFileName(path);
if (!filename) goto end;
+ if (!saveFileData(filename, &id_set, sizeof(FsGameCardIdSet))) goto end;
+
printf("successfully saved gamecard id set as \"%s\"\n", filename);
success = true;
diff --git a/include/core/nacp.h b/include/core/nacp.h
index 158c6af..6e267ff 100644
--- a/include/core/nacp.h
+++ b/include/core/nacp.h
@@ -49,7 +49,12 @@ typedef enum {
typedef enum {
NacpUserAccountSwitchLock_Disable = 0,
NacpUserAccountSwitchLock_Enable = 1,
- NacpUserAccountSwitchLock_Count = 2 ///< Total values supported by this enum.
+ NacpUserAccountSwitchLock_Count = 2, ///< Total values supported by this enum.
+
+ // Old.
+ NacpTouchScreenUsage_None = 0,
+ NacpTouchScreenUsage_Supported = 1,
+ NacpTouchScreenUsage_Required = 2
} NacpUserAccountSwitchLock;
typedef enum {
@@ -61,7 +66,8 @@ typedef enum {
typedef enum {
NacpAttribute_Demo = BIT(0),
NacpAttribute_RetailInteractiveDisplay = BIT(1),
- NacpAttribute_Count = 2 ///< Total values supported by this enum.
+ NacpAttribute_DownloadPlay = BIT(2), ///< Removed.
+ NacpAttribute_Count = 3 ///< Total values supported by this enum.
} NacpAttribute;
/// Indexes used to access NACP Title structs.
@@ -106,7 +112,7 @@ typedef enum {
NacpSupportedLanguage_TraditionalChinese = BIT(13),
NacpSupportedLanguage_SimplifiedChinese = BIT(14),
NacpSupportedLanguage_BrazilianPortuguese = BIT(15),
- NacpSupportedLanguage_Count = 16, ///< Total values supported by this enum. Should always match NacpLanguage_Count.
+ NacpSupportedLanguage_Count = 16, ///< Total values supported by this enum. Should always match NacpLanguage_Count.
///< Old.
NacpSupportedLanguage_Taiwanese = NacpSupportedLanguage_TraditionalChinese,
@@ -216,6 +222,14 @@ typedef enum {
NacpRuntimeParameterDelivery_Count = 3 ///< Total values supported by this enum.
} NacpRuntimeParameterDelivery;
+typedef enum {
+ NacpAppropriateAgeForChina_None = 0,
+ NacpAppropriateAgeForChina_Age8 = 1,
+ NacpAppropriateAgeForChina_Age12 = 2,
+ NacpAppropriateAgeForChina_Age16 = 3,
+ NacpAppropriateAgeForChina_Count = 4 ///< Total values supported by this enum.
+} NacpAppropriateAgeForChina;
+
typedef enum {
NacpUndecidedParameter75b8b_A = 0,
NacpUndecidedParameter75b8b_B = 1,
@@ -239,6 +253,17 @@ typedef enum {
NacpStartupUserAccountOption_Count = 1 ///< Total values supported by this enum.
} NacpStartupUserAccountOption;
+typedef enum {
+ NacpRuntimeUpgrade_Deny = 0,
+ NacpRuntimeUpgrade_Allow = 1,
+ NacpRuntimeUpgrade_Count = 2 ///< Total values supported by this enum.
+} NacpRuntimeUpgrade;
+
+typedef enum {
+ NacpSupportingLimitedLicenses_Demo = BIT(1),
+ NacpSupportingLimitedLicenses_Count = 1 ///< Total values supported by this enum.
+} NacpSupportingLimitedLicenses;
+
typedef enum {
NacpPlayLogQueryCapability_None = 0,
NacpPlayLogQueryCapability_WhiteList = 1,
@@ -257,9 +282,8 @@ typedef enum {
} NacpRequiredNetworkServiceLicenseOnLaunch;
typedef enum {
- NacpJitConfigurationFlag_None = 0,
- NacpJitConfigurationFlag_Enabled = 1,
- NacpJitConfigurationFlag_Count = 2 ///< Total values supported by this enum.
+ NacpJitConfigurationFlag_Enabled = BIT_LONG(0),
+ NacpJitConfigurationFlag_Count = 1 ///< Total values supported by this enum.
} NacpJitConfigurationFlag;
typedef struct {
@@ -269,23 +293,27 @@ typedef struct {
NXDT_ASSERT(NacpJitConfiguration, 0x10);
-typedef struct {
- u16 index : 15;
- u16 continue_set : 1; ///< Called "flag" by Nintendo, which isn't really great.
-} NacpDescriptors;
-
-NXDT_ASSERT(NacpDescriptors, 0x2);
+typedef enum {
+ NacpRequiredAddOnContentsSetDescriptorFlag_None = 0,
+ NacpRequiredAddOnContentsSetDescriptorFlag_Continue = 1
+} NacpRequiredAddOnContentsSetDescriptorFlag;
typedef struct {
- NacpDescriptors descriptors[0x20];
+ u16 index : 15;
+ u16 flag : 1; ///< NacpRequiredAddOnContentsSetDescriptorFlag.
+} NacpRequiredAddOnContentsSetDescriptor;
+
+NXDT_ASSERT(NacpRequiredAddOnContentsSetDescriptor, 0x2);
+
+typedef struct {
+ NacpRequiredAddOnContentsSetDescriptor descriptors[0x20];
} NacpRequiredAddOnContentsSetBinaryDescriptor;
NXDT_ASSERT(NacpRequiredAddOnContentsSetBinaryDescriptor, 0x40);
typedef enum {
- NacpPlayReportPermission_None = 0,
- NacpPlayReportPermission_TargetMarketing = 1,
- NacpPlayReportPermission_Count = 2 ///< Total values supported by this enum.
+ NacpPlayReportPermission_TargetMarketing = BIT(0),
+ NacpPlayReportPermission_Count = 1 ///< Total values supported by this enum.
} NacpPlayReportPermission;
typedef enum {
@@ -300,6 +328,16 @@ typedef enum {
NacpCrashScreenshotForDev_Count = 2 ///< Total values supported by this enum.
} NacpCrashScreenshotForDev;
+typedef enum {
+ NacpContentsAvailabilityTransitionPolicy_NoPolicy = 0,
+ NacpContentsAvailabilityTransitionPolicy_Stable = 1,
+ NacpContentsAvailabilityTransitionPolicy_Changeable = 2,
+ NacpContentsAvailabilityTransitionPolicy_Count = 3, ///< Total values supported by this enum.
+
+ // Old.
+ NacpContentsAvailabilityTransitionPolicy_Legacy = NacpContentsAvailabilityTransitionPolicy_NoPolicy
+} NacpContentsAvailabilityTransitionPolicy;
+
typedef struct {
u64 application_id[8];
} NacpAccessibleLaunchRequiredVersion;
@@ -310,7 +348,7 @@ typedef struct {
NacpTitle title[0x10];
char isbn[0x25];
u8 startup_user_account; ///< NacpStartupUserAccount.
- u8 user_account_switch_lock; ///< NacpUserAccountSwitchLock. Old: touch_screen_usage (None, Supported, Required).
+ u8 user_account_switch_lock; ///< NacpUserAccountSwitchLock.
u8 add_on_content_registration_type; ///< NacpAddOnContentRegistrationType.
u32 attribute; ///< NacpAttribute.
u32 supported_language; ///< NacpSupportedLanguage.
@@ -335,14 +373,14 @@ typedef struct {
u8 logo_handling; ///< NacpLogoHandling.
u8 runtime_add_on_content_install; ///< NacpRuntimeAddOnContentInstall.
u8 runtime_parameter_delivery; ///< NacpRuntimeParameterDelivery.
- u8 reserved_1;
+ u8 appropriate_age_for_china; ///< NacpAppropriateAgeForChina.
u8 undecided_parameter_75b8b; ///< NacpUndecidedParameter75b8b.
u8 crash_report; ///< NacpCrashReport.
u8 hdcp; ///< NacpHdcp.
u64 seed_for_pseudo_device_id;
char bcat_passphrase[0x41];
u8 startup_user_account_option; ///< NacpStartupUserAccountOption.
- u8 reserved_2[0x6];
+ u8 reserved_for_user_account_save_data_operation[0x6];
s64 user_account_save_data_size_max;
s64 user_account_save_data_journal_size_max;
s64 device_save_data_size_max;
@@ -352,22 +390,25 @@ typedef struct {
s64 cache_storage_journal_size;
s64 cache_storage_data_and_journal_size_max;
u16 cache_storage_index_max;
- u8 reserved_3[0x6];
+ u8 reserved_1[0x1];
+ u8 runtime_upgrade; ///< NacpRuntimeUpgrade.
+ u32 supporting_limited_licenses; ///< NacpSupportingLimitedLicenses.
u64 play_log_queryable_application_id[0x10];
u8 play_log_query_capability; ///< NacpPlayLogQueryCapability.
u8 repair; ///< NacpRepair.
u8 program_index;
u8 required_network_service_license_on_launch; ///< NacpRequiredNetworkServiceLicenseOnLaunch.
- u8 reserved_4[0x4];
+ u8 reserved_2[0x4];
NacpNeighborDetectionClientConfiguration neighbor_detection_client_configuration;
NacpJitConfiguration jit_configuration;
NacpRequiredAddOnContentsSetBinaryDescriptor required_add_on_contents_set_binary_descriptor;
u8 play_report_permission; ///< NacpPlayReportPermission.
u8 crash_screenshot_for_prod; ///< NacpCrashScreenshotForProd.
u8 crash_screenshot_for_dev; ///< NacpCrashScreenshotForDev.
- u8 reserved_5[0x5];
+ u8 contents_availability_transition_policy; ///< NacpContentsAvailabilityTransitionPolicy.
+ u8 reserved_3[0x4];
NacpAccessibleLaunchRequiredVersion accessible_launch_required_version;
- u8 reserved_6[0xBB8];
+ u8 reserved_4[0xBB8];
} _NacpStruct;
NXDT_ASSERT(_NacpStruct, 0x4000);
@@ -413,8 +454,13 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
/// 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).
+/// If dealing with a bitflag field such as:
+/// * NacpAttribute
+/// * NacpSupportedLanguage
+/// * NacpParentalControl
+/// * NacpStartupUserAccountOption
+/// * NacpRepair
+/// Then, 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);
@@ -430,17 +476,18 @@ const char *nacpGetLogoTypeString(u8 logo_type);
const char *nacpGetLogoHandlingString(u8 logo_handling);
const char *nacpGetRuntimeAddOnContentInstallString(u8 runtime_add_on_content_install);
const char *nacpGetRuntimeParameterDeliveryString(u8 runtime_parameter_delivery);
+const char *nacpGetAppropriateAgeForChina(u8 appropriate_age_for_china);
const char *nacpGetUndecidedParameter75b8bString(u8 undecided_parameter_75b8b);
const char *nacpGetCrashReportString(u8 crash_report);
const char *nacpGetHdcpString(u8 hdcp);
const char *nacpGetStartupUserAccountOptionString(u8 startup_user_account_option);
+const char *nacpGetRuntimeUpgradeString(u8 runtime_upgrade);
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); ///< 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);
+const char *nacpGetContentsAvailabilityTransitionPolicyString(u8 contents_availability_transition_policy);
/// Helper inline functions.
diff --git a/libs/libusbhsfs b/libs/libusbhsfs
index d6afc3c..0580fc3 160000
--- a/libs/libusbhsfs
+++ b/libs/libusbhsfs
@@ -1 +1 @@
-Subproject commit d6afc3c2ba17158553397d1f1d3a607da661f2ba
+Subproject commit 0580fc38903546a99cc09e4f16418a3863e067b0
diff --git a/source/core/cnmt.c b/source/core/cnmt.c
index 35f42e7..0a3dfa2 100644
--- a/source/core/cnmt.c
+++ b/source/core/cnmt.c
@@ -23,7 +23,10 @@
#include "cnmt.h"
#include "title.h"
+/* Helper macros. */
+
#define CNMT_MINIMUM_FILENAME_LENGTH 23 /* Content Meta Type + "_" + Title ID + ".cnmt". */
+#define CNMT_ADD_FMT_STR(fmt, ...) utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, fmt, ##__VA_ARGS__)
/* Global variables. */
@@ -367,31 +370,33 @@ bool cnmtGenerateAuthoringToolXml(ContentMetaContext *cnmt_ctx, NcaContext *nca_
cnmt_ctx->authoring_tool_xml = NULL;
cnmt_ctx->authoring_tool_xml_size = 0;
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- "\n" \
- "\n" \
- " %s\n" \
- " 0x%016lx\n" \
- " %u\n" \
- " \n" \
- " \n",
- titleGetNcmContentMetaTypeName(cnmt_ctx->packaged_header->content_meta_type), \
- cnmt_ctx->packaged_header->title_id, \
- cnmt_ctx->packaged_header->version.value)) goto end;
+ if (!CNMT_ADD_FMT_STR("\n" \
+ "\n" \
+ " %s\n" \
+ " 0x%016lx\n" \
+ " %u\n" \
+ " %u\n" \
+ " %u\n", \
+ titleGetNcmContentMetaTypeName(cnmt_ctx->packaged_header->content_meta_type), \
+ cnmt_ctx->packaged_header->title_id, \
+ cnmt_ctx->packaged_header->version.value, \
+ cnmt_ctx->packaged_header->version.application_version.release_ver, \
+ cnmt_ctx->packaged_header->version.application_version.private_ver)) goto end;
/* ContentMetaAttribute. */
for(i = 0; i < ContentMetaAttribute_Count; i++)
{
if (!(cnmt_ctx->packaged_header->content_meta_attribute & (u8)BIT(i))) continue;
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " %s\n", g_cnmtAttributeStrings[i])) goto end;
+ if (!CNMT_ADD_FMT_STR(" %s\n", g_cnmtAttributeStrings[i])) goto end;
count++;
}
- if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ if (!count && !CNMT_ADD_FMT_STR(" \n")) goto end;
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " %u\n", \
- cnmt_ctx->packaged_header->required_download_system_version.value)) goto end;
+ /* RequiredDownloadSystemVersion. */
+ if (!CNMT_ADD_FMT_STR(" %u\n", cnmt_ctx->packaged_header->required_download_system_version.value)) goto end;
+ /* Contents. */
for(i = 0; i < nca_ctx_count; i++)
{
NcaContext *cur_nca_ctx = &(nca_ctx[i]);
@@ -417,34 +422,35 @@ bool cnmtGenerateAuthoringToolXml(ContentMetaContext *cnmt_ctx, NcaContext *nca_
goto end;
}
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " %s\n" \
- " %s\n" \
- " %lu\n" \
- " %s\n" \
- " %u\n" \
- " %u\n" \
- " \n", \
- titleGetNcmContentTypeName(cur_nca_ctx->content_type), \
- cur_nca_ctx->content_id_str, \
- cur_nca_ctx->content_size, \
- cur_nca_ctx->hash_str, \
- cur_nca_ctx->key_generation, \
- cur_nca_ctx->id_offset)) goto end;
+ if (!CNMT_ADD_FMT_STR(" \n" \
+ " %s\n" \
+ " %s\n" \
+ " %lu\n" \
+ " %s\n" \
+ " %u\n" \
+ " %u\n" \
+ " \n", \
+ titleGetNcmContentTypeName(cur_nca_ctx->content_type), \
+ cur_nca_ctx->content_id_str, \
+ cur_nca_ctx->content_size, \
+ cur_nca_ctx->hash_str, \
+ cur_nca_ctx->key_generation, \
+ cur_nca_ctx->id_offset)) goto end;
}
utilsGenerateHexStringFromData(digest_str, sizeof(digest_str), cnmt_ctx->digest, CNMT_DIGEST_SIZE, false);
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " %s\n" \
- " %u\n" \
- " \n" \
- " \n", \
- digest_str, \
- cnmt_ctx->nca_ctx->key_generation)) goto end;
+ /* ContentMeta, Digest, KeyGenerationMin, KeepGeneration and KeepGenerationSpecified. */
+ if (!CNMT_ADD_FMT_STR(" \n" \
+ " %s\n" \
+ " %u\n" \
+ " \n" \
+ " \n", \
+ digest_str, \
+ cnmt_ctx->nca_ctx->key_generation)) goto end;
+ /* RequiredSystemVersion (Application, Patch) / RequiredApplicationVersion (AddOnContent). */
+ /* PatchId (Application) / ApplicationId (Patch, AddOnContent). */
if (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)
{
@@ -454,21 +460,20 @@ bool cnmtGenerateAuthoringToolXml(ContentMetaContext *cnmt_ctx, NcaContext *nca_
u64 required_title_id = cnmtGetRequiredTitleId(cnmt_ctx);
const char *required_title_type_str = cnmtGetRequiredTitleTypeString(cnmt_ctx->packaged_header->content_meta_type);
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " <%s>%u%s>\n" \
- " <%s>0x%016lx%s>\n", \
- required_title_version_str, required_title_version, required_title_version_str, \
- required_title_type_str, required_title_id, required_title_type_str)) goto end;
+ if (!CNMT_ADD_FMT_STR(" <%s>%u%s>\n" \
+ " <%s>0x%016lx%s>\n", \
+ required_title_version_str, required_title_version, required_title_version_str, \
+ required_title_type_str, required_title_id, required_title_type_str)) goto end;
}
+ /* RequiredApplicationVersion (Application). */
if (cnmt_ctx->packaged_header->content_meta_type == NcmContentMetaType_Application)
{
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " %u\n", \
- ((ContentMetaApplicationMetaExtendedHeader*)cnmt_ctx->extended_header)->required_application_version.value)) goto end;
+ if (!CNMT_ADD_FMT_STR(" %u\n", \
+ ((ContentMetaApplicationMetaExtendedHeader*)cnmt_ctx->extended_header)->required_application_version.value)) goto end;
}
- if (!(success = utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, ""))) goto end;
+ if (!(success = CNMT_ADD_FMT_STR(""))) goto end;
/* Update CNMT context. */
cnmt_ctx->authoring_tool_xml = xml_buf;
diff --git a/source/core/nacp.c b/source/core/nacp.c
index 534dc0c..49df3b1 100644
--- a/source/core/nacp.c
+++ b/source/core/nacp.c
@@ -23,6 +23,23 @@
#include "nacp.h"
#include "title.h"
+/* Helper macros. */
+
+#define NACP_ADD_FMT_STR_T1(fmt, ...) utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, fmt, ##__VA_ARGS__)
+#define NACP_ADD_FMT_STR_T2(fmt, ...) utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, fmt, ##__VA_ARGS__)
+#define NACP_ADD_STR(tag_name, value) nacpAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, tag_name, value)
+#define NACP_ADD_ENUM(tag_name, value, str_func) nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, tag_name, value, \
+ &str_func)
+#define NACP_ADD_BITFLAG(tag_name, flag, flag_width, max_flag_idx, str_func, allow_empty_str) nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, tag_name, flag, \
+ flag_width, max_flag_idx, &(str_func), \
+ allow_empty_str)
+#define NACP_ADD_U16(tag_name, value, hex, prefix) nacpAddU16FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, tag_name, value, hex, \
+ prefix)
+#define NACP_ADD_U32(tag_name, value, hex, prefix) nacpAddU32FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, tag_name, value, hex, \
+ prefix)
+#define NACP_ADD_U64(tag_name, value, hex, prefix) nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, tag_name, value, hex, \
+ prefix)
+
/* Type definitions. */
typedef const char *(*NacpStringFunction)(u8 value); /* Used while adding fields to the AuthoringTool-like XML. */
@@ -68,7 +85,8 @@ static const char *g_nacpAddOnContentRegistrationTypeStrings[NacpAddOnContentReg
static const char *g_nacpAttributeStrings[NacpAttribute_Count] = {
"Demo",
- "RetailInteractiveDisplay"
+ "RetailInteractiveDisplay",
+ "DownloadPlay"
};
static const char *g_nacpParentalControlStrings[NacpParentalControl_Count] = {
@@ -137,6 +155,13 @@ static const char *g_nacpRuntimeParameterDeliveryStrings[NacpRuntimeParameterDel
"OnRestart"
};
+static const char *g_nacpAppropriateAgeForChinaStrings[NacpAppropriateAgeForChina_Count] = {
+ "None",
+ "Age8",
+ "Age12",
+ "Age16"
+};
+
static const char *g_nacpUndecidedParameter75b8bStrings[NacpUndecidedParameter75b8b_Count] = {
"a",
"b"
@@ -156,6 +181,11 @@ static const char *g_nacpStartupUserAccountOptionStrings[NacpStartupUserAccountO
"IsOptional"
};
+static const char *g_nacpRuntimeUpgradeStrings[NacpRuntimeUpgrade_Count] = {
+ "Deny",
+ "Allow"
+};
+
static const char *g_nacpPlayLogQueryCapabilityStrings[NacpPlayLogQueryCapability_Count] = {
"None",
"WhiteList",
@@ -170,16 +200,6 @@ static const char *g_nacpRequiredNetworkServiceLicenseOnLaunchStrings[NacpRequir
"Common"
};
-static const char *g_nacpJitConfigurationFlagStrings[NacpJitConfigurationFlag_Count] = {
- "false",
- "true"
-};
-
-static const char *g_nacpPlayReportPermissionStrings[NacpPlayReportPermission_Count] = {
- "Deny",
- "Allow"
-};
-
static const char *g_nacpCrashScreenshotForProdStrings[NacpCrashScreenshotForProd_Count] = {
"Deny",
"Allow"
@@ -190,13 +210,19 @@ static const char *g_nacpCrashScreenshotForDevStrings[NacpCrashScreenshotForDev_
"Allow"
};
+static const char *g_nacpContentsAvailabilityTransitionPolicyStrings[NacpContentsAvailabilityTransitionPolicy_Count] = {
+ "NoPolicy",
+ "Stable",
+ "Changeable"
+};
+
/* Function prototypes. */
NX_INLINE bool nacpCheckBitflagField(const void *flag, u8 flag_bitcount, u8 idx);
static bool nacpAddStringFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, const char *value);
static bool nacpAddEnumFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u8 value, NacpStringFunction str_func);
-static bool nacpAddBitflagFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, const void *flag, u8 flag_width, u8 max_flag_idx, NacpStringFunction str_func);
+static bool nacpAddBitflagFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, const void *flag, u8 flag_width, u8 max_flag_idx, NacpStringFunction str_func, bool allow_empty_str);
static bool nacpAddU16FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u16 value, bool hex, bool prefix);
static bool nacpAddU32FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u32 value, bool hex, bool prefix);
static bool nacpAddU64FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u64 value, bool hex, bool prefix);
@@ -424,6 +450,8 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
_NacpStruct *nacp = nacp_ctx->data;
+ Version app_ver = { .value = version };
+
u8 i = 0, count = 0;
char *xml_buf = NULL;
u64 xml_buf_size = 0;
@@ -437,6 +465,9 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
NacpNeighborDetectionClientConfiguration *ndcc = &(nacp->neighbor_detection_client_configuration);
NacpRequiredAddOnContentsSetBinaryDescriptor *raocsbd = &(nacp->required_add_on_contents_set_binary_descriptor);
+ bool raocsbd_available = false;
+
+ bool alrv_available = false;
bool success = false;
@@ -445,9 +476,8 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
nacp_ctx->authoring_tool_xml = NULL;
nacp_ctx->authoring_tool_xml_size = 0;
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- "\n" \
- "\n")) goto end;
+ if (!NACP_ADD_FMT_STR_T1("\n" \
+ "\n")) goto end;
/* Title. */
for(i = 0, count = 0; i < NacpLanguage_Count; i++)
@@ -455,56 +485,53 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
NacpTitle *title = &(nacp->title[i]);
if (!*(title->name) || !*(title->publisher)) continue;
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " %s\n" \
- " %s\n" \
- " %s\n" \
- " \n", \
- nacpGetLanguageString(i), \
- title->name, \
- title->publisher)) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " %s\n" \
+ " %s\n" \
+ " %s\n" \
+ " \n", \
+ nacpGetLanguageString(i), \
+ title->name, \
+ title->publisher)) goto end;
count++;
}
- if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ if (!count && !NACP_ADD_FMT_STR_T1(" \n")) goto end;
/* Isbn. */
- if (!nacpAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Isbn", nacp->isbn)) goto end;
+ if (!NACP_ADD_STR("Isbn", nacp->isbn)) goto end;
/* StartupUserAccount. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "StartupUserAccount", nacp->startup_user_account, &nacpGetStartupUserAccountString)) goto end;
+ if (!NACP_ADD_ENUM("StartupUserAccount", nacp->startup_user_account, nacpGetStartupUserAccountString)) goto end;
/* StartupUserAccountOption. */
- if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "StartupUserAccountOption", &(nacp->startup_user_account_option), sizeof(nacp->startup_user_account_option), \
- NacpStartupUserAccountOption_Count, &nacpGetStartupUserAccountOptionString)) goto end;
+ if (!NACP_ADD_BITFLAG("StartupUserAccountOption", &(nacp->startup_user_account_option), sizeof(nacp->startup_user_account_option), NacpStartupUserAccountOption_Count, \
+ nacpGetStartupUserAccountOptionString, true)) goto end;
/* UserAccountSwitchLock. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSwitchLock", nacp->user_account_switch_lock, &nacpGetUserAccountSwitchLockString)) goto end;
+ if (!NACP_ADD_ENUM("UserAccountSwitchLock", nacp->user_account_switch_lock, nacpGetUserAccountSwitchLockString)) goto end;
/* Attribute. */
- if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Attribute", &(nacp->attribute), sizeof(nacp->attribute), NacpAttribute_Count, &nacpGetAttributeString)) goto end;
+ if (!NACP_ADD_BITFLAG("Attribute", &(nacp->attribute), sizeof(nacp->attribute), NacpAttribute_Count, nacpGetAttributeString, false)) goto end;
/* ParentalControl. */
- if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ParentalControl", &(nacp->parental_control), sizeof(nacp->parental_control), NacpParentalControl_Count, \
- &nacpGetParentalControlString)) goto end;
+ if (!NACP_ADD_BITFLAG("ParentalControl", &(nacp->parental_control), sizeof(nacp->parental_control), NacpParentalControl_Count, nacpGetParentalControlString, false)) goto end;
/* SupportedLanguage. */
- if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SupportedLanguage", &(nacp->supported_language), sizeof(nacp->supported_language), NacpSupportedLanguage_Count, \
- &nacpGetLanguageString)) goto end;
+ if (!NACP_ADD_BITFLAG("SupportedLanguage", &(nacp->supported_language), sizeof(nacp->supported_language), NacpSupportedLanguage_Count, nacpGetLanguageString, false)) goto end;
/* Screenshot. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Screenshot", nacp->screenshot, &nacpGetScreenshotString)) goto end;
+ if (!NACP_ADD_ENUM("Screenshot", nacp->screenshot, nacpGetScreenshotString)) goto end;
/* VideoCapture. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "VideoCapture", nacp->video_capture, &nacpGetVideoCaptureString)) goto end;
+ if (!NACP_ADD_ENUM("VideoCapture", nacp->video_capture, nacpGetVideoCaptureString)) goto end;
/* PresenceGroupId. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "PresenceGroupId", nacp->presence_group_id, true, true)) goto end;
+ if (!NACP_ADD_U64("PresenceGroupId", nacp->presence_group_id, true, true)) goto end;
/* DisplayVersion. */
- if (!nacpAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DisplayVersion", nacp->display_version)) goto end;
+ if (!NACP_ADD_STR("DisplayVersion", nacp->display_version)) goto end;
/* Rating. */
for(i = 0, count = 0; i < NacpRatingAgeOrganization_Count; i++)
@@ -512,78 +539,75 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
s8 age = *(((s8*)&(nacp->rating_age)) + i);
if (age < 0) continue;
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " %s\n" \
- " %d\n" \
- " \n", \
- nacpGetRatingAgeOrganizationString(i), \
- age)) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " %s\n" \
+ " %d\n" \
+ " \n", \
+ nacpGetRatingAgeOrganizationString(i), \
+ age)) goto end;
count++;
}
- if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ if (!count && !NACP_ADD_FMT_STR_T1(" \n")) goto end;
/* DataLossConfirmation. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DataLossConfirmation", nacp->data_loss_confirmation, &nacpGetDataLossConfirmationString)) goto end;
+ if (!NACP_ADD_ENUM("DataLossConfirmation", nacp->data_loss_confirmation, nacpGetDataLossConfirmationString)) goto end;
/* PlayLogPolicy. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "PlayLogPolicy", nacp->play_log_policy, &nacpGetPlayLogPolicyString)) goto end;
+ if (!NACP_ADD_ENUM("PlayLogPolicy", nacp->play_log_policy, nacpGetPlayLogPolicyString)) goto end;
/* SaveDataOwnerId. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SaveDataOwnerId", nacp->save_data_owner_id, true, true)) goto end;
+ if (!NACP_ADD_U64("SaveDataOwnerId", nacp->save_data_owner_id, true, true)) goto end;
/* UserAccountSaveDataSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataSize", (u64)nacp->user_account_save_data_size, true, true)) goto end;
+ if (!NACP_ADD_U64("UserAccountSaveDataSize", (u64)nacp->user_account_save_data_size, true, true)) goto end;
/* UserAccountSaveDataJournalSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataJournalSize", (u64)nacp->user_account_save_data_journal_size, true, true)) goto end;
+ if (!NACP_ADD_U64("UserAccountSaveDataJournalSize", (u64)nacp->user_account_save_data_journal_size, true, true)) goto end;
/* UserAccountSaveDataTotalSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataTotalSize", (u64)(nacp->user_account_save_data_size + nacp->user_account_save_data_journal_size), true, true)) goto end;
+ if (!NACP_ADD_U64("UserAccountSaveDataTotalSize", (u64)(nacp->user_account_save_data_size + nacp->user_account_save_data_journal_size), true, true)) goto end;
/* DeviceSaveDataSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataSize", (u64)nacp->device_save_data_size, true, true)) goto end;
+ if (!NACP_ADD_U64("DeviceSaveDataSize", (u64)nacp->device_save_data_size, true, true)) goto end;
/* DeviceSaveDataJournalSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataJournalSize", (u64)nacp->device_save_data_journal_size, true, true)) goto end;
+ if (!NACP_ADD_U64("DeviceSaveDataJournalSize", (u64)nacp->device_save_data_journal_size, true, true)) goto end;
/* BcatDeliveryCacheStorageSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "BcatDeliveryCacheStorageSize", (u64)nacp->bcat_delivery_cache_storage_size, true, true)) goto end;
+ if (!NACP_ADD_U64("BcatDeliveryCacheStorageSize", (u64)nacp->bcat_delivery_cache_storage_size, true, true)) goto end;
/* ApplicationErrorCodeCategory. */
- if (!nacpAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ApplicationErrorCodeCategory", nacp->application_error_code_category)) goto end;
+ if (!NACP_ADD_STR("ApplicationErrorCodeCategory", nacp->application_error_code_category)) goto end;
/* AddOnContentBaseId. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "AddOnContentBaseId", nacp->add_on_content_base_id, true, true)) goto end;
+ if (!NACP_ADD_U64("AddOnContentBaseId", nacp->add_on_content_base_id, true, true)) goto end;
/* Version. */
- if (!nacpAddU32FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Version", version, false, false)) goto end;
+ if (!NACP_ADD_U32("Version", version, false, false)) goto end;
- /* ReleaseVersion and PrivateVersion. Unused but kept anyway. */
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " \n")) goto end;
+ /* ReleaseVersion. */
+ if (!NACP_ADD_U32("ReleaseVersion", app_ver.application_version.release_ver, false, false)) goto end;
+
+ /* PrivateVersion. */
+ if (!NACP_ADD_U32("PrivateVersion", app_ver.application_version.private_ver, false, false)) goto end;
/* LogoType. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "LogoType", nacp->logo_type, &nacpGetLogoTypeString)) goto end;
+ if (!NACP_ADD_ENUM("LogoType", nacp->logo_type, nacpGetLogoTypeString)) goto end;
/* RequiredSystemVersion. */
- if (!nacpAddU32FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RequiredSystemVersion", required_system_version, false, false)) goto end;
+ if (!NACP_ADD_U32("RequiredSystemVersion", required_system_version, false, false)) goto end;
/* LocalCommunicationId. */
- for(i = 0, count = 0; i < 0x8; i++)
+ for(i = 0; i < 0x8; i++)
{
if (!nacp->local_communication_id[i]) continue;
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "LocalCommunicationId", nacp->local_communication_id[i], true, true)) goto end;
- count++;
+ if (!NACP_ADD_U64("LocalCommunicationId", nacp->local_communication_id[i], true, true)) goto end;
}
- if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
-
/* LogoHandling. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "LogoHandling", nacp->logo_handling, &nacpGetLogoHandlingString)) goto end;
+ if (!NACP_ADD_ENUM("LogoHandling", nacp->logo_handling, nacpGetLogoHandlingString)) goto end;
/* Icon. */
for(i = 0, count = 0; i < nacp_ctx->icon_count; i++)
@@ -597,101 +621,96 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
utilsGenerateHexStringFromData(icon_hash_str, sizeof(icon_hash_str), icon_hash, sizeof(icon_hash) / 2, false);
/* Add XML element. */
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " %s\n" \
- " \n" \
- " \n" \
- " \n" \
- " %s\n" \
- " \n", \
- nacpGetLanguageString(icon_ctx->language), \
- icon_hash_str)) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " %s\n" \
+ /*" \n" \
+ " \n" \
+ " \n" \*/
+ " %s\n" \
+ " \n", \
+ nacpGetLanguageString(icon_ctx->language), \
+ icon_hash_str)) goto end;
count++;
}
- if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ if (!count && !NACP_ADD_FMT_STR_T1(" \n")) goto end;
/* HtmlDocumentPath, LegalInformationFilePath and AccessibleUrlsFilePath. Unused but kept anyway. */
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " \n" \
- " \n")) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " \n" \
+ " \n")) goto end;
/* SeedForPseudoDeviceId. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SeedForPseudoDeviceId", nacp->seed_for_pseudo_device_id, true, false)) goto end;
+ if (!NACP_ADD_U64("SeedForPseudoDeviceId", nacp->seed_for_pseudo_device_id, true, false)) goto end;
/* BcatPassphrase. */
- if (!nacpAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "BcatPassphrase", nacp->bcat_passphrase)) goto end;
+ if (!NACP_ADD_STR("BcatPassphrase", nacp->bcat_passphrase)) goto end;
/* AddOnContentRegistrationType. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "AddOnContentRegistrationType", nacp->add_on_content_registration_type, &nacpGetAddOnContentRegistrationTypeString)) goto end;
+ if (!NACP_ADD_ENUM("AddOnContentRegistrationType", nacp->add_on_content_registration_type, nacpGetAddOnContentRegistrationTypeString)) goto end;
/* UserAccountSaveDataSizeMax. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataSizeMax", (u64)nacp->user_account_save_data_size_max, true, true)) goto end;
+ if (!NACP_ADD_U64("UserAccountSaveDataSizeMax", (u64)nacp->user_account_save_data_size_max, true, true)) goto end;
/* UserAccountSaveDataJournalSizeMax. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataJournalSizeMax", (u64)nacp->user_account_save_data_journal_size_max, true, true)) goto end;
+ if (!NACP_ADD_U64("UserAccountSaveDataJournalSizeMax", (u64)nacp->user_account_save_data_journal_size_max, true, true)) goto end;
/* DeviceSaveDataSizeMax. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataSizeMax", (u64)nacp->device_save_data_size_max, true, true)) goto end;
+ if (!NACP_ADD_U64("DeviceSaveDataSizeMax", (u64)nacp->device_save_data_size_max, true, true)) goto end;
/* DeviceSaveDataJournalSizeMax. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataJournalSizeMax", (u64)nacp->device_save_data_journal_size_max, true, true)) goto end;
+ if (!NACP_ADD_U64("DeviceSaveDataJournalSizeMax", (u64)nacp->device_save_data_journal_size_max, true, true)) goto end;
/* TemporaryStorageSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "TemporaryStorageSize", (u64)nacp->temporary_storage_size, true, true)) goto end;
+ if (!NACP_ADD_U64("TemporaryStorageSize", (u64)nacp->temporary_storage_size, true, true)) goto end;
/* CacheStorageSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageSize", (u64)nacp->cache_storage_size, true, true)) goto end;
+ if (!NACP_ADD_U64("CacheStorageSize", (u64)nacp->cache_storage_size, true, true)) goto end;
/* CacheStorageJournalSize. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageJournalSize", (u64)nacp->cache_storage_journal_size, true, true)) goto end;
+ if (!NACP_ADD_U64("CacheStorageJournalSize", (u64)nacp->cache_storage_journal_size, true, true)) goto end;
/* CacheStorageDataAndJournalSizeMax. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageDataAndJournalSizeMax", (u64)nacp->cache_storage_data_and_journal_size_max, true, true)) goto end;
+ if (!NACP_ADD_U64("CacheStorageDataAndJournalSizeMax", (u64)nacp->cache_storage_data_and_journal_size_max, true, true)) goto end;
/* CacheStorageIndexMax. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageIndexMax", (u64)nacp->cache_storage_index_max, true, true)) goto end;
+ if (!NACP_ADD_U64("CacheStorageIndexMax", (u64)nacp->cache_storage_index_max, true, true)) goto end;
/* Hdcp. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Hdcp", nacp->hdcp, &nacpGetHdcpString)) goto end;
+ if (!NACP_ADD_ENUM("Hdcp", nacp->hdcp, nacpGetHdcpString)) goto end;
/* CrashReport. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CrashReport", nacp->crash_report, &nacpGetCrashReportString)) goto end;
+ if (!NACP_ADD_ENUM("CrashReport", nacp->crash_report, nacpGetCrashReportString)) goto end;
/* CrashScreenshotForProd. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CrashScreenshotForProd", nacp->crash_screenshot_for_prod, &nacpGetCrashScreenshotForProdString)) goto end;
+ if (!NACP_ADD_ENUM("CrashScreenshotForProd", nacp->crash_screenshot_for_prod, nacpGetCrashScreenshotForProdString)) goto end;
/* CrashScreenshotForDev. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CrashScreenshotForDev", nacp->crash_screenshot_for_dev, &nacpGetCrashScreenshotForDevString)) goto end;
+ if (!NACP_ADD_ENUM("CrashScreenshotForDev", nacp->crash_screenshot_for_dev, nacpGetCrashScreenshotForDevString)) goto end;
/* RuntimeAddOnContentInstall. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RuntimeAddOnContentInstall", nacp->runtime_add_on_content_install, &nacpGetRuntimeAddOnContentInstallString)) goto end;
+ if (!NACP_ADD_ENUM("RuntimeAddOnContentInstall", nacp->runtime_add_on_content_install, nacpGetRuntimeAddOnContentInstallString)) goto end;
/* PlayLogQueryableApplicationId. */
- for(i = 0, count = 0; i < 0x10; i++)
+ for(i = 0; i < 0x10; i++)
{
if (!nacp->play_log_queryable_application_id[i]) continue;
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "PlayLogQueryableApplicationId", nacp->play_log_queryable_application_id[i], true, true)) goto end;
- count++;
+ if (!NACP_ADD_U64("PlayLogQueryableApplicationId", nacp->play_log_queryable_application_id[i], true, true)) goto end;
}
- if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
-
/* PlayLogQueryCapability. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "PlayLogQueryCapability", nacp->play_log_query_capability, &nacpGetPlayLogQueryCapabilityString)) goto end;
+ if (!NACP_ADD_ENUM("PlayLogQueryCapability", nacp->play_log_query_capability, nacpGetPlayLogQueryCapabilityString)) goto end;
/* Repair. */
- if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Repair", &(nacp->repair), sizeof(nacp->repair), NacpRepair_Count, &nacpGetRepairString)) goto end;
+ if (!NACP_ADD_BITFLAG("Repair", &(nacp->repair), sizeof(nacp->repair), NacpRepair_Count, nacpGetRepairString, false)) goto end;
/* ProgramIndex. */
- if (!nacpAddU16FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ProgramIndex", nacp->program_index, false, false)) goto end;
+ if (!NACP_ADD_U16("ProgramIndex", nacp->program_index, false, false)) goto end;
/* RequiredNetworkServiceLicenseOnLaunch. */
- 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;
+ if (!NACP_ADD_BITFLAG("RequiredNetworkServiceLicenseOnLaunch", &(nacp->required_network_service_license_on_launch), sizeof(nacp->required_network_service_license_on_launch), \
+ NacpRequiredNetworkServiceLicenseOnLaunch_Count, nacpGetRequiredNetworkServiceLicenseOnLaunchString, false)) goto end;
/* NeighborDetectionClientConfiguration. */
ndcc_sgc_available = (ndcc->send_group_configuration.group_id && memcmp(ndcc->send_group_configuration.key, null_key, sizeof(null_key)));
@@ -704,18 +723,17 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
if (ndcc_sgc_available || ndcc_rgc_available)
{
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n")) goto end;
/* SendGroupConfiguration. */
utilsGenerateHexStringFromData(key_str, sizeof(key_str), ndcc->send_group_configuration.key, sizeof(ndcc->send_group_configuration.key), false);
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " 0x%016lx\n" \
- " %s\n" \
- " \n", \
- ndcc->send_group_configuration.group_id, \
- key_str)) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " 0x%016lx\n" \
+ " %s\n" \
+ " \n", \
+ ndcc->send_group_configuration.group_id, \
+ key_str)) goto end;
/* ReceivableGroupConfiguration. */
for(i = 0; i < 0x10; i++)
@@ -724,85 +742,122 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
utilsGenerateHexStringFromData(key_str, sizeof(key_str), rgc->key, sizeof(rgc->key), false);
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " 0x%016lx\n" \
- " %s\n" \
- " \n", \
- rgc->group_id, \
- key_str)) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " 0x%016lx\n" \
+ " %s\n" \
+ " \n", \
+ rgc->group_id, \
+ key_str)) goto end;
}
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
- } else {
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n")) goto end;
}
/* JitConfiguration. */
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " %s\n" \
- " %lu\n" \
- " \n", \
- nacpGetJitConfigurationFlagString(nacp->jit_configuration.jit_configuration_flag), \
- nacp->jit_configuration.memory_size)) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " %s\n" \
+ " %lu\n" \
+ " \n", \
+ (nacp->jit_configuration.jit_configuration_flag & NacpJitConfigurationFlag_Enabled) ? "true" : "false", \
+ nacp->jit_configuration.memory_size)) goto end;
- /* History. Unused but kept anyway. */
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ /* History. */
+ //if (!NACP_ADD_FMT_STR_T1(" \n")) goto end;
/* RuntimeParameterDelivery. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RuntimeParameterDelivery", nacp->runtime_parameter_delivery, &nacpGetRuntimeParameterDeliveryString)) goto end;
+ if (!NACP_ADD_ENUM("RuntimeParameterDelivery", nacp->runtime_parameter_delivery, nacpGetRuntimeParameterDeliveryString)) goto end;
+
+ /* AppropriateAgeForChina. */
+ if (!NACP_ADD_ENUM("AppropriateAgeForChina", nacp->appropriate_age_for_china, nacpGetAppropriateAgeForChina)) goto end;
/* RequiredAddOnContentsSet. */
- for(i = 0, count = 0; i < 0x20; i++)
+ for(i = 0; i < 0x20; i++)
{
- NacpDescriptors *descriptor = &(raocsbd->descriptors[i]);
- if (!descriptor->index || !descriptor->continue_set) continue;
+ NacpRequiredAddOnContentsSetDescriptor *descriptor = &(raocsbd->descriptors[i]);
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " %u\n" \
- " \n", \
- descriptor->index)) goto end;
+ if (descriptor->index)
+ {
+ raocsbd_available = true;
+ break;
+ }
- count++;
+ if (descriptor->flag != NacpRequiredAddOnContentsSetDescriptorFlag_Continue) break;
}
- if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ if (raocsbd_available)
+ {
+ if (!NACP_ADD_FMT_STR_T1(" \n")) goto end;
+
+ for(i = 0; i < 0x20; i++)
+ {
+ NacpRequiredAddOnContentsSetDescriptor *descriptor = &(raocsbd->descriptors[i]);
+ if (!descriptor->index) continue;
+
+ if (!NACP_ADD_FMT_STR_T1(" %u\n", descriptor->index)) goto end;
+
+ if (descriptor->flag != NacpRequiredAddOnContentsSetDescriptorFlag_Continue) break;
+ }
+
+ if (!NACP_ADD_FMT_STR_T1(" \n")) goto end;
+ }
/* PlayReportPermission. */
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " %s\n" \
- " \n", \
- nacpGetPlayReportPermissionString(nacp->play_report_permission))) goto end;
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " %s\n" \
+ " \n", \
+ (nacp->play_report_permission & NacpPlayReportPermission_TargetMarketing) ? "Allow" : "Deny")) goto end;
/* AccessibleLaunchRequiredVersion. */
- for(i = 0, count = 0; i < 0x8; i++)
+ for(i = 0; i < 0x8; i++)
{
- if (!nacp->accessible_launch_required_version.application_id[i]) continue;
-
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" \
- " 0x%016lx\n" \
- " \n", \
- nacp->accessible_launch_required_version.application_id[i])) goto end;
-
- count++;
+ if (nacp->accessible_launch_required_version.application_id[i])
+ {
+ alrv_available = true;
+ break;
+ }
}
- if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ if (alrv_available)
+ {
+ if (!NACP_ADD_FMT_STR_T1(" \n")) goto end;
+
+ for(i = 0; i < 0x8; i++)
+ {
+ u64 id = nacp->accessible_launch_required_version.application_id[i];
+ if (!id) continue;
+
+ if (!NACP_ADD_FMT_STR_T1(" 0x%016lx\n", id)) goto end;
+ }
+
+ if (!NACP_ADD_FMT_STR_T1(" \n")) goto end;
+ } else {
+ if (!NACP_ADD_FMT_STR_T1(" \n")) goto end;
+ }
/* UndecidedParameter75b8b. */
- if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UndecidedParameter75b8b", nacp->undecided_parameter_75b8b, &nacpGetUndecidedParameter75b8bString)) goto end;
+ if (!NACP_ADD_ENUM("UndecidedParameter75b8b", nacp->undecided_parameter_75b8b, nacpGetUndecidedParameter75b8bString)) goto end;
/* ApplicationId. */
- if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ApplicationId", nacp_ctx->nca_ctx->header.program_id, true, true)) goto end;
+ if (!NACP_ADD_U64("ApplicationId", nacp_ctx->nca_ctx->header.program_id, true, true)) goto end;
- /* FilterDescriptionFilePath. Unused but kept anyway. */
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " \n")) goto end;
+ /* FilterDescriptionFilePath and CompressionFileConfigurationFilePath. */
+ /*if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " \n")) goto end;*/
- if (!(success = utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, ""))) goto end;
+ /* ContentsAvailabilityTransitionPolicy. */
+ if (!NACP_ADD_ENUM("ContentsAvailabilityTransitionPolicy", nacp->contents_availability_transition_policy, nacpGetContentsAvailabilityTransitionPolicyString)) goto end;
+
+ /* LimitedLicenseSettings. */
+ if (!NACP_ADD_FMT_STR_T1(" \n" \
+ " %s\n" \
+ " \n" \
+ " %s\n" \
+ " \n" \
+ " \n", \
+ nacpGetRuntimeUpgradeString(nacp->runtime_upgrade), \
+ (nacp->supporting_limited_licenses & NacpSupportingLimitedLicenses_Demo) ? "Demo" : "None")) goto end;
+
+ if (!(success = NACP_ADD_FMT_STR_T1(""))) goto end;
/* Update NACP context. */
nacp_ctx->authoring_tool_xml = xml_buf;
@@ -893,6 +948,11 @@ const char *nacpGetRuntimeParameterDeliveryString(u8 runtime_parameter_delivery)
return (runtime_parameter_delivery < NacpRuntimeParameterDelivery_Count ? g_nacpRuntimeParameterDeliveryStrings[runtime_parameter_delivery] : g_unknownString);
}
+const char *nacpGetAppropriateAgeForChina(u8 appropriate_age_for_china)
+{
+ return (appropriate_age_for_china < NacpAppropriateAgeForChina_Count ? g_nacpAppropriateAgeForChinaStrings[appropriate_age_for_china] : g_unknownString);
+}
+
const char *nacpGetUndecidedParameter75b8bString(u8 undecided_parameter_75b8b)
{
return (undecided_parameter_75b8b < NacpUndecidedParameter75b8b_Count ? g_nacpUndecidedParameter75b8bStrings[undecided_parameter_75b8b] : g_unknownString);
@@ -913,6 +973,11 @@ const char *nacpGetStartupUserAccountOptionString(u8 startup_user_account_option
return (startup_user_account_option < NacpStartupUserAccountOption_Count ? g_nacpStartupUserAccountOptionStrings[startup_user_account_option] : g_unknownString);
}
+const char *nacpGetRuntimeUpgradeString(u8 runtime_upgrade)
+{
+ return (runtime_upgrade < NacpRuntimeUpgrade_Count ? g_nacpRuntimeUpgradeStrings[runtime_upgrade] : g_unknownString);
+}
+
const char *nacpGetPlayLogQueryCapabilityString(u8 play_log_query_capability)
{
return (play_log_query_capability < NacpPlayLogQueryCapability_Count ? g_nacpPlayLogQueryCapabilityStrings[play_log_query_capability] : g_unknownString);
@@ -929,16 +994,6 @@ const char *nacpGetRequiredNetworkServiceLicenseOnLaunchString(u8 required_netwo
g_nacpRequiredNetworkServiceLicenseOnLaunchStrings[required_network_service_license_on_launch] : g_unknownString);
}
-const char *nacpGetJitConfigurationFlagString(u64 jig_configuration_flag)
-{
- return (jig_configuration_flag < NacpJitConfigurationFlag_Count ? g_nacpJitConfigurationFlagStrings[jig_configuration_flag] : g_unknownString);
-}
-
-const char *nacpGetPlayReportPermissionString(u8 play_report_permission)
-{
- return (play_report_permission < NacpPlayReportPermission_Count ? g_nacpPlayReportPermissionStrings[play_report_permission] : g_unknownString);
-}
-
const char *nacpGetCrashScreenshotForProdString(u8 crash_screenshot_for_prod)
{
return (crash_screenshot_for_prod < NacpCrashScreenshotForProd_Count ? g_nacpCrashScreenshotForProdStrings[crash_screenshot_for_prod] : g_unknownString);
@@ -949,6 +1004,12 @@ const char *nacpGetCrashScreenshotForDevString(u8 crash_screenshot_for_dev)
return (crash_screenshot_for_dev < NacpCrashScreenshotForDev_Count ? g_nacpCrashScreenshotForDevStrings[crash_screenshot_for_dev] : g_unknownString);
}
+const char *nacpGetContentsAvailabilityTransitionPolicyString(u8 contents_availability_transition_policy)
+{
+ return (contents_availability_transition_policy < NacpContentsAvailabilityTransitionPolicy_Count ? \
+ g_nacpContentsAvailabilityTransitionPolicyStrings[contents_availability_transition_policy] : g_unknownString);
+}
+
NX_INLINE bool nacpCheckBitflagField(const void *flag, u8 flag_bitcount, u8 idx)
{
if (!flag || !flag_bitcount || !IS_POWER_OF_TWO(flag_bitcount) || idx >= flag_bitcount) return false;
@@ -966,8 +1027,7 @@ static bool nacpAddStringFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_si
return false;
}
- return (*value ? utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>%s%s>\n", tag_name, value, tag_name) : \
- utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s />\n", tag_name));
+ return (*value ? NACP_ADD_FMT_STR_T2(" <%s>%s%s>\n", tag_name, value, tag_name) : NACP_ADD_FMT_STR_T2(" <%s />\n", tag_name));
}
static bool nacpAddEnumFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u8 value, NacpStringFunction str_func)
@@ -978,10 +1038,10 @@ static bool nacpAddEnumFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size
return false;
}
- return utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>%s%s>\n", tag_name, str_func(value), tag_name);
+ return NACP_ADD_FMT_STR_T2(" <%s>%s%s>\n", tag_name, str_func(value), tag_name);
}
-static bool nacpAddBitflagFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, const void *flag, u8 flag_width, u8 max_flag_idx, NacpStringFunction str_func)
+static bool nacpAddBitflagFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, const void *flag, u8 flag_width, u8 max_flag_idx, NacpStringFunction str_func, bool allow_empty_str)
{
u8 flag_bitcount = 0, i = 0, count = 0;
const u8 *flag_u8 = (const u8*)flag;
@@ -1008,7 +1068,7 @@ static bool nacpAddBitflagFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_s
for(i = 0; i < max_flag_idx; i++)
{
if (!nacpCheckBitflagField(flag, flag_bitcount, i)) continue;
- if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>%s%s>\n", tag_name, str_func(i), tag_name)) goto end;
+ if (!NACP_ADD_FMT_STR_T2(" <%s>%s%s>\n", tag_name, str_func(i), tag_name)) goto end;
count++;
}
@@ -1016,7 +1076,7 @@ static bool nacpAddBitflagFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_s
if (!count) empty_flag = true;
}
- if (empty_flag && !utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s />\n", tag_name)) goto end;
+ if (empty_flag && allow_empty_str && !NACP_ADD_FMT_STR_T2(" <%s />\n", tag_name)) goto end;
success = true;
@@ -1034,7 +1094,7 @@ static bool nacpAddU16FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size,
const char *str = (hex ? (prefix ? " <%s>0x%04x%s>\n" : " <%s>%04x%s>\n") : " <%s>%u%s>\n");
- return utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, str, tag_name, value, tag_name);
+ return NACP_ADD_FMT_STR_T2(str, tag_name, value, tag_name);
}
static bool nacpAddU32FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u32 value, bool hex, bool prefix)
@@ -1047,7 +1107,7 @@ static bool nacpAddU32FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size,
const char *str = (hex ? (prefix ? " <%s>0x%08x%s>\n" : " <%s>%08x%s>\n") : " <%s>%u%s>\n");
- return utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, str, tag_name, value, tag_name);
+ return NACP_ADD_FMT_STR_T2(str, tag_name, value, tag_name);
}
static bool nacpAddU64FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u64 value, bool hex, bool prefix)
@@ -1060,5 +1120,5 @@ static bool nacpAddU64FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size,
const char *str = (hex ? (prefix ? " <%s>0x%016lx%s>\n" : " <%s>%016lx%s>\n") : " <%s>%lu%s>\n");
- return utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, str, tag_name, value, tag_name);
+ return NACP_ADD_FMT_STR_T2(str, tag_name, value, tag_name);
}
diff --git a/source/core/nxdt_utils.c b/source/core/nxdt_utils.c
index a5c4daa..4dd2e78 100644
--- a/source/core/nxdt_utils.c
+++ b/source/core/nxdt_utils.c
@@ -159,7 +159,8 @@ bool utilsInitializeResources(const int program_argc, const char **program_argv)
LOG_MSG("Running under %s mode.", _utilsAppletModeCheck() ? "applet" : "title override");
/* Create output directories (SD card only). */
- utilsCreateOutputDirectories(NULL);
+ /* TODO: remove the APP_TITLE check whenever we're ready for a release. */
+ if (!strcasecmp(APP_TITLE, "nxdumptool")) utilsCreateOutputDirectories(NULL);
if (g_appLaunchPath)
{
diff --git a/source/core/program_info.c b/source/core/program_info.c
index 4e9aba7..46df0cb 100644
--- a/source/core/program_info.c
+++ b/source/core/program_info.c
@@ -25,6 +25,11 @@
#include "program_info.h"
#include "elf_symbol.h"
+/* Helper macros. */
+
+#define PI_ADD_FMT_STR_T1(fmt, ...) utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, fmt, ##__VA_ARGS__)
+#define PI_ADD_FMT_STR_T2(fmt, ...) utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, fmt, ##__VA_ARGS__)
+
/* Global variables. */
static const char *g_trueString = "True", *g_falseString = "False";
@@ -203,36 +208,33 @@ bool programInfoGenerateAuthoringToolXml(ProgramInfoContext *program_info_ctx)
/* Get SDK version and build type strings. */
if (!programInfoGetSdkVersionAndBuildTypeFromSdkNso(program_info_ctx, &sdk_version, &build_type)) goto end;
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- "\n" \
- "\n")) goto end;
+ if (!PI_ADD_FMT_STR_T1("\n" \
+ "\n")) goto end;
/* SdkVersion. */
if (!programInfoAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SdkVersion", sdk_version)) goto end;
-
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" /* Impossible to get. */ \
- " %s\n" \
- " \n" /* Impossible to get. */ \
- " %u\n", \
- sdk_version, \
- is_64bit ? 64 : 32)) goto end;
+
+ if (!PI_ADD_FMT_STR_T1(" \n" /* Impossible to get. */ \
+ " %s\n" \
+ " \n" /* Impossible to get. */ \
+ " %u\n", \
+ sdk_version, \
+ is_64bit ? 64 : 32)) goto end;
/* BuildType. */
if (!programInfoAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "BuildType", build_type)) goto end;
- if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" /* Impossible to get. */ \
- " \n" /* Impossible to get. */ \
- " %s\n" \
- " \n" /* Impossible to get. */ \
- " \n" \
- " %s\n" \
- " %s\n" \
- " \n", \
- npdm_acid_b64, \
- program_info_ctx->npdm_ctx.acid_header->flags.production ? g_trueString : g_falseString, \
- program_info_ctx->npdm_ctx.acid_header->flags.unqualified_approval ? g_trueString : g_falseString)) goto end;
+ if (!PI_ADD_FMT_STR_T1(" \n" /* Impossible to get. */ \
+ " \n" /* Impossible to get. */ \
+ " %s\n" \
+ " \n" /* Impossible to get. */ \
+ " \n" \
+ " %s\n" \
+ " %s\n" \
+ " \n", \
+ npdm_acid_b64, \
+ program_info_ctx->npdm_ctx.acid_header->flags.production ? g_trueString : g_falseString, \
+ program_info_ctx->npdm_ctx.acid_header->flags.unqualified_approval ? g_trueString : g_falseString)) goto end;
/* MiddlewareList. */
if (!programInfoAddNsoApiListToAuthoringToolXml(&xml_buf, &xml_buf_size, program_info_ctx, "Middleware", "Module", "SDK MW")) goto end;
@@ -252,14 +254,13 @@ bool programInfoGenerateAuthoringToolXml(ProgramInfoContext *program_info_ctx)
/* FsAccessControlData. */
if (!programInfoAddFsAccessControlDataToAuthoringToolXml(&xml_buf, &xml_buf_size, program_info_ctx)) goto end;
- if (!(success = utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
- " \n" /* Impossible to get. */ \
- " \n" /* Impossible to get. */ \
- " \n" /* Impossible to get. */ \
- " \n" /* Impossible to get. */ \
- " \n" /* Impossible to get. */ \
- " \n" /* Impossible to get. */ \
- ""))) goto end;
+ if (!(success = PI_ADD_FMT_STR_T1(" \n" /* Impossible to get. */ \
+ " \n" /* Impossible to get. */ \
+ " \n" /* Impossible to get. */ \
+ " \n" /* Impossible to get. */ \
+ " \n" /* Impossible to get. */ \
+ " \n" /* Impossible to get. */ \
+ ""))) goto end;
/* Update ProgramInfo context. */
program_info_ctx->authoring_tool_xml = xml_buf;
@@ -397,11 +398,11 @@ static bool programInfoAddNsoApiListToAuthoringToolXml(char **xml_buf, u64 *xml_
/* Append an empty XML element if no entries for this API list exist. */
if (!api_list_exists)
{
- success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%sList />\n", api_list_tag);
+ success = PI_ADD_FMT_STR_T2(" <%sList />\n", api_list_tag);
goto end;
}
- if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%sList>\n", api_list_tag)) goto end;
+ if (!PI_ADD_FMT_STR_T2(" <%sList>\n", api_list_tag)) goto end;
/* Retrieve full API list. */
for(u32 i = 0; i < program_info_ctx->nso_count; i++)
@@ -415,24 +416,23 @@ static bool programInfoAddNsoApiListToAuthoringToolXml(char **xml_buf, u64 *xml_
if (programInfoIsApiInfoEntryValid(sdk_prefix, sdk_prefix_len, sdk_entry, &sdk_entry_vender, &sdk_entry_vender_len, &sdk_entry_name, false))
{
- if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, \
- " <%s>\n" \
- " <%sName>%s%sName>\n" \
- " %.*s\n" \
- " %s\n" \
- " %s>\n", \
- api_list_tag, \
- api_entry_prefix, sdk_entry_name, api_entry_prefix, \
- sdk_entry_vender_len, sdk_entry_vender, \
- nso_ctx->nso_filename, \
- api_list_tag)) goto end;
+ if (!PI_ADD_FMT_STR_T2(" <%s>\n" \
+ " <%sName>%s%sName>\n" \
+ " %.*s\n" \
+ " %s\n" \
+ " %s>\n", \
+ api_list_tag, \
+ api_entry_prefix, sdk_entry_name, api_entry_prefix, \
+ sdk_entry_vender_len, sdk_entry_vender, \
+ nso_ctx->nso_filename, \
+ api_list_tag)) goto end;
}
j += strlen(sdk_entry);
}
}
- success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " %sList>\n", api_list_tag);
+ success = PI_ADD_FMT_STR_T2(" %sList>\n", api_list_tag);
end:
return success;
@@ -466,8 +466,7 @@ static bool programInfoAddStringFieldToAuthoringToolXml(char **xml_buf, u64 *xml
return false;
}
- return ((value && *value) ? utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>%s%s>\n", tag_name, value, tag_name) : \
- utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s />\n", tag_name));
+ return ((value && *value) ? PI_ADD_FMT_STR_T2(" <%s>%s%s>\n", tag_name, value, tag_name) : PI_ADD_FMT_STR_T2(" <%s />\n", tag_name));
}
static bool programInfoAddNsoSymbolsToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, ProgramInfoContext *program_info_ctx)
@@ -488,8 +487,8 @@ static bool programInfoAddNsoSymbolsToAuthoringToolXml(char **xml_buf, u64 *xml_
for(u32 i = 0; i < program_info_ctx->nso_count; i++)
{
nso_ctx = &(program_info_ctx->nso_ctx[i]);
- if (nso_ctx->nso_filename && !strcmp(nso_ctx->nso_filename, "main") && nso_ctx->rodata_dynstr_section && nso_ctx->rodata_dynstr_section_size && nso_ctx->rodata_dynsym_section && \
- nso_ctx->rodata_dynsym_section_size) break;
+ if (nso_ctx->nso_filename && !strcmp(nso_ctx->nso_filename, "main") && nso_ctx->rodata_dynstr_section && nso_ctx->rodata_dynstr_section_size && \
+ nso_ctx->rodata_dynsym_section && nso_ctx->rodata_dynsym_section_size) break;
nso_ctx = NULL;
}
@@ -511,7 +510,7 @@ static bool programInfoAddNsoSymbolsToAuthoringToolXml(char **xml_buf, u64 *xml_
/* Bail out if we couldn't find any valid symbols. */
if (!symbols_exist) goto end;
- if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " \n")) goto end;
+ if (!PI_ADD_FMT_STR_T2(" \n")) goto end;
/* Parse ELF dynamic symbol table to retrieve the symbol strings. */
for(u64 i = 0; i < nso_ctx->rodata_dynsym_section_size; i += symbol_size)
@@ -520,20 +519,19 @@ static bool programInfoAddNsoSymbolsToAuthoringToolXml(char **xml_buf, u64 *xml_
if (!programInfoIsElfSymbolValid(nso_ctx->rodata_dynsym_section + i, nso_ctx->rodata_dynstr_section, nso_ctx->rodata_dynstr_section_size, is_64bit, &symbol_str)) continue;
- if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, \
- " \n" \
- " %s\n" \
- " %s\n" \
- " \n", \
- symbol_str, \
- nso_ctx->nso_filename)) goto end;
+ if (!PI_ADD_FMT_STR_T2(" \n" \
+ " %s\n" \
+ " %s\n" \
+ " \n", \
+ symbol_str, \
+ nso_ctx->nso_filename)) goto end;
}
- success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " \n");
+ success = PI_ADD_FMT_STR_T2(" \n");
end:
/* Append an empty XML element if no valid symbols exist. */
- if (!success && (!nso_ctx || !symbols_exist)) success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " \n");
+ if (!success && (!nso_ctx || !symbols_exist)) success = PI_ADD_FMT_STR_T2(" \n");
return success;
}
@@ -592,25 +590,24 @@ static bool programInfoAddFsAccessControlDataToAuthoringToolXml(char **xml_buf,
/* Padding to a 0x4-byte boundary is needed. Each accessibility field takes up a single byte, so we can get away with it by aligning the ID count. */
save_data_owner_ids = (u64*)((u8*)save_data_owner_block + sizeof(NpdmFsAccessControlDataSaveDataOwnerBlock) + ALIGN_UP(save_data_owner_block->save_data_owner_id_count, 0x4));
- if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " \n")) goto end;
+ if (!PI_ADD_FMT_STR_T2(" \n")) goto end;
/* Append save data owner IDs. */
for(u32 i = 0; i < save_data_owner_block->save_data_owner_id_count; i++)
{
- if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, \
- " \n" \
- " %s\n" \
- " 0x%016lx\n" \
- " \n", \
- g_facAccessibilityStrings[save_data_owner_block->accessibility[i] & 0x3], \
- save_data_owner_ids[i])) goto end;
+ if (!PI_ADD_FMT_STR_T2(" \n" \
+ " %s\n" \
+ " 0x%016lx\n" \
+ " \n", \
+ g_facAccessibilityStrings[save_data_owner_block->accessibility[i] & 0x3], \
+ save_data_owner_ids[i])) goto end;
}
- success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " \n");
+ success = PI_ADD_FMT_STR_T2(" \n");
end:
/* Append an empty XML element if no FS access control data exists. */
- if (!success && !sdo_data_available) success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " \n");
+ if (!success && !sdo_data_available) success = PI_ADD_FMT_STR_T2(" \n");
return success;
}
diff --git a/source/exception_handler.cpp b/source/exception_handler.cpp
index 36ea9a6..551993b 100644
--- a/source/exception_handler.cpp
+++ b/source/exception_handler.cpp
@@ -24,9 +24,12 @@
#include
#include
-#define FP_MASK 0xFFFFFFFFFF000000UL
-#define STACK_TRACE_SIZE 0x20
-#define IS_HB_ADDR(x) (info.addr && info.size && (x) >= info.addr && (x) < (info.addr + info.size))
+/* Helper macros. */
+
+#define FP_MASK 0xFFFFFFFFFF000000UL
+#define STACK_TRACE_SIZE 0x20
+#define IS_HB_ADDR(x) (info.addr && info.size && (x) >= info.addr && (x) < (info.addr + info.size))
+#define EH_ADD_FMT_STR(fmt, ...) utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, fmt, ##__VA_ARGS__)
namespace i18n = brls::i18n; /* For getStr(). */
using namespace i18n::literals; /* For _i18n. */
@@ -168,45 +171,45 @@ extern "C" {
break;
}
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "Type: %s (0x%X)\r\n", error_desc_str.c_str(), ctx->error_desc);
+ EH_ADD_FMT_STR("Type: %s (0x%X)\r\n", error_desc_str.c_str(), ctx->error_desc);
/* Log CPU registers. */
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "Registers:");
+ EH_ADD_FMT_STR("Registers:");
for(size_t i = 0; i < MAX_ELEMENTS(ctx->cpu_gprs); i++)
{
u64 reg = ctx->cpu_gprs[i].x;
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n X%02lu: 0x%lX", i, reg);
- if (IS_HB_ADDR(reg)) utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, " (BASE + 0x%lX)", reg - info.addr);
+ EH_ADD_FMT_STR("\r\n X%02lu: 0x%lX", i, reg);
+ if (IS_HB_ADDR(reg)) EH_ADD_FMT_STR(" (BASE + 0x%lX)", reg - info.addr);
}
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n FP: 0x%lX", ctx->fp.x);
- if (IS_HB_ADDR(ctx->fp.x)) utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, " (BASE + 0x%lX)", ctx->fp.x - info.addr);
+ EH_ADD_FMT_STR("\r\n FP: 0x%lX", ctx->fp.x);
+ if (IS_HB_ADDR(ctx->fp.x)) EH_ADD_FMT_STR(" (BASE + 0x%lX)", ctx->fp.x - info.addr);
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n LR: 0x%lX", ctx->lr.x);
- if (IS_HB_ADDR(ctx->lr.x)) utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, " (BASE + 0x%lX)", ctx->lr.x - info.addr);
+ EH_ADD_FMT_STR("\r\n LR: 0x%lX", ctx->lr.x);
+ if (IS_HB_ADDR(ctx->lr.x)) EH_ADD_FMT_STR(" (BASE + 0x%lX)", ctx->lr.x - info.addr);
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n SP: 0x%lX", ctx->sp.x);
- if (IS_HB_ADDR(ctx->sp.x)) utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, " (BASE + 0x%lX)", ctx->sp.x - info.addr);
+ EH_ADD_FMT_STR("\r\n SP: 0x%lX", ctx->sp.x);
+ if (IS_HB_ADDR(ctx->sp.x)) EH_ADD_FMT_STR(" (BASE + 0x%lX)", ctx->sp.x - info.addr);
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n PC: 0x%lX", ctx->pc.x);
- if (IS_HB_ADDR(ctx->pc.x)) utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, " (BASE + 0x%lX)", ctx->pc.x - info.addr);
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n");
+ EH_ADD_FMT_STR("\r\n PC: 0x%lX", ctx->pc.x);
+ if (IS_HB_ADDR(ctx->pc.x)) EH_ADD_FMT_STR(" (BASE + 0x%lX)", ctx->pc.x - info.addr);
+ EH_ADD_FMT_STR("\r\n");
/* Unwind stack. */
if (nxdt::utils::UnwindStack(stack_trace, &stack_trace_size, STACK_TRACE_SIZE, ctx->fp.x))
{
/* Log stack trace. */
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "Stack Trace:");
+ EH_ADD_FMT_STR("Stack Trace:");
for(u32 i = 0; i < stack_trace_size; i++)
{
u64 addr = stack_trace[i];
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n [%02u]: 0x%lX", stack_trace_size - i - 1, addr);
- if (IS_HB_ADDR(addr)) utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, " (BASE + 0x%lX)", addr - info.addr);
+ EH_ADD_FMT_STR("\r\n [%02u]: 0x%lX", stack_trace_size - i - 1, addr);
+ if (IS_HB_ADDR(addr)) EH_ADD_FMT_STR(" (BASE + 0x%lX)", addr - info.addr);
}
- utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n");
+ EH_ADD_FMT_STR("\r\n");
}
/* Write log string. */
@@ -216,7 +219,8 @@ extern "C" {
if (exception_str) free(exception_str);
/* Abort program execution. */
- crash_str = (g_borealisInitialized ? i18n::getStr("generic/exception_triggered"_i18n, error_desc_str, ctx->error_desc) : fmt::format("Fatal exception triggered!\nReason: {} (0x{:X}).", error_desc_str, ctx->error_desc));
+ crash_str = (g_borealisInitialized ? i18n::getStr("generic/exception_triggered"_i18n, error_desc_str, ctx->error_desc) : \
+ fmt::format("Fatal exception triggered!\nReason: {} (0x{:X}).", error_desc_str, ctx->error_desc));
crash_str += (fmt::format("\nPC: 0x{:X}", ctx->pc.x) + (IS_HB_ADDR(ctx->pc.x) ? fmt::format(" (BASE + 0x{:X}).", ctx->pc.x - info.addr) : "."));
nxdt::utils::AbortProgramExecution(crash_str);
}
diff --git a/todo.txt b/todo.txt
index 49fa468..bd1942a 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,11 +1,11 @@
todo:
+ nca: support for sparse sections
+ nca: support for compressed fs sections
+
log: verbosity levels
log: nxlink output for advanced users
- nca: support for compressed fs sections?
- nca: support for sparse sections?
-
title: more functions for title lookup? (filters, patches / aoc, etc.)
title: more functions for content lookup? (based on id)
title: parse the update partition from gamecards (if available) to generate ncmcontentinfo data for all update titles