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

NACP parsing (part 2).

NeighborDetectionClientConfiguration and RequiredAddOnContentsSetBinaryDescriptor haven't been implemented (yet).
This commit is contained in:
Pablo Curiel 2020-10-04 03:05:05 -04:00
parent d385d40862
commit 1e41148c02
5 changed files with 616 additions and 108 deletions

View file

@ -232,7 +232,7 @@ int main(int argc, char *argv[])
fclose(xml_fd);
}
} else {
consolePrint("cnmt initialize ctx failed\n");
consolePrint("cnmt xml failed\n");
}
out2:

View file

@ -0,0 +1,256 @@
/*
* main.c
*
* Copyright (c) 2020, DarkMatterCore <pabloacurielz@gmail.com>.
*
* This file is part of nxdumptool (https://github.com/DarkMatterCore/nxdumptool).
*
* nxdumptool is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* nxdumptool is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "utils.h"
#include "gamecard.h"
#include "title.h"
#include "nacp.h"
static void consolePrint(const char *text, ...)
{
va_list v;
va_start(v, text);
vfprintf(stdout, text, v);
va_end(v);
consoleUpdate(NULL);
}
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
int ret = 0;
LOGFILE(APP_TITLE " starting.");
consoleInit(NULL);
consolePrint("initializing...\n");
if (!utilsInitializeResources())
{
ret = -1;
goto out;
}
u32 app_count = 0;
TitleApplicationMetadata **app_metadata = NULL;
TitleUserApplicationData user_app_data = {0};
u32 selected_idx = 0, page_size = 30, scroll = 0;
bool exit_prompt = true;
NcaContext *nca_ctx = NULL;
Ticket tik = {0};
NacpContext nacp_ctx = {0};
app_metadata = titleGetApplicationMetadataEntries(false, &app_count);
if (!app_metadata || !app_count)
{
consolePrint("app metadata failed\n");
goto out2;
}
consolePrint("app metadata succeeded\n");
utilsSleep(1);
while(true)
{
consoleClear();
printf("select an user application to generate a nacp xml for.\npress b to exit.\n\n");
printf("title: %u / %u\n\n", selected_idx + 1, app_count);
for(u32 i = scroll; i < app_count; i++)
{
if (i >= (scroll + page_size)) break;
printf("%s%016lX - %s\n", i == selected_idx ? " -> " : " ", app_metadata[i]->title_id, app_metadata[i]->lang_entry.name);
}
printf("\n");
consoleUpdate(NULL);
u64 btn_down = 0, btn_held = 0;
while(true)
{
hidScanInput();
btn_down = utilsHidKeysAllDown();
btn_held = utilsHidKeysAllHeld();
if (btn_down || btn_held) break;
if (titleIsGameCardInfoUpdated())
{
free(app_metadata);
app_metadata = titleGetApplicationMetadataEntries(false, &app_count);
if (!app_metadata)
{
consolePrint("\napp metadata failed\n");
goto out2;
}
selected_idx = scroll = 0;
break;
}
}
if (btn_down & KEY_A)
{
if (!titleGetUserApplicationData(app_metadata[selected_idx]->title_id, &user_app_data) || !user_app_data.app_info)
{
consolePrint("\nthe selected title doesn't have available base content.\n");
utilsSleep(3);
continue;
}
break;
} else
if ((btn_down & KEY_DDOWN) || (btn_held & (KEY_LSTICK_DOWN | KEY_RSTICK_DOWN)))
{
selected_idx++;
if (selected_idx >= app_count)
{
if (btn_down & KEY_DDOWN)
{
selected_idx = scroll = 0;
} else {
selected_idx = (app_count - 1);
}
} else
if (selected_idx >= (scroll + (page_size / 2)) && app_count > (scroll + page_size))
{
scroll++;
}
} else
if ((btn_down & KEY_DUP) || (btn_held & (KEY_LSTICK_UP | KEY_RSTICK_UP)))
{
selected_idx--;
if (selected_idx == UINT32_MAX)
{
if (btn_down & KEY_DUP)
{
selected_idx = (app_count - 1);
scroll = (app_count >= page_size ? (app_count - page_size) : 0);
} else {
selected_idx = 0;
}
} else
if (selected_idx < (scroll + (page_size / 2)) && scroll > 0)
{
scroll--;
}
} else
if (btn_down & KEY_B)
{
exit_prompt = false;
goto out2;
}
if (btn_held & (KEY_LSTICK_DOWN | KEY_RSTICK_DOWN | KEY_LSTICK_UP | KEY_RSTICK_UP)) svcSleepThread(50000000); // 50 ms
}
consoleClear();
consolePrint("selected title:\n%s (%016lX)\n\n", app_metadata[selected_idx]->lang_entry.name, app_metadata[selected_idx]->title_id);
nca_ctx = calloc(1, sizeof(NcaContext));
if (!nca_ctx)
{
consolePrint("nca ctx calloc failed\n");
goto out2;
}
consolePrint("nca ctx calloc succeeded\n");
if (!ncaInitializeContext(nca_ctx, user_app_data.app_info->storage_id, (user_app_data.app_info->storage_id == NcmStorageId_GameCard ? GameCardHashFileSystemPartitionType_Secure : 0), \
titleGetContentInfoByTypeAndIdOffset(user_app_data.app_info, NcmContentType_Control, 0), &tik))
{
consolePrint("Control nca initialize ctx failed\n");
goto out2;
}
consolePrint("Control nca initialize ctx succeeded\n");
if (!nacpInitializeContext(&nacp_ctx, nca_ctx))
{
consolePrint("nacp initialize ctx failed\n");
goto out2;
}
consolePrint("nacp initialize ctx succeeded\n");
if (nacpGenerateAuthoringToolXml(&nacp_ctx))
{
consolePrint("nacp xml succeeded\n");
FILE *xml_fd = NULL;
char path[FS_MAX_PATH] = {0};
sprintf(path, "sdmc:/%s.nacp.xml", nca_ctx->content_id_str);
xml_fd = fopen(path, "wb");
if (xml_fd)
{
fwrite(nacp_ctx.authoring_tool_xml, 1, nacp_ctx.authoring_tool_xml_size, xml_fd);
fclose(xml_fd);
xml_fd = NULL;
}
for(u8 i = 0; i < nacp_ctx.icon_count; i++)
{
NacpIconContext *icon_ctx = &(nacp_ctx.icon_ctx[i]);
sprintf(path, "sdmc:/%s.nx.%s.jpg", nca_ctx->content_id_str, nacpGetLanguageString(icon_ctx->language));
xml_fd = fopen(path, "wb");
if (xml_fd)
{
fwrite(icon_ctx->icon_data, 1, icon_ctx->icon_size, xml_fd);
fclose(xml_fd);
xml_fd = NULL;
}
}
} else {
consolePrint("nacp xml failed\n");
}
out2:
if (exit_prompt)
{
consolePrint("press any button to exit\n");
utilsWaitForButtonPress(KEY_NONE);
}
nacpFreeContext(&nacp_ctx);
if (nca_ctx) free(nca_ctx);
if (app_metadata) free(app_metadata);
out:
utilsCloseResources();
consoleExit(NULL);
return ret;
}

View file

@ -113,34 +113,80 @@ static const char *g_nacpRatingAgeOrganizationStrings[] = {
[NacpRatingAgeOrganization_IARCGeneric] = "IARCGeneric"
};
static const char *g_nacpLogoTypeStrings[] = {
[NacpLogoType_LicensedByNintendo] = "LicensedByNintendo",
[NacpLogoType_DistributedByNintendo] = "DistributedByNintendo",
[NacpLogoType_Nintendo] = "Nintendo"
};
static const char *g_nacpLogoHandlingStrings[] = {
[NacpLogoHandling_Auto] = "Auto",
[NacpLogoHandling_Manual] = "Manual"
};
static const char *g_nacpRuntimeAddOnContentInstallStrings[] = {
[NacpRuntimeAddOnContentInstall_Deny] = "Deny",
[NacpRuntimeAddOnContentInstall_AllowAppend] = "AllowAppend",
[NacpRuntimeAddOnContentInstall_AllowAppendButDontDownloadWhenUsingNetwork] = "AllowAppendButDontDownloadWhenUsingNetwork"
};
static const char *g_nacpNacpRuntimeParameterDeliveryStrings[] = {
[NacpRuntimeParameterDelivery_Always] = "Always",
[NacpRuntimeParameterDelivery_AlwaysIfUserStateMatched] = "AlwaysIfUserStateMatched",
[NacpRuntimeParameterDelivery_OnRestart] = "OnRestart"
};
static const char *g_nacpCrashReportStrings[] = {
[NacpCrashReport_Deny] = "Deny",
[NacpCrashReport_Allow] = "Allow"
};
static const char *g_nacpHdcpStrings[] = {
[NacpHdcp_None] = "None",
[NacpHdcp_Required] = "Required"
};
static const char *g_nacpStartupUserAccountOptionStrings[] = {
[NacpStartupUserAccountOption_IsOptional] = "IsOptional"
};
static const char *g_nacpRepairStrings[] = {
[NacpRepair_SuppressGameCardAccess] = "SuppressGameCardAccess"
};
static const char *g_nacpRequiredNetworkServiceLicenseOnLaunchStrings[] = {
[NacpRequiredNetworkServiceLicenseOnLaunch_Common] = "RequiredNetworkServiceLicenseOnLaunch"
};
static const char *g_nacpJitConfigurationFlagStrings[] = {
[NacpJitConfigurationFlag_None] = "None",
[NacpJitConfigurationFlag_Enabled] = "Enabled"
};
static const char *g_nacpPlayReportPermissionStrings[] = {
[NacpPlayReportPermission_None] = "None",
[NacpPlayReportPermission_TargetMarketing] = "TargetMarketing"
};
static const char *g_nacpCrashScreenshotForProdStrings[] = {
[NacpCrashScreenshotForProd_Deny] = "Deny",
[NacpCrashScreenshotForProd_Allow] = "Allow"
};
static const char *g_nacpCrashScreenshotForDevStrings[] = {
[NacpCrashScreenshotForDev_Deny] = "Deny",
[NacpCrashScreenshotForDev_Allow] = "Allow"
};
/* 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 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);
static bool nacpAddU64FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u64 value);
static bool nacpAddU16FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u16 value, bool hex);
bool nacpInitializeContext(NacpContext *out, NcaContext *nca_ctx)
{
@ -212,7 +258,7 @@ bool nacpInitializeContext(NacpContext *out, NcaContext *nca_ctx)
NacpIconContext *icon_ctx = NULL;
/* Check if the current language is supported. */
if (!nacpCheckBitflagField(&(out->data->supported_language_flag), i, NacpLanguage_Count)) continue;
if (!nacpCheckBitflagField(&(out->data->supported_language_flag), sizeof(out->data->supported_language_flag) * 8, i)) continue;
/* Get language string. */
language_str = nacpGetLanguageString(i);
@ -282,9 +328,14 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx)
}
_NacpStruct *nacp = nacp_ctx->data;
u8 i = 0, count = 0;
char *xml_buf = NULL;
u64 xml_buf_size = 0;
u8 icon_hash[SHA256_HASH_SIZE] = {0};
char icon_hash_str[SHA256_HASH_SIZE + 1] = {0};
bool success = false;
/* Free AuthoringTool-like XML data if needed. */
@ -329,21 +380,22 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx)
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "AddOnContentRegistrationType", nacp->add_on_content_registration_type, &nacpGetAddOnContentRegistrationTypeString)) goto end;
/* AttributeFlag. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Attribute", &(nacp->attribute_flag), NacpAttribute_Count, &nacpGetAttributeString)) goto end;
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Attribute", &(nacp->attribute_flag), sizeof(nacp->attribute_flag), NacpAttribute_Count, &nacpGetAttributeString)) goto end;
/* SupportedLanguageFlag. */
/* SupportedLanguage. */
/* Even though this is a bitflag field, it doesn't follow the same format as the rest. */
for(i = 0, count = 0; i < NacpLanguage_Count; i++)
{
if (!nacpCheckBitflagField(&(nacp->supported_language_flag), i, NacpLanguage_Count)) continue;
if (!nacpCheckBitflagField(&(nacp->supported_language_flag), sizeof(nacp->supported_language_flag) * 8, i)) continue;
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SupportedLanguage", i, &nacpGetLanguageString)) goto end;
count++;
}
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <SupportedLanguage />\n")) goto end;
/* ParentalControlFlag. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ParentalControl", &(nacp->parental_control_flag), NacpParentalControl_Count, &nacpGetParentalControlString)) goto end;
/* ParentalControl. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ParentalControl", &(nacp->parental_control_flag), sizeof(nacp->parental_control_flag), NacpParentalControl_Count, \
&nacpGetParentalControlString)) goto end;
/* Screenshot. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Screenshot", nacp->screenshot, &nacpGetScreenshotString)) goto end;
@ -416,14 +468,127 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx)
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <LocalCommunicationId />\n")) goto end;
/* LogoType. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "LogoType", nacp->logo_type, &nacpGetLogoTypeString)) goto end;
/* LogoHandling. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "LogoHandling", nacp->logo_handling, &nacpGetLogoHandlingString)) goto end;
/* RuntimeAddOnContentInstall. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RuntimeAddOnContentInstall", nacp->runtime_add_on_content_install, &nacpGetRuntimeAddOnContentInstallString)) goto end;
/* RuntimeParameterDelivery. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RuntimeParameterDelivery", nacp->runtime_parameter_delivery, &nacpGetRuntimeParameterDeliveryString)) goto end;
/* CrashReport. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CrashReport", nacp->crash_report, &nacpGetCrashReportString)) goto end;
/* Hdcp. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Hdcp", nacp->hdcp, &nacpGetHdcpString)) goto end;
/* SeedForPseudoDeviceId. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SeedForPseudoDeviceId", nacp->seed_for_pseudo_device_id)) goto end;
/* BcatPassphrase. */
if (!nacpAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "BcatPassphrase", nacp->bcat_passphrase)) goto end;
/* StartupUserAccountOption. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "StartupUserAccountOption", &(nacp->startup_user_account_option_flag), sizeof(nacp->startup_user_account_option_flag), \
NacpStartupUserAccountOption_Count, &nacpGetStartupUserAccountOptionString)) goto end;
/* UserAccountSaveDataSizeMax. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataSizeMax", nacp->user_account_save_data_size_max)) goto end;
/* UserAccountSaveDataJournalSizeMax. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataJournalSizeMax", nacp->user_account_save_data_journal_size_max)) goto end;
/* DeviceSaveDataSizeMax. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataSizeMax", nacp->device_save_data_size_max)) goto end;
/* DeviceSaveDataJournalSizeMax. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataJournalSizeMax", nacp->device_save_data_journal_size_max)) goto end;
/* TemporaryStorageSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "TemporaryStorageSize", nacp->temporary_storage_size)) goto end;
/* CacheStorageSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageSize", nacp->cache_storage_size)) goto end;
/* CacheStorageJournalSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageJournalSize", nacp->cache_storage_journal_size)) goto end;
/* CacheStorageDataAndJournalSizeMax. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageDataAndJournalSizeMax", nacp->cache_storage_data_and_journal_size_max)) goto end;
/* CacheStorageIndexMax. */
if (!nacpAddU16FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageIndexMax", nacp->cache_storage_index_max, true)) goto end;
/* PlayLogQueryableApplicationId. */
for(i = 0, count = 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])) goto end;
count++;
}
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <PlayLogQueryableApplicationId />\n")) goto end;
/* Repair. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "Repair", &(nacp->repair_flag), sizeof(nacp->repair_flag), NacpRepair_Count, &nacpGetRepairString)) goto end;
/* ProgramIndex. */
if (!nacpAddU16FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ProgramIndex", nacp->program_index, false)) goto end;
/* RequiredNetworkServiceLicenseOnLaunch. */
if (!nacpAddBitflagFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "RequiredNetworkServiceLicenseOnLaunch", &(nacp->required_network_service_license_on_launch_flag), \
sizeof(nacp->required_network_service_license_on_launch_flag), NacpRequiredNetworkServiceLicenseOnLaunch_Count, &nacpGetRequiredNetworkServiceLicenseOnLaunchString)) goto end;
/* TO DO: add NacpNeighborDetectionClientConfiguration. */
/* JitConfiguration. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
" <JitConfiguration>\n" \
" <IsEnabled>%s</IsEnabled>\n" \
" <MemorySize>0x%016lx</MemorySize>\n" \
" </JitConfiguration>\n", \
nacpGetJitConfigurationFlagString(nacp->jit_configuration.jit_configuration_flag),
nacp->jit_configuration.memory_size)) goto end;
/* TO DO: add NacpRequiredAddOnContentsSetBinaryDescriptor. */
/* PlayReportPermission. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "PlayReportPermission", nacp->play_report_permission, &nacpGetPlayReportPermissionString)) goto end;
/* CrashScreenshotForProd. */
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "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;
/* Icon. */
for(i = 0, count = 0; i < nacp_ctx->icon_count; i++)
{
NacpIconContext *icon_ctx = &(nacp_ctx->icon_ctx[i]);
/* Calculate icon hash. */
sha256CalculateHash(icon_hash, icon_ctx->icon_data, icon_ctx->icon_size);
/* Generate icon hash string. */
utilsGenerateHexStringFromData(icon_hash_str, SHA256_HASH_SIZE + 1, icon_hash, SHA256_HASH_SIZE / 2);
/* Add XML element. */
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
" <Icon>\n" \
" <Language>%s</Language>\n" \
" <NxIconHash>%s</NxIconHash>\n" \
" </Icon>\n", \
nacpGetLanguageString(icon_ctx->language), \
icon_hash_str)) goto end;
count++;
}
if (!count && !utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, " <Icon />\n")) goto end;
if (!(success = utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, "</Application>"))) goto end;
@ -496,52 +661,133 @@ const char *nacpGetRatingAgeOrganizationString(u8 rating_age_organization)
return (rating_age_organization < NacpRatingAgeOrganization_Count ? g_nacpRatingAgeOrganizationStrings[rating_age_organization] : g_unknownString);
}
const char *nacpGetLogoTypeString(u8 logo_type)
{
return (logo_type < NacpLogoType_Count ? g_nacpLogoTypeStrings[logo_type] : g_unknownString);
}
const char *nacpGetLogoHandlingString(u8 logo_handling)
{
return (logo_handling < NacpLogoHandling_Count ? g_nacpLogoHandlingStrings[logo_handling] : g_unknownString);
}
const char *nacpGetRuntimeAddOnContentInstallString(u8 runtime_add_on_content_install)
{
return (runtime_add_on_content_install < NacpRuntimeAddOnContentInstall_Count ? g_nacpRuntimeAddOnContentInstallStrings[runtime_add_on_content_install] : g_unknownString);
}
const char *nacpGetRuntimeParameterDeliveryString(u8 runtime_parameter_delivery)
{
return (runtime_parameter_delivery < NacpRuntimeParameterDelivery_Count ? g_nacpNacpRuntimeParameterDeliveryStrings[runtime_parameter_delivery] : g_unknownString);
}
const char *nacpGetCrashReportString(u8 crash_report)
{
return (crash_report < NacpCrashReport_Count ? g_nacpCrashReportStrings[crash_report] : g_unknownString);
}
const char *nacpGetHdcpString(u8 hdcp)
{
return (hdcp < NacpHdcp_Count ? g_nacpHdcpStrings[hdcp] : g_unknownString);
}
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 *nacpGetRepairString(u8 repair)
{
return (repair < NacpRepair_Count ? g_nacpRepairStrings[repair] : g_unknownString);
}
const char *nacpGetRequiredNetworkServiceLicenseOnLaunchString(u8 required_network_service_license_on_launch)
{
return (required_network_service_license_on_launch < NacpRequiredNetworkServiceLicenseOnLaunch_Count ? \
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);
}
const char *nacpGetCrashScreenshotForDevString(u8 crash_screenshot_for_dev)
{
return (crash_screenshot_for_dev < NacpCrashScreenshotForDev_Count ? g_nacpCrashScreenshotForDevStrings[crash_screenshot_for_dev] : 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;
const u8 *flag_u8 = (const u8*)flag;
u8 byte_idx = (idx >> 3);
u8 bitmask = BIT(idx - ALIGN_DOWN(idx, 8));
return (flag_u8[byte_idx] & bitmask);
}
static bool nacpAddStringFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, const char *value)
{
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name) || !value) return false;
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name) || !value)
{
LOGFILE("Invalid parameters!");
return false;
}
return (strlen(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));
}
static bool nacpAddEnumFieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u8 value, NacpStringFunction str_func)
{
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name) || !str_func) return false;
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name) || !str_func)
{
LOGFILE("Invalid parameters!");
return false;
}
return utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%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 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)
{
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name) || !flag || max_flag_idx >= 0x20 || !str_func) return false;
u8 flag_bitcount = 0, i = 0, count = 0;
const u8 *flag_u8 = (const u8*)flag;
bool success = false, empty_flag = true;
u8 i = 0, count = 0;
bool success = false;
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name) || !flag || !flag_width || (flag_width > 1 && !IS_POWER_OF_TWO(flag_width)) || flag_width > 0x10 || \
(flag_bitcount = (flag_width * 8)) < max_flag_idx || !str_func)
{
LOGFILE("Invalid parameters!");
return false;
}
if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>", tag_name)) goto end;
if (*((u32*)flag))
for(i = 0; i < flag_width; i++)
{
if (flag_u8[i])
{
empty_flag = false;
break;
}
}
if (!empty_flag)
{
for(i = 0; i < max_flag_idx; i++)
{
if (!nacpCheckBitflagField(flag, i, max_flag_idx)) continue;
if (!nacpCheckBitflagField(flag, flag_bitcount, i)) continue;
if (count && !utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, ",")) goto end;
if (!utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, "%s", str_func(i))) goto end;
count++;
@ -560,6 +806,23 @@ end:
static bool nacpAddU64FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u64 value)
{
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name)) return false;
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name))
{
LOGFILE("Invalid parameters!");
return false;
}
return utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>0x%016lx</%s>\n", tag_name, value, tag_name);
}
static bool nacpAddU16FieldToAuthoringToolXml(char **xml_buf, u64 *xml_buf_size, const char *tag_name, u16 value, bool hex)
{
if (!xml_buf || !xml_buf_size || !tag_name || !strlen(tag_name))
{
LOGFILE("Invalid parameters!");
return false;
}
return (hex ? utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>0x%04x</%s>\n", tag_name, value, tag_name) : \
utilsAppendFormattedStringToBuffer(xml_buf, xml_buf_size, " <%s>%u</%s>\n", tag_name, value, tag_name));
}

View file

@ -165,7 +165,7 @@ typedef enum {
NacpRatingAgeOrganization_ACB = 10,
NacpRatingAgeOrganization_OFLC = 11,
NacpRatingAgeOrganization_IARCGeneric = 12,
NacpRatingAgeOrganization_Count = 13
NacpRatingAgeOrganization_Count = 13 ///< Not a real value.
} NacpRatingAgeOrganization;
typedef struct {
@ -188,52 +188,77 @@ typedef struct {
typedef enum {
NacpLogoType_LicensedByNintendo = 0,
NacpLogoType_DistributedByNintendo = 1, ///< Removed.
NacpLogoType_Nintendo = 2
NacpLogoType_Nintendo = 2,
NacpLogoType_Count = 3 ///< Not a real value.
} NacpLogoType;
typedef enum {
NacpLogoHandling_Auto = 0,
NacpLogoHandling_Manual = 1
NacpLogoHandling_Manual = 1,
NacpLogoHandling_Count = 2 ///< Not a real value.
} NacpLogoHandling;
typedef enum {
NacpRuntimeAddOnContentInstall_Deny = 0,
NacpRuntimeAddOnContentInstall_AllowAppend = 1,
NacpRuntimeAddOnContentInstall_AllowAppendButDontDownloadWhenUsingNetwork = 2
NacpRuntimeAddOnContentInstall_AllowAppendButDontDownloadWhenUsingNetwork = 2,
NacpRuntimeAddOnContentInstall_Count = 3 ///< Not a real value.
} NacpRuntimeAddOnContentInstall;
typedef enum {
NacpRuntimeParameterDelivery_Always = 0,
NacpRuntimeParameterDelivery_AlwaysIfUserStateMatched = 1,
NacpRuntimeParameterDelivery_OnRestart = 2
NacpRuntimeParameterDelivery_OnRestart = 2,
NacpRuntimeParameterDelivery_Count = 3 ///< Not a real value.
} NacpRuntimeParameterDelivery;
typedef enum {
NacpCrashReport_Deny = 0,
NacpCrashReport_Allow = 1
NacpCrashReport_Allow = 1,
NacpCrashReport_Count = 2 ///< Not a real value.
} NacpCrashReport;
typedef enum {
NacpHdcp_None = 0,
NacpHdcp_Required = 1
NacpHdcp_Required = 1,
NacpHdcp_Count = 2 ///< Not a real value.
} NacpHdcp;
typedef struct {
u8 NacpStartupUserAccountOption_IsOptional : 1;
u8 NacpStartupUserAccountOption_Reserved : 7;
/// Indexes used to access NACP startup user account option info.
typedef enum {
NacpStartupUserAccountOption_IsOptional = 0,
NacpStartupUserAccountOption_Count = 1 ///< Not a real value.
} NacpStartupUserAccountOption;
typedef struct {
u8 NacpStartupUserAccountOptionFlag_IsOptional : 1;
u8 NacpStartupUserAccountOptionFlag_Reserved : 7;
} NacpStartupUserAccountOptionFlag;
typedef enum {
NacpPlayLogQueryCapability_None = 0,
NacpPlayLogQueryCapability_WhiteList = 1,
NacpPlayLogQueryCapability_All = 2
NacpPlayLogQueryCapability_All = 2,
NacpPlayLogQueryCapability_Count = 3 ///< Not a real value.
} NacpPlayLogQueryCapability;
/// Indexes used to access NACP repair info.
typedef enum {
NacpRepair_SuppressGameCardAccess = 0,
NacpRepair_Count = 1 ///< Not a real value.
} NacpRepair;
typedef struct {
u8 NacpRepairFlag_SuppressGameCardAccess : 1;
u8 NacpRepairFlag_Reserved : 7;
} NacpRepairFlag;
/// Indexes used to access NACP required network service license on launch info.
typedef enum {
NacpRequiredNetworkServiceLicenseOnLaunch_Common = 0,
NacpRequiredNetworkServiceLicenseOnLaunch_Count = 1 ///< Not a real value.
} NacpRequiredNetworkServiceLicenseOnLaunch;
typedef struct {
u8 NacpRequiredNetworkServiceLicenseOnLaunchFlag_Common : 1;
u8 NacpRequiredNetworkServiceLicenseOnLaunchFlag_Reserved : 7;
@ -241,7 +266,8 @@ typedef struct {
typedef enum {
NacpJitConfigurationFlag_None = 0,
NacpJitConfigurationFlag_Enabled = 1
NacpJitConfigurationFlag_Enabled = 1,
NacpJitConfigurationFlag_Count = 2 ///< Not a real value.
} NacpJitConfigurationFlag;
typedef struct {
@ -251,7 +277,7 @@ typedef struct {
typedef struct {
u16 NacpDescriptors_Index : 15;
u16 NacpDescriptors_ContinueSet : 1; ///< Not given a name by Nintendo.
u16 NacpDescriptors_ContinueSet : 1; ///< Called "flag" by Nintendo.
} NacpDescriptors;
typedef struct {
@ -260,17 +286,20 @@ typedef struct {
typedef enum {
NacpPlayReportPermission_None = 0,
NacpPlayReportPermission_TargetMarketing = 1
NacpPlayReportPermission_TargetMarketing = 1,
NacpPlayReportPermission_Count = 2 ///< Not a real value.
} NacpPlayReportPermission;
typedef enum {
NacpCrashScreenshotForProd_Deny = 0,
NacpCrashScreenshotForProd_Allow = 1
NacpCrashScreenshotForProd_Allow = 1,
NacpCrashScreenshotForProd_Count = 2 ///< Not a real value.
} NacpCrashScreenshotForProd;
typedef enum {
NacpCrashScreenshotForDev_Deny = 0,
NacpCrashScreenshotForDev_Allow = 1
NacpCrashScreenshotForDev_Allow = 1,
NacpCrashScreenshotForDev_Count = 2 ///< Not a real value.
} NacpCrashScreenshotForDev;
typedef struct {
@ -307,7 +336,7 @@ typedef struct {
u8 hdcp; ///< NacpHdcp.
u64 seed_for_pseudo_device_id;
char bcat_passphrase[0x41];
NacpStartupUserAccountOption startup_user_account_option;
NacpStartupUserAccountOptionFlag startup_user_account_option_flag;
u8 reserved_2[0x6];
u64 user_account_save_data_size_max;
u64 user_account_save_data_journal_size_max;
@ -348,7 +377,7 @@ typedef struct {
///< Bear in mind that generating a patch modifies the NCA context.
_NacpStruct *data; ///< Pointer to a dynamically allocated buffer that holds the full NACP.
u8 data_hash[SHA256_HASH_SIZE]; ///< SHA-256 checksum calculated over the whole NACP. Used to determine if NcaHierarchicalSha256Patch generation is truly needed.
u32 icon_count; ///< NACP icon count. May be zero if no icons are available.
u8 icon_count; ///< NACP icon count. May be zero if no icons are available.
NacpIconContext *icon_ctx; ///< Pointer to a dynamically allocated buffer that holds 'icon_count' NACP icon contexts. May be NULL if no icons are available.
char *authoring_tool_xml; ///< Pointer to a dynamically allocated, NULL-terminated buffer that holds AuthoringTool-like XML data.
///< This is always NULL unless nacpGenerateAuthoringToolXml() is used on this NacpContext.
@ -363,68 +392,32 @@ bool nacpInitializeContext(NacpContext *out, NcaContext *nca_ctx);
/// If the function succeeds, XML data and size will get saved to the 'authoring_tool_xml' and 'authoring_tool_xml_size' members from the NacpContext.
bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx);
/// Returns a pointer to a string holding the name of the provided NacpLanguage value. Returns "Unknown" if the provided value is invalid.
/// These functions return pointers to string representations of the input value.
/// If the provided value is invalid, "Unknown" is returned.
const char *nacpGetLanguageString(u8 language);
/// Returns a pointer to a string holding the name of the provided NacpStartupUserAccount value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetStartupUserAccountString(u8 startup_user_account);
/// Returns a pointer to a string holding the name of the provided NacpUserAccountSwitchLock value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetUserAccountSwitchLockString(u8 user_account_switch_lock);
/// Returns a pointer to a string holding the name of the provided NacpAddOnContentRegistrationType value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetAddOnContentRegistrationTypeString(u8 add_on_content_registration_type);
/// Returns a pointer to a string holding the name of the provided NacpAttribute value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetAttributeString(u8 attribute);
/// Returns a pointer to a string holding the name of the provided NacpParentalControl value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetParentalControlString(u8 parental_control);
/// Returns a pointer to a string holding the name of the provided NacpScreenshot value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetScreenshotString(u8 screenshot);
/// Returns a pointer to a string holding the name of the provided NacpVideoCapture value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetVideoCaptureString(u8 video_capture);
/// Returns a pointer to a string holding the name of the provided NacpDataLossConfirmation value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetDataLossConfirmationString(u8 data_loss_confirmation);
/// Returns a pointer to a string holding the name of the provided NacpPlayLogPolicy value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetPlayLogPolicyString(u8 play_log_policy);
/// Returns a pointer to a string holding the name of the provided NacpRatingAgeOrganization value. Returns "Unknown" if the provided value is invalid.
const char *nacpGetRatingAgeOrganizationString(u8 rating_age_organization);
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 *nacpGetCrashReportString(u8 crash_report);
const char *nacpGetHdcpString(u8 hdcp);
const char *nacpGetStartupUserAccountOptionString(u8 startup_user_account_option);
const char *nacpGetRepairString(u8 repair);
const char *nacpGetRequiredNetworkServiceLicenseOnLaunchString(u8 required_network_service_license_on_launch);
const char *nacpGetJitConfigurationFlagString(u64 jig_configuration_flag);
const char *nacpGetPlayReportPermissionString(u8 play_report_permission);
const char *nacpGetCrashScreenshotForProdString(u8 crash_screenshot_for_prod);
const char *nacpGetCrashScreenshotForDevString(u8 crash_screenshot_for_dev);
/// Helper inline functions.
@ -438,7 +431,7 @@ NX_INLINE void nacpFreeContext(NacpContext *nacp_ctx)
if (nacp_ctx->icon_ctx)
{
for(u32 i = 0; i < nacp_ctx->icon_count; i++)
for(u8 i = 0; i < nacp_ctx->icon_count; i++)
{
if (nacp_ctx->icon_ctx[i].icon_data) free(nacp_ctx->icon_ctx[i].icon_data);
}
@ -459,7 +452,7 @@ NX_INLINE bool nacpIsValidContext(NacpContext *nacp_ctx)
{
if (!nacp_ctx || !nacp_ctx->nca_ctx || !nacp_ctx->romfs_file_entry || !nacp_ctx->data || (!nacp_ctx->icon_count && nacp_ctx->icon_ctx) || (nacp_ctx->icon_count && !nacp_ctx->icon_ctx)) return false;
for(u32 i = 0; i < nacp_ctx->icon_count; i++)
for(u8 i = 0; i < nacp_ctx->icon_count; i++)
{
if (!nacpIsValidIconContext(&(nacp_ctx->icon_ctx[i]))) return false;
}
@ -480,9 +473,4 @@ NX_INLINE bool nacpGenerateNcaPatch(NacpContext *nacp_ctx)
return (nacpIsValidContext(nacp_ctx) && romfsGenerateFileEntryPatch(&(nacp_ctx->romfs_ctx), nacp_ctx->romfs_file_entry, nacp_ctx->data, sizeof(_NacpStruct), 0, &(nacp_ctx->nca_patch)));
}
NX_INLINE bool nacpCheckBitflagField(const void *flag, u8 idx, u8 max_flag_idx)
{
return (flag && idx < 0x20 && idx < max_flag_idx && ((*((const u32*)flag) >> idx) & 0x1));
}
#endif /* __NACP_H__ */

View file

@ -50,6 +50,7 @@
#define ALIGN_DOWN(x, y) ((x) & ~((y) - 1))
#define ALIGN_UP(x, y) ((((y) - 1) + (x)) & ~((y) - 1))
#define IS_ALIGNED(x, y) (((x) & ((y) - 1)) == 0)
#define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0)
#define BIS_SYSTEM_PARTITION_MOUNT_NAME "sys:"