1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-22 18:26:39 +00:00

More changes.

* gc_dumper: fixed Card ID Set dumping.

* nacp: updated structs and enums to match latest changes (big thanks to @0Liam !), added helper macros.

* cnmt: added helper macros.

* program_info: added helper macros.

* exception_handler: added helper macros.

* nxdt_utils: only create output directories if the app isn't a PoC build.

* todo: changed task priority order. Sparse/compressed section support is mandatory and must be implemented ASAP.
This commit is contained in:
Pablo Curiel 2022-03-18 17:48:16 +01:00
parent 9604b5923d
commit 7189943680
9 changed files with 476 additions and 362 deletions

View file

@ -696,11 +696,11 @@ static bool saveGameCardIdSet(void)
crc = crc32Calculate(&id_set, sizeof(FsGameCardIdSet)); crc = crc32Calculate(&id_set, sizeof(FsGameCardIdSet));
snprintf(path, MAX_ELEMENTS(path), " (Card ID Set) (%08X).bin", crc); snprintf(path, MAX_ELEMENTS(path), " (Card ID Set) (%08X).bin", crc);
if (!saveFileData(filename, &id_set, sizeof(FsGameCardIdSet))) goto end;
filename = generateOutputFileName(path); filename = generateOutputFileName(path);
if (!filename) goto end; if (!filename) goto end;
if (!saveFileData(filename, &id_set, sizeof(FsGameCardIdSet))) goto end;
printf("successfully saved gamecard id set as \"%s\"\n", filename); printf("successfully saved gamecard id set as \"%s\"\n", filename);
success = true; success = true;

View file

@ -49,7 +49,12 @@ typedef enum {
typedef enum { typedef enum {
NacpUserAccountSwitchLock_Disable = 0, NacpUserAccountSwitchLock_Disable = 0,
NacpUserAccountSwitchLock_Enable = 1, 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; } NacpUserAccountSwitchLock;
typedef enum { typedef enum {
@ -61,7 +66,8 @@ typedef enum {
typedef enum { typedef enum {
NacpAttribute_Demo = BIT(0), NacpAttribute_Demo = BIT(0),
NacpAttribute_RetailInteractiveDisplay = BIT(1), 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; } NacpAttribute;
/// Indexes used to access NACP Title structs. /// Indexes used to access NACP Title structs.
@ -106,7 +112,7 @@ typedef enum {
NacpSupportedLanguage_TraditionalChinese = BIT(13), NacpSupportedLanguage_TraditionalChinese = BIT(13),
NacpSupportedLanguage_SimplifiedChinese = BIT(14), NacpSupportedLanguage_SimplifiedChinese = BIT(14),
NacpSupportedLanguage_BrazilianPortuguese = BIT(15), 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. ///< Old.
NacpSupportedLanguage_Taiwanese = NacpSupportedLanguage_TraditionalChinese, NacpSupportedLanguage_Taiwanese = NacpSupportedLanguage_TraditionalChinese,
@ -216,6 +222,14 @@ typedef enum {
NacpRuntimeParameterDelivery_Count = 3 ///< Total values supported by this enum. NacpRuntimeParameterDelivery_Count = 3 ///< Total values supported by this enum.
} NacpRuntimeParameterDelivery; } 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 { typedef enum {
NacpUndecidedParameter75b8b_A = 0, NacpUndecidedParameter75b8b_A = 0,
NacpUndecidedParameter75b8b_B = 1, NacpUndecidedParameter75b8b_B = 1,
@ -239,6 +253,17 @@ typedef enum {
NacpStartupUserAccountOption_Count = 1 ///< Total values supported by this enum. NacpStartupUserAccountOption_Count = 1 ///< Total values supported by this enum.
} NacpStartupUserAccountOption; } 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 { typedef enum {
NacpPlayLogQueryCapability_None = 0, NacpPlayLogQueryCapability_None = 0,
NacpPlayLogQueryCapability_WhiteList = 1, NacpPlayLogQueryCapability_WhiteList = 1,
@ -257,9 +282,8 @@ typedef enum {
} NacpRequiredNetworkServiceLicenseOnLaunch; } NacpRequiredNetworkServiceLicenseOnLaunch;
typedef enum { typedef enum {
NacpJitConfigurationFlag_None = 0, NacpJitConfigurationFlag_Enabled = BIT_LONG(0),
NacpJitConfigurationFlag_Enabled = 1, NacpJitConfigurationFlag_Count = 1 ///< Total values supported by this enum.
NacpJitConfigurationFlag_Count = 2 ///< Total values supported by this enum.
} NacpJitConfigurationFlag; } NacpJitConfigurationFlag;
typedef struct { typedef struct {
@ -269,23 +293,27 @@ typedef struct {
NXDT_ASSERT(NacpJitConfiguration, 0x10); NXDT_ASSERT(NacpJitConfiguration, 0x10);
typedef struct { typedef enum {
u16 index : 15; NacpRequiredAddOnContentsSetDescriptorFlag_None = 0,
u16 continue_set : 1; ///< Called "flag" by Nintendo, which isn't really great. NacpRequiredAddOnContentsSetDescriptorFlag_Continue = 1
} NacpDescriptors; } NacpRequiredAddOnContentsSetDescriptorFlag;
NXDT_ASSERT(NacpDescriptors, 0x2);
typedef struct { typedef struct {
NacpDescriptors descriptors[0x20]; u16 index : 15;
u16 flag : 1; ///< NacpRequiredAddOnContentsSetDescriptorFlag.
} NacpRequiredAddOnContentsSetDescriptor;
NXDT_ASSERT(NacpRequiredAddOnContentsSetDescriptor, 0x2);
typedef struct {
NacpRequiredAddOnContentsSetDescriptor descriptors[0x20];
} NacpRequiredAddOnContentsSetBinaryDescriptor; } NacpRequiredAddOnContentsSetBinaryDescriptor;
NXDT_ASSERT(NacpRequiredAddOnContentsSetBinaryDescriptor, 0x40); NXDT_ASSERT(NacpRequiredAddOnContentsSetBinaryDescriptor, 0x40);
typedef enum { typedef enum {
NacpPlayReportPermission_None = 0, NacpPlayReportPermission_TargetMarketing = BIT(0),
NacpPlayReportPermission_TargetMarketing = 1, NacpPlayReportPermission_Count = 1 ///< Total values supported by this enum.
NacpPlayReportPermission_Count = 2 ///< Total values supported by this enum.
} NacpPlayReportPermission; } NacpPlayReportPermission;
typedef enum { typedef enum {
@ -300,6 +328,16 @@ typedef enum {
NacpCrashScreenshotForDev_Count = 2 ///< Total values supported by this enum. NacpCrashScreenshotForDev_Count = 2 ///< Total values supported by this enum.
} NacpCrashScreenshotForDev; } 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 { typedef struct {
u64 application_id[8]; u64 application_id[8];
} NacpAccessibleLaunchRequiredVersion; } NacpAccessibleLaunchRequiredVersion;
@ -310,7 +348,7 @@ typedef struct {
NacpTitle title[0x10]; NacpTitle title[0x10];
char isbn[0x25]; char isbn[0x25];
u8 startup_user_account; ///< NacpStartupUserAccount. 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. u8 add_on_content_registration_type; ///< NacpAddOnContentRegistrationType.
u32 attribute; ///< NacpAttribute. u32 attribute; ///< NacpAttribute.
u32 supported_language; ///< NacpSupportedLanguage. u32 supported_language; ///< NacpSupportedLanguage.
@ -335,14 +373,14 @@ typedef struct {
u8 logo_handling; ///< NacpLogoHandling. u8 logo_handling; ///< NacpLogoHandling.
u8 runtime_add_on_content_install; ///< NacpRuntimeAddOnContentInstall. u8 runtime_add_on_content_install; ///< NacpRuntimeAddOnContentInstall.
u8 runtime_parameter_delivery; ///< NacpRuntimeParameterDelivery. u8 runtime_parameter_delivery; ///< NacpRuntimeParameterDelivery.
u8 reserved_1; u8 appropriate_age_for_china; ///< NacpAppropriateAgeForChina.
u8 undecided_parameter_75b8b; ///< NacpUndecidedParameter75b8b. u8 undecided_parameter_75b8b; ///< NacpUndecidedParameter75b8b.
u8 crash_report; ///< NacpCrashReport. u8 crash_report; ///< NacpCrashReport.
u8 hdcp; ///< NacpHdcp. u8 hdcp; ///< NacpHdcp.
u64 seed_for_pseudo_device_id; u64 seed_for_pseudo_device_id;
char bcat_passphrase[0x41]; char bcat_passphrase[0x41];
u8 startup_user_account_option; ///< NacpStartupUserAccountOption. 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_size_max;
s64 user_account_save_data_journal_size_max; s64 user_account_save_data_journal_size_max;
s64 device_save_data_size_max; s64 device_save_data_size_max;
@ -352,22 +390,25 @@ typedef struct {
s64 cache_storage_journal_size; s64 cache_storage_journal_size;
s64 cache_storage_data_and_journal_size_max; s64 cache_storage_data_and_journal_size_max;
u16 cache_storage_index_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]; u64 play_log_queryable_application_id[0x10];
u8 play_log_query_capability; ///< NacpPlayLogQueryCapability. u8 play_log_query_capability; ///< NacpPlayLogQueryCapability.
u8 repair; ///< NacpRepair. u8 repair; ///< NacpRepair.
u8 program_index; u8 program_index;
u8 required_network_service_license_on_launch; ///< NacpRequiredNetworkServiceLicenseOnLaunch. u8 required_network_service_license_on_launch; ///< NacpRequiredNetworkServiceLicenseOnLaunch.
u8 reserved_4[0x4]; u8 reserved_2[0x4];
NacpNeighborDetectionClientConfiguration neighbor_detection_client_configuration; NacpNeighborDetectionClientConfiguration neighbor_detection_client_configuration;
NacpJitConfiguration jit_configuration; NacpJitConfiguration jit_configuration;
NacpRequiredAddOnContentsSetBinaryDescriptor required_add_on_contents_set_binary_descriptor; NacpRequiredAddOnContentsSetBinaryDescriptor required_add_on_contents_set_binary_descriptor;
u8 play_report_permission; ///< NacpPlayReportPermission. u8 play_report_permission; ///< NacpPlayReportPermission.
u8 crash_screenshot_for_prod; ///< NacpCrashScreenshotForProd. u8 crash_screenshot_for_prod; ///< NacpCrashScreenshotForProd.
u8 crash_screenshot_for_dev; ///< NacpCrashScreenshotForDev. 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; NacpAccessibleLaunchRequiredVersion accessible_launch_required_version;
u8 reserved_6[0xBB8]; u8 reserved_4[0xBB8];
} _NacpStruct; } _NacpStruct;
NXDT_ASSERT(_NacpStruct, 0x4000); 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"). /// 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 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. /// If dealing with a bitflag field such as:
/// (e.g. NacpAttribute_RetailInteractiveDisplay -> Use 1 instead). /// * 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 *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 *nacpGetStartupUserAccountString(u8 startup_user_account);
const char *nacpGetUserAccountSwitchLockString(u8 user_account_switch_lock); 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 *nacpGetLogoHandlingString(u8 logo_handling);
const char *nacpGetRuntimeAddOnContentInstallString(u8 runtime_add_on_content_install); const char *nacpGetRuntimeAddOnContentInstallString(u8 runtime_add_on_content_install);
const char *nacpGetRuntimeParameterDeliveryString(u8 runtime_parameter_delivery); const char *nacpGetRuntimeParameterDeliveryString(u8 runtime_parameter_delivery);
const char *nacpGetAppropriateAgeForChina(u8 appropriate_age_for_china);
const char *nacpGetUndecidedParameter75b8bString(u8 undecided_parameter_75b8b); const char *nacpGetUndecidedParameter75b8bString(u8 undecided_parameter_75b8b);
const char *nacpGetCrashReportString(u8 crash_report); const char *nacpGetCrashReportString(u8 crash_report);
const char *nacpGetHdcpString(u8 hdcp); const char *nacpGetHdcpString(u8 hdcp);
const char *nacpGetStartupUserAccountOptionString(u8 startup_user_account_option); const char *nacpGetStartupUserAccountOptionString(u8 startup_user_account_option);
const char *nacpGetRuntimeUpgradeString(u8 runtime_upgrade);
const char *nacpGetPlayLogQueryCapabilityString(u8 play_log_query_capability); const char *nacpGetPlayLogQueryCapabilityString(u8 play_log_query_capability);
const char *nacpGetRepairString(u8 repair); const char *nacpGetRepairString(u8 repair);
const char *nacpGetRequiredNetworkServiceLicenseOnLaunchString(u8 required_network_service_license_on_launch); 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 *nacpGetCrashScreenshotForProdString(u8 crash_screenshot_for_prod);
const char *nacpGetCrashScreenshotForDevString(u8 crash_screenshot_for_dev); const char *nacpGetCrashScreenshotForDevString(u8 crash_screenshot_for_dev);
const char *nacpGetContentsAvailabilityTransitionPolicyString(u8 contents_availability_transition_policy);
/// Helper inline functions. /// Helper inline functions.

@ -1 +1 @@
Subproject commit d6afc3c2ba17158553397d1f1d3a607da661f2ba Subproject commit 0580fc38903546a99cc09e4f16418a3863e067b0

View file

@ -23,7 +23,10 @@
#include "cnmt.h" #include "cnmt.h"
#include "title.h" #include "title.h"
/* Helper macros. */
#define CNMT_MINIMUM_FILENAME_LENGTH 23 /* Content Meta Type + "_" + Title ID + ".cnmt". */ #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. */ /* Global variables. */
@ -367,31 +370,33 @@ bool cnmtGenerateAuthoringToolXml(ContentMetaContext *cnmt_ctx, NcaContext *nca_
cnmt_ctx->authoring_tool_xml = NULL; cnmt_ctx->authoring_tool_xml = NULL;
cnmt_ctx->authoring_tool_xml_size = 0; cnmt_ctx->authoring_tool_xml_size = 0;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!CNMT_ADD_FMT_STR("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" \
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" \ "<ContentMeta>\n" \
"<ContentMeta>\n" \ " <Type>%s</Type>\n" \
" <Type>%s</Type>\n" \ " <Id>0x%016lx</Id>\n" \
" <Id>0x%016lx</Id>\n" \ " <Version>%u</Version>\n" \
" <Version>%u</Version>\n" \ " <ReleaseVersion>%u</ReleaseVersion>\n" \
" <ReleaseVersion />\n" \ " <PrivateVersion>%u</PrivateVersion>\n", \
" <PrivateVersion />\n", titleGetNcmContentMetaTypeName(cnmt_ctx->packaged_header->content_meta_type), \
titleGetNcmContentMetaTypeName(cnmt_ctx->packaged_header->content_meta_type), \ cnmt_ctx->packaged_header->title_id, \
cnmt_ctx->packaged_header->title_id, \ cnmt_ctx->packaged_header->version.value, \
cnmt_ctx->packaged_header->version.value)) goto end; cnmt_ctx->packaged_header->version.application_version.release_ver, \
cnmt_ctx->packaged_header->version.application_version.private_ver)) goto end;
/* ContentMetaAttribute. */ /* ContentMetaAttribute. */
for(i = 0; i < ContentMetaAttribute_Count; i++) for(i = 0; i < ContentMetaAttribute_Count; i++)
{ {
if (!(cnmt_ctx->packaged_header->content_meta_attribute & (u8)BIT(i))) continue; if (!(cnmt_ctx->packaged_header->content_meta_attribute & (u8)BIT(i))) continue;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <ContentMetaAttribute>%s</ContentMetaAttribute>\n", g_cnmtAttributeStrings[i])) goto end; if (!CNMT_ADD_FMT_STR(" <ContentMetaAttribute>%s</ContentMetaAttribute>\n", g_cnmtAttributeStrings[i])) goto end;
count++; count++;
} }
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <ContentMetaAttribute />\n")) goto end; if (!count && !CNMT_ADD_FMT_STR(" <ContentMetaAttribute />\n")) goto end;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <RequiredDownloadSystemVersion>%u</RequiredDownloadSystemVersion>\n", \ /* RequiredDownloadSystemVersion. */
cnmt_ctx->packaged_header->required_download_system_version.value)) goto end; if (!CNMT_ADD_FMT_STR(" <RequiredDownloadSystemVersion>%u</RequiredDownloadSystemVersion>\n", cnmt_ctx->packaged_header->required_download_system_version.value)) goto end;
/* Contents. */
for(i = 0; i < nca_ctx_count; i++) for(i = 0; i < nca_ctx_count; i++)
{ {
NcaContext *cur_nca_ctx = &(nca_ctx[i]); NcaContext *cur_nca_ctx = &(nca_ctx[i]);
@ -417,34 +422,35 @@ bool cnmtGenerateAuthoringToolXml(ContentMetaContext *cnmt_ctx, NcaContext *nca_
goto end; goto end;
} }
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!CNMT_ADD_FMT_STR(" <Content>\n" \
" <Content>\n" \ " <Type>%s</Type>\n" \
" <Type>%s</Type>\n" \ " <Id>%s</Id>\n" \
" <Id>%s</Id>\n" \ " <Size>%lu</Size>\n" \
" <Size>%lu</Size>\n" \ " <Hash>%s</Hash>\n" \
" <Hash>%s</Hash>\n" \ " <KeyGeneration>%u</KeyGeneration>\n" \
" <KeyGeneration>%u</KeyGeneration>\n" \ " <IdOffset>%u</IdOffset>\n" \
" <IdOffset>%u</IdOffset>\n" \ " </Content>\n", \
" </Content>\n", \ titleGetNcmContentTypeName(cur_nca_ctx->content_type), \
titleGetNcmContentTypeName(cur_nca_ctx->content_type), \ cur_nca_ctx->content_id_str, \
cur_nca_ctx->content_id_str, \ cur_nca_ctx->content_size, \
cur_nca_ctx->content_size, \ cur_nca_ctx->hash_str, \
cur_nca_ctx->hash_str, \ cur_nca_ctx->key_generation, \
cur_nca_ctx->key_generation, \ cur_nca_ctx->id_offset)) goto end;
cur_nca_ctx->id_offset)) goto end;
} }
utilsGenerateHexStringFromData(digest_str, sizeof(digest_str), cnmt_ctx->digest, CNMT_DIGEST_SIZE, false); utilsGenerateHexStringFromData(digest_str, sizeof(digest_str), cnmt_ctx->digest, CNMT_DIGEST_SIZE, false);
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ /* ContentMeta, Digest, KeyGenerationMin, KeepGeneration and KeepGenerationSpecified. */
" <ContentMeta />\n" \ if (!CNMT_ADD_FMT_STR(" <ContentMeta />\n" \
" <Digest>%s</Digest>\n" \ " <Digest>%s</Digest>\n" \
" <KeyGenerationMin>%u</KeyGenerationMin>\n" \ " <KeyGenerationMin>%u</KeyGenerationMin>\n" \
" <KeepGeneration />\n" \ " <KeepGeneration />\n" \
" <KeepGenerationSpecified />\n", \ " <KeepGenerationSpecified />\n", \
digest_str, \ digest_str, \
cnmt_ctx->nca_ctx->key_generation)) goto end; 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 || \ 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) 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); u64 required_title_id = cnmtGetRequiredTitleId(cnmt_ctx);
const char *required_title_type_str = cnmtGetRequiredTitleTypeString(cnmt_ctx->packaged_header->content_meta_type); const char *required_title_type_str = cnmtGetRequiredTitleTypeString(cnmt_ctx->packaged_header->content_meta_type);
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!CNMT_ADD_FMT_STR(" <%s>%u</%s>\n" \
" <%s>%u</%s>\n" \ " <%s>0x%016lx</%s>\n", \
" <%s>0x%016lx</%s>\n", \ required_title_version_str, required_title_version, required_title_version_str, \
required_title_version_str, required_title_version, required_title_version_str, \ required_title_type_str, required_title_id, required_title_type_str)) goto end;
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 (cnmt_ctx->packaged_header->content_meta_type == NcmContentMetaType_Application)
{ {
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!CNMT_ADD_FMT_STR(" <RequiredApplicationVersion>%u</RequiredApplicationVersion>\n", \
" <RequiredApplicationVersion>%u</RequiredApplicationVersion>\n", \ ((ContentMetaApplicationMetaExtendedHeader*)cnmt_ctx->extended_header)->required_application_version.value)) goto end;
((ContentMetaApplicationMetaExtendedHeader*)cnmt_ctx->extended_header)->required_application_version.value)) goto end;
} }
if (!(success = utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, "</ContentMeta>"))) goto end; if (!(success = CNMT_ADD_FMT_STR("</ContentMeta>"))) goto end;
/* Update CNMT context. */ /* Update CNMT context. */
cnmt_ctx->authoring_tool_xml = xml_buf; cnmt_ctx->authoring_tool_xml = xml_buf;

View file

@ -23,6 +23,23 @@
#include "nacp.h" #include "nacp.h"
#include "title.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. */ /* Type definitions. */
typedef const char *(*NacpStringFunction)(u8 value); /* Used while adding fields to the AuthoringTool-like XML. */ 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] = { static const char *g_nacpAttributeStrings[NacpAttribute_Count] = {
"Demo", "Demo",
"RetailInteractiveDisplay" "RetailInteractiveDisplay",
"DownloadPlay"
}; };
static const char *g_nacpParentalControlStrings[NacpParentalControl_Count] = { static const char *g_nacpParentalControlStrings[NacpParentalControl_Count] = {
@ -137,6 +155,13 @@ static const char *g_nacpRuntimeParameterDeliveryStrings[NacpRuntimeParameterDel
"OnRestart" "OnRestart"
}; };
static const char *g_nacpAppropriateAgeForChinaStrings[NacpAppropriateAgeForChina_Count] = {
"None",
"Age8",
"Age12",
"Age16"
};
static const char *g_nacpUndecidedParameter75b8bStrings[NacpUndecidedParameter75b8b_Count] = { static const char *g_nacpUndecidedParameter75b8bStrings[NacpUndecidedParameter75b8b_Count] = {
"a", "a",
"b" "b"
@ -156,6 +181,11 @@ static const char *g_nacpStartupUserAccountOptionStrings[NacpStartupUserAccountO
"IsOptional" "IsOptional"
}; };
static const char *g_nacpRuntimeUpgradeStrings[NacpRuntimeUpgrade_Count] = {
"Deny",
"Allow"
};
static const char *g_nacpPlayLogQueryCapabilityStrings[NacpPlayLogQueryCapability_Count] = { static const char *g_nacpPlayLogQueryCapabilityStrings[NacpPlayLogQueryCapability_Count] = {
"None", "None",
"WhiteList", "WhiteList",
@ -170,16 +200,6 @@ static const char *g_nacpRequiredNetworkServiceLicenseOnLaunchStrings[NacpRequir
"Common" "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] = { static const char *g_nacpCrashScreenshotForProdStrings[NacpCrashScreenshotForProd_Count] = {
"Deny", "Deny",
"Allow" "Allow"
@ -190,13 +210,19 @@ static const char *g_nacpCrashScreenshotForDevStrings[NacpCrashScreenshotForDev_
"Allow" "Allow"
}; };
static const char *g_nacpContentsAvailabilityTransitionPolicyStrings[NacpContentsAvailabilityTransitionPolicy_Count] = {
"NoPolicy",
"Stable",
"Changeable"
};
/* Function prototypes. */ /* Function prototypes. */
NX_INLINE bool nacpCheckBitflagField(const void *flag, u8 flag_bitcount, u8 idx); 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 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 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 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 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); 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; _NacpStruct *nacp = nacp_ctx->data;
Version app_ver = { .value = version };
u8 i = 0, count = 0; u8 i = 0, count = 0;
char *xml_buf = NULL; char *xml_buf = NULL;
u64 xml_buf_size = 0; 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); NacpNeighborDetectionClientConfiguration *ndcc = &(nacp->neighbor_detection_client_configuration);
NacpRequiredAddOnContentsSetBinaryDescriptor *raocsbd = &(nacp->required_add_on_contents_set_binary_descriptor); NacpRequiredAddOnContentsSetBinaryDescriptor *raocsbd = &(nacp->required_add_on_contents_set_binary_descriptor);
bool raocsbd_available = false;
bool alrv_available = false;
bool success = 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 = NULL;
nacp_ctx->authoring_tool_xml_size = 0; nacp_ctx->authoring_tool_xml_size = 0;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_FMT_STR_T1("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" \
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" \ "<Application>\n")) goto end;
"<Application>\n")) goto end;
/* Title. */ /* Title. */
for(i = 0, count = 0; i < NacpLanguage_Count; i++) 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]); NacpTitle *title = &(nacp->title[i]);
if (!*(title->name) || !*(title->publisher)) continue; if (!*(title->name) || !*(title->publisher)) continue;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_FMT_STR_T1(" <Title>\n" \
" <Title>\n" \ " <Language>%s</Language>\n" \
" <Language>%s</Language>\n" \ " <Name>%s</Name>\n" \
" <Name>%s</Name>\n" \ " <Publisher>%s</Publisher>\n" \
" <Publisher>%s</Publisher>\n" \ " </Title>\n", \
" </Title>\n", \ nacpGetLanguageString(i), \
nacpGetLanguageString(i), \ title->name, \
title->name, \ title->publisher)) goto end;
title->publisher)) goto end;
count++; count++;
} }
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <Title />\n")) goto end; if (!count && !NACP_ADD_FMT_STR_T1(" <Title />\n")) goto end;
/* Isbn. */ /* Isbn. */
if (!nacpAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Isbn", nacp->isbn)) goto end; if (!NACP_ADD_STR("Isbn", nacp->isbn)) goto end;
/* StartupUserAccount. */ /* 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. */ /* StartupUserAccountOption. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "StartupUserAccountOption", &(nacp->startup_user_account_option), sizeof(nacp->startup_user_account_option), \ if (!NACP_ADD_BITFLAG("StartupUserAccountOption", &(nacp->startup_user_account_option), sizeof(nacp->startup_user_account_option), NacpStartupUserAccountOption_Count, \
NacpStartupUserAccountOption_Count, &nacpGetStartupUserAccountOptionString)) goto end; nacpGetStartupUserAccountOptionString, true)) goto end;
/* UserAccountSwitchLock. */ /* 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. */ /* 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. */ /* ParentalControl. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ParentalControl", &(nacp->parental_control), sizeof(nacp->parental_control), NacpParentalControl_Count, \ if (!NACP_ADD_BITFLAG("ParentalControl", &(nacp->parental_control), sizeof(nacp->parental_control), NacpParentalControl_Count, nacpGetParentalControlString, false)) goto end;
&nacpGetParentalControlString)) goto end;
/* SupportedLanguage. */ /* SupportedLanguage. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SupportedLanguage", &(nacp->supported_language), sizeof(nacp->supported_language), NacpSupportedLanguage_Count, \ if (!NACP_ADD_BITFLAG("SupportedLanguage", &(nacp->supported_language), sizeof(nacp->supported_language), NacpSupportedLanguage_Count, nacpGetLanguageString, false)) goto end;
&nacpGetLanguageString)) goto end;
/* Screenshot. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* Rating. */
for(i = 0, count = 0; i < NacpRatingAgeOrganization_Count; i++) 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); s8 age = *(((s8*)&(nacp->rating_age)) + i);
if (age < 0) continue; if (age < 0) continue;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_FMT_STR_T1(" <Rating>\n" \
" <Rating>\n" \ " <Organization>%s</Organization>\n" \
" <Organization>%s</Organization>\n" \ " <Age>%d</Age>\n" \
" <Age>%d</Age>\n" \ " </Rating>\n", \
" </Rating>\n", \ nacpGetRatingAgeOrganizationString(i), \
nacpGetRatingAgeOrganizationString(i), \ age)) goto end;
age)) goto end;
count++; count++;
} }
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <Rating />\n")) goto end; if (!count && !NACP_ADD_FMT_STR_T1(" <Rating />\n")) goto end;
/* DataLossConfirmation. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* ReleaseVersion. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_U32("ReleaseVersion", app_ver.application_version.release_ver, false, false)) goto end;
" <ReleaseVersion />\n" \
" <PrivateVersion />\n")) goto end; /* PrivateVersion. */
if (!NACP_ADD_U32("PrivateVersion", app_ver.application_version.private_ver, false, false)) goto end;
/* LogoType. */ /* 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. */ /* 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. */ /* LocalCommunicationId. */
for(i = 0, count = 0; i < 0x8; i++) for(i = 0; i < 0x8; i++)
{ {
if (!nacp->local_communication_id[i]) continue; if (!nacp->local_communication_id[i]) continue;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "LocalCommunicationId", nacp->local_communication_id[i], true, true)) goto end; if (!NACP_ADD_U64("LocalCommunicationId", nacp->local_communication_id[i], true, true)) goto end;
count++;
} }
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <LocalCommunicationId />\n")) goto end;
/* LogoHandling. */ /* 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. */ /* Icon. */
for(i = 0, count = 0; i < nacp_ctx->icon_count; i++) 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); utilsGenerateHexStringFromData(icon_hash_str, sizeof(icon_hash_str), icon_hash, sizeof(icon_hash) / 2, false);
/* Add XML element. */ /* Add XML element. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_FMT_STR_T1(" <Icon>\n" \
" <Icon>\n" \ " <Language>%s</Language>\n" \
" <Language>%s</Language>\n" \ /*" <IconPath />\n" \
" <IconPath />\n" \ " <NxIconPath />\n" \
" <NxIconPath />\n" \ " <RawIconHash />\n" \*/
" <RawIconHash />\n" \ " <NxIconHash>%s</NxIconHash>\n" \
" <NxIconHash>%s</NxIconHash>\n" \ " </Icon>\n", \
" </Icon>\n", \ nacpGetLanguageString(icon_ctx->language), \
nacpGetLanguageString(icon_ctx->language), \ icon_hash_str)) goto end;
icon_hash_str)) goto end;
count++; count++;
} }
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <Icon />\n")) goto end; if (!count && !NACP_ADD_FMT_STR_T1(" <Icon />\n")) goto end;
/* HtmlDocumentPath, LegalInformationFilePath and AccessibleUrlsFilePath. Unused but kept anyway. */ /* HtmlDocumentPath, LegalInformationFilePath and AccessibleUrlsFilePath. Unused but kept anyway. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_FMT_STR_T1(" <HtmlDocumentPath UseEnvironmentVariable=\"false\" />\n" \
" <HtmlDocumentPath />\n" \ " <LegalInformationFilePath UseEnvironmentVariable=\"false\" />\n" \
" <LegalInformationFilePath />\n" \ " <AccessibleUrlsFilePath UseEnvironmentVariable=\"false\" />\n")) goto end;
" <AccessibleUrlsFilePath />\n")) goto end;
/* SeedForPseudoDeviceId. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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 (!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; if (!NACP_ADD_U64("PlayLogQueryableApplicationId", nacp->play_log_queryable_application_id[i], true, true)) goto end;
count++;
} }
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <PlayLogQueryableApplicationId />\n")) goto end;
/* PlayLogQueryCapability. */ /* 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. */ /* 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. */ /* 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. */ /* RequiredNetworkServiceLicenseOnLaunch. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RequiredNetworkServiceLicenseOnLaunch", &(nacp->required_network_service_license_on_launch), \ if (!NACP_ADD_BITFLAG("RequiredNetworkServiceLicenseOnLaunch", &(nacp->required_network_service_license_on_launch), sizeof(nacp->required_network_service_license_on_launch), \
sizeof(nacp->required_network_service_license_on_launch), NacpRequiredNetworkServiceLicenseOnLaunch_Count, &nacpGetRequiredNetworkServiceLicenseOnLaunchString)) goto end; NacpRequiredNetworkServiceLicenseOnLaunch_Count, nacpGetRequiredNetworkServiceLicenseOnLaunchString, false)) goto end;
/* NeighborDetectionClientConfiguration. */ /* NeighborDetectionClientConfiguration. */
ndcc_sgc_available = (ndcc->send_group_configuration.group_id && memcmp(ndcc->send_group_configuration.key, null_key, sizeof(null_key))); 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 (ndcc_sgc_available || ndcc_rgc_available)
{ {
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <NeighborDetectionClientConfiguration>\n")) goto end; if (!NACP_ADD_FMT_STR_T1(" <NeighborDetectionClientConfiguration>\n")) goto end;
/* SendGroupConfiguration. */ /* SendGroupConfiguration. */
utilsGenerateHexStringFromData(key_str, sizeof(key_str), ndcc->send_group_configuration.key, sizeof(ndcc->send_group_configuration.key), false); 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, \ if (!NACP_ADD_FMT_STR_T1(" <SendGroupConfiguration>\n" \
" <SendGroupConfiguration>\n" \ " <GroupId>0x%016lx</GroupId>\n" \
" <GroupId>0x%016lx</GroupId>\n" \ " <Key>%s</Key>\n" \
" <Key>%s</Key>\n" \ " </SendGroupConfiguration>\n", \
" </SendGroupConfiguration>\n", \ ndcc->send_group_configuration.group_id, \
ndcc->send_group_configuration.group_id, \ key_str)) goto end;
key_str)) goto end;
/* ReceivableGroupConfiguration. */ /* ReceivableGroupConfiguration. */
for(i = 0; i < 0x10; i++) 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); utilsGenerateHexStringFromData(key_str, sizeof(key_str), rgc->key, sizeof(rgc->key), false);
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_FMT_STR_T1(" <ReceivableGroupConfiguration>\n" \
" <ReceivableGroupConfiguration>\n" \ " <GroupId>0x%016lx</GroupId>\n" \
" <GroupId>0x%016lx</GroupId>\n" \ " <Key>%s</Key>\n" \
" <Key>%s</Key>\n" \ " </ReceivableGroupConfiguration>\n", \
" </ReceivableGroupConfiguration>\n", \ rgc->group_id, \
rgc->group_id, \ key_str)) goto end;
key_str)) goto end;
} }
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " </NeighborDetectionClientConfiguration>\n")) goto end; if (!NACP_ADD_FMT_STR_T1(" </NeighborDetectionClientConfiguration>\n")) goto end;
} else {
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <NeighborDetectionClientConfiguration />\n")) goto end;
} }
/* JitConfiguration. */ /* JitConfiguration. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_FMT_STR_T1(" <Jit>\n" \
" <Jit>\n" \ " <IsEnabled>%s</IsEnabled>\n" \
" <IsEnabled>%s</IsEnabled>\n" \ " <MemorySize>%lu</MemorySize>\n" \
" <MemorySize>%lu</MemorySize>\n" \ " </Jit>\n", \
" </Jit>\n", \ (nacp->jit_configuration.jit_configuration_flag & NacpJitConfigurationFlag_Enabled) ? "true" : "false", \
nacpGetJitConfigurationFlagString(nacp->jit_configuration.jit_configuration_flag), \ nacp->jit_configuration.memory_size)) goto end;
nacp->jit_configuration.memory_size)) goto end;
/* History. Unused but kept anyway. */ /* History. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <History />\n")) goto end; //if (!NACP_ADD_FMT_STR_T1(" <History />\n")) goto end;
/* RuntimeParameterDelivery. */ /* 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. */ /* RequiredAddOnContentsSet. */
for(i = 0, count = 0; i < 0x20; i++) for(i = 0; i < 0x20; i++)
{ {
NacpDescriptors *descriptor = &(raocsbd->descriptors[i]); NacpRequiredAddOnContentsSetDescriptor *descriptor = &(raocsbd->descriptors[i]);
if (!descriptor->index || !descriptor->continue_set) continue;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (descriptor->index)
" <RequiredAddOnContentsSet>\n" \ {
" <Index>%u</Index>\n" \ raocsbd_available = true;
" </RequiredAddOnContentsSet>\n", \ break;
descriptor->index)) goto end; }
count++; if (descriptor->flag != NacpRequiredAddOnContentsSetDescriptorFlag_Continue) break;
} }
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <RequiredAddOnContentsSet />\n")) goto end; if (raocsbd_available)
{
if (!NACP_ADD_FMT_STR_T1(" <RequiredAddOnContentsSet>\n")) goto end;
for(i = 0; i < 0x20; i++)
{
NacpRequiredAddOnContentsSetDescriptor *descriptor = &(raocsbd->descriptors[i]);
if (!descriptor->index) continue;
if (!NACP_ADD_FMT_STR_T1(" <Index>%u</Index>\n", descriptor->index)) goto end;
if (descriptor->flag != NacpRequiredAddOnContentsSetDescriptorFlag_Continue) break;
}
if (!NACP_ADD_FMT_STR_T1(" </RequiredAddOnContentsSet>\n")) goto end;
}
/* PlayReportPermission. */ /* PlayReportPermission. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!NACP_ADD_FMT_STR_T1(" <PlayReportPermission>\n" \
" <PlayReportPermission>\n" \ " <TargetMarketing>%s</TargetMarketing>\n" \
" <TargetMarketing>%s</TargetMarketing>\n" \ " </PlayReportPermission>\n", \
" </PlayReportPermission>\n", \ (nacp->play_report_permission & NacpPlayReportPermission_TargetMarketing) ? "Allow" : "Deny")) goto end;
nacpGetPlayReportPermissionString(nacp->play_report_permission))) goto end;
/* AccessibleLaunchRequiredVersion. */ /* 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 (nacp->accessible_launch_required_version.application_id[i])
{
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ alrv_available = true;
" <AccessibleLaunchRequiredVersion>\n" \ break;
" <ApplicationId>0x%016lx</ApplicationId>\n" \ }
" </AccessibleLaunchRequiredVersion>\n", \
nacp->accessible_launch_required_version.application_id[i])) goto end;
count++;
} }
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <AccessibleLaunchRequiredVersion />\n")) goto end; if (alrv_available)
{
if (!NACP_ADD_FMT_STR_T1(" <AccessibleLaunchRequiredVersion>\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(" <ApplicationId>0x%016lx</ApplicationId>\n", id)) goto end;
}
if (!NACP_ADD_FMT_STR_T1(" </AccessibleLaunchRequiredVersion>\n")) goto end;
} else {
if (!NACP_ADD_FMT_STR_T1(" <AccessibleLaunchRequiredVersion />\n")) goto end;
}
/* UndecidedParameter75b8b. */ /* 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. */ /* 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. */ /* FilterDescriptionFilePath and CompressionFileConfigurationFilePath. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <FilterDescriptionFilePath />\n")) goto end; /*if (!NACP_ADD_FMT_STR_T1(" <FilterDescriptionFilePath />\n" \
" <CompressionFileConfigurationFilePath />\n")) goto end;*/
if (!(success = utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, "</Application>"))) goto end; /* ContentsAvailabilityTransitionPolicy. */
if (!NACP_ADD_ENUM("ContentsAvailabilityTransitionPolicy", nacp->contents_availability_transition_policy, nacpGetContentsAvailabilityTransitionPolicyString)) goto end;
/* LimitedLicenseSettings. */
if (!NACP_ADD_FMT_STR_T1(" <LimitedLicenseSettings>\n" \
" <RuntimeUpgrade>%s</RuntimeUpgrade>\n" \
" <SupportingLimitedLicenses>\n" \
" <LimitedLicense>%s</LimitedLicense>\n" \
" </SupportingLimitedLicenses>\n" \
" </LimitedLicenseSettings>\n", \
nacpGetRuntimeUpgradeString(nacp->runtime_upgrade), \
(nacp->supporting_limited_licenses & NacpSupportingLimitedLicenses_Demo) ? "Demo" : "None")) goto end;
if (!(success = NACP_ADD_FMT_STR_T1("</Application>"))) goto end;
/* Update NACP context. */ /* Update NACP context. */
nacp_ctx->authoring_tool_xml = xml_buf; 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); 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) const char *nacpGetUndecidedParameter75b8bString(u8 undecided_parameter_75b8b)
{ {
return (undecided_parameter_75b8b < NacpUndecidedParameter75b8b_Count ? g_nacpUndecidedParameter75b8bStrings[undecided_parameter_75b8b] : g_unknownString); 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); 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) const char *nacpGetPlayLogQueryCapabilityString(u8 play_log_query_capability)
{ {
return (play_log_query_capability < NacpPlayLogQueryCapability_Count ? g_nacpPlayLogQueryCapabilityStrings[play_log_query_capability] : g_unknownString); 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); 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) const char *nacpGetCrashScreenshotForProdString(u8 crash_screenshot_for_prod)
{ {
return (crash_screenshot_for_prod < NacpCrashScreenshotForProd_Count ? g_nacpCrashScreenshotForProdStrings[crash_screenshot_for_prod] : g_unknownString); 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); 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) 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; 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 false;
} }
return (*value ? utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>%s</%s>\n", tag_name, value, 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));
utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s />\n", tag_name));
} }
static bool nacpAddEnumFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u8 value, NacpStringFunction str_func) 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 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; u8 flag_bitcount = 0, i = 0, count = 0;
const u8 *flag_u8 = (const u8*)flag; 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++) for(i = 0; i < max_flag_idx; i++)
{ {
if (!nacpCheckBitflagField(flag, flag_bitcount, i)) continue; 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++; count++;
} }
@ -1016,7 +1076,7 @@ static bool nacpAddBitflagFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_s
if (!count) empty_flag = true; 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; 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"); 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) 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"); 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) 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"); 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);
} }

View file

@ -159,7 +159,8 @@ bool utilsInitializeResources(const int program_argc, const char **program_argv)
LOG_MSG("Running under %s mode.", _utilsAppletModeCheck() ? "applet" : "title override"); LOG_MSG("Running under %s mode.", _utilsAppletModeCheck() ? "applet" : "title override");
/* Create output directories (SD card only). */ /* 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) if (g_appLaunchPath)
{ {

View file

@ -25,6 +25,11 @@
#include "program_info.h" #include "program_info.h"
#include "elf_symbol.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. */ /* Global variables. */
static const char *g_trueString = "True", *g_falseString = "False"; 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. */ /* Get SDK version and build type strings. */
if (!programInfoGetSdkVersionAndBuildTypeFromSdkNso(program_info_ctx, &sdk_version, &build_type)) goto end; if (!programInfoGetSdkVersionAndBuildTypeFromSdkNso(program_info_ctx, &sdk_version, &build_type)) goto end;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!PI_ADD_FMT_STR_T1("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" \
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" \ "<ProgramInfo>\n")) goto end;
"<ProgramInfo>\n")) goto end;
/* SdkVersion. */ /* SdkVersion. */
if (!programInfoAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SdkVersion", sdk_version)) goto end; if (!programInfoAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SdkVersion", sdk_version)) goto end;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!PI_ADD_FMT_STR_T1(" <ToolVersion />\n" /* Impossible to get. */ \
" <ToolVersion />\n" /* Impossible to get. */ \ " <NxAddonVersion>%s</NxAddonVersion>\n" \
" <NxAddonVersion>%s</NxAddonVersion>\n" \ " <PatchToolVersion />\n" /* Impossible to get. */ \
" <PatchToolVersion />\n" /* Impossible to get. */ \ " <BuildTarget>%u</BuildTarget>\n", \
" <BuildTarget>%u</BuildTarget>\n", \ sdk_version, \
sdk_version, \ is_64bit ? 64 : 32)) goto end;
is_64bit ? 64 : 32)) goto end;
/* BuildType. */ /* BuildType. */
if (!programInfoAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "BuildType", build_type)) goto end; if (!programInfoAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "BuildType", build_type)) goto end;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!PI_ADD_FMT_STR_T1(" <EnableDeadStrip />\n" /* Impossible to get. */ \
" <EnableDeadStrip />\n" /* Impossible to get. */ \ " <EnableDeadStripSpecified />\n" /* Impossible to get. */ \
" <EnableDeadStripSpecified />\n" /* Impossible to get. */ \ " <Desc>%s</Desc>\n" \
" <Desc>%s</Desc>\n" \ " <DescFileName />\n" /* Impossible to get. */ \
" <DescFileName />\n" /* Impossible to get. */ \ " <DescFlags>\n" \
" <DescFlags>\n" \ " <Production>%s</Production>\n" \
" <Production>%s</Production>\n" \ " <UnqualifiedApproval>%s</UnqualifiedApproval>\n" \
" <UnqualifiedApproval>%s</UnqualifiedApproval>\n" \ " </DescFlags>\n", \
" </DescFlags>\n", \ npdm_acid_b64, \
npdm_acid_b64, \ program_info_ctx->npdm_ctx.acid_header->flags.production ? g_trueString : g_falseString, \
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;
program_info_ctx->npdm_ctx.acid_header->flags.unqualified_approval ? g_trueString : g_falseString)) goto end;
/* MiddlewareList. */ /* MiddlewareList. */
if (!programInfoAddNsoApiListToAuthoringToolXml(&xml_buf, &xml_buf_size, program_info_ctx, "Middleware", "Module", "SDK MW")) goto end; 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. */ /* FsAccessControlData. */
if (!programInfoAddFsAccessControlDataToAuthoringToolXml(&xml_buf, &xml_buf_size, program_info_ctx)) goto end; if (!programInfoAddFsAccessControlDataToAuthoringToolXml(&xml_buf, &xml_buf_size, program_info_ctx)) goto end;
if (!(success = utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \ if (!(success = PI_ADD_FMT_STR_T1(" <EnableGlobalDestructor />\n" /* Impossible to get. */ \
" <EnableGlobalDestructor />\n" /* Impossible to get. */ \ " <EnableGlobalDestructorSpecified />\n" /* Impossible to get. */ \
" <EnableGlobalDestructorSpecified />\n" /* Impossible to get. */ \ " <IncludeNssFile />\n" /* Impossible to get. */ \
" <IncludeNssFile />\n" /* Impossible to get. */ \ " <IncludeNssFileSpecified />\n" /* Impossible to get. */ \
" <IncludeNssFileSpecified />\n" /* Impossible to get. */ \ " <History />\n" /* Impossible to get. */ \
" <History />\n" /* Impossible to get. */ \ " <TargetTriplet />\n" /* Impossible to get. */ \
" <TargetTriplet />\n" /* Impossible to get. */ \ "</ProgramInfo>"))) goto end;
"</ProgramInfo>"))) goto end;
/* Update ProgramInfo context. */ /* Update ProgramInfo context. */
program_info_ctx->authoring_tool_xml = xml_buf; 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. */ /* Append an empty XML element if no entries for this API list exist. */
if (!api_list_exists) 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; 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. */ /* Retrieve full API list. */
for(u32 i = 0; i < program_info_ctx->nso_count; i++) 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 (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, \ if (!PI_ADD_FMT_STR_T2(" <%s>\n" \
" <%s>\n" \ " <%sName>%s</%sName>\n" \
" <%sName>%s</%sName>\n" \ " <VenderName>%.*s</VenderName>\n" \
" <VenderName>%.*s</VenderName>\n" \ " <NsoName>%s</NsoName>\n" \
" <NsoName>%s</NsoName>\n" \ " </%s>\n", \
" </%s>\n", \ api_list_tag, \
api_list_tag, \ api_entry_prefix, sdk_entry_name, api_entry_prefix, \
api_entry_prefix, sdk_entry_name, api_entry_prefix, \ sdk_entry_vender_len, sdk_entry_vender, \
sdk_entry_vender_len, sdk_entry_vender, \ nso_ctx->nso_filename, \
nso_ctx->nso_filename, \ api_list_tag)) goto end;
api_list_tag)) goto end;
} }
j += strlen(sdk_entry); 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: end:
return success; return success;
@ -466,8 +466,7 @@ static bool programInfoAddStringFieldToAuthoringToolXml(char **xml_buf, u64 *xml
return false; return false;
} }
return ((value && *value) ? utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>%s</%s>\n", tag_name, value, 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));
utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s />\n", tag_name));
} }
static bool programInfoAddNsoSymbolsToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, ProgramInfoContext *program_info_ctx) 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++) for(u32 i = 0; i < program_info_ctx->nso_count; i++)
{ {
nso_ctx = &(program_info_ctx->nso_ctx[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 && \ 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_size) break; nso_ctx->rodata_dynsym_section && nso_ctx->rodata_dynsym_section_size) break;
nso_ctx = NULL; 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. */ /* Bail out if we couldn't find any valid symbols. */
if (!symbols_exist) goto end; if (!symbols_exist) goto end;
if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <UnresolvedApiList>\n")) goto end; if (!PI_ADD_FMT_STR_T2(" <UnresolvedApiList>\n")) goto end;
/* Parse ELF dynamic symbol table to retrieve the symbol strings. */ /* Parse ELF dynamic symbol table to retrieve the symbol strings. */
for(u64 i = 0; i < nso_ctx->rodata_dynsym_section_size; i += symbol_size) 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 (!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, \ if (!PI_ADD_FMT_STR_T2(" <UnresolvedApi>\n" \
" <UnresolvedApi>\n" \ " <ApiName>%s</ApiName>\n" \
" <ApiName>%s</ApiName>\n" \ " <NsoName>%s</NsoName>\n" \
" <NsoName>%s</NsoName>\n" \ " </UnresolvedApi>\n", \
" </UnresolvedApi>\n", \ symbol_str, \
symbol_str, \ nso_ctx->nso_filename)) goto end;
nso_ctx->nso_filename)) goto end;
} }
success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " </UnresolvedApiList>\n"); success = PI_ADD_FMT_STR_T2(" </UnresolvedApiList>\n");
end: end:
/* Append an empty XML element if no valid symbols exist. */ /* Append an empty XML element if no valid symbols exist. */
if (!success && (!nso_ctx || !symbols_exist)) success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <UnresolvedApiList />\n"); if (!success && (!nso_ctx || !symbols_exist)) success = PI_ADD_FMT_STR_T2(" <UnresolvedApiList />\n");
return success; 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. */ /* 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)); 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, " <FsAccessControlData>\n")) goto end; if (!PI_ADD_FMT_STR_T2(" <FsAccessControlData>\n")) goto end;
/* Append save data owner IDs. */ /* Append save data owner IDs. */
for(u32 i = 0; i < save_data_owner_block->save_data_owner_id_count; i++) for(u32 i = 0; i < save_data_owner_block->save_data_owner_id_count; i++)
{ {
if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, \ if (!PI_ADD_FMT_STR_T2(" <SaveDataOwnerIds>\n" \
" <SaveDataOwnerIds>\n" \ " <Accessibility>%s</Accessibility>\n" \
" <Accessibility>%s</Accessibility>\n" \ " <Id>0x%016lx</Id>\n" \
" <Id>0x%016lx</Id>\n" \ " </SaveDataOwnerIds>\n", \
" </SaveDataOwnerIds>\n", \ g_facAccessibilityStrings[save_data_owner_block->accessibility[i] & 0x3], \
g_facAccessibilityStrings[save_data_owner_block->accessibility[i] & 0x3], \ save_data_owner_ids[i])) goto end;
save_data_owner_ids[i])) goto end;
} }
success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " </FsAccessControlData>\n"); success = PI_ADD_FMT_STR_T2(" </FsAccessControlData>\n");
end: end:
/* Append an empty XML element if no FS access control data exists. */ /* Append an empty XML element if no FS access control data exists. */
if (!success && !sdo_data_available) success = utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <FsAccessControlData />\n"); if (!success && !sdo_data_available) success = PI_ADD_FMT_STR_T2(" <FsAccessControlData />\n");
return success; return success;
} }

View file

@ -24,9 +24,12 @@
#include <nxdt_utils.h> #include <nxdt_utils.h>
#include <borealis.hpp> #include <borealis.hpp>
#define FP_MASK 0xFFFFFFFFFF000000UL /* Helper macros. */
#define STACK_TRACE_SIZE 0x20
#define IS_HB_ADDR(x) (info.addr && info.size && (x) >= info.addr && (x) < (info.addr + info.size)) #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(). */ namespace i18n = brls::i18n; /* For getStr(). */
using namespace i18n::literals; /* For _i18n. */ using namespace i18n::literals; /* For _i18n. */
@ -168,45 +171,45 @@ extern "C" {
break; 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. */ /* 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++) for(size_t i = 0; i < MAX_ELEMENTS(ctx->cpu_gprs); i++)
{ {
u64 reg = ctx->cpu_gprs[i].x; u64 reg = ctx->cpu_gprs[i].x;
utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n X%02lu: 0x%lX", i, reg); EH_ADD_FMT_STR("\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); 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); EH_ADD_FMT_STR("\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); 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); EH_ADD_FMT_STR("\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); 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); EH_ADD_FMT_STR("\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); 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); EH_ADD_FMT_STR("\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); if (IS_HB_ADDR(ctx->pc.x)) EH_ADD_FMT_STR(" (BASE + 0x%lX)", ctx->pc.x - info.addr);
utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n"); EH_ADD_FMT_STR("\r\n");
/* Unwind stack. */ /* Unwind stack. */
if (nxdt::utils::UnwindStack(stack_trace, &stack_trace_size, STACK_TRACE_SIZE, ctx->fp.x)) if (nxdt::utils::UnwindStack(stack_trace, &stack_trace_size, STACK_TRACE_SIZE, ctx->fp.x))
{ {
/* Log stack trace. */ /* 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++) for(u32 i = 0; i < stack_trace_size; i++)
{ {
u64 addr = stack_trace[i]; u64 addr = stack_trace[i];
utilsAppendFormattedStringToBuffer(&exception_str, &exception_str_size, "\r\n [%02u]: 0x%lX", stack_trace_size - i - 1, addr); EH_ADD_FMT_STR("\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); 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. */ /* Write log string. */
@ -216,7 +219,8 @@ extern "C" {
if (exception_str) free(exception_str); if (exception_str) free(exception_str);
/* Abort program execution. */ /* 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) : ".")); 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); nxdt::utils::AbortProgramExecution(crash_str);
} }

View file

@ -1,11 +1,11 @@
todo: todo:
nca: support for sparse sections
nca: support for compressed fs sections
log: verbosity levels log: verbosity levels
log: nxlink output for advanced users 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 title lookup? (filters, patches / aoc, etc.)
title: more functions for content lookup? (based on id) 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 title: parse the update partition from gamecards (if available) to generate ncmcontentinfo data for all update titles